• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
epfs_lookup(struct inode * dir,struct dentry * dentry,unsigned int flags)19 struct 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)
epfs_tmpfile(struct user_namespace *,struct inode * dir,struct dentry * dentry,umode_t mode)26 static int epfs_tmpfile(struct user_namespace *, struct inode *dir,
27 			     struct dentry *dentry, umode_t mode)
28 #else
29 static 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 
42 const 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)
epfs_getattr(struct user_namespace * mnt_userns,const struct path * path,struct kstat * stat,u32 request_mask,unsigned int flags)48 static 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
52 static 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 
82 out_getattr:
83 	mutex_unlock(&info->lock);
84 	return ret;
85 }
86 
87 const struct inode_operations epfs_file_iops = {
88 	.getattr = epfs_getattr,
89 };
90 
epfs_iget(struct super_block * sb,bool is_dir)91 struct 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