xref: /kernel/linux/linux-5.10/fs/epfs/inode.c (revision 8c2ecf20)
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