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