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