• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * fs/epfs/super.c
4  *
5  * Copyright (c) 2022 Huawei Technologies Co., Ltd.
6  * Author: weilongping@huawei.com
7  * Create: 2022-06-10
8  */
9 #include <linux/file.h>
10 #include <linux/fs.h>
11 #include <linux/slab.h>
12 #include <linux/statfs.h>
13 #include <linux/version.h>
14 
15 #include "internal.h"
16 
epfs_alloc_inode(struct super_block * sb)17 static struct inode *epfs_alloc_inode(struct super_block *sb)
18 {
19 	struct epfs_inode_info *info =
20 		kmem_cache_zalloc(epfs_inode_cachep, GFP_KERNEL);
21 	if (IS_ENABLED(CONFIG_EPFS_DEBUG))
22 		epfs_debug("inode info: %p", info);
23 	inode_init_once(&info->vfs_inode);
24 	mutex_init(&info->lock);
25 	return &info->vfs_inode;
26 }
27 
28 // Free epfs_inode_info
epfs_free_inode(struct inode * inode)29 static void epfs_free_inode(struct inode *inode)
30 {
31 	if (IS_ENABLED(CONFIG_EPFS_DEBUG))
32 		epfs_debug("free_inode: %p", inode);
33 	kmem_cache_free(epfs_inode_cachep,
34 			epfs_inode_to_private(inode));
35 }
36 
37 #if LINUX_VERSION_CODE < KERNEL_VERSION(5, 2, 0)
i_callback(struct rcu_head * head)38 static void i_callback(struct rcu_head *head)
39 {
40 	struct inode *inode = container_of(head, struct inode, i_rcu);
41 
42 	epfs_free_inode(inode);
43 }
44 #endif
45 
46 // Destroy epfs_range
epfs_destroy_inode(struct inode * inode)47 static void epfs_destroy_inode(struct inode *inode)
48 {
49 	struct epfs_inode_info *info = epfs_inode_to_private(inode);
50 
51 	mutex_lock(&info->lock);
52 	kfree(info->range);
53 	info->range = NULL;
54 	mutex_unlock(&info->lock);
55 #if LINUX_VERSION_CODE < KERNEL_VERSION(5, 2, 0)
56 	call_rcu(&inode->i_rcu, i_callback);
57 #endif
58 }
59 
60 // Clear vfs_inode
epfs_evict_inode(struct inode * inode)61 static void epfs_evict_inode(struct inode *inode)
62 {
63 	struct epfs_inode_info *info = epfs_inode_to_private(inode);
64 
65 	clear_inode(inode);
66 	mutex_lock(&info->lock);
67 	if (info->origin_file) {
68 		fput(info->origin_file);
69 		info->origin_file = NULL;
70 	}
71 	mutex_unlock(&info->lock);
72 }
73 
epfs_statfs(struct dentry * dentry,struct kstatfs * buf)74 static int epfs_statfs(struct dentry *dentry, struct kstatfs *buf)
75 {
76 	buf->f_type = EPFS_SUPER_MAGIC;
77 	return 0;
78 }
79 struct super_operations epfs_sops = {
80 	.alloc_inode = epfs_alloc_inode,
81 	.destroy_inode = epfs_destroy_inode,
82 #if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 2, 0)
83 	.free_inode = epfs_free_inode,
84 #endif
85 	.evict_inode = epfs_evict_inode,
86 	.statfs = epfs_statfs,
87 };
88 
epfs_fill_super(struct super_block * s,void * data,int silent)89 static int epfs_fill_super(struct super_block *s, void *data, int silent)
90 {
91 	struct inode *inode;
92 
93 	s->s_op = &epfs_sops;
94 	s->s_d_op = &epfs_dops;
95 	s->s_magic = EPFS_SUPER_MAGIC;
96 	inode = epfs_iget(s, true /* dir */);
97 	if (!inode) {
98 		epfs_err("Failed to get root inode!");
99 		return -ENOMEM;
100 	}
101 
102 	s->s_root = d_make_root(inode);
103 	if (!s->s_root) {
104 		epfs_err("Failed to make root inode");
105 		return -ENOMEM;
106 	}
107 
108 	return 0;
109 }
110 
epfs_mount(struct file_system_type * fs_type,int flags,const char * dev_name,void * raw_data)111 struct dentry *epfs_mount(struct file_system_type *fs_type, int flags,
112 			       const char *dev_name, void *raw_data)
113 {
114 	return mount_nodev(fs_type, flags, raw_data, epfs_fill_super);
115 }
116 
epfs_kill_sb(struct super_block * sb)117 void epfs_kill_sb(struct super_block *sb)
118 {
119 	kill_anon_super(sb);
120 }
121 
122 struct file_system_type epfs_fs_type = {
123 	.owner = THIS_MODULE,
124 	.name = "epfs",
125 	.mount = epfs_mount,
126 	.kill_sb = epfs_kill_sb,
127 };
128