• 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)
26 #if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 6, 0)
epfs_tmpfile(struct mnt_idmap * idmap,struct inode * dir,struct file * file,umode_t mode)27 static int epfs_tmpfile(struct mnt_idmap *idmap, struct inode *dir,
28 			     struct file *file, umode_t mode)
29 #else
30 static int epfs_tmpfile(struct user_namespace *mnt_userns, struct inode *dir,
31 			     struct file *file, umode_t mode)
32 #endif
33 #else
34 static int epfs_tmpfile(struct inode *dir, struct dentry *dentry, umode_t mode)
35 #endif
36 {
37 	struct inode *inode = epfs_iget(dir->i_sb, false);
38 
39 	if (!inode)
40 		return -ENOSPC;
41 	d_tmpfile(file, inode);
42 	if (IS_ENABLED(CONFIG_EPFS_DEBUG))
43 		epfs_debug("epfs: tmpfile %p", inode);
44 	return finish_open_simple(file, 0);;
45 }
46 
47 const struct inode_operations epfs_dir_iops = {
48 	.tmpfile = epfs_tmpfile,
49 	.lookup = epfs_lookup,
50 };
51 
52 #if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 12, 0)
53 #if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 6, 0)
epfs_getattr(struct mnt_idmap * idmap,const struct path * path,struct kstat * stat,u32 request_mask,unsigned int flags)54 static int epfs_getattr(struct mnt_idmap *idmap,
55 			     const struct path *path, struct kstat *stat,
56 			     u32 request_mask, unsigned int flags)
57 #else
58 static int epfs_getattr(struct user_namespace *mnt_userns,
59 			     const struct path *path, struct kstat *stat,
60 			     u32 request_mask, unsigned int flags)
61 #endif
62 #else
63 static int epfs_getattr(const struct path *path, struct kstat *stat,
64 			     u32 request_mask, unsigned int flags)
65 #endif
66 {
67 	struct dentry *dentry = path->dentry;
68 	struct inode *inode = d_inode(dentry);
69 	struct epfs_inode_info *info = epfs_inode_to_private(inode);
70 	struct file *origin_file;
71 	struct kstat origin_stat;
72 	int ret;
73 
74 	mutex_lock(&info->lock);
75 	origin_file = info->origin_file;
76 	if (!origin_file) {
77 		ret = -ENOENT;
78 		goto out_getattr;
79 	}
80 	ret = vfs_getattr(&(origin_file->f_path), &origin_stat, request_mask,
81 			  flags);
82 	if (ret)
83 		goto out_getattr;
84 	fsstack_copy_attr_all(inode, file_inode(origin_file));
85 	fsstack_copy_inode_size(inode, file_inode(origin_file));
86 #if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 12, 0)
87 #if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 6, 0)
88 	generic_fillattr(idmap, request_mask, d_inode(dentry), stat);
89 #else
90 	generic_fillattr(mnt_userns, d_inode(dentry), stat);
91 #endif
92 #else
93 	generic_fillattr(d_inode(dentry), stat);
94 #endif
95 	stat->blocks = origin_stat.blocks;
96 
97 out_getattr:
98 	mutex_unlock(&info->lock);
99 	return ret;
100 }
101 
102 const struct inode_operations epfs_file_iops = {
103 	.getattr = epfs_getattr,
104 };
105 
epfs_iget(struct super_block * sb,bool is_dir)106 struct inode *epfs_iget(struct super_block *sb, bool is_dir)
107 {
108 	struct inode *inode = new_inode(sb);
109 
110 	if (!inode) {
111 		epfs_err("Failed to allocate new inode");
112 		return NULL;
113 	}
114 	if (is_dir) {
115 		inode->i_op = &epfs_dir_iops;
116 		inode->i_fop = &epfs_dir_fops;
117 		inode->i_mode = S_IFDIR | 0770;
118 	} else {
119 		inode->i_op = &epfs_file_iops;
120 		inode->i_fop = &epfs_file_fops;
121 		inode->i_mode = S_IFREG;
122 	}
123 	inode->i_uid = USER_DATA_RW_UID;
124 	inode->i_gid = USER_DATA_RW_GID;
125 	return inode;
126 }
127