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