1 /* SPDX-License-Identifier: GPL-2.0 */
2 /*
3 * fs/hmdfs/hmdfs.h
4 *
5 * Copyright (c) 2020-2021 Huawei Device Co., Ltd.
6 */
7
8 #ifndef HMDFS_H
9 #define HMDFS_H
10
11 #include <linux/fs.h>
12 #include <linux/kfifo.h>
13 #include <linux/kobject.h>
14 #include <linux/kref.h>
15 #include <linux/sched.h>
16 #include <linux/version.h>
17
18 #include "comm/protocol.h"
19
20 #if KERNEL_VERSION(4, 15, 0) < LINUX_VERSION_CODE
21 #define hmdfs_time_t timespec64
22 #define hmdfs_time_compare timespec64_compare
23 #define hmdfs_time_add timespec64_add
24 #else
25 #define hmdfs_time_t timespec
26 #define hmdfs_time_compare timespec_compare
27 #define hmdfs_time_add timespec_add
28 #endif
29
30 #define HMDFS_PAGE_SIZE 4096
31 #define HMDFS_PAGE_OFFSET 12
32
33 /* max xattr value size, not include '\0' */
34 #define HMDFS_XATTR_SIZE_MAX 4096
35 /* max listxattr response size, include '\0' */
36 #define HMDFS_LISTXATTR_SIZE_MAX 4096
37
38 // 20 digits +'\0', Converted from a u64 integer
39 #define HMDFS_ACCOUNT_HASH_MAX_LEN 21
40 #define CTRL_PATH_MAX_LEN 21
41
42 #define HMDFS_SUPER_MAGIC 0x20200302
43
44 #define DEFAULT_WRITE_CACHE_TIMEOUT 30
45 #define DEFAULT_SRV_REQ_MAX_ACTIVE 16
46
47 #define HMDFS_INODE_INVALID_FILE_ID (1U << 31)
48 #define HMDFS_FID_VER_BOOT_COOKIE_SHIFT 15
49
50 /* According to task_struct instead of workqueue_struct */
51 #define HMDFS_WQ_NAME_LEN 16
52
53 #define HMDFS_DEF_WB_TIMEOUT_MS 60000
54 #define HMDFS_MAX_WB_TIMEOUT_MS 900000
55
56 #define HMDFS_READPAGES_NR_MAX 32
57
58 #define HMDFS_CID_SIZE 64
59
60 enum {
61 HMDFS_FEATURE_READPAGES = 1ULL << 0,
62 HMDFS_FEATURE_READPAGES_OPEN = 1ULL << 1,
63 HMDFS_ATOMIC_OPEN = 1ULL << 2,
64 };
65
66 struct client_statistic;
67 struct server_statistic;
68 struct hmdfs_writeback;
69 struct hmdfs_server_writeback;
70 struct hmdfs_syncfs_info {
71 wait_queue_head_t wq;
72 atomic_t wait_count;
73 int remote_ret;
74 unsigned long long version;
75
76 /* Protect version in concurrent operations */
77 spinlock_t v_lock;
78 /*
79 * Serialize hmdfs_sync_fs() process:
80 * |<- pending_list ->| exexuting |<- wait_list ->|
81 * syncfs_1 syncfs_2 (syncfs_3) syncfs_4 syncfs_5
82 *
83 * Abandon syncfs processes in pending_list after syncfs_3 finished;
84 * Pick the last syncfs process in wait_list after syncfs_3 finished;
85 */
86 bool is_executing;
87 /* syncfs process arriving after current exexcuting syncfs */
88 struct list_head wait_list;
89 /* syncfs process arriving before current exexcuting syncfs */
90 struct list_head pending_list;
91 spinlock_t list_lock;
92 };
93
94 struct hmdfs_share_table {
95 struct list_head item_list_head;
96 spinlock_t item_list_lock;
97 struct workqueue_struct *share_item_timeout_wq;
98 int item_cnt;
99 int max_cnt;
100 };
101
102 struct hmdfs_sb_info {
103 /* list for all registered superblocks */
104 struct list_head list;
105 struct mutex umount_mutex;
106
107 struct kobject kobj;
108 struct completion s_kobj_unregister;
109 struct super_block *sb;
110 struct super_block *lower_sb;
111 /* from mount, which is root */
112 const struct cred *cred;
113 /* from update cmd, expected to be system */
114 const struct cred *system_cred;
115 struct {
116 struct mutex node_lock;
117 struct list_head node_list;
118 atomic_t conn_seq;
119 unsigned long recent_ol;
120 } connections;
121 char *local_dst;
122 char *real_dst;
123 char *local_src;
124 char *cache_dir;
125 /* seq number for hmdfs super block */
126 unsigned int seq;
127
128 /*
129 * This value indicate how long the pagecache stay valid(in seconds) in
130 * client if metadate(except iversion) is equal to server. This
131 * functionality is disabled if this value is 0.
132 */
133 unsigned int write_cache_timeout;
134 unsigned int dcache_timeout;
135 unsigned int dcache_precision;
136 unsigned long dcache_threshold;
137 struct list_head client_cache;
138 struct list_head server_cache;
139 struct list_head to_delete;
140 struct mutex cache_list_lock;
141
142 /* local operation time statistic */
143 struct server_statistic *s_server_statis;
144
145 /* client statistic */
146 struct client_statistic *s_client_statis;
147
148 /* TIMEOUT of each command */
149 struct kobject s_cmd_timeout_kobj;
150 struct completion s_timeout_kobj_unregister;
151 unsigned int s_cmd_timeout[F_SIZE];
152
153 /* For case sensitive */
154 bool s_case_sensitive;
155
156 /* For features supporting */
157 u64 s_features;
158
159 /* For merge & device view */
160 unsigned int s_merge_switch;
161 /* For writeback */
162 struct hmdfs_writeback *h_wb;
163 /* For server writeback */
164 struct hmdfs_server_writeback *h_swb;
165
166 /* syncfs info */
167 struct hmdfs_syncfs_info hsi;
168
169 /* To bridge the userspace utils */
170 struct kfifo notify_fifo;
171 spinlock_t notify_fifo_lock;
172 struct mutex cmd_handler_mutex;
173
174 /* For reboot detect */
175 uint64_t boot_cookie;
176 /* offline process */
177 unsigned int async_cb_delay;
178 /* For server handle requests */
179 unsigned int async_req_max_active;
180 /* stash dirty pages during offline */
181 bool s_offline_stash;
182
183 /* Timeout (ms) to retry writing remote pages */
184 unsigned int wb_timeout_ms;
185
186 struct path stash_work_dir;
187 /* dentry cache */
188 bool s_dentry_cache;
189
190 /* share table */
191 struct hmdfs_share_table share_table;
192
193 /* msgs that are waiting for remote */
194 struct list_head async_readdir_msg_list;
195 /* protect async_readdir_msg_list */
196 spinlock_t async_readdir_msg_lock;
197 /* async readdir work that are queued but not finished */
198 struct list_head async_readdir_work_list;
199 /* protect async_readdir_work_list */
200 spinlock_t async_readdir_work_lock;
201 /* wait for async_readdir_work_list to be empty in umount */
202 wait_queue_head_t async_readdir_wq;
203 /* don't allow async readdir */
204 bool async_readdir_prohibit;
205
206 /* multi user */
207 unsigned int user_id;
208 };
209
hmdfs_sb(struct super_block * sb)210 static inline struct hmdfs_sb_info *hmdfs_sb(struct super_block *sb)
211 {
212 return sb->s_fs_info;
213 }
214
hmdfs_is_stash_enabled(const struct hmdfs_sb_info * sbi)215 static inline bool hmdfs_is_stash_enabled(const struct hmdfs_sb_info *sbi)
216 {
217 return sbi->s_offline_stash;
218 }
219
220 struct setattr_info {
221 loff_t size;
222 unsigned int valid;
223 umode_t mode;
224 kuid_t uid;
225 kgid_t gid;
226 long long atime;
227 long atime_nsec;
228 long long mtime;
229 long mtime_nsec;
230 long long ctime;
231 long ctime_nsec;
232 };
233
234 struct hmdfs_file_info {
235 union {
236 struct {
237 struct rb_root root;
238 struct mutex comrade_list_lock;
239 };
240 struct {
241 struct file *lower_file;
242 int device_id;
243 };
244 };
245 struct list_head comrade_list;
246 };
247
hmdfs_f(struct file * file)248 static inline struct hmdfs_file_info *hmdfs_f(struct file *file)
249 {
250 return file->private_data;
251 }
252
253 // Almost all the source files want this, so...
254 #include "inode.h"
255
256 /* locking helpers */
lock_parent(struct dentry * dentry)257 static inline struct dentry *lock_parent(struct dentry *dentry)
258 {
259 struct dentry *dir = dget_parent(dentry);
260
261 inode_lock_nested(d_inode(dir), I_MUTEX_PARENT);
262 return dir;
263 }
264
unlock_dir(struct dentry * dir)265 static inline void unlock_dir(struct dentry *dir)
266 {
267 inode_unlock(d_inode(dir));
268 dput(dir);
269 }
270
271 extern uint64_t path_hash(const char *path, int len, bool case_sense);
272 extern int vfs_path_lookup(struct dentry *dentry, struct vfsmount *mnt,
273 const char *name, unsigned int flags,
274 struct path *path);
275 extern ssize_t hmdfs_remote_listxattr(struct dentry *dentry, char *buffer,
276 size_t size);
277
278 int check_filename(const char *name, int len);
279
280 int hmdfs_permission(struct inode *inode, int mask);
281
282 int hmdfs_parse_options(struct hmdfs_sb_info *sbi, const char *data);
283
284 /* Refer to comments in hmdfs_request_work_fn() */
285 #define HMDFS_SERVER_CTX_FLAGS (PF_KTHREAD | PF_WQ_WORKER | PF_NPROC_EXCEEDED)
286
is_current_hmdfs_server_ctx(void)287 static inline bool is_current_hmdfs_server_ctx(void)
288 {
289 return ((current->flags & HMDFS_SERVER_CTX_FLAGS) ==
290 HMDFS_SERVER_CTX_FLAGS);
291 }
292
293 extern uint64_t hmdfs_gen_boot_cookie(void);
294
str_n_case_eq(const char * s1,const char * s2,size_t len)295 static inline bool str_n_case_eq(const char *s1, const char *s2, size_t len)
296 {
297 return !strncasecmp(s1, s2, len);
298 }
299
qstr_case_eq(const struct qstr * q1,const struct qstr * q2)300 static inline bool qstr_case_eq(const struct qstr *q1, const struct qstr *q2)
301 {
302 return q1->len == q2->len && str_n_case_eq(q1->name, q2->name, q2->len);
303 }
304
qstr_eq(const struct qstr * q1,const struct qstr * q2)305 static inline bool qstr_eq(const struct qstr *q1, const struct qstr *q2)
306 {
307 return q1->len == q2->len && !strncmp(q1->name, q2->name, q2->len);
308 }
309
310 /*****************************************************************************
311 * log print helpers
312 *****************************************************************************/
313 __printf(4, 5) void __hmdfs_log(const char *level, const bool ratelimited,
314 const char *function, const char *fmt, ...);
315 #define hmdfs_err(fmt, ...) \
316 __hmdfs_log(KERN_ERR, false, __func__, fmt, ##__VA_ARGS__)
317 #define hmdfs_warning(fmt, ...) \
318 __hmdfs_log(KERN_WARNING, false, __func__, fmt, ##__VA_ARGS__)
319 #define hmdfs_info(fmt, ...) \
320 __hmdfs_log(KERN_INFO, false, __func__, fmt, ##__VA_ARGS__)
321 #define hmdfs_err_ratelimited(fmt, ...) \
322 __hmdfs_log(KERN_ERR, true, __func__, fmt, ##__VA_ARGS__)
323 #define hmdfs_warning_ratelimited(fmt, ...) \
324 __hmdfs_log(KERN_WARNING, true, __func__, fmt, ##__VA_ARGS__)
325 #define hmdfs_info_ratelimited(fmt, ...) \
326 __hmdfs_log(KERN_INFO, true, __func__, fmt, ##__VA_ARGS__)
327 #ifdef CONFIG_HMDFS_FS_DEBUG
328 #define hmdfs_debug(fmt, ...) \
329 __hmdfs_log(KERN_DEBUG, false, __func__, fmt, ##__VA_ARGS__)
330 #define hmdfs_debug_ratelimited(fmt, ...) \
331 __hmdfs_log(KERN_DEBUG, true, __func__, fmt, ##__VA_ARGS__)
332 #else
333 #define hmdfs_debug(fmt, ...) ((void)0)
334 #define hmdfs_debug_ratelimited(fmt, ...) ((void)0)
335 #endif
336
337 /*****************************************************************************
338 * inode/file operations declartion
339 *****************************************************************************/
340 extern const struct inode_operations hmdfs_device_ops;
341 extern const struct inode_operations hmdfs_root_ops;
342 extern const struct file_operations hmdfs_root_fops;
343 extern const struct file_operations hmdfs_device_fops;
344
345 #endif // HMDFS_H
346