• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
24 struct 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 
33 struct 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 
44 struct hmdfs_dentry_comrade {
45 	uint64_t dev_id;
46 	struct dentry *lo_d;
47 	struct list_head list;
48 };
49 
50 enum FILE_CMD_MERGE {
51 	F_MKDIR_MERGE = 0,
52 	F_CREATE_MERGE = 1,
53 };
54 
55 struct hmdfs_recursive_para {
56 	bool is_last;
57 	int opcode;
58 	umode_t mode;
59 	bool want_excl;
60 	const char *name;
61 };
62 
63 struct 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 
hmdfs_dm(struct dentry * dentry)71 static inline struct hmdfs_dentry_info_merge *hmdfs_dm(struct dentry *dentry)
72 {
73 	return dentry->d_fsdata;
74 }
75 
hmdfs_cm(struct hmdfs_dentry_comrade * comrade)76 static inline umode_t hmdfs_cm(struct hmdfs_dentry_comrade *comrade)
77 {
78 	return d_inode(comrade->lo_d)->i_mode;
79 }
80 
comrade_is_local(struct hmdfs_dentry_comrade * comrade)81 static inline bool comrade_is_local(struct hmdfs_dentry_comrade *comrade)
82 {
83 	return comrade->dev_id == HMDFS_DEVID_LOCAL;
84 }
85 
86 struct hmdfs_cache_entry *allocate_entry(const char *name, int namelen,
87 					 int d_type);
88 
89 struct dentry *hmdfs_lookup_cloud_merge(struct inode *parent_inode,
90 				  struct dentry *child_dentry,
91 				  unsigned int flags);
92 
93 struct dentry *hmdfs_lookup_merge(struct inode *parent_inode,
94 				  struct dentry *child_dentry,
95 				  unsigned int flags);
96 struct hmdfs_file_info *
97 get_next_hmdfs_file_info(struct hmdfs_file_info *fi_head, int device_id);
98 
99 struct hmdfs_file_info *get_hmdfs_file_info(struct hmdfs_file_info *fi_head,
100 					    int device_id);
101 int insert_filename(struct rb_root *root, struct hmdfs_cache_entry **new_entry);
102 struct hmdfs_dentry_comrade *alloc_comrade(struct dentry *lo_d, int dev_id);
103 int check_filename(const char *name, int len);
104 int init_hmdfs_dentry_info_merge(struct hmdfs_sb_info *sbi,
105 	struct dentry *dentry);
106 void hmdfs_init_recursive_para(struct hmdfs_recursive_para *rec_op_para,
107 			       int opcode, mode_t mode, bool want_excl,
108 			       const char *name);
109 void link_comrade(struct list_head *onstack_comrades_head,
110 		  struct hmdfs_dentry_comrade *comrade);
111 void update_inode_attr(struct inode *inode, struct dentry *child_dentry);
112 int get_num_comrades(struct dentry *dentry);
113 void assign_comrades_unlocked(struct dentry *child_dentry,
114 			      struct list_head *onstack_comrades_head);
115 struct hmdfs_dentry_comrade *lookup_comrade(struct path lower_path,
116 					    const char *d_name,
117 					    int dev_id,
118 					    unsigned int flags);
119 bool is_valid_comrade(struct hmdfs_dentry_info_merge *mdi, umode_t mode);
120 int merge_lookup_async(struct hmdfs_dentry_info_merge *mdi,
121 		       struct hmdfs_sb_info *sbi, int devid,
122 		       const char *name, unsigned int flags);
123 char *hmdfs_get_real_dname(struct dentry *dentry, int *devid, int *type);
124 void lock_root_inode_shared(struct inode *root, bool *locked, bool *down);
125 void restore_root_inode_sem(struct inode *root, bool locked, bool down);
126 int hmdfs_getattr_merge(const struct path *path, struct kstat *stat,
127 			u32 request_mask, unsigned int flags);
128 int hmdfs_setattr_merge(struct dentry *dentry, struct iattr *ia);
129 int hmdfs_rmdir_merge(struct inode *dir, struct dentry *dentry);
130 int hmdfs_unlink_merge(struct inode *dir, struct dentry *dentry);
131 int hmdfs_rename_merge(struct inode *old_dir, struct dentry *old_dentry,
132 		       struct inode *new_dir, struct dentry *new_dentry,
133 		       unsigned int flags);
134 int 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 
destroy_comrade(struct hmdfs_dentry_comrade * comrade)138 static inline void destroy_comrade(struct hmdfs_dentry_comrade *comrade)
139 {
140 	dput(comrade->lo_d);
141 	kfree(comrade);
142 }
143 
144 void clear_comrades(struct dentry *dentry);
145 
link_comrade_unlocked(struct dentry * dentry,struct hmdfs_dentry_comrade * comrade)146 static 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 
154 void clear_comrades_locked(struct list_head *comrade_list);
155 
is_comrade_list_empty(struct hmdfs_dentry_info_merge * mdi)156 static 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 
has_merge_lookup_work(struct hmdfs_dentry_info_merge * mdi)167 static 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 
is_merge_lookup_end(struct hmdfs_dentry_info_merge * mdi)178 static 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 
189 void 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 
hmdfs_i_merge(struct hmdfs_inode_info * hii)213 static 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 
221 struct dentry *hmdfs_get_lo_d(struct dentry *dentry, int dev_id);
222 struct dentry *hmdfs_get_fst_lo_d(struct dentry *dentry);
223 
224 /*****************************************************************************
225  * Inode operations for the merge view
226  *****************************************************************************/
227 
228 extern const struct inode_operations hmdfs_file_iops_merge;
229 extern const struct file_operations hmdfs_file_fops_merge;
230 extern const struct inode_operations hmdfs_dir_iops_merge;
231 extern const struct file_operations hmdfs_dir_fops_merge;
232 extern const struct inode_operations hmdfs_file_iops_cloud_merge;
233 extern const struct inode_operations hmdfs_dir_iops_cloud_merge;
234 extern const struct dentry_operations hmdfs_dops_merge;
235 
236 /*****************************************************************************
237  * dentry cache for the merge view
238  *****************************************************************************/
239 extern struct kmem_cache *hmdfs_dentry_merge_cachep;
240 
241 #endif // HMDFS_MERGE_H
242