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