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