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