• 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 
16 /*****************************************************************************
17  * Dentires for merge view and their comrades.
18  * A dentry's lower dentry is named COMRADE.
19  *****************************************************************************/
20 
21 struct hmdfs_dentry_info_merge {
22 	unsigned long ctime;
23 	// For the merge view to link dentries with same names
24 	struct mutex comrade_list_lock;
25 	struct list_head comrade_list;
26 };
27 
28 struct hmdfs_dentry_comrade {
29 	uint64_t dev_id;
30 	struct dentry *lo_d;
31 	struct list_head list;
32 };
33 
34 enum FILE_CMD_MERGE {
35 	F_MKDIR_MERGE = 0,
36 	F_CREATE_MERGE = 1,
37 };
38 
39 struct hmdfs_recursive_para {
40 	bool is_last;
41 	int opcode;
42 	umode_t mode;
43 	bool want_excl;
44 	const char *name;
45 };
hmdfs_dm(struct dentry * dentry)46 static inline struct hmdfs_dentry_info_merge *hmdfs_dm(struct dentry *dentry)
47 {
48 	return dentry->d_fsdata;
49 }
50 
hmdfs_cm(struct hmdfs_dentry_comrade * comrade)51 static inline umode_t hmdfs_cm(struct hmdfs_dentry_comrade *comrade)
52 {
53 	return d_inode(comrade->lo_d)->i_mode;
54 }
55 
comrade_is_local(struct hmdfs_dentry_comrade * comrade)56 static inline bool comrade_is_local(struct hmdfs_dentry_comrade *comrade)
57 {
58 	return comrade->dev_id == HMDFS_DEVID_LOCAL;
59 }
60 
61 struct dentry *hmdfs_lookup_merge(struct inode *parent_inode,
62 				  struct dentry *child_dentry,
63 				  unsigned int flags);
64 
65 struct hmdfs_dentry_comrade *alloc_comrade(struct dentry *lo_d, int dev_id);
66 
67 void link_comrade(struct list_head *onstack_comrades_head,
68 		  struct hmdfs_dentry_comrade *comrade);
69 
destroy_comrade(struct hmdfs_dentry_comrade * comrade)70 static inline void destroy_comrade(struct hmdfs_dentry_comrade *comrade)
71 {
72 	dput(comrade->lo_d);
73 	kfree(comrade);
74 }
75 
76 void clear_comrades(struct dentry *dentry);
77 
link_comrade_unlocked(struct dentry * dentry,struct hmdfs_dentry_comrade * comrade)78 static inline void link_comrade_unlocked(struct dentry *dentry,
79 					 struct hmdfs_dentry_comrade *comrade)
80 {
81 	mutex_lock(&hmdfs_dm(dentry)->comrade_list_lock);
82 	link_comrade(&hmdfs_dm(dentry)->comrade_list, comrade);
83 	mutex_unlock(&hmdfs_dm(dentry)->comrade_list_lock);
84 }
85 
86 void clear_comrades_locked(struct list_head *comrade_list);
87 
88 #define for_each_comrade_locked(_dentry, _comrade)                             \
89 	list_for_each_entry(_comrade, &(hmdfs_dm(_dentry)->comrade_list), list)
90 
91 #define hmdfs_trace_merge(_trace_func, _parent_inode, _child_dentry, err)      \
92 	{                                                                      \
93 		struct hmdfs_dentry_comrade *comrade;                          \
94 		struct hmdfs_dentry_info_merge *dm = hmdfs_dm(_child_dentry);  \
95 		_trace_func(_parent_inode, _child_dentry, err);                \
96 		if (likely(dm)) {                                              \
97 			mutex_lock(&dm->comrade_list_lock);                    \
98 			for_each_comrade_locked(_child_dentry, comrade)        \
99 				trace_hmdfs_show_comrade(_child_dentry,        \
100 							 comrade->lo_d,        \
101 							 comrade->dev_id);     \
102 			mutex_unlock(&dm->comrade_list_lock);                  \
103 		}                                                              \
104 	}
105 
106 #define hmdfs_trace_rename_merge(olddir, olddentry, newdir, newdentry, err)    \
107 	{                                                                      \
108 		struct hmdfs_dentry_comrade *comrade;                          \
109 		trace_hmdfs_rename_merge(olddir, olddentry, newdir, newdentry, \
110 					 err);                                 \
111 		mutex_lock(&hmdfs_dm(olddentry)->comrade_list_lock);           \
112 		for_each_comrade_locked(olddentry, comrade)                    \
113 			trace_hmdfs_show_comrade(olddentry, comrade->lo_d,     \
114 						 comrade->dev_id);             \
115 		mutex_unlock(&hmdfs_dm(olddentry)->comrade_list_lock);         \
116 		mutex_lock(&hmdfs_dm(newdentry)->comrade_list_lock);           \
117 		for_each_comrade_locked(newdentry, comrade)                    \
118 			trace_hmdfs_show_comrade(newdentry, comrade->lo_d,     \
119 						 comrade->dev_id);             \
120 		mutex_unlock(&hmdfs_dm(newdentry)->comrade_list_lock);         \
121 	}
122 
123 /*****************************************************************************
124  * Helper functions abstarcting out comrade
125  *****************************************************************************/
126 
hmdfs_i_merge(struct hmdfs_inode_info * hii)127 static inline bool hmdfs_i_merge(struct hmdfs_inode_info *hii)
128 {
129 	__u8 t = hii->inode_type;
130 	return t == HMDFS_LAYER_FIRST_MERGE || t == HMDFS_LAYER_OTHER_MERGE;
131 }
132 
133 struct dentry *hmdfs_get_lo_d(struct dentry *dentry, int dev_id);
134 struct dentry *hmdfs_get_fst_lo_d(struct dentry *dentry);
135 
136 /*****************************************************************************
137  * Inode operations for the merge view
138  *****************************************************************************/
139 
140 extern const struct inode_operations hmdfs_file_iops_merge;
141 extern const struct file_operations hmdfs_file_fops_merge;
142 extern const struct inode_operations hmdfs_dir_iops_merge;
143 extern const struct file_operations hmdfs_dir_fops_merge;
144 extern const struct dentry_operations hmdfs_dops_merge;
145 
146 /*****************************************************************************
147  * dentry cache for the merge view
148  *****************************************************************************/
149 extern struct kmem_cache *hmdfs_dentry_merge_cachep;
150 
151 #endif // HMDFS_MERGE_H
152