1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * Copyright (c) 1998-2022 Erez Zadok
4  * Copyright (c) 2009	   Shrikar Archak
5  * Copyright (c) 2003-2022 Stony Brook University
6  * Copyright (c) 2003-2022 The Research Foundation of SUNY
7  */
8 #include <linux/backing-dev-defs.h>
9 #include <linux/ratelimit.h>
10 #include <linux/slab.h>
11 #include <linux/parser.h>
12 #include "sharefs.h"
13 
14 enum {
15 	OPT_USER_ID,
16 	OPT_OVERRIDE,
17 	OPT_OVERRIDE_SUPPORT_DELETE,
18 	OPT_ERR,
19 };
20 
21 static match_table_t sharefs_tokens = {
22 	{ OPT_USER_ID, "user_id=%s" },
23 	{ OPT_OVERRIDE, "override" },
24 	{ OPT_OVERRIDE_SUPPORT_DELETE, "override_support_delete" },
25 	{ OPT_ERR, NULL }
26 };
27 
sharefs_parse_options(struct sharefs_sb_info *sbi, const char *data)28 int sharefs_parse_options(struct sharefs_sb_info *sbi, const char *data)
29 {
30 	char *p = NULL;
31 	char *name = NULL;
32 	char *options = NULL;
33 	char *options_src = NULL;
34 	substring_t args[MAX_OPT_ARGS];
35 	unsigned int user_id = 0;
36 	int err = 0;
37 
38 	options = kstrdup(data, GFP_KERNEL);
39 	if (data && !options) {
40 		err = -ENOMEM;
41 		goto out;
42 	}
43 	options_src = options;
44 
45 	while ((p = strsep(&options_src, ",")) != NULL) {
46 		int token;
47 
48 		if (!*p)
49 			continue;
50 		args[0].to = args[0].from = NULL;
51 		token = match_token(p, sharefs_tokens, args);
52 
53 		switch (token) {
54 		case OPT_USER_ID:
55 			name = match_strdup(&args[0]);
56 			if (name) {
57 				err = kstrtouint(name, 10, &user_id);
58 				kfree(name);
59 				name = NULL;
60 				if (err)
61 					goto out;
62 				sbi->user_id = user_id;
63 			}
64 			break;
65 		case OPT_OVERRIDE:
66 			sbi->override = true;
67 			break;
68 		case OPT_OVERRIDE_SUPPORT_DELETE:
69 			sbi->override_support_delete = true;
70 			break;
71 		default:
72 			err = -EINVAL;
73 			goto out;
74 		}
75 	}
76 out:
77 	kfree(options);
78 
79 	return err;
80 }
81 
82 /*
83  * The inode cache is used with alloc_inode for both our inode info and the
84  * vfs inode.
85  */
86 static struct kmem_cache *sharefs_inode_cachep;
87 
88 /* final actions when unmounting a file system */
sharefs_put_super(struct super_block *sb)89 static void sharefs_put_super(struct super_block *sb)
90 {
91 	struct sharefs_sb_info *spd;
92 	struct super_block *s;
93 
94 	spd = SHAREFS_SB(sb);
95 	if (!spd)
96 		return;
97 
98 	/* decrement lower super references */
99 	s = sharefs_lower_super(sb);
100 	sharefs_set_lower_super(sb, NULL);
101 	atomic_dec(&s->s_active);
102 
103 	kfree(spd);
104 	sb->s_fs_info = NULL;
105 }
106 
sharefs_statfs(struct dentry *dentry, struct kstatfs *buf)107 static int sharefs_statfs(struct dentry *dentry, struct kstatfs *buf)
108 {
109 	int err;
110 	struct path lower_path;
111 
112 	sharefs_get_lower_path(dentry, &lower_path);
113 	err = vfs_statfs(&lower_path, buf);
114 	sharefs_put_lower_path(dentry, &lower_path);
115 
116 	/* set return buf to our f/s to avoid confusing user-level utils */
117 	buf->f_type = SHAREFS_SUPER_MAGIC;
118 
119 	return err;
120 }
121 
122 /*
123  * Called by iput() when the inode reference count reached zero
124  * and the inode is not hashed anywhere.  Used to clear anything
125  * that needs to be, before the inode is completely destroyed and put
126  * on the inode free list.
127  */
sharefs_evict_inode(struct inode *inode)128 static void sharefs_evict_inode(struct inode *inode)
129 {
130 	struct inode *lower_inode;
131 
132 	truncate_inode_pages(&inode->i_data, 0);
133 	clear_inode(inode);
134 	/*
135 	 * Decrement a reference to a lower_inode, which was incremented
136 	 * by our read_inode when it was created initially.
137 	 */
138 	lower_inode = sharefs_lower_inode(inode);
139 	sharefs_set_lower_inode(inode, NULL);
140 	iput(lower_inode);
141 }
142 
__sharefs_log(const char *level, const bool ratelimited, const char *function, const char *fmt, ...)143 void __sharefs_log(const char *level, const bool ratelimited,
144 		 const char *function, const char *fmt, ...)
145 {
146 	struct va_format vaf;
147 	va_list args;
148 
149 	va_start(args, fmt);
150 	vaf.fmt = fmt;
151 	vaf.va = &args;
152 	if (ratelimited)
153 		printk_ratelimited("%s sharefs: %s() %pV\n", level,
154 				   function, &vaf);
155 	else
156 		printk("%s sharefs: %s() %pV\n", level, function, &vaf);
157 	va_end(args);
158 }
159 
sharefs_alloc_inode(struct super_block *sb)160 static struct inode *sharefs_alloc_inode(struct super_block *sb)
161 {
162 	struct sharefs_inode_info *i;
163 
164 	i = kmem_cache_alloc(sharefs_inode_cachep, GFP_KERNEL);
165 	if (!i)
166 		return NULL;
167 
168 	/* memset everything up to the inode to 0 */
169 	memset(i, 0, offsetof(struct sharefs_inode_info, vfs_inode));
170 
171 	atomic64_set(&i->vfs_inode.i_version, 1);
172 	return &i->vfs_inode;
173 }
174 
sharefs_destroy_inode(struct inode *inode)175 static void sharefs_destroy_inode(struct inode *inode)
176 {
177 	kmem_cache_free(sharefs_inode_cachep, SHAREFS_I(inode));
178 }
179 
180 /* sharefs inode cache constructor */
init_once(void *obj)181 static void init_once(void *obj)
182 {
183 	struct sharefs_inode_info *i = obj;
184 
185 	inode_init_once(&i->vfs_inode);
186 }
187 
sharefs_init_inode_cache(void)188 int sharefs_init_inode_cache(void)
189 {
190 	int err = 0;
191 
192 	sharefs_inode_cachep =
193 		kmem_cache_create("sharefs_inode_cache",
194 				  sizeof(struct sharefs_inode_info), 0,
195 				  SLAB_RECLAIM_ACCOUNT, init_once);
196 	if (!sharefs_inode_cachep)
197 		err = -ENOMEM;
198 	return err;
199 }
200 
201 /* sharefs inode cache destructor */
sharefs_destroy_inode_cache(void)202 void sharefs_destroy_inode_cache(void)
203 {
204 	if (sharefs_inode_cachep)
205 		kmem_cache_destroy(sharefs_inode_cachep);
206 }
207 
208 const struct super_operations sharefs_sops = {
209 	.put_super	= sharefs_put_super,
210 	.statfs		= sharefs_statfs,
211 	.evict_inode	= sharefs_evict_inode,
212 	.alloc_inode	= sharefs_alloc_inode,
213 	.destroy_inode	= sharefs_destroy_inode,
214 };
215