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