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 };
hmdfs_dm(struct dentry * dentry)62 static inline struct hmdfs_dentry_info_merge *hmdfs_dm(struct dentry *dentry)
63 {
64 return dentry->d_fsdata;
65 }
66
hmdfs_cm(struct hmdfs_dentry_comrade * comrade)67 static inline umode_t hmdfs_cm(struct hmdfs_dentry_comrade *comrade)
68 {
69 return d_inode(comrade->lo_d)->i_mode;
70 }
71
comrade_is_local(struct hmdfs_dentry_comrade * comrade)72 static inline bool comrade_is_local(struct hmdfs_dentry_comrade *comrade)
73 {
74 return comrade->dev_id == HMDFS_DEVID_LOCAL;
75 }
76
77 struct dentry *hmdfs_lookup_merge(struct inode *parent_inode,
78 struct dentry *child_dentry,
79 unsigned int flags);
80
81 struct hmdfs_dentry_comrade *alloc_comrade(struct dentry *lo_d, int dev_id);
82
83 void link_comrade(struct list_head *onstack_comrades_head,
84 struct hmdfs_dentry_comrade *comrade);
85
destroy_comrade(struct hmdfs_dentry_comrade * comrade)86 static inline void destroy_comrade(struct hmdfs_dentry_comrade *comrade)
87 {
88 dput(comrade->lo_d);
89 kfree(comrade);
90 }
91
92 void clear_comrades(struct dentry *dentry);
93
link_comrade_unlocked(struct dentry * dentry,struct hmdfs_dentry_comrade * comrade)94 static inline void link_comrade_unlocked(struct dentry *dentry,
95 struct hmdfs_dentry_comrade *comrade)
96 {
97 mutex_lock(&hmdfs_dm(dentry)->comrade_list_lock);
98 link_comrade(&hmdfs_dm(dentry)->comrade_list, comrade);
99 mutex_unlock(&hmdfs_dm(dentry)->comrade_list_lock);
100 }
101
102 void clear_comrades_locked(struct list_head *comrade_list);
103
is_comrade_list_empty(struct hmdfs_dentry_info_merge * mdi)104 static inline bool is_comrade_list_empty(struct hmdfs_dentry_info_merge *mdi)
105 {
106 bool ret;
107
108 mutex_lock(&mdi->comrade_list_lock);
109 ret = list_empty(&mdi->comrade_list);
110 mutex_unlock(&mdi->comrade_list_lock);
111
112 return ret;
113 }
114
has_merge_lookup_work(struct hmdfs_dentry_info_merge * mdi)115 static inline bool has_merge_lookup_work(struct hmdfs_dentry_info_merge *mdi)
116 {
117 bool ret;
118
119 mutex_lock(&mdi->work_lock);
120 ret = (mdi->work_count != 0);
121 mutex_unlock(&mdi->work_lock);
122
123 return ret;
124 }
125
is_merge_lookup_end(struct hmdfs_dentry_info_merge * mdi)126 static inline bool is_merge_lookup_end(struct hmdfs_dentry_info_merge *mdi)
127 {
128 bool ret;
129
130 mutex_lock(&mdi->work_lock);
131 ret = mdi->work_count == 0 || !is_comrade_list_empty(mdi);
132 mutex_unlock(&mdi->work_lock);
133
134 return ret;
135 }
136
137 #define for_each_comrade_locked(_dentry, _comrade) \
138 list_for_each_entry(_comrade, &(hmdfs_dm(_dentry)->comrade_list), list)
139
140 #define hmdfs_trace_merge(_trace_func, _parent_inode, _child_dentry, err) \
141 { \
142 struct hmdfs_dentry_comrade *comrade; \
143 struct hmdfs_dentry_info_merge *dm = hmdfs_dm(_child_dentry); \
144 _trace_func(_parent_inode, _child_dentry, err); \
145 if (likely(dm)) { \
146 mutex_lock(&dm->comrade_list_lock); \
147 for_each_comrade_locked(_child_dentry, comrade) \
148 trace_hmdfs_show_comrade(_child_dentry, \
149 comrade->lo_d, \
150 comrade->dev_id); \
151 mutex_unlock(&dm->comrade_list_lock); \
152 } \
153 }
154
155 #define hmdfs_trace_rename_merge(olddir, olddentry, newdir, newdentry, err) \
156 { \
157 struct hmdfs_dentry_comrade *comrade; \
158 trace_hmdfs_rename_merge(olddir, olddentry, newdir, newdentry, \
159 err); \
160 mutex_lock(&hmdfs_dm(olddentry)->comrade_list_lock); \
161 for_each_comrade_locked(olddentry, comrade) \
162 trace_hmdfs_show_comrade(olddentry, comrade->lo_d, \
163 comrade->dev_id); \
164 mutex_unlock(&hmdfs_dm(olddentry)->comrade_list_lock); \
165 mutex_lock(&hmdfs_dm(newdentry)->comrade_list_lock); \
166 for_each_comrade_locked(newdentry, comrade) \
167 trace_hmdfs_show_comrade(newdentry, comrade->lo_d, \
168 comrade->dev_id); \
169 mutex_unlock(&hmdfs_dm(newdentry)->comrade_list_lock); \
170 }
171
172 /*****************************************************************************
173 * Helper functions abstarcting out comrade
174 *****************************************************************************/
175
hmdfs_i_merge(struct hmdfs_inode_info * hii)176 static inline bool hmdfs_i_merge(struct hmdfs_inode_info *hii)
177 {
178 __u8 t = hii->inode_type;
179 return t == HMDFS_LAYER_FIRST_MERGE || t == HMDFS_LAYER_OTHER_MERGE;
180 }
181
182 struct dentry *hmdfs_get_lo_d(struct dentry *dentry, int dev_id);
183 struct dentry *hmdfs_get_fst_lo_d(struct dentry *dentry);
184
185 /*****************************************************************************
186 * Inode operations for the merge view
187 *****************************************************************************/
188
189 extern const struct inode_operations hmdfs_file_iops_merge;
190 extern const struct file_operations hmdfs_file_fops_merge;
191 extern const struct inode_operations hmdfs_dir_iops_merge;
192 extern const struct file_operations hmdfs_dir_fops_merge;
193 extern const struct dentry_operations hmdfs_dops_merge;
194
195 /*****************************************************************************
196 * dentry cache for the merge view
197 *****************************************************************************/
198 extern struct kmem_cache *hmdfs_dentry_merge_cachep;
199
200 #endif // HMDFS_MERGE_H
201