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_SHARE_ITEM_TIMEOUT_S 60
59 #define HMDFS_SHARE_ITEMS_MAX 4
60
61 #define HMDFS_IOC 0xf2
62 #define HMDFS_IOC_SET_SHARE_PATH _IOW(HMDFS_IOC, 1, \
63 struct hmdfs_share_control)
64
65 #define HMDFS_CID_SIZE 64
66
67 enum {
68 HMDFS_FEATURE_READPAGES = 1ULL << 0,
69 HMDFS_FEATURE_READPAGES_OPEN = 1ULL << 1,
70 HMDFS_ATOMIC_OPEN = 1ULL << 2,
71 };
72
73 struct client_statistic;
74 struct server_statistic;
75 struct hmdfs_writeback;
76 struct hmdfs_server_writeback;
77 struct hmdfs_syncfs_info {
78 wait_queue_head_t wq;
79 atomic_t wait_count;
80 int remote_ret;
81 unsigned long long version;
82
83 /* Protect version in concurrent operations */
84 spinlock_t v_lock;
85 /*
86 * Serialize hmdfs_sync_fs() process:
87 * |<- pending_list ->| exexuting |<- wait_list ->|
88 * syncfs_1 syncfs_2 (syncfs_3) syncfs_4 syncfs_5
89 *
90 * Abandon syncfs processes in pending_list after syncfs_3 finished;
91 * Pick the last syncfs process in wait_list after syncfs_3 finished;
92 */
93 bool is_executing;
94 /* syncfs process arriving after current exexcuting syncfs */
95 struct list_head wait_list;
96 /* syncfs process arriving before current exexcuting syncfs */
97 struct list_head pending_list;
98 spinlock_t list_lock;
99 };
100
101 struct hmdfs_share_item {
102 struct file *file;
103 struct qstr relative_path;
104 char cid[HMDFS_CID_SIZE];
105 unsigned long timeout;
106 struct kref ref;
107 struct list_head list;
108 };
109
110 struct hmdfs_share_table {
111 struct list_head item_list_head;
112 spinlock_t item_list_lock;
113 int item_cnt;
114 int max_cnt;
115 };
116
117 struct hmdfs_sb_info {
118 /* list for all registered superblocks */
119 struct list_head list;
120 struct mutex umount_mutex;
121
122 struct kobject kobj;
123 struct completion s_kobj_unregister;
124 struct super_block *sb;
125 struct super_block *lower_sb;
126 /* from mount, which is root */
127 const struct cred *cred;
128 /* from update cmd, expected to be system */
129 const struct cred *system_cred;
130 struct {
131 struct mutex node_lock;
132 struct list_head node_list;
133 atomic_t conn_seq;
134 unsigned long recent_ol;
135 } connections;
136 char *local_dst;
137 char *real_dst;
138 char *local_src;
139 char *cache_dir;
140 /* seq number for hmdfs super block */
141 unsigned int seq;
142
143 /*
144 * This value indicate how long the pagecache stay valid(in seconds) in
145 * client if metadate(except iversion) is equal to server. This
146 * functionality is disabled if this value is 0.
147 */
148 unsigned int write_cache_timeout;
149 unsigned int dcache_timeout;
150 unsigned int dcache_precision;
151 unsigned long dcache_threshold;
152 struct list_head client_cache;
153 struct list_head server_cache;
154 struct list_head to_delete;
155 struct mutex cache_list_lock;
156
157 /* local operation time statistic */
158 struct server_statistic *s_server_statis;
159
160 /* client statistic */
161 struct client_statistic *s_client_statis;
162
163 /* TIMEOUT of each command */
164 struct kobject s_cmd_timeout_kobj;
165 struct completion s_timeout_kobj_unregister;
166 unsigned int s_cmd_timeout[F_SIZE];
167
168 /* For case sensitive */
169 bool s_case_sensitive;
170
171 /* For features supporting */
172 u64 s_features;
173
174 /* For merge & device view */
175 unsigned int s_merge_switch;
176 /* For writeback */
177 struct hmdfs_writeback *h_wb;
178 /* For server writeback */
179 struct hmdfs_server_writeback *h_swb;
180
181 /* syncfs info */
182 struct hmdfs_syncfs_info hsi;
183
184 /* To bridge the userspace utils */
185 struct kfifo notify_fifo;
186 spinlock_t notify_fifo_lock;
187
188 /* For reboot detect */
189 uint64_t boot_cookie;
190 /* offline process */
191 unsigned int async_cb_delay;
192 /* For server handle requests */
193 unsigned int async_req_max_active;
194 /* stash dirty pages during offline */
195 bool s_offline_stash;
196
197 /* Timeout (ms) to retry writing remote pages */
198 unsigned int wb_timeout_ms;
199
200 struct path stash_work_dir;
201 /* dentry cache */
202 bool s_dentry_cache;
203
204 /* share table */
205 struct hmdfs_share_table share_table;
206
207 /* msgs that are waiting for remote */
208 struct list_head async_readdir_msg_list;
209 /* protect async_readdir_msg_list */
210 spinlock_t async_readdir_msg_lock;
211 /* async readdir work that are queued but not finished */
212 struct list_head async_readdir_work_list;
213 /* protect async_readdir_work_list */
214 spinlock_t async_readdir_work_lock;
215 /* wait for async_readdir_work_list to be empty in umount */
216 wait_queue_head_t async_readdir_wq;
217 /* don't allow async readdir */
218 bool async_readdir_prohibit;
219
220 /* multi user */
221 unsigned int user_id;
222 };
223
224 struct hmdfs_share_control {
225 __u32 src_fd;
226 char cid[HMDFS_CID_SIZE];
227 };
228
hmdfs_sb(struct super_block * sb)229 static inline struct hmdfs_sb_info *hmdfs_sb(struct super_block *sb)
230 {
231 return sb->s_fs_info;
232 }
233
hmdfs_is_stash_enabled(const struct hmdfs_sb_info * sbi)234 static inline bool hmdfs_is_stash_enabled(const struct hmdfs_sb_info *sbi)
235 {
236 return sbi->s_offline_stash;
237 }
238
239 struct setattr_info {
240 loff_t size;
241 unsigned int valid;
242 umode_t mode;
243 kuid_t uid;
244 kgid_t gid;
245 long long atime;
246 long atime_nsec;
247 long long mtime;
248 long mtime_nsec;
249 long long ctime;
250 long ctime_nsec;
251 };
252
253 struct hmdfs_file_info {
254 union {
255 struct {
256 struct rb_root root;
257 struct mutex comrade_list_lock;
258 };
259 struct {
260 struct file *lower_file;
261 int device_id;
262 };
263 };
264 struct list_head comrade_list;
265 };
266
hmdfs_f(struct file * file)267 static inline struct hmdfs_file_info *hmdfs_f(struct file *file)
268 {
269 return file->private_data;
270 }
271
272 // Almost all the source files want this, so...
273 #include "inode.h"
274
275 /* locking helpers */
lock_parent(struct dentry * dentry)276 static inline struct dentry *lock_parent(struct dentry *dentry)
277 {
278 struct dentry *dir = dget_parent(dentry);
279
280 inode_lock_nested(d_inode(dir), I_MUTEX_PARENT);
281 return dir;
282 }
283
unlock_dir(struct dentry * dir)284 static inline void unlock_dir(struct dentry *dir)
285 {
286 inode_unlock(d_inode(dir));
287 dput(dir);
288 }
289
290 extern uint64_t path_hash(const char *path, int len, bool case_sense);
291 extern int vfs_path_lookup(struct dentry *dentry, struct vfsmount *mnt,
292 const char *name, unsigned int flags,
293 struct path *path);
294 extern ssize_t hmdfs_remote_listxattr(struct dentry *dentry, char *buffer,
295 size_t size);
296
297 int check_filename(const char *name, int len);
298
299 int hmdfs_permission(struct inode *inode, int mask);
300
301 int hmdfs_parse_options(struct hmdfs_sb_info *sbi, const char *data);
302
303 /* Refer to comments in hmdfs_request_work_fn() */
304 #define HMDFS_SERVER_CTX_FLAGS (PF_KTHREAD | PF_WQ_WORKER | PF_NPROC_EXCEEDED)
305
is_current_hmdfs_server_ctx(void)306 static inline bool is_current_hmdfs_server_ctx(void)
307 {
308 return ((current->flags & HMDFS_SERVER_CTX_FLAGS) ==
309 HMDFS_SERVER_CTX_FLAGS);
310 }
311
312 extern uint64_t hmdfs_gen_boot_cookie(void);
313
str_n_case_eq(const char * s1,const char * s2,size_t len)314 static inline bool str_n_case_eq(const char *s1, const char *s2, size_t len)
315 {
316 return !strncasecmp(s1, s2, len);
317 }
318
qstr_case_eq(const struct qstr * q1,const struct qstr * q2)319 static inline bool qstr_case_eq(const struct qstr *q1, const struct qstr *q2)
320 {
321 return q1->len == q2->len && str_n_case_eq(q1->name, q2->name, q2->len);
322 }
323
qstr_eq(const struct qstr * q1,const struct qstr * q2)324 static inline bool qstr_eq(const struct qstr *q1, const struct qstr *q2)
325 {
326 return q1->len == q2->len && !strncmp(q1->name, q2->name, q2->len);
327 }
328
329 bool hmdfs_is_share_file(struct file *file);
330
331 bool hmdfs_is_share_item_still_valid(struct hmdfs_share_item *item);
332
333 inline void release_share_item(struct hmdfs_share_item *item);
334
335 void hmdfs_remove_share_item(struct kref *ref);
336
337 struct hmdfs_share_item *hmdfs_lookup_share_item(struct hmdfs_share_table *st,
338 struct qstr *cur_relative_path);
339
340 inline void set_item_timeout(struct hmdfs_share_item *item);
341
342 /*****************************************************************************
343 * log print helpers
344 *****************************************************************************/
345 __printf(4, 5) void __hmdfs_log(const char *level, const bool ratelimited,
346 const char *function, const char *fmt, ...);
347 #define hmdfs_err(fmt, ...) \
348 __hmdfs_log(KERN_ERR, false, __func__, fmt, ##__VA_ARGS__)
349 #define hmdfs_warning(fmt, ...) \
350 __hmdfs_log(KERN_WARNING, false, __func__, fmt, ##__VA_ARGS__)
351 #define hmdfs_info(fmt, ...) \
352 __hmdfs_log(KERN_INFO, false, __func__, fmt, ##__VA_ARGS__)
353 #define hmdfs_err_ratelimited(fmt, ...) \
354 __hmdfs_log(KERN_ERR, true, __func__, fmt, ##__VA_ARGS__)
355 #define hmdfs_warning_ratelimited(fmt, ...) \
356 __hmdfs_log(KERN_WARNING, true, __func__, fmt, ##__VA_ARGS__)
357 #define hmdfs_info_ratelimited(fmt, ...) \
358 __hmdfs_log(KERN_INFO, true, __func__, fmt, ##__VA_ARGS__)
359 #ifdef CONFIG_HMDFS_FS_DEBUG
360 #define hmdfs_debug(fmt, ...) \
361 __hmdfs_log(KERN_DEBUG, false, __func__, fmt, ##__VA_ARGS__)
362 #define hmdfs_debug_ratelimited(fmt, ...) \
363 __hmdfs_log(KERN_DEBUG, true, __func__, fmt, ##__VA_ARGS__)
364 #else
365 #define hmdfs_debug(fmt, ...) ((void)0)
366 #define hmdfs_debug_ratelimited(fmt, ...) ((void)0)
367 #endif
368
369 /*****************************************************************************
370 * inode/file operations declartion
371 *****************************************************************************/
372 extern const struct inode_operations hmdfs_device_ops;
373 extern const struct inode_operations hmdfs_root_ops;
374 extern const struct file_operations hmdfs_root_fops;
375 extern const struct file_operations hmdfs_device_fops;
376
377 #endif // HMDFS_H
378