18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * fs/epfs/inode.c 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * Copyright (c) 2022 Huawei Technologies Co., Ltd. 68c2ecf20Sopenharmony_ci * Author: weilongping@huawei.com 78c2ecf20Sopenharmony_ci * Create: 2022-06-10 88c2ecf20Sopenharmony_ci */ 98c2ecf20Sopenharmony_ci#include <linux/fs.h> 108c2ecf20Sopenharmony_ci#include <linux/fs_stack.h> 118c2ecf20Sopenharmony_ci#include <linux/version.h> 128c2ecf20Sopenharmony_ci 138c2ecf20Sopenharmony_ci#include "internal.h" 148c2ecf20Sopenharmony_ci 158c2ecf20Sopenharmony_ci#define USER_DATA_RW 1008 168c2ecf20Sopenharmony_ci#define USER_DATA_RW_UID KUIDT_INIT(USER_DATA_RW) 178c2ecf20Sopenharmony_ci#define USER_DATA_RW_GID KGIDT_INIT(USER_DATA_RW) 188c2ecf20Sopenharmony_ci 198c2ecf20Sopenharmony_cistruct dentry *epfs_lookup(struct inode *dir, struct dentry *dentry, 208c2ecf20Sopenharmony_ci unsigned int flags) 218c2ecf20Sopenharmony_ci{ 228c2ecf20Sopenharmony_ci return ERR_PTR(-ENOENT); 238c2ecf20Sopenharmony_ci} 248c2ecf20Sopenharmony_ci 258c2ecf20Sopenharmony_ci#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 12, 0) 268c2ecf20Sopenharmony_cistatic int epfs_tmpfile(struct user_namespace *, struct inode *dir, 278c2ecf20Sopenharmony_ci struct dentry *dentry, umode_t mode) 288c2ecf20Sopenharmony_ci#else 298c2ecf20Sopenharmony_cistatic int epfs_tmpfile(struct inode *dir, struct dentry *dentry, umode_t mode) 308c2ecf20Sopenharmony_ci#endif 318c2ecf20Sopenharmony_ci{ 328c2ecf20Sopenharmony_ci struct inode *inode = epfs_iget(dir->i_sb, false); 338c2ecf20Sopenharmony_ci 348c2ecf20Sopenharmony_ci if (!inode) 358c2ecf20Sopenharmony_ci return -ENOSPC; 368c2ecf20Sopenharmony_ci d_tmpfile(dentry, inode); 378c2ecf20Sopenharmony_ci if (IS_ENABLED(CONFIG_EPFS_DEBUG)) 388c2ecf20Sopenharmony_ci epfs_debug("epfs: tmpfile %p", inode); 398c2ecf20Sopenharmony_ci return 0; 408c2ecf20Sopenharmony_ci} 418c2ecf20Sopenharmony_ci 428c2ecf20Sopenharmony_ciconst struct inode_operations epfs_dir_iops = { 438c2ecf20Sopenharmony_ci .tmpfile = epfs_tmpfile, 448c2ecf20Sopenharmony_ci .lookup = epfs_lookup, 458c2ecf20Sopenharmony_ci}; 468c2ecf20Sopenharmony_ci 478c2ecf20Sopenharmony_ci#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 12, 0) 488c2ecf20Sopenharmony_cistatic int epfs_getattr(struct user_namespace *mnt_userns, 498c2ecf20Sopenharmony_ci const struct path *path, struct kstat *stat, 508c2ecf20Sopenharmony_ci u32 request_mask, unsigned int flags) 518c2ecf20Sopenharmony_ci#else 528c2ecf20Sopenharmony_cistatic int epfs_getattr(const struct path *path, struct kstat *stat, 538c2ecf20Sopenharmony_ci u32 request_mask, unsigned int flags) 548c2ecf20Sopenharmony_ci#endif 558c2ecf20Sopenharmony_ci{ 568c2ecf20Sopenharmony_ci struct dentry *dentry = path->dentry; 578c2ecf20Sopenharmony_ci struct inode *inode = d_inode(dentry); 588c2ecf20Sopenharmony_ci struct epfs_inode_info *info = epfs_inode_to_private(inode); 598c2ecf20Sopenharmony_ci struct file *origin_file; 608c2ecf20Sopenharmony_ci struct kstat origin_stat; 618c2ecf20Sopenharmony_ci int ret; 628c2ecf20Sopenharmony_ci 638c2ecf20Sopenharmony_ci mutex_lock(&info->lock); 648c2ecf20Sopenharmony_ci origin_file = info->origin_file; 658c2ecf20Sopenharmony_ci if (!origin_file) { 668c2ecf20Sopenharmony_ci ret = -ENOENT; 678c2ecf20Sopenharmony_ci goto out_getattr; 688c2ecf20Sopenharmony_ci } 698c2ecf20Sopenharmony_ci ret = vfs_getattr(&(origin_file->f_path), &origin_stat, request_mask, 708c2ecf20Sopenharmony_ci flags); 718c2ecf20Sopenharmony_ci if (ret) 728c2ecf20Sopenharmony_ci goto out_getattr; 738c2ecf20Sopenharmony_ci fsstack_copy_attr_all(inode, file_inode(origin_file)); 748c2ecf20Sopenharmony_ci fsstack_copy_inode_size(inode, file_inode(origin_file)); 758c2ecf20Sopenharmony_ci#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 12, 0) 768c2ecf20Sopenharmony_ci generic_fillattr(mnt_userns, d_inode(dentry), stat); 778c2ecf20Sopenharmony_ci#else 788c2ecf20Sopenharmony_ci generic_fillattr(d_inode(dentry), stat); 798c2ecf20Sopenharmony_ci#endif 808c2ecf20Sopenharmony_ci stat->blocks = origin_stat.blocks; 818c2ecf20Sopenharmony_ci 828c2ecf20Sopenharmony_ciout_getattr: 838c2ecf20Sopenharmony_ci mutex_unlock(&info->lock); 848c2ecf20Sopenharmony_ci return ret; 858c2ecf20Sopenharmony_ci} 868c2ecf20Sopenharmony_ci 878c2ecf20Sopenharmony_ciconst struct inode_operations epfs_file_iops = { 888c2ecf20Sopenharmony_ci .getattr = epfs_getattr, 898c2ecf20Sopenharmony_ci}; 908c2ecf20Sopenharmony_ci 918c2ecf20Sopenharmony_cistruct inode *epfs_iget(struct super_block *sb, bool is_dir) 928c2ecf20Sopenharmony_ci{ 938c2ecf20Sopenharmony_ci struct inode *inode = new_inode(sb); 948c2ecf20Sopenharmony_ci 958c2ecf20Sopenharmony_ci if (!inode) { 968c2ecf20Sopenharmony_ci epfs_err("Failed to allocate new inode"); 978c2ecf20Sopenharmony_ci return NULL; 988c2ecf20Sopenharmony_ci } 998c2ecf20Sopenharmony_ci if (is_dir) { 1008c2ecf20Sopenharmony_ci inode->i_op = &epfs_dir_iops; 1018c2ecf20Sopenharmony_ci inode->i_fop = &epfs_dir_fops; 1028c2ecf20Sopenharmony_ci inode->i_mode = S_IFDIR | 0770; 1038c2ecf20Sopenharmony_ci } else { 1048c2ecf20Sopenharmony_ci inode->i_op = &epfs_file_iops; 1058c2ecf20Sopenharmony_ci inode->i_fop = &epfs_file_fops; 1068c2ecf20Sopenharmony_ci inode->i_mode = S_IFREG; 1078c2ecf20Sopenharmony_ci } 1088c2ecf20Sopenharmony_ci inode->i_uid = USER_DATA_RW_UID; 1098c2ecf20Sopenharmony_ci inode->i_gid = USER_DATA_RW_GID; 1108c2ecf20Sopenharmony_ci return inode; 1118c2ecf20Sopenharmony_ci} 112