• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * fs/hmdfs/super.c
4  *
5  * Copyright (c) 2020-2021 Huawei Device Co., Ltd.
6  */
7 
8 #include <linux/backing-dev-defs.h>
9 #include <linux/ratelimit.h>
10 #include <linux/parser.h>
11 #include <linux/slab.h>
12 
13 #include "hmdfs.h"
14 
15 enum {
16 	OPT_RA_PAGES,
17 	OPT_LOCAL_DST,
18 	OPT_CACHE_DIR,
19 	OPT_CLOUD_DIR,
20 	OPT_S_CASE,
21 	OPT_VIEW_TYPE,
22 	OPT_CLOUD_DISK_TYPE,
23 	OPT_NO_OFFLINE_STASH,
24 	OPT_NO_DENTRY_CACHE,
25 	OPT_USER_ID,
26 	OPT_DEVELOPER,
27 	OPT_ERR,
28 };
29 
30 static match_table_t hmdfs_tokens = {
31 	{ OPT_RA_PAGES, "ra_pages=%s" },
32 	{ OPT_LOCAL_DST, "local_dst=%s" },
33 	{ OPT_CACHE_DIR, "cache_dir=%s" },
34 	{ OPT_CLOUD_DIR, "cloud_dir=%s" },
35 	{ OPT_S_CASE, "sensitive" },
36 	{ OPT_VIEW_TYPE, "merge" },
37 	{ OPT_CLOUD_DISK_TYPE, "cloud_disk"},
38 	{ OPT_NO_OFFLINE_STASH, "no_offline_stash" },
39 	{ OPT_NO_DENTRY_CACHE, "no_dentry_cache" },
40 	{ OPT_USER_ID, "user_id=%s"},
41 	{ OPT_DEVELOPER, "developer"},
42 	{ OPT_ERR, NULL },
43 };
44 
45 #define DEAULT_RA_PAGES 128
46 
__hmdfs_log(const char * level,const bool ratelimited,const char * function,const char * fmt,...)47 void __hmdfs_log(const char *level, const bool ratelimited,
48 		 const char *function, const char *fmt, ...)
49 {
50 	struct va_format vaf;
51 	va_list args;
52 
53 	va_start(args, fmt);
54 	vaf.fmt = fmt;
55 	vaf.va = &args;
56 	if (ratelimited)
57 		printk_ratelimited("%s hmdfs: %s() %pV\n", level,
58 				   function, &vaf);
59 	else
60 		printk("%s hmdfs: %s() %pV\n", level, function, &vaf);
61 	va_end(args);
62 }
63 
hmdfs_match_strdup(const substring_t * s,char ** dst)64 static int hmdfs_match_strdup(const substring_t *s, char **dst)
65 {
66 	char *dup = NULL;
67 
68 	dup = match_strdup(s);
69 	if (!dup)
70 		return -ENOMEM;
71 
72 	if (*dst)
73 		kfree(*dst);
74 	*dst = dup;
75 
76 	return 0;
77 }
78 
hmdfs_parse_options(struct hmdfs_sb_info * sbi,const char * data)79 int hmdfs_parse_options(struct hmdfs_sb_info *sbi, const char *data)
80 {
81 	char *p = NULL;
82 	char *name = NULL;
83 	char *options = NULL;
84 	char *options_src = NULL;
85 	substring_t args[MAX_OPT_ARGS];
86 	unsigned long value = DEAULT_RA_PAGES;
87 	unsigned int user_id = 0;
88 	struct super_block *sb = sbi->sb;
89 	int err = 0;
90 	size_t size = 0;
91 
92 	size = strlen(data);
93 	if (size >= HMDFS_PAGE_SIZE) {
94 		return -EINVAL;
95 	}
96 
97 	options = kstrdup(data, GFP_KERNEL);
98 	if (data && !options) {
99 		err = -ENOMEM;
100 		goto out;
101 	}
102 	options_src = options;
103 	err = super_setup_bdi(sb);
104 	if (err)
105 		goto out;
106 
107 	while ((p = strsep(&options_src, ",")) != NULL) {
108 		int token;
109 
110 		if (!*p)
111 			continue;
112 		args[0].to = args[0].from = NULL;
113 		token = match_token(p, hmdfs_tokens, args);
114 
115 		switch (token) {
116 		case OPT_RA_PAGES:
117 			name = match_strdup(&args[0]);
118 			if (name) {
119 				err = kstrtoul(name, 10, &value);
120 				kfree(name);
121 				name = NULL;
122 				if (err)
123 					goto out;
124 			}
125 			break;
126 		case OPT_LOCAL_DST:
127 			err = hmdfs_match_strdup(&args[0], &sbi->local_dst);
128 			if (err)
129 				goto out;
130 			break;
131 		case OPT_CACHE_DIR:
132 			err = hmdfs_match_strdup(&args[0], &sbi->cache_dir);
133 			if (err)
134 				goto out;
135 			break;
136 		case OPT_CLOUD_DIR:
137 			err = hmdfs_match_strdup(&args[0], &sbi->cloud_dir);
138 			if (err)
139 				goto out;
140 			break;
141 		case OPT_S_CASE:
142 			sbi->s_case_sensitive = true;
143 			break;
144 		case OPT_VIEW_TYPE:
145 			sbi->s_merge_switch = true;
146 			break;
147 		case OPT_CLOUD_DISK_TYPE:
148 			sbi->s_cloud_disk_switch = true;
149 			break;
150 		case OPT_NO_OFFLINE_STASH:
151 			sbi->s_offline_stash = false;
152 			break;
153 		case OPT_NO_DENTRY_CACHE:
154 			sbi->s_dentry_cache = false;
155 			break;
156 		case OPT_USER_ID:
157 			name = match_strdup(&args[0]);
158 			if (name) {
159 				err = kstrtouint(name, 10, &user_id);
160 				kfree(name);
161 				name = NULL;
162 				if (err)
163 					goto out;
164 				sbi->user_id = user_id;
165 			}
166 			break;
167 		case OPT_DEVELOPER:
168 			break;
169 		default:
170 			err = -EINVAL;
171 			goto out;
172 		}
173 	}
174 out:
175 	kfree(options);
176 	sb->s_bdi->ra_pages = value;
177 	if (sbi->local_dst == NULL)
178 		err = -EINVAL;
179 
180 	if (sbi->s_offline_stash && !sbi->cache_dir) {
181 		hmdfs_warning("no cache_dir for offline stash");
182 		sbi->s_offline_stash = false;
183 	}
184 
185 	if (sbi->s_dentry_cache && !sbi->cache_dir) {
186 		hmdfs_warning("no cache_dir for dentry cache");
187 		sbi->s_dentry_cache = false;
188 	}
189 
190 	return err;
191 }
192