]> git.proxmox.com Git - mirror_ubuntu-zesty-kernel.git/blob - fs/aufs/file.h
UBUNTU: SAUCE: Import aufs driver
[mirror_ubuntu-zesty-kernel.git] / fs / aufs / file.h
1 /*
2 * Copyright (C) 2005-2016 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/poll.h>
30 #include "rwsem.h"
31
32 struct au_branch;
33 struct au_hfile {
34 struct file *hf_file;
35 struct au_branch *hf_br;
36 };
37
38 struct au_vdir;
39 struct au_fidir {
40 aufs_bindex_t fd_bbot;
41 aufs_bindex_t fd_nent;
42 struct au_vdir *fd_vdir_cache;
43 struct au_hfile fd_hfile[];
44 };
45
46 static inline int au_fidir_sz(int nent)
47 {
48 AuDebugOn(nent < 0);
49 return sizeof(struct au_fidir) + sizeof(struct au_hfile) * nent;
50 }
51
52 struct au_finfo {
53 atomic_t fi_generation;
54
55 struct au_rwsem fi_rwsem;
56 aufs_bindex_t fi_btop;
57
58 /* do not union them */
59 struct { /* for non-dir */
60 struct au_hfile fi_htop;
61 atomic_t fi_mmapped;
62 };
63 struct au_fidir *fi_hdir; /* for dir only */
64
65 struct hlist_node fi_hlist;
66 union {
67 struct file *fi_file; /* very ugly */
68 struct llist_node fi_lnode; /* delayed free */
69 };
70 } ____cacheline_aligned_in_smp;
71
72 /* ---------------------------------------------------------------------- */
73
74 /* file.c */
75 extern const struct address_space_operations aufs_aop;
76 unsigned int au_file_roflags(unsigned int flags);
77 struct file *au_h_open(struct dentry *dentry, aufs_bindex_t bindex, int flags,
78 struct file *file, int force_wr);
79 struct au_do_open_args {
80 int no_lock;
81 int (*open)(struct file *file, int flags,
82 struct file *h_file);
83 struct au_fidir *fidir;
84 struct file *h_file;
85 };
86 int au_do_open(struct file *file, struct au_do_open_args *args);
87 int au_reopen_nondir(struct file *file);
88 struct au_pin;
89 int au_ready_to_write(struct file *file, loff_t len, struct au_pin *pin);
90 int au_reval_and_lock_fdi(struct file *file, int (*reopen)(struct file *file),
91 int wlock);
92 int 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 unsigned int aufs_poll(struct file *file, poll_table *wait);
98 #endif
99
100 #ifdef CONFIG_AUFS_BR_HFSPLUS
101 /* hfsplus.c */
102 struct file *au_h_open_pre(struct dentry *dentry, aufs_bindex_t bindex,
103 int force_wr);
104 void au_h_open_post(struct dentry *dentry, aufs_bindex_t bindex,
105 struct file *h_file);
106 #else
107 AuStub(struct file *, au_h_open_pre, return NULL, struct dentry *dentry,
108 aufs_bindex_t bindex, int force_wr)
109 AuStubVoid(au_h_open_post, struct dentry *dentry, aufs_bindex_t bindex,
110 struct file *h_file);
111 #endif
112
113 /* f_op.c */
114 extern const struct file_operations aufs_file_fop;
115 int au_do_open_nondir(struct file *file, int flags, struct file *h_file);
116 int aufs_release_nondir(struct inode *inode __maybe_unused, struct file *file);
117 struct file *au_read_pre(struct file *file, int keep_fi);
118
119 /* finfo.c */
120 void au_hfput(struct au_hfile *hf, int execed);
121 void au_set_h_fptr(struct file *file, aufs_bindex_t bindex,
122 struct file *h_file);
123
124 void au_update_figen(struct file *file);
125 struct au_fidir *au_fidir_alloc(struct super_block *sb);
126 int au_fidir_realloc(struct au_finfo *finfo, int nbr, int may_shrink);
127
128 void au_fi_init_once(void *_fi);
129 void au_finfo_fin(struct file *file, int atonce);
130 int au_finfo_init(struct file *file, struct au_fidir *fidir);
131
132 /* ioctl.c */
133 long aufs_ioctl_nondir(struct file *file, unsigned int cmd, unsigned long arg);
134 #ifdef CONFIG_COMPAT
135 long aufs_compat_ioctl_dir(struct file *file, unsigned int cmd,
136 unsigned long arg);
137 long aufs_compat_ioctl_nondir(struct file *file, unsigned int cmd,
138 unsigned long arg);
139 #endif
140
141 /* ---------------------------------------------------------------------- */
142
143 static inline struct au_finfo *au_fi(struct file *file)
144 {
145 return file->private_data;
146 }
147
148 /* ---------------------------------------------------------------------- */
149
150 /*
151 * fi_read_lock, fi_write_lock,
152 * fi_read_unlock, fi_write_unlock, fi_downgrade_lock
153 */
154 AuSimpleRwsemFuncs(fi, struct file *f, &au_fi(f)->fi_rwsem);
155
156 #define FiMustNoWaiters(f) AuRwMustNoWaiters(&au_fi(f)->fi_rwsem)
157 #define FiMustAnyLock(f) AuRwMustAnyLock(&au_fi(f)->fi_rwsem)
158 #define FiMustWriteLock(f) AuRwMustWriteLock(&au_fi(f)->fi_rwsem)
159
160 /* ---------------------------------------------------------------------- */
161
162 /* todo: hard/soft set? */
163 static inline aufs_bindex_t au_fbtop(struct file *file)
164 {
165 FiMustAnyLock(file);
166 return au_fi(file)->fi_btop;
167 }
168
169 static inline aufs_bindex_t au_fbbot_dir(struct file *file)
170 {
171 FiMustAnyLock(file);
172 AuDebugOn(!au_fi(file)->fi_hdir);
173 return au_fi(file)->fi_hdir->fd_bbot;
174 }
175
176 static inline struct au_vdir *au_fvdir_cache(struct file *file)
177 {
178 FiMustAnyLock(file);
179 AuDebugOn(!au_fi(file)->fi_hdir);
180 return au_fi(file)->fi_hdir->fd_vdir_cache;
181 }
182
183 static inline void au_set_fbtop(struct file *file, aufs_bindex_t bindex)
184 {
185 FiMustWriteLock(file);
186 au_fi(file)->fi_btop = bindex;
187 }
188
189 static inline void au_set_fbbot_dir(struct file *file, aufs_bindex_t bindex)
190 {
191 FiMustWriteLock(file);
192 AuDebugOn(!au_fi(file)->fi_hdir);
193 au_fi(file)->fi_hdir->fd_bbot = bindex;
194 }
195
196 static inline void au_set_fvdir_cache(struct file *file,
197 struct au_vdir *vdir_cache)
198 {
199 FiMustWriteLock(file);
200 AuDebugOn(!au_fi(file)->fi_hdir);
201 au_fi(file)->fi_hdir->fd_vdir_cache = vdir_cache;
202 }
203
204 static inline struct file *au_hf_top(struct file *file)
205 {
206 FiMustAnyLock(file);
207 AuDebugOn(au_fi(file)->fi_hdir);
208 return au_fi(file)->fi_htop.hf_file;
209 }
210
211 static inline struct file *au_hf_dir(struct file *file, aufs_bindex_t bindex)
212 {
213 FiMustAnyLock(file);
214 AuDebugOn(!au_fi(file)->fi_hdir);
215 return au_fi(file)->fi_hdir->fd_hfile[0 + bindex].hf_file;
216 }
217
218 /* todo: memory barrier? */
219 static inline unsigned int au_figen(struct file *f)
220 {
221 return atomic_read(&au_fi(f)->fi_generation);
222 }
223
224 static inline void au_set_mmapped(struct file *f)
225 {
226 if (atomic_inc_return(&au_fi(f)->fi_mmapped))
227 return;
228 pr_warn("fi_mmapped wrapped around\n");
229 while (!atomic_inc_return(&au_fi(f)->fi_mmapped))
230 ;
231 }
232
233 static inline void au_unset_mmapped(struct file *f)
234 {
235 atomic_dec(&au_fi(f)->fi_mmapped);
236 }
237
238 static inline int au_test_mmapped(struct file *f)
239 {
240 return atomic_read(&au_fi(f)->fi_mmapped);
241 }
242
243 /* customize vma->vm_file */
244
245 static inline void au_do_vm_file_reset(struct vm_area_struct *vma,
246 struct file *file)
247 {
248 struct file *f;
249
250 f = vma->vm_file;
251 get_file(file);
252 vma->vm_file = file;
253 fput(f);
254 }
255
256 #ifdef CONFIG_MMU
257 #define AuDbgVmRegion(file, vma) do {} while (0)
258
259 static inline void au_vm_file_reset(struct vm_area_struct *vma,
260 struct file *file)
261 {
262 au_do_vm_file_reset(vma, file);
263 }
264 #else
265 #define AuDbgVmRegion(file, vma) \
266 AuDebugOn((vma)->vm_region && (vma)->vm_region->vm_file != (file))
267
268 static inline void au_vm_file_reset(struct vm_area_struct *vma,
269 struct file *file)
270 {
271 struct file *f;
272
273 au_do_vm_file_reset(vma, file);
274 f = vma->vm_region->vm_file;
275 get_file(file);
276 vma->vm_region->vm_file = file;
277 fput(f);
278 }
279 #endif /* CONFIG_MMU */
280
281 /* handle vma->vm_prfile */
282 static inline void au_vm_prfile_set(struct vm_area_struct *vma,
283 struct file *file)
284 {
285 get_file(file);
286 vma->vm_prfile = file;
287 #ifndef CONFIG_MMU
288 get_file(file);
289 vma->vm_region->vm_prfile = file;
290 #endif
291 }
292
293 #endif /* __KERNEL__ */
294 #endif /* __AUFS_FILE_H__ */