• 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 };
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