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