xref: /kernel/linux/linux-6.6/fs/hmdfs/hmdfs.h (revision 62306a36)
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
69enum {
70	HMDFS_FEATURE_READPAGES		= 1ULL << 0,
71	HMDFS_FEATURE_READPAGES_OPEN	= 1ULL << 1,
72	HMDFS_ATOMIC_OPEN		= 1ULL << 2,
73};
74
75struct client_statistic;
76struct server_statistic;
77struct hmdfs_writeback;
78struct hmdfs_server_writeback;
79struct 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
103struct 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
111struct 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
225static inline struct hmdfs_sb_info *hmdfs_sb(struct super_block *sb)
226{
227	return sb->s_fs_info;
228}
229
230static inline bool hmdfs_is_stash_enabled(const struct hmdfs_sb_info *sbi)
231{
232	return sbi->s_offline_stash;
233}
234
235struct 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
245struct 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
259struct 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
273static 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 */
282static 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
290static inline void unlock_dir(struct dentry *dir)
291{
292	inode_unlock(d_inode(dir));
293	dput(dir);
294}
295
296extern uint64_t path_hash(const char *path, int len, bool case_sense);
297extern int vfs_path_lookup(struct dentry *dentry, struct vfsmount *mnt,
298			   const char *name, unsigned int flags,
299			   struct path *path);
300extern ssize_t hmdfs_remote_listxattr(struct dentry *dentry, char *buffer,
301				      size_t size);
302
303int check_filename(const char *name, int len);
304
305int hmdfs_permission(struct mnt_idmap *idmap, struct inode *inode, int mask);
306
307int 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
312static inline bool is_current_hmdfs_server_ctx(void)
313{
314	return ((current->flags & HMDFS_SERVER_CTX_FLAGS) ==
315		HMDFS_SERVER_CTX_FLAGS);
316}
317
318extern uint64_t hmdfs_gen_boot_cookie(void);
319
320static inline bool str_n_case_eq(const char *s1, const char *s2, size_t len)
321{
322	return !strncasecmp(s1, s2, len);
323}
324
325static 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
330static 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 *****************************************************************************/
365extern const struct inode_operations hmdfs_device_ops;
366extern const struct inode_operations hmdfs_root_ops;
367extern const struct file_operations hmdfs_root_fops;
368extern const struct file_operations hmdfs_device_fops;
369
370#endif // HMDFS_H
371