1// SPDX-License-Identifier: GPL-2.0 2/* 3 * fs/epfs/inode.c 4 * 5 * Copyright (c) 2022 Huawei Technologies Co., Ltd. 6 * Author: weilongping@huawei.com 7 * Create: 2022-06-10 8 */ 9#include <linux/fs.h> 10#include <linux/fs_stack.h> 11#include <linux/version.h> 12 13#include "internal.h" 14 15#define USER_DATA_RW 1008 16#define USER_DATA_RW_UID KUIDT_INIT(USER_DATA_RW) 17#define USER_DATA_RW_GID KGIDT_INIT(USER_DATA_RW) 18 19struct dentry *epfs_lookup(struct inode *dir, struct dentry *dentry, 20 unsigned int flags) 21{ 22 return ERR_PTR(-ENOENT); 23} 24 25#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 12, 0) 26static int epfs_tmpfile(struct user_namespace *, struct inode *dir, 27 struct dentry *dentry, umode_t mode) 28#else 29static int epfs_tmpfile(struct inode *dir, struct dentry *dentry, umode_t mode) 30#endif 31{ 32 struct inode *inode = epfs_iget(dir->i_sb, false); 33 34 if (!inode) 35 return -ENOSPC; 36 d_tmpfile(dentry, inode); 37 if (IS_ENABLED(CONFIG_EPFS_DEBUG)) 38 epfs_debug("epfs: tmpfile %p", inode); 39 return 0; 40} 41 42const struct inode_operations epfs_dir_iops = { 43 .tmpfile = epfs_tmpfile, 44 .lookup = epfs_lookup, 45}; 46 47#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 12, 0) 48static int epfs_getattr(struct user_namespace *mnt_userns, 49 const struct path *path, struct kstat *stat, 50 u32 request_mask, unsigned int flags) 51#else 52static int epfs_getattr(const struct path *path, struct kstat *stat, 53 u32 request_mask, unsigned int flags) 54#endif 55{ 56 struct dentry *dentry = path->dentry; 57 struct inode *inode = d_inode(dentry); 58 struct epfs_inode_info *info = epfs_inode_to_private(inode); 59 struct file *origin_file; 60 struct kstat origin_stat; 61 int ret; 62 63 mutex_lock(&info->lock); 64 origin_file = info->origin_file; 65 if (!origin_file) { 66 ret = -ENOENT; 67 goto out_getattr; 68 } 69 ret = vfs_getattr(&(origin_file->f_path), &origin_stat, request_mask, 70 flags); 71 if (ret) 72 goto out_getattr; 73 fsstack_copy_attr_all(inode, file_inode(origin_file)); 74 fsstack_copy_inode_size(inode, file_inode(origin_file)); 75#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 12, 0) 76 generic_fillattr(mnt_userns, d_inode(dentry), stat); 77#else 78 generic_fillattr(d_inode(dentry), stat); 79#endif 80 stat->blocks = origin_stat.blocks; 81 82out_getattr: 83 mutex_unlock(&info->lock); 84 return ret; 85} 86 87const struct inode_operations epfs_file_iops = { 88 .getattr = epfs_getattr, 89}; 90 91struct inode *epfs_iget(struct super_block *sb, bool is_dir) 92{ 93 struct inode *inode = new_inode(sb); 94 95 if (!inode) { 96 epfs_err("Failed to allocate new inode"); 97 return NULL; 98 } 99 if (is_dir) { 100 inode->i_op = &epfs_dir_iops; 101 inode->i_fop = &epfs_dir_fops; 102 inode->i_mode = S_IFDIR | 0770; 103 } else { 104 inode->i_op = &epfs_file_iops; 105 inode->i_fop = &epfs_file_fops; 106 inode->i_mode = S_IFREG; 107 } 108 inode->i_uid = USER_DATA_RW_UID; 109 inode->i_gid = USER_DATA_RW_GID; 110 return inode; 111} 112