1/* SPDX-License-Identifier: GPL-2.0 */
2/*
3 * fs/hmdfs/hmdfs_merge_view.h
4 *
5 * Copyright (c) 2020-2021 Huawei Device Co., Ltd.
6 */
7
8#ifndef HMDFS_MERGE_VIEW_H
9#define HMDFS_MERGE_VIEW_H
10
11#include "hmdfs.h"
12
13#include "comm/connection.h"
14#include <linux/slab.h>
15#include <linux/types.h>
16#include <linux/wait.h>
17#include <linux/workqueue.h>
18
19/*****************************************************************************
20 * Dentires for merge view and their comrades.
21 * A dentry's lower dentry is named COMRADE.
22 *****************************************************************************/
23
24struct merge_lookup_work {
25	char *name;
26	int devid;
27	unsigned int flags;
28	struct hmdfs_sb_info *sbi;
29	wait_queue_head_t *wait_queue;
30	struct work_struct work;
31};
32
33struct hmdfs_dentry_info_merge {
34	unsigned long ctime;
35	int type;
36	int work_count;
37	struct mutex work_lock;
38	wait_queue_head_t wait_queue;
39	__u8 dentry_type;
40	struct mutex comrade_list_lock;
41	struct list_head comrade_list;
42};
43
44struct hmdfs_dentry_comrade {
45	uint64_t dev_id;
46	struct dentry *lo_d;
47	struct list_head list;
48};
49
50enum FILE_CMD_MERGE {
51	F_MKDIR_MERGE = 0,
52	F_CREATE_MERGE = 1,
53};
54
55struct hmdfs_recursive_para {
56	bool is_last;
57	int opcode;
58	umode_t mode;
59	bool want_excl;
60	const char *name;
61};
62
63struct hmdfs_rename_para {
64	struct inode *old_dir;
65	struct dentry *old_dentry;
66	struct inode *new_dir;
67	struct dentry *new_dentry;
68	unsigned int flags;
69};
70
71static inline struct hmdfs_dentry_info_merge *hmdfs_dm(struct dentry *dentry)
72{
73	return dentry->d_fsdata;
74}
75
76static inline umode_t hmdfs_cm(struct hmdfs_dentry_comrade *comrade)
77{
78	return d_inode(comrade->lo_d)->i_mode;
79}
80
81static inline bool comrade_is_local(struct hmdfs_dentry_comrade *comrade)
82{
83	return comrade->dev_id == HMDFS_DEVID_LOCAL;
84}
85
86struct hmdfs_cache_entry *allocate_entry(const char *name, int namelen,
87					 int d_type);
88
89struct dentry *hmdfs_lookup_cloud_merge(struct inode *parent_inode,
90				  struct dentry *child_dentry,
91				  unsigned int flags);
92
93struct dentry *hmdfs_lookup_merge(struct inode *parent_inode,
94				  struct dentry *child_dentry,
95				  unsigned int flags);
96struct hmdfs_file_info *
97get_next_hmdfs_file_info(struct hmdfs_file_info *fi_head, int device_id);
98
99struct hmdfs_file_info *get_hmdfs_file_info(struct hmdfs_file_info *fi_head,
100					    int device_id);
101int insert_filename(struct rb_root *root, struct hmdfs_cache_entry **new_entry);
102struct hmdfs_dentry_comrade *alloc_comrade(struct dentry *lo_d, int dev_id);
103int check_filename(const char *name, int len);
104int init_hmdfs_dentry_info_merge(struct hmdfs_sb_info *sbi,
105	struct dentry *dentry);
106void hmdfs_init_recursive_para(struct hmdfs_recursive_para *rec_op_para,
107			       int opcode, mode_t mode, bool want_excl,
108			       const char *name);
109void link_comrade(struct list_head *onstack_comrades_head,
110		  struct hmdfs_dentry_comrade *comrade);
111void update_inode_attr(struct inode *inode, struct dentry *child_dentry);
112int get_num_comrades(struct dentry *dentry);
113void assign_comrades_unlocked(struct dentry *child_dentry,
114			      struct list_head *onstack_comrades_head);
115struct hmdfs_dentry_comrade *lookup_comrade(struct path lower_path,
116					    const char *d_name,
117					    int dev_id,
118					    unsigned int flags);
119bool is_valid_comrade(struct hmdfs_dentry_info_merge *mdi, umode_t mode);
120int merge_lookup_async(struct hmdfs_dentry_info_merge *mdi,
121		       struct hmdfs_sb_info *sbi, int devid,
122		       const char *name, unsigned int flags);
123char *hmdfs_get_real_dname(struct dentry *dentry, int *devid, int *type);
124void lock_root_inode_shared(struct inode *root, bool *locked, bool *down);
125void restore_root_inode_sem(struct inode *root, bool locked, bool down);
126int hmdfs_getattr_merge(const struct path *path, struct kstat *stat,
127			u32 request_mask, unsigned int flags);
128int hmdfs_setattr_merge(struct dentry *dentry, struct iattr *ia);
129int hmdfs_rmdir_merge(struct inode *dir, struct dentry *dentry);
130int hmdfs_unlink_merge(struct inode *dir, struct dentry *dentry);
131int hmdfs_rename_merge(struct inode *old_dir, struct dentry *old_dentry,
132		       struct inode *new_dir, struct dentry *new_dentry,
133		       unsigned int flags);
134int do_rename_merge(struct inode *old_dir, struct dentry *old_dentry,
135		    struct inode *new_dir, struct dentry *new_dentry,
136		    unsigned int flags);
137
138static inline void destroy_comrade(struct hmdfs_dentry_comrade *comrade)
139{
140	dput(comrade->lo_d);
141	kfree(comrade);
142}
143
144void clear_comrades(struct dentry *dentry);
145
146static inline void link_comrade_unlocked(struct dentry *dentry,
147					 struct hmdfs_dentry_comrade *comrade)
148{
149	mutex_lock(&hmdfs_dm(dentry)->comrade_list_lock);
150	link_comrade(&hmdfs_dm(dentry)->comrade_list, comrade);
151	mutex_unlock(&hmdfs_dm(dentry)->comrade_list_lock);
152}
153
154void clear_comrades_locked(struct list_head *comrade_list);
155
156static inline bool is_comrade_list_empty(struct hmdfs_dentry_info_merge *mdi)
157{
158	bool ret;
159
160	mutex_lock(&mdi->comrade_list_lock);
161	ret = list_empty(&mdi->comrade_list);
162	mutex_unlock(&mdi->comrade_list_lock);
163
164	return ret;
165}
166
167static inline bool has_merge_lookup_work(struct hmdfs_dentry_info_merge *mdi)
168{
169	bool ret;
170
171	mutex_lock(&mdi->work_lock);
172	ret = (mdi->work_count != 0);
173	mutex_unlock(&mdi->work_lock);
174
175	return ret;
176}
177
178static inline bool is_merge_lookup_end(struct hmdfs_dentry_info_merge *mdi)
179{
180	bool ret;
181
182	mutex_lock(&mdi->work_lock);
183	ret = mdi->work_count == 0 || !is_comrade_list_empty(mdi);
184	mutex_unlock(&mdi->work_lock);
185
186	return ret;
187}
188
189void hmdfs_update_meta(struct inode *dir);
190
191#define for_each_comrade_locked(_dentry, _comrade)                             \
192	list_for_each_entry(_comrade, &(hmdfs_dm(_dentry)->comrade_list), list)
193
194#define hmdfs_trace_merge(_trace_func, _parent_inode, _child_dentry, err)      \
195	{                                                                      \
196		struct hmdfs_dentry_comrade *comrade;                          \
197		struct hmdfs_dentry_info_merge *dm = hmdfs_dm(_child_dentry);  \
198		_trace_func(_parent_inode, _child_dentry, err);                \
199		if (likely(dm)) {                                              \
200			mutex_lock(&dm->comrade_list_lock);                    \
201			for_each_comrade_locked(_child_dentry, comrade)        \
202				trace_hmdfs_show_comrade(_child_dentry,        \
203							 comrade->lo_d,        \
204							 comrade->dev_id);     \
205			mutex_unlock(&dm->comrade_list_lock);                  \
206		}                                                              \
207	}
208
209/*****************************************************************************
210 * Helper functions abstarcting out comrade
211 *****************************************************************************/
212
213static inline bool hmdfs_i_merge(struct hmdfs_inode_info *hii)
214{
215	__u8 t = hii->inode_type;
216	return t == HMDFS_LAYER_FIRST_MERGE || t == HMDFS_LAYER_OTHER_MERGE ||
217	       t == HMDFS_LAYER_FIRST_MERGE_CLOUD ||
218	       t == HMDFS_LAYER_OTHER_MERGE_CLOUD;
219}
220
221struct dentry *hmdfs_get_lo_d(struct dentry *dentry, int dev_id);
222struct dentry *hmdfs_get_fst_lo_d(struct dentry *dentry);
223
224/*****************************************************************************
225 * Inode operations for the merge view
226 *****************************************************************************/
227
228extern const struct inode_operations hmdfs_file_iops_merge;
229extern const struct file_operations hmdfs_file_fops_merge;
230extern const struct inode_operations hmdfs_dir_iops_merge;
231extern const struct file_operations hmdfs_dir_fops_merge;
232extern const struct inode_operations hmdfs_file_iops_cloud_merge;
233extern const struct inode_operations hmdfs_dir_iops_cloud_merge;
234extern const struct dentry_operations hmdfs_dops_merge;
235
236/*****************************************************************************
237 * dentry cache for the merge view
238 *****************************************************************************/
239extern struct kmem_cache *hmdfs_dentry_merge_cachep;
240
241#endif // HMDFS_MERGE_H
242