• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
64 #define HMDFS_CID_SIZE 64
65 
66 #define DIR_MODE 0771
67 
68 enum {
69 	HMDFS_FEATURE_READPAGES		= 1ULL << 0,
70 	HMDFS_FEATURE_READPAGES_OPEN	= 1ULL << 1,
71 	HMDFS_ATOMIC_OPEN		= 1ULL << 2,
72 };
73 
74 struct client_statistic;
75 struct server_statistic;
76 struct hmdfs_writeback;
77 struct hmdfs_server_writeback;
78 struct hmdfs_syncfs_info {
79 	wait_queue_head_t wq;
80 	atomic_t wait_count;
81 	int remote_ret;
82 	unsigned long long version;
83 
84 	/* Protect version in concurrent operations */
85 	spinlock_t v_lock;
86 	/*
87 	 * Serialize hmdfs_sync_fs() process:
88 	 *  |<- pending_list ->|   exexuting    |<-  wait_list  ->|
89 	 *   syncfs_1 syncfs_2     (syncfs_3)    syncfs_4 syncfs_5
90 	 *
91 	 * Abandon syncfs processes in pending_list after syncfs_3 finished;
92 	 * Pick the last syncfs process in wait_list after syncfs_3 finished;
93 	 */
94 	bool is_executing;
95 	/* syncfs process arriving after current exexcuting syncfs */
96 	struct list_head wait_list;
97 	/* syncfs process arriving before current exexcuting syncfs */
98 	struct list_head pending_list;
99 	spinlock_t list_lock;
100 };
101 
102 struct hmdfs_share_table {
103 	struct list_head item_list_head;
104 	spinlock_t item_list_lock;
105 	struct workqueue_struct *share_item_timeout_wq;
106 	int item_cnt;
107 	int max_cnt;
108 };
109 
110 struct hmdfs_sb_info {
111 	/* list for all registered superblocks */
112 	struct list_head list;
113 	struct mutex umount_mutex;
114 
115 	struct kobject kobj;
116 	struct completion s_kobj_unregister;
117 	struct super_block *sb;
118 	struct super_block *lower_sb;
119 	/* from mount, which is root */
120 	const struct cred *cred;
121 	/* from update cmd, expected to be system */
122 	const struct cred *system_cred;
123 	struct {
124 		struct mutex node_lock;
125 		struct list_head node_list;
126 		atomic_t conn_seq;
127 		unsigned long recent_ol;
128 	} connections;
129 	char *local_dst;
130 	char *real_dst;
131 	char *local_src;
132 	char *cache_dir;
133 	char *cloud_dir;
134 	/* seq number for hmdfs super block */
135 	unsigned int seq;
136 
137 	/*
138 	 * This value indicate how long the pagecache stay valid(in seconds) in
139 	 * client if metadate(except iversion) is equal to server. This
140 	 * functionality is disabled if this value is 0.
141 	 */
142 	unsigned int write_cache_timeout;
143 	unsigned int dcache_timeout;
144 	unsigned int dcache_precision;
145 	unsigned long dcache_threshold;
146 	struct list_head client_cache;
147 	struct list_head server_cache;
148 	struct list_head to_delete;
149 	struct mutex cache_list_lock;
150 
151 	/* local operation time statistic */
152 	struct server_statistic *s_server_statis;
153 
154 	/* client statistic */
155 	struct client_statistic *s_client_statis;
156 
157 	/* TIMEOUT of each command */
158 	struct kobject s_cmd_timeout_kobj;
159 	struct completion s_timeout_kobj_unregister;
160 	unsigned int s_cmd_timeout[F_SIZE];
161 
162 	/* For case sensitive */
163 	bool s_case_sensitive;
164 
165 	/* For features supporting */
166 	u64 s_features;
167 
168 	/* For merge & device view */
169 	unsigned int s_merge_switch;
170 	/* For writeback */
171 	struct hmdfs_writeback *h_wb;
172 	/* For server writeback */
173 	struct hmdfs_server_writeback *h_swb;
174 
175 	/* syncfs info */
176 	struct hmdfs_syncfs_info hsi;
177 
178 	/* To bridge the userspace utils */
179 	struct kfifo notify_fifo;
180 	spinlock_t notify_fifo_lock;
181 	struct mutex cmd_handler_mutex;
182 
183 	/* For reboot detect */
184 	uint64_t boot_cookie;
185 	/* offline process */
186 	unsigned int async_cb_delay;
187 	/* For server handle requests */
188 	unsigned int async_req_max_active;
189 	/* stash dirty pages during offline */
190 	bool s_offline_stash;
191 
192 	/* Timeout (ms) to retry writing remote pages */
193 	unsigned int wb_timeout_ms;
194 
195 	struct path stash_work_dir;
196 	/* dentry cache */
197 	bool s_dentry_cache;
198 
199 	/* share table */
200 	struct hmdfs_share_table share_table;
201 
202 	/* msgs that are waiting for remote */
203 	struct list_head async_readdir_msg_list;
204 	/* protect async_readdir_msg_list */
205 	spinlock_t async_readdir_msg_lock;
206 	/* async readdir work that are queued but not finished */
207 	struct list_head async_readdir_work_list;
208 	/* protect async_readdir_work_list */
209 	spinlock_t async_readdir_work_lock;
210 	/* wait for async_readdir_work_list to be empty in umount */
211 	wait_queue_head_t async_readdir_wq;
212 	/* don't allow async readdir */
213 	bool async_readdir_prohibit;
214 
215 	/* multi user */
216 	unsigned int user_id;
217 };
218 
hmdfs_sb(struct super_block * sb)219 static inline struct hmdfs_sb_info *hmdfs_sb(struct super_block *sb)
220 {
221 	return sb->s_fs_info;
222 }
223 
hmdfs_is_stash_enabled(const struct hmdfs_sb_info * sbi)224 static inline bool hmdfs_is_stash_enabled(const struct hmdfs_sb_info *sbi)
225 {
226 	return sbi->s_offline_stash;
227 }
228 
229 struct hmdfs_dst_info{
230 	uint64_t local_path_len;
231 	uint64_t local_path_pos;
232 	uint64_t distributed_path_len;
233 	uint64_t distributed_path_pos;
234 	uint64_t bundle_name_len;
235 	uint64_t bundle_name_pos;
236 	uint64_t size;
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 /*****************************************************************************
330  * log print helpers
331  *****************************************************************************/
332 __printf(4, 5) void __hmdfs_log(const char *level, const bool ratelimited,
333 				const char *function, const char *fmt, ...);
334 #define hmdfs_err(fmt, ...)	\
335 	__hmdfs_log(KERN_ERR, false, __func__, fmt, ##__VA_ARGS__)
336 #define hmdfs_warning(fmt, ...) \
337 	__hmdfs_log(KERN_WARNING, false, __func__, fmt, ##__VA_ARGS__)
338 #define hmdfs_info(fmt, ...) \
339 	__hmdfs_log(KERN_INFO, false, __func__, fmt, ##__VA_ARGS__)
340 #define hmdfs_err_ratelimited(fmt, ...)	\
341 	__hmdfs_log(KERN_ERR, true, __func__, fmt, ##__VA_ARGS__)
342 #define hmdfs_warning_ratelimited(fmt, ...) \
343 	__hmdfs_log(KERN_WARNING, true, __func__, fmt, ##__VA_ARGS__)
344 #define hmdfs_info_ratelimited(fmt, ...) \
345 	__hmdfs_log(KERN_INFO, true, __func__, fmt, ##__VA_ARGS__)
346 #ifdef CONFIG_HMDFS_FS_DEBUG
347 #define hmdfs_debug(fmt, ...) \
348 	__hmdfs_log(KERN_DEBUG, false, __func__, fmt, ##__VA_ARGS__)
349 #define hmdfs_debug_ratelimited(fmt, ...) \
350 	__hmdfs_log(KERN_DEBUG, true, __func__, fmt, ##__VA_ARGS__)
351 #else
352 #define hmdfs_debug(fmt, ...)       ((void)0)
353 #define hmdfs_debug_ratelimited(fmt, ...)       ((void)0)
354 #endif
355 
356 /*****************************************************************************
357  * inode/file operations declartion
358  *****************************************************************************/
359 extern const struct inode_operations hmdfs_device_ops;
360 extern const struct inode_operations hmdfs_root_ops;
361 extern const struct file_operations hmdfs_root_fops;
362 extern const struct file_operations hmdfs_device_fops;
363 
364 #endif // HMDFS_H
365