Merge branch 'stable-3.2' into pandora-3.2
[pandora-kernel.git] / fs / aufs / file.h
1 /*
2  * Copyright (C) 2005-2012 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, write to the Free Software
16  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
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/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 } ____cacheline_aligned_in_smp;
66
67 /* ---------------------------------------------------------------------- */
68
69 /* file.c */
70 extern const struct address_space_operations aufs_aop;
71 unsigned int au_file_roflags(unsigned int flags);
72 struct file *au_h_open(struct dentry *dentry, aufs_bindex_t bindex, int flags,
73                        struct file *file);
74 int au_do_open(struct file *file, int (*open)(struct file *file, int flags),
75                struct au_fidir *fidir);
76 int au_reopen_nondir(struct file *file);
77 struct au_pin;
78 int au_ready_to_write(struct file *file, loff_t len, struct au_pin *pin);
79 int au_reval_and_lock_fdi(struct file *file, int (*reopen)(struct file *file),
80                           int wlock);
81 int au_do_flush(struct file *file, fl_owner_t id,
82                 int (*flush)(struct file *file, fl_owner_t id));
83
84 /* poll.c */
85 #ifdef CONFIG_AUFS_POLL
86 unsigned int aufs_poll(struct file *file, poll_table *wait);
87 #endif
88
89 #ifdef CONFIG_AUFS_BR_HFSPLUS
90 /* hfsplus.c */
91 struct file *au_h_open_pre(struct dentry *dentry, aufs_bindex_t bindex);
92 void au_h_open_post(struct dentry *dentry, aufs_bindex_t bindex,
93                     struct file *h_file);
94 #else
95 static inline
96 struct file *au_h_open_pre(struct dentry *dentry, aufs_bindex_t bindex)
97 {
98         return NULL;
99 }
100
101 AuStubVoid(au_h_open_post, struct dentry *dentry, aufs_bindex_t bindex,
102            struct file *h_file);
103 #endif
104
105 /* f_op.c */
106 extern const struct file_operations aufs_file_fop;
107 int au_do_open_nondir(struct file *file, int flags);
108 int aufs_release_nondir(struct inode *inode __maybe_unused, struct file *file);
109
110 #ifdef CONFIG_AUFS_SP_IATTR
111 /* f_op_sp.c */
112 int au_special_file(umode_t mode);
113 void au_init_special_fop(struct inode *inode, umode_t mode, dev_t rdev);
114 #else
115 AuStubInt0(au_special_file, umode_t mode)
116 static inline void au_init_special_fop(struct inode *inode, umode_t mode,
117                                        dev_t rdev)
118 {
119         init_special_inode(inode, mode, rdev);
120 }
121 #endif
122
123 /* finfo.c */
124 void au_hfput(struct au_hfile *hf, struct file *file);
125 void au_set_h_fptr(struct file *file, aufs_bindex_t bindex,
126                    struct file *h_file);
127
128 void au_update_figen(struct file *file);
129 struct au_fidir *au_fidir_alloc(struct super_block *sb);
130 int au_fidir_realloc(struct au_finfo *finfo, int nbr);
131
132 void au_fi_init_once(void *_fi);
133 void au_finfo_fin(struct file *file);
134 int au_finfo_init(struct file *file, struct au_fidir *fidir);
135
136 /* ioctl.c */
137 long aufs_ioctl_nondir(struct file *file, unsigned int cmd, unsigned long arg);
138 #ifdef CONFIG_COMPAT
139 long aufs_compat_ioctl_dir(struct file *file, unsigned int cmd,
140                            unsigned long arg);
141 #endif
142
143 /* ---------------------------------------------------------------------- */
144
145 static inline struct au_finfo *au_fi(struct file *file)
146 {
147         return file->private_data;
148 }
149
150 /* ---------------------------------------------------------------------- */
151
152 /*
153  * fi_read_lock, fi_write_lock,
154  * fi_read_unlock, fi_write_unlock, fi_downgrade_lock
155  */
156 AuSimpleRwsemFuncs(fi, struct file *f, &au_fi(f)->fi_rwsem);
157
158 #define FiMustNoWaiters(f)      AuRwMustNoWaiters(&au_fi(f)->fi_rwsem)
159 #define FiMustAnyLock(f)        AuRwMustAnyLock(&au_fi(f)->fi_rwsem)
160 #define FiMustWriteLock(f)      AuRwMustWriteLock(&au_fi(f)->fi_rwsem)
161
162 /* ---------------------------------------------------------------------- */
163
164 /* todo: hard/soft set? */
165 static inline aufs_bindex_t au_fbstart(struct file *file)
166 {
167         FiMustAnyLock(file);
168         return au_fi(file)->fi_btop;
169 }
170
171 static inline aufs_bindex_t au_fbend_dir(struct file *file)
172 {
173         FiMustAnyLock(file);
174         AuDebugOn(!au_fi(file)->fi_hdir);
175         return au_fi(file)->fi_hdir->fd_bbot;
176 }
177
178 static inline struct au_vdir *au_fvdir_cache(struct file *file)
179 {
180         FiMustAnyLock(file);
181         AuDebugOn(!au_fi(file)->fi_hdir);
182         return au_fi(file)->fi_hdir->fd_vdir_cache;
183 }
184
185 static inline void au_set_fbstart(struct file *file, aufs_bindex_t bindex)
186 {
187         FiMustWriteLock(file);
188         au_fi(file)->fi_btop = bindex;
189 }
190
191 static inline void au_set_fbend_dir(struct file *file, aufs_bindex_t bindex)
192 {
193         FiMustWriteLock(file);
194         AuDebugOn(!au_fi(file)->fi_hdir);
195         au_fi(file)->fi_hdir->fd_bbot = bindex;
196 }
197
198 static inline void au_set_fvdir_cache(struct file *file,
199                                       struct au_vdir *vdir_cache)
200 {
201         FiMustWriteLock(file);
202         AuDebugOn(!au_fi(file)->fi_hdir);
203         au_fi(file)->fi_hdir->fd_vdir_cache = vdir_cache;
204 }
205
206 static inline struct file *au_hf_top(struct file *file)
207 {
208         FiMustAnyLock(file);
209         AuDebugOn(au_fi(file)->fi_hdir);
210         return au_fi(file)->fi_htop.hf_file;
211 }
212
213 static inline struct file *au_hf_dir(struct file *file, aufs_bindex_t bindex)
214 {
215         FiMustAnyLock(file);
216         AuDebugOn(!au_fi(file)->fi_hdir);
217         return au_fi(file)->fi_hdir->fd_hfile[0 + bindex].hf_file;
218 }
219
220 /* todo: memory barrier? */
221 static inline unsigned int au_figen(struct file *f)
222 {
223         return atomic_read(&au_fi(f)->fi_generation);
224 }
225
226 static inline void au_set_mmapped(struct file *f)
227 {
228         if (atomic_inc_return(&au_fi(f)->fi_mmapped))
229                 return;
230         pr_warning("fi_mmapped wrapped around\n");
231         while (!atomic_inc_return(&au_fi(f)->fi_mmapped))
232                 ;
233 }
234
235 static inline void au_unset_mmapped(struct file *f)
236 {
237         atomic_dec(&au_fi(f)->fi_mmapped);
238 }
239
240 static inline int au_test_mmapped(struct file *f)
241 {
242         return atomic_read(&au_fi(f)->fi_mmapped);
243 }
244
245 /* customize vma->vm_file */
246
247 static inline void au_do_vm_file_reset(struct vm_area_struct *vma,
248                                        struct file *file)
249 {
250         struct file *f;
251
252         f = vma->vm_file;
253         get_file(file);
254         vma->vm_file = file;
255         fput(f);
256 }
257
258 #ifdef CONFIG_MMU
259 #define AuDbgVmRegion(file, vma) do {} while (0)
260
261 static inline void au_vm_file_reset(struct vm_area_struct *vma,
262                                     struct file *file)
263 {
264         au_do_vm_file_reset(vma, file);
265 }
266 #else
267 #define AuDbgVmRegion(file, vma) \
268         AuDebugOn((vma)->vm_region && (vma)->vm_region->vm_file != (file))
269
270 static inline void au_vm_file_reset(struct vm_area_struct *vma,
271                                     struct file *file)
272 {
273         struct file *f;
274
275         au_do_vm_file_reset(vma, file);
276         f = vma->vm_region->vm_file;
277         get_file(file);
278         vma->vm_region->vm_file = file;
279         fput(f);
280 }
281 #endif /* CONFIG_MMU */
282
283 /* handle vma->vm_prfile */
284 static inline void au_vm_prfile_set(struct vm_area_struct *vma,
285                                     struct file *file)
286 {
287 #ifdef CONFIG_AUFS_PROC_MAP
288         get_file(file);
289         vma->vm_prfile = file;
290 #ifndef CONFIG_MMU
291         get_file(file);
292         vma->vm_region->vm_prfile = file;
293 #endif
294 #endif
295 }
296
297 #endif /* __KERNEL__ */
298 #endif /* __AUFS_FILE_H__ */