]> git.proxmox.com Git - mirror_ubuntu-artful-kernel.git/blob - fs/aufs/branch.h
e9591cfa2568651c8b97e1a785ff3e5f1b4f94af
[mirror_ubuntu-artful-kernel.git] / fs / aufs / branch.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 * branch filesystems and xino for them
20 */
21
22 #ifndef __AUFS_BRANCH_H__
23 #define __AUFS_BRANCH_H__
24
25 #ifdef __KERNEL__
26
27 #include <linux/mount.h>
28 #include "dynop.h"
29 #include "rwsem.h"
30 #include "super.h"
31
32 /* ---------------------------------------------------------------------- */
33
34 /* a xino file */
35 struct au_xino_file {
36 struct file *xi_file;
37 struct {
38 spinlock_t spin;
39 ino_t *array;
40 int total;
41 /* reserved for future use */
42 /* unsigned long *bitmap; */
43 wait_queue_head_t wqh;
44 } xi_nondir;
45
46 /* todo: make xino files an array to support huge inode number */
47
48 #ifdef CONFIG_DEBUG_FS
49 struct dentry *xi_dbgaufs;
50 #endif
51 };
52
53 /* File-based Hierarchical Storage Management */
54 struct au_br_fhsm {
55 #ifdef CONFIG_AUFS_FHSM
56 struct mutex bf_lock;
57 unsigned long bf_jiffy;
58 struct aufs_stfs bf_stfs;
59 int bf_readable;
60 #endif
61 };
62
63 /* members for writable branch only */
64 enum {AuBrWh_BASE, AuBrWh_PLINK, AuBrWh_ORPH, AuBrWh_Last};
65 struct au_wbr {
66 struct au_rwsem wbr_wh_rwsem;
67 struct dentry *wbr_wh[AuBrWh_Last];
68 atomic_t wbr_wh_running;
69 #define wbr_whbase wbr_wh[AuBrWh_BASE] /* whiteout base */
70 #define wbr_plink wbr_wh[AuBrWh_PLINK] /* pseudo-link dir */
71 #define wbr_orph wbr_wh[AuBrWh_ORPH] /* dir for orphans */
72
73 /* mfs mode */
74 unsigned long long wbr_bytes;
75 };
76
77 /* ext2 has 3 types of operations at least, ext3 has 4 */
78 #define AuBrDynOp (AuDyLast * 4)
79
80 #ifdef CONFIG_AUFS_HFSNOTIFY
81 /* support for asynchronous destruction */
82 struct au_br_hfsnotify {
83 struct fsnotify_group *hfsn_group;
84 };
85 #endif
86
87 /* sysfs entries */
88 struct au_brsysfs {
89 char name[16];
90 struct attribute attr;
91 };
92
93 enum {
94 AuBrSysfs_BR,
95 AuBrSysfs_BRID,
96 AuBrSysfs_Last
97 };
98
99 /* protected by superblock rwsem */
100 struct au_branch {
101 struct au_xino_file br_xino;
102
103 aufs_bindex_t br_id;
104
105 int br_perm;
106 struct path br_path;
107 spinlock_t br_dykey_lock;
108 struct au_dykey *br_dykey[AuBrDynOp];
109 struct percpu_counter br_count;
110
111 struct au_wbr *br_wbr;
112 struct au_br_fhsm *br_fhsm;
113
114 /* xino truncation */
115 atomic_t br_xino_running;
116
117 #ifdef CONFIG_AUFS_HFSNOTIFY
118 struct au_br_hfsnotify *br_hfsn;
119 #endif
120
121 #ifdef CONFIG_SYSFS
122 /* entries under sysfs per mount-point */
123 struct au_brsysfs br_sysfs[AuBrSysfs_Last];
124 #endif
125 };
126
127 /* ---------------------------------------------------------------------- */
128
129 static inline struct vfsmount *au_br_mnt(struct au_branch *br)
130 {
131 return br->br_path.mnt;
132 }
133
134 static inline struct dentry *au_br_dentry(struct au_branch *br)
135 {
136 return br->br_path.dentry;
137 }
138
139 static inline struct super_block *au_br_sb(struct au_branch *br)
140 {
141 return au_br_mnt(br)->mnt_sb;
142 }
143
144 static inline void au_br_get(struct au_branch *br)
145 {
146 percpu_counter_inc(&br->br_count);
147 }
148
149 static inline void au_br_put(struct au_branch *br)
150 {
151 percpu_counter_dec(&br->br_count);
152 }
153
154 static inline s64 au_br_count(struct au_branch *br)
155 {
156 return percpu_counter_sum(&br->br_count);
157 }
158
159 static inline void au_br_count_init(struct au_branch *br)
160 {
161 percpu_counter_init(&br->br_count, 0, GFP_NOFS);
162 }
163
164 static inline void au_br_count_fin(struct au_branch *br)
165 {
166 percpu_counter_destroy(&br->br_count);
167 }
168
169 static inline int au_br_rdonly(struct au_branch *br)
170 {
171 return ((au_br_sb(br)->s_flags & MS_RDONLY)
172 || !au_br_writable(br->br_perm))
173 ? -EROFS : 0;
174 }
175
176 static inline int au_br_hnotifyable(int brperm __maybe_unused)
177 {
178 #ifdef CONFIG_AUFS_HNOTIFY
179 return !(brperm & AuBrPerm_RR);
180 #else
181 return 0;
182 #endif
183 }
184
185 static inline int au_br_test_oflag(int oflag, struct au_branch *br)
186 {
187 int err, exec_flag;
188
189 err = 0;
190 exec_flag = oflag & __FMODE_EXEC;
191 if (unlikely(exec_flag && path_noexec(&br->br_path)))
192 err = -EACCES;
193
194 return err;
195 }
196
197 /* ---------------------------------------------------------------------- */
198
199 /* branch.c */
200 struct au_sbinfo;
201 void au_br_free(struct au_sbinfo *sinfo);
202 int au_br_index(struct super_block *sb, aufs_bindex_t br_id);
203 struct au_opt_add;
204 int au_br_add(struct super_block *sb, struct au_opt_add *add, int remount);
205 struct au_opt_del;
206 int au_br_del(struct super_block *sb, struct au_opt_del *del, int remount);
207 long au_ibusy_ioctl(struct file *file, unsigned long arg);
208 #ifdef CONFIG_COMPAT
209 long au_ibusy_compat_ioctl(struct file *file, unsigned long arg);
210 #endif
211 struct au_opt_mod;
212 int au_br_mod(struct super_block *sb, struct au_opt_mod *mod, int remount,
213 int *do_refresh);
214 struct aufs_stfs;
215 int au_br_stfs(struct au_branch *br, struct aufs_stfs *stfs);
216
217 /* xino.c */
218 static const loff_t au_loff_max = LLONG_MAX;
219
220 int au_xib_trunc(struct super_block *sb);
221 ssize_t xino_fread(vfs_readf_t func, struct file *file, void *buf, size_t size,
222 loff_t *pos);
223 ssize_t xino_fwrite(vfs_writef_t func, struct file *file, void *buf,
224 size_t size, loff_t *pos);
225 struct file *au_xino_create2(struct file *base_file, struct file *copy_src);
226 struct file *au_xino_create(struct super_block *sb, char *fname, int silent);
227 ino_t au_xino_new_ino(struct super_block *sb);
228 void au_xino_delete_inode(struct inode *inode, const int unlinked);
229 int au_xino_write(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino,
230 ino_t ino);
231 int au_xino_read(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino,
232 ino_t *ino);
233 int au_xino_br(struct super_block *sb, struct au_branch *br, ino_t hino,
234 struct file *base_file, int do_test);
235 int au_xino_trunc(struct super_block *sb, aufs_bindex_t bindex);
236
237 struct au_opt_xino;
238 int au_xino_set(struct super_block *sb, struct au_opt_xino *xino, int remount);
239 void au_xino_clr(struct super_block *sb);
240 struct file *au_xino_def(struct super_block *sb);
241 int au_xino_path(struct seq_file *seq, struct file *file);
242
243 void au_xinondir_leave(struct super_block *sb, aufs_bindex_t bindex,
244 ino_t h_ino, int idx);
245 int au_xinondir_enter(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino,
246 int *idx);
247
248 /* ---------------------------------------------------------------------- */
249
250 /* Superblock to branch */
251 static inline
252 aufs_bindex_t au_sbr_id(struct super_block *sb, aufs_bindex_t bindex)
253 {
254 return au_sbr(sb, bindex)->br_id;
255 }
256
257 static inline
258 struct vfsmount *au_sbr_mnt(struct super_block *sb, aufs_bindex_t bindex)
259 {
260 return au_br_mnt(au_sbr(sb, bindex));
261 }
262
263 static inline
264 struct super_block *au_sbr_sb(struct super_block *sb, aufs_bindex_t bindex)
265 {
266 return au_br_sb(au_sbr(sb, bindex));
267 }
268
269 static inline void au_sbr_get(struct super_block *sb, aufs_bindex_t bindex)
270 {
271 au_br_get(au_sbr(sb, bindex));
272 }
273
274 static inline void au_sbr_put(struct super_block *sb, aufs_bindex_t bindex)
275 {
276 au_br_put(au_sbr(sb, bindex));
277 }
278
279 static inline int au_sbr_perm(struct super_block *sb, aufs_bindex_t bindex)
280 {
281 return au_sbr(sb, bindex)->br_perm;
282 }
283
284 static inline int au_sbr_whable(struct super_block *sb, aufs_bindex_t bindex)
285 {
286 return au_br_whable(au_sbr_perm(sb, bindex));
287 }
288
289 /* ---------------------------------------------------------------------- */
290
291 /*
292 * wbr_wh_read_lock, wbr_wh_write_lock
293 * wbr_wh_read_unlock, wbr_wh_write_unlock, wbr_wh_downgrade_lock
294 */
295 AuSimpleRwsemFuncs(wbr_wh, struct au_wbr *wbr, &wbr->wbr_wh_rwsem);
296
297 #define WbrWhMustNoWaiters(wbr) AuRwMustNoWaiters(&wbr->wbr_wh_rwsem)
298 #define WbrWhMustAnyLock(wbr) AuRwMustAnyLock(&wbr->wbr_wh_rwsem)
299 #define WbrWhMustWriteLock(wbr) AuRwMustWriteLock(&wbr->wbr_wh_rwsem)
300
301 /* ---------------------------------------------------------------------- */
302
303 #ifdef CONFIG_AUFS_FHSM
304 static inline void au_br_fhsm_init(struct au_br_fhsm *brfhsm)
305 {
306 mutex_init(&brfhsm->bf_lock);
307 brfhsm->bf_jiffy = 0;
308 brfhsm->bf_readable = 0;
309 }
310
311 static inline void au_br_fhsm_fin(struct au_br_fhsm *brfhsm)
312 {
313 mutex_destroy(&brfhsm->bf_lock);
314 }
315 #else
316 AuStubVoid(au_br_fhsm_init, struct au_br_fhsm *brfhsm)
317 AuStubVoid(au_br_fhsm_fin, struct au_br_fhsm *brfhsm)
318 #endif
319
320 #endif /* __KERNEL__ */
321 #endif /* __AUFS_BRANCH_H__ */