]> git.proxmox.com Git - mirror_ubuntu-bionic-kernel.git/blob - fs/aufs/file.h
x86/mm: Use WRITE_ONCE() when setting PTEs
[mirror_ubuntu-bionic-kernel.git] / fs / aufs / file.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 * file operations
20 */
21
22 #ifndef __AUFS_FILE_H__
23 #define __AUFS_FILE_H__
24
25 #ifdef __KERNEL__
26
27 #include <linux/file.h>
28 #include <linux/fs.h>
29 #include <linux/mm_types.h>
30 #include <linux/poll.h>
31 #include "rwsem.h"
32
33 struct au_branch;
34 struct au_hfile {
35 struct file *hf_file;
36 struct au_branch *hf_br;
37 };
38
39 struct au_vdir;
40 struct au_fidir {
41 aufs_bindex_t fd_bbot;
42 aufs_bindex_t fd_nent;
43 struct au_vdir *fd_vdir_cache;
44 struct au_hfile fd_hfile[];
45 };
46
47 static inline int au_fidir_sz(int nent)
48 {
49 AuDebugOn(nent < 0);
50 return sizeof(struct au_fidir) + sizeof(struct au_hfile) * nent;
51 }
52
53 struct au_finfo {
54 atomic_t fi_generation;
55
56 struct au_rwsem fi_rwsem;
57 aufs_bindex_t fi_btop;
58
59 /* do not union them */
60 struct { /* for non-dir */
61 struct au_hfile fi_htop;
62 atomic_t fi_mmapped;
63 };
64 struct au_fidir *fi_hdir; /* for dir only */
65
66 struct hlist_bl_node fi_hlist;
67 struct file *fi_file; /* very ugly */
68 } ____cacheline_aligned_in_smp;
69
70 /* ---------------------------------------------------------------------- */
71
72 /* file.c */
73 extern const struct address_space_operations aufs_aop;
74 unsigned int au_file_roflags(unsigned int flags);
75 struct file *au_h_open(struct dentry *dentry, aufs_bindex_t bindex, int flags,
76 struct file *file, int force_wr);
77 struct au_do_open_args {
78 int aopen;
79 int (*open)(struct file *file, int flags,
80 struct file *h_file);
81 struct au_fidir *fidir;
82 struct file *h_file;
83 };
84 int au_do_open(struct file *file, struct au_do_open_args *args);
85 int au_reopen_nondir(struct file *file);
86 struct au_pin;
87 int au_ready_to_write(struct file *file, loff_t len, struct au_pin *pin);
88 int au_reval_and_lock_fdi(struct file *file, int (*reopen)(struct file *file),
89 int wlock, unsigned int fi_lsc);
90 int au_do_flush(struct file *file, fl_owner_t id,
91 int (*flush)(struct file *file, fl_owner_t id));
92
93 /* poll.c */
94 #ifdef CONFIG_AUFS_POLL
95 unsigned int aufs_poll(struct file *file, poll_table *wait);
96 #endif
97
98 #ifdef CONFIG_AUFS_BR_HFSPLUS
99 /* hfsplus.c */
100 struct file *au_h_open_pre(struct dentry *dentry, aufs_bindex_t bindex,
101 int force_wr);
102 void au_h_open_post(struct dentry *dentry, aufs_bindex_t bindex,
103 struct file *h_file);
104 #else
105 AuStub(struct file *, au_h_open_pre, return NULL, struct dentry *dentry,
106 aufs_bindex_t bindex, int force_wr)
107 AuStubVoid(au_h_open_post, struct dentry *dentry, aufs_bindex_t bindex,
108 struct file *h_file);
109 #endif
110
111 /* f_op.c */
112 extern const struct file_operations aufs_file_fop;
113 int au_do_open_nondir(struct file *file, int flags, struct file *h_file);
114 int aufs_release_nondir(struct inode *inode __maybe_unused, struct file *file);
115 struct file *au_read_pre(struct file *file, int keep_fi, unsigned int lsc);
116
117 /* finfo.c */
118 void au_hfput(struct au_hfile *hf, int execed);
119 void au_set_h_fptr(struct file *file, aufs_bindex_t bindex,
120 struct file *h_file);
121
122 void au_update_figen(struct file *file);
123 struct au_fidir *au_fidir_alloc(struct super_block *sb);
124 int au_fidir_realloc(struct au_finfo *finfo, int nbr, int may_shrink);
125
126 void au_fi_init_once(void *_fi);
127 void au_finfo_fin(struct file *file);
128 int au_finfo_init(struct file *file, struct au_fidir *fidir);
129
130 /* ioctl.c */
131 long aufs_ioctl_nondir(struct file *file, unsigned int cmd, unsigned long arg);
132 #ifdef CONFIG_COMPAT
133 long aufs_compat_ioctl_dir(struct file *file, unsigned int cmd,
134 unsigned long arg);
135 long aufs_compat_ioctl_nondir(struct file *file, unsigned int cmd,
136 unsigned long arg);
137 #endif
138
139 /* ---------------------------------------------------------------------- */
140
141 static inline struct au_finfo *au_fi(struct file *file)
142 {
143 return file->private_data;
144 }
145
146 /* ---------------------------------------------------------------------- */
147
148 #define fi_read_lock(f) au_rw_read_lock(&au_fi(f)->fi_rwsem)
149 #define fi_write_lock(f) au_rw_write_lock(&au_fi(f)->fi_rwsem)
150 #define fi_read_trylock(f) au_rw_read_trylock(&au_fi(f)->fi_rwsem)
151 #define fi_write_trylock(f) au_rw_write_trylock(&au_fi(f)->fi_rwsem)
152 /*
153 #define fi_read_trylock_nested(f) \
154 au_rw_read_trylock_nested(&au_fi(f)->fi_rwsem)
155 #define fi_write_trylock_nested(f) \
156 au_rw_write_trylock_nested(&au_fi(f)->fi_rwsem)
157 */
158
159 #define fi_read_unlock(f) au_rw_read_unlock(&au_fi(f)->fi_rwsem)
160 #define fi_write_unlock(f) au_rw_write_unlock(&au_fi(f)->fi_rwsem)
161 #define fi_downgrade_lock(f) au_rw_dgrade_lock(&au_fi(f)->fi_rwsem)
162
163 /* lock subclass for finfo */
164 enum {
165 AuLsc_FI_1,
166 AuLsc_FI_2
167 };
168
169 static inline void fi_read_lock_nested(struct file *f, unsigned int lsc)
170 {
171 au_rw_read_lock_nested(&au_fi(f)->fi_rwsem, lsc);
172 }
173
174 static inline void fi_write_lock_nested(struct file *f, unsigned int lsc)
175 {
176 au_rw_write_lock_nested(&au_fi(f)->fi_rwsem, lsc);
177 }
178
179 /*
180 * fi_read_lock_1, fi_write_lock_1,
181 * fi_read_lock_2, fi_write_lock_2
182 */
183 #define AuReadLockFunc(name) \
184 static inline void fi_read_lock_##name(struct file *f) \
185 { fi_read_lock_nested(f, AuLsc_FI_##name); }
186
187 #define AuWriteLockFunc(name) \
188 static inline void fi_write_lock_##name(struct file *f) \
189 { fi_write_lock_nested(f, AuLsc_FI_##name); }
190
191 #define AuRWLockFuncs(name) \
192 AuReadLockFunc(name) \
193 AuWriteLockFunc(name)
194
195 AuRWLockFuncs(1);
196 AuRWLockFuncs(2);
197
198 #undef AuReadLockFunc
199 #undef AuWriteLockFunc
200 #undef AuRWLockFuncs
201
202 #define FiMustNoWaiters(f) AuRwMustNoWaiters(&au_fi(f)->fi_rwsem)
203 #define FiMustAnyLock(f) AuRwMustAnyLock(&au_fi(f)->fi_rwsem)
204 #define FiMustWriteLock(f) AuRwMustWriteLock(&au_fi(f)->fi_rwsem)
205
206 /* ---------------------------------------------------------------------- */
207
208 /* todo: hard/soft set? */
209 static inline aufs_bindex_t au_fbtop(struct file *file)
210 {
211 FiMustAnyLock(file);
212 return au_fi(file)->fi_btop;
213 }
214
215 static inline aufs_bindex_t au_fbbot_dir(struct file *file)
216 {
217 FiMustAnyLock(file);
218 AuDebugOn(!au_fi(file)->fi_hdir);
219 return au_fi(file)->fi_hdir->fd_bbot;
220 }
221
222 static inline struct au_vdir *au_fvdir_cache(struct file *file)
223 {
224 FiMustAnyLock(file);
225 AuDebugOn(!au_fi(file)->fi_hdir);
226 return au_fi(file)->fi_hdir->fd_vdir_cache;
227 }
228
229 static inline void au_set_fbtop(struct file *file, aufs_bindex_t bindex)
230 {
231 FiMustWriteLock(file);
232 au_fi(file)->fi_btop = bindex;
233 }
234
235 static inline void au_set_fbbot_dir(struct file *file, aufs_bindex_t bindex)
236 {
237 FiMustWriteLock(file);
238 AuDebugOn(!au_fi(file)->fi_hdir);
239 au_fi(file)->fi_hdir->fd_bbot = bindex;
240 }
241
242 static inline void au_set_fvdir_cache(struct file *file,
243 struct au_vdir *vdir_cache)
244 {
245 FiMustWriteLock(file);
246 AuDebugOn(!au_fi(file)->fi_hdir);
247 au_fi(file)->fi_hdir->fd_vdir_cache = vdir_cache;
248 }
249
250 static inline struct file *au_hf_top(struct file *file)
251 {
252 FiMustAnyLock(file);
253 AuDebugOn(au_fi(file)->fi_hdir);
254 return au_fi(file)->fi_htop.hf_file;
255 }
256
257 static inline struct file *au_hf_dir(struct file *file, aufs_bindex_t bindex)
258 {
259 FiMustAnyLock(file);
260 AuDebugOn(!au_fi(file)->fi_hdir);
261 return au_fi(file)->fi_hdir->fd_hfile[0 + bindex].hf_file;
262 }
263
264 /* todo: memory barrier? */
265 static inline unsigned int au_figen(struct file *f)
266 {
267 return atomic_read(&au_fi(f)->fi_generation);
268 }
269
270 static inline void au_set_mmapped(struct file *f)
271 {
272 if (atomic_inc_return(&au_fi(f)->fi_mmapped))
273 return;
274 pr_warn("fi_mmapped wrapped around\n");
275 while (!atomic_inc_return(&au_fi(f)->fi_mmapped))
276 ;
277 }
278
279 static inline void au_unset_mmapped(struct file *f)
280 {
281 atomic_dec(&au_fi(f)->fi_mmapped);
282 }
283
284 static inline int au_test_mmapped(struct file *f)
285 {
286 return atomic_read(&au_fi(f)->fi_mmapped);
287 }
288
289 /* customize vma->vm_file */
290
291 static inline void au_do_vm_file_reset(struct vm_area_struct *vma,
292 struct file *file)
293 {
294 struct file *f;
295
296 f = vma->vm_file;
297 get_file(file);
298 vma->vm_file = file;
299 fput(f);
300 }
301
302 #ifdef CONFIG_MMU
303 #define AuDbgVmRegion(file, vma) do {} while (0)
304
305 static inline void au_vm_file_reset(struct vm_area_struct *vma,
306 struct file *file)
307 {
308 au_do_vm_file_reset(vma, file);
309 }
310 #else
311 #define AuDbgVmRegion(file, vma) \
312 AuDebugOn((vma)->vm_region && (vma)->vm_region->vm_file != (file))
313
314 static inline void au_vm_file_reset(struct vm_area_struct *vma,
315 struct file *file)
316 {
317 struct file *f;
318
319 au_do_vm_file_reset(vma, file);
320 f = vma->vm_region->vm_file;
321 get_file(file);
322 vma->vm_region->vm_file = file;
323 fput(f);
324 }
325 #endif /* CONFIG_MMU */
326
327 /* handle vma->vm_prfile */
328 static inline void au_vm_prfile_set(struct vm_area_struct *vma,
329 struct file *file)
330 {
331 get_file(file);
332 vma->vm_prfile = file;
333 #ifndef CONFIG_MMU
334 get_file(file);
335 vma->vm_region->vm_prfile = file;
336 #endif
337 }
338
339 #endif /* __KERNEL__ */
340 #endif /* __AUFS_FILE_H__ */