]> git.proxmox.com Git - mirror_ubuntu-bionic-kernel.git/blob - fs/aufs/branch.h
x86/speculation/mds: Add sysfs reporting for MDS
[mirror_ubuntu-bionic-kernel.git] / fs / aufs / branch.h
1 /*
2 * Copyright (C) 2005-2017 Junjiro R. Okajima
3 *
4 * This program, aufs is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program. If not, see <http://www.gnu.org/licenses/>.
16 */
17
18 /*
19 * branch filesystems and xino for them
20 */
21
22 #ifndef __AUFS_BRANCH_H__
23 #define __AUFS_BRANCH_H__
24
25 #ifdef __KERNEL__
26
27 #include <linux/mount.h>
28 #include "dirren.h"
29 #include "dynop.h"
30 #include "rwsem.h"
31 #include "super.h"
32
33 /* ---------------------------------------------------------------------- */
34
35 /* a xino file */
36 struct au_xino_file {
37 struct file *xi_file;
38 struct {
39 spinlock_t spin;
40 ino_t *array;
41 int total;
42 /* reserved for future use */
43 /* unsigned long *bitmap; */
44 wait_queue_head_t wqh;
45 } xi_nondir;
46
47 /* todo: make xino files an array to support huge inode number */
48
49 #ifdef CONFIG_DEBUG_FS
50 struct dentry *xi_dbgaufs;
51 #endif
52 };
53
54 /* File-based Hierarchical Storage Management */
55 struct au_br_fhsm {
56 #ifdef CONFIG_AUFS_FHSM
57 struct mutex bf_lock;
58 unsigned long bf_jiffy;
59 struct aufs_stfs bf_stfs;
60 int bf_readable;
61 #endif
62 };
63
64 /* members for writable branch only */
65 enum {AuBrWh_BASE, AuBrWh_PLINK, AuBrWh_ORPH, AuBrWh_Last};
66 struct au_wbr {
67 struct au_rwsem wbr_wh_rwsem;
68 struct dentry *wbr_wh[AuBrWh_Last];
69 atomic_t wbr_wh_running;
70 #define wbr_whbase wbr_wh[AuBrWh_BASE] /* whiteout base */
71 #define wbr_plink wbr_wh[AuBrWh_PLINK] /* pseudo-link dir */
72 #define wbr_orph wbr_wh[AuBrWh_ORPH] /* dir for orphans */
73
74 /* mfs mode */
75 unsigned long long wbr_bytes;
76 };
77
78 /* ext2 has 3 types of operations at least, ext3 has 4 */
79 #define AuBrDynOp (AuDyLast * 4)
80
81 #ifdef CONFIG_AUFS_HFSNOTIFY
82 /* support for asynchronous destruction */
83 struct au_br_hfsnotify {
84 struct fsnotify_group *hfsn_group;
85 };
86 #endif
87
88 /* sysfs entries */
89 struct au_brsysfs {
90 char name[16];
91 struct attribute attr;
92 };
93
94 enum {
95 AuBrSysfs_BR,
96 AuBrSysfs_BRID,
97 AuBrSysfs_Last
98 };
99
100 /* protected by superblock rwsem */
101 struct au_branch {
102 struct au_xino_file br_xino;
103
104 aufs_bindex_t br_id;
105
106 int br_perm;
107 struct path br_path;
108 spinlock_t br_dykey_lock;
109 struct au_dykey *br_dykey[AuBrDynOp];
110 struct percpu_counter br_count;
111
112 struct au_wbr *br_wbr;
113 struct au_br_fhsm *br_fhsm;
114
115 /* xino truncation */
116 atomic_t br_xino_running;
117
118 #ifdef CONFIG_AUFS_HFSNOTIFY
119 struct au_br_hfsnotify *br_hfsn;
120 #endif
121
122 #ifdef CONFIG_SYSFS
123 /* entries under sysfs per mount-point */
124 struct au_brsysfs br_sysfs[AuBrSysfs_Last];
125 #endif
126
127 struct au_dr_br br_dirren;
128 };
129
130 /* ---------------------------------------------------------------------- */
131
132 static inline struct vfsmount *au_br_mnt(struct au_branch *br)
133 {
134 return br->br_path.mnt;
135 }
136
137 static inline struct dentry *au_br_dentry(struct au_branch *br)
138 {
139 return br->br_path.dentry;
140 }
141
142 static inline struct super_block *au_br_sb(struct au_branch *br)
143 {
144 return au_br_mnt(br)->mnt_sb;
145 }
146
147 static inline void au_br_get(struct au_branch *br)
148 {
149 percpu_counter_inc(&br->br_count);
150 }
151
152 static inline void au_br_put(struct au_branch *br)
153 {
154 percpu_counter_dec(&br->br_count);
155 }
156
157 static inline s64 au_br_count(struct au_branch *br)
158 {
159 return percpu_counter_sum(&br->br_count);
160 }
161
162 static inline void au_br_count_init(struct au_branch *br)
163 {
164 percpu_counter_init(&br->br_count, 0, GFP_NOFS);
165 }
166
167 static inline void au_br_count_fin(struct au_branch *br)
168 {
169 percpu_counter_destroy(&br->br_count);
170 }
171
172 static inline int au_br_rdonly(struct au_branch *br)
173 {
174 return (sb_rdonly(au_br_sb(br))
175 || !au_br_writable(br->br_perm))
176 ? -EROFS : 0;
177 }
178
179 static inline int au_br_hnotifyable(int brperm __maybe_unused)
180 {
181 #ifdef CONFIG_AUFS_HNOTIFY
182 return !(brperm & AuBrPerm_RR);
183 #else
184 return 0;
185 #endif
186 }
187
188 static inline int au_br_test_oflag(int oflag, struct au_branch *br)
189 {
190 int err, exec_flag;
191
192 err = 0;
193 exec_flag = oflag & __FMODE_EXEC;
194 if (unlikely(exec_flag && path_noexec(&br->br_path)))
195 err = -EACCES;
196
197 return err;
198 }
199
200 /* ---------------------------------------------------------------------- */
201
202 /* branch.c */
203 struct au_sbinfo;
204 void au_br_free(struct au_sbinfo *sinfo);
205 int au_br_index(struct super_block *sb, aufs_bindex_t br_id);
206 struct au_opt_add;
207 int au_br_add(struct super_block *sb, struct au_opt_add *add, int remount);
208 struct au_opt_del;
209 int au_br_del(struct super_block *sb, struct au_opt_del *del, int remount);
210 long au_ibusy_ioctl(struct file *file, unsigned long arg);
211 #ifdef CONFIG_COMPAT
212 long au_ibusy_compat_ioctl(struct file *file, unsigned long arg);
213 #endif
214 struct au_opt_mod;
215 int au_br_mod(struct super_block *sb, struct au_opt_mod *mod, int remount,
216 int *do_refresh);
217 struct aufs_stfs;
218 int au_br_stfs(struct au_branch *br, struct aufs_stfs *stfs);
219
220 /* xino.c */
221 static const loff_t au_loff_max = LLONG_MAX;
222
223 int au_xib_trunc(struct super_block *sb);
224 ssize_t xino_fread(vfs_readf_t func, struct file *file, void *buf, size_t size,
225 loff_t *pos);
226 ssize_t xino_fwrite(vfs_writef_t func, struct file *file, void *buf,
227 size_t size, loff_t *pos);
228 struct file *au_xino_create2(struct file *base_file, struct file *copy_src);
229 struct file *au_xino_create(struct super_block *sb, char *fname, int silent);
230 ino_t au_xino_new_ino(struct super_block *sb);
231 void au_xino_delete_inode(struct inode *inode, const int unlinked);
232 int au_xino_write(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino,
233 ino_t ino);
234 int au_xino_read(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino,
235 ino_t *ino);
236 int au_xino_br(struct super_block *sb, struct au_branch *br, ino_t hino,
237 struct file *base_file, int do_test);
238 int au_xino_trunc(struct super_block *sb, aufs_bindex_t bindex);
239
240 struct au_opt_xino;
241 int au_xino_set(struct super_block *sb, struct au_opt_xino *xino, int remount);
242 void au_xino_clr(struct super_block *sb);
243 struct file *au_xino_def(struct super_block *sb);
244 int au_xino_path(struct seq_file *seq, struct file *file);
245
246 void au_xinondir_leave(struct super_block *sb, aufs_bindex_t bindex,
247 ino_t h_ino, int idx);
248 int au_xinondir_enter(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino,
249 int *idx);
250
251 /* ---------------------------------------------------------------------- */
252
253 /* Superblock to branch */
254 static inline
255 aufs_bindex_t au_sbr_id(struct super_block *sb, aufs_bindex_t bindex)
256 {
257 return au_sbr(sb, bindex)->br_id;
258 }
259
260 static inline
261 struct vfsmount *au_sbr_mnt(struct super_block *sb, aufs_bindex_t bindex)
262 {
263 return au_br_mnt(au_sbr(sb, bindex));
264 }
265
266 static inline
267 struct super_block *au_sbr_sb(struct super_block *sb, aufs_bindex_t bindex)
268 {
269 return au_br_sb(au_sbr(sb, bindex));
270 }
271
272 static inline void au_sbr_get(struct super_block *sb, aufs_bindex_t bindex)
273 {
274 au_br_get(au_sbr(sb, bindex));
275 }
276
277 static inline void au_sbr_put(struct super_block *sb, aufs_bindex_t bindex)
278 {
279 au_br_put(au_sbr(sb, bindex));
280 }
281
282 static inline int au_sbr_perm(struct super_block *sb, aufs_bindex_t bindex)
283 {
284 return au_sbr(sb, bindex)->br_perm;
285 }
286
287 static inline int au_sbr_whable(struct super_block *sb, aufs_bindex_t bindex)
288 {
289 return au_br_whable(au_sbr_perm(sb, bindex));
290 }
291
292 /* ---------------------------------------------------------------------- */
293
294 #define wbr_wh_read_lock(wbr) au_rw_read_lock(&(wbr)->wbr_wh_rwsem)
295 #define wbr_wh_write_lock(wbr) au_rw_write_lock(&(wbr)->wbr_wh_rwsem)
296 #define wbr_wh_read_trylock(wbr) au_rw_read_trylock(&(wbr)->wbr_wh_rwsem)
297 #define wbr_wh_write_trylock(wbr) au_rw_write_trylock(&(wbr)->wbr_wh_rwsem)
298 /*
299 #define wbr_wh_read_trylock_nested(wbr) \
300 au_rw_read_trylock_nested(&(wbr)->wbr_wh_rwsem)
301 #define wbr_wh_write_trylock_nested(wbr) \
302 au_rw_write_trylock_nested(&(wbr)->wbr_wh_rwsem)
303 */
304
305 #define wbr_wh_read_unlock(wbr) au_rw_read_unlock(&(wbr)->wbr_wh_rwsem)
306 #define wbr_wh_write_unlock(wbr) au_rw_write_unlock(&(wbr)->wbr_wh_rwsem)
307 #define wbr_wh_downgrade_lock(wbr) au_rw_dgrade_lock(&(wbr)->wbr_wh_rwsem)
308
309 #define WbrWhMustNoWaiters(wbr) AuRwMustNoWaiters(&(wbr)->wbr_wh_rwsem)
310 #define WbrWhMustAnyLock(wbr) AuRwMustAnyLock(&(wbr)->wbr_wh_rwsem)
311 #define WbrWhMustWriteLock(wbr) AuRwMustWriteLock(&(wbr)->wbr_wh_rwsem)
312
313 /* ---------------------------------------------------------------------- */
314
315 #ifdef CONFIG_AUFS_FHSM
316 static inline void au_br_fhsm_init(struct au_br_fhsm *brfhsm)
317 {
318 mutex_init(&brfhsm->bf_lock);
319 brfhsm->bf_jiffy = 0;
320 brfhsm->bf_readable = 0;
321 }
322
323 static inline void au_br_fhsm_fin(struct au_br_fhsm *brfhsm)
324 {
325 mutex_destroy(&brfhsm->bf_lock);
326 }
327 #else
328 AuStubVoid(au_br_fhsm_init, struct au_br_fhsm *brfhsm)
329 AuStubVoid(au_br_fhsm_fin, struct au_br_fhsm *brfhsm)
330 #endif
331
332 #endif /* __KERNEL__ */
333 #endif /* __AUFS_BRANCH_H__ */