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