]> git.proxmox.com Git - mirror_ubuntu-bionic-kernel.git/blame - fs/aufs/dentry.h
scsi: core: Fix race on creating sense cache
[mirror_ubuntu-bionic-kernel.git] / fs / aufs / dentry.h
CommitLineData
c088e31d
SF
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 * lookup and dentry operations
20 */
21
22#ifndef __AUFS_DENTRY_H__
23#define __AUFS_DENTRY_H__
24
25#ifdef __KERNEL__
26
27#include <linux/dcache.h>
28#include "dirren.h"
29#include "rwsem.h"
30
31struct au_hdentry {
32 struct dentry *hd_dentry;
33 aufs_bindex_t hd_id;
34};
35
36struct au_dinfo {
37 atomic_t di_generation;
38
39 struct au_rwsem di_rwsem;
40 aufs_bindex_t di_btop, di_bbot, di_bwh, di_bdiropq;
41 unsigned char di_tmpfile; /* to allow the different name */
42 struct au_hdentry *di_hdentry;
43} ____cacheline_aligned_in_smp;
44
45/* ---------------------------------------------------------------------- */
46
47/* flags for au_lkup_dentry() */
48#define AuLkup_ALLOW_NEG 1
49#define AuLkup_IGNORE_PERM (1 << 1)
50#define AuLkup_DIRREN (1 << 2)
51#define au_ftest_lkup(flags, name) ((flags) & AuLkup_##name)
52#define au_fset_lkup(flags, name) \
53 do { (flags) |= AuLkup_##name; } while (0)
54#define au_fclr_lkup(flags, name) \
55 do { (flags) &= ~AuLkup_##name; } while (0)
56
57#ifndef CONFIG_AUFS_DIRREN
58#undef AuLkup_DIRREN
59#define AuLkup_DIRREN 0
60#endif
61
62struct au_do_lookup_args {
63 unsigned int flags;
64 mode_t type;
65 struct qstr whname, *name;
66 struct au_dr_lookup dirren;
67};
68
69/* ---------------------------------------------------------------------- */
70
71/* dentry.c */
72extern const struct dentry_operations aufs_dop, aufs_dop_noreval;
73struct au_branch;
74struct dentry *au_sio_lkup_one(struct qstr *name, struct dentry *parent);
75int au_h_verify(struct dentry *h_dentry, unsigned int udba, struct inode *h_dir,
76 struct dentry *h_parent, struct au_branch *br);
77
78int au_lkup_dentry(struct dentry *dentry, aufs_bindex_t btop,
79 unsigned int flags);
80int au_lkup_neg(struct dentry *dentry, aufs_bindex_t bindex, int wh);
81int au_refresh_dentry(struct dentry *dentry, struct dentry *parent);
82int au_reval_dpath(struct dentry *dentry, unsigned int sigen);
83void au_refresh_dop(struct dentry *dentry, int force_reval);
84
85/* dinfo.c */
86void au_di_init_once(void *_di);
87struct au_dinfo *au_di_alloc(struct super_block *sb, unsigned int lsc);
88void au_di_free(struct au_dinfo *dinfo);
89void au_di_swap(struct au_dinfo *a, struct au_dinfo *b);
90void au_di_cp(struct au_dinfo *dst, struct au_dinfo *src);
91int au_di_init(struct dentry *dentry);
92void au_di_fin(struct dentry *dentry);
93int au_di_realloc(struct au_dinfo *dinfo, int nbr, int may_shrink);
94
95void di_read_lock(struct dentry *d, int flags, unsigned int lsc);
96void di_read_unlock(struct dentry *d, int flags);
97void di_downgrade_lock(struct dentry *d, int flags);
98void di_write_lock(struct dentry *d, unsigned int lsc);
99void di_write_unlock(struct dentry *d);
100void di_write_lock2_child(struct dentry *d1, struct dentry *d2, int isdir);
101void di_write_lock2_parent(struct dentry *d1, struct dentry *d2, int isdir);
102void di_write_unlock2(struct dentry *d1, struct dentry *d2);
103
104struct dentry *au_h_dptr(struct dentry *dentry, aufs_bindex_t bindex);
105struct dentry *au_h_d_alias(struct dentry *dentry, aufs_bindex_t bindex);
106aufs_bindex_t au_dbtail(struct dentry *dentry);
107aufs_bindex_t au_dbtaildir(struct dentry *dentry);
108
109void au_set_h_dptr(struct dentry *dentry, aufs_bindex_t bindex,
110 struct dentry *h_dentry);
111int au_digen_test(struct dentry *dentry, unsigned int sigen);
112int au_dbrange_test(struct dentry *dentry);
113void au_update_digen(struct dentry *dentry);
114void au_update_dbrange(struct dentry *dentry, int do_put_zero);
115void au_update_dbtop(struct dentry *dentry);
116void au_update_dbbot(struct dentry *dentry);
117int au_find_dbindex(struct dentry *dentry, struct dentry *h_dentry);
118
119/* ---------------------------------------------------------------------- */
120
121static inline struct au_dinfo *au_di(struct dentry *dentry)
122{
123 return dentry->d_fsdata;
124}
125
126/* ---------------------------------------------------------------------- */
127
128/* lock subclass for dinfo */
129enum {
130 AuLsc_DI_CHILD, /* child first */
131 AuLsc_DI_CHILD2, /* rename(2), link(2), and cpup at hnotify */
132 AuLsc_DI_CHILD3, /* copyup dirs */
133 AuLsc_DI_PARENT,
134 AuLsc_DI_PARENT2,
135 AuLsc_DI_PARENT3,
136 AuLsc_DI_TMP /* temp for replacing dinfo */
137};
138
139/*
140 * di_read_lock_child, di_write_lock_child,
141 * di_read_lock_child2, di_write_lock_child2,
142 * di_read_lock_child3, di_write_lock_child3,
143 * di_read_lock_parent, di_write_lock_parent,
144 * di_read_lock_parent2, di_write_lock_parent2,
145 * di_read_lock_parent3, di_write_lock_parent3,
146 */
147#define AuReadLockFunc(name, lsc) \
148static inline void di_read_lock_##name(struct dentry *d, int flags) \
149{ di_read_lock(d, flags, AuLsc_DI_##lsc); }
150
151#define AuWriteLockFunc(name, lsc) \
152static inline void di_write_lock_##name(struct dentry *d) \
153{ di_write_lock(d, AuLsc_DI_##lsc); }
154
155#define AuRWLockFuncs(name, lsc) \
156 AuReadLockFunc(name, lsc) \
157 AuWriteLockFunc(name, lsc)
158
159AuRWLockFuncs(child, CHILD);
160AuRWLockFuncs(child2, CHILD2);
161AuRWLockFuncs(child3, CHILD3);
162AuRWLockFuncs(parent, PARENT);
163AuRWLockFuncs(parent2, PARENT2);
164AuRWLockFuncs(parent3, PARENT3);
165
166#undef AuReadLockFunc
167#undef AuWriteLockFunc
168#undef AuRWLockFuncs
169
170#define DiMustNoWaiters(d) AuRwMustNoWaiters(&au_di(d)->di_rwsem)
171#define DiMustAnyLock(d) AuRwMustAnyLock(&au_di(d)->di_rwsem)
172#define DiMustWriteLock(d) AuRwMustWriteLock(&au_di(d)->di_rwsem)
173
174/* ---------------------------------------------------------------------- */
175
176/* todo: memory barrier? */
177static inline unsigned int au_digen(struct dentry *d)
178{
179 return atomic_read(&au_di(d)->di_generation);
180}
181
182static inline void au_h_dentry_init(struct au_hdentry *hdentry)
183{
184 hdentry->hd_dentry = NULL;
185}
186
187static inline struct au_hdentry *au_hdentry(struct au_dinfo *di,
188 aufs_bindex_t bindex)
189{
190 return di->di_hdentry + bindex;
191}
192
193static inline void au_hdput(struct au_hdentry *hd)
194{
195 if (hd)
196 dput(hd->hd_dentry);
197}
198
199static inline aufs_bindex_t au_dbtop(struct dentry *dentry)
200{
201 DiMustAnyLock(dentry);
202 return au_di(dentry)->di_btop;
203}
204
205static inline aufs_bindex_t au_dbbot(struct dentry *dentry)
206{
207 DiMustAnyLock(dentry);
208 return au_di(dentry)->di_bbot;
209}
210
211static inline aufs_bindex_t au_dbwh(struct dentry *dentry)
212{
213 DiMustAnyLock(dentry);
214 return au_di(dentry)->di_bwh;
215}
216
217static inline aufs_bindex_t au_dbdiropq(struct dentry *dentry)
218{
219 DiMustAnyLock(dentry);
220 return au_di(dentry)->di_bdiropq;
221}
222
223/* todo: hard/soft set? */
224static inline void au_set_dbtop(struct dentry *dentry, aufs_bindex_t bindex)
225{
226 DiMustWriteLock(dentry);
227 au_di(dentry)->di_btop = bindex;
228}
229
230static inline void au_set_dbbot(struct dentry *dentry, aufs_bindex_t bindex)
231{
232 DiMustWriteLock(dentry);
233 au_di(dentry)->di_bbot = bindex;
234}
235
236static inline void au_set_dbwh(struct dentry *dentry, aufs_bindex_t bindex)
237{
238 DiMustWriteLock(dentry);
239 /* dbwh can be outside of btop - bbot range */
240 au_di(dentry)->di_bwh = bindex;
241}
242
243static inline void au_set_dbdiropq(struct dentry *dentry, aufs_bindex_t bindex)
244{
245 DiMustWriteLock(dentry);
246 au_di(dentry)->di_bdiropq = bindex;
247}
248
249/* ---------------------------------------------------------------------- */
250
251#ifdef CONFIG_AUFS_HNOTIFY
252static inline void au_digen_dec(struct dentry *d)
253{
254 atomic_dec(&au_di(d)->di_generation);
255}
256
257static inline void au_hn_di_reinit(struct dentry *dentry)
258{
259 dentry->d_fsdata = NULL;
260}
261#else
262AuStubVoid(au_hn_di_reinit, struct dentry *dentry __maybe_unused)
263#endif /* CONFIG_AUFS_HNOTIFY */
264
265#endif /* __KERNEL__ */
266#endif /* __AUFS_DENTRY_H__ */