162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * fs/hmdfs/inode_local.c 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Copyright (c) 2020-2021 Huawei Device Co., Ltd. 662306a36Sopenharmony_ci */ 762306a36Sopenharmony_ci 862306a36Sopenharmony_ci#include <linux/file.h> 962306a36Sopenharmony_ci#include <linux/fs_stack.h> 1062306a36Sopenharmony_ci#include <linux/kernel.h> 1162306a36Sopenharmony_ci#include <linux/mount.h> 1262306a36Sopenharmony_ci#include <linux/namei.h> 1362306a36Sopenharmony_ci#include <linux/string.h> 1462306a36Sopenharmony_ci 1562306a36Sopenharmony_ci#include "authority/authentication.h" 1662306a36Sopenharmony_ci#include "comm/socket_adapter.h" 1762306a36Sopenharmony_ci#include "comm/transport.h" 1862306a36Sopenharmony_ci#include "hmdfs_client.h" 1962306a36Sopenharmony_ci#include "hmdfs_dentryfile.h" 2062306a36Sopenharmony_ci#include "hmdfs_device_view.h" 2162306a36Sopenharmony_ci#include "hmdfs_share.h" 2262306a36Sopenharmony_ci#include "hmdfs_trace.h" 2362306a36Sopenharmony_ci 2462306a36Sopenharmony_ciextern struct kmem_cache *hmdfs_dentry_cachep; 2562306a36Sopenharmony_ci 2662306a36Sopenharmony_cistruct hmdfs_name_data { 2762306a36Sopenharmony_ci struct dir_context ctx; 2862306a36Sopenharmony_ci const struct qstr *to_find; 2962306a36Sopenharmony_ci char *name; 3062306a36Sopenharmony_ci bool found; 3162306a36Sopenharmony_ci}; 3262306a36Sopenharmony_ci 3362306a36Sopenharmony_ciint init_hmdfs_dentry_info(struct hmdfs_sb_info *sbi, struct dentry *dentry, 3462306a36Sopenharmony_ci int dentry_type) 3562306a36Sopenharmony_ci{ 3662306a36Sopenharmony_ci struct hmdfs_dentry_info *info = 3762306a36Sopenharmony_ci kmem_cache_zalloc(hmdfs_dentry_cachep, GFP_ATOMIC); 3862306a36Sopenharmony_ci 3962306a36Sopenharmony_ci if (!info) 4062306a36Sopenharmony_ci return -ENOMEM; 4162306a36Sopenharmony_ci INIT_LIST_HEAD(&info->cache_list_head); 4262306a36Sopenharmony_ci INIT_LIST_HEAD(&info->remote_cache_list_head); 4362306a36Sopenharmony_ci spin_lock_init(&info->cache_list_lock); 4462306a36Sopenharmony_ci mutex_init(&info->remote_cache_list_lock); 4562306a36Sopenharmony_ci mutex_init(&info->cache_pull_lock); 4662306a36Sopenharmony_ci spin_lock_init(&info->lock); 4762306a36Sopenharmony_ci info->dentry_type = dentry_type; 4862306a36Sopenharmony_ci info->device_id = 0; 4962306a36Sopenharmony_ci dentry->d_fsdata = info; 5062306a36Sopenharmony_ci if (dentry_type == HMDFS_LAYER_ZERO || 5162306a36Sopenharmony_ci dentry_type == HMDFS_LAYER_FIRST_DEVICE || 5262306a36Sopenharmony_ci dentry_type == HMDFS_LAYER_SECOND_LOCAL || 5362306a36Sopenharmony_ci dentry_type == HMDFS_LAYER_SECOND_CLOUD || 5462306a36Sopenharmony_ci dentry_type == HMDFS_LAYER_SECOND_REMOTE) 5562306a36Sopenharmony_ci d_set_d_op(dentry, &hmdfs_dev_dops); 5662306a36Sopenharmony_ci else 5762306a36Sopenharmony_ci d_set_d_op(dentry, &hmdfs_dops); 5862306a36Sopenharmony_ci return 0; 5962306a36Sopenharmony_ci} 6062306a36Sopenharmony_ci 6162306a36Sopenharmony_cistatic inline void set_sharefile_flag(struct hmdfs_dentry_info *gdi) 6262306a36Sopenharmony_ci{ 6362306a36Sopenharmony_ci gdi->file_type = HM_SHARE; 6462306a36Sopenharmony_ci} 6562306a36Sopenharmony_ci 6662306a36Sopenharmony_cistatic void check_and_fixup_share_ops(struct inode *inode, 6762306a36Sopenharmony_ci const char *name) 6862306a36Sopenharmony_ci{ 6962306a36Sopenharmony_ci if (is_share_dir(inode, name)) { 7062306a36Sopenharmony_ci inode->i_op = &hmdfs_dir_inode_ops_share; 7162306a36Sopenharmony_ci inode->i_fop = &hmdfs_dir_ops_share; 7262306a36Sopenharmony_ci } 7362306a36Sopenharmony_ci} 7462306a36Sopenharmony_ci 7562306a36Sopenharmony_cistruct inode *fill_inode_local(struct super_block *sb, 7662306a36Sopenharmony_ci struct inode *lower_inode, const char *name) 7762306a36Sopenharmony_ci{ 7862306a36Sopenharmony_ci int ret = 0; 7962306a36Sopenharmony_ci struct inode *inode; 8062306a36Sopenharmony_ci struct hmdfs_sb_info *sbi = hmdfs_sb(sb); 8162306a36Sopenharmony_ci struct hmdfs_inode_info *info; 8262306a36Sopenharmony_ci 8362306a36Sopenharmony_ci if (!igrab(lower_inode)) 8462306a36Sopenharmony_ci return ERR_PTR(-ESTALE); 8562306a36Sopenharmony_ci 8662306a36Sopenharmony_ci inode = hmdfs_iget5_locked_local(sb, lower_inode); 8762306a36Sopenharmony_ci if (!inode) { 8862306a36Sopenharmony_ci hmdfs_err("iget5_locked get inode NULL"); 8962306a36Sopenharmony_ci iput(lower_inode); 9062306a36Sopenharmony_ci return ERR_PTR(-ENOMEM); 9162306a36Sopenharmony_ci } 9262306a36Sopenharmony_ci if (!(inode->i_state & I_NEW)) { 9362306a36Sopenharmony_ci iput(lower_inode); 9462306a36Sopenharmony_ci return inode; 9562306a36Sopenharmony_ci } 9662306a36Sopenharmony_ci 9762306a36Sopenharmony_ci info = hmdfs_i(inode); 9862306a36Sopenharmony_ci#ifdef CONFIG_HMDFS_FS_PERMISSION 9962306a36Sopenharmony_ci info->perm = hmdfs_read_perm(lower_inode); 10062306a36Sopenharmony_ci#endif 10162306a36Sopenharmony_ci if (S_ISDIR(lower_inode->i_mode)) 10262306a36Sopenharmony_ci inode->i_mode = (lower_inode->i_mode & S_IFMT) | S_IRWXU | 10362306a36Sopenharmony_ci S_IRWXG | S_IXOTH; 10462306a36Sopenharmony_ci else if (S_ISREG(lower_inode->i_mode)) 10562306a36Sopenharmony_ci inode->i_mode = (lower_inode->i_mode & S_IFMT) | S_IRUSR | 10662306a36Sopenharmony_ci S_IWUSR | S_IRGRP | S_IWGRP; 10762306a36Sopenharmony_ci else if (S_ISLNK(lower_inode->i_mode)) 10862306a36Sopenharmony_ci inode->i_mode = 10962306a36Sopenharmony_ci S_IFREG | S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP; 11062306a36Sopenharmony_ci 11162306a36Sopenharmony_ci#ifdef CONFIG_HMDFS_FS_PERMISSION 11262306a36Sopenharmony_ci inode->i_uid = lower_inode->i_uid; 11362306a36Sopenharmony_ci inode->i_gid = lower_inode->i_gid; 11462306a36Sopenharmony_ci#else 11562306a36Sopenharmony_ci inode->i_uid = KUIDT_INIT((uid_t)1000); 11662306a36Sopenharmony_ci inode->i_gid = KGIDT_INIT((gid_t)1000); 11762306a36Sopenharmony_ci#endif 11862306a36Sopenharmony_ci inode->i_atime = lower_inode->i_atime; 11962306a36Sopenharmony_ci inode->__i_ctime = lower_inode->__i_ctime; 12062306a36Sopenharmony_ci inode->i_mtime = lower_inode->i_mtime; 12162306a36Sopenharmony_ci inode->i_generation = lower_inode->i_generation; 12262306a36Sopenharmony_ci 12362306a36Sopenharmony_ci info->inode_type = HMDFS_LAYER_OTHER_LOCAL; 12462306a36Sopenharmony_ci if (S_ISDIR(lower_inode->i_mode)) { 12562306a36Sopenharmony_ci inode->i_op = &hmdfs_dir_inode_ops_local; 12662306a36Sopenharmony_ci inode->i_fop = &hmdfs_dir_ops_local; 12762306a36Sopenharmony_ci inode->i_mode |= S_IXUGO; 12862306a36Sopenharmony_ci } else if (S_ISREG(lower_inode->i_mode)) { 12962306a36Sopenharmony_ci inode->i_op = &hmdfs_file_iops_local; 13062306a36Sopenharmony_ci inode->i_fop = &hmdfs_file_fops_local; 13162306a36Sopenharmony_ci } else if (S_ISLNK(lower_inode->i_mode)) { 13262306a36Sopenharmony_ci inode->i_op = &hmdfs_symlink_iops_local; 13362306a36Sopenharmony_ci inode->i_fop = &hmdfs_file_fops_local; 13462306a36Sopenharmony_ci inode->i_size = i_size_read(lower_inode); 13562306a36Sopenharmony_ci } else { 13662306a36Sopenharmony_ci ret = -EIO; 13762306a36Sopenharmony_ci goto bad_inode; 13862306a36Sopenharmony_ci } 13962306a36Sopenharmony_ci 14062306a36Sopenharmony_ci if (sbi->s_cloud_disk_switch) 14162306a36Sopenharmony_ci inode->i_mapping->a_ops = &hmdfs_aops_cloud; 14262306a36Sopenharmony_ci 14362306a36Sopenharmony_ci fsstack_copy_inode_size(inode, lower_inode); 14462306a36Sopenharmony_ci check_and_fixup_share_ops(inode, name); 14562306a36Sopenharmony_ci unlock_new_inode(inode); 14662306a36Sopenharmony_ci return inode; 14762306a36Sopenharmony_cibad_inode: 14862306a36Sopenharmony_ci iget_failed(inode); 14962306a36Sopenharmony_ci return ERR_PTR(ret); 15062306a36Sopenharmony_ci} 15162306a36Sopenharmony_ci 15262306a36Sopenharmony_ci/* hmdfs_convert_lookup_flags - covert hmdfs lookup flags to vfs lookup flags 15362306a36Sopenharmony_ci * 15462306a36Sopenharmony_ci * @hmdfs_flags: hmdfs lookup flags 15562306a36Sopenharmony_ci * @vfs_flags: pointer to converted flags 15662306a36Sopenharmony_ci * 15762306a36Sopenharmony_ci * return 0 on success, or err code on failure. 15862306a36Sopenharmony_ci */ 15962306a36Sopenharmony_ciint hmdfs_convert_lookup_flags(unsigned int hmdfs_flags, 16062306a36Sopenharmony_ci unsigned int *vfs_flags) 16162306a36Sopenharmony_ci{ 16262306a36Sopenharmony_ci *vfs_flags = 0; 16362306a36Sopenharmony_ci 16462306a36Sopenharmony_ci /* currently only support HMDFS_LOOKUP_REVAL */ 16562306a36Sopenharmony_ci if (hmdfs_flags & ~HMDFS_LOOKUP_REVAL) 16662306a36Sopenharmony_ci return -EINVAL; 16762306a36Sopenharmony_ci 16862306a36Sopenharmony_ci if (hmdfs_flags & HMDFS_LOOKUP_REVAL) 16962306a36Sopenharmony_ci *vfs_flags |= LOOKUP_REVAL; 17062306a36Sopenharmony_ci 17162306a36Sopenharmony_ci return 0; 17262306a36Sopenharmony_ci} 17362306a36Sopenharmony_ci 17462306a36Sopenharmony_cistatic bool hmdfs_name_match(struct dir_context *ctx, const char *name, 17562306a36Sopenharmony_ci int namelen, loff_t offset, u64 ino, 17662306a36Sopenharmony_ci unsigned int d_type) 17762306a36Sopenharmony_ci{ 17862306a36Sopenharmony_ci struct hmdfs_name_data *buf = 17962306a36Sopenharmony_ci container_of(ctx, struct hmdfs_name_data, ctx); 18062306a36Sopenharmony_ci struct qstr candidate = QSTR_INIT(name, namelen); 18162306a36Sopenharmony_ci 18262306a36Sopenharmony_ci if (qstr_case_eq(buf->to_find, &candidate)) { 18362306a36Sopenharmony_ci memcpy(buf->name, name, namelen); 18462306a36Sopenharmony_ci buf->name[namelen] = 0; 18562306a36Sopenharmony_ci buf->found = true; 18662306a36Sopenharmony_ci return false; 18762306a36Sopenharmony_ci } 18862306a36Sopenharmony_ci return true; 18962306a36Sopenharmony_ci} 19062306a36Sopenharmony_ci 19162306a36Sopenharmony_cistatic int __lookup_nosensitive(struct path *lower_parent_path, 19262306a36Sopenharmony_ci struct dentry *child_dentry, unsigned int flags, 19362306a36Sopenharmony_ci struct path *lower_path) 19462306a36Sopenharmony_ci{ 19562306a36Sopenharmony_ci struct file *file; 19662306a36Sopenharmony_ci const struct cred *cred = current_cred(); 19762306a36Sopenharmony_ci const struct qstr *name = &child_dentry->d_name; 19862306a36Sopenharmony_ci int err; 19962306a36Sopenharmony_ci struct hmdfs_name_data buffer = { 20062306a36Sopenharmony_ci .ctx.actor = hmdfs_name_match, 20162306a36Sopenharmony_ci .to_find = name, 20262306a36Sopenharmony_ci .name = __getname(), 20362306a36Sopenharmony_ci .found = false, 20462306a36Sopenharmony_ci }; 20562306a36Sopenharmony_ci 20662306a36Sopenharmony_ci if (!buffer.name) { 20762306a36Sopenharmony_ci err = -ENOMEM; 20862306a36Sopenharmony_ci goto out; 20962306a36Sopenharmony_ci } 21062306a36Sopenharmony_ci file = dentry_open(lower_parent_path, O_RDONLY, cred); 21162306a36Sopenharmony_ci if (IS_ERR(file)) { 21262306a36Sopenharmony_ci err = PTR_ERR(file); 21362306a36Sopenharmony_ci goto put_name; 21462306a36Sopenharmony_ci } 21562306a36Sopenharmony_ci err = iterate_dir(file, &buffer.ctx); 21662306a36Sopenharmony_ci fput(file); 21762306a36Sopenharmony_ci if (err) 21862306a36Sopenharmony_ci goto put_name; 21962306a36Sopenharmony_ci if (buffer.found) 22062306a36Sopenharmony_ci err = vfs_path_lookup(lower_parent_path->dentry, 22162306a36Sopenharmony_ci lower_parent_path->mnt, buffer.name, 22262306a36Sopenharmony_ci flags, lower_path); 22362306a36Sopenharmony_ci else 22462306a36Sopenharmony_ci err = -ENOENT; 22562306a36Sopenharmony_ciput_name: 22662306a36Sopenharmony_ci __putname(buffer.name); 22762306a36Sopenharmony_ciout: 22862306a36Sopenharmony_ci return err; 22962306a36Sopenharmony_ci} 23062306a36Sopenharmony_ci 23162306a36Sopenharmony_cistatic inline void set_symlink_flag(struct hmdfs_dentry_info *gdi) 23262306a36Sopenharmony_ci{ 23362306a36Sopenharmony_ci gdi->file_type = HM_SYMLINK; 23462306a36Sopenharmony_ci} 23562306a36Sopenharmony_ci 23662306a36Sopenharmony_cistruct dentry *hmdfs_lookup_local(struct inode *parent_inode, 23762306a36Sopenharmony_ci struct dentry *child_dentry, 23862306a36Sopenharmony_ci unsigned int flags) 23962306a36Sopenharmony_ci{ 24062306a36Sopenharmony_ci const char *d_name = child_dentry->d_name.name; 24162306a36Sopenharmony_ci int err = 0; 24262306a36Sopenharmony_ci struct path lower_path, lower_parent_path; 24362306a36Sopenharmony_ci struct dentry *lower_dentry = NULL, *parent_dentry = NULL, *ret = NULL; 24462306a36Sopenharmony_ci struct hmdfs_dentry_info *gdi = NULL; 24562306a36Sopenharmony_ci struct inode *child_inode = NULL; 24662306a36Sopenharmony_ci struct hmdfs_sb_info *sbi = hmdfs_sb(child_dentry->d_sb); 24762306a36Sopenharmony_ci 24862306a36Sopenharmony_ci trace_hmdfs_lookup_local(parent_inode, child_dentry, flags); 24962306a36Sopenharmony_ci if (child_dentry->d_name.len > NAME_MAX) { 25062306a36Sopenharmony_ci ret = ERR_PTR(-ENAMETOOLONG); 25162306a36Sopenharmony_ci goto out; 25262306a36Sopenharmony_ci } 25362306a36Sopenharmony_ci 25462306a36Sopenharmony_ci /* local device */ 25562306a36Sopenharmony_ci parent_dentry = dget_parent(child_dentry); 25662306a36Sopenharmony_ci hmdfs_get_lower_path(parent_dentry, &lower_parent_path); 25762306a36Sopenharmony_ci err = init_hmdfs_dentry_info(sbi, child_dentry, 25862306a36Sopenharmony_ci HMDFS_LAYER_OTHER_LOCAL); 25962306a36Sopenharmony_ci if (err) { 26062306a36Sopenharmony_ci ret = ERR_PTR(err); 26162306a36Sopenharmony_ci goto out_err; 26262306a36Sopenharmony_ci } 26362306a36Sopenharmony_ci 26462306a36Sopenharmony_ci gdi = hmdfs_d(child_dentry); 26562306a36Sopenharmony_ci 26662306a36Sopenharmony_ci flags &= ~LOOKUP_FOLLOW; 26762306a36Sopenharmony_ci err = vfs_path_lookup(lower_parent_path.dentry, lower_parent_path.mnt, 26862306a36Sopenharmony_ci (child_dentry->d_name.name), 0, &lower_path); 26962306a36Sopenharmony_ci if (err && err != -ENOENT) { 27062306a36Sopenharmony_ci ret = ERR_PTR(err); 27162306a36Sopenharmony_ci goto out_err; 27262306a36Sopenharmony_ci } else if (!err) { 27362306a36Sopenharmony_ci hmdfs_set_lower_path(child_dentry, &lower_path); 27462306a36Sopenharmony_ci child_inode = fill_inode_local(parent_inode->i_sb, 27562306a36Sopenharmony_ci d_inode(lower_path.dentry), 27662306a36Sopenharmony_ci child_dentry->d_name.name); 27762306a36Sopenharmony_ci 27862306a36Sopenharmony_ci if (S_ISLNK(d_inode(lower_path.dentry)->i_mode)) 27962306a36Sopenharmony_ci set_symlink_flag(gdi); 28062306a36Sopenharmony_ci if (IS_ERR(child_inode)) { 28162306a36Sopenharmony_ci err = PTR_ERR(child_inode); 28262306a36Sopenharmony_ci ret = ERR_PTR(err); 28362306a36Sopenharmony_ci hmdfs_put_reset_lower_path(child_dentry); 28462306a36Sopenharmony_ci goto out_err; 28562306a36Sopenharmony_ci } 28662306a36Sopenharmony_ci ret = d_splice_alias(child_inode, child_dentry); 28762306a36Sopenharmony_ci if (IS_ERR(ret)) { 28862306a36Sopenharmony_ci err = PTR_ERR(ret); 28962306a36Sopenharmony_ci hmdfs_put_reset_lower_path(child_dentry); 29062306a36Sopenharmony_ci goto out_err; 29162306a36Sopenharmony_ci } 29262306a36Sopenharmony_ci 29362306a36Sopenharmony_ci check_and_fixup_ownership(parent_inode, child_inode); 29462306a36Sopenharmony_ci goto out_err; 29562306a36Sopenharmony_ci } 29662306a36Sopenharmony_ci /* 29762306a36Sopenharmony_ci * return 0 here, so that vfs can continue the process of making this 29862306a36Sopenharmony_ci * negative dentry to a positive one while creating a new file. 29962306a36Sopenharmony_ci */ 30062306a36Sopenharmony_ci err = 0; 30162306a36Sopenharmony_ci ret = 0; 30262306a36Sopenharmony_ci 30362306a36Sopenharmony_ci lower_dentry = lookup_one_len_unlocked(d_name, lower_parent_path.dentry, 30462306a36Sopenharmony_ci child_dentry->d_name.len); 30562306a36Sopenharmony_ci if (IS_ERR(lower_dentry)) { 30662306a36Sopenharmony_ci err = PTR_ERR(lower_dentry); 30762306a36Sopenharmony_ci ret = lower_dentry; 30862306a36Sopenharmony_ci goto out_err; 30962306a36Sopenharmony_ci } 31062306a36Sopenharmony_ci lower_path.dentry = lower_dentry; 31162306a36Sopenharmony_ci lower_path.mnt = mntget(lower_parent_path.mnt); 31262306a36Sopenharmony_ci hmdfs_set_lower_path(child_dentry, &lower_path); 31362306a36Sopenharmony_ci 31462306a36Sopenharmony_ciout_err: 31562306a36Sopenharmony_ci if (!err) 31662306a36Sopenharmony_ci hmdfs_set_time(child_dentry, jiffies); 31762306a36Sopenharmony_ci hmdfs_put_lower_path(&lower_parent_path); 31862306a36Sopenharmony_ci dput(parent_dentry); 31962306a36Sopenharmony_ciout: 32062306a36Sopenharmony_ci trace_hmdfs_lookup_local_end(parent_inode, child_dentry, err); 32162306a36Sopenharmony_ci return ret; 32262306a36Sopenharmony_ci} 32362306a36Sopenharmony_ci 32462306a36Sopenharmony_ciint hmdfs_mkdir_local_dentry(struct inode *dir, struct dentry *dentry, 32562306a36Sopenharmony_ci umode_t mode) 32662306a36Sopenharmony_ci{ 32762306a36Sopenharmony_ci struct inode *lower_dir = hmdfs_i(dir)->lower_inode; 32862306a36Sopenharmony_ci struct dentry *lower_dir_dentry = NULL; 32962306a36Sopenharmony_ci struct super_block *sb = dir->i_sb; 33062306a36Sopenharmony_ci struct path lower_path; 33162306a36Sopenharmony_ci struct dentry *lower_dentry = NULL; 33262306a36Sopenharmony_ci int error = 0; 33362306a36Sopenharmony_ci struct inode *lower_inode = NULL; 33462306a36Sopenharmony_ci struct inode *child_inode = NULL; 33562306a36Sopenharmony_ci bool local_res = false; 33662306a36Sopenharmony_ci struct cache_fs_override or; 33762306a36Sopenharmony_ci __u16 child_perm; 33862306a36Sopenharmony_ci kuid_t tmp_uid; 33962306a36Sopenharmony_ci 34062306a36Sopenharmony_ci error = hmdfs_override_dir_id_fs(&or, dir, dentry, &child_perm); 34162306a36Sopenharmony_ci if (error) 34262306a36Sopenharmony_ci goto cleanup; 34362306a36Sopenharmony_ci 34462306a36Sopenharmony_ci hmdfs_get_lower_path(dentry, &lower_path); 34562306a36Sopenharmony_ci lower_dentry = lower_path.dentry; 34662306a36Sopenharmony_ci lower_dir_dentry = lock_parent(lower_dentry); 34762306a36Sopenharmony_ci 34862306a36Sopenharmony_ci tmp_uid = hmdfs_override_inode_uid(lower_dir); 34962306a36Sopenharmony_ci mode = (mode & S_IFMT) | 00771; 35062306a36Sopenharmony_ci 35162306a36Sopenharmony_ci error = vfs_mkdir(&nop_mnt_idmap, lower_dir, lower_dentry, mode); 35262306a36Sopenharmony_ci hmdfs_revert_inode_uid(lower_dir, tmp_uid); 35362306a36Sopenharmony_ci if (error) { 35462306a36Sopenharmony_ci hmdfs_err("vfs_mkdir() error:%d", error); 35562306a36Sopenharmony_ci goto out; 35662306a36Sopenharmony_ci } 35762306a36Sopenharmony_ci local_res = true; 35862306a36Sopenharmony_ci lower_inode = d_inode(lower_dentry); 35962306a36Sopenharmony_ci#ifdef CONFIG_HMDFS_FS_PERMISSION 36062306a36Sopenharmony_ci error = hmdfs_persist_perm(lower_dentry, &child_perm); 36162306a36Sopenharmony_ci#endif 36262306a36Sopenharmony_ci child_inode = fill_inode_local(sb, lower_inode, dentry->d_name.name); 36362306a36Sopenharmony_ci if (IS_ERR(child_inode)) { 36462306a36Sopenharmony_ci error = PTR_ERR(child_inode); 36562306a36Sopenharmony_ci goto out; 36662306a36Sopenharmony_ci } 36762306a36Sopenharmony_ci d_add(dentry, child_inode); 36862306a36Sopenharmony_ci set_nlink(dir, hmdfs_i(dir)->lower_inode->i_nlink); 36962306a36Sopenharmony_ciout: 37062306a36Sopenharmony_ci unlock_dir(lower_dir_dentry); 37162306a36Sopenharmony_ci if (local_res) 37262306a36Sopenharmony_ci hmdfs_drop_remote_cache_dents(dentry->d_parent); 37362306a36Sopenharmony_ci 37462306a36Sopenharmony_ci if (error) { 37562306a36Sopenharmony_ci hmdfs_clear_drop_flag(dentry->d_parent); 37662306a36Sopenharmony_ci d_drop(dentry); 37762306a36Sopenharmony_ci } 37862306a36Sopenharmony_ci hmdfs_put_lower_path(&lower_path); 37962306a36Sopenharmony_ci hmdfs_revert_dir_id_fs(&or); 38062306a36Sopenharmony_cicleanup: 38162306a36Sopenharmony_ci return error; 38262306a36Sopenharmony_ci} 38362306a36Sopenharmony_ci 38462306a36Sopenharmony_ciint hmdfs_mkdir_local(struct mnt_idmap *idmap, struct inode *dir, struct dentry *dentry, umode_t mode) 38562306a36Sopenharmony_ci{ 38662306a36Sopenharmony_ci int err = 0; 38762306a36Sopenharmony_ci 38862306a36Sopenharmony_ci if (check_filename(dentry->d_name.name, dentry->d_name.len)) { 38962306a36Sopenharmony_ci err = -EINVAL; 39062306a36Sopenharmony_ci return err; 39162306a36Sopenharmony_ci } 39262306a36Sopenharmony_ci 39362306a36Sopenharmony_ci if (hmdfs_file_type(dentry->d_name.name) != HMDFS_TYPE_COMMON) { 39462306a36Sopenharmony_ci err = -EACCES; 39562306a36Sopenharmony_ci return err; 39662306a36Sopenharmony_ci } 39762306a36Sopenharmony_ci err = hmdfs_mkdir_local_dentry(dir, dentry, mode); 39862306a36Sopenharmony_ci trace_hmdfs_mkdir_local(dir, dentry, err); 39962306a36Sopenharmony_ci return err; 40062306a36Sopenharmony_ci} 40162306a36Sopenharmony_ci 40262306a36Sopenharmony_ciint hmdfs_create_local_dentry(struct inode *dir, struct dentry *dentry, 40362306a36Sopenharmony_ci umode_t mode, bool want_excl) 40462306a36Sopenharmony_ci{ 40562306a36Sopenharmony_ci struct inode *lower_dir = NULL; 40662306a36Sopenharmony_ci struct dentry *lower_dir_dentry = NULL; 40762306a36Sopenharmony_ci struct super_block *sb = dir->i_sb; 40862306a36Sopenharmony_ci struct path lower_path; 40962306a36Sopenharmony_ci struct dentry *lower_dentry = NULL; 41062306a36Sopenharmony_ci int error = 0; 41162306a36Sopenharmony_ci struct inode *lower_inode = NULL; 41262306a36Sopenharmony_ci struct inode *child_inode = NULL; 41362306a36Sopenharmony_ci kuid_t tmp_uid; 41462306a36Sopenharmony_ci#ifdef CONFIG_HMDFS_FS_PERMISSION 41562306a36Sopenharmony_ci const struct cred *saved_cred = NULL; 41662306a36Sopenharmony_ci struct fs_struct *saved_fs = NULL, *copied_fs = NULL; 41762306a36Sopenharmony_ci __u16 child_perm; 41862306a36Sopenharmony_ci#endif 41962306a36Sopenharmony_ci 42062306a36Sopenharmony_ci#ifdef CONFIG_HMDFS_FS_PERMISSION 42162306a36Sopenharmony_ci saved_cred = hmdfs_override_file_fsids(dir, &child_perm); 42262306a36Sopenharmony_ci if (!saved_cred) { 42362306a36Sopenharmony_ci error = -ENOMEM; 42462306a36Sopenharmony_ci goto path_err; 42562306a36Sopenharmony_ci } 42662306a36Sopenharmony_ci 42762306a36Sopenharmony_ci saved_fs = current->fs; 42862306a36Sopenharmony_ci copied_fs = hmdfs_override_fsstruct(saved_fs); 42962306a36Sopenharmony_ci if (!copied_fs) { 43062306a36Sopenharmony_ci error = -ENOMEM; 43162306a36Sopenharmony_ci goto revert_fsids; 43262306a36Sopenharmony_ci } 43362306a36Sopenharmony_ci#endif 43462306a36Sopenharmony_ci hmdfs_get_lower_path(dentry, &lower_path); 43562306a36Sopenharmony_ci lower_dentry = lower_path.dentry; 43662306a36Sopenharmony_ci mode = (mode & S_IFMT) | 00660; 43762306a36Sopenharmony_ci lower_dir_dentry = lock_parent(lower_dentry); 43862306a36Sopenharmony_ci lower_dir = d_inode(lower_dir_dentry); 43962306a36Sopenharmony_ci tmp_uid = hmdfs_override_inode_uid(lower_dir); 44062306a36Sopenharmony_ci error = vfs_create(&nop_mnt_idmap, lower_dir, lower_dentry, mode, want_excl); 44162306a36Sopenharmony_ci hmdfs_revert_inode_uid(lower_dir, tmp_uid); 44262306a36Sopenharmony_ci unlock_dir(lower_dir_dentry); 44362306a36Sopenharmony_ci if (error) 44462306a36Sopenharmony_ci goto out; 44562306a36Sopenharmony_ci 44662306a36Sopenharmony_ci lower_inode = d_inode(lower_dentry); 44762306a36Sopenharmony_ci#ifdef CONFIG_HMDFS_FS_PERMISSION 44862306a36Sopenharmony_ci error = hmdfs_persist_perm(lower_dentry, &child_perm); 44962306a36Sopenharmony_ci#endif 45062306a36Sopenharmony_ci child_inode = fill_inode_local(sb, lower_inode, dentry->d_name.name); 45162306a36Sopenharmony_ci if (IS_ERR(child_inode)) { 45262306a36Sopenharmony_ci error = PTR_ERR(child_inode); 45362306a36Sopenharmony_ci goto out_created; 45462306a36Sopenharmony_ci } 45562306a36Sopenharmony_ci d_add(dentry, child_inode); 45662306a36Sopenharmony_ci 45762306a36Sopenharmony_ciout_created: 45862306a36Sopenharmony_ci hmdfs_drop_remote_cache_dents(dentry->d_parent); 45962306a36Sopenharmony_ciout: 46062306a36Sopenharmony_ci if (error) { 46162306a36Sopenharmony_ci hmdfs_clear_drop_flag(dentry->d_parent); 46262306a36Sopenharmony_ci d_drop(dentry); 46362306a36Sopenharmony_ci } 46462306a36Sopenharmony_ci hmdfs_put_lower_path(&lower_path); 46562306a36Sopenharmony_ci 46662306a36Sopenharmony_ci#ifdef CONFIG_HMDFS_FS_PERMISSION 46762306a36Sopenharmony_ci hmdfs_revert_fsstruct(saved_fs, copied_fs); 46862306a36Sopenharmony_cirevert_fsids: 46962306a36Sopenharmony_ci hmdfs_revert_fsids(saved_cred); 47062306a36Sopenharmony_ci#endif 47162306a36Sopenharmony_ci#ifdef CONFIG_HMDFS_FS_PERMISSION 47262306a36Sopenharmony_cipath_err: 47362306a36Sopenharmony_ci#endif 47462306a36Sopenharmony_ci return error; 47562306a36Sopenharmony_ci} 47662306a36Sopenharmony_ci 47762306a36Sopenharmony_ciint hmdfs_create_local(struct mnt_idmap *idmap, struct inode *dir, struct dentry *child_dentry, 47862306a36Sopenharmony_ci umode_t mode, bool want_excl) 47962306a36Sopenharmony_ci{ 48062306a36Sopenharmony_ci int err = 0; 48162306a36Sopenharmony_ci 48262306a36Sopenharmony_ci if (check_filename(child_dentry->d_name.name, 48362306a36Sopenharmony_ci child_dentry->d_name.len)) { 48462306a36Sopenharmony_ci err = -EINVAL; 48562306a36Sopenharmony_ci return err; 48662306a36Sopenharmony_ci } 48762306a36Sopenharmony_ci 48862306a36Sopenharmony_ci if (hmdfs_file_type(child_dentry->d_name.name) != HMDFS_TYPE_COMMON) { 48962306a36Sopenharmony_ci err = -EACCES; 49062306a36Sopenharmony_ci return err; 49162306a36Sopenharmony_ci } 49262306a36Sopenharmony_ci 49362306a36Sopenharmony_ci err = hmdfs_create_local_dentry(dir, child_dentry, mode, want_excl); 49462306a36Sopenharmony_ci trace_hmdfs_create_local(dir, child_dentry, err); 49562306a36Sopenharmony_ci return err; 49662306a36Sopenharmony_ci} 49762306a36Sopenharmony_ci 49862306a36Sopenharmony_ciint hmdfs_rmdir_local_dentry(struct inode *dir, struct dentry *dentry) 49962306a36Sopenharmony_ci{ 50062306a36Sopenharmony_ci struct inode *lower_dir = NULL; 50162306a36Sopenharmony_ci struct dentry *lower_dir_dentry = NULL; 50262306a36Sopenharmony_ci kuid_t tmp_uid; 50362306a36Sopenharmony_ci struct path lower_path; 50462306a36Sopenharmony_ci struct dentry *lower_dentry = NULL; 50562306a36Sopenharmony_ci struct dentry *lookup_dentry = NULL; 50662306a36Sopenharmony_ci int error = 0; 50762306a36Sopenharmony_ci 50862306a36Sopenharmony_ci hmdfs_clear_cache_dents(dentry, true); 50962306a36Sopenharmony_ci hmdfs_get_lower_path(dentry, &lower_path); 51062306a36Sopenharmony_ci lower_dentry = lower_path.dentry; 51162306a36Sopenharmony_ci lower_dir_dentry = lock_parent(lower_dentry); 51262306a36Sopenharmony_ci lower_dir = d_inode(lower_dir_dentry); 51362306a36Sopenharmony_ci 51462306a36Sopenharmony_ci lookup_dentry = lookup_one_len(lower_dentry->d_name.name, lower_dir_dentry, 51562306a36Sopenharmony_ci lower_dentry->d_name.len); 51662306a36Sopenharmony_ci if (IS_ERR(lookup_dentry)) { 51762306a36Sopenharmony_ci error = PTR_ERR(lookup_dentry); 51862306a36Sopenharmony_ci hmdfs_err("lookup_one_len failed, err = %d", error); 51962306a36Sopenharmony_ci goto lookup_err; 52062306a36Sopenharmony_ci } 52162306a36Sopenharmony_ci tmp_uid = hmdfs_override_inode_uid(lower_dir); 52262306a36Sopenharmony_ci 52362306a36Sopenharmony_ci error = vfs_rmdir(&nop_mnt_idmap, lower_dir, lookup_dentry); 52462306a36Sopenharmony_ci hmdfs_revert_inode_uid(lower_dir, tmp_uid); 52562306a36Sopenharmony_ci dput(lookup_dentry); 52662306a36Sopenharmony_cilookup_err: 52762306a36Sopenharmony_ci unlock_dir(lower_dir_dentry); 52862306a36Sopenharmony_ci hmdfs_put_lower_path(&lower_path); 52962306a36Sopenharmony_ci if (error) 53062306a36Sopenharmony_ci goto path_err; 53162306a36Sopenharmony_ci hmdfs_drop_remote_cache_dents(dentry->d_parent); 53262306a36Sopenharmony_cipath_err: 53362306a36Sopenharmony_ci if (error) 53462306a36Sopenharmony_ci hmdfs_clear_drop_flag(dentry->d_parent); 53562306a36Sopenharmony_ci return error; 53662306a36Sopenharmony_ci} 53762306a36Sopenharmony_ci 53862306a36Sopenharmony_ciint hmdfs_rmdir_local(struct inode *dir, struct dentry *dentry) 53962306a36Sopenharmony_ci{ 54062306a36Sopenharmony_ci int err = 0; 54162306a36Sopenharmony_ci 54262306a36Sopenharmony_ci if (hmdfs_file_type(dentry->d_name.name) != HMDFS_TYPE_COMMON) { 54362306a36Sopenharmony_ci err = -EACCES; 54462306a36Sopenharmony_ci goto out; 54562306a36Sopenharmony_ci } 54662306a36Sopenharmony_ci 54762306a36Sopenharmony_ci err = hmdfs_rmdir_local_dentry(dir, dentry); 54862306a36Sopenharmony_ci if (err != 0) { 54962306a36Sopenharmony_ci hmdfs_err("rm dir failed:%d", err); 55062306a36Sopenharmony_ci goto out; 55162306a36Sopenharmony_ci } 55262306a36Sopenharmony_ci 55362306a36Sopenharmony_ci /* drop dentry even remote failed 55462306a36Sopenharmony_ci * it maybe cause that one remote devices disconnect 55562306a36Sopenharmony_ci * when doing remote rmdir 55662306a36Sopenharmony_ci */ 55762306a36Sopenharmony_ci d_drop(dentry); 55862306a36Sopenharmony_ciout: 55962306a36Sopenharmony_ci /* return connect device's errcode */ 56062306a36Sopenharmony_ci trace_hmdfs_rmdir_local(dir, dentry, err); 56162306a36Sopenharmony_ci return err; 56262306a36Sopenharmony_ci} 56362306a36Sopenharmony_ci 56462306a36Sopenharmony_ciint hmdfs_unlink_local_dentry(struct inode *dir, struct dentry *dentry) 56562306a36Sopenharmony_ci{ 56662306a36Sopenharmony_ci struct dentry *lower_dir_dentry = NULL; 56762306a36Sopenharmony_ci struct path lower_path; 56862306a36Sopenharmony_ci struct inode *lower_dir = NULL; 56962306a36Sopenharmony_ci struct dentry *lower_dentry = NULL; 57062306a36Sopenharmony_ci struct dentry *lookup_dentry = NULL; 57162306a36Sopenharmony_ci int error; 57262306a36Sopenharmony_ci kuid_t tmp_uid; 57362306a36Sopenharmony_ci 57462306a36Sopenharmony_ci hmdfs_get_lower_path(dentry, &lower_path); 57562306a36Sopenharmony_ci lower_dentry = lower_path.dentry; 57662306a36Sopenharmony_ci dget(lower_dentry); 57762306a36Sopenharmony_ci lower_dir_dentry = lock_parent(lower_dentry); 57862306a36Sopenharmony_ci lower_dir = d_inode(lower_dir_dentry); 57962306a36Sopenharmony_ci lookup_dentry = lookup_one_len(lower_dentry->d_name.name, lower_dir_dentry, 58062306a36Sopenharmony_ci lower_dentry->d_name.len); 58162306a36Sopenharmony_ci if (IS_ERR(lookup_dentry)) { 58262306a36Sopenharmony_ci error = PTR_ERR(lookup_dentry); 58362306a36Sopenharmony_ci hmdfs_err("lookup_one_len failed, err = %d", error); 58462306a36Sopenharmony_ci goto lookup_err; 58562306a36Sopenharmony_ci } 58662306a36Sopenharmony_ci 58762306a36Sopenharmony_ci tmp_uid = hmdfs_override_inode_uid(lower_dir); 58862306a36Sopenharmony_ci error = vfs_unlink(&nop_mnt_idmap, lower_dir, lookup_dentry, NULL); 58962306a36Sopenharmony_ci hmdfs_revert_inode_uid(lower_dir, tmp_uid); 59062306a36Sopenharmony_ci set_nlink(d_inode(dentry), 59162306a36Sopenharmony_ci hmdfs_i(d_inode(dentry))->lower_inode->i_nlink); 59262306a36Sopenharmony_ci dput(lookup_dentry); 59362306a36Sopenharmony_cilookup_err: 59462306a36Sopenharmony_ci unlock_dir(lower_dir_dentry); 59562306a36Sopenharmony_ci dput(lower_dentry); 59662306a36Sopenharmony_ci if (error) 59762306a36Sopenharmony_ci goto path_err; 59862306a36Sopenharmony_ci 59962306a36Sopenharmony_ci hmdfs_drop_remote_cache_dents(dentry->d_parent); 60062306a36Sopenharmony_ci d_drop(dentry); 60162306a36Sopenharmony_ci 60262306a36Sopenharmony_cipath_err: 60362306a36Sopenharmony_ci hmdfs_put_lower_path(&lower_path); 60462306a36Sopenharmony_ci if (error) 60562306a36Sopenharmony_ci hmdfs_clear_drop_flag(dentry->d_parent); 60662306a36Sopenharmony_ci return error; 60762306a36Sopenharmony_ci} 60862306a36Sopenharmony_ci 60962306a36Sopenharmony_ciint hmdfs_unlink_local(struct inode *dir, struct dentry *dentry) 61062306a36Sopenharmony_ci{ 61162306a36Sopenharmony_ci if (hmdfs_file_type(dentry->d_name.name) != HMDFS_TYPE_COMMON) 61262306a36Sopenharmony_ci return -EACCES; 61362306a36Sopenharmony_ci 61462306a36Sopenharmony_ci return hmdfs_unlink_local_dentry(dir, dentry); 61562306a36Sopenharmony_ci} 61662306a36Sopenharmony_ci 61762306a36Sopenharmony_ciint hmdfs_rename_local_dentry(struct inode *old_dir, struct dentry *old_dentry, 61862306a36Sopenharmony_ci struct inode *new_dir, struct dentry *new_dentry, 61962306a36Sopenharmony_ci unsigned int flags) 62062306a36Sopenharmony_ci{ 62162306a36Sopenharmony_ci struct path lower_old_path; 62262306a36Sopenharmony_ci struct path lower_new_path; 62362306a36Sopenharmony_ci struct dentry *lower_old_dentry = NULL; 62462306a36Sopenharmony_ci struct dentry *lower_new_dentry = NULL; 62562306a36Sopenharmony_ci struct dentry *lower_old_dir_dentry = NULL; 62662306a36Sopenharmony_ci struct dentry *lower_new_dir_dentry = NULL; 62762306a36Sopenharmony_ci struct dentry *trap = NULL; 62862306a36Sopenharmony_ci struct renamedata rename_data; 62962306a36Sopenharmony_ci int rc = 0; 63062306a36Sopenharmony_ci kuid_t old_dir_uid, new_dir_uid; 63162306a36Sopenharmony_ci 63262306a36Sopenharmony_ci if (flags) 63362306a36Sopenharmony_ci return -EINVAL; 63462306a36Sopenharmony_ci 63562306a36Sopenharmony_ci hmdfs_get_lower_path(old_dentry, &lower_old_path); 63662306a36Sopenharmony_ci lower_old_dentry = lower_old_path.dentry; 63762306a36Sopenharmony_ci if (!lower_old_dentry) { 63862306a36Sopenharmony_ci hmdfs_err("lower_old_dentry as NULL"); 63962306a36Sopenharmony_ci rc = -EACCES; 64062306a36Sopenharmony_ci goto out_put_old_path; 64162306a36Sopenharmony_ci } 64262306a36Sopenharmony_ci 64362306a36Sopenharmony_ci hmdfs_get_lower_path(new_dentry, &lower_new_path); 64462306a36Sopenharmony_ci lower_new_dentry = lower_new_path.dentry; 64562306a36Sopenharmony_ci if (!lower_new_dentry) { 64662306a36Sopenharmony_ci hmdfs_err("lower_new_dentry as NULL"); 64762306a36Sopenharmony_ci rc = -EACCES; 64862306a36Sopenharmony_ci goto out_put_new_path; 64962306a36Sopenharmony_ci } 65062306a36Sopenharmony_ci 65162306a36Sopenharmony_ci lower_old_dir_dentry = dget_parent(lower_old_dentry); 65262306a36Sopenharmony_ci lower_new_dir_dentry = dget_parent(lower_new_dentry); 65362306a36Sopenharmony_ci trap = lock_rename(lower_old_dir_dentry, lower_new_dir_dentry); 65462306a36Sopenharmony_ci new_dir_uid = hmdfs_override_inode_uid(d_inode(lower_new_dir_dentry)); 65562306a36Sopenharmony_ci old_dir_uid = hmdfs_override_inode_uid(d_inode(lower_old_dir_dentry)); 65662306a36Sopenharmony_ci 65762306a36Sopenharmony_ci /* source should not be ancestor of target */ 65862306a36Sopenharmony_ci if (trap == lower_old_dentry) { 65962306a36Sopenharmony_ci rc = -EINVAL; 66062306a36Sopenharmony_ci goto out_lock; 66162306a36Sopenharmony_ci } 66262306a36Sopenharmony_ci /* target should not be ancestor of source */ 66362306a36Sopenharmony_ci if (trap == lower_new_dentry) { 66462306a36Sopenharmony_ci rc = -ENOTEMPTY; 66562306a36Sopenharmony_ci goto out_lock; 66662306a36Sopenharmony_ci } 66762306a36Sopenharmony_ci 66862306a36Sopenharmony_ci rename_data.old_mnt_idmap = &nop_mnt_idmap; 66962306a36Sopenharmony_ci rename_data.old_dir = d_inode(lower_old_dir_dentry); 67062306a36Sopenharmony_ci rename_data.old_dentry = lower_old_dentry; 67162306a36Sopenharmony_ci rename_data.new_mnt_idmap = &nop_mnt_idmap; 67262306a36Sopenharmony_ci rename_data.new_dir = d_inode(lower_new_dir_dentry); 67362306a36Sopenharmony_ci rename_data.new_dentry = lower_new_dentry; 67462306a36Sopenharmony_ci rename_data.flags = flags; 67562306a36Sopenharmony_ci rc = vfs_rename(&rename_data); 67662306a36Sopenharmony_ci 67762306a36Sopenharmony_ciout_lock: 67862306a36Sopenharmony_ci dget(old_dentry); 67962306a36Sopenharmony_ci 68062306a36Sopenharmony_ci hmdfs_revert_inode_uid(d_inode(lower_old_dir_dentry), old_dir_uid); 68162306a36Sopenharmony_ci hmdfs_revert_inode_uid(d_inode(lower_new_dir_dentry), new_dir_uid); 68262306a36Sopenharmony_ci 68362306a36Sopenharmony_ci unlock_rename(lower_old_dir_dentry, lower_new_dir_dentry); 68462306a36Sopenharmony_ci if (rc == 0) { 68562306a36Sopenharmony_ci hmdfs_drop_remote_cache_dents(old_dentry->d_parent); 68662306a36Sopenharmony_ci if (old_dentry->d_parent != new_dentry->d_parent) 68762306a36Sopenharmony_ci hmdfs_drop_remote_cache_dents(new_dentry->d_parent); 68862306a36Sopenharmony_ci } else { 68962306a36Sopenharmony_ci hmdfs_clear_drop_flag(old_dentry->d_parent); 69062306a36Sopenharmony_ci if (old_dentry->d_parent != new_dentry->d_parent) 69162306a36Sopenharmony_ci hmdfs_clear_drop_flag(old_dentry->d_parent); 69262306a36Sopenharmony_ci d_drop(new_dentry); 69362306a36Sopenharmony_ci } 69462306a36Sopenharmony_ci 69562306a36Sopenharmony_ci dput(old_dentry); 69662306a36Sopenharmony_ci dput(lower_old_dir_dentry); 69762306a36Sopenharmony_ci dput(lower_new_dir_dentry); 69862306a36Sopenharmony_ci 69962306a36Sopenharmony_ciout_put_new_path: 70062306a36Sopenharmony_ci hmdfs_put_lower_path(&lower_new_path); 70162306a36Sopenharmony_ciout_put_old_path: 70262306a36Sopenharmony_ci hmdfs_put_lower_path(&lower_old_path); 70362306a36Sopenharmony_ci return rc; 70462306a36Sopenharmony_ci} 70562306a36Sopenharmony_ci 70662306a36Sopenharmony_ciint hmdfs_rename_local(struct mnt_idmap *idmap, struct inode *old_dir, struct dentry *old_dentry, 70762306a36Sopenharmony_ci struct inode *new_dir, struct dentry *new_dentry, 70862306a36Sopenharmony_ci unsigned int flags) 70962306a36Sopenharmony_ci{ 71062306a36Sopenharmony_ci int err = 0; 71162306a36Sopenharmony_ci int ret = 0; 71262306a36Sopenharmony_ci 71362306a36Sopenharmony_ci trace_hmdfs_rename_local(old_dir, old_dentry, new_dir, new_dentry, 71462306a36Sopenharmony_ci flags); 71562306a36Sopenharmony_ci if (hmdfs_file_type(old_dentry->d_name.name) != HMDFS_TYPE_COMMON || 71662306a36Sopenharmony_ci hmdfs_file_type(new_dentry->d_name.name) != HMDFS_TYPE_COMMON) { 71762306a36Sopenharmony_ci err = -EACCES; 71862306a36Sopenharmony_ci goto rename_out; 71962306a36Sopenharmony_ci } 72062306a36Sopenharmony_ci 72162306a36Sopenharmony_ci if (hmdfs_i(old_dir)->inode_type != hmdfs_i(new_dir)->inode_type) { 72262306a36Sopenharmony_ci hmdfs_err("in different view"); 72362306a36Sopenharmony_ci err = -EPERM; 72462306a36Sopenharmony_ci goto rename_out; 72562306a36Sopenharmony_ci } 72662306a36Sopenharmony_ci 72762306a36Sopenharmony_ci if (hmdfs_d(old_dentry)->device_id != hmdfs_d(new_dentry)->device_id) { 72862306a36Sopenharmony_ci err = -EXDEV; 72962306a36Sopenharmony_ci goto rename_out; 73062306a36Sopenharmony_ci } 73162306a36Sopenharmony_ci 73262306a36Sopenharmony_ci if (S_ISREG(old_dentry->d_inode->i_mode)) { 73362306a36Sopenharmony_ci err = hmdfs_rename_local_dentry(old_dir, old_dentry, new_dir, 73462306a36Sopenharmony_ci new_dentry, flags); 73562306a36Sopenharmony_ci } else if (S_ISDIR(old_dentry->d_inode->i_mode)) { 73662306a36Sopenharmony_ci ret = hmdfs_rename_local_dentry(old_dir, old_dentry, new_dir, 73762306a36Sopenharmony_ci new_dentry, flags); 73862306a36Sopenharmony_ci if (ret != 0) { 73962306a36Sopenharmony_ci err = ret; 74062306a36Sopenharmony_ci goto rename_out; 74162306a36Sopenharmony_ci } 74262306a36Sopenharmony_ci } 74362306a36Sopenharmony_ci 74462306a36Sopenharmony_ci if (!err) 74562306a36Sopenharmony_ci d_invalidate(old_dentry); 74662306a36Sopenharmony_ci 74762306a36Sopenharmony_cirename_out: 74862306a36Sopenharmony_ci return err; 74962306a36Sopenharmony_ci} 75062306a36Sopenharmony_ci 75162306a36Sopenharmony_cistatic bool symname_is_allowed(const char *symname) 75262306a36Sopenharmony_ci{ 75362306a36Sopenharmony_ci char *p = NULL; 75462306a36Sopenharmony_ci size_t len; 75562306a36Sopenharmony_ci 75662306a36Sopenharmony_ci len = strnlen(symname, PATH_MAX); 75762306a36Sopenharmony_ci if (len >= PATH_MAX) 75862306a36Sopenharmony_ci return false; 75962306a36Sopenharmony_ci 76062306a36Sopenharmony_ci p = strstr(symname, "/../"); 76162306a36Sopenharmony_ci if (p) 76262306a36Sopenharmony_ci return false; 76362306a36Sopenharmony_ci 76462306a36Sopenharmony_ci if (len == 2u && strncmp(symname, "..", 2u) == 0) 76562306a36Sopenharmony_ci return false; 76662306a36Sopenharmony_ci if (len >= 3u && strncmp(symname, "../", 3u) == 0) 76762306a36Sopenharmony_ci return false; 76862306a36Sopenharmony_ci if (len >= 3u && strncmp(symname + len - 3u, "/..", 3u) == 0) 76962306a36Sopenharmony_ci return false; 77062306a36Sopenharmony_ci return true; 77162306a36Sopenharmony_ci} 77262306a36Sopenharmony_ci 77362306a36Sopenharmony_ciint hmdfs_symlink_local(struct mnt_idmap *idmap, struct inode *dir, struct dentry *dentry, 77462306a36Sopenharmony_ci const char *symname) 77562306a36Sopenharmony_ci{ 77662306a36Sopenharmony_ci int err; 77762306a36Sopenharmony_ci struct dentry *lower_dentry = NULL; 77862306a36Sopenharmony_ci struct dentry *lower_parent_dentry = NULL; 77962306a36Sopenharmony_ci struct path lower_path; 78062306a36Sopenharmony_ci struct inode *child_inode = NULL; 78162306a36Sopenharmony_ci struct inode *lower_dir_inode = hmdfs_i(dir)->lower_inode; 78262306a36Sopenharmony_ci struct hmdfs_dentry_info *gdi = hmdfs_d(dentry); 78362306a36Sopenharmony_ci kuid_t tmp_uid; 78462306a36Sopenharmony_ci#ifdef CONFIG_HMDFS_FS_PERMISSION 78562306a36Sopenharmony_ci const struct cred *saved_cred = NULL; 78662306a36Sopenharmony_ci struct fs_struct *saved_fs = NULL, *copied_fs = NULL; 78762306a36Sopenharmony_ci __u16 child_perm; 78862306a36Sopenharmony_ci#endif 78962306a36Sopenharmony_ci 79062306a36Sopenharmony_ci if (unlikely(!symname_is_allowed(symname))) { 79162306a36Sopenharmony_ci err = -EPERM; 79262306a36Sopenharmony_ci goto path_err; 79362306a36Sopenharmony_ci } 79462306a36Sopenharmony_ci 79562306a36Sopenharmony_ci#ifdef CONFIG_HMDFS_FS_PERMISSION 79662306a36Sopenharmony_ci saved_cred = hmdfs_override_file_fsids(dir, &child_perm); 79762306a36Sopenharmony_ci if (!saved_cred) { 79862306a36Sopenharmony_ci err = -ENOMEM; 79962306a36Sopenharmony_ci goto path_err; 80062306a36Sopenharmony_ci } 80162306a36Sopenharmony_ci 80262306a36Sopenharmony_ci saved_fs = current->fs; 80362306a36Sopenharmony_ci copied_fs = hmdfs_override_fsstruct(saved_fs); 80462306a36Sopenharmony_ci if (!copied_fs) { 80562306a36Sopenharmony_ci err = -ENOMEM; 80662306a36Sopenharmony_ci goto revert_fsids; 80762306a36Sopenharmony_ci } 80862306a36Sopenharmony_ci#endif 80962306a36Sopenharmony_ci hmdfs_get_lower_path(dentry, &lower_path); 81062306a36Sopenharmony_ci lower_dentry = lower_path.dentry; 81162306a36Sopenharmony_ci lower_parent_dentry = lock_parent(lower_dentry); 81262306a36Sopenharmony_ci tmp_uid = hmdfs_override_inode_uid(lower_dir_inode); 81362306a36Sopenharmony_ci err = vfs_symlink(&nop_mnt_idmap, lower_dir_inode, lower_dentry, symname); 81462306a36Sopenharmony_ci hmdfs_revert_inode_uid(lower_dir_inode, tmp_uid); 81562306a36Sopenharmony_ci unlock_dir(lower_parent_dentry); 81662306a36Sopenharmony_ci if (err) 81762306a36Sopenharmony_ci goto out_err; 81862306a36Sopenharmony_ci set_symlink_flag(gdi); 81962306a36Sopenharmony_ci#ifdef CONFIG_HMDFS_FS_PERMISSION 82062306a36Sopenharmony_ci err = hmdfs_persist_perm(lower_dentry, &child_perm); 82162306a36Sopenharmony_ci#endif 82262306a36Sopenharmony_ci child_inode = fill_inode_local(dir->i_sb, d_inode(lower_dentry), 82362306a36Sopenharmony_ci dentry->d_name.name); 82462306a36Sopenharmony_ci if (IS_ERR(child_inode)) { 82562306a36Sopenharmony_ci err = PTR_ERR(child_inode); 82662306a36Sopenharmony_ci goto out_err; 82762306a36Sopenharmony_ci } 82862306a36Sopenharmony_ci d_add(dentry, child_inode); 82962306a36Sopenharmony_ci fsstack_copy_attr_times(dir, lower_dir_inode); 83062306a36Sopenharmony_ci fsstack_copy_inode_size(dir, lower_dir_inode); 83162306a36Sopenharmony_ci 83262306a36Sopenharmony_ciout_err: 83362306a36Sopenharmony_ci hmdfs_put_lower_path(&lower_path); 83462306a36Sopenharmony_ci#ifdef CONFIG_HMDFS_FS_PERMISSION 83562306a36Sopenharmony_ci hmdfs_revert_fsstruct(saved_fs, copied_fs); 83662306a36Sopenharmony_cirevert_fsids: 83762306a36Sopenharmony_ci hmdfs_revert_fsids(saved_cred); 83862306a36Sopenharmony_ci#endif 83962306a36Sopenharmony_cipath_err: 84062306a36Sopenharmony_ci return err; 84162306a36Sopenharmony_ci} 84262306a36Sopenharmony_ci 84362306a36Sopenharmony_cistatic const char *hmdfs_get_link_local(struct dentry *dentry, 84462306a36Sopenharmony_ci struct inode *inode, 84562306a36Sopenharmony_ci struct delayed_call *done) 84662306a36Sopenharmony_ci{ 84762306a36Sopenharmony_ci const char *link = NULL; 84862306a36Sopenharmony_ci struct dentry *lower_dentry = NULL; 84962306a36Sopenharmony_ci struct inode *lower_inode = NULL; 85062306a36Sopenharmony_ci struct path lower_path; 85162306a36Sopenharmony_ci 85262306a36Sopenharmony_ci if(!dentry) { 85362306a36Sopenharmony_ci hmdfs_err("dentry MULL"); 85462306a36Sopenharmony_ci link = ERR_PTR(-ECHILD); 85562306a36Sopenharmony_ci goto link_out; 85662306a36Sopenharmony_ci } 85762306a36Sopenharmony_ci 85862306a36Sopenharmony_ci hmdfs_get_lower_path(dentry, &lower_path); 85962306a36Sopenharmony_ci lower_dentry = lower_path.dentry; 86062306a36Sopenharmony_ci lower_inode = d_inode(lower_dentry); 86162306a36Sopenharmony_ci if(!lower_inode->i_op || !lower_inode->i_op->get_link) { 86262306a36Sopenharmony_ci hmdfs_err("The lower inode doesn't support get_link i_op"); 86362306a36Sopenharmony_ci link = ERR_PTR(-EINVAL); 86462306a36Sopenharmony_ci goto out; 86562306a36Sopenharmony_ci } 86662306a36Sopenharmony_ci 86762306a36Sopenharmony_ci link = lower_inode->i_op->get_link(lower_dentry, lower_inode, done); 86862306a36Sopenharmony_ci if(IS_ERR_OR_NULL(link)) 86962306a36Sopenharmony_ci goto out; 87062306a36Sopenharmony_ci fsstack_copy_attr_atime(inode, lower_inode); 87162306a36Sopenharmony_ciout: 87262306a36Sopenharmony_ci hmdfs_put_lower_path(&lower_path); 87362306a36Sopenharmony_cilink_out: 87462306a36Sopenharmony_ci return link; 87562306a36Sopenharmony_ci} 87662306a36Sopenharmony_ci 87762306a36Sopenharmony_cistatic int hmdfs_setattr_local(struct mnt_idmap *idmap, struct dentry *dentry, struct iattr *ia) 87862306a36Sopenharmony_ci{ 87962306a36Sopenharmony_ci struct inode *inode = d_inode(dentry); 88062306a36Sopenharmony_ci struct inode *lower_inode = hmdfs_i(inode)->lower_inode; 88162306a36Sopenharmony_ci struct path lower_path; 88262306a36Sopenharmony_ci struct dentry *lower_dentry = NULL; 88362306a36Sopenharmony_ci struct iattr lower_ia; 88462306a36Sopenharmony_ci unsigned int ia_valid = ia->ia_valid; 88562306a36Sopenharmony_ci int err = 0; 88662306a36Sopenharmony_ci kuid_t tmp_uid; 88762306a36Sopenharmony_ci 88862306a36Sopenharmony_ci hmdfs_get_lower_path(dentry, &lower_path); 88962306a36Sopenharmony_ci lower_dentry = lower_path.dentry; 89062306a36Sopenharmony_ci memcpy(&lower_ia, ia, sizeof(lower_ia)); 89162306a36Sopenharmony_ci if (ia_valid & ATTR_FILE) 89262306a36Sopenharmony_ci lower_ia.ia_file = hmdfs_f(ia->ia_file)->lower_file; 89362306a36Sopenharmony_ci lower_ia.ia_valid &= ~(ATTR_UID | ATTR_GID | ATTR_MODE); 89462306a36Sopenharmony_ci if (ia_valid & ATTR_SIZE) { 89562306a36Sopenharmony_ci err = inode_newsize_ok(inode, ia->ia_size); 89662306a36Sopenharmony_ci if (err) 89762306a36Sopenharmony_ci goto out; 89862306a36Sopenharmony_ci truncate_setsize(inode, ia->ia_size); 89962306a36Sopenharmony_ci } 90062306a36Sopenharmony_ci inode_lock(lower_inode); 90162306a36Sopenharmony_ci tmp_uid = hmdfs_override_inode_uid(lower_inode); 90262306a36Sopenharmony_ci 90362306a36Sopenharmony_ci err = notify_change(&nop_mnt_idmap, lower_dentry, &lower_ia, NULL); 90462306a36Sopenharmony_ci i_size_write(inode, i_size_read(lower_inode)); 90562306a36Sopenharmony_ci inode->i_atime = lower_inode->i_atime; 90662306a36Sopenharmony_ci inode->i_mtime = lower_inode->i_mtime; 90762306a36Sopenharmony_ci inode->__i_ctime = lower_inode->__i_ctime; 90862306a36Sopenharmony_ci err = update_inode_to_dentry(dentry, inode); 90962306a36Sopenharmony_ci hmdfs_revert_inode_uid(lower_inode, tmp_uid); 91062306a36Sopenharmony_ci 91162306a36Sopenharmony_ci inode_unlock(lower_inode); 91262306a36Sopenharmony_ciout: 91362306a36Sopenharmony_ci hmdfs_put_lower_path(&lower_path); 91462306a36Sopenharmony_ci return err; 91562306a36Sopenharmony_ci} 91662306a36Sopenharmony_ci 91762306a36Sopenharmony_cistatic int hmdfs_getattr_local(struct mnt_idmap *idmap, const struct path *path, struct kstat *stat, 91862306a36Sopenharmony_ci u32 request_mask, unsigned int flags) 91962306a36Sopenharmony_ci{ 92062306a36Sopenharmony_ci struct path lower_path; 92162306a36Sopenharmony_ci int ret; 92262306a36Sopenharmony_ci 92362306a36Sopenharmony_ci if (path->dentry == NULL || hmdfs_d(path->dentry) == NULL) { 92462306a36Sopenharmony_ci hmdfs_err("dentry is NULL"); 92562306a36Sopenharmony_ci return -ENOENT; 92662306a36Sopenharmony_ci } 92762306a36Sopenharmony_ci 92862306a36Sopenharmony_ci hmdfs_get_lower_path(path->dentry, &lower_path); 92962306a36Sopenharmony_ci ret = vfs_getattr(&lower_path, stat, request_mask, flags); 93062306a36Sopenharmony_ci stat->ino = d_inode(path->dentry)->i_ino; 93162306a36Sopenharmony_ci stat->uid = d_inode(path->dentry)->i_uid; 93262306a36Sopenharmony_ci stat->gid = d_inode(path->dentry)->i_gid; 93362306a36Sopenharmony_ci stat->dev = 0; 93462306a36Sopenharmony_ci stat->rdev = 0; 93562306a36Sopenharmony_ci hmdfs_put_lower_path(&lower_path); 93662306a36Sopenharmony_ci 93762306a36Sopenharmony_ci return ret; 93862306a36Sopenharmony_ci} 93962306a36Sopenharmony_ci 94062306a36Sopenharmony_ciint hmdfs_permission(struct mnt_idmap *idmap, struct inode *inode, int mask) 94162306a36Sopenharmony_ci{ 94262306a36Sopenharmony_ci#ifdef CONFIG_HMDFS_FS_PERMISSION 94362306a36Sopenharmony_ci unsigned int mode = inode->i_mode; 94462306a36Sopenharmony_ci kuid_t cur_uid = current_fsuid(); 94562306a36Sopenharmony_ci 94662306a36Sopenharmony_ci if (uid_eq(cur_uid, ROOT_UID) || uid_eq(cur_uid, SYSTEM_UID)) 94762306a36Sopenharmony_ci return 0; 94862306a36Sopenharmony_ci 94962306a36Sopenharmony_ci if (uid_eq(cur_uid, inode->i_uid)) { 95062306a36Sopenharmony_ci mode >>= 6; 95162306a36Sopenharmony_ci } else if (in_group_p(inode->i_gid)) { 95262306a36Sopenharmony_ci mode >>= 3; 95362306a36Sopenharmony_ci } 95462306a36Sopenharmony_ci 95562306a36Sopenharmony_ci if ((mask & ~mode & (MAY_READ | MAY_WRITE | MAY_EXEC)) == 0) 95662306a36Sopenharmony_ci return 0; 95762306a36Sopenharmony_ci 95862306a36Sopenharmony_ci trace_hmdfs_permission(inode->i_ino); 95962306a36Sopenharmony_ci return -EACCES; 96062306a36Sopenharmony_ci#else 96162306a36Sopenharmony_ci 96262306a36Sopenharmony_ci return 0; 96362306a36Sopenharmony_ci#endif 96462306a36Sopenharmony_ci} 96562306a36Sopenharmony_ci 96662306a36Sopenharmony_cistatic ssize_t hmdfs_local_listxattr(struct dentry *dentry, char *list, 96762306a36Sopenharmony_ci size_t size) 96862306a36Sopenharmony_ci{ 96962306a36Sopenharmony_ci struct path lower_path; 97062306a36Sopenharmony_ci ssize_t res = 0; 97162306a36Sopenharmony_ci size_t r_size = size; 97262306a36Sopenharmony_ci 97362306a36Sopenharmony_ci if (!hmdfs_support_xattr(dentry)) 97462306a36Sopenharmony_ci return -EOPNOTSUPP; 97562306a36Sopenharmony_ci 97662306a36Sopenharmony_ci if (size > HMDFS_LISTXATTR_SIZE_MAX) 97762306a36Sopenharmony_ci r_size = HMDFS_LISTXATTR_SIZE_MAX; 97862306a36Sopenharmony_ci 97962306a36Sopenharmony_ci hmdfs_get_lower_path(dentry, &lower_path); 98062306a36Sopenharmony_ci res = vfs_listxattr(lower_path.dentry, list, r_size); 98162306a36Sopenharmony_ci hmdfs_put_lower_path(&lower_path); 98262306a36Sopenharmony_ci 98362306a36Sopenharmony_ci if (res == -ERANGE && r_size != size) { 98462306a36Sopenharmony_ci hmdfs_info("no support listxattr size over than %d", 98562306a36Sopenharmony_ci HMDFS_LISTXATTR_SIZE_MAX); 98662306a36Sopenharmony_ci res = -E2BIG; 98762306a36Sopenharmony_ci } 98862306a36Sopenharmony_ci 98962306a36Sopenharmony_ci return res; 99062306a36Sopenharmony_ci} 99162306a36Sopenharmony_cistruct dentry *hmdfs_lookup_share(struct inode *parent_inode, 99262306a36Sopenharmony_ci struct dentry *child_dentry, unsigned int flags) 99362306a36Sopenharmony_ci{ 99462306a36Sopenharmony_ci const struct qstr *d_name = &child_dentry->d_name; 99562306a36Sopenharmony_ci int err = 0; 99662306a36Sopenharmony_ci struct dentry *ret = NULL; 99762306a36Sopenharmony_ci struct hmdfs_sb_info *sbi = hmdfs_sb(child_dentry->d_sb); 99862306a36Sopenharmony_ci struct path src_path; 99962306a36Sopenharmony_ci struct inode *child_inode = NULL; 100062306a36Sopenharmony_ci 100162306a36Sopenharmony_ci trace_hmdfs_lookup_share(parent_inode, child_dentry, flags); 100262306a36Sopenharmony_ci if (d_name->len > NAME_MAX) { 100362306a36Sopenharmony_ci ret = ERR_PTR(-ENAMETOOLONG); 100462306a36Sopenharmony_ci goto err_out; 100562306a36Sopenharmony_ci } 100662306a36Sopenharmony_ci 100762306a36Sopenharmony_ci err = init_hmdfs_dentry_info(sbi, child_dentry, HMDFS_LAYER_OTHER_LOCAL); 100862306a36Sopenharmony_ci if (err) { 100962306a36Sopenharmony_ci ret = ERR_PTR(err); 101062306a36Sopenharmony_ci goto err_out; 101162306a36Sopenharmony_ci } 101262306a36Sopenharmony_ci 101362306a36Sopenharmony_ci err = get_path_from_share_table(sbi, child_dentry, &src_path); 101462306a36Sopenharmony_ci if (err) { 101562306a36Sopenharmony_ci ret = ERR_PTR(err); 101662306a36Sopenharmony_ci goto err_out; 101762306a36Sopenharmony_ci } 101862306a36Sopenharmony_ci 101962306a36Sopenharmony_ci hmdfs_set_lower_path(child_dentry, &src_path); 102062306a36Sopenharmony_ci child_inode = fill_inode_local(parent_inode->i_sb, 102162306a36Sopenharmony_ci d_inode(src_path.dentry), d_name->name); 102262306a36Sopenharmony_ci 102362306a36Sopenharmony_ci set_sharefile_flag(hmdfs_d(child_dentry)); 102462306a36Sopenharmony_ci 102562306a36Sopenharmony_ci if (IS_ERR(child_inode)) { 102662306a36Sopenharmony_ci err = PTR_ERR(child_inode); 102762306a36Sopenharmony_ci ret = ERR_PTR(err); 102862306a36Sopenharmony_ci hmdfs_put_reset_lower_path(child_dentry); 102962306a36Sopenharmony_ci goto err_out; 103062306a36Sopenharmony_ci } 103162306a36Sopenharmony_ci ret = d_splice_alias(child_inode, child_dentry); 103262306a36Sopenharmony_ci if (IS_ERR(ret)) { 103362306a36Sopenharmony_ci err = PTR_ERR(ret); 103462306a36Sopenharmony_ci hmdfs_put_reset_lower_path(child_dentry); 103562306a36Sopenharmony_ci goto err_out; 103662306a36Sopenharmony_ci } 103762306a36Sopenharmony_ci 103862306a36Sopenharmony_ci check_and_fixup_ownership(parent_inode, child_inode); 103962306a36Sopenharmony_ci 104062306a36Sopenharmony_cierr_out: 104162306a36Sopenharmony_ci trace_hmdfs_lookup_share_end(parent_inode, child_dentry, err); 104262306a36Sopenharmony_ci return ret; 104362306a36Sopenharmony_ci} 104462306a36Sopenharmony_ci 104562306a36Sopenharmony_ciconst struct inode_operations hmdfs_dir_inode_ops_local = { 104662306a36Sopenharmony_ci .lookup = hmdfs_lookup_local, 104762306a36Sopenharmony_ci .mkdir = hmdfs_mkdir_local, 104862306a36Sopenharmony_ci .create = hmdfs_create_local, 104962306a36Sopenharmony_ci .rmdir = hmdfs_rmdir_local, 105062306a36Sopenharmony_ci .unlink = hmdfs_unlink_local, 105162306a36Sopenharmony_ci .symlink = hmdfs_symlink_local, 105262306a36Sopenharmony_ci .rename = hmdfs_rename_local, 105362306a36Sopenharmony_ci .permission = hmdfs_permission, 105462306a36Sopenharmony_ci .setattr = hmdfs_setattr_local, 105562306a36Sopenharmony_ci .getattr = hmdfs_getattr_local, 105662306a36Sopenharmony_ci}; 105762306a36Sopenharmony_ci 105862306a36Sopenharmony_ciconst struct inode_operations hmdfs_symlink_iops_local = { 105962306a36Sopenharmony_ci .get_link = hmdfs_get_link_local, 106062306a36Sopenharmony_ci .permission = hmdfs_permission, 106162306a36Sopenharmony_ci .setattr = hmdfs_setattr_local, 106262306a36Sopenharmony_ci}; 106362306a36Sopenharmony_ci 106462306a36Sopenharmony_ciconst struct inode_operations hmdfs_dir_inode_ops_share = { 106562306a36Sopenharmony_ci .lookup = hmdfs_lookup_share, 106662306a36Sopenharmony_ci .permission = hmdfs_permission, 106762306a36Sopenharmony_ci}; 106862306a36Sopenharmony_ci 106962306a36Sopenharmony_ciconst struct inode_operations hmdfs_file_iops_local = { 107062306a36Sopenharmony_ci .setattr = hmdfs_setattr_local, 107162306a36Sopenharmony_ci .getattr = hmdfs_getattr_local, 107262306a36Sopenharmony_ci .permission = hmdfs_permission, 107362306a36Sopenharmony_ci .listxattr = hmdfs_local_listxattr, 107462306a36Sopenharmony_ci}; 1075