]> git.pld-linux.org Git - packages/kernel.git/blame - kernel-aufs2.patch
- package modules.devname, modules.softdep, modules.builtin.bin
[packages/kernel.git] / kernel-aufs2.patch
CommitLineData
027c5e7a 1aufs2.1 kbuild patch for linux-2.6.
7f207e10
AM
2
3diff --git a/fs/Kconfig b/fs/Kconfig
2cbb1c4b 4index 19891aa..b660b64 100644
7f207e10
AM
5--- a/fs/Kconfig
6+++ b/fs/Kconfig
2cbb1c4b 7@@ -208,6 +208,7 @@ source "fs/pstore/Kconfig"
7f207e10
AM
8 source "fs/sysv/Kconfig"
9 source "fs/ufs/Kconfig"
10 source "fs/exofs/Kconfig"
11+source "fs/aufs/Kconfig"
12
13 endif # MISC_FILESYSTEMS
14
15diff --git a/fs/Makefile b/fs/Makefile
2cbb1c4b 16index fb68c2b..c031a85 100644
7f207e10
AM
17--- a/fs/Makefile
18+++ b/fs/Makefile
2cbb1c4b 19@@ -124,3 +124,4 @@ obj-$(CONFIG_GFS2_FS) += gfs2/
7f207e10
AM
20 obj-$(CONFIG_EXOFS_FS) += exofs/
21 obj-$(CONFIG_CEPH_FS) += ceph/
bf0370f2 22 obj-$(CONFIG_PSTORE) += pstore/
2cbb1c4b 23+obj-$(CONFIG_AUFS_FS) += aufs/
7f207e10 24diff --git a/include/linux/Kbuild b/include/linux/Kbuild
2cbb1c4b 25index 01f6362..8b3b9f1 100644
7f207e10
AM
26--- a/include/linux/Kbuild
27+++ b/include/linux/Kbuild
2cbb1c4b 28@@ -65,6 +65,7 @@ header-y += atmppp.h
7f207e10
AM
29 header-y += atmsap.h
30 header-y += atmsvc.h
31 header-y += audit.h
32+header-y += aufs_type.h
33 header-y += auto_fs.h
34 header-y += auto_fs4.h
35 header-y += auxvec.h
027c5e7a 36aufs2.1 base patch for linux-2.6.
7f207e10
AM
37
38diff --git a/fs/namei.c b/fs/namei.c
2cbb1c4b 39index 0223c41..cc5dc02 100644
7f207e10
AM
40--- a/fs/namei.c
41+++ b/fs/namei.c
2cbb1c4b 42@@ -1690,7 +1690,7 @@ static struct dentry *__lookup_hash(struct qstr *name,
7f207e10
AM
43 * needs parent already locked. Doesn't follow mounts.
44 * SMP-safe.
45 */
46-static struct dentry *lookup_hash(struct nameidata *nd)
47+struct dentry *lookup_hash(struct nameidata *nd)
48 {
7f207e10
AM
49 return __lookup_hash(&nd->last, nd->path.dentry, nd);
50 }
7f207e10 51diff --git a/fs/splice.c b/fs/splice.c
2cbb1c4b 52index aa866d3..19afec6 100644
7f207e10
AM
53--- a/fs/splice.c
54+++ b/fs/splice.c
2cbb1c4b 55@@ -1085,8 +1085,8 @@ EXPORT_SYMBOL(generic_splice_sendpage);
7f207e10
AM
56 /*
57 * Attempt to initiate a splice from pipe to file.
58 */
59-static long do_splice_from(struct pipe_inode_info *pipe, struct file *out,
60- loff_t *ppos, size_t len, unsigned int flags)
61+long do_splice_from(struct pipe_inode_info *pipe, struct file *out,
62+ loff_t *ppos, size_t len, unsigned int flags)
63 {
64 ssize_t (*splice_write)(struct pipe_inode_info *, struct file *,
65 loff_t *, size_t, unsigned int);
2cbb1c4b 66@@ -1113,9 +1113,9 @@ static long do_splice_from(struct pipe_inode_info *pipe, struct file *out,
7f207e10
AM
67 /*
68 * Attempt to initiate a splice from a file to a pipe.
69 */
70-static long do_splice_to(struct file *in, loff_t *ppos,
71- struct pipe_inode_info *pipe, size_t len,
72- unsigned int flags)
73+long do_splice_to(struct file *in, loff_t *ppos,
74+ struct pipe_inode_info *pipe, size_t len,
75+ unsigned int flags)
76 {
77 ssize_t (*splice_read)(struct file *, loff_t *,
78 struct pipe_inode_info *, size_t, unsigned int);
79diff --git a/include/linux/namei.h b/include/linux/namei.h
2cbb1c4b 80index eba45ea..21ed6c9 100644
7f207e10
AM
81--- a/include/linux/namei.h
82+++ b/include/linux/namei.h
2cbb1c4b 83@@ -82,6 +82,7 @@ extern int vfs_path_lookup(struct dentry *, struct vfsmount *,
7f207e10
AM
84 extern struct file *lookup_instantiate_filp(struct nameidata *nd, struct dentry *dentry,
85 int (*open)(struct inode *, struct file *));
86
87+extern struct dentry *lookup_hash(struct nameidata *nd);
7f207e10
AM
88 extern struct dentry *lookup_one_len(const char *, struct dentry *, int);
89
027c5e7a 90 extern int follow_down_one(struct path *);
7f207e10
AM
91diff --git a/include/linux/splice.h b/include/linux/splice.h
92index 997c3b4..be9a153 100644
93--- a/include/linux/splice.h
94+++ b/include/linux/splice.h
95@@ -89,4 +89,10 @@ extern int splice_grow_spd(struct pipe_inode_info *, struct splice_pipe_desc *);
96 extern void splice_shrink_spd(struct pipe_inode_info *,
97 struct splice_pipe_desc *);
98
99+extern long do_splice_from(struct pipe_inode_info *pipe, struct file *out,
100+ loff_t *ppos, size_t len, unsigned int flags);
101+extern long do_splice_to(struct file *in, loff_t *ppos,
102+ struct pipe_inode_info *pipe, size_t len,
103+ unsigned int flags);
1facf9fc 104+
7f207e10 105 #endif
027c5e7a 106aufs2.1 standalone patch for linux-2.6.
7f207e10
AM
107
108diff --git a/fs/file_table.c b/fs/file_table.c
2cbb1c4b 109index 01e4c1e..0e800e2 100644
7f207e10
AM
110--- a/fs/file_table.c
111+++ b/fs/file_table.c
2cbb1c4b 112@@ -443,6 +443,8 @@ void file_sb_list_del(struct file *file)
7f207e10
AM
113 }
114 }
115
116+EXPORT_SYMBOL(file_sb_list_del);
1facf9fc 117+
7f207e10
AM
118 #ifdef CONFIG_SMP
119
120 /*
121diff --git a/fs/inode.c b/fs/inode.c
2cbb1c4b 122index 43566d1..4291eae 100644
7f207e10
AM
123--- a/fs/inode.c
124+++ b/fs/inode.c
2cbb1c4b
JR
125@@ -69,6 +69,7 @@ static DEFINE_SPINLOCK(inode_lru_lock);
126
127 __cacheline_aligned_in_smp DEFINE_SPINLOCK(inode_sb_list_lock);
128 __cacheline_aligned_in_smp DEFINE_SPINLOCK(inode_wb_list_lock);
129+EXPORT_SYMBOL(inode_sb_list_lock);
7f207e10
AM
130
131 /*
2cbb1c4b 132 * iprune_sem provides exclusion between the icache shrinking and the
7f207e10 133diff --git a/fs/namei.c b/fs/namei.c
2cbb1c4b 134index cc5dc02..121d5ba 100644
7f207e10
AM
135--- a/fs/namei.c
136+++ b/fs/namei.c
2cbb1c4b 137@@ -365,6 +365,7 @@ int deny_write_access(struct file * file)
7f207e10
AM
138
139 return 0;
140 }
141+EXPORT_SYMBOL(deny_write_access);
142
143 /**
144 * path_get - get a reference to a path
2cbb1c4b 145@@ -1694,6 +1695,7 @@ struct dentry *lookup_hash(struct nameidata *nd)
027c5e7a 146 {
7f207e10
AM
147 return __lookup_hash(&nd->last, nd->path.dentry, nd);
148 }
149+EXPORT_SYMBOL(lookup_hash);
150
7f207e10
AM
151 /**
152 * lookup_one_len - filesystem helper to lookup single pathname component
153diff --git a/fs/namespace.c b/fs/namespace.c
2cbb1c4b 154index fe59bd1..7d3843f 100644
7f207e10
AM
155--- a/fs/namespace.c
156+++ b/fs/namespace.c
2cbb1c4b 157@@ -1508,6 +1508,7 @@ int iterate_mounts(int (*f)(struct vfsmount *, void *), void *arg,
7f207e10
AM
158 }
159 return 0;
160 }
161+EXPORT_SYMBOL(iterate_mounts);
162
163 static void cleanup_group_ids(struct vfsmount *mnt, struct vfsmount *end)
164 {
165diff --git a/fs/notify/group.c b/fs/notify/group.c
166index d309f38..f0e9568 100644
167--- a/fs/notify/group.c
168+++ b/fs/notify/group.c
169@@ -22,6 +22,7 @@
170 #include <linux/srcu.h>
171 #include <linux/rculist.h>
172 #include <linux/wait.h>
173+#include <linux/module.h>
174
175 #include <linux/fsnotify_backend.h>
176 #include "fsnotify.h"
177@@ -70,6 +71,7 @@ void fsnotify_put_group(struct fsnotify_group *group)
178 if (atomic_dec_and_test(&group->refcnt))
179 fsnotify_destroy_group(group);
180 }
181+EXPORT_SYMBOL(fsnotify_put_group);
182
183 /*
184 * Create a new fsnotify_group and hold a reference for the group returned.
185@@ -102,3 +104,4 @@ struct fsnotify_group *fsnotify_alloc_group(const struct fsnotify_ops *ops)
186
187 return group;
188 }
189+EXPORT_SYMBOL(fsnotify_alloc_group);
190diff --git a/fs/notify/mark.c b/fs/notify/mark.c
2cbb1c4b 191index 252ab1f..2199b9b 100644
7f207e10
AM
192--- a/fs/notify/mark.c
193+++ b/fs/notify/mark.c
2cbb1c4b 194@@ -112,6 +112,7 @@ void fsnotify_put_mark(struct fsnotify_mark *mark)
7f207e10
AM
195 if (atomic_dec_and_test(&mark->refcnt))
196 mark->free_mark(mark);
197 }
198+EXPORT_SYMBOL(fsnotify_put_mark);
199
200 /*
201 * Any time a mark is getting freed we end up here.
2cbb1c4b 202@@ -189,6 +190,7 @@ void fsnotify_destroy_mark(struct fsnotify_mark *mark)
7f207e10
AM
203 if (unlikely(atomic_dec_and_test(&group->num_marks)))
204 fsnotify_final_destroy_group(group);
205 }
206+EXPORT_SYMBOL(fsnotify_destroy_mark);
207
208 void fsnotify_set_mark_mask_locked(struct fsnotify_mark *mark, __u32 mask)
209 {
2cbb1c4b 210@@ -276,6 +278,7 @@ err:
7f207e10
AM
211
212 return ret;
213 }
214+EXPORT_SYMBOL(fsnotify_add_mark);
215
216 /*
217 * clear any marks in a group in which mark->flags & flags is true
2cbb1c4b 218@@ -331,6 +334,7 @@ void fsnotify_init_mark(struct fsnotify_mark *mark,
7f207e10
AM
219 atomic_set(&mark->refcnt, 1);
220 mark->free_mark = free_mark;
221 }
222+EXPORT_SYMBOL(fsnotify_init_mark);
223
224 static int fsnotify_mark_destroy(void *ignored)
225 {
226diff --git a/fs/open.c b/fs/open.c
2cbb1c4b 227index b52cf01..c1b341c 100644
7f207e10
AM
228--- a/fs/open.c
229+++ b/fs/open.c
230@@ -60,6 +60,7 @@ int do_truncate(struct dentry *dentry, loff_t length, unsigned int time_attrs,
231 mutex_unlock(&dentry->d_inode->i_mutex);
232 return ret;
233 }
234+EXPORT_SYMBOL(do_truncate);
235
236 static long do_sys_truncate(const char __user *pathname, loff_t length)
237 {
238diff --git a/fs/splice.c b/fs/splice.c
2cbb1c4b 239index 19afec6..11f07f8 100644
7f207e10
AM
240--- a/fs/splice.c
241+++ b/fs/splice.c
2cbb1c4b 242@@ -1109,6 +1109,7 @@ long do_splice_from(struct pipe_inode_info *pipe, struct file *out,
7f207e10
AM
243
244 return splice_write(pipe, out, ppos, len, flags);
245 }
246+EXPORT_SYMBOL(do_splice_from);
247
248 /*
249 * Attempt to initiate a splice from a file to a pipe.
2cbb1c4b 250@@ -1135,6 +1136,7 @@ long do_splice_to(struct file *in, loff_t *ppos,
7f207e10
AM
251
252 return splice_read(in, ppos, pipe, len, flags);
253 }
254+EXPORT_SYMBOL(do_splice_to);
255
256 /**
257 * splice_direct_to_actor - splices data directly between two non-pipes
258diff --git a/security/commoncap.c b/security/commoncap.c
2cbb1c4b 259index a93b3b7..024282c 100644
7f207e10
AM
260--- a/security/commoncap.c
261+++ b/security/commoncap.c
2cbb1c4b 262@@ -971,3 +971,4 @@ int cap_file_mmap(struct file *file, unsigned long reqprot,
7f207e10
AM
263 return ret;
264 }
2cbb1c4b 265
7f207e10
AM
266+EXPORT_SYMBOL(cap_file_mmap);
267diff --git a/security/device_cgroup.c b/security/device_cgroup.c
2cbb1c4b 268index 1be6826..215278c 100644
7f207e10
AM
269--- a/security/device_cgroup.c
270+++ b/security/device_cgroup.c
2cbb1c4b 271@@ -508,6 +508,7 @@ found:
7f207e10
AM
272
273 return -EPERM;
274 }
2cbb1c4b 275+EXPORT_SYMBOL(__devcgroup_inode_permission);
7f207e10
AM
276
277 int devcgroup_inode_mknod(int mode, dev_t dev)
278 {
279diff --git a/security/security.c b/security/security.c
2cbb1c4b 280index 4ba6d4c..9f64bb8 100644
7f207e10
AM
281--- a/security/security.c
282+++ b/security/security.c
2cbb1c4b 283@@ -373,6 +373,7 @@ int security_path_rmdir(struct path *dir, struct dentry *dentry)
7f207e10
AM
284 return 0;
285 return security_ops->path_rmdir(dir, dentry);
286 }
287+EXPORT_SYMBOL(security_path_rmdir);
288
289 int security_path_unlink(struct path *dir, struct dentry *dentry)
290 {
2cbb1c4b 291@@ -389,6 +390,7 @@ int security_path_symlink(struct path *dir, struct dentry *dentry,
7f207e10
AM
292 return 0;
293 return security_ops->path_symlink(dir, dentry, old_name);
294 }
295+EXPORT_SYMBOL(security_path_symlink);
296
297 int security_path_link(struct dentry *old_dentry, struct path *new_dir,
298 struct dentry *new_dentry)
2cbb1c4b 299@@ -397,6 +399,7 @@ int security_path_link(struct dentry *old_dentry, struct path *new_dir,
7f207e10
AM
300 return 0;
301 return security_ops->path_link(old_dentry, new_dir, new_dentry);
302 }
303+EXPORT_SYMBOL(security_path_link);
304
305 int security_path_rename(struct path *old_dir, struct dentry *old_dentry,
306 struct path *new_dir, struct dentry *new_dentry)
2cbb1c4b 307@@ -415,6 +418,7 @@ int security_path_truncate(struct path *path)
7f207e10
AM
308 return 0;
309 return security_ops->path_truncate(path);
310 }
311+EXPORT_SYMBOL(security_path_truncate);
312
313 int security_path_chmod(struct dentry *dentry, struct vfsmount *mnt,
314 mode_t mode)
2cbb1c4b 315@@ -423,6 +427,7 @@ int security_path_chmod(struct dentry *dentry, struct vfsmount *mnt,
7f207e10
AM
316 return 0;
317 return security_ops->path_chmod(dentry, mnt, mode);
318 }
319+EXPORT_SYMBOL(security_path_chmod);
320
321 int security_path_chown(struct path *path, uid_t uid, gid_t gid)
322 {
2cbb1c4b 323@@ -430,6 +435,7 @@ int security_path_chown(struct path *path, uid_t uid, gid_t gid)
7f207e10
AM
324 return 0;
325 return security_ops->path_chown(path, uid, gid);
326 }
327+EXPORT_SYMBOL(security_path_chown);
328
329 int security_path_chroot(struct path *path)
330 {
2cbb1c4b 331@@ -506,6 +512,7 @@ int security_inode_readlink(struct dentry *dentry)
7f207e10
AM
332 return 0;
333 return security_ops->inode_readlink(dentry);
334 }
335+EXPORT_SYMBOL(security_inode_readlink);
336
337 int security_inode_follow_link(struct dentry *dentry, struct nameidata *nd)
338 {
2cbb1c4b 339@@ -520,6 +527,7 @@ int security_inode_permission(struct inode *inode, int mask)
7f207e10 340 return 0;
2cbb1c4b 341 return security_ops->inode_permission(inode, mask, 0);
7f207e10
AM
342 }
343+EXPORT_SYMBOL(security_inode_permission);
344
027c5e7a 345 int security_inode_exec_permission(struct inode *inode, unsigned int flags)
7f207e10 346 {
2cbb1c4b 347@@ -626,6 +634,7 @@ int security_file_permission(struct file *file, int mask)
7f207e10
AM
348
349 return fsnotify_perm(file, mask);
350 }
351+EXPORT_SYMBOL(security_file_permission);
352
353 int security_file_alloc(struct file *file)
354 {
2cbb1c4b 355@@ -653,6 +662,7 @@ int security_file_mmap(struct file *file, unsigned long reqprot,
7f207e10
AM
356 return ret;
357 return ima_file_mmap(file, prot);
358 }
359+EXPORT_SYMBOL(security_file_mmap);
360
361 int security_file_mprotect(struct vm_area_struct *vma, unsigned long reqprot,
362 unsigned long prot)
363diff -urN /usr/share/empty/Documentation/ABI/testing/debugfs-aufs linux/Documentation/ABI/testing/debugfs-aufs
364--- /usr/share/empty/Documentation/ABI/testing/debugfs-aufs 1970-01-01 01:00:00.000000000 +0100
2cbb1c4b 365+++ linux/Documentation/ABI/testing/debugfs-aufs 2011-07-11 11:34:24.068331673 +0200
7f207e10
AM
366@@ -0,0 +1,37 @@
367+What: /debug/aufs/si_<id>/
368+Date: March 2009
369+Contact: J. R. Okajima <hooanon05@yahoo.co.jp>
370+Description:
371+ Under /debug/aufs, a directory named si_<id> is created
372+ per aufs mount, where <id> is a unique id generated
373+ internally.
1facf9fc 374+
7f207e10
AM
375+What: /debug/aufs/si_<id>/xib
376+Date: March 2009
377+Contact: J. R. Okajima <hooanon05@yahoo.co.jp>
378+Description:
379+ It shows the consumed blocks by xib (External Inode Number
380+ Bitmap), its block size and file size.
381+ When the aufs mount option 'noxino' is specified, it
382+ will be empty. About XINO files, see the aufs manual.
383+
384+What: /debug/aufs/si_<id>/xino0, xino1 ... xinoN
385+Date: March 2009
386+Contact: J. R. Okajima <hooanon05@yahoo.co.jp>
387+Description:
388+ It shows the consumed blocks by xino (External Inode Number
389+ Translation Table), its link count, block size and file
390+ size.
391+ When the aufs mount option 'noxino' is specified, it
392+ will be empty. About XINO files, see the aufs manual.
393+
394+What: /debug/aufs/si_<id>/xigen
395+Date: March 2009
396+Contact: J. R. Okajima <hooanon05@yahoo.co.jp>
397+Description:
398+ It shows the consumed blocks by xigen (External Inode
399+ Generation Table), its block size and file size.
400+ If CONFIG_AUFS_EXPORT is disabled, this entry will not
401+ be created.
402+ When the aufs mount option 'noxino' is specified, it
403+ will be empty. About XINO files, see the aufs manual.
404diff -urN /usr/share/empty/Documentation/ABI/testing/sysfs-aufs linux/Documentation/ABI/testing/sysfs-aufs
405--- /usr/share/empty/Documentation/ABI/testing/sysfs-aufs 1970-01-01 01:00:00.000000000 +0100
2cbb1c4b 406+++ linux/Documentation/ABI/testing/sysfs-aufs 2011-07-11 11:34:24.068331673 +0200
7f207e10
AM
407@@ -0,0 +1,24 @@
408+What: /sys/fs/aufs/si_<id>/
409+Date: March 2009
410+Contact: J. R. Okajima <hooanon05@yahoo.co.jp>
411+Description:
412+ Under /sys/fs/aufs, a directory named si_<id> is created
413+ per aufs mount, where <id> is a unique id generated
414+ internally.
415+
416+What: /sys/fs/aufs/si_<id>/br0, br1 ... brN
417+Date: March 2009
418+Contact: J. R. Okajima <hooanon05@yahoo.co.jp>
419+Description:
420+ It shows the abolute path of a member directory (which
421+ is called branch) in aufs, and its permission.
422+
423+What: /sys/fs/aufs/si_<id>/xi_path
424+Date: March 2009
425+Contact: J. R. Okajima <hooanon05@yahoo.co.jp>
426+Description:
427+ It shows the abolute path of XINO (External Inode Number
428+ Bitmap, Translation Table and Generation Table) file
429+ even if it is the default path.
430+ When the aufs mount option 'noxino' is specified, it
431+ will be empty. About XINO files, see the aufs manual.
432diff -urN /usr/share/empty/fs/aufs/aufs.h linux/fs/aufs/aufs.h
433--- /usr/share/empty/fs/aufs/aufs.h 1970-01-01 01:00:00.000000000 +0100
2cbb1c4b
JR
434+++ linux/fs/aufs/aufs.h 2011-07-11 11:34:24.070331673 +0200
435@@ -0,0 +1,60 @@
7f207e10 436+/*
027c5e7a 437+ * Copyright (C) 2005-2011 Junjiro R. Okajima
7f207e10
AM
438+ *
439+ * This program, aufs is free software; you can redistribute it and/or modify
440+ * it under the terms of the GNU General Public License as published by
441+ * the Free Software Foundation; either version 2 of the License, or
442+ * (at your option) any later version.
443+ *
444+ * This program is distributed in the hope that it will be useful,
445+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
446+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
447+ * GNU General Public License for more details.
448+ *
449+ * You should have received a copy of the GNU General Public License
450+ * along with this program; if not, write to the Free Software
451+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
452+ */
453+
454+/*
455+ * all header files
456+ */
457+
458+#ifndef __AUFS_H__
459+#define __AUFS_H__
460+
461+#ifdef __KERNEL__
462+
463+#define AuStub(type, name, body, ...) \
464+ static inline type name(__VA_ARGS__) { body; }
465+
466+#define AuStubVoid(name, ...) \
467+ AuStub(void, name, , __VA_ARGS__)
468+#define AuStubInt0(name, ...) \
469+ AuStub(int, name, return 0, __VA_ARGS__)
470+
471+#include "debug.h"
472+
473+#include "branch.h"
474+#include "cpup.h"
475+#include "dcsub.h"
476+#include "dbgaufs.h"
477+#include "dentry.h"
478+#include "dir.h"
479+#include "dynop.h"
480+#include "file.h"
481+#include "fstype.h"
482+#include "inode.h"
483+#include "loop.h"
484+#include "module.h"
7f207e10
AM
485+#include "opts.h"
486+#include "rwsem.h"
487+#include "spl.h"
488+#include "super.h"
489+#include "sysaufs.h"
490+#include "vfsub.h"
491+#include "whout.h"
492+#include "wkq.h"
493+
494+#endif /* __KERNEL__ */
495+#endif /* __AUFS_H__ */
496diff -urN /usr/share/empty/fs/aufs/branch.c linux/fs/aufs/branch.c
497--- /usr/share/empty/fs/aufs/branch.c 1970-01-01 01:00:00.000000000 +0100
2cbb1c4b 498+++ linux/fs/aufs/branch.c 2011-07-11 11:34:24.070331673 +0200
027c5e7a 499@@ -0,0 +1,1160 @@
7f207e10 500+/*
027c5e7a 501+ * Copyright (C) 2005-2011 Junjiro R. Okajima
7f207e10
AM
502+ *
503+ * This program, aufs is free software; you can redistribute it and/or modify
504+ * it under the terms of the GNU General Public License as published by
505+ * the Free Software Foundation; either version 2 of the License, or
506+ * (at your option) any later version.
507+ *
508+ * This program is distributed in the hope that it will be useful,
509+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
510+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
511+ * GNU General Public License for more details.
512+ *
513+ * You should have received a copy of the GNU General Public License
514+ * along with this program; if not, write to the Free Software
515+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
516+ */
517+
518+/*
519+ * branch management
520+ */
521+
027c5e7a 522+#include <linux/compat.h>
7f207e10
AM
523+#include <linux/file.h>
524+#include <linux/statfs.h>
525+#include "aufs.h"
526+
527+/*
528+ * free a single branch
1facf9fc 529+ */
530+static void au_br_do_free(struct au_branch *br)
531+{
532+ int i;
533+ struct au_wbr *wbr;
4a4d8108 534+ struct au_dykey **key;
1facf9fc 535+
027c5e7a
AM
536+ au_hnotify_fin_br(br);
537+
1facf9fc 538+ if (br->br_xino.xi_file)
539+ fput(br->br_xino.xi_file);
540+ mutex_destroy(&br->br_xino.xi_nondir_mtx);
541+
542+ AuDebugOn(atomic_read(&br->br_count));
543+
544+ wbr = br->br_wbr;
545+ if (wbr) {
546+ for (i = 0; i < AuBrWh_Last; i++)
547+ dput(wbr->wbr_wh[i]);
548+ AuDebugOn(atomic_read(&wbr->wbr_wh_running));
dece6358 549+ AuRwDestroy(&wbr->wbr_wh_rwsem);
1facf9fc 550+ }
551+
4a4d8108
AM
552+ key = br->br_dykey;
553+ for (i = 0; i < AuBrDynOp; i++, key++)
554+ if (*key)
555+ au_dy_put(*key);
556+ else
557+ break;
558+
1facf9fc 559+ mntput(br->br_mnt);
1facf9fc 560+ kfree(wbr);
561+ kfree(br);
562+}
563+
564+/*
565+ * frees all branches
566+ */
567+void au_br_free(struct au_sbinfo *sbinfo)
568+{
569+ aufs_bindex_t bmax;
570+ struct au_branch **br;
571+
dece6358
AM
572+ AuRwMustWriteLock(&sbinfo->si_rwsem);
573+
1facf9fc 574+ bmax = sbinfo->si_bend + 1;
575+ br = sbinfo->si_branch;
576+ while (bmax--)
577+ au_br_do_free(*br++);
578+}
579+
580+/*
581+ * find the index of a branch which is specified by @br_id.
582+ */
583+int au_br_index(struct super_block *sb, aufs_bindex_t br_id)
584+{
585+ aufs_bindex_t bindex, bend;
586+
587+ bend = au_sbend(sb);
588+ for (bindex = 0; bindex <= bend; bindex++)
589+ if (au_sbr_id(sb, bindex) == br_id)
590+ return bindex;
591+ return -1;
592+}
593+
594+/* ---------------------------------------------------------------------- */
595+
596+/*
597+ * add a branch
598+ */
599+
b752ccd1
AM
600+static int test_overlap(struct super_block *sb, struct dentry *h_adding,
601+ struct dentry *h_root)
1facf9fc 602+{
b752ccd1
AM
603+ if (unlikely(h_adding == h_root
604+ || au_test_loopback_overlap(sb, h_adding)))
1facf9fc 605+ return 1;
b752ccd1
AM
606+ if (h_adding->d_sb != h_root->d_sb)
607+ return 0;
608+ return au_test_subdir(h_adding, h_root)
609+ || au_test_subdir(h_root, h_adding);
1facf9fc 610+}
611+
612+/*
613+ * returns a newly allocated branch. @new_nbranch is a number of branches
614+ * after adding a branch.
615+ */
616+static struct au_branch *au_br_alloc(struct super_block *sb, int new_nbranch,
617+ int perm)
618+{
619+ struct au_branch *add_branch;
620+ struct dentry *root;
4a4d8108 621+ int err;
1facf9fc 622+
4a4d8108 623+ err = -ENOMEM;
1facf9fc 624+ root = sb->s_root;
625+ add_branch = kmalloc(sizeof(*add_branch), GFP_NOFS);
626+ if (unlikely(!add_branch))
627+ goto out;
628+
027c5e7a
AM
629+ err = au_hnotify_init_br(add_branch, perm);
630+ if (unlikely(err))
631+ goto out_br;
632+
1facf9fc 633+ add_branch->br_wbr = NULL;
634+ if (au_br_writable(perm)) {
635+ /* may be freed separately at changing the branch permission */
636+ add_branch->br_wbr = kmalloc(sizeof(*add_branch->br_wbr),
637+ GFP_NOFS);
638+ if (unlikely(!add_branch->br_wbr))
027c5e7a 639+ goto out_hnotify;
1facf9fc 640+ }
641+
4a4d8108
AM
642+ err = au_sbr_realloc(au_sbi(sb), new_nbranch);
643+ if (!err)
644+ err = au_di_realloc(au_di(root), new_nbranch);
645+ if (!err)
646+ err = au_ii_realloc(au_ii(root->d_inode), new_nbranch);
647+ if (!err)
648+ return add_branch; /* success */
1facf9fc 649+
1facf9fc 650+ kfree(add_branch->br_wbr);
4a4d8108 651+
027c5e7a
AM
652+out_hnotify:
653+ au_hnotify_fin_br(add_branch);
4f0767ce 654+out_br:
1facf9fc 655+ kfree(add_branch);
4f0767ce 656+out:
4a4d8108 657+ return ERR_PTR(err);
1facf9fc 658+}
659+
660+/*
661+ * test if the branch permission is legal or not.
662+ */
663+static int test_br(struct inode *inode, int brperm, char *path)
664+{
665+ int err;
666+
4a4d8108
AM
667+ err = (au_br_writable(brperm) && IS_RDONLY(inode));
668+ if (!err)
669+ goto out;
1facf9fc 670+
4a4d8108
AM
671+ err = -EINVAL;
672+ pr_err("write permission for readonly mount or inode, %s\n", path);
673+
4f0767ce 674+out:
1facf9fc 675+ return err;
676+}
677+
678+/*
679+ * returns:
680+ * 0: success, the caller will add it
681+ * plus: success, it is already unified, the caller should ignore it
682+ * minus: error
683+ */
684+static int test_add(struct super_block *sb, struct au_opt_add *add, int remount)
685+{
686+ int err;
687+ aufs_bindex_t bend, bindex;
688+ struct dentry *root;
689+ struct inode *inode, *h_inode;
690+
691+ root = sb->s_root;
692+ bend = au_sbend(sb);
693+ if (unlikely(bend >= 0
694+ && au_find_dbindex(root, add->path.dentry) >= 0)) {
695+ err = 1;
696+ if (!remount) {
697+ err = -EINVAL;
4a4d8108 698+ pr_err("%s duplicated\n", add->pathname);
1facf9fc 699+ }
700+ goto out;
701+ }
702+
703+ err = -ENOSPC; /* -E2BIG; */
704+ if (unlikely(AUFS_BRANCH_MAX <= add->bindex
705+ || AUFS_BRANCH_MAX - 1 <= bend)) {
4a4d8108 706+ pr_err("number of branches exceeded %s\n", add->pathname);
1facf9fc 707+ goto out;
708+ }
709+
710+ err = -EDOM;
711+ if (unlikely(add->bindex < 0 || bend + 1 < add->bindex)) {
4a4d8108 712+ pr_err("bad index %d\n", add->bindex);
1facf9fc 713+ goto out;
714+ }
715+
716+ inode = add->path.dentry->d_inode;
717+ err = -ENOENT;
718+ if (unlikely(!inode->i_nlink)) {
4a4d8108 719+ pr_err("no existence %s\n", add->pathname);
1facf9fc 720+ goto out;
721+ }
722+
723+ err = -EINVAL;
724+ if (unlikely(inode->i_sb == sb)) {
4a4d8108 725+ pr_err("%s must be outside\n", add->pathname);
1facf9fc 726+ goto out;
727+ }
728+
729+ if (unlikely(au_test_fs_unsuppoted(inode->i_sb))) {
4a4d8108
AM
730+ pr_err("unsupported filesystem, %s (%s)\n",
731+ add->pathname, au_sbtype(inode->i_sb));
1facf9fc 732+ goto out;
733+ }
734+
735+ err = test_br(add->path.dentry->d_inode, add->perm, add->pathname);
736+ if (unlikely(err))
737+ goto out;
738+
739+ if (bend < 0)
740+ return 0; /* success */
741+
742+ err = -EINVAL;
743+ for (bindex = 0; bindex <= bend; bindex++)
744+ if (unlikely(test_overlap(sb, add->path.dentry,
745+ au_h_dptr(root, bindex)))) {
4a4d8108 746+ pr_err("%s is overlapped\n", add->pathname);
1facf9fc 747+ goto out;
748+ }
749+
750+ err = 0;
751+ if (au_opt_test(au_mntflags(sb), WARN_PERM)) {
752+ h_inode = au_h_dptr(root, 0)->d_inode;
753+ if ((h_inode->i_mode & S_IALLUGO) != (inode->i_mode & S_IALLUGO)
754+ || h_inode->i_uid != inode->i_uid
755+ || h_inode->i_gid != inode->i_gid)
4a4d8108
AM
756+ pr_warning("uid/gid/perm %s %u/%u/0%o, %u/%u/0%o\n",
757+ add->pathname,
758+ inode->i_uid, inode->i_gid,
759+ (inode->i_mode & S_IALLUGO),
760+ h_inode->i_uid, h_inode->i_gid,
761+ (h_inode->i_mode & S_IALLUGO));
1facf9fc 762+ }
763+
4f0767ce 764+out:
1facf9fc 765+ return err;
766+}
767+
768+/*
769+ * initialize or clean the whiteouts for an adding branch
770+ */
771+static int au_br_init_wh(struct super_block *sb, struct au_branch *br,
772+ int new_perm, struct dentry *h_root)
773+{
774+ int err, old_perm;
775+ aufs_bindex_t bindex;
776+ struct mutex *h_mtx;
777+ struct au_wbr *wbr;
778+ struct au_hinode *hdir;
779+
780+ wbr = br->br_wbr;
781+ old_perm = br->br_perm;
782+ br->br_perm = new_perm;
783+ hdir = NULL;
784+ h_mtx = NULL;
785+ bindex = au_br_index(sb, br->br_id);
786+ if (0 <= bindex) {
787+ hdir = au_hi(sb->s_root->d_inode, bindex);
4a4d8108 788+ au_hn_imtx_lock_nested(hdir, AuLsc_I_PARENT);
1facf9fc 789+ } else {
790+ h_mtx = &h_root->d_inode->i_mutex;
791+ mutex_lock_nested(h_mtx, AuLsc_I_PARENT);
792+ }
793+ if (!wbr)
794+ err = au_wh_init(h_root, br, sb);
795+ else {
796+ wbr_wh_write_lock(wbr);
797+ err = au_wh_init(h_root, br, sb);
798+ wbr_wh_write_unlock(wbr);
799+ }
800+ if (hdir)
4a4d8108 801+ au_hn_imtx_unlock(hdir);
1facf9fc 802+ else
803+ mutex_unlock(h_mtx);
804+ br->br_perm = old_perm;
805+
806+ if (!err && wbr && !au_br_writable(new_perm)) {
807+ kfree(wbr);
808+ br->br_wbr = NULL;
809+ }
810+
811+ return err;
812+}
813+
814+static int au_wbr_init(struct au_branch *br, struct super_block *sb,
815+ int perm, struct path *path)
816+{
817+ int err;
4a4d8108 818+ struct kstatfs kst;
1facf9fc 819+ struct au_wbr *wbr;
4a4d8108 820+ struct dentry *h_dentry;
1facf9fc 821+
822+ wbr = br->br_wbr;
dece6358 823+ au_rw_init(&wbr->wbr_wh_rwsem);
1facf9fc 824+ memset(wbr->wbr_wh, 0, sizeof(wbr->wbr_wh));
825+ atomic_set(&wbr->wbr_wh_running, 0);
826+ wbr->wbr_bytes = 0;
827+
4a4d8108
AM
828+ /*
829+ * a limit for rmdir/rename a dir
830+ * cf. AUFS_MAX_NAMELEN in include/linux/aufs_type.h
831+ */
7f207e10 832+ err = vfs_statfs(path, &kst);
4a4d8108
AM
833+ if (unlikely(err))
834+ goto out;
835+ err = -EINVAL;
7f207e10 836+ h_dentry = path->dentry;
4a4d8108
AM
837+ if (kst.f_namelen >= NAME_MAX)
838+ err = au_br_init_wh(sb, br, perm, h_dentry);
839+ else
840+ pr_err("%.*s(%s), unsupported namelen %ld\n",
841+ AuDLNPair(h_dentry), au_sbtype(h_dentry->d_sb),
842+ kst.f_namelen);
1facf9fc 843+
4f0767ce 844+out:
1facf9fc 845+ return err;
846+}
847+
848+/* intialize a new branch */
849+static int au_br_init(struct au_branch *br, struct super_block *sb,
850+ struct au_opt_add *add)
851+{
852+ int err;
853+
854+ err = 0;
855+ memset(&br->br_xino, 0, sizeof(br->br_xino));
856+ mutex_init(&br->br_xino.xi_nondir_mtx);
857+ br->br_perm = add->perm;
858+ br->br_mnt = add->path.mnt; /* set first, mntget() later */
4a4d8108
AM
859+ spin_lock_init(&br->br_dykey_lock);
860+ memset(br->br_dykey, 0, sizeof(br->br_dykey));
1facf9fc 861+ atomic_set(&br->br_count, 0);
862+ br->br_xino_upper = AUFS_XINO_TRUNC_INIT;
863+ atomic_set(&br->br_xino_running, 0);
864+ br->br_id = au_new_br_id(sb);
7f207e10 865+ AuDebugOn(br->br_id < 0);
1facf9fc 866+
867+ if (au_br_writable(add->perm)) {
868+ err = au_wbr_init(br, sb, add->perm, &add->path);
869+ if (unlikely(err))
b752ccd1 870+ goto out_err;
1facf9fc 871+ }
872+
873+ if (au_opt_test(au_mntflags(sb), XINO)) {
874+ err = au_xino_br(sb, br, add->path.dentry->d_inode->i_ino,
875+ au_sbr(sb, 0)->br_xino.xi_file, /*do_test*/1);
876+ if (unlikely(err)) {
877+ AuDebugOn(br->br_xino.xi_file);
b752ccd1 878+ goto out_err;
1facf9fc 879+ }
880+ }
881+
882+ sysaufs_br_init(br);
883+ mntget(add->path.mnt);
b752ccd1 884+ goto out; /* success */
1facf9fc 885+
4f0767ce 886+out_err:
b752ccd1 887+ br->br_mnt = NULL;
4f0767ce 888+out:
1facf9fc 889+ return err;
890+}
891+
892+static void au_br_do_add_brp(struct au_sbinfo *sbinfo, aufs_bindex_t bindex,
893+ struct au_branch *br, aufs_bindex_t bend,
894+ aufs_bindex_t amount)
895+{
896+ struct au_branch **brp;
897+
dece6358
AM
898+ AuRwMustWriteLock(&sbinfo->si_rwsem);
899+
1facf9fc 900+ brp = sbinfo->si_branch + bindex;
901+ memmove(brp + 1, brp, sizeof(*brp) * amount);
902+ *brp = br;
903+ sbinfo->si_bend++;
904+ if (unlikely(bend < 0))
905+ sbinfo->si_bend = 0;
906+}
907+
908+static void au_br_do_add_hdp(struct au_dinfo *dinfo, aufs_bindex_t bindex,
909+ aufs_bindex_t bend, aufs_bindex_t amount)
910+{
911+ struct au_hdentry *hdp;
912+
1308ab2a 913+ AuRwMustWriteLock(&dinfo->di_rwsem);
914+
1facf9fc 915+ hdp = dinfo->di_hdentry + bindex;
916+ memmove(hdp + 1, hdp, sizeof(*hdp) * amount);
917+ au_h_dentry_init(hdp);
918+ dinfo->di_bend++;
919+ if (unlikely(bend < 0))
920+ dinfo->di_bstart = 0;
921+}
922+
923+static void au_br_do_add_hip(struct au_iinfo *iinfo, aufs_bindex_t bindex,
924+ aufs_bindex_t bend, aufs_bindex_t amount)
925+{
926+ struct au_hinode *hip;
927+
1308ab2a 928+ AuRwMustWriteLock(&iinfo->ii_rwsem);
929+
1facf9fc 930+ hip = iinfo->ii_hinode + bindex;
931+ memmove(hip + 1, hip, sizeof(*hip) * amount);
932+ hip->hi_inode = NULL;
4a4d8108 933+ au_hn_init(hip);
1facf9fc 934+ iinfo->ii_bend++;
935+ if (unlikely(bend < 0))
936+ iinfo->ii_bstart = 0;
937+}
938+
939+static void au_br_do_add(struct super_block *sb, struct dentry *h_dentry,
940+ struct au_branch *br, aufs_bindex_t bindex)
941+{
942+ struct dentry *root;
943+ struct inode *root_inode;
944+ aufs_bindex_t bend, amount;
945+
946+ root = sb->s_root;
947+ root_inode = root->d_inode;
1facf9fc 948+ bend = au_sbend(sb);
949+ amount = bend + 1 - bindex;
950+ au_br_do_add_brp(au_sbi(sb), bindex, br, bend, amount);
951+ au_br_do_add_hdp(au_di(root), bindex, bend, amount);
952+ au_br_do_add_hip(au_ii(root_inode), bindex, bend, amount);
953+ au_set_h_dptr(root, bindex, dget(h_dentry));
954+ au_set_h_iptr(root_inode, bindex, au_igrab(h_dentry->d_inode),
955+ /*flags*/0);
956+}
957+
958+int au_br_add(struct super_block *sb, struct au_opt_add *add, int remount)
959+{
960+ int err;
1facf9fc 961+ aufs_bindex_t bend, add_bindex;
962+ struct dentry *root, *h_dentry;
963+ struct inode *root_inode;
964+ struct au_branch *add_branch;
965+
966+ root = sb->s_root;
967+ root_inode = root->d_inode;
968+ IMustLock(root_inode);
969+ err = test_add(sb, add, remount);
970+ if (unlikely(err < 0))
971+ goto out;
972+ if (err) {
973+ err = 0;
974+ goto out; /* success */
975+ }
976+
977+ bend = au_sbend(sb);
978+ add_branch = au_br_alloc(sb, bend + 2, add->perm);
979+ err = PTR_ERR(add_branch);
980+ if (IS_ERR(add_branch))
981+ goto out;
982+
983+ err = au_br_init(add_branch, sb, add);
984+ if (unlikely(err)) {
985+ au_br_do_free(add_branch);
986+ goto out;
987+ }
988+
989+ add_bindex = add->bindex;
990+ h_dentry = add->path.dentry;
991+ if (!remount)
992+ au_br_do_add(sb, h_dentry, add_branch, add_bindex);
993+ else {
994+ sysaufs_brs_del(sb, add_bindex);
995+ au_br_do_add(sb, h_dentry, add_branch, add_bindex);
996+ sysaufs_brs_add(sb, add_bindex);
997+ }
998+
1308ab2a 999+ if (!add_bindex) {
1facf9fc 1000+ au_cpup_attr_all(root_inode, /*force*/1);
1308ab2a 1001+ sb->s_maxbytes = h_dentry->d_sb->s_maxbytes;
1002+ } else
1facf9fc 1003+ au_add_nlink(root_inode, h_dentry->d_inode);
1facf9fc 1004+
1005+ /*
4a4d8108 1006+ * this test/set prevents aufs from handling unnecesary notify events
027c5e7a 1007+ * of xino files, in case of re-adding a writable branch which was
1facf9fc 1008+ * once detached from aufs.
1009+ */
1010+ if (au_xino_brid(sb) < 0
1011+ && au_br_writable(add_branch->br_perm)
1012+ && !au_test_fs_bad_xino(h_dentry->d_sb)
1013+ && add_branch->br_xino.xi_file
1014+ && add_branch->br_xino.xi_file->f_dentry->d_parent == h_dentry)
1015+ au_xino_brid_set(sb, add_branch->br_id);
1016+
4f0767ce 1017+out:
1facf9fc 1018+ return err;
1019+}
1020+
1021+/* ---------------------------------------------------------------------- */
1022+
1023+/*
1024+ * delete a branch
1025+ */
1026+
1027+/* to show the line number, do not make it inlined function */
4a4d8108 1028+#define AuVerbose(do_info, fmt, ...) do { \
1facf9fc 1029+ if (do_info) \
4a4d8108 1030+ pr_info(fmt, ##__VA_ARGS__); \
1facf9fc 1031+} while (0)
1032+
027c5e7a
AM
1033+static int au_test_ibusy(struct inode *inode, aufs_bindex_t bstart,
1034+ aufs_bindex_t bend)
1035+{
1036+ return (inode && !S_ISDIR(inode->i_mode)) || bstart == bend;
1037+}
1038+
1039+static int au_test_dbusy(struct dentry *dentry, aufs_bindex_t bstart,
1040+ aufs_bindex_t bend)
1041+{
1042+ return au_test_ibusy(dentry->d_inode, bstart, bend);
1043+}
1044+
1facf9fc 1045+/*
1046+ * test if the branch is deletable or not.
1047+ */
1048+static int test_dentry_busy(struct dentry *root, aufs_bindex_t bindex,
b752ccd1 1049+ unsigned int sigen, const unsigned int verbose)
1facf9fc 1050+{
1051+ int err, i, j, ndentry;
1052+ aufs_bindex_t bstart, bend;
1facf9fc 1053+ struct au_dcsub_pages dpages;
1054+ struct au_dpage *dpage;
1055+ struct dentry *d;
1facf9fc 1056+
1057+ err = au_dpages_init(&dpages, GFP_NOFS);
1058+ if (unlikely(err))
1059+ goto out;
1060+ err = au_dcsub_pages(&dpages, root, NULL, NULL);
1061+ if (unlikely(err))
1062+ goto out_dpages;
1063+
1facf9fc 1064+ for (i = 0; !err && i < dpages.ndpage; i++) {
1065+ dpage = dpages.dpages + i;
1066+ ndentry = dpage->ndentry;
1067+ for (j = 0; !err && j < ndentry; j++) {
1068+ d = dpage->dentries[j];
027c5e7a
AM
1069+ AuDebugOn(!d->d_count);
1070+ if (!au_digen_test(d, sigen)) {
1facf9fc 1071+ di_read_lock_child(d, AuLock_IR);
027c5e7a
AM
1072+ if (unlikely(au_dbrange_test(d))) {
1073+ di_read_unlock(d, AuLock_IR);
1074+ continue;
1075+ }
1076+ } else {
1facf9fc 1077+ di_write_lock_child(d);
027c5e7a
AM
1078+ if (unlikely(au_dbrange_test(d))) {
1079+ di_write_unlock(d);
1080+ continue;
1081+ }
1facf9fc 1082+ err = au_reval_dpath(d, sigen);
1083+ if (!err)
1084+ di_downgrade_lock(d, AuLock_IR);
1085+ else {
1086+ di_write_unlock(d);
1087+ break;
1088+ }
1089+ }
1090+
027c5e7a 1091+ /* AuDbgDentry(d); */
1facf9fc 1092+ bstart = au_dbstart(d);
1093+ bend = au_dbend(d);
1094+ if (bstart <= bindex
1095+ && bindex <= bend
1096+ && au_h_dptr(d, bindex)
027c5e7a 1097+ && au_test_dbusy(d, bstart, bend)) {
1facf9fc 1098+ err = -EBUSY;
1099+ AuVerbose(verbose, "busy %.*s\n", AuDLNPair(d));
027c5e7a 1100+ AuDbgDentry(d);
1facf9fc 1101+ }
1102+ di_read_unlock(d, AuLock_IR);
1103+ }
1104+ }
1105+
4f0767ce 1106+out_dpages:
1facf9fc 1107+ au_dpages_free(&dpages);
4f0767ce 1108+out:
1facf9fc 1109+ return err;
1110+}
1111+
1112+static int test_inode_busy(struct super_block *sb, aufs_bindex_t bindex,
b752ccd1 1113+ unsigned int sigen, const unsigned int verbose)
1facf9fc 1114+{
1115+ int err;
7f207e10
AM
1116+ unsigned long long max, ull;
1117+ struct inode *i, **array;
1facf9fc 1118+ aufs_bindex_t bstart, bend;
1facf9fc 1119+
7f207e10
AM
1120+ array = au_iarray_alloc(sb, &max);
1121+ err = PTR_ERR(array);
1122+ if (IS_ERR(array))
1123+ goto out;
1124+
1facf9fc 1125+ err = 0;
7f207e10
AM
1126+ AuDbg("b%d\n", bindex);
1127+ for (ull = 0; !err && ull < max; ull++) {
1128+ i = array[ull];
1129+ if (i->i_ino == AUFS_ROOT_INO)
1facf9fc 1130+ continue;
1131+
7f207e10 1132+ /* AuDbgInode(i); */
1facf9fc 1133+ if (au_iigen(i) == sigen)
1134+ ii_read_lock_child(i);
1135+ else {
1136+ ii_write_lock_child(i);
027c5e7a
AM
1137+ err = au_refresh_hinode_self(i);
1138+ au_iigen_dec(i);
1facf9fc 1139+ if (!err)
1140+ ii_downgrade_lock(i);
1141+ else {
1142+ ii_write_unlock(i);
1143+ break;
1144+ }
1145+ }
1146+
1147+ bstart = au_ibstart(i);
1148+ bend = au_ibend(i);
1149+ if (bstart <= bindex
1150+ && bindex <= bend
1151+ && au_h_iptr(i, bindex)
027c5e7a 1152+ && au_test_ibusy(i, bstart, bend)) {
1facf9fc 1153+ err = -EBUSY;
1154+ AuVerbose(verbose, "busy i%lu\n", i->i_ino);
7f207e10 1155+ AuDbgInode(i);
1facf9fc 1156+ }
1157+ ii_read_unlock(i);
1158+ }
7f207e10 1159+ au_iarray_free(array, max);
1facf9fc 1160+
7f207e10 1161+out:
1facf9fc 1162+ return err;
1163+}
1164+
b752ccd1
AM
1165+static int test_children_busy(struct dentry *root, aufs_bindex_t bindex,
1166+ const unsigned int verbose)
1facf9fc 1167+{
1168+ int err;
1169+ unsigned int sigen;
1170+
1171+ sigen = au_sigen(root->d_sb);
1172+ DiMustNoWaiters(root);
1173+ IiMustNoWaiters(root->d_inode);
1174+ di_write_unlock(root);
b752ccd1 1175+ err = test_dentry_busy(root, bindex, sigen, verbose);
1facf9fc 1176+ if (!err)
b752ccd1 1177+ err = test_inode_busy(root->d_sb, bindex, sigen, verbose);
1facf9fc 1178+ di_write_lock_child(root); /* aufs_write_lock() calls ..._child() */
1179+
1180+ return err;
1181+}
1182+
1183+static void au_br_do_del_brp(struct au_sbinfo *sbinfo,
1184+ const aufs_bindex_t bindex,
1185+ const aufs_bindex_t bend)
1186+{
1187+ struct au_branch **brp, **p;
1188+
dece6358
AM
1189+ AuRwMustWriteLock(&sbinfo->si_rwsem);
1190+
1facf9fc 1191+ brp = sbinfo->si_branch + bindex;
1192+ if (bindex < bend)
1193+ memmove(brp, brp + 1, sizeof(*brp) * (bend - bindex));
1194+ sbinfo->si_branch[0 + bend] = NULL;
1195+ sbinfo->si_bend--;
1196+
1197+ p = krealloc(sbinfo->si_branch, sizeof(*p) * bend, GFP_NOFS);
1198+ if (p)
1199+ sbinfo->si_branch = p;
4a4d8108 1200+ /* harmless error */
1facf9fc 1201+}
1202+
1203+static void au_br_do_del_hdp(struct au_dinfo *dinfo, const aufs_bindex_t bindex,
1204+ const aufs_bindex_t bend)
1205+{
1206+ struct au_hdentry *hdp, *p;
1207+
1308ab2a 1208+ AuRwMustWriteLock(&dinfo->di_rwsem);
1209+
4a4d8108 1210+ hdp = dinfo->di_hdentry;
1facf9fc 1211+ if (bindex < bend)
4a4d8108
AM
1212+ memmove(hdp + bindex, hdp + bindex + 1,
1213+ sizeof(*hdp) * (bend - bindex));
1214+ hdp[0 + bend].hd_dentry = NULL;
1facf9fc 1215+ dinfo->di_bend--;
1216+
4a4d8108 1217+ p = krealloc(hdp, sizeof(*p) * bend, GFP_NOFS);
1facf9fc 1218+ if (p)
1219+ dinfo->di_hdentry = p;
4a4d8108 1220+ /* harmless error */
1facf9fc 1221+}
1222+
1223+static void au_br_do_del_hip(struct au_iinfo *iinfo, const aufs_bindex_t bindex,
1224+ const aufs_bindex_t bend)
1225+{
1226+ struct au_hinode *hip, *p;
1227+
1308ab2a 1228+ AuRwMustWriteLock(&iinfo->ii_rwsem);
1229+
1facf9fc 1230+ hip = iinfo->ii_hinode + bindex;
1231+ if (bindex < bend)
1232+ memmove(hip, hip + 1, sizeof(*hip) * (bend - bindex));
1233+ iinfo->ii_hinode[0 + bend].hi_inode = NULL;
4a4d8108 1234+ au_hn_init(iinfo->ii_hinode + bend);
1facf9fc 1235+ iinfo->ii_bend--;
1236+
1237+ p = krealloc(iinfo->ii_hinode, sizeof(*p) * bend, GFP_NOFS);
1238+ if (p)
1239+ iinfo->ii_hinode = p;
4a4d8108 1240+ /* harmless error */
1facf9fc 1241+}
1242+
1243+static void au_br_do_del(struct super_block *sb, aufs_bindex_t bindex,
1244+ struct au_branch *br)
1245+{
1246+ aufs_bindex_t bend;
1247+ struct au_sbinfo *sbinfo;
1248+ struct dentry *root;
1249+ struct inode *inode;
1250+
dece6358
AM
1251+ SiMustWriteLock(sb);
1252+
1facf9fc 1253+ root = sb->s_root;
1254+ inode = root->d_inode;
1facf9fc 1255+ sbinfo = au_sbi(sb);
1256+ bend = sbinfo->si_bend;
1257+
1258+ dput(au_h_dptr(root, bindex));
1259+ au_hiput(au_hi(inode, bindex));
1260+ au_br_do_free(br);
1261+
1262+ au_br_do_del_brp(sbinfo, bindex, bend);
1263+ au_br_do_del_hdp(au_di(root), bindex, bend);
1264+ au_br_do_del_hip(au_ii(inode), bindex, bend);
1265+}
1266+
1267+int au_br_del(struct super_block *sb, struct au_opt_del *del, int remount)
1268+{
1269+ int err, rerr, i;
1270+ unsigned int mnt_flags;
1271+ aufs_bindex_t bindex, bend, br_id;
1272+ unsigned char do_wh, verbose;
1273+ struct au_branch *br;
1274+ struct au_wbr *wbr;
1275+
1276+ err = 0;
1277+ bindex = au_find_dbindex(sb->s_root, del->h_path.dentry);
1278+ if (bindex < 0) {
1279+ if (remount)
1280+ goto out; /* success */
1281+ err = -ENOENT;
4a4d8108 1282+ pr_err("%s no such branch\n", del->pathname);
1facf9fc 1283+ goto out;
1284+ }
1285+ AuDbg("bindex b%d\n", bindex);
1286+
1287+ err = -EBUSY;
1288+ mnt_flags = au_mntflags(sb);
1289+ verbose = !!au_opt_test(mnt_flags, VERBOSE);
1290+ bend = au_sbend(sb);
1291+ if (unlikely(!bend)) {
1292+ AuVerbose(verbose, "no more branches left\n");
1293+ goto out;
1294+ }
1295+ br = au_sbr(sb, bindex);
1296+ i = atomic_read(&br->br_count);
1297+ if (unlikely(i)) {
1298+ AuVerbose(verbose, "%d file(s) opened\n", i);
e49829fe 1299+ goto out;
1facf9fc 1300+ }
1301+
1302+ wbr = br->br_wbr;
1303+ do_wh = wbr && (wbr->wbr_whbase || wbr->wbr_plink || wbr->wbr_orph);
1304+ if (do_wh) {
1308ab2a 1305+ /* instead of WbrWhMustWriteLock(wbr) */
1306+ SiMustWriteLock(sb);
1facf9fc 1307+ for (i = 0; i < AuBrWh_Last; i++) {
1308+ dput(wbr->wbr_wh[i]);
1309+ wbr->wbr_wh[i] = NULL;
1310+ }
1311+ }
1312+
b752ccd1 1313+ err = test_children_busy(sb->s_root, bindex, verbose);
1facf9fc 1314+ if (unlikely(err)) {
1315+ if (do_wh)
1316+ goto out_wh;
1317+ goto out;
1318+ }
1319+
1320+ err = 0;
1321+ br_id = br->br_id;
1322+ if (!remount)
1323+ au_br_do_del(sb, bindex, br);
1324+ else {
1325+ sysaufs_brs_del(sb, bindex);
1326+ au_br_do_del(sb, bindex, br);
1327+ sysaufs_brs_add(sb, bindex);
1328+ }
1329+
1308ab2a 1330+ if (!bindex) {
1facf9fc 1331+ au_cpup_attr_all(sb->s_root->d_inode, /*force*/1);
1308ab2a 1332+ sb->s_maxbytes = au_sbr_sb(sb, 0)->s_maxbytes;
1333+ } else
1facf9fc 1334+ au_sub_nlink(sb->s_root->d_inode, del->h_path.dentry->d_inode);
1335+ if (au_opt_test(mnt_flags, PLINK))
1336+ au_plink_half_refresh(sb, br_id);
1337+
b752ccd1 1338+ if (au_xino_brid(sb) == br_id)
1facf9fc 1339+ au_xino_brid_set(sb, -1);
1340+ goto out; /* success */
1341+
4f0767ce 1342+out_wh:
1facf9fc 1343+ /* revert */
1344+ rerr = au_br_init_wh(sb, br, br->br_perm, del->h_path.dentry);
1345+ if (rerr)
4a4d8108
AM
1346+ pr_warning("failed re-creating base whiteout, %s. (%d)\n",
1347+ del->pathname, rerr);
4f0767ce 1348+out:
1facf9fc 1349+ return err;
1350+}
1351+
1352+/* ---------------------------------------------------------------------- */
1353+
027c5e7a
AM
1354+static int au_ibusy(struct super_block *sb, struct aufs_ibusy __user *arg)
1355+{
1356+ int err;
1357+ aufs_bindex_t bstart, bend;
1358+ struct aufs_ibusy ibusy;
1359+ struct inode *inode, *h_inode;
1360+
1361+ err = -EPERM;
1362+ if (unlikely(!capable(CAP_SYS_ADMIN)))
1363+ goto out;
1364+
1365+ err = copy_from_user(&ibusy, arg, sizeof(ibusy));
1366+ if (!err)
1367+ err = !access_ok(VERIFY_WRITE, &arg->h_ino, sizeof(arg->h_ino));
1368+ if (unlikely(err)) {
1369+ err = -EFAULT;
1370+ AuTraceErr(err);
1371+ goto out;
1372+ }
1373+
1374+ err = -EINVAL;
1375+ si_read_lock(sb, AuLock_FLUSH);
1376+ if (unlikely(ibusy.bindex < 0 || ibusy.bindex > au_sbend(sb)))
1377+ goto out_unlock;
1378+
1379+ err = 0;
1380+ ibusy.h_ino = 0; /* invalid */
1381+ inode = ilookup(sb, ibusy.ino);
1382+ if (!inode
1383+ || inode->i_ino == AUFS_ROOT_INO
1384+ || is_bad_inode(inode))
1385+ goto out_unlock;
1386+
1387+ ii_read_lock_child(inode);
1388+ bstart = au_ibstart(inode);
1389+ bend = au_ibend(inode);
1390+ if (bstart <= ibusy.bindex && ibusy.bindex <= bend) {
1391+ h_inode = au_h_iptr(inode, ibusy.bindex);
1392+ if (h_inode && au_test_ibusy(inode, bstart, bend))
1393+ ibusy.h_ino = h_inode->i_ino;
1394+ }
1395+ ii_read_unlock(inode);
1396+ iput(inode);
1397+
1398+out_unlock:
1399+ si_read_unlock(sb);
1400+ if (!err) {
1401+ err = __put_user(ibusy.h_ino, &arg->h_ino);
1402+ if (unlikely(err)) {
1403+ err = -EFAULT;
1404+ AuTraceErr(err);
1405+ }
1406+ }
1407+out:
1408+ return err;
1409+}
1410+
1411+long au_ibusy_ioctl(struct file *file, unsigned long arg)
1412+{
1413+ return au_ibusy(file->f_dentry->d_sb, (void __user *)arg);
1414+}
1415+
1416+#ifdef CONFIG_COMPAT
1417+long au_ibusy_compat_ioctl(struct file *file, unsigned long arg)
1418+{
1419+ return au_ibusy(file->f_dentry->d_sb, compat_ptr(arg));
1420+}
1421+#endif
1422+
1423+/* ---------------------------------------------------------------------- */
1424+
1facf9fc 1425+/*
1426+ * change a branch permission
1427+ */
1428+
dece6358
AM
1429+static void au_warn_ima(void)
1430+{
1431+#ifdef CONFIG_IMA
1308ab2a 1432+ /* since it doesn't support mark_files_ro() */
027c5e7a 1433+ AuWarn1("RW -> RO makes IMA to produce wrong message\n");
dece6358
AM
1434+#endif
1435+}
1436+
1facf9fc 1437+static int do_need_sigen_inc(int a, int b)
1438+{
1439+ return au_br_whable(a) && !au_br_whable(b);
1440+}
1441+
1442+static int need_sigen_inc(int old, int new)
1443+{
1444+ return do_need_sigen_inc(old, new)
1445+ || do_need_sigen_inc(new, old);
1446+}
1447+
7f207e10
AM
1448+static unsigned long long au_farray_cb(void *a,
1449+ unsigned long long max __maybe_unused,
1450+ void *arg)
1451+{
1452+ unsigned long long n;
1453+ struct file **p, *f;
1454+ struct super_block *sb = arg;
1455+
1456+ n = 0;
1457+ p = a;
1458+ lg_global_lock(files_lglock);
1459+ do_file_list_for_each_entry(sb, f) {
1460+ if (au_fi(f)
027c5e7a 1461+ && file_count(f)
7f207e10
AM
1462+ && !special_file(f->f_dentry->d_inode->i_mode)) {
1463+ get_file(f);
1464+ *p++ = f;
1465+ n++;
1466+ AuDebugOn(n > max);
1467+ }
1468+ } while_file_list_for_each_entry;
1469+ lg_global_unlock(files_lglock);
1470+
1471+ return n;
1472+}
1473+
1474+static struct file **au_farray_alloc(struct super_block *sb,
1475+ unsigned long long *max)
1476+{
1477+ *max = atomic_long_read(&au_sbi(sb)->si_nfiles);
1478+ return au_array_alloc(max, au_farray_cb, sb);
1479+}
1480+
1481+static void au_farray_free(struct file **a, unsigned long long max)
1482+{
1483+ unsigned long long ull;
1484+
1485+ for (ull = 0; ull < max; ull++)
1486+ if (a[ull])
1487+ fput(a[ull]);
1488+ au_array_free(a);
1489+}
1490+
1facf9fc 1491+static int au_br_mod_files_ro(struct super_block *sb, aufs_bindex_t bindex)
1492+{
7f207e10 1493+ int err, do_warn;
027c5e7a 1494+ unsigned int mnt_flags;
7f207e10 1495+ unsigned long long ull, max;
e49829fe 1496+ aufs_bindex_t br_id;
027c5e7a 1497+ unsigned char verbose;
7f207e10 1498+ struct file *file, *hf, **array;
e49829fe
JR
1499+ struct inode *inode;
1500+ struct au_hfile *hfile;
1facf9fc 1501+
027c5e7a
AM
1502+ mnt_flags = au_mntflags(sb);
1503+ verbose = !!au_opt_test(mnt_flags, VERBOSE);
1504+
7f207e10
AM
1505+ array = au_farray_alloc(sb, &max);
1506+ err = PTR_ERR(array);
1507+ if (IS_ERR(array))
1facf9fc 1508+ goto out;
1509+
7f207e10 1510+ do_warn = 0;
e49829fe 1511+ br_id = au_sbr_id(sb, bindex);
7f207e10
AM
1512+ for (ull = 0; ull < max; ull++) {
1513+ file = array[ull];
1facf9fc 1514+
7f207e10 1515+ /* AuDbg("%.*s\n", AuDLNPair(file->f_dentry)); */
1facf9fc 1516+ fi_read_lock(file);
1517+ if (unlikely(au_test_mmapped(file))) {
1518+ err = -EBUSY;
027c5e7a
AM
1519+ AuVerbose(verbose, "mmapped %.*s\n",
1520+ AuDLNPair(file->f_dentry));
7f207e10 1521+ AuDbgFile(file);
1facf9fc 1522+ FiMustNoWaiters(file);
1523+ fi_read_unlock(file);
7f207e10 1524+ goto out_array;
1facf9fc 1525+ }
1526+
027c5e7a 1527+ inode = file->f_dentry->d_inode;
e49829fe
JR
1528+ hfile = &au_fi(file)->fi_htop;
1529+ hf = hfile->hf_file;
1530+ if (!S_ISREG(inode->i_mode)
1facf9fc 1531+ || !(file->f_mode & FMODE_WRITE)
e49829fe 1532+ || hfile->hf_br->br_id != br_id
7f207e10
AM
1533+ || !(hf->f_mode & FMODE_WRITE))
1534+ array[ull] = NULL;
1535+ else {
1536+ do_warn = 1;
1537+ get_file(file);
1facf9fc 1538+ }
1539+
1facf9fc 1540+ FiMustNoWaiters(file);
1541+ fi_read_unlock(file);
7f207e10
AM
1542+ fput(file);
1543+ }
1facf9fc 1544+
1545+ err = 0;
7f207e10 1546+ if (do_warn)
dece6358 1547+ au_warn_ima();
7f207e10
AM
1548+
1549+ for (ull = 0; ull < max; ull++) {
1550+ file = array[ull];
1551+ if (!file)
1552+ continue;
1553+
1facf9fc 1554+ /* todo: already flushed? */
1555+ /* cf. fs/super.c:mark_files_ro() */
7f207e10
AM
1556+ /* fi_read_lock(file); */
1557+ hfile = &au_fi(file)->fi_htop;
1558+ hf = hfile->hf_file;
1559+ /* fi_read_unlock(file); */
027c5e7a 1560+ spin_lock(&hf->f_lock);
1facf9fc 1561+ hf->f_mode &= ~FMODE_WRITE;
027c5e7a 1562+ spin_unlock(&hf->f_lock);
1facf9fc 1563+ if (!file_check_writeable(hf)) {
1564+ file_release_write(hf);
1565+ mnt_drop_write(hf->f_vfsmnt);
1566+ }
1567+ }
1568+
7f207e10
AM
1569+out_array:
1570+ au_farray_free(array, max);
4f0767ce 1571+out:
7f207e10 1572+ AuTraceErr(err);
1facf9fc 1573+ return err;
1574+}
1575+
1576+int au_br_mod(struct super_block *sb, struct au_opt_mod *mod, int remount,
7f207e10 1577+ int *do_refresh)
1facf9fc 1578+{
1579+ int err, rerr;
1580+ aufs_bindex_t bindex;
1308ab2a 1581+ struct path path;
1facf9fc 1582+ struct dentry *root;
1583+ struct au_branch *br;
1584+
1585+ root = sb->s_root;
1facf9fc 1586+ bindex = au_find_dbindex(root, mod->h_root);
1587+ if (bindex < 0) {
1588+ if (remount)
1589+ return 0; /* success */
1590+ err = -ENOENT;
4a4d8108 1591+ pr_err("%s no such branch\n", mod->path);
1facf9fc 1592+ goto out;
1593+ }
1594+ AuDbg("bindex b%d\n", bindex);
1595+
1596+ err = test_br(mod->h_root->d_inode, mod->perm, mod->path);
1597+ if (unlikely(err))
1598+ goto out;
1599+
1600+ br = au_sbr(sb, bindex);
1601+ if (br->br_perm == mod->perm)
1602+ return 0; /* success */
1603+
1604+ if (au_br_writable(br->br_perm)) {
1605+ /* remove whiteout base */
1606+ err = au_br_init_wh(sb, br, mod->perm, mod->h_root);
1607+ if (unlikely(err))
1608+ goto out;
1609+
1610+ if (!au_br_writable(mod->perm)) {
1611+ /* rw --> ro, file might be mmapped */
1612+ DiMustNoWaiters(root);
1613+ IiMustNoWaiters(root->d_inode);
1614+ di_write_unlock(root);
1615+ err = au_br_mod_files_ro(sb, bindex);
1616+ /* aufs_write_lock() calls ..._child() */
1617+ di_write_lock_child(root);
1618+
1619+ if (unlikely(err)) {
1620+ rerr = -ENOMEM;
1621+ br->br_wbr = kmalloc(sizeof(*br->br_wbr),
1622+ GFP_NOFS);
1308ab2a 1623+ if (br->br_wbr) {
1624+ path.mnt = br->br_mnt;
1625+ path.dentry = mod->h_root;
1626+ rerr = au_wbr_init(br, sb, br->br_perm,
1627+ &path);
1628+ }
1facf9fc 1629+ if (unlikely(rerr)) {
1630+ AuIOErr("nested error %d (%d)\n",
1631+ rerr, err);
1632+ br->br_perm = mod->perm;
1633+ }
1634+ }
1635+ }
1636+ } else if (au_br_writable(mod->perm)) {
1637+ /* ro --> rw */
1638+ err = -ENOMEM;
1639+ br->br_wbr = kmalloc(sizeof(*br->br_wbr), GFP_NOFS);
1640+ if (br->br_wbr) {
1308ab2a 1641+ path.mnt = br->br_mnt;
1642+ path.dentry = mod->h_root;
1facf9fc 1643+ err = au_wbr_init(br, sb, mod->perm, &path);
1644+ if (unlikely(err)) {
1645+ kfree(br->br_wbr);
1646+ br->br_wbr = NULL;
1647+ }
1648+ }
1649+ }
1650+
1651+ if (!err) {
7f207e10 1652+ *do_refresh |= need_sigen_inc(br->br_perm, mod->perm);
1facf9fc 1653+ br->br_perm = mod->perm;
1654+ }
1655+
4f0767ce 1656+out:
7f207e10 1657+ AuTraceErr(err);
1facf9fc 1658+ return err;
1659+}
7f207e10
AM
1660diff -urN /usr/share/empty/fs/aufs/branch.h linux/fs/aufs/branch.h
1661--- /usr/share/empty/fs/aufs/branch.h 1970-01-01 01:00:00.000000000 +0100
2cbb1c4b 1662+++ linux/fs/aufs/branch.h 2011-07-11 11:34:24.070331673 +0200
027c5e7a 1663@@ -0,0 +1,233 @@
1facf9fc 1664+/*
027c5e7a 1665+ * Copyright (C) 2005-2011 Junjiro R. Okajima
1facf9fc 1666+ *
1667+ * This program, aufs is free software; you can redistribute it and/or modify
1668+ * it under the terms of the GNU General Public License as published by
1669+ * the Free Software Foundation; either version 2 of the License, or
1670+ * (at your option) any later version.
dece6358
AM
1671+ *
1672+ * This program is distributed in the hope that it will be useful,
1673+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1674+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1675+ * GNU General Public License for more details.
1676+ *
1677+ * You should have received a copy of the GNU General Public License
1678+ * along with this program; if not, write to the Free Software
1679+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 1680+ */
1681+
1682+/*
1683+ * branch filesystems and xino for them
1684+ */
1685+
1686+#ifndef __AUFS_BRANCH_H__
1687+#define __AUFS_BRANCH_H__
1688+
1689+#ifdef __KERNEL__
1690+
1691+#include <linux/fs.h>
1692+#include <linux/mount.h>
1facf9fc 1693+#include <linux/aufs_type.h>
4a4d8108 1694+#include "dynop.h"
1facf9fc 1695+#include "rwsem.h"
1696+#include "super.h"
1697+
1698+/* ---------------------------------------------------------------------- */
1699+
1700+/* a xino file */
1701+struct au_xino_file {
1702+ struct file *xi_file;
1703+ struct mutex xi_nondir_mtx;
1704+
1705+ /* todo: make xino files an array to support huge inode number */
1706+
1707+#ifdef CONFIG_DEBUG_FS
1708+ struct dentry *xi_dbgaufs;
1709+#endif
1710+};
1711+
1712+/* members for writable branch only */
1713+enum {AuBrWh_BASE, AuBrWh_PLINK, AuBrWh_ORPH, AuBrWh_Last};
1714+struct au_wbr {
dece6358 1715+ struct au_rwsem wbr_wh_rwsem;
1facf9fc 1716+ struct dentry *wbr_wh[AuBrWh_Last];
4a4d8108 1717+ atomic_t wbr_wh_running;
1facf9fc 1718+#define wbr_whbase wbr_wh[AuBrWh_BASE] /* whiteout base */
1719+#define wbr_plink wbr_wh[AuBrWh_PLINK] /* pseudo-link dir */
1720+#define wbr_orph wbr_wh[AuBrWh_ORPH] /* dir for orphans */
1721+
1722+ /* mfs mode */
1723+ unsigned long long wbr_bytes;
1724+};
1725+
4a4d8108
AM
1726+/* ext2 has 3 types of operations at least, ext3 has 4 */
1727+#define AuBrDynOp (AuDyLast * 4)
1728+
1facf9fc 1729+/* protected by superblock rwsem */
1730+struct au_branch {
1731+ struct au_xino_file br_xino;
1732+
1733+ aufs_bindex_t br_id;
1734+
1735+ int br_perm;
1736+ struct vfsmount *br_mnt;
4a4d8108
AM
1737+ spinlock_t br_dykey_lock;
1738+ struct au_dykey *br_dykey[AuBrDynOp];
1facf9fc 1739+ atomic_t br_count;
1740+
1741+ struct au_wbr *br_wbr;
1742+
1743+ /* xino truncation */
1744+ blkcnt_t br_xino_upper; /* watermark in blocks */
1745+ atomic_t br_xino_running;
1746+
027c5e7a
AM
1747+#ifdef CONFIG_AUFS_HFSNOTIFY
1748+ struct fsnotify_group *br_hfsn_group;
1749+ struct fsnotify_ops br_hfsn_ops;
1750+#endif
1751+
1facf9fc 1752+#ifdef CONFIG_SYSFS
1753+ /* an entry under sysfs per mount-point */
1754+ char br_name[8];
1755+ struct attribute br_attr;
1756+#endif
1757+};
1758+
1759+/* ---------------------------------------------------------------------- */
1760+
1761+/* branch permission and attribute */
1762+enum {
1763+ AuBrPerm_RW, /* writable, linkable wh */
1764+ AuBrPerm_RO, /* readonly, no wh */
1765+ AuBrPerm_RR, /* natively readonly, no wh */
1766+
1767+ AuBrPerm_RWNoLinkWH, /* un-linkable whiteouts */
1768+
1769+ AuBrPerm_ROWH, /* whiteout-able */
1770+ AuBrPerm_RRWH, /* whiteout-able */
1771+
1772+ AuBrPerm_Last
1773+};
1774+
1775+static inline int au_br_writable(int brperm)
1776+{
1777+ return brperm == AuBrPerm_RW || brperm == AuBrPerm_RWNoLinkWH;
1778+}
1779+
1780+static inline int au_br_whable(int brperm)
1781+{
1782+ return brperm == AuBrPerm_RW
1783+ || brperm == AuBrPerm_ROWH
1784+ || brperm == AuBrPerm_RRWH;
1785+}
1786+
1787+static inline int au_br_rdonly(struct au_branch *br)
1788+{
1789+ return ((br->br_mnt->mnt_sb->s_flags & MS_RDONLY)
1790+ || !au_br_writable(br->br_perm))
1791+ ? -EROFS : 0;
1792+}
1793+
4a4d8108 1794+static inline int au_br_hnotifyable(int brperm __maybe_unused)
1facf9fc 1795+{
4a4d8108 1796+#ifdef CONFIG_AUFS_HNOTIFY
1facf9fc 1797+ return brperm != AuBrPerm_RR && brperm != AuBrPerm_RRWH;
1798+#else
1799+ return 0;
1800+#endif
1801+}
1802+
1803+/* ---------------------------------------------------------------------- */
1804+
1805+/* branch.c */
1806+struct au_sbinfo;
1807+void au_br_free(struct au_sbinfo *sinfo);
1808+int au_br_index(struct super_block *sb, aufs_bindex_t br_id);
1809+struct au_opt_add;
1810+int au_br_add(struct super_block *sb, struct au_opt_add *add, int remount);
1811+struct au_opt_del;
1812+int au_br_del(struct super_block *sb, struct au_opt_del *del, int remount);
027c5e7a
AM
1813+long au_ibusy_ioctl(struct file *file, unsigned long arg);
1814+#ifdef CONFIG_COMPAT
1815+long au_ibusy_compat_ioctl(struct file *file, unsigned long arg);
1816+#endif
1facf9fc 1817+struct au_opt_mod;
1818+int au_br_mod(struct super_block *sb, struct au_opt_mod *mod, int remount,
7f207e10 1819+ int *do_refresh);
1facf9fc 1820+
1821+/* xino.c */
1822+static const loff_t au_loff_max = LLONG_MAX;
1823+
1824+int au_xib_trunc(struct super_block *sb);
1825+ssize_t xino_fread(au_readf_t func, struct file *file, void *buf, size_t size,
1826+ loff_t *pos);
1827+ssize_t xino_fwrite(au_writef_t func, struct file *file, void *buf, size_t size,
1828+ loff_t *pos);
1829+struct file *au_xino_create2(struct file *base_file, struct file *copy_src);
1830+struct file *au_xino_create(struct super_block *sb, char *fname, int silent);
1831+ino_t au_xino_new_ino(struct super_block *sb);
b752ccd1 1832+void au_xino_delete_inode(struct inode *inode, const int unlinked);
1facf9fc 1833+int au_xino_write(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino,
1834+ ino_t ino);
1835+int au_xino_read(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino,
1836+ ino_t *ino);
1837+int au_xino_br(struct super_block *sb, struct au_branch *br, ino_t hino,
1838+ struct file *base_file, int do_test);
1839+int au_xino_trunc(struct super_block *sb, aufs_bindex_t bindex);
1840+
1841+struct au_opt_xino;
1842+int au_xino_set(struct super_block *sb, struct au_opt_xino *xino, int remount);
1843+void au_xino_clr(struct super_block *sb);
1844+struct file *au_xino_def(struct super_block *sb);
1845+int au_xino_path(struct seq_file *seq, struct file *file);
1846+
1847+/* ---------------------------------------------------------------------- */
1848+
1849+/* Superblock to branch */
1850+static inline
1851+aufs_bindex_t au_sbr_id(struct super_block *sb, aufs_bindex_t bindex)
1852+{
1853+ return au_sbr(sb, bindex)->br_id;
1854+}
1855+
1856+static inline
1857+struct vfsmount *au_sbr_mnt(struct super_block *sb, aufs_bindex_t bindex)
1858+{
1859+ return au_sbr(sb, bindex)->br_mnt;
1860+}
1861+
1862+static inline
1863+struct super_block *au_sbr_sb(struct super_block *sb, aufs_bindex_t bindex)
1864+{
1865+ return au_sbr_mnt(sb, bindex)->mnt_sb;
1866+}
1867+
1868+static inline void au_sbr_put(struct super_block *sb, aufs_bindex_t bindex)
1869+{
e49829fe 1870+ atomic_dec(&au_sbr(sb, bindex)->br_count);
1facf9fc 1871+}
1872+
1873+static inline int au_sbr_perm(struct super_block *sb, aufs_bindex_t bindex)
1874+{
1875+ return au_sbr(sb, bindex)->br_perm;
1876+}
1877+
1878+static inline int au_sbr_whable(struct super_block *sb, aufs_bindex_t bindex)
1879+{
1880+ return au_br_whable(au_sbr_perm(sb, bindex));
1881+}
1882+
1883+/* ---------------------------------------------------------------------- */
1884+
1885+/*
1886+ * wbr_wh_read_lock, wbr_wh_write_lock
1887+ * wbr_wh_read_unlock, wbr_wh_write_unlock, wbr_wh_downgrade_lock
1888+ */
1889+AuSimpleRwsemFuncs(wbr_wh, struct au_wbr *wbr, &wbr->wbr_wh_rwsem);
1890+
dece6358
AM
1891+#define WbrWhMustNoWaiters(wbr) AuRwMustNoWaiters(&wbr->wbr_wh_rwsem)
1892+#define WbrWhMustAnyLock(wbr) AuRwMustAnyLock(&wbr->wbr_wh_rwsem)
1893+#define WbrWhMustWriteLock(wbr) AuRwMustWriteLock(&wbr->wbr_wh_rwsem)
1894+
1facf9fc 1895+#endif /* __KERNEL__ */
1896+#endif /* __AUFS_BRANCH_H__ */
7f207e10
AM
1897diff -urN /usr/share/empty/fs/aufs/conf.mk linux/fs/aufs/conf.mk
1898--- /usr/share/empty/fs/aufs/conf.mk 1970-01-01 01:00:00.000000000 +0100
2cbb1c4b
JR
1899+++ linux/fs/aufs/conf.mk 2011-07-11 11:34:24.071331673 +0200
1900@@ -0,0 +1,38 @@
4a4d8108
AM
1901+
1902+AuConfStr = CONFIG_AUFS_FS=${CONFIG_AUFS_FS}
1903+
1904+define AuConf
1905+ifdef ${1}
1906+AuConfStr += ${1}=${${1}}
1907+endif
1908+endef
1909+
b752ccd1 1910+AuConfAll = BRANCH_MAX_127 BRANCH_MAX_511 BRANCH_MAX_1023 BRANCH_MAX_32767 \
e49829fe 1911+ SBILIST \
7f207e10 1912+ HNOTIFY HFSNOTIFY \
4a4d8108
AM
1913+ EXPORT INO_T_64 \
1914+ RDU \
2cbb1c4b 1915+ PROC_MAP \
4a4d8108
AM
1916+ SP_IATTR \
1917+ SHWH \
1918+ BR_RAMFS \
1919+ BR_FUSE POLL \
1920+ BR_HFSPLUS \
1921+ BDEV_LOOP \
b752ccd1
AM
1922+ DEBUG MAGIC_SYSRQ
1923+$(foreach i, ${AuConfAll}, \
4a4d8108
AM
1924+ $(eval $(call AuConf,CONFIG_AUFS_${i})))
1925+
1926+AuConfName = ${obj}/conf.str
1927+${AuConfName}.tmp: FORCE
1928+ @echo ${AuConfStr} | tr ' ' '\n' | sed -e 's/^/"/' -e 's/$$/\\n"/' > $@
1929+${AuConfName}: ${AuConfName}.tmp
1930+ @diff -q $< $@ > /dev/null 2>&1 || { \
1931+ echo ' GEN ' $@; \
1932+ cp -p $< $@; \
1933+ }
1934+FORCE:
1935+clean-files += ${AuConfName} ${AuConfName}.tmp
1936+${obj}/sysfs.o: ${AuConfName}
b752ccd1
AM
1937+
1938+-include ${srctree}/${src}/conf_priv.mk
7f207e10
AM
1939diff -urN /usr/share/empty/fs/aufs/cpup.c linux/fs/aufs/cpup.c
1940--- /usr/share/empty/fs/aufs/cpup.c 1970-01-01 01:00:00.000000000 +0100
2cbb1c4b 1941+++ linux/fs/aufs/cpup.c 2011-07-11 11:34:24.071331673 +0200
027c5e7a 1942@@ -0,0 +1,1063 @@
1facf9fc 1943+/*
027c5e7a 1944+ * Copyright (C) 2005-2011 Junjiro R. Okajima
1facf9fc 1945+ *
1946+ * This program, aufs is free software; you can redistribute it and/or modify
1947+ * it under the terms of the GNU General Public License as published by
1948+ * the Free Software Foundation; either version 2 of the License, or
1949+ * (at your option) any later version.
dece6358
AM
1950+ *
1951+ * This program is distributed in the hope that it will be useful,
1952+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1953+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1954+ * GNU General Public License for more details.
1955+ *
1956+ * You should have received a copy of the GNU General Public License
1957+ * along with this program; if not, write to the Free Software
1958+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 1959+ */
1960+
1961+/*
1962+ * copy-up functions, see wbr_policy.c for copy-down
1963+ */
1964+
dece6358 1965+#include <linux/file.h>
1facf9fc 1966+#include <linux/fs_stack.h>
dece6358 1967+#include <linux/mm.h>
1facf9fc 1968+#include <linux/uaccess.h>
1969+#include "aufs.h"
1970+
1971+void au_cpup_attr_flags(struct inode *dst, struct inode *src)
1972+{
1973+ const unsigned int mask = S_DEAD | S_SWAPFILE | S_PRIVATE
1974+ | S_NOATIME | S_NOCMTIME;
1975+
1976+ dst->i_flags |= src->i_flags & ~mask;
1977+ if (au_test_fs_notime(dst->i_sb))
1978+ dst->i_flags |= S_NOATIME | S_NOCMTIME;
1979+}
1980+
1981+void au_cpup_attr_timesizes(struct inode *inode)
1982+{
1983+ struct inode *h_inode;
1984+
1985+ h_inode = au_h_iptr(inode, au_ibstart(inode));
1986+ fsstack_copy_attr_times(inode, h_inode);
4a4d8108 1987+ fsstack_copy_inode_size(inode, h_inode);
1facf9fc 1988+}
1989+
1990+void au_cpup_attr_nlink(struct inode *inode, int force)
1991+{
1992+ struct inode *h_inode;
1993+ struct super_block *sb;
1994+ aufs_bindex_t bindex, bend;
1995+
1996+ sb = inode->i_sb;
1997+ bindex = au_ibstart(inode);
1998+ h_inode = au_h_iptr(inode, bindex);
1999+ if (!force
2000+ && !S_ISDIR(h_inode->i_mode)
2001+ && au_opt_test(au_mntflags(sb), PLINK)
2002+ && au_plink_test(inode))
2003+ return;
2004+
2005+ inode->i_nlink = h_inode->i_nlink;
2006+
2007+ /*
2008+ * fewer nlink makes find(1) noisy, but larger nlink doesn't.
2009+ * it may includes whplink directory.
2010+ */
2011+ if (S_ISDIR(h_inode->i_mode)) {
2012+ bend = au_ibend(inode);
2013+ for (bindex++; bindex <= bend; bindex++) {
2014+ h_inode = au_h_iptr(inode, bindex);
2015+ if (h_inode)
2016+ au_add_nlink(inode, h_inode);
2017+ }
2018+ }
2019+}
2020+
2021+void au_cpup_attr_changeable(struct inode *inode)
2022+{
2023+ struct inode *h_inode;
2024+
2025+ h_inode = au_h_iptr(inode, au_ibstart(inode));
2026+ inode->i_mode = h_inode->i_mode;
2027+ inode->i_uid = h_inode->i_uid;
2028+ inode->i_gid = h_inode->i_gid;
2029+ au_cpup_attr_timesizes(inode);
2030+ au_cpup_attr_flags(inode, h_inode);
2031+}
2032+
2033+void au_cpup_igen(struct inode *inode, struct inode *h_inode)
2034+{
2035+ struct au_iinfo *iinfo = au_ii(inode);
2036+
1308ab2a 2037+ IiMustWriteLock(inode);
2038+
1facf9fc 2039+ iinfo->ii_higen = h_inode->i_generation;
2040+ iinfo->ii_hsb1 = h_inode->i_sb;
2041+}
2042+
2043+void au_cpup_attr_all(struct inode *inode, int force)
2044+{
2045+ struct inode *h_inode;
2046+
2047+ h_inode = au_h_iptr(inode, au_ibstart(inode));
2048+ au_cpup_attr_changeable(inode);
2049+ if (inode->i_nlink > 0)
2050+ au_cpup_attr_nlink(inode, force);
2051+ inode->i_rdev = h_inode->i_rdev;
2052+ inode->i_blkbits = h_inode->i_blkbits;
2053+ au_cpup_igen(inode, h_inode);
2054+}
2055+
2056+/* ---------------------------------------------------------------------- */
2057+
2058+/* Note: dt_dentry and dt_h_dentry are not dget/dput-ed */
2059+
2060+/* keep the timestamps of the parent dir when cpup */
2061+void au_dtime_store(struct au_dtime *dt, struct dentry *dentry,
2062+ struct path *h_path)
2063+{
2064+ struct inode *h_inode;
2065+
2066+ dt->dt_dentry = dentry;
2067+ dt->dt_h_path = *h_path;
2068+ h_inode = h_path->dentry->d_inode;
2069+ dt->dt_atime = h_inode->i_atime;
2070+ dt->dt_mtime = h_inode->i_mtime;
2071+ /* smp_mb(); */
2072+}
2073+
2074+void au_dtime_revert(struct au_dtime *dt)
2075+{
2076+ struct iattr attr;
2077+ int err;
2078+
2079+ attr.ia_atime = dt->dt_atime;
2080+ attr.ia_mtime = dt->dt_mtime;
2081+ attr.ia_valid = ATTR_FORCE | ATTR_MTIME | ATTR_MTIME_SET
2082+ | ATTR_ATIME | ATTR_ATIME_SET;
2083+
2084+ err = vfsub_notify_change(&dt->dt_h_path, &attr);
2085+ if (unlikely(err))
4a4d8108 2086+ pr_warning("restoring timestamps failed(%d). ignored\n", err);
1facf9fc 2087+}
2088+
2089+/* ---------------------------------------------------------------------- */
2090+
2091+static noinline_for_stack
2092+int cpup_iattr(struct dentry *dst, aufs_bindex_t bindex, struct dentry *h_src)
2093+{
2094+ int err, sbits;
2095+ struct iattr ia;
2096+ struct path h_path;
1308ab2a 2097+ struct inode *h_isrc, *h_idst;
1facf9fc 2098+
2099+ h_path.dentry = au_h_dptr(dst, bindex);
1308ab2a 2100+ h_idst = h_path.dentry->d_inode;
1facf9fc 2101+ h_path.mnt = au_sbr_mnt(dst->d_sb, bindex);
2102+ h_isrc = h_src->d_inode;
1308ab2a 2103+ ia.ia_valid = ATTR_FORCE | ATTR_UID | ATTR_GID
1facf9fc 2104+ | ATTR_ATIME | ATTR_MTIME
2105+ | ATTR_ATIME_SET | ATTR_MTIME_SET;
1facf9fc 2106+ ia.ia_uid = h_isrc->i_uid;
2107+ ia.ia_gid = h_isrc->i_gid;
2108+ ia.ia_atime = h_isrc->i_atime;
2109+ ia.ia_mtime = h_isrc->i_mtime;
1308ab2a 2110+ if (h_idst->i_mode != h_isrc->i_mode
2111+ && !S_ISLNK(h_idst->i_mode)) {
2112+ ia.ia_valid |= ATTR_MODE;
2113+ ia.ia_mode = h_isrc->i_mode;
2114+ }
2115+ sbits = !!(h_isrc->i_mode & (S_ISUID | S_ISGID));
2116+ au_cpup_attr_flags(h_idst, h_isrc);
1facf9fc 2117+ err = vfsub_notify_change(&h_path, &ia);
2118+
2119+ /* is this nfs only? */
2120+ if (!err && sbits && au_test_nfs(h_path.dentry->d_sb)) {
2121+ ia.ia_valid = ATTR_FORCE | ATTR_MODE;
2122+ ia.ia_mode = h_isrc->i_mode;
2123+ err = vfsub_notify_change(&h_path, &ia);
2124+ }
2125+
2126+ return err;
2127+}
2128+
2129+/* ---------------------------------------------------------------------- */
2130+
2131+static int au_do_copy_file(struct file *dst, struct file *src, loff_t len,
2132+ char *buf, unsigned long blksize)
2133+{
2134+ int err;
2135+ size_t sz, rbytes, wbytes;
2136+ unsigned char all_zero;
2137+ char *p, *zp;
2138+ struct mutex *h_mtx;
2139+ /* reduce stack usage */
2140+ struct iattr *ia;
2141+
2142+ zp = page_address(ZERO_PAGE(0));
2143+ if (unlikely(!zp))
2144+ return -ENOMEM; /* possible? */
2145+
2146+ err = 0;
2147+ all_zero = 0;
2148+ while (len) {
2149+ AuDbg("len %lld\n", len);
2150+ sz = blksize;
2151+ if (len < blksize)
2152+ sz = len;
2153+
2154+ rbytes = 0;
2155+ /* todo: signal_pending? */
2156+ while (!rbytes || err == -EAGAIN || err == -EINTR) {
2157+ rbytes = vfsub_read_k(src, buf, sz, &src->f_pos);
2158+ err = rbytes;
2159+ }
2160+ if (unlikely(err < 0))
2161+ break;
2162+
2163+ all_zero = 0;
2164+ if (len >= rbytes && rbytes == blksize)
2165+ all_zero = !memcmp(buf, zp, rbytes);
2166+ if (!all_zero) {
2167+ wbytes = rbytes;
2168+ p = buf;
2169+ while (wbytes) {
2170+ size_t b;
2171+
2172+ b = vfsub_write_k(dst, p, wbytes, &dst->f_pos);
2173+ err = b;
2174+ /* todo: signal_pending? */
2175+ if (unlikely(err == -EAGAIN || err == -EINTR))
2176+ continue;
2177+ if (unlikely(err < 0))
2178+ break;
2179+ wbytes -= b;
2180+ p += b;
2181+ }
2182+ } else {
2183+ loff_t res;
2184+
2185+ AuLabel(hole);
2186+ res = vfsub_llseek(dst, rbytes, SEEK_CUR);
2187+ err = res;
2188+ if (unlikely(res < 0))
2189+ break;
2190+ }
2191+ len -= rbytes;
2192+ err = 0;
2193+ }
2194+
2195+ /* the last block may be a hole */
2196+ if (!err && all_zero) {
2197+ AuLabel(last hole);
2198+
2199+ err = 1;
2200+ if (au_test_nfs(dst->f_dentry->d_sb)) {
2201+ /* nfs requires this step to make last hole */
2202+ /* is this only nfs? */
2203+ do {
2204+ /* todo: signal_pending? */
2205+ err = vfsub_write_k(dst, "\0", 1, &dst->f_pos);
2206+ } while (err == -EAGAIN || err == -EINTR);
2207+ if (err == 1)
2208+ dst->f_pos--;
2209+ }
2210+
2211+ if (err == 1) {
2212+ ia = (void *)buf;
2213+ ia->ia_size = dst->f_pos;
2214+ ia->ia_valid = ATTR_SIZE | ATTR_FILE;
2215+ ia->ia_file = dst;
2216+ h_mtx = &dst->f_dentry->d_inode->i_mutex;
2217+ mutex_lock_nested(h_mtx, AuLsc_I_CHILD2);
2218+ err = vfsub_notify_change(&dst->f_path, ia);
2219+ mutex_unlock(h_mtx);
2220+ }
2221+ }
2222+
2223+ return err;
2224+}
2225+
2226+int au_copy_file(struct file *dst, struct file *src, loff_t len)
2227+{
2228+ int err;
2229+ unsigned long blksize;
2230+ unsigned char do_kfree;
2231+ char *buf;
2232+
2233+ err = -ENOMEM;
2234+ blksize = dst->f_dentry->d_sb->s_blocksize;
2235+ if (!blksize || PAGE_SIZE < blksize)
2236+ blksize = PAGE_SIZE;
2237+ AuDbg("blksize %lu\n", blksize);
2238+ do_kfree = (blksize != PAGE_SIZE && blksize >= sizeof(struct iattr *));
2239+ if (do_kfree)
2240+ buf = kmalloc(blksize, GFP_NOFS);
2241+ else
2242+ buf = (void *)__get_free_page(GFP_NOFS);
2243+ if (unlikely(!buf))
2244+ goto out;
2245+
2246+ if (len > (1 << 22))
2247+ AuDbg("copying a large file %lld\n", (long long)len);
2248+
2249+ src->f_pos = 0;
2250+ dst->f_pos = 0;
2251+ err = au_do_copy_file(dst, src, len, buf, blksize);
2252+ if (do_kfree)
2253+ kfree(buf);
2254+ else
2255+ free_page((unsigned long)buf);
2256+
4f0767ce 2257+out:
1facf9fc 2258+ return err;
2259+}
2260+
2261+/*
2262+ * to support a sparse file which is opened with O_APPEND,
2263+ * we need to close the file.
2264+ */
2265+static int au_cp_regular(struct dentry *dentry, aufs_bindex_t bdst,
4a4d8108 2266+ aufs_bindex_t bsrc, loff_t len)
1facf9fc 2267+{
2268+ int err, i;
2269+ enum { SRC, DST };
2270+ struct {
2271+ aufs_bindex_t bindex;
2272+ unsigned int flags;
2273+ struct dentry *dentry;
2274+ struct file *file;
2275+ void *label, *label_file;
2276+ } *f, file[] = {
2277+ {
2278+ .bindex = bsrc,
2279+ .flags = O_RDONLY | O_NOATIME | O_LARGEFILE,
2280+ .file = NULL,
2281+ .label = &&out,
2282+ .label_file = &&out_src
2283+ },
2284+ {
2285+ .bindex = bdst,
2286+ .flags = O_WRONLY | O_NOATIME | O_LARGEFILE,
2287+ .file = NULL,
2288+ .label = &&out_src,
2289+ .label_file = &&out_dst
2290+ }
2291+ };
2292+ struct super_block *sb;
2293+
2294+ /* bsrc branch can be ro/rw. */
2295+ sb = dentry->d_sb;
2296+ f = file;
2297+ for (i = 0; i < 2; i++, f++) {
2298+ f->dentry = au_h_dptr(dentry, f->bindex);
2299+ f->file = au_h_open(dentry, f->bindex, f->flags, /*file*/NULL);
2300+ err = PTR_ERR(f->file);
2301+ if (IS_ERR(f->file))
2302+ goto *f->label;
2303+ err = -EINVAL;
2304+ if (unlikely(!f->file->f_op))
2305+ goto *f->label_file;
2306+ }
2307+
2308+ /* try stopping to update while we copyup */
2309+ IMustLock(file[SRC].dentry->d_inode);
2310+ err = au_copy_file(file[DST].file, file[SRC].file, len);
2311+
4f0767ce 2312+out_dst:
1facf9fc 2313+ fput(file[DST].file);
2314+ au_sbr_put(sb, file[DST].bindex);
4f0767ce 2315+out_src:
1facf9fc 2316+ fput(file[SRC].file);
2317+ au_sbr_put(sb, file[SRC].bindex);
4f0767ce 2318+out:
1facf9fc 2319+ return err;
2320+}
2321+
2322+static int au_do_cpup_regular(struct dentry *dentry, aufs_bindex_t bdst,
2323+ aufs_bindex_t bsrc, loff_t len,
2324+ struct inode *h_dir, struct path *h_path)
2325+{
2326+ int err, rerr;
2327+ loff_t l;
2328+
2329+ err = 0;
2330+ l = i_size_read(au_h_iptr(dentry->d_inode, bsrc));
2331+ if (len == -1 || l < len)
2332+ len = l;
2333+ if (len)
2334+ err = au_cp_regular(dentry, bdst, bsrc, len);
2335+ if (!err)
2336+ goto out; /* success */
2337+
2338+ rerr = vfsub_unlink(h_dir, h_path, /*force*/0);
2339+ if (rerr) {
2340+ AuIOErr("failed unlinking cpup-ed %.*s(%d, %d)\n",
2341+ AuDLNPair(h_path->dentry), err, rerr);
2342+ err = -EIO;
2343+ }
2344+
4f0767ce 2345+out:
1facf9fc 2346+ return err;
2347+}
2348+
2349+static int au_do_cpup_symlink(struct path *h_path, struct dentry *h_src,
2350+ struct inode *h_dir)
2351+{
2352+ int err, symlen;
2353+ mm_segment_t old_fs;
b752ccd1
AM
2354+ union {
2355+ char *k;
2356+ char __user *u;
2357+ } sym;
1facf9fc 2358+
2359+ err = -ENOSYS;
2360+ if (unlikely(!h_src->d_inode->i_op->readlink))
2361+ goto out;
2362+
2363+ err = -ENOMEM;
b752ccd1
AM
2364+ sym.k = __getname_gfp(GFP_NOFS);
2365+ if (unlikely(!sym.k))
1facf9fc 2366+ goto out;
2367+
2368+ old_fs = get_fs();
2369+ set_fs(KERNEL_DS);
b752ccd1 2370+ symlen = h_src->d_inode->i_op->readlink(h_src, sym.u, PATH_MAX);
1facf9fc 2371+ err = symlen;
2372+ set_fs(old_fs);
2373+
2374+ if (symlen > 0) {
b752ccd1
AM
2375+ sym.k[symlen] = 0;
2376+ err = vfsub_symlink(h_dir, h_path, sym.k);
1facf9fc 2377+ }
b752ccd1 2378+ __putname(sym.k);
1facf9fc 2379+
4f0767ce 2380+out:
1facf9fc 2381+ return err;
2382+}
2383+
2384+/* return with the lower dst inode is locked */
2385+static noinline_for_stack
2386+int cpup_entry(struct dentry *dentry, aufs_bindex_t bdst,
2387+ aufs_bindex_t bsrc, loff_t len, unsigned int flags,
2388+ struct dentry *dst_parent)
2389+{
2390+ int err;
2391+ umode_t mode;
2392+ unsigned int mnt_flags;
2393+ unsigned char isdir;
2394+ const unsigned char do_dt = !!au_ftest_cpup(flags, DTIME);
2395+ struct au_dtime dt;
2396+ struct path h_path;
2397+ struct dentry *h_src, *h_dst, *h_parent;
2398+ struct inode *h_inode, *h_dir;
2399+ struct super_block *sb;
2400+
2401+ /* bsrc branch can be ro/rw. */
2402+ h_src = au_h_dptr(dentry, bsrc);
2403+ h_inode = h_src->d_inode;
2404+ AuDebugOn(h_inode != au_h_iptr(dentry->d_inode, bsrc));
2405+
2406+ /* try stopping to be referenced while we are creating */
2407+ h_dst = au_h_dptr(dentry, bdst);
2408+ h_parent = h_dst->d_parent; /* dir inode is locked */
2409+ h_dir = h_parent->d_inode;
2410+ IMustLock(h_dir);
2411+ AuDebugOn(h_parent != h_dst->d_parent);
2412+
2413+ sb = dentry->d_sb;
2414+ h_path.mnt = au_sbr_mnt(sb, bdst);
2415+ if (do_dt) {
2416+ h_path.dentry = h_parent;
2417+ au_dtime_store(&dt, dst_parent, &h_path);
2418+ }
2419+ h_path.dentry = h_dst;
2420+
2421+ isdir = 0;
2422+ mode = h_inode->i_mode;
2423+ switch (mode & S_IFMT) {
2424+ case S_IFREG:
2425+ /* try stopping to update while we are referencing */
2426+ IMustLock(h_inode);
2427+ err = vfsub_create(h_dir, &h_path, mode | S_IWUSR);
2428+ if (!err)
2429+ err = au_do_cpup_regular
2430+ (dentry, bdst, bsrc, len,
2431+ au_h_iptr(dst_parent->d_inode, bdst), &h_path);
2432+ break;
2433+ case S_IFDIR:
2434+ isdir = 1;
2435+ err = vfsub_mkdir(h_dir, &h_path, mode);
2436+ if (!err) {
2437+ /*
2438+ * strange behaviour from the users view,
2439+ * particularry setattr case
2440+ */
2441+ if (au_ibstart(dst_parent->d_inode) == bdst)
2442+ au_cpup_attr_nlink(dst_parent->d_inode,
2443+ /*force*/1);
2444+ au_cpup_attr_nlink(dentry->d_inode, /*force*/1);
2445+ }
2446+ break;
2447+ case S_IFLNK:
2448+ err = au_do_cpup_symlink(&h_path, h_src, h_dir);
2449+ break;
2450+ case S_IFCHR:
2451+ case S_IFBLK:
2452+ AuDebugOn(!capable(CAP_MKNOD));
2453+ /*FALLTHROUGH*/
2454+ case S_IFIFO:
2455+ case S_IFSOCK:
2456+ err = vfsub_mknod(h_dir, &h_path, mode, h_inode->i_rdev);
2457+ break;
2458+ default:
2459+ AuIOErr("Unknown inode type 0%o\n", mode);
2460+ err = -EIO;
2461+ }
2462+
2463+ mnt_flags = au_mntflags(sb);
2464+ if (!au_opt_test(mnt_flags, UDBA_NONE)
2465+ && !isdir
2466+ && au_opt_test(mnt_flags, XINO)
2467+ && h_inode->i_nlink == 1
2468+ /* todo: unnecessary? */
2469+ /* && dentry->d_inode->i_nlink == 1 */
2470+ && bdst < bsrc
2471+ && !au_ftest_cpup(flags, KEEPLINO))
1308ab2a 2472+ au_xino_write(sb, bsrc, h_inode->i_ino, /*ino*/0);
1facf9fc 2473+ /* ignore this error */
2474+
2475+ if (do_dt)
2476+ au_dtime_revert(&dt);
2477+ return err;
2478+}
2479+
2480+/*
2481+ * copyup the @dentry from @bsrc to @bdst.
2482+ * the caller must set the both of lower dentries.
2483+ * @len is for truncating when it is -1 copyup the entire file.
2484+ * in link/rename cases, @dst_parent may be different from the real one.
2485+ */
2486+static int au_cpup_single(struct dentry *dentry, aufs_bindex_t bdst,
2487+ aufs_bindex_t bsrc, loff_t len, unsigned int flags,
2488+ struct dentry *dst_parent)
2489+{
2490+ int err, rerr;
2491+ aufs_bindex_t old_ibstart;
2492+ unsigned char isdir, plink;
2493+ struct au_dtime dt;
2494+ struct path h_path;
2495+ struct dentry *h_src, *h_dst, *h_parent;
2496+ struct inode *dst_inode, *h_dir, *inode;
2497+ struct super_block *sb;
2498+
2499+ AuDebugOn(bsrc <= bdst);
2500+
2501+ sb = dentry->d_sb;
2502+ h_path.mnt = au_sbr_mnt(sb, bdst);
2503+ h_dst = au_h_dptr(dentry, bdst);
2504+ h_parent = h_dst->d_parent; /* dir inode is locked */
2505+ h_dir = h_parent->d_inode;
2506+ IMustLock(h_dir);
2507+
2508+ h_src = au_h_dptr(dentry, bsrc);
2509+ inode = dentry->d_inode;
2510+
2511+ if (!dst_parent)
2512+ dst_parent = dget_parent(dentry);
2513+ else
2514+ dget(dst_parent);
2515+
2516+ plink = !!au_opt_test(au_mntflags(sb), PLINK);
2517+ dst_inode = au_h_iptr(inode, bdst);
2518+ if (dst_inode) {
2519+ if (unlikely(!plink)) {
2520+ err = -EIO;
027c5e7a
AM
2521+ AuIOErr("hi%lu(i%lu) exists on b%d "
2522+ "but plink is disabled\n",
2523+ dst_inode->i_ino, inode->i_ino, bdst);
1facf9fc 2524+ goto out;
2525+ }
2526+
2527+ if (dst_inode->i_nlink) {
2528+ const int do_dt = au_ftest_cpup(flags, DTIME);
2529+
2530+ h_src = au_plink_lkup(inode, bdst);
2531+ err = PTR_ERR(h_src);
2532+ if (IS_ERR(h_src))
2533+ goto out;
2534+ if (unlikely(!h_src->d_inode)) {
2535+ err = -EIO;
2536+ AuIOErr("i%lu exists on a upper branch "
027c5e7a
AM
2537+ "but not pseudo-linked\n",
2538+ inode->i_ino);
1facf9fc 2539+ dput(h_src);
2540+ goto out;
2541+ }
2542+
2543+ if (do_dt) {
2544+ h_path.dentry = h_parent;
2545+ au_dtime_store(&dt, dst_parent, &h_path);
2546+ }
2547+ h_path.dentry = h_dst;
2548+ err = vfsub_link(h_src, h_dir, &h_path);
2549+ if (do_dt)
2550+ au_dtime_revert(&dt);
2551+ dput(h_src);
2552+ goto out;
2553+ } else
2554+ /* todo: cpup_wh_file? */
2555+ /* udba work */
4a4d8108 2556+ au_update_ibrange(inode, /*do_put_zero*/1);
1facf9fc 2557+ }
2558+
2559+ old_ibstart = au_ibstart(inode);
2560+ err = cpup_entry(dentry, bdst, bsrc, len, flags, dst_parent);
2561+ if (unlikely(err))
2562+ goto out;
2563+ dst_inode = h_dst->d_inode;
2564+ mutex_lock_nested(&dst_inode->i_mutex, AuLsc_I_CHILD2);
2565+
2566+ err = cpup_iattr(dentry, bdst, h_src);
2567+ isdir = S_ISDIR(dst_inode->i_mode);
2568+ if (!err) {
4a4d8108
AM
2569+ if (bdst < old_ibstart) {
2570+ if (S_ISREG(inode->i_mode)) {
2571+ err = au_dy_iaop(inode, bdst, dst_inode);
2572+ if (unlikely(err))
2573+ goto out_rev;
2574+ }
1facf9fc 2575+ au_set_ibstart(inode, bdst);
4a4d8108 2576+ }
1facf9fc 2577+ au_set_h_iptr(inode, bdst, au_igrab(dst_inode),
2578+ au_hi_flags(inode, isdir));
2579+ mutex_unlock(&dst_inode->i_mutex);
2580+ if (!isdir
2581+ && h_src->d_inode->i_nlink > 1
2582+ && plink)
2583+ au_plink_append(inode, bdst, h_dst);
2584+ goto out; /* success */
2585+ }
2586+
2587+ /* revert */
4a4d8108 2588+out_rev:
1facf9fc 2589+ h_path.dentry = h_parent;
2590+ mutex_unlock(&dst_inode->i_mutex);
2591+ au_dtime_store(&dt, dst_parent, &h_path);
2592+ h_path.dentry = h_dst;
2593+ if (!isdir)
2594+ rerr = vfsub_unlink(h_dir, &h_path, /*force*/0);
2595+ else
2596+ rerr = vfsub_rmdir(h_dir, &h_path);
2597+ au_dtime_revert(&dt);
2598+ if (rerr) {
2599+ AuIOErr("failed removing broken entry(%d, %d)\n", err, rerr);
2600+ err = -EIO;
2601+ }
2602+
4f0767ce 2603+out:
1facf9fc 2604+ dput(dst_parent);
2605+ return err;
2606+}
2607+
2608+struct au_cpup_single_args {
2609+ int *errp;
2610+ struct dentry *dentry;
2611+ aufs_bindex_t bdst, bsrc;
2612+ loff_t len;
2613+ unsigned int flags;
2614+ struct dentry *dst_parent;
2615+};
2616+
2617+static void au_call_cpup_single(void *args)
2618+{
2619+ struct au_cpup_single_args *a = args;
2620+ *a->errp = au_cpup_single(a->dentry, a->bdst, a->bsrc, a->len,
2621+ a->flags, a->dst_parent);
2622+}
2623+
2624+int au_sio_cpup_single(struct dentry *dentry, aufs_bindex_t bdst,
2625+ aufs_bindex_t bsrc, loff_t len, unsigned int flags,
2626+ struct dentry *dst_parent)
2627+{
2628+ int err, wkq_err;
2629+ umode_t mode;
2630+ struct dentry *h_dentry;
2631+
2632+ h_dentry = au_h_dptr(dentry, bsrc);
2633+ mode = h_dentry->d_inode->i_mode & S_IFMT;
2634+ if ((mode != S_IFCHR && mode != S_IFBLK)
2635+ || capable(CAP_MKNOD))
2636+ err = au_cpup_single(dentry, bdst, bsrc, len, flags,
2637+ dst_parent);
2638+ else {
2639+ struct au_cpup_single_args args = {
2640+ .errp = &err,
2641+ .dentry = dentry,
2642+ .bdst = bdst,
2643+ .bsrc = bsrc,
2644+ .len = len,
2645+ .flags = flags,
2646+ .dst_parent = dst_parent
2647+ };
2648+ wkq_err = au_wkq_wait(au_call_cpup_single, &args);
2649+ if (unlikely(wkq_err))
2650+ err = wkq_err;
2651+ }
2652+
2653+ return err;
2654+}
2655+
2656+/*
2657+ * copyup the @dentry from the first active lower branch to @bdst,
2658+ * using au_cpup_single().
2659+ */
2660+static int au_cpup_simple(struct dentry *dentry, aufs_bindex_t bdst, loff_t len,
2661+ unsigned int flags)
2662+{
2663+ int err;
2664+ aufs_bindex_t bsrc, bend;
2665+
2666+ bend = au_dbend(dentry);
2667+ for (bsrc = bdst + 1; bsrc <= bend; bsrc++)
2668+ if (au_h_dptr(dentry, bsrc))
2669+ break;
2670+
2671+ err = au_lkup_neg(dentry, bdst);
2672+ if (!err) {
2673+ err = au_cpup_single(dentry, bdst, bsrc, len, flags, NULL);
2674+ if (!err)
2675+ return 0; /* success */
2676+
2677+ /* revert */
2678+ au_set_h_dptr(dentry, bdst, NULL);
2679+ au_set_dbstart(dentry, bsrc);
2680+ }
2681+
2682+ return err;
2683+}
2684+
2685+struct au_cpup_simple_args {
2686+ int *errp;
2687+ struct dentry *dentry;
2688+ aufs_bindex_t bdst;
2689+ loff_t len;
2690+ unsigned int flags;
2691+};
2692+
2693+static void au_call_cpup_simple(void *args)
2694+{
2695+ struct au_cpup_simple_args *a = args;
2696+ *a->errp = au_cpup_simple(a->dentry, a->bdst, a->len, a->flags);
2697+}
2698+
2699+int au_sio_cpup_simple(struct dentry *dentry, aufs_bindex_t bdst, loff_t len,
2700+ unsigned int flags)
2701+{
2702+ int err, wkq_err;
2703+ unsigned char do_sio;
2704+ struct dentry *parent;
2705+ struct inode *h_dir;
2706+
2707+ parent = dget_parent(dentry);
2708+ h_dir = au_h_iptr(parent->d_inode, bdst);
2709+ do_sio = !!au_test_h_perm_sio(h_dir, MAY_EXEC | MAY_WRITE);
2710+ if (!do_sio) {
2711+ /*
2712+ * testing CAP_MKNOD is for generic fs,
2713+ * but CAP_FSETID is for xfs only, currently.
2714+ */
2715+ umode_t mode = dentry->d_inode->i_mode;
2716+ do_sio = (((mode & (S_IFCHR | S_IFBLK))
2717+ && !capable(CAP_MKNOD))
2718+ || ((mode & (S_ISUID | S_ISGID))
2719+ && !capable(CAP_FSETID)));
2720+ }
2721+ if (!do_sio)
2722+ err = au_cpup_simple(dentry, bdst, len, flags);
2723+ else {
2724+ struct au_cpup_simple_args args = {
2725+ .errp = &err,
2726+ .dentry = dentry,
2727+ .bdst = bdst,
2728+ .len = len,
2729+ .flags = flags
2730+ };
2731+ wkq_err = au_wkq_wait(au_call_cpup_simple, &args);
2732+ if (unlikely(wkq_err))
2733+ err = wkq_err;
2734+ }
2735+
2736+ dput(parent);
2737+ return err;
2738+}
2739+
2740+/* ---------------------------------------------------------------------- */
2741+
2742+/*
2743+ * copyup the deleted file for writing.
2744+ */
2745+static int au_do_cpup_wh(struct dentry *dentry, aufs_bindex_t bdst,
2746+ struct dentry *wh_dentry, struct file *file,
2747+ loff_t len)
2748+{
2749+ int err;
2750+ aufs_bindex_t bstart;
2751+ struct au_dinfo *dinfo;
2752+ struct dentry *h_d_dst, *h_d_start;
4a4d8108 2753+ struct au_hdentry *hdp;
1facf9fc 2754+
2755+ dinfo = au_di(dentry);
1308ab2a 2756+ AuRwMustWriteLock(&dinfo->di_rwsem);
2757+
1facf9fc 2758+ bstart = dinfo->di_bstart;
4a4d8108
AM
2759+ hdp = dinfo->di_hdentry;
2760+ h_d_dst = hdp[0 + bdst].hd_dentry;
1facf9fc 2761+ dinfo->di_bstart = bdst;
4a4d8108 2762+ hdp[0 + bdst].hd_dentry = wh_dentry;
027c5e7a
AM
2763+ if (file) {
2764+ h_d_start = hdp[0 + bstart].hd_dentry;
4a4d8108 2765+ hdp[0 + bstart].hd_dentry = au_hf_top(file)->f_dentry;
027c5e7a 2766+ }
1facf9fc 2767+ err = au_cpup_single(dentry, bdst, bstart, len, !AuCpup_DTIME,
2768+ /*h_parent*/NULL);
027c5e7a
AM
2769+ if (file) {
2770+ if (!err)
2771+ err = au_reopen_nondir(file);
4a4d8108 2772+ hdp[0 + bstart].hd_dentry = h_d_start;
1facf9fc 2773+ }
4a4d8108 2774+ hdp[0 + bdst].hd_dentry = h_d_dst;
1facf9fc 2775+ dinfo->di_bstart = bstart;
2776+
2777+ return err;
2778+}
2779+
2780+static int au_cpup_wh(struct dentry *dentry, aufs_bindex_t bdst, loff_t len,
2781+ struct file *file)
2782+{
2783+ int err;
2784+ struct au_dtime dt;
2785+ struct dentry *parent, *h_parent, *wh_dentry;
2786+ struct au_branch *br;
2787+ struct path h_path;
2788+
2789+ br = au_sbr(dentry->d_sb, bdst);
2790+ parent = dget_parent(dentry);
2791+ h_parent = au_h_dptr(parent, bdst);
2792+ wh_dentry = au_whtmp_lkup(h_parent, br, &dentry->d_name);
2793+ err = PTR_ERR(wh_dentry);
2794+ if (IS_ERR(wh_dentry))
2795+ goto out;
2796+
2797+ h_path.dentry = h_parent;
2798+ h_path.mnt = br->br_mnt;
2799+ au_dtime_store(&dt, parent, &h_path);
2800+ err = au_do_cpup_wh(dentry, bdst, wh_dentry, file, len);
2801+ if (unlikely(err))
2802+ goto out_wh;
2803+
2804+ dget(wh_dentry);
2805+ h_path.dentry = wh_dentry;
4a4d8108
AM
2806+ if (!S_ISDIR(wh_dentry->d_inode->i_mode))
2807+ err = vfsub_unlink(h_parent->d_inode, &h_path, /*force*/0);
2808+ else
2809+ err = vfsub_rmdir(h_parent->d_inode, &h_path);
1facf9fc 2810+ if (unlikely(err)) {
2811+ AuIOErr("failed remove copied-up tmp file %.*s(%d)\n",
2812+ AuDLNPair(wh_dentry), err);
2813+ err = -EIO;
2814+ }
2815+ au_dtime_revert(&dt);
2816+ au_set_hi_wh(dentry->d_inode, bdst, wh_dentry);
2817+
4f0767ce 2818+out_wh:
1facf9fc 2819+ dput(wh_dentry);
4f0767ce 2820+out:
1facf9fc 2821+ dput(parent);
2822+ return err;
2823+}
2824+
2825+struct au_cpup_wh_args {
2826+ int *errp;
2827+ struct dentry *dentry;
2828+ aufs_bindex_t bdst;
2829+ loff_t len;
2830+ struct file *file;
2831+};
2832+
2833+static void au_call_cpup_wh(void *args)
2834+{
2835+ struct au_cpup_wh_args *a = args;
2836+ *a->errp = au_cpup_wh(a->dentry, a->bdst, a->len, a->file);
2837+}
2838+
2839+int au_sio_cpup_wh(struct dentry *dentry, aufs_bindex_t bdst, loff_t len,
2840+ struct file *file)
2841+{
2842+ int err, wkq_err;
2843+ struct dentry *parent, *h_orph, *h_parent, *h_dentry;
2844+ struct inode *dir, *h_dir, *h_tmpdir, *h_inode;
2845+ struct au_wbr *wbr;
2846+
2847+ parent = dget_parent(dentry);
2848+ dir = parent->d_inode;
2849+ h_orph = NULL;
2850+ h_parent = NULL;
2851+ h_dir = au_igrab(au_h_iptr(dir, bdst));
2852+ h_tmpdir = h_dir;
2853+ if (!h_dir->i_nlink) {
2854+ wbr = au_sbr(dentry->d_sb, bdst)->br_wbr;
2855+ h_orph = wbr->wbr_orph;
2856+
2857+ h_parent = dget(au_h_dptr(parent, bdst));
1facf9fc 2858+ au_set_h_dptr(parent, bdst, dget(h_orph));
2859+ h_tmpdir = h_orph->d_inode;
1facf9fc 2860+ au_set_h_iptr(dir, bdst, au_igrab(h_tmpdir), /*flags*/0);
2861+
2862+ /* this temporary unlock is safe */
2863+ if (file)
4a4d8108 2864+ h_dentry = au_hf_top(file)->f_dentry;
1facf9fc 2865+ else
2866+ h_dentry = au_h_dptr(dentry, au_dbstart(dentry));
2867+ h_inode = h_dentry->d_inode;
2868+ IMustLock(h_inode);
2869+ mutex_unlock(&h_inode->i_mutex);
dece6358 2870+ mutex_lock_nested(&h_tmpdir->i_mutex, AuLsc_I_PARENT3);
1facf9fc 2871+ mutex_lock_nested(&h_inode->i_mutex, AuLsc_I_CHILD);
4a4d8108 2872+ /* todo: au_h_open_pre()? */
1facf9fc 2873+ }
2874+
2875+ if (!au_test_h_perm_sio(h_tmpdir, MAY_EXEC | MAY_WRITE))
2876+ err = au_cpup_wh(dentry, bdst, len, file);
2877+ else {
2878+ struct au_cpup_wh_args args = {
2879+ .errp = &err,
2880+ .dentry = dentry,
2881+ .bdst = bdst,
2882+ .len = len,
2883+ .file = file
2884+ };
2885+ wkq_err = au_wkq_wait(au_call_cpup_wh, &args);
2886+ if (unlikely(wkq_err))
2887+ err = wkq_err;
2888+ }
2889+
2890+ if (h_orph) {
2891+ mutex_unlock(&h_tmpdir->i_mutex);
4a4d8108 2892+ /* todo: au_h_open_post()? */
1facf9fc 2893+ au_set_h_iptr(dir, bdst, au_igrab(h_dir), /*flags*/0);
1facf9fc 2894+ au_set_h_dptr(parent, bdst, h_parent);
2895+ }
2896+ iput(h_dir);
2897+ dput(parent);
2898+
2899+ return err;
2900+}
2901+
2902+/* ---------------------------------------------------------------------- */
2903+
2904+/*
2905+ * generic routine for both of copy-up and copy-down.
2906+ */
2907+/* cf. revalidate function in file.c */
2908+int au_cp_dirs(struct dentry *dentry, aufs_bindex_t bdst,
2909+ int (*cp)(struct dentry *dentry, aufs_bindex_t bdst,
2910+ struct dentry *h_parent, void *arg),
2911+ void *arg)
2912+{
2913+ int err;
2914+ struct au_pin pin;
2915+ struct dentry *d, *parent, *h_parent, *real_parent;
2916+
2917+ err = 0;
2918+ parent = dget_parent(dentry);
2919+ if (IS_ROOT(parent))
2920+ goto out;
2921+
2922+ au_pin_init(&pin, dentry, bdst, AuLsc_DI_PARENT2, AuLsc_I_PARENT2,
2923+ au_opt_udba(dentry->d_sb), AuPin_MNT_WRITE);
2924+
2925+ /* do not use au_dpage */
2926+ real_parent = parent;
2927+ while (1) {
2928+ dput(parent);
2929+ parent = dget_parent(dentry);
2930+ h_parent = au_h_dptr(parent, bdst);
2931+ if (h_parent)
2932+ goto out; /* success */
2933+
2934+ /* find top dir which is necessary to cpup */
2935+ do {
2936+ d = parent;
2937+ dput(parent);
2938+ parent = dget_parent(d);
2939+ di_read_lock_parent3(parent, !AuLock_IR);
2940+ h_parent = au_h_dptr(parent, bdst);
2941+ di_read_unlock(parent, !AuLock_IR);
2942+ } while (!h_parent);
2943+
2944+ if (d != real_parent)
2945+ di_write_lock_child3(d);
2946+
2947+ /* somebody else might create while we were sleeping */
2948+ if (!au_h_dptr(d, bdst) || !au_h_dptr(d, bdst)->d_inode) {
2949+ if (au_h_dptr(d, bdst))
2950+ au_update_dbstart(d);
2951+
2952+ au_pin_set_dentry(&pin, d);
2953+ err = au_do_pin(&pin);
2954+ if (!err) {
2955+ err = cp(d, bdst, h_parent, arg);
2956+ au_unpin(&pin);
2957+ }
2958+ }
2959+
2960+ if (d != real_parent)
2961+ di_write_unlock(d);
2962+ if (unlikely(err))
2963+ break;
2964+ }
2965+
4f0767ce 2966+out:
1facf9fc 2967+ dput(parent);
2968+ return err;
2969+}
2970+
2971+static int au_cpup_dir(struct dentry *dentry, aufs_bindex_t bdst,
2972+ struct dentry *h_parent __maybe_unused ,
2973+ void *arg __maybe_unused)
2974+{
2975+ return au_sio_cpup_simple(dentry, bdst, -1, AuCpup_DTIME);
2976+}
2977+
2978+int au_cpup_dirs(struct dentry *dentry, aufs_bindex_t bdst)
2979+{
2980+ return au_cp_dirs(dentry, bdst, au_cpup_dir, NULL);
2981+}
2982+
2983+int au_test_and_cpup_dirs(struct dentry *dentry, aufs_bindex_t bdst)
2984+{
2985+ int err;
2986+ struct dentry *parent;
2987+ struct inode *dir;
2988+
2989+ parent = dget_parent(dentry);
2990+ dir = parent->d_inode;
2991+ err = 0;
2992+ if (au_h_iptr(dir, bdst))
2993+ goto out;
2994+
2995+ di_read_unlock(parent, AuLock_IR);
2996+ di_write_lock_parent(parent);
2997+ /* someone else might change our inode while we were sleeping */
2998+ if (!au_h_iptr(dir, bdst))
2999+ err = au_cpup_dirs(dentry, bdst);
3000+ di_downgrade_lock(parent, AuLock_IR);
3001+
4f0767ce 3002+out:
1facf9fc 3003+ dput(parent);
3004+ return err;
3005+}
7f207e10
AM
3006diff -urN /usr/share/empty/fs/aufs/cpup.h linux/fs/aufs/cpup.h
3007--- /usr/share/empty/fs/aufs/cpup.h 1970-01-01 01:00:00.000000000 +0100
2cbb1c4b 3008+++ linux/fs/aufs/cpup.h 2011-07-11 11:34:24.071331673 +0200
7f207e10 3009@@ -0,0 +1,83 @@
1facf9fc 3010+/*
027c5e7a 3011+ * Copyright (C) 2005-2011 Junjiro R. Okajima
1facf9fc 3012+ *
3013+ * This program, aufs is free software; you can redistribute it and/or modify
3014+ * it under the terms of the GNU General Public License as published by
3015+ * the Free Software Foundation; either version 2 of the License, or
3016+ * (at your option) any later version.
dece6358
AM
3017+ *
3018+ * This program is distributed in the hope that it will be useful,
3019+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
3020+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
3021+ * GNU General Public License for more details.
3022+ *
3023+ * You should have received a copy of the GNU General Public License
3024+ * along with this program; if not, write to the Free Software
3025+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 3026+ */
3027+
3028+/*
3029+ * copy-up/down functions
3030+ */
3031+
3032+#ifndef __AUFS_CPUP_H__
3033+#define __AUFS_CPUP_H__
3034+
3035+#ifdef __KERNEL__
3036+
dece6358
AM
3037+#include <linux/path.h>
3038+#include <linux/time.h>
1facf9fc 3039+#include <linux/aufs_type.h>
3040+
dece6358
AM
3041+struct inode;
3042+struct file;
3043+
1facf9fc 3044+void au_cpup_attr_flags(struct inode *dst, struct inode *src);
3045+void au_cpup_attr_timesizes(struct inode *inode);
3046+void au_cpup_attr_nlink(struct inode *inode, int force);
3047+void au_cpup_attr_changeable(struct inode *inode);
3048+void au_cpup_igen(struct inode *inode, struct inode *h_inode);
3049+void au_cpup_attr_all(struct inode *inode, int force);
3050+
3051+/* ---------------------------------------------------------------------- */
3052+
3053+/* cpup flags */
3054+#define AuCpup_DTIME 1 /* do dtime_store/revert */
3055+#define AuCpup_KEEPLINO (1 << 1) /* do not clear the lower xino,
3056+ for link(2) */
3057+#define au_ftest_cpup(flags, name) ((flags) & AuCpup_##name)
7f207e10
AM
3058+#define au_fset_cpup(flags, name) \
3059+ do { (flags) |= AuCpup_##name; } while (0)
3060+#define au_fclr_cpup(flags, name) \
3061+ do { (flags) &= ~AuCpup_##name; } while (0)
1facf9fc 3062+
3063+int au_copy_file(struct file *dst, struct file *src, loff_t len);
3064+int au_sio_cpup_single(struct dentry *dentry, aufs_bindex_t bdst,
3065+ aufs_bindex_t bsrc, loff_t len, unsigned int flags,
3066+ struct dentry *dst_parent);
3067+int au_sio_cpup_simple(struct dentry *dentry, aufs_bindex_t bdst, loff_t len,
3068+ unsigned int flags);
3069+int au_sio_cpup_wh(struct dentry *dentry, aufs_bindex_t bdst, loff_t len,
3070+ struct file *file);
3071+
3072+int au_cp_dirs(struct dentry *dentry, aufs_bindex_t bdst,
3073+ int (*cp)(struct dentry *dentry, aufs_bindex_t bdst,
3074+ struct dentry *h_parent, void *arg),
3075+ void *arg);
3076+int au_cpup_dirs(struct dentry *dentry, aufs_bindex_t bdst);
3077+int au_test_and_cpup_dirs(struct dentry *dentry, aufs_bindex_t bdst);
3078+
3079+/* ---------------------------------------------------------------------- */
3080+
3081+/* keep timestamps when copyup */
3082+struct au_dtime {
3083+ struct dentry *dt_dentry;
3084+ struct path dt_h_path;
3085+ struct timespec dt_atime, dt_mtime;
3086+};
3087+void au_dtime_store(struct au_dtime *dt, struct dentry *dentry,
3088+ struct path *h_path);
3089+void au_dtime_revert(struct au_dtime *dt);
3090+
3091+#endif /* __KERNEL__ */
3092+#endif /* __AUFS_CPUP_H__ */
7f207e10
AM
3093diff -urN /usr/share/empty/fs/aufs/dbgaufs.c linux/fs/aufs/dbgaufs.c
3094--- /usr/share/empty/fs/aufs/dbgaufs.c 1970-01-01 01:00:00.000000000 +0100
2cbb1c4b 3095+++ linux/fs/aufs/dbgaufs.c 2011-07-11 11:34:24.071331673 +0200
4a4d8108 3096@@ -0,0 +1,334 @@
1facf9fc 3097+/*
027c5e7a 3098+ * Copyright (C) 2005-2011 Junjiro R. Okajima
1facf9fc 3099+ *
3100+ * This program, aufs is free software; you can redistribute it and/or modify
3101+ * it under the terms of the GNU General Public License as published by
3102+ * the Free Software Foundation; either version 2 of the License, or
3103+ * (at your option) any later version.
dece6358
AM
3104+ *
3105+ * This program is distributed in the hope that it will be useful,
3106+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
3107+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
3108+ * GNU General Public License for more details.
3109+ *
3110+ * You should have received a copy of the GNU General Public License
3111+ * along with this program; if not, write to the Free Software
3112+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 3113+ */
3114+
3115+/*
3116+ * debugfs interface
3117+ */
3118+
3119+#include <linux/debugfs.h>
3120+#include "aufs.h"
3121+
3122+#ifndef CONFIG_SYSFS
3123+#error DEBUG_FS depends upon SYSFS
3124+#endif
3125+
3126+static struct dentry *dbgaufs;
3127+static const mode_t dbgaufs_mode = S_IRUSR | S_IRGRP | S_IROTH;
3128+
3129+/* 20 is max digits length of ulong 64 */
3130+struct dbgaufs_arg {
3131+ int n;
3132+ char a[20 * 4];
3133+};
3134+
3135+/*
3136+ * common function for all XINO files
3137+ */
3138+static int dbgaufs_xi_release(struct inode *inode __maybe_unused,
3139+ struct file *file)
3140+{
3141+ kfree(file->private_data);
3142+ return 0;
3143+}
3144+
3145+static int dbgaufs_xi_open(struct file *xf, struct file *file, int do_fcnt)
3146+{
3147+ int err;
3148+ struct kstat st;
3149+ struct dbgaufs_arg *p;
3150+
3151+ err = -ENOMEM;
3152+ p = kmalloc(sizeof(*p), GFP_NOFS);
3153+ if (unlikely(!p))
3154+ goto out;
3155+
3156+ err = 0;
3157+ p->n = 0;
3158+ file->private_data = p;
3159+ if (!xf)
3160+ goto out;
3161+
3162+ err = vfs_getattr(xf->f_vfsmnt, xf->f_dentry, &st);
3163+ if (!err) {
3164+ if (do_fcnt)
3165+ p->n = snprintf
3166+ (p->a, sizeof(p->a), "%ld, %llux%lu %lld\n",
3167+ (long)file_count(xf), st.blocks, st.blksize,
3168+ (long long)st.size);
3169+ else
3170+ p->n = snprintf(p->a, sizeof(p->a), "%llux%lu %lld\n",
3171+ st.blocks, st.blksize,
3172+ (long long)st.size);
3173+ AuDebugOn(p->n >= sizeof(p->a));
3174+ } else {
3175+ p->n = snprintf(p->a, sizeof(p->a), "err %d\n", err);
3176+ err = 0;
3177+ }
3178+
4f0767ce 3179+out:
1facf9fc 3180+ return err;
3181+
3182+}
3183+
3184+static ssize_t dbgaufs_xi_read(struct file *file, char __user *buf,
3185+ size_t count, loff_t *ppos)
3186+{
3187+ struct dbgaufs_arg *p;
3188+
3189+ p = file->private_data;
3190+ return simple_read_from_buffer(buf, count, ppos, p->a, p->n);
3191+}
3192+
3193+/* ---------------------------------------------------------------------- */
3194+
3195+static int dbgaufs_xib_open(struct inode *inode, struct file *file)
3196+{
3197+ int err;
3198+ struct au_sbinfo *sbinfo;
3199+ struct super_block *sb;
3200+
3201+ sbinfo = inode->i_private;
3202+ sb = sbinfo->si_sb;
3203+ si_noflush_read_lock(sb);
3204+ err = dbgaufs_xi_open(sbinfo->si_xib, file, /*do_fcnt*/0);
3205+ si_read_unlock(sb);
3206+ return err;
3207+}
3208+
3209+static const struct file_operations dbgaufs_xib_fop = {
4a4d8108 3210+ .owner = THIS_MODULE,
1facf9fc 3211+ .open = dbgaufs_xib_open,
3212+ .release = dbgaufs_xi_release,
3213+ .read = dbgaufs_xi_read
3214+};
3215+
3216+/* ---------------------------------------------------------------------- */
3217+
3218+#define DbgaufsXi_PREFIX "xi"
3219+
3220+static int dbgaufs_xino_open(struct inode *inode, struct file *file)
3221+{
3222+ int err;
3223+ long l;
3224+ struct au_sbinfo *sbinfo;
3225+ struct super_block *sb;
3226+ struct file *xf;
3227+ struct qstr *name;
3228+
3229+ err = -ENOENT;
3230+ xf = NULL;
3231+ name = &file->f_dentry->d_name;
3232+ if (unlikely(name->len < sizeof(DbgaufsXi_PREFIX)
3233+ || memcmp(name->name, DbgaufsXi_PREFIX,
3234+ sizeof(DbgaufsXi_PREFIX) - 1)))
3235+ goto out;
3236+ err = strict_strtol(name->name + sizeof(DbgaufsXi_PREFIX) - 1, 10, &l);
3237+ if (unlikely(err))
3238+ goto out;
3239+
3240+ sbinfo = inode->i_private;
3241+ sb = sbinfo->si_sb;
3242+ si_noflush_read_lock(sb);
3243+ if (l <= au_sbend(sb)) {
3244+ xf = au_sbr(sb, (aufs_bindex_t)l)->br_xino.xi_file;
3245+ err = dbgaufs_xi_open(xf, file, /*do_fcnt*/1);
3246+ } else
3247+ err = -ENOENT;
3248+ si_read_unlock(sb);
3249+
4f0767ce 3250+out:
1facf9fc 3251+ return err;
3252+}
3253+
3254+static const struct file_operations dbgaufs_xino_fop = {
4a4d8108 3255+ .owner = THIS_MODULE,
1facf9fc 3256+ .open = dbgaufs_xino_open,
3257+ .release = dbgaufs_xi_release,
3258+ .read = dbgaufs_xi_read
3259+};
3260+
3261+void dbgaufs_brs_del(struct super_block *sb, aufs_bindex_t bindex)
3262+{
3263+ aufs_bindex_t bend;
3264+ struct au_branch *br;
3265+ struct au_xino_file *xi;
3266+
3267+ if (!au_sbi(sb)->si_dbgaufs)
3268+ return;
3269+
3270+ bend = au_sbend(sb);
3271+ for (; bindex <= bend; bindex++) {
3272+ br = au_sbr(sb, bindex);
3273+ xi = &br->br_xino;
3274+ if (xi->xi_dbgaufs) {
3275+ debugfs_remove(xi->xi_dbgaufs);
3276+ xi->xi_dbgaufs = NULL;
3277+ }
3278+ }
3279+}
3280+
3281+void dbgaufs_brs_add(struct super_block *sb, aufs_bindex_t bindex)
3282+{
3283+ struct au_sbinfo *sbinfo;
3284+ struct dentry *parent;
3285+ struct au_branch *br;
3286+ struct au_xino_file *xi;
3287+ aufs_bindex_t bend;
3288+ char name[sizeof(DbgaufsXi_PREFIX) + 5]; /* "xi" bindex NULL */
3289+
3290+ sbinfo = au_sbi(sb);
3291+ parent = sbinfo->si_dbgaufs;
3292+ if (!parent)
3293+ return;
3294+
3295+ bend = au_sbend(sb);
3296+ for (; bindex <= bend; bindex++) {
3297+ snprintf(name, sizeof(name), DbgaufsXi_PREFIX "%d", bindex);
3298+ br = au_sbr(sb, bindex);
3299+ xi = &br->br_xino;
3300+ AuDebugOn(xi->xi_dbgaufs);
3301+ xi->xi_dbgaufs = debugfs_create_file(name, dbgaufs_mode, parent,
3302+ sbinfo, &dbgaufs_xino_fop);
3303+ /* ignore an error */
3304+ if (unlikely(!xi->xi_dbgaufs))
3305+ AuWarn1("failed %s under debugfs\n", name);
3306+ }
3307+}
3308+
3309+/* ---------------------------------------------------------------------- */
3310+
3311+#ifdef CONFIG_AUFS_EXPORT
3312+static int dbgaufs_xigen_open(struct inode *inode, struct file *file)
3313+{
3314+ int err;
3315+ struct au_sbinfo *sbinfo;
3316+ struct super_block *sb;
3317+
3318+ sbinfo = inode->i_private;
3319+ sb = sbinfo->si_sb;
3320+ si_noflush_read_lock(sb);
3321+ err = dbgaufs_xi_open(sbinfo->si_xigen, file, /*do_fcnt*/0);
3322+ si_read_unlock(sb);
3323+ return err;
3324+}
3325+
3326+static const struct file_operations dbgaufs_xigen_fop = {
4a4d8108 3327+ .owner = THIS_MODULE,
1facf9fc 3328+ .open = dbgaufs_xigen_open,
3329+ .release = dbgaufs_xi_release,
3330+ .read = dbgaufs_xi_read
3331+};
3332+
3333+static int dbgaufs_xigen_init(struct au_sbinfo *sbinfo)
3334+{
3335+ int err;
3336+
dece6358
AM
3337+ /*
3338+ * This function is a dynamic '__init' fucntion actually,
3339+ * so the tiny check for si_rwsem is unnecessary.
3340+ */
3341+ /* AuRwMustWriteLock(&sbinfo->si_rwsem); */
3342+
1facf9fc 3343+ err = -EIO;
3344+ sbinfo->si_dbgaufs_xigen = debugfs_create_file
3345+ ("xigen", dbgaufs_mode, sbinfo->si_dbgaufs, sbinfo,
3346+ &dbgaufs_xigen_fop);
3347+ if (sbinfo->si_dbgaufs_xigen)
3348+ err = 0;
3349+
3350+ return err;
3351+}
3352+#else
3353+static int dbgaufs_xigen_init(struct au_sbinfo *sbinfo)
3354+{
3355+ return 0;
3356+}
3357+#endif /* CONFIG_AUFS_EXPORT */
3358+
3359+/* ---------------------------------------------------------------------- */
3360+
3361+void dbgaufs_si_fin(struct au_sbinfo *sbinfo)
3362+{
dece6358
AM
3363+ /*
3364+ * This function is a dynamic '__init' fucntion actually,
3365+ * so the tiny check for si_rwsem is unnecessary.
3366+ */
3367+ /* AuRwMustWriteLock(&sbinfo->si_rwsem); */
3368+
1facf9fc 3369+ debugfs_remove_recursive(sbinfo->si_dbgaufs);
3370+ sbinfo->si_dbgaufs = NULL;
3371+ kobject_put(&sbinfo->si_kobj);
3372+}
3373+
3374+int dbgaufs_si_init(struct au_sbinfo *sbinfo)
3375+{
3376+ int err;
3377+ char name[SysaufsSiNameLen];
3378+
dece6358
AM
3379+ /*
3380+ * This function is a dynamic '__init' fucntion actually,
3381+ * so the tiny check for si_rwsem is unnecessary.
3382+ */
3383+ /* AuRwMustWriteLock(&sbinfo->si_rwsem); */
3384+
1facf9fc 3385+ err = -ENOENT;
3386+ if (!dbgaufs) {
3387+ AuErr1("/debug/aufs is uninitialized\n");
3388+ goto out;
3389+ }
3390+
3391+ err = -EIO;
3392+ sysaufs_name(sbinfo, name);
3393+ sbinfo->si_dbgaufs = debugfs_create_dir(name, dbgaufs);
3394+ if (unlikely(!sbinfo->si_dbgaufs))
3395+ goto out;
3396+ kobject_get(&sbinfo->si_kobj);
3397+
3398+ sbinfo->si_dbgaufs_xib = debugfs_create_file
3399+ ("xib", dbgaufs_mode, sbinfo->si_dbgaufs, sbinfo,
3400+ &dbgaufs_xib_fop);
3401+ if (unlikely(!sbinfo->si_dbgaufs_xib))
3402+ goto out_dir;
3403+
3404+ err = dbgaufs_xigen_init(sbinfo);
3405+ if (!err)
3406+ goto out; /* success */
3407+
4f0767ce 3408+out_dir:
1facf9fc 3409+ dbgaufs_si_fin(sbinfo);
4f0767ce 3410+out:
1facf9fc 3411+ return err;
3412+}
3413+
3414+/* ---------------------------------------------------------------------- */
3415+
3416+void dbgaufs_fin(void)
3417+{
3418+ debugfs_remove(dbgaufs);
3419+}
3420+
3421+int __init dbgaufs_init(void)
3422+{
3423+ int err;
3424+
3425+ err = -EIO;
3426+ dbgaufs = debugfs_create_dir(AUFS_NAME, NULL);
3427+ if (dbgaufs)
3428+ err = 0;
3429+ return err;
3430+}
7f207e10
AM
3431diff -urN /usr/share/empty/fs/aufs/dbgaufs.h linux/fs/aufs/dbgaufs.h
3432--- /usr/share/empty/fs/aufs/dbgaufs.h 1970-01-01 01:00:00.000000000 +0100
2cbb1c4b 3433+++ linux/fs/aufs/dbgaufs.h 2011-07-11 11:34:24.071331673 +0200
4a4d8108 3434@@ -0,0 +1,52 @@
1facf9fc 3435+/*
027c5e7a 3436+ * Copyright (C) 2005-2011 Junjiro R. Okajima
1facf9fc 3437+ *
3438+ * This program, aufs is free software; you can redistribute it and/or modify
3439+ * it under the terms of the GNU General Public License as published by
3440+ * the Free Software Foundation; either version 2 of the License, or
3441+ * (at your option) any later version.
dece6358
AM
3442+ *
3443+ * This program is distributed in the hope that it will be useful,
3444+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
3445+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
3446+ * GNU General Public License for more details.
3447+ *
3448+ * You should have received a copy of the GNU General Public License
3449+ * along with this program; if not, write to the Free Software
3450+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 3451+ */
3452+
3453+/*
3454+ * debugfs interface
3455+ */
3456+
3457+#ifndef __DBGAUFS_H__
3458+#define __DBGAUFS_H__
3459+
3460+#ifdef __KERNEL__
3461+
dece6358 3462+#include <linux/init.h>
1facf9fc 3463+#include <linux/aufs_type.h>
3464+
dece6358 3465+struct super_block;
1facf9fc 3466+struct au_sbinfo;
dece6358 3467+
1facf9fc 3468+#ifdef CONFIG_DEBUG_FS
3469+/* dbgaufs.c */
3470+void dbgaufs_brs_del(struct super_block *sb, aufs_bindex_t bindex);
3471+void dbgaufs_brs_add(struct super_block *sb, aufs_bindex_t bindex);
3472+void dbgaufs_si_fin(struct au_sbinfo *sbinfo);
3473+int dbgaufs_si_init(struct au_sbinfo *sbinfo);
3474+void dbgaufs_fin(void);
3475+int __init dbgaufs_init(void);
1facf9fc 3476+#else
4a4d8108
AM
3477+AuStubVoid(dbgaufs_brs_del, struct super_block *sb, aufs_bindex_t bindex)
3478+AuStubVoid(dbgaufs_brs_add, struct super_block *sb, aufs_bindex_t bindex)
3479+AuStubVoid(dbgaufs_si_fin, struct au_sbinfo *sbinfo)
3480+AuStubInt0(dbgaufs_si_init, struct au_sbinfo *sbinfo)
3481+AuStubVoid(dbgaufs_fin, void)
3482+AuStubInt0(__init dbgaufs_init, void)
1facf9fc 3483+#endif /* CONFIG_DEBUG_FS */
3484+
3485+#endif /* __KERNEL__ */
3486+#endif /* __DBGAUFS_H__ */
7f207e10
AM
3487diff -urN /usr/share/empty/fs/aufs/dcsub.c linux/fs/aufs/dcsub.c
3488--- /usr/share/empty/fs/aufs/dcsub.c 1970-01-01 01:00:00.000000000 +0100
2cbb1c4b 3489+++ linux/fs/aufs/dcsub.c 2011-07-11 11:34:24.071331673 +0200
027c5e7a 3490@@ -0,0 +1,243 @@
1facf9fc 3491+/*
027c5e7a 3492+ * Copyright (C) 2005-2011 Junjiro R. Okajima
1facf9fc 3493+ *
3494+ * This program, aufs is free software; you can redistribute it and/or modify
3495+ * it under the terms of the GNU General Public License as published by
3496+ * the Free Software Foundation; either version 2 of the License, or
3497+ * (at your option) any later version.
dece6358
AM
3498+ *
3499+ * This program is distributed in the hope that it will be useful,
3500+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
3501+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
3502+ * GNU General Public License for more details.
3503+ *
3504+ * You should have received a copy of the GNU General Public License
3505+ * along with this program; if not, write to the Free Software
3506+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 3507+ */
3508+
3509+/*
3510+ * sub-routines for dentry cache
3511+ */
3512+
3513+#include "aufs.h"
3514+
3515+static void au_dpage_free(struct au_dpage *dpage)
3516+{
3517+ int i;
3518+ struct dentry **p;
3519+
3520+ p = dpage->dentries;
3521+ for (i = 0; i < dpage->ndentry; i++)
3522+ dput(*p++);
3523+ free_page((unsigned long)dpage->dentries);
3524+}
3525+
3526+int au_dpages_init(struct au_dcsub_pages *dpages, gfp_t gfp)
3527+{
3528+ int err;
3529+ void *p;
3530+
3531+ err = -ENOMEM;
3532+ dpages->dpages = kmalloc(sizeof(*dpages->dpages), gfp);
3533+ if (unlikely(!dpages->dpages))
3534+ goto out;
3535+
3536+ p = (void *)__get_free_page(gfp);
3537+ if (unlikely(!p))
3538+ goto out_dpages;
3539+
3540+ dpages->dpages[0].ndentry = 0;
3541+ dpages->dpages[0].dentries = p;
3542+ dpages->ndpage = 1;
3543+ return 0; /* success */
3544+
4f0767ce 3545+out_dpages:
1facf9fc 3546+ kfree(dpages->dpages);
4f0767ce 3547+out:
1facf9fc 3548+ return err;
3549+}
3550+
3551+void au_dpages_free(struct au_dcsub_pages *dpages)
3552+{
3553+ int i;
3554+ struct au_dpage *p;
3555+
3556+ p = dpages->dpages;
3557+ for (i = 0; i < dpages->ndpage; i++)
3558+ au_dpage_free(p++);
3559+ kfree(dpages->dpages);
3560+}
3561+
3562+static int au_dpages_append(struct au_dcsub_pages *dpages,
3563+ struct dentry *dentry, gfp_t gfp)
3564+{
3565+ int err, sz;
3566+ struct au_dpage *dpage;
3567+ void *p;
3568+
3569+ dpage = dpages->dpages + dpages->ndpage - 1;
3570+ sz = PAGE_SIZE / sizeof(dentry);
3571+ if (unlikely(dpage->ndentry >= sz)) {
3572+ AuLabel(new dpage);
3573+ err = -ENOMEM;
3574+ sz = dpages->ndpage * sizeof(*dpages->dpages);
3575+ p = au_kzrealloc(dpages->dpages, sz,
3576+ sz + sizeof(*dpages->dpages), gfp);
3577+ if (unlikely(!p))
3578+ goto out;
3579+
3580+ dpages->dpages = p;
3581+ dpage = dpages->dpages + dpages->ndpage;
3582+ p = (void *)__get_free_page(gfp);
3583+ if (unlikely(!p))
3584+ goto out;
3585+
3586+ dpage->ndentry = 0;
3587+ dpage->dentries = p;
3588+ dpages->ndpage++;
3589+ }
3590+
027c5e7a
AM
3591+ AuDebugOn(!dentry->d_count);
3592+ dpage->dentries[dpage->ndentry++] = dget_dlock(dentry);
1facf9fc 3593+ return 0; /* success */
3594+
4f0767ce 3595+out:
1facf9fc 3596+ return err;
3597+}
3598+
3599+int au_dcsub_pages(struct au_dcsub_pages *dpages, struct dentry *root,
3600+ au_dpages_test test, void *arg)
3601+{
3602+ int err;
027c5e7a 3603+ struct dentry *this_parent;
1facf9fc 3604+ struct list_head *next;
3605+ struct super_block *sb = root->d_sb;
3606+
3607+ err = 0;
027c5e7a
AM
3608+ write_seqlock(&rename_lock);
3609+ this_parent = root;
3610+ spin_lock(&this_parent->d_lock);
4f0767ce 3611+repeat:
1facf9fc 3612+ next = this_parent->d_subdirs.next;
4f0767ce 3613+resume:
1facf9fc 3614+ if (this_parent->d_sb == sb
3615+ && !IS_ROOT(this_parent)
027c5e7a
AM
3616+ && au_di(this_parent)
3617+ && this_parent->d_count
1facf9fc 3618+ && (!test || test(this_parent, arg))) {
3619+ err = au_dpages_append(dpages, this_parent, GFP_ATOMIC);
3620+ if (unlikely(err))
3621+ goto out;
3622+ }
3623+
3624+ while (next != &this_parent->d_subdirs) {
3625+ struct list_head *tmp = next;
3626+ struct dentry *dentry = list_entry(tmp, struct dentry,
3627+ d_u.d_child);
027c5e7a 3628+
1facf9fc 3629+ next = tmp->next;
027c5e7a
AM
3630+ spin_lock_nested(&dentry->d_lock, DENTRY_D_LOCK_NESTED);
3631+ if (dentry->d_count) {
3632+ if (!list_empty(&dentry->d_subdirs)) {
3633+ spin_unlock(&this_parent->d_lock);
3634+ spin_release(&dentry->d_lock.dep_map, 1,
3635+ _RET_IP_);
3636+ this_parent = dentry;
3637+ spin_acquire(&this_parent->d_lock.dep_map, 0, 1,
3638+ _RET_IP_);
3639+ goto repeat;
3640+ }
3641+ if (dentry->d_sb == sb
3642+ && au_di(dentry)
3643+ && (!test || test(dentry, arg)))
3644+ err = au_dpages_append(dpages, dentry,
3645+ GFP_ATOMIC);
1facf9fc 3646+ }
027c5e7a
AM
3647+ spin_unlock(&dentry->d_lock);
3648+ if (unlikely(err))
3649+ goto out;
1facf9fc 3650+ }
3651+
3652+ if (this_parent != root) {
027c5e7a
AM
3653+ struct dentry *tmp;
3654+ struct dentry *child;
3655+
3656+ tmp = this_parent->d_parent;
3657+ rcu_read_lock();
3658+ spin_unlock(&this_parent->d_lock);
3659+ child = this_parent;
3660+ this_parent = tmp;
3661+ spin_lock(&this_parent->d_lock);
3662+ rcu_read_unlock();
3663+ next = child->d_u.d_child.next;
1facf9fc 3664+ goto resume;
3665+ }
027c5e7a 3666+
4f0767ce 3667+out:
027c5e7a
AM
3668+ spin_unlock(&this_parent->d_lock);
3669+ write_sequnlock(&rename_lock);
1facf9fc 3670+ return err;
3671+}
3672+
3673+int au_dcsub_pages_rev(struct au_dcsub_pages *dpages, struct dentry *dentry,
3674+ int do_include, au_dpages_test test, void *arg)
3675+{
3676+ int err;
3677+
3678+ err = 0;
027c5e7a
AM
3679+ write_seqlock(&rename_lock);
3680+ spin_lock(&dentry->d_lock);
3681+ if (do_include
3682+ && dentry->d_count
3683+ && (!test || test(dentry, arg)))
1facf9fc 3684+ err = au_dpages_append(dpages, dentry, GFP_ATOMIC);
027c5e7a
AM
3685+ spin_unlock(&dentry->d_lock);
3686+ if (unlikely(err))
3687+ goto out;
3688+
3689+ /*
3690+ * vfsmount_lock is unnecessary since this is a traverse in a single
3691+ * mount
3692+ */
1facf9fc 3693+ while (!IS_ROOT(dentry)) {
027c5e7a
AM
3694+ dentry = dentry->d_parent; /* rename_lock is locked */
3695+ spin_lock(&dentry->d_lock);
3696+ if (dentry->d_count
3697+ && (!test || test(dentry, arg)))
1facf9fc 3698+ err = au_dpages_append(dpages, dentry, GFP_ATOMIC);
027c5e7a
AM
3699+ spin_unlock(&dentry->d_lock);
3700+ if (unlikely(err))
3701+ break;
1facf9fc 3702+ }
3703+
4f0767ce 3704+out:
027c5e7a 3705+ write_sequnlock(&rename_lock);
1facf9fc 3706+ return err;
3707+}
3708+
027c5e7a
AM
3709+static inline int au_dcsub_dpages_aufs(struct dentry *dentry, void *arg)
3710+{
3711+ return au_di(dentry) && dentry->d_sb == arg;
3712+}
3713+
3714+int au_dcsub_pages_rev_aufs(struct au_dcsub_pages *dpages,
3715+ struct dentry *dentry, int do_include)
3716+{
3717+ return au_dcsub_pages_rev(dpages, dentry, do_include,
3718+ au_dcsub_dpages_aufs, dentry->d_sb);
3719+}
3720+
4a4d8108 3721+int au_test_subdir(struct dentry *d1, struct dentry *d2)
1facf9fc 3722+{
4a4d8108
AM
3723+ struct path path[2] = {
3724+ {
3725+ .dentry = d1
3726+ },
3727+ {
3728+ .dentry = d2
3729+ }
3730+ };
1facf9fc 3731+
4a4d8108 3732+ return path_is_under(path + 0, path + 1);
1facf9fc 3733+}
7f207e10
AM
3734diff -urN /usr/share/empty/fs/aufs/dcsub.h linux/fs/aufs/dcsub.h
3735--- /usr/share/empty/fs/aufs/dcsub.h 1970-01-01 01:00:00.000000000 +0100
2cbb1c4b 3736+++ linux/fs/aufs/dcsub.h 2011-07-11 11:34:24.071331673 +0200
027c5e7a 3737@@ -0,0 +1,95 @@
1facf9fc 3738+/*
027c5e7a 3739+ * Copyright (C) 2005-2011 Junjiro R. Okajima
1facf9fc 3740+ *
3741+ * This program, aufs is free software; you can redistribute it and/or modify
3742+ * it under the terms of the GNU General Public License as published by
3743+ * the Free Software Foundation; either version 2 of the License, or
3744+ * (at your option) any later version.
dece6358
AM
3745+ *
3746+ * This program is distributed in the hope that it will be useful,
3747+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
3748+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
3749+ * GNU General Public License for more details.
3750+ *
3751+ * You should have received a copy of the GNU General Public License
3752+ * along with this program; if not, write to the Free Software
3753+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 3754+ */
3755+
3756+/*
3757+ * sub-routines for dentry cache
3758+ */
3759+
3760+#ifndef __AUFS_DCSUB_H__
3761+#define __AUFS_DCSUB_H__
3762+
3763+#ifdef __KERNEL__
3764+
7f207e10 3765+#include <linux/dcache.h>
027c5e7a 3766+#include <linux/fs.h>
dece6358
AM
3767+#include <linux/types.h>
3768+
3769+struct dentry;
1facf9fc 3770+
3771+struct au_dpage {
3772+ int ndentry;
3773+ struct dentry **dentries;
3774+};
3775+
3776+struct au_dcsub_pages {
3777+ int ndpage;
3778+ struct au_dpage *dpages;
3779+};
3780+
3781+/* ---------------------------------------------------------------------- */
3782+
7f207e10 3783+/* dcsub.c */
1facf9fc 3784+int au_dpages_init(struct au_dcsub_pages *dpages, gfp_t gfp);
3785+void au_dpages_free(struct au_dcsub_pages *dpages);
3786+typedef int (*au_dpages_test)(struct dentry *dentry, void *arg);
3787+int au_dcsub_pages(struct au_dcsub_pages *dpages, struct dentry *root,
3788+ au_dpages_test test, void *arg);
3789+int au_dcsub_pages_rev(struct au_dcsub_pages *dpages, struct dentry *dentry,
3790+ int do_include, au_dpages_test test, void *arg);
027c5e7a
AM
3791+int au_dcsub_pages_rev_aufs(struct au_dcsub_pages *dpages,
3792+ struct dentry *dentry, int do_include);
4a4d8108 3793+int au_test_subdir(struct dentry *d1, struct dentry *d2);
1facf9fc 3794+
7f207e10
AM
3795+/* ---------------------------------------------------------------------- */
3796+
027c5e7a
AM
3797+static inline int au_d_hashed_positive(struct dentry *d)
3798+{
3799+ int err;
3800+ struct inode *inode = d->d_inode;
3801+ err = 0;
3802+ if (unlikely(d_unhashed(d) || !inode || !inode->i_nlink))
3803+ err = -ENOENT;
3804+ return err;
3805+}
3806+
3807+static inline int au_d_alive(struct dentry *d)
3808+{
3809+ int err;
3810+ struct inode *inode;
3811+ err = 0;
3812+ if (!IS_ROOT(d))
3813+ err = au_d_hashed_positive(d);
3814+ else {
3815+ inode = d->d_inode;
3816+ if (unlikely(d_unlinked(d) || !inode || !inode->i_nlink))
3817+ err = -ENOENT;
3818+ }
3819+ return err;
3820+}
3821+
3822+static inline int au_alive_dir(struct dentry *d)
7f207e10 3823+{
027c5e7a
AM
3824+ int err;
3825+ err = au_d_alive(d);
3826+ if (unlikely(err || IS_DEADDIR(d->d_inode)))
3827+ err = -ENOENT;
3828+ return err;
7f207e10
AM
3829+}
3830+
1facf9fc 3831+#endif /* __KERNEL__ */
3832+#endif /* __AUFS_DCSUB_H__ */
7f207e10
AM
3833diff -urN /usr/share/empty/fs/aufs/debug.c linux/fs/aufs/debug.c
3834--- /usr/share/empty/fs/aufs/debug.c 1970-01-01 01:00:00.000000000 +0100
2cbb1c4b
JR
3835+++ linux/fs/aufs/debug.c 2011-07-11 11:34:24.071331673 +0200
3836@@ -0,0 +1,479 @@
1facf9fc 3837+/*
027c5e7a 3838+ * Copyright (C) 2005-2011 Junjiro R. Okajima
1facf9fc 3839+ *
3840+ * This program, aufs is free software; you can redistribute it and/or modify
3841+ * it under the terms of the GNU General Public License as published by
3842+ * the Free Software Foundation; either version 2 of the License, or
3843+ * (at your option) any later version.
dece6358
AM
3844+ *
3845+ * This program is distributed in the hope that it will be useful,
3846+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
3847+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
3848+ * GNU General Public License for more details.
3849+ *
3850+ * You should have received a copy of the GNU General Public License
3851+ * along with this program; if not, write to the Free Software
3852+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 3853+ */
3854+
3855+/*
3856+ * debug print functions
3857+ */
3858+
dece6358 3859+#include <linux/module.h>
7f207e10 3860+#include <linux/vt_kern.h>
1facf9fc 3861+#include "aufs.h"
3862+
3863+int aufs_debug;
3864+MODULE_PARM_DESC(debug, "debug print");
3865+module_param_named(debug, aufs_debug, int, S_IRUGO | S_IWUSR | S_IWGRP);
3866+
3867+char *au_plevel = KERN_DEBUG;
e49829fe
JR
3868+#define dpri(fmt, ...) do { \
3869+ if ((au_plevel \
3870+ && strcmp(au_plevel, KERN_DEBUG)) \
3871+ || au_debug_test()) \
3872+ printk("%s" fmt, au_plevel, ##__VA_ARGS__); \
1facf9fc 3873+} while (0)
3874+
3875+/* ---------------------------------------------------------------------- */
3876+
3877+void au_dpri_whlist(struct au_nhash *whlist)
3878+{
3879+ unsigned long ul, n;
3880+ struct hlist_head *head;
3881+ struct au_vdir_wh *tpos;
3882+ struct hlist_node *pos;
3883+
3884+ n = whlist->nh_num;
3885+ head = whlist->nh_head;
3886+ for (ul = 0; ul < n; ul++) {
3887+ hlist_for_each_entry(tpos, pos, head, wh_hash)
3888+ dpri("b%d, %.*s, %d\n",
3889+ tpos->wh_bindex,
3890+ tpos->wh_str.len, tpos->wh_str.name,
3891+ tpos->wh_str.len);
3892+ head++;
3893+ }
3894+}
3895+
3896+void au_dpri_vdir(struct au_vdir *vdir)
3897+{
3898+ unsigned long ul;
3899+ union au_vdir_deblk_p p;
3900+ unsigned char *o;
3901+
3902+ if (!vdir || IS_ERR(vdir)) {
3903+ dpri("err %ld\n", PTR_ERR(vdir));
3904+ return;
3905+ }
3906+
3907+ dpri("deblk %u, nblk %lu, deblk %p, last{%lu, %p}, ver %lu\n",
3908+ vdir->vd_deblk_sz, vdir->vd_nblk, vdir->vd_deblk,
3909+ vdir->vd_last.ul, vdir->vd_last.p.deblk, vdir->vd_version);
3910+ for (ul = 0; ul < vdir->vd_nblk; ul++) {
3911+ p.deblk = vdir->vd_deblk[ul];
3912+ o = p.deblk;
3913+ dpri("[%lu]: %p\n", ul, o);
3914+ }
3915+}
3916+
3917+static int do_pri_inode(aufs_bindex_t bindex, struct inode *inode,
3918+ struct dentry *wh)
3919+{
3920+ char *n = NULL;
3921+ int l = 0;
3922+
3923+ if (!inode || IS_ERR(inode)) {
3924+ dpri("i%d: err %ld\n", bindex, PTR_ERR(inode));
3925+ return -1;
3926+ }
3927+
3928+ /* the type of i_blocks depends upon CONFIG_LSF */
3929+ BUILD_BUG_ON(sizeof(inode->i_blocks) != sizeof(unsigned long)
3930+ && sizeof(inode->i_blocks) != sizeof(u64));
3931+ if (wh) {
3932+ n = (void *)wh->d_name.name;
3933+ l = wh->d_name.len;
3934+ }
3935+
3936+ dpri("i%d: i%lu, %s, cnt %d, nl %u, 0%o, sz %llu, blk %llu,"
b752ccd1 3937+ " ct %lld, np %lu, st 0x%lx, f 0x%x, v %llu, g %x%s%.*s\n",
1facf9fc 3938+ bindex,
3939+ inode->i_ino, inode->i_sb ? au_sbtype(inode->i_sb) : "??",
3940+ atomic_read(&inode->i_count), inode->i_nlink, inode->i_mode,
3941+ i_size_read(inode), (unsigned long long)inode->i_blocks,
3942+ (long long)timespec_to_ns(&inode->i_ctime) & 0x0ffff,
3943+ inode->i_mapping ? inode->i_mapping->nrpages : 0,
b752ccd1
AM
3944+ inode->i_state, inode->i_flags, inode->i_version,
3945+ inode->i_generation,
1facf9fc 3946+ l ? ", wh " : "", l, n);
3947+ return 0;
3948+}
3949+
3950+void au_dpri_inode(struct inode *inode)
3951+{
3952+ struct au_iinfo *iinfo;
3953+ aufs_bindex_t bindex;
3954+ int err;
3955+
3956+ err = do_pri_inode(-1, inode, NULL);
3957+ if (err || !au_test_aufs(inode->i_sb))
3958+ return;
3959+
3960+ iinfo = au_ii(inode);
3961+ if (!iinfo)
3962+ return;
3963+ dpri("i-1: bstart %d, bend %d, gen %d\n",
3964+ iinfo->ii_bstart, iinfo->ii_bend, au_iigen(inode));
3965+ if (iinfo->ii_bstart < 0)
3966+ return;
3967+ for (bindex = iinfo->ii_bstart; bindex <= iinfo->ii_bend; bindex++)
3968+ do_pri_inode(bindex, iinfo->ii_hinode[0 + bindex].hi_inode,
3969+ iinfo->ii_hinode[0 + bindex].hi_whdentry);
3970+}
3971+
2cbb1c4b
JR
3972+void au_dpri_dalias(struct inode *inode)
3973+{
3974+ struct dentry *d;
3975+
3976+ spin_lock(&inode->i_lock);
3977+ list_for_each_entry(d, &inode->i_dentry, d_alias)
3978+ au_dpri_dentry(d);
3979+ spin_unlock(&inode->i_lock);
3980+}
3981+
1facf9fc 3982+static int do_pri_dentry(aufs_bindex_t bindex, struct dentry *dentry)
3983+{
3984+ struct dentry *wh = NULL;
3985+
3986+ if (!dentry || IS_ERR(dentry)) {
3987+ dpri("d%d: err %ld\n", bindex, PTR_ERR(dentry));
3988+ return -1;
3989+ }
3990+ /* do not call dget_parent() here */
027c5e7a 3991+ /* note: access d_xxx without d_lock */
1facf9fc 3992+ dpri("d%d: %.*s?/%.*s, %s, cnt %d, flags 0x%x\n",
3993+ bindex,
3994+ AuDLNPair(dentry->d_parent), AuDLNPair(dentry),
3995+ dentry->d_sb ? au_sbtype(dentry->d_sb) : "??",
027c5e7a 3996+ dentry->d_count, dentry->d_flags);
1facf9fc 3997+ if (bindex >= 0 && dentry->d_inode && au_test_aufs(dentry->d_sb)) {
3998+ struct au_iinfo *iinfo = au_ii(dentry->d_inode);
3999+ if (iinfo)
4000+ wh = iinfo->ii_hinode[0 + bindex].hi_whdentry;
4001+ }
4002+ do_pri_inode(bindex, dentry->d_inode, wh);
4003+ return 0;
4004+}
4005+
4006+void au_dpri_dentry(struct dentry *dentry)
4007+{
4008+ struct au_dinfo *dinfo;
4009+ aufs_bindex_t bindex;
4010+ int err;
4a4d8108 4011+ struct au_hdentry *hdp;
1facf9fc 4012+
4013+ err = do_pri_dentry(-1, dentry);
4014+ if (err || !au_test_aufs(dentry->d_sb))
4015+ return;
4016+
4017+ dinfo = au_di(dentry);
4018+ if (!dinfo)
4019+ return;
4020+ dpri("d-1: bstart %d, bend %d, bwh %d, bdiropq %d, gen %d\n",
4021+ dinfo->di_bstart, dinfo->di_bend,
4022+ dinfo->di_bwh, dinfo->di_bdiropq, au_digen(dentry));
4023+ if (dinfo->di_bstart < 0)
4024+ return;
4a4d8108 4025+ hdp = dinfo->di_hdentry;
1facf9fc 4026+ for (bindex = dinfo->di_bstart; bindex <= dinfo->di_bend; bindex++)
4a4d8108 4027+ do_pri_dentry(bindex, hdp[0 + bindex].hd_dentry);
1facf9fc 4028+}
4029+
4030+static int do_pri_file(aufs_bindex_t bindex, struct file *file)
4031+{
4032+ char a[32];
4033+
4034+ if (!file || IS_ERR(file)) {
4035+ dpri("f%d: err %ld\n", bindex, PTR_ERR(file));
4036+ return -1;
4037+ }
4038+ a[0] = 0;
4039+ if (bindex < 0
4040+ && file->f_dentry
4041+ && au_test_aufs(file->f_dentry->d_sb)
4042+ && au_fi(file))
e49829fe 4043+ snprintf(a, sizeof(a), ", gen %d, mmapped %d",
2cbb1c4b 4044+ au_figen(file), atomic_read(&au_fi(file)->fi_mmapped));
b752ccd1 4045+ dpri("f%d: mode 0x%x, flags 0%o, cnt %ld, v %llu, pos %llu%s\n",
1facf9fc 4046+ bindex, file->f_mode, file->f_flags, (long)file_count(file),
b752ccd1 4047+ file->f_version, file->f_pos, a);
1facf9fc 4048+ if (file->f_dentry)
4049+ do_pri_dentry(bindex, file->f_dentry);
4050+ return 0;
4051+}
4052+
4053+void au_dpri_file(struct file *file)
4054+{
4055+ struct au_finfo *finfo;
4a4d8108
AM
4056+ struct au_fidir *fidir;
4057+ struct au_hfile *hfile;
1facf9fc 4058+ aufs_bindex_t bindex;
4059+ int err;
4060+
4061+ err = do_pri_file(-1, file);
4062+ if (err || !file->f_dentry || !au_test_aufs(file->f_dentry->d_sb))
4063+ return;
4064+
4065+ finfo = au_fi(file);
4066+ if (!finfo)
4067+ return;
4a4d8108 4068+ if (finfo->fi_btop < 0)
1facf9fc 4069+ return;
4a4d8108
AM
4070+ fidir = finfo->fi_hdir;
4071+ if (!fidir)
4072+ do_pri_file(finfo->fi_btop, finfo->fi_htop.hf_file);
4073+ else
e49829fe
JR
4074+ for (bindex = finfo->fi_btop;
4075+ bindex >= 0 && bindex <= fidir->fd_bbot;
4a4d8108
AM
4076+ bindex++) {
4077+ hfile = fidir->fd_hfile + bindex;
4078+ do_pri_file(bindex, hfile ? hfile->hf_file : NULL);
4079+ }
1facf9fc 4080+}
4081+
4082+static int do_pri_br(aufs_bindex_t bindex, struct au_branch *br)
4083+{
4084+ struct vfsmount *mnt;
4085+ struct super_block *sb;
4086+
4087+ if (!br || IS_ERR(br))
4088+ goto out;
4089+ mnt = br->br_mnt;
4090+ if (!mnt || IS_ERR(mnt))
4091+ goto out;
4092+ sb = mnt->mnt_sb;
4093+ if (!sb || IS_ERR(sb))
4094+ goto out;
4095+
4096+ dpri("s%d: {perm 0x%x, cnt %d, wbr %p}, "
b752ccd1 4097+ "%s, dev 0x%02x%02x, flags 0x%lx, cnt %d, active %d, "
1facf9fc 4098+ "xino %d\n",
4099+ bindex, br->br_perm, atomic_read(&br->br_count), br->br_wbr,
4100+ au_sbtype(sb), MAJOR(sb->s_dev), MINOR(sb->s_dev),
b752ccd1 4101+ sb->s_flags, sb->s_count,
1facf9fc 4102+ atomic_read(&sb->s_active), !!br->br_xino.xi_file);
4103+ return 0;
4104+
4f0767ce 4105+out:
1facf9fc 4106+ dpri("s%d: err %ld\n", bindex, PTR_ERR(br));
4107+ return -1;
4108+}
4109+
4110+void au_dpri_sb(struct super_block *sb)
4111+{
4112+ struct au_sbinfo *sbinfo;
4113+ aufs_bindex_t bindex;
4114+ int err;
4115+ /* to reuduce stack size */
4116+ struct {
4117+ struct vfsmount mnt;
4118+ struct au_branch fake;
4119+ } *a;
4120+
4121+ /* this function can be called from magic sysrq */
4122+ a = kzalloc(sizeof(*a), GFP_ATOMIC);
4123+ if (unlikely(!a)) {
4124+ dpri("no memory\n");
4125+ return;
4126+ }
4127+
4128+ a->mnt.mnt_sb = sb;
4129+ a->fake.br_perm = 0;
4130+ a->fake.br_mnt = &a->mnt;
4131+ a->fake.br_xino.xi_file = NULL;
4132+ atomic_set(&a->fake.br_count, 0);
4133+ smp_mb(); /* atomic_set */
4134+ err = do_pri_br(-1, &a->fake);
4135+ kfree(a);
4136+ dpri("dev 0x%x\n", sb->s_dev);
4137+ if (err || !au_test_aufs(sb))
4138+ return;
4139+
4140+ sbinfo = au_sbi(sb);
4141+ if (!sbinfo)
4142+ return;
4143+ dpri("nw %d, gen %u, kobj %d\n",
4144+ atomic_read(&sbinfo->si_nowait.nw_len), sbinfo->si_generation,
4145+ atomic_read(&sbinfo->si_kobj.kref.refcount));
4146+ for (bindex = 0; bindex <= sbinfo->si_bend; bindex++)
4147+ do_pri_br(bindex, sbinfo->si_branch[0 + bindex]);
4148+}
4149+
4150+/* ---------------------------------------------------------------------- */
4151+
4152+void au_dbg_sleep_jiffy(int jiffy)
4153+{
4154+ while (jiffy)
4155+ jiffy = schedule_timeout_uninterruptible(jiffy);
4156+}
4157+
4158+void au_dbg_iattr(struct iattr *ia)
4159+{
4160+#define AuBit(name) if (ia->ia_valid & ATTR_ ## name) \
4161+ dpri(#name "\n")
4162+ AuBit(MODE);
4163+ AuBit(UID);
4164+ AuBit(GID);
4165+ AuBit(SIZE);
4166+ AuBit(ATIME);
4167+ AuBit(MTIME);
4168+ AuBit(CTIME);
4169+ AuBit(ATIME_SET);
4170+ AuBit(MTIME_SET);
4171+ AuBit(FORCE);
4172+ AuBit(ATTR_FLAG);
4173+ AuBit(KILL_SUID);
4174+ AuBit(KILL_SGID);
4175+ AuBit(FILE);
4176+ AuBit(KILL_PRIV);
4177+ AuBit(OPEN);
4178+ AuBit(TIMES_SET);
4179+#undef AuBit
4180+ dpri("ia_file %p\n", ia->ia_file);
4181+}
4182+
4183+/* ---------------------------------------------------------------------- */
4184+
027c5e7a
AM
4185+void __au_dbg_verify_dinode(struct dentry *dentry, const char *func, int line)
4186+{
4187+ struct inode *h_inode, *inode = dentry->d_inode;
4188+ struct dentry *h_dentry;
4189+ aufs_bindex_t bindex, bend, bi;
4190+
4191+ if (!inode /* || au_di(dentry)->di_lsc == AuLsc_DI_TMP */)
4192+ return;
4193+
4194+ bend = au_dbend(dentry);
4195+ bi = au_ibend(inode);
4196+ if (bi < bend)
4197+ bend = bi;
4198+ bindex = au_dbstart(dentry);
4199+ bi = au_ibstart(inode);
4200+ if (bi > bindex)
4201+ bindex = bi;
4202+
4203+ for (; bindex <= bend; bindex++) {
4204+ h_dentry = au_h_dptr(dentry, bindex);
4205+ if (!h_dentry)
4206+ continue;
4207+ h_inode = au_h_iptr(inode, bindex);
4208+ if (unlikely(h_inode != h_dentry->d_inode)) {
4209+ int old = au_debug_test();
4210+ if (!old)
4211+ au_debug(1);
4212+ AuDbg("b%d, %s:%d\n", bindex, func, line);
4213+ AuDbgDentry(dentry);
4214+ AuDbgInode(inode);
4215+ if (!old)
4216+ au_debug(0);
4217+ BUG();
4218+ }
4219+ }
4220+}
4221+
1facf9fc 4222+void au_dbg_verify_dir_parent(struct dentry *dentry, unsigned int sigen)
4223+{
4224+ struct dentry *parent;
4225+
4226+ parent = dget_parent(dentry);
027c5e7a
AM
4227+ AuDebugOn(!S_ISDIR(dentry->d_inode->i_mode));
4228+ AuDebugOn(IS_ROOT(dentry));
4229+ AuDebugOn(au_digen_test(parent, sigen));
1facf9fc 4230+ dput(parent);
4231+}
4232+
4233+void au_dbg_verify_nondir_parent(struct dentry *dentry, unsigned int sigen)
4234+{
4235+ struct dentry *parent;
027c5e7a 4236+ struct inode *inode;
1facf9fc 4237+
4238+ parent = dget_parent(dentry);
027c5e7a
AM
4239+ inode = dentry->d_inode;
4240+ AuDebugOn(inode && S_ISDIR(dentry->d_inode->i_mode));
4241+ AuDebugOn(au_digen_test(parent, sigen));
1facf9fc 4242+ dput(parent);
4243+}
4244+
4245+void au_dbg_verify_gen(struct dentry *parent, unsigned int sigen)
4246+{
4247+ int err, i, j;
4248+ struct au_dcsub_pages dpages;
4249+ struct au_dpage *dpage;
4250+ struct dentry **dentries;
4251+
4252+ err = au_dpages_init(&dpages, GFP_NOFS);
4253+ AuDebugOn(err);
027c5e7a 4254+ err = au_dcsub_pages_rev_aufs(&dpages, parent, /*do_include*/1);
1facf9fc 4255+ AuDebugOn(err);
4256+ for (i = dpages.ndpage - 1; !err && i >= 0; i--) {
4257+ dpage = dpages.dpages + i;
4258+ dentries = dpage->dentries;
4259+ for (j = dpage->ndentry - 1; !err && j >= 0; j--)
027c5e7a 4260+ AuDebugOn(au_digen_test(dentries[j], sigen));
1facf9fc 4261+ }
4262+ au_dpages_free(&dpages);
4263+}
4264+
1facf9fc 4265+void au_dbg_verify_kthread(void)
4266+{
7f207e10 4267+ if (current->flags & PF_WQ_WORKER) {
1facf9fc 4268+ au_dbg_blocked();
7f207e10 4269+ WARN_ON(1);
1facf9fc 4270+ }
4271+}
4272+
4273+/* ---------------------------------------------------------------------- */
4274+
4275+void au_debug_sbinfo_init(struct au_sbinfo *sbinfo __maybe_unused)
4276+{
4277+#ifdef AuForceNoPlink
4278+ au_opt_clr(sbinfo->si_mntflags, PLINK);
4279+#endif
4280+#ifdef AuForceNoXino
4281+ au_opt_clr(sbinfo->si_mntflags, XINO);
4282+#endif
4283+#ifdef AuForceNoRefrof
4284+ au_opt_clr(sbinfo->si_mntflags, REFROF);
4285+#endif
4a4d8108
AM
4286+#ifdef AuForceHnotify
4287+ au_opt_set_udba(sbinfo->si_mntflags, UDBA_HNOTIFY);
1facf9fc 4288+#endif
1308ab2a 4289+#ifdef AuForceRd0
4290+ sbinfo->si_rdblk = 0;
4291+ sbinfo->si_rdhash = 0;
4292+#endif
1facf9fc 4293+}
4294+
4295+int __init au_debug_init(void)
4296+{
4297+ aufs_bindex_t bindex;
4298+ struct au_vdir_destr destr;
4299+
4300+ bindex = -1;
4301+ AuDebugOn(bindex >= 0);
4302+
4303+ destr.len = -1;
4304+ AuDebugOn(destr.len < NAME_MAX);
4305+
4306+#ifdef CONFIG_4KSTACKS
4a4d8108 4307+ pr_warning("CONFIG_4KSTACKS is defined.\n");
1facf9fc 4308+#endif
4309+
4310+#ifdef AuForceNoBrs
4311+ sysaufs_brs = 0;
4312+#endif
4313+
4314+ return 0;
4315+}
7f207e10
AM
4316diff -urN /usr/share/empty/fs/aufs/debug.h linux/fs/aufs/debug.h
4317--- /usr/share/empty/fs/aufs/debug.h 1970-01-01 01:00:00.000000000 +0100
2cbb1c4b
JR
4318+++ linux/fs/aufs/debug.h 2011-07-11 11:34:24.072331673 +0200
4319@@ -0,0 +1,252 @@
1facf9fc 4320+/*
027c5e7a 4321+ * Copyright (C) 2005-2011 Junjiro R. Okajima
1facf9fc 4322+ *
4323+ * This program, aufs is free software; you can redistribute it and/or modify
4324+ * it under the terms of the GNU General Public License as published by
4325+ * the Free Software Foundation; either version 2 of the License, or
4326+ * (at your option) any later version.
dece6358
AM
4327+ *
4328+ * This program is distributed in the hope that it will be useful,
4329+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
4330+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
4331+ * GNU General Public License for more details.
4332+ *
4333+ * You should have received a copy of the GNU General Public License
4334+ * along with this program; if not, write to the Free Software
4335+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 4336+ */
4337+
4338+/*
4339+ * debug print functions
4340+ */
4341+
4342+#ifndef __AUFS_DEBUG_H__
4343+#define __AUFS_DEBUG_H__
4344+
4345+#ifdef __KERNEL__
4346+
1308ab2a 4347+#include <asm/system.h>
dece6358 4348+#include <linux/bug.h>
7f207e10 4349+/* #include <linux/err.h> */
1308ab2a 4350+#include <linux/init.h>
4a4d8108
AM
4351+#include <linux/module.h>
4352+#include <linux/kallsyms.h>
7f207e10 4353+/* #include <linux/kernel.h> */
1facf9fc 4354+#include <linux/delay.h>
7f207e10 4355+/* #include <linux/kd.h> */
1facf9fc 4356+#include <linux/sysrq.h>
4357+#include <linux/aufs_type.h>
4358+
4a4d8108
AM
4359+#include <asm/system.h>
4360+
1facf9fc 4361+#ifdef CONFIG_AUFS_DEBUG
4362+#define AuDebugOn(a) BUG_ON(a)
4363+
4364+/* module parameter */
4365+extern int aufs_debug;
4366+static inline void au_debug(int n)
4367+{
4368+ aufs_debug = n;
4369+ smp_mb();
4370+}
4371+
4372+static inline int au_debug_test(void)
4373+{
4374+ return aufs_debug;
4375+}
4376+#else
4377+#define AuDebugOn(a) do {} while (0)
4a4d8108
AM
4378+AuStubVoid(au_debug, int n)
4379+AuStubInt0(au_debug_test, void)
1facf9fc 4380+#endif /* CONFIG_AUFS_DEBUG */
4381+
4382+/* ---------------------------------------------------------------------- */
4383+
4384+/* debug print */
4385+
4a4d8108 4386+#define AuDbg(fmt, ...) do { \
1facf9fc 4387+ if (au_debug_test()) \
4a4d8108 4388+ pr_debug("DEBUG: " fmt, ##__VA_ARGS__); \
1facf9fc 4389+} while (0)
4a4d8108
AM
4390+#define AuLabel(l) AuDbg(#l "\n")
4391+#define AuIOErr(fmt, ...) pr_err("I/O Error, " fmt, ##__VA_ARGS__)
4392+#define AuWarn1(fmt, ...) do { \
1facf9fc 4393+ static unsigned char _c; \
4394+ if (!_c++) \
4a4d8108 4395+ pr_warning(fmt, ##__VA_ARGS__); \
1facf9fc 4396+} while (0)
4397+
4a4d8108 4398+#define AuErr1(fmt, ...) do { \
1facf9fc 4399+ static unsigned char _c; \
4400+ if (!_c++) \
4a4d8108 4401+ pr_err(fmt, ##__VA_ARGS__); \
1facf9fc 4402+} while (0)
4403+
4a4d8108 4404+#define AuIOErr1(fmt, ...) do { \
1facf9fc 4405+ static unsigned char _c; \
4406+ if (!_c++) \
4a4d8108 4407+ AuIOErr(fmt, ##__VA_ARGS__); \
1facf9fc 4408+} while (0)
4409+
4410+#define AuUnsupportMsg "This operation is not supported." \
4411+ " Please report this application to aufs-users ML."
4a4d8108
AM
4412+#define AuUnsupport(fmt, ...) do { \
4413+ pr_err(AuUnsupportMsg "\n" fmt, ##__VA_ARGS__); \
1facf9fc 4414+ dump_stack(); \
4415+} while (0)
4416+
4417+#define AuTraceErr(e) do { \
4418+ if (unlikely((e) < 0)) \
4419+ AuDbg("err %d\n", (int)(e)); \
4420+} while (0)
4421+
4422+#define AuTraceErrPtr(p) do { \
4423+ if (IS_ERR(p)) \
4424+ AuDbg("err %ld\n", PTR_ERR(p)); \
4425+} while (0)
4426+
4427+/* dirty macros for debug print, use with "%.*s" and caution */
4428+#define AuLNPair(qstr) (qstr)->len, (qstr)->name
4429+#define AuDLNPair(d) AuLNPair(&(d)->d_name)
4430+
4431+/* ---------------------------------------------------------------------- */
4432+
4433+struct au_sbinfo;
4434+struct au_finfo;
dece6358 4435+struct dentry;
1facf9fc 4436+#ifdef CONFIG_AUFS_DEBUG
4437+extern char *au_plevel;
4438+struct au_nhash;
4439+void au_dpri_whlist(struct au_nhash *whlist);
4440+struct au_vdir;
4441+void au_dpri_vdir(struct au_vdir *vdir);
dece6358 4442+struct inode;
1facf9fc 4443+void au_dpri_inode(struct inode *inode);
2cbb1c4b 4444+void au_dpri_dalias(struct inode *inode);
1facf9fc 4445+void au_dpri_dentry(struct dentry *dentry);
dece6358 4446+struct file;
1facf9fc 4447+void au_dpri_file(struct file *filp);
dece6358 4448+struct super_block;
1facf9fc 4449+void au_dpri_sb(struct super_block *sb);
4450+
4451+void au_dbg_sleep_jiffy(int jiffy);
dece6358 4452+struct iattr;
1facf9fc 4453+void au_dbg_iattr(struct iattr *ia);
4454+
027c5e7a
AM
4455+#define au_dbg_verify_dinode(d) __au_dbg_verify_dinode(d, __func__, __LINE__)
4456+void __au_dbg_verify_dinode(struct dentry *dentry, const char *func, int line);
1facf9fc 4457+void au_dbg_verify_dir_parent(struct dentry *dentry, unsigned int sigen);
4458+void au_dbg_verify_nondir_parent(struct dentry *dentry, unsigned int sigen);
4459+void au_dbg_verify_gen(struct dentry *parent, unsigned int sigen);
1facf9fc 4460+void au_dbg_verify_kthread(void);
4461+
4462+int __init au_debug_init(void);
4463+void au_debug_sbinfo_init(struct au_sbinfo *sbinfo);
4464+#define AuDbgWhlist(w) do { \
4465+ AuDbg(#w "\n"); \
4466+ au_dpri_whlist(w); \
4467+} while (0)
4468+
4469+#define AuDbgVdir(v) do { \
4470+ AuDbg(#v "\n"); \
4471+ au_dpri_vdir(v); \
4472+} while (0)
4473+
4474+#define AuDbgInode(i) do { \
4475+ AuDbg(#i "\n"); \
4476+ au_dpri_inode(i); \
4477+} while (0)
4478+
2cbb1c4b
JR
4479+#define AuDbgDAlias(i) do { \
4480+ AuDbg(#i "\n"); \
4481+ au_dpri_dalias(i); \
4482+} while (0)
4483+
1facf9fc 4484+#define AuDbgDentry(d) do { \
4485+ AuDbg(#d "\n"); \
4486+ au_dpri_dentry(d); \
4487+} while (0)
4488+
4489+#define AuDbgFile(f) do { \
4490+ AuDbg(#f "\n"); \
4491+ au_dpri_file(f); \
4492+} while (0)
4493+
4494+#define AuDbgSb(sb) do { \
4495+ AuDbg(#sb "\n"); \
4496+ au_dpri_sb(sb); \
4497+} while (0)
4498+
4499+#define AuDbgSleep(sec) do { \
4500+ AuDbg("sleep %d sec\n", sec); \
4501+ ssleep(sec); \
4502+} while (0)
4503+
4504+#define AuDbgSleepJiffy(jiffy) do { \
4505+ AuDbg("sleep %d jiffies\n", jiffy); \
4506+ au_dbg_sleep_jiffy(jiffy); \
4507+} while (0)
4508+
4509+#define AuDbgIAttr(ia) do { \
4510+ AuDbg("ia_valid 0x%x\n", (ia)->ia_valid); \
4511+ au_dbg_iattr(ia); \
4512+} while (0)
4a4d8108
AM
4513+
4514+#define AuDbgSym(addr) do { \
4515+ char sym[KSYM_SYMBOL_LEN]; \
4516+ sprint_symbol(sym, (unsigned long)addr); \
4517+ AuDbg("%s\n", sym); \
4518+} while (0)
4519+
4520+#define AuInfoSym(addr) do { \
4521+ char sym[KSYM_SYMBOL_LEN]; \
4522+ sprint_symbol(sym, (unsigned long)addr); \
4523+ AuInfo("%s\n", sym); \
4524+} while (0)
1facf9fc 4525+#else
027c5e7a 4526+AuStubVoid(au_dbg_verify_dinode, struct dentry *dentry)
4a4d8108
AM
4527+AuStubVoid(au_dbg_verify_dir_parent, struct dentry *dentry, unsigned int sigen)
4528+AuStubVoid(au_dbg_verify_nondir_parent, struct dentry *dentry,
4529+ unsigned int sigen)
4530+AuStubVoid(au_dbg_verify_gen, struct dentry *parent, unsigned int sigen)
4531+AuStubVoid(au_dbg_verify_kthread, void)
4532+AuStubInt0(__init au_debug_init, void)
4533+AuStubVoid(au_debug_sbinfo_init, struct au_sbinfo *sbinfo)
1facf9fc 4534+
1facf9fc 4535+#define AuDbgWhlist(w) do {} while (0)
4536+#define AuDbgVdir(v) do {} while (0)
4537+#define AuDbgInode(i) do {} while (0)
2cbb1c4b 4538+#define AuDbgDAlias(i) do {} while (0)
1facf9fc 4539+#define AuDbgDentry(d) do {} while (0)
4540+#define AuDbgFile(f) do {} while (0)
4541+#define AuDbgSb(sb) do {} while (0)
4542+#define AuDbgSleep(sec) do {} while (0)
4543+#define AuDbgSleepJiffy(jiffy) do {} while (0)
4544+#define AuDbgIAttr(ia) do {} while (0)
4a4d8108
AM
4545+#define AuDbgSym(addr) do {} while (0)
4546+#define AuInfoSym(addr) do {} while (0)
1facf9fc 4547+#endif /* CONFIG_AUFS_DEBUG */
4548+
4549+/* ---------------------------------------------------------------------- */
4550+
4551+#ifdef CONFIG_AUFS_MAGIC_SYSRQ
4552+int __init au_sysrq_init(void);
4553+void au_sysrq_fin(void);
4554+
4555+#ifdef CONFIG_HW_CONSOLE
4556+#define au_dbg_blocked() do { \
4557+ WARN_ON(1); \
0c5527e5 4558+ handle_sysrq('w'); \
1facf9fc 4559+} while (0)
4560+#else
4a4d8108 4561+AuStubVoid(au_dbg_blocked, void)
1facf9fc 4562+#endif
4563+
4564+#else
4a4d8108
AM
4565+AuStubInt0(__init au_sysrq_init, void)
4566+AuStubVoid(au_sysrq_fin, void)
4567+AuStubVoid(au_dbg_blocked, void)
1facf9fc 4568+#endif /* CONFIG_AUFS_MAGIC_SYSRQ */
4569+
4570+#endif /* __KERNEL__ */
4571+#endif /* __AUFS_DEBUG_H__ */
7f207e10
AM
4572diff -urN /usr/share/empty/fs/aufs/dentry.c linux/fs/aufs/dentry.c
4573--- /usr/share/empty/fs/aufs/dentry.c 1970-01-01 01:00:00.000000000 +0100
2cbb1c4b 4574+++ linux/fs/aufs/dentry.c 2011-07-11 11:34:24.072331673 +0200
027c5e7a 4575@@ -0,0 +1,1140 @@
1facf9fc 4576+/*
027c5e7a 4577+ * Copyright (C) 2005-2011 Junjiro R. Okajima
1facf9fc 4578+ *
4579+ * This program, aufs is free software; you can redistribute it and/or modify
4580+ * it under the terms of the GNU General Public License as published by
4581+ * the Free Software Foundation; either version 2 of the License, or
4582+ * (at your option) any later version.
dece6358
AM
4583+ *
4584+ * This program is distributed in the hope that it will be useful,
4585+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
4586+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
4587+ * GNU General Public License for more details.
4588+ *
4589+ * You should have received a copy of the GNU General Public License
4590+ * along with this program; if not, write to the Free Software
4591+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 4592+ */
4593+
4594+/*
4595+ * lookup and dentry operations
4596+ */
4597+
dece6358 4598+#include <linux/namei.h>
1facf9fc 4599+#include "aufs.h"
4600+
4601+static void au_h_nd(struct nameidata *h_nd, struct nameidata *nd)
4602+{
4603+ if (nd) {
4604+ *h_nd = *nd;
4605+
4606+ /*
4607+ * gave up supporting LOOKUP_CREATE/OPEN for lower fs,
4608+ * due to whiteout and branch permission.
4609+ */
4610+ h_nd->flags &= ~(/*LOOKUP_PARENT |*/ LOOKUP_OPEN | LOOKUP_CREATE
b752ccd1 4611+ | LOOKUP_FOLLOW | LOOKUP_EXCL);
1facf9fc 4612+ /* unnecessary? */
4613+ h_nd->intent.open.file = NULL;
4614+ } else
4615+ memset(h_nd, 0, sizeof(*h_nd));
4616+}
4617+
4618+struct au_lkup_one_args {
4619+ struct dentry **errp;
4620+ struct qstr *name;
4621+ struct dentry *h_parent;
4622+ struct au_branch *br;
4623+ struct nameidata *nd;
4624+};
4625+
4626+struct dentry *au_lkup_one(struct qstr *name, struct dentry *h_parent,
4627+ struct au_branch *br, struct nameidata *nd)
4628+{
4629+ struct dentry *h_dentry;
4630+ int err;
4631+ struct nameidata h_nd;
4632+
4633+ if (au_test_fs_null_nd(h_parent->d_sb))
4634+ return vfsub_lookup_one_len(name->name, h_parent, name->len);
4635+
4636+ au_h_nd(&h_nd, nd);
4637+ h_nd.path.dentry = h_parent;
4638+ h_nd.path.mnt = br->br_mnt;
4639+
2cbb1c4b 4640+ err = vfsub_name_hash(name->name, &h_nd.last, name->len);
1facf9fc 4641+ h_dentry = ERR_PTR(err);
4642+ if (!err) {
4643+ path_get(&h_nd.path);
4644+ h_dentry = vfsub_lookup_hash(&h_nd);
4645+ path_put(&h_nd.path);
4646+ }
4647+
4a4d8108 4648+ AuTraceErrPtr(h_dentry);
1facf9fc 4649+ return h_dentry;
4650+}
4651+
4652+static void au_call_lkup_one(void *args)
4653+{
4654+ struct au_lkup_one_args *a = args;
4655+ *a->errp = au_lkup_one(a->name, a->h_parent, a->br, a->nd);
4656+}
4657+
4658+#define AuLkup_ALLOW_NEG 1
4659+#define au_ftest_lkup(flags, name) ((flags) & AuLkup_##name)
7f207e10
AM
4660+#define au_fset_lkup(flags, name) \
4661+ do { (flags) |= AuLkup_##name; } while (0)
4662+#define au_fclr_lkup(flags, name) \
4663+ do { (flags) &= ~AuLkup_##name; } while (0)
1facf9fc 4664+
4665+struct au_do_lookup_args {
4666+ unsigned int flags;
4667+ mode_t type;
4668+ struct nameidata *nd;
4669+};
4670+
4671+/*
4672+ * returns positive/negative dentry, NULL or an error.
4673+ * NULL means whiteout-ed or not-found.
4674+ */
4675+static struct dentry*
4676+au_do_lookup(struct dentry *h_parent, struct dentry *dentry,
4677+ aufs_bindex_t bindex, struct qstr *wh_name,
4678+ struct au_do_lookup_args *args)
4679+{
4680+ struct dentry *h_dentry;
4681+ struct inode *h_inode, *inode;
1facf9fc 4682+ struct au_branch *br;
4683+ int wh_found, opq;
4684+ unsigned char wh_able;
4685+ const unsigned char allow_neg = !!au_ftest_lkup(args->flags, ALLOW_NEG);
4686+
1facf9fc 4687+ wh_found = 0;
4688+ br = au_sbr(dentry->d_sb, bindex);
4689+ wh_able = !!au_br_whable(br->br_perm);
4690+ if (wh_able)
4691+ wh_found = au_wh_test(h_parent, wh_name, br, /*try_sio*/0);
4692+ h_dentry = ERR_PTR(wh_found);
4693+ if (!wh_found)
4694+ goto real_lookup;
4695+ if (unlikely(wh_found < 0))
4696+ goto out;
4697+
4698+ /* We found a whiteout */
4699+ /* au_set_dbend(dentry, bindex); */
4700+ au_set_dbwh(dentry, bindex);
4701+ if (!allow_neg)
4702+ return NULL; /* success */
4703+
4f0767ce 4704+real_lookup:
4a4d8108 4705+ h_dentry = au_lkup_one(&dentry->d_name, h_parent, br, args->nd);
1facf9fc 4706+ if (IS_ERR(h_dentry))
4707+ goto out;
4708+
4709+ h_inode = h_dentry->d_inode;
4710+ if (!h_inode) {
4711+ if (!allow_neg)
4712+ goto out_neg;
4713+ } else if (wh_found
4714+ || (args->type && args->type != (h_inode->i_mode & S_IFMT)))
4715+ goto out_neg;
4716+
4717+ if (au_dbend(dentry) <= bindex)
4718+ au_set_dbend(dentry, bindex);
4719+ if (au_dbstart(dentry) < 0 || bindex < au_dbstart(dentry))
4720+ au_set_dbstart(dentry, bindex);
4721+ au_set_h_dptr(dentry, bindex, h_dentry);
4722+
4723+ inode = dentry->d_inode;
4724+ if (!h_inode || !S_ISDIR(h_inode->i_mode) || !wh_able
4725+ || (inode && !S_ISDIR(inode->i_mode)))
4726+ goto out; /* success */
4727+
4728+ mutex_lock_nested(&h_inode->i_mutex, AuLsc_I_CHILD);
4729+ opq = au_diropq_test(h_dentry, br);
4730+ mutex_unlock(&h_inode->i_mutex);
4731+ if (opq > 0)
4732+ au_set_dbdiropq(dentry, bindex);
4733+ else if (unlikely(opq < 0)) {
4734+ au_set_h_dptr(dentry, bindex, NULL);
4735+ h_dentry = ERR_PTR(opq);
4736+ }
4737+ goto out;
4738+
4f0767ce 4739+out_neg:
1facf9fc 4740+ dput(h_dentry);
4741+ h_dentry = NULL;
4f0767ce 4742+out:
1facf9fc 4743+ return h_dentry;
4744+}
4745+
dece6358
AM
4746+static int au_test_shwh(struct super_block *sb, const struct qstr *name)
4747+{
4748+ if (unlikely(!au_opt_test(au_mntflags(sb), SHWH)
4749+ && !strncmp(name->name, AUFS_WH_PFX, AUFS_WH_PFX_LEN)))
4750+ return -EPERM;
4751+ return 0;
4752+}
4753+
1facf9fc 4754+/*
4755+ * returns the number of lower positive dentries,
4756+ * otherwise an error.
4757+ * can be called at unlinking with @type is zero.
4758+ */
4759+int au_lkup_dentry(struct dentry *dentry, aufs_bindex_t bstart, mode_t type,
4760+ struct nameidata *nd)
4761+{
4762+ int npositive, err;
4763+ aufs_bindex_t bindex, btail, bdiropq;
4764+ unsigned char isdir;
4765+ struct qstr whname;
4766+ struct au_do_lookup_args args = {
4767+ .flags = 0,
4768+ .type = type,
4769+ .nd = nd
4770+ };
4771+ const struct qstr *name = &dentry->d_name;
4772+ struct dentry *parent;
4773+ struct inode *inode;
4774+
dece6358
AM
4775+ err = au_test_shwh(dentry->d_sb, name);
4776+ if (unlikely(err))
1facf9fc 4777+ goto out;
4778+
4779+ err = au_wh_name_alloc(&whname, name);
4780+ if (unlikely(err))
4781+ goto out;
4782+
4783+ inode = dentry->d_inode;
4784+ isdir = !!(inode && S_ISDIR(inode->i_mode));
4785+ if (!type)
4786+ au_fset_lkup(args.flags, ALLOW_NEG);
4787+
4788+ npositive = 0;
4a4d8108 4789+ parent = dget_parent(dentry);
1facf9fc 4790+ btail = au_dbtaildir(parent);
4791+ for (bindex = bstart; bindex <= btail; bindex++) {
4792+ struct dentry *h_parent, *h_dentry;
4793+ struct inode *h_inode, *h_dir;
4794+
4795+ h_dentry = au_h_dptr(dentry, bindex);
4796+ if (h_dentry) {
4797+ if (h_dentry->d_inode)
4798+ npositive++;
4799+ if (type != S_IFDIR)
4800+ break;
4801+ continue;
4802+ }
4803+ h_parent = au_h_dptr(parent, bindex);
4804+ if (!h_parent)
4805+ continue;
4806+ h_dir = h_parent->d_inode;
4807+ if (!h_dir || !S_ISDIR(h_dir->i_mode))
4808+ continue;
4809+
4810+ mutex_lock_nested(&h_dir->i_mutex, AuLsc_I_PARENT);
4811+ h_dentry = au_do_lookup(h_parent, dentry, bindex, &whname,
4812+ &args);
4813+ mutex_unlock(&h_dir->i_mutex);
4814+ err = PTR_ERR(h_dentry);
4815+ if (IS_ERR(h_dentry))
4a4d8108 4816+ goto out_parent;
1facf9fc 4817+ au_fclr_lkup(args.flags, ALLOW_NEG);
4818+
4819+ if (au_dbwh(dentry) >= 0)
4820+ break;
4821+ if (!h_dentry)
4822+ continue;
4823+ h_inode = h_dentry->d_inode;
4824+ if (!h_inode)
4825+ continue;
4826+ npositive++;
4827+ if (!args.type)
4828+ args.type = h_inode->i_mode & S_IFMT;
4829+ if (args.type != S_IFDIR)
4830+ break;
4831+ else if (isdir) {
4832+ /* the type of lower may be different */
4833+ bdiropq = au_dbdiropq(dentry);
4834+ if (bdiropq >= 0 && bdiropq <= bindex)
4835+ break;
4836+ }
4837+ }
4838+
4839+ if (npositive) {
4840+ AuLabel(positive);
4841+ au_update_dbstart(dentry);
4842+ }
4843+ err = npositive;
4844+ if (unlikely(!au_opt_test(au_mntflags(dentry->d_sb), UDBA_NONE)
027c5e7a 4845+ && au_dbstart(dentry) < 0)) {
1facf9fc 4846+ err = -EIO;
027c5e7a
AM
4847+ AuIOErr("both of real entry and whiteout found, %.*s, err %d\n",
4848+ AuDLNPair(dentry), err);
4849+ }
1facf9fc 4850+
4f0767ce 4851+out_parent:
4a4d8108 4852+ dput(parent);
1facf9fc 4853+ kfree(whname.name);
4f0767ce 4854+out:
1facf9fc 4855+ return err;
4856+}
4857+
4858+struct dentry *au_sio_lkup_one(struct qstr *name, struct dentry *parent,
4859+ struct au_branch *br)
4860+{
4861+ struct dentry *dentry;
4862+ int wkq_err;
4863+
4864+ if (!au_test_h_perm_sio(parent->d_inode, MAY_EXEC))
4865+ dentry = au_lkup_one(name, parent, br, /*nd*/NULL);
4866+ else {
4867+ struct au_lkup_one_args args = {
4868+ .errp = &dentry,
4869+ .name = name,
4870+ .h_parent = parent,
4871+ .br = br,
4872+ .nd = NULL
4873+ };
4874+
4875+ wkq_err = au_wkq_wait(au_call_lkup_one, &args);
4876+ if (unlikely(wkq_err))
4877+ dentry = ERR_PTR(wkq_err);
4878+ }
4879+
4880+ return dentry;
4881+}
4882+
4883+/*
4884+ * lookup @dentry on @bindex which should be negative.
4885+ */
4886+int au_lkup_neg(struct dentry *dentry, aufs_bindex_t bindex)
4887+{
4888+ int err;
4889+ struct dentry *parent, *h_parent, *h_dentry;
1facf9fc 4890+
1facf9fc 4891+ parent = dget_parent(dentry);
4892+ h_parent = au_h_dptr(parent, bindex);
4a4d8108 4893+ h_dentry = au_sio_lkup_one(&dentry->d_name, h_parent,
1facf9fc 4894+ au_sbr(dentry->d_sb, bindex));
4895+ err = PTR_ERR(h_dentry);
4896+ if (IS_ERR(h_dentry))
4897+ goto out;
4898+ if (unlikely(h_dentry->d_inode)) {
4899+ err = -EIO;
027c5e7a
AM
4900+ AuIOErr("%.*s should be negative on b%d.\n",
4901+ AuDLNPair(h_dentry), bindex);
1facf9fc 4902+ dput(h_dentry);
4903+ goto out;
4904+ }
4905+
4a4d8108 4906+ err = 0;
1facf9fc 4907+ if (bindex < au_dbstart(dentry))
4908+ au_set_dbstart(dentry, bindex);
4909+ if (au_dbend(dentry) < bindex)
4910+ au_set_dbend(dentry, bindex);
4911+ au_set_h_dptr(dentry, bindex, h_dentry);
1facf9fc 4912+
4f0767ce 4913+out:
1facf9fc 4914+ dput(parent);
4915+ return err;
4916+}
4917+
4918+/* ---------------------------------------------------------------------- */
4919+
4920+/* subset of struct inode */
4921+struct au_iattr {
4922+ unsigned long i_ino;
4923+ /* unsigned int i_nlink; */
4924+ uid_t i_uid;
4925+ gid_t i_gid;
4926+ u64 i_version;
4927+/*
4928+ loff_t i_size;
4929+ blkcnt_t i_blocks;
4930+*/
4931+ umode_t i_mode;
4932+};
4933+
4934+static void au_iattr_save(struct au_iattr *ia, struct inode *h_inode)
4935+{
4936+ ia->i_ino = h_inode->i_ino;
4937+ /* ia->i_nlink = h_inode->i_nlink; */
4938+ ia->i_uid = h_inode->i_uid;
4939+ ia->i_gid = h_inode->i_gid;
4940+ ia->i_version = h_inode->i_version;
4941+/*
4942+ ia->i_size = h_inode->i_size;
4943+ ia->i_blocks = h_inode->i_blocks;
4944+*/
4945+ ia->i_mode = (h_inode->i_mode & S_IFMT);
4946+}
4947+
4948+static int au_iattr_test(struct au_iattr *ia, struct inode *h_inode)
4949+{
4950+ return ia->i_ino != h_inode->i_ino
4951+ /* || ia->i_nlink != h_inode->i_nlink */
4952+ || ia->i_uid != h_inode->i_uid
4953+ || ia->i_gid != h_inode->i_gid
4954+ || ia->i_version != h_inode->i_version
4955+/*
4956+ || ia->i_size != h_inode->i_size
4957+ || ia->i_blocks != h_inode->i_blocks
4958+*/
4959+ || ia->i_mode != (h_inode->i_mode & S_IFMT);
4960+}
4961+
4962+static int au_h_verify_dentry(struct dentry *h_dentry, struct dentry *h_parent,
4963+ struct au_branch *br)
4964+{
4965+ int err;
4966+ struct au_iattr ia;
4967+ struct inode *h_inode;
4968+ struct dentry *h_d;
4969+ struct super_block *h_sb;
4970+
4971+ err = 0;
4972+ memset(&ia, -1, sizeof(ia));
4973+ h_sb = h_dentry->d_sb;
4974+ h_inode = h_dentry->d_inode;
4975+ if (h_inode)
4976+ au_iattr_save(&ia, h_inode);
4977+ else if (au_test_nfs(h_sb) || au_test_fuse(h_sb))
4978+ /* nfs d_revalidate may return 0 for negative dentry */
4979+ /* fuse d_revalidate always return 0 for negative dentry */
4980+ goto out;
4981+
4982+ /* main purpose is namei.c:cached_lookup() and d_revalidate */
4983+ h_d = au_lkup_one(&h_dentry->d_name, h_parent, br, /*nd*/NULL);
4984+ err = PTR_ERR(h_d);
4985+ if (IS_ERR(h_d))
4986+ goto out;
4987+
4988+ err = 0;
4989+ if (unlikely(h_d != h_dentry
4990+ || h_d->d_inode != h_inode
4991+ || (h_inode && au_iattr_test(&ia, h_inode))))
4992+ err = au_busy_or_stale();
4993+ dput(h_d);
4994+
4f0767ce 4995+out:
1facf9fc 4996+ AuTraceErr(err);
4997+ return err;
4998+}
4999+
5000+int au_h_verify(struct dentry *h_dentry, unsigned int udba, struct inode *h_dir,
5001+ struct dentry *h_parent, struct au_branch *br)
5002+{
5003+ int err;
5004+
5005+ err = 0;
027c5e7a
AM
5006+ if (udba == AuOpt_UDBA_REVAL
5007+ && !au_test_fs_remote(h_dentry->d_sb)) {
1facf9fc 5008+ IMustLock(h_dir);
5009+ err = (h_dentry->d_parent->d_inode != h_dir);
027c5e7a 5010+ } else if (udba != AuOpt_UDBA_NONE)
1facf9fc 5011+ err = au_h_verify_dentry(h_dentry, h_parent, br);
5012+
5013+ return err;
5014+}
5015+
5016+/* ---------------------------------------------------------------------- */
5017+
027c5e7a 5018+static int au_do_refresh_hdentry(struct dentry *dentry, struct dentry *parent)
1facf9fc 5019+{
027c5e7a 5020+ int err;
1facf9fc 5021+ aufs_bindex_t new_bindex, bindex, bend, bwh, bdiropq;
027c5e7a
AM
5022+ struct au_hdentry tmp, *p, *q;
5023+ struct au_dinfo *dinfo;
5024+ struct super_block *sb;
1facf9fc 5025+
027c5e7a 5026+ DiMustWriteLock(dentry);
1308ab2a 5027+
027c5e7a
AM
5028+ sb = dentry->d_sb;
5029+ dinfo = au_di(dentry);
1facf9fc 5030+ bend = dinfo->di_bend;
5031+ bwh = dinfo->di_bwh;
5032+ bdiropq = dinfo->di_bdiropq;
027c5e7a 5033+ p = dinfo->di_hdentry + dinfo->di_bstart;
1facf9fc 5034+ for (bindex = dinfo->di_bstart; bindex <= bend; bindex++, p++) {
027c5e7a 5035+ if (!p->hd_dentry)
1facf9fc 5036+ continue;
5037+
027c5e7a
AM
5038+ new_bindex = au_br_index(sb, p->hd_id);
5039+ if (new_bindex == bindex)
1facf9fc 5040+ continue;
1facf9fc 5041+
1facf9fc 5042+ if (dinfo->di_bwh == bindex)
5043+ bwh = new_bindex;
5044+ if (dinfo->di_bdiropq == bindex)
5045+ bdiropq = new_bindex;
5046+ if (new_bindex < 0) {
5047+ au_hdput(p);
5048+ p->hd_dentry = NULL;
5049+ continue;
5050+ }
5051+
5052+ /* swap two lower dentries, and loop again */
5053+ q = dinfo->di_hdentry + new_bindex;
5054+ tmp = *q;
5055+ *q = *p;
5056+ *p = tmp;
5057+ if (tmp.hd_dentry) {
5058+ bindex--;
5059+ p--;
5060+ }
5061+ }
5062+
1facf9fc 5063+ dinfo->di_bwh = -1;
5064+ if (bwh >= 0 && bwh <= au_sbend(sb) && au_sbr_whable(sb, bwh))
5065+ dinfo->di_bwh = bwh;
5066+
5067+ dinfo->di_bdiropq = -1;
5068+ if (bdiropq >= 0
5069+ && bdiropq <= au_sbend(sb)
5070+ && au_sbr_whable(sb, bdiropq))
5071+ dinfo->di_bdiropq = bdiropq;
5072+
027c5e7a
AM
5073+ err = -EIO;
5074+ dinfo->di_bstart = -1;
5075+ dinfo->di_bend = -1;
1facf9fc 5076+ bend = au_dbend(parent);
5077+ p = dinfo->di_hdentry;
5078+ for (bindex = 0; bindex <= bend; bindex++, p++)
5079+ if (p->hd_dentry) {
5080+ dinfo->di_bstart = bindex;
5081+ break;
5082+ }
5083+
027c5e7a
AM
5084+ if (dinfo->di_bstart >= 0) {
5085+ p = dinfo->di_hdentry + bend;
5086+ for (bindex = bend; bindex >= 0; bindex--, p--)
5087+ if (p->hd_dentry) {
5088+ dinfo->di_bend = bindex;
5089+ err = 0;
5090+ break;
5091+ }
5092+ }
5093+
5094+ return err;
1facf9fc 5095+}
5096+
027c5e7a 5097+static void au_do_hide(struct dentry *dentry)
1facf9fc 5098+{
027c5e7a 5099+ struct inode *inode;
1facf9fc 5100+
027c5e7a
AM
5101+ inode = dentry->d_inode;
5102+ if (inode) {
5103+ if (!S_ISDIR(inode->i_mode)) {
5104+ if (inode->i_nlink && !d_unhashed(dentry))
5105+ drop_nlink(inode);
5106+ } else {
5107+ clear_nlink(inode);
5108+ /* stop next lookup */
5109+ inode->i_flags |= S_DEAD;
5110+ }
5111+ smp_mb(); /* necessary? */
5112+ }
5113+ d_drop(dentry);
5114+}
1308ab2a 5115+
027c5e7a
AM
5116+static int au_hide_children(struct dentry *parent)
5117+{
5118+ int err, i, j, ndentry;
5119+ struct au_dcsub_pages dpages;
5120+ struct au_dpage *dpage;
5121+ struct dentry *dentry;
1facf9fc 5122+
027c5e7a 5123+ err = au_dpages_init(&dpages, GFP_NOFS);
1facf9fc 5124+ if (unlikely(err))
5125+ goto out;
027c5e7a
AM
5126+ err = au_dcsub_pages(&dpages, parent, NULL, NULL);
5127+ if (unlikely(err))
5128+ goto out_dpages;
1facf9fc 5129+
027c5e7a
AM
5130+ /* in reverse order */
5131+ for (i = dpages.ndpage - 1; i >= 0; i--) {
5132+ dpage = dpages.dpages + i;
5133+ ndentry = dpage->ndentry;
5134+ for (j = ndentry - 1; j >= 0; j--) {
5135+ dentry = dpage->dentries[j];
5136+ if (dentry != parent)
5137+ au_do_hide(dentry);
5138+ }
5139+ }
1facf9fc 5140+
027c5e7a
AM
5141+out_dpages:
5142+ au_dpages_free(&dpages);
4f0767ce 5143+out:
027c5e7a 5144+ return err;
1facf9fc 5145+}
5146+
027c5e7a 5147+static void au_hide(struct dentry *dentry)
1facf9fc 5148+{
027c5e7a
AM
5149+ int err;
5150+ struct inode *inode;
1facf9fc 5151+
027c5e7a
AM
5152+ AuDbgDentry(dentry);
5153+ inode = dentry->d_inode;
5154+ if (inode && S_ISDIR(inode->i_mode)) {
5155+ /* shrink_dcache_parent(dentry); */
5156+ err = au_hide_children(dentry);
5157+ if (unlikely(err))
5158+ AuIOErr("%.*s, failed hiding children, ignored %d\n",
5159+ AuDLNPair(dentry), err);
5160+ }
5161+ au_do_hide(dentry);
5162+}
1facf9fc 5163+
027c5e7a
AM
5164+/*
5165+ * By adding a dirty branch, a cached dentry may be affected in various ways.
5166+ *
5167+ * a dirty branch is added
5168+ * - on the top of layers
5169+ * - in the middle of layers
5170+ * - to the bottom of layers
5171+ *
5172+ * on the added branch there exists
5173+ * - a whiteout
5174+ * - a diropq
5175+ * - a same named entry
5176+ * + exist
5177+ * * negative --> positive
5178+ * * positive --> positive
5179+ * - type is unchanged
5180+ * - type is changed
5181+ * + doesn't exist
5182+ * * negative --> negative
5183+ * * positive --> negative (rejected by au_br_del() for non-dir case)
5184+ * - none
5185+ */
5186+static int au_refresh_by_dinfo(struct dentry *dentry, struct au_dinfo *dinfo,
5187+ struct au_dinfo *tmp)
5188+{
5189+ int err;
5190+ aufs_bindex_t bindex, bend;
5191+ struct {
5192+ struct dentry *dentry;
5193+ struct inode *inode;
5194+ mode_t mode;
5195+ } orig_h, tmp_h;
5196+ struct au_hdentry *hd;
5197+ struct inode *inode, *h_inode;
5198+ struct dentry *h_dentry;
5199+
5200+ err = 0;
5201+ AuDebugOn(dinfo->di_bstart < 0);
5202+ orig_h.dentry = dinfo->di_hdentry[dinfo->di_bstart].hd_dentry;
5203+ orig_h.inode = orig_h.dentry->d_inode;
5204+ orig_h.mode = 0;
5205+ if (orig_h.inode)
5206+ orig_h.mode = orig_h.inode->i_mode & S_IFMT;
5207+ memset(&tmp_h, 0, sizeof(tmp_h));
5208+ if (tmp->di_bstart >= 0) {
5209+ tmp_h.dentry = tmp->di_hdentry[tmp->di_bstart].hd_dentry;
5210+ tmp_h.inode = tmp_h.dentry->d_inode;
5211+ if (tmp_h.inode)
5212+ tmp_h.mode = tmp_h.inode->i_mode & S_IFMT;
5213+ }
5214+
5215+ inode = dentry->d_inode;
5216+ if (!orig_h.inode) {
5217+ AuDbg("nagative originally\n");
5218+ if (inode) {
5219+ au_hide(dentry);
5220+ goto out;
5221+ }
5222+ AuDebugOn(inode);
5223+ AuDebugOn(dinfo->di_bstart != dinfo->di_bend);
5224+ AuDebugOn(dinfo->di_bdiropq != -1);
5225+
5226+ if (!tmp_h.inode) {
5227+ AuDbg("negative --> negative\n");
5228+ /* should have only one negative lower */
5229+ if (tmp->di_bstart >= 0
5230+ && tmp->di_bstart < dinfo->di_bstart) {
5231+ AuDebugOn(tmp->di_bstart != tmp->di_bend);
5232+ AuDebugOn(dinfo->di_bstart != dinfo->di_bend);
5233+ au_set_h_dptr(dentry, dinfo->di_bstart, NULL);
5234+ au_di_cp(dinfo, tmp);
5235+ hd = tmp->di_hdentry + tmp->di_bstart;
5236+ au_set_h_dptr(dentry, tmp->di_bstart,
5237+ dget(hd->hd_dentry));
5238+ }
5239+ au_dbg_verify_dinode(dentry);
5240+ } else {
5241+ AuDbg("negative --> positive\n");
5242+ /*
5243+ * similar to the behaviour of creating with bypassing
5244+ * aufs.
5245+ * unhash it in order to force an error in the
5246+ * succeeding create operation.
5247+ * we should not set S_DEAD here.
5248+ */
5249+ d_drop(dentry);
5250+ /* au_di_swap(tmp, dinfo); */
5251+ au_dbg_verify_dinode(dentry);
5252+ }
5253+ } else {
5254+ AuDbg("positive originally\n");
5255+ /* inode may be NULL */
5256+ AuDebugOn(inode && (inode->i_mode & S_IFMT) != orig_h.mode);
5257+ if (!tmp_h.inode) {
5258+ AuDbg("positive --> negative\n");
5259+ /* or bypassing aufs */
5260+ au_hide(dentry);
5261+ if (tmp->di_bwh >= 0 && tmp->di_bwh <= dinfo->di_bstart)
5262+ dinfo->di_bwh = tmp->di_bwh;
5263+ if (inode)
5264+ err = au_refresh_hinode_self(inode);
5265+ au_dbg_verify_dinode(dentry);
5266+ } else if (orig_h.mode == tmp_h.mode) {
5267+ AuDbg("positive --> positive, same type\n");
5268+ if (!S_ISDIR(orig_h.mode)
5269+ && dinfo->di_bstart > tmp->di_bstart) {
5270+ /*
5271+ * similar to the behaviour of removing and
5272+ * creating.
5273+ */
5274+ au_hide(dentry);
5275+ if (inode)
5276+ err = au_refresh_hinode_self(inode);
5277+ au_dbg_verify_dinode(dentry);
5278+ } else {
5279+ /* fill empty slots */
5280+ if (dinfo->di_bstart > tmp->di_bstart)
5281+ dinfo->di_bstart = tmp->di_bstart;
5282+ if (dinfo->di_bend < tmp->di_bend)
5283+ dinfo->di_bend = tmp->di_bend;
5284+ dinfo->di_bwh = tmp->di_bwh;
5285+ dinfo->di_bdiropq = tmp->di_bdiropq;
5286+ hd = tmp->di_hdentry;
5287+ bend = dinfo->di_bend;
5288+ for (bindex = tmp->di_bstart; bindex <= bend;
5289+ bindex++) {
5290+ if (au_h_dptr(dentry, bindex))
5291+ continue;
5292+ h_dentry = hd[bindex].hd_dentry;
5293+ if (!h_dentry)
5294+ continue;
5295+ h_inode = h_dentry->d_inode;
5296+ AuDebugOn(!h_inode);
5297+ AuDebugOn(orig_h.mode
5298+ != (h_inode->i_mode
5299+ & S_IFMT));
5300+ au_set_h_dptr(dentry, bindex,
5301+ dget(h_dentry));
5302+ }
5303+ err = au_refresh_hinode(inode, dentry);
5304+ au_dbg_verify_dinode(dentry);
5305+ }
5306+ } else {
5307+ AuDbg("positive --> positive, different type\n");
5308+ /* similar to the behaviour of removing and creating */
5309+ au_hide(dentry);
5310+ if (inode)
5311+ err = au_refresh_hinode_self(inode);
5312+ au_dbg_verify_dinode(dentry);
5313+ }
5314+ }
5315+
5316+out:
5317+ return err;
5318+}
5319+
5320+int au_refresh_dentry(struct dentry *dentry, struct dentry *parent)
5321+{
5322+ int err, ebrange;
5323+ unsigned int sigen;
5324+ struct au_dinfo *dinfo, *tmp;
5325+ struct super_block *sb;
5326+ struct inode *inode;
5327+
5328+ DiMustWriteLock(dentry);
5329+ AuDebugOn(IS_ROOT(dentry));
5330+ AuDebugOn(!parent->d_inode);
5331+
5332+ sb = dentry->d_sb;
5333+ inode = dentry->d_inode;
5334+ sigen = au_sigen(sb);
5335+ err = au_digen_test(parent, sigen);
5336+ if (unlikely(err))
5337+ goto out;
5338+
5339+ dinfo = au_di(dentry);
5340+ err = au_di_realloc(dinfo, au_sbend(sb) + 1);
5341+ if (unlikely(err))
5342+ goto out;
5343+ ebrange = au_dbrange_test(dentry);
5344+ if (!ebrange)
5345+ ebrange = au_do_refresh_hdentry(dentry, parent);
5346+
5347+ if (d_unhashed(dentry) || ebrange) {
5348+ AuDebugOn(au_dbstart(dentry) < 0 && au_dbend(dentry) >= 0);
5349+ if (inode)
5350+ err = au_refresh_hinode_self(inode);
5351+ au_dbg_verify_dinode(dentry);
5352+ if (!err)
5353+ goto out_dgen; /* success */
5354+ goto out;
5355+ }
5356+
5357+ /* temporary dinfo */
5358+ AuDbgDentry(dentry);
5359+ err = -ENOMEM;
5360+ tmp = au_di_alloc(sb, AuLsc_DI_TMP);
5361+ if (unlikely(!tmp))
5362+ goto out;
5363+ au_di_swap(tmp, dinfo);
5364+ /* returns the number of positive dentries */
5365+ /*
5366+ * if current working dir is removed, it returns an error.
5367+ * but the dentry is legal.
5368+ */
5369+ err = au_lkup_dentry(dentry, /*bstart*/0, /*type*/0, /*nd*/NULL);
5370+ AuDbgDentry(dentry);
5371+ au_di_swap(tmp, dinfo);
5372+ if (err == -ENOENT)
5373+ err = 0;
5374+ if (err >= 0) {
5375+ /* compare/refresh by dinfo */
5376+ AuDbgDentry(dentry);
5377+ err = au_refresh_by_dinfo(dentry, dinfo, tmp);
5378+ au_dbg_verify_dinode(dentry);
5379+ AuTraceErr(err);
5380+ }
5381+ au_rw_write_unlock(&tmp->di_rwsem);
5382+ au_di_free(tmp);
5383+ if (unlikely(err))
5384+ goto out;
5385+
5386+out_dgen:
5387+ au_update_digen(dentry);
5388+out:
5389+ if (unlikely(err && !(dentry->d_flags & DCACHE_NFSFS_RENAMED))) {
5390+ AuIOErr("failed refreshing %.*s, %d\n",
5391+ AuDLNPair(dentry), err);
5392+ AuDbgDentry(dentry);
5393+ }
5394+ AuTraceErr(err);
5395+ return err;
5396+}
5397+
5398+static noinline_for_stack
5399+int au_do_h_d_reval(struct dentry *h_dentry, struct nameidata *nd,
5400+ struct dentry *dentry, aufs_bindex_t bindex)
5401+{
5402+ int err, valid;
5403+ int (*reval)(struct dentry *, struct nameidata *);
5404+
5405+ err = 0;
5406+ if (!(h_dentry->d_flags & DCACHE_OP_REVALIDATE))
5407+ goto out;
5408+ reval = h_dentry->d_op->d_revalidate;
5409+
5410+ AuDbg("b%d\n", bindex);
5411+ if (au_test_fs_null_nd(h_dentry->d_sb))
5412+ /* it may return tri-state */
5413+ valid = reval(h_dentry, NULL);
5414+ else {
5415+ struct nameidata h_nd;
5416+ int locked;
1facf9fc 5417+ struct dentry *parent;
5418+
5419+ au_h_nd(&h_nd, nd);
5420+ parent = nd->path.dentry;
5421+ locked = (nd && nd->path.dentry != dentry);
5422+ if (locked)
5423+ di_read_lock_parent(parent, AuLock_IR);
5424+ BUG_ON(bindex > au_dbend(parent));
5425+ h_nd.path.dentry = au_h_dptr(parent, bindex);
5426+ BUG_ON(!h_nd.path.dentry);
5427+ h_nd.path.mnt = au_sbr(parent->d_sb, bindex)->br_mnt;
5428+ path_get(&h_nd.path);
5429+ valid = reval(h_dentry, &h_nd);
5430+ path_put(&h_nd.path);
5431+ if (locked)
5432+ di_read_unlock(parent, AuLock_IR);
5433+ }
5434+
5435+ if (unlikely(valid < 0))
5436+ err = valid;
5437+ else if (!valid)
5438+ err = -EINVAL;
5439+
4f0767ce 5440+out:
1facf9fc 5441+ AuTraceErr(err);
5442+ return err;
5443+}
5444+
5445+/* todo: remove this */
5446+static int h_d_revalidate(struct dentry *dentry, struct inode *inode,
5447+ struct nameidata *nd, int do_udba)
5448+{
5449+ int err;
5450+ umode_t mode, h_mode;
5451+ aufs_bindex_t bindex, btail, bstart, ibs, ibe;
5452+ unsigned char plus, unhashed, is_root, h_plus;
4a4d8108 5453+ struct inode *h_inode, *h_cached_inode;
1facf9fc 5454+ struct dentry *h_dentry;
5455+ struct qstr *name, *h_name;
5456+
5457+ err = 0;
5458+ plus = 0;
5459+ mode = 0;
1facf9fc 5460+ ibs = -1;
5461+ ibe = -1;
5462+ unhashed = !!d_unhashed(dentry);
5463+ is_root = !!IS_ROOT(dentry);
5464+ name = &dentry->d_name;
5465+
5466+ /*
7f207e10
AM
5467+ * Theoretically, REVAL test should be unnecessary in case of
5468+ * {FS,I}NOTIFY.
5469+ * But {fs,i}notify doesn't fire some necessary events,
1facf9fc 5470+ * IN_ATTRIB for atime/nlink/pageio
5471+ * IN_DELETE for NFS dentry
5472+ * Let's do REVAL test too.
5473+ */
5474+ if (do_udba && inode) {
5475+ mode = (inode->i_mode & S_IFMT);
5476+ plus = (inode->i_nlink > 0);
1facf9fc 5477+ ibs = au_ibstart(inode);
5478+ ibe = au_ibend(inode);
5479+ }
5480+
5481+ bstart = au_dbstart(dentry);
5482+ btail = bstart;
5483+ if (inode && S_ISDIR(inode->i_mode))
5484+ btail = au_dbtaildir(dentry);
5485+ for (bindex = bstart; bindex <= btail; bindex++) {
5486+ h_dentry = au_h_dptr(dentry, bindex);
5487+ if (!h_dentry)
5488+ continue;
5489+
5490+ AuDbg("b%d, %.*s\n", bindex, AuDLNPair(h_dentry));
027c5e7a 5491+ spin_lock(&h_dentry->d_lock);
1facf9fc 5492+ h_name = &h_dentry->d_name;
5493+ if (unlikely(do_udba
5494+ && !is_root
5495+ && (unhashed != !!d_unhashed(h_dentry)
5496+ || name->len != h_name->len
5497+ || memcmp(name->name, h_name->name, name->len))
5498+ )) {
5499+ AuDbg("unhash 0x%x 0x%x, %.*s %.*s\n",
5500+ unhashed, d_unhashed(h_dentry),
5501+ AuDLNPair(dentry), AuDLNPair(h_dentry));
027c5e7a 5502+ spin_unlock(&h_dentry->d_lock);
1facf9fc 5503+ goto err;
5504+ }
027c5e7a 5505+ spin_unlock(&h_dentry->d_lock);
1facf9fc 5506+
5507+ err = au_do_h_d_reval(h_dentry, nd, dentry, bindex);
5508+ if (unlikely(err))
5509+ /* do not goto err, to keep the errno */
5510+ break;
5511+
5512+ /* todo: plink too? */
5513+ if (!do_udba)
5514+ continue;
5515+
5516+ /* UDBA tests */
5517+ h_inode = h_dentry->d_inode;
5518+ if (unlikely(!!inode != !!h_inode))
5519+ goto err;
5520+
5521+ h_plus = plus;
5522+ h_mode = mode;
5523+ h_cached_inode = h_inode;
5524+ if (h_inode) {
5525+ h_mode = (h_inode->i_mode & S_IFMT);
5526+ h_plus = (h_inode->i_nlink > 0);
5527+ }
5528+ if (inode && ibs <= bindex && bindex <= ibe)
5529+ h_cached_inode = au_h_iptr(inode, bindex);
5530+
5531+ if (unlikely(plus != h_plus
5532+ || mode != h_mode
5533+ || h_cached_inode != h_inode))
5534+ goto err;
5535+ continue;
5536+
5537+ err:
5538+ err = -EINVAL;
5539+ break;
5540+ }
5541+
5542+ return err;
5543+}
5544+
027c5e7a 5545+/* todo: consolidate with do_refresh() and au_reval_for_attr() */
1facf9fc 5546+static int simple_reval_dpath(struct dentry *dentry, unsigned int sigen)
5547+{
5548+ int err;
5549+ struct dentry *parent;
1facf9fc 5550+
027c5e7a 5551+ if (!au_digen_test(dentry, sigen))
1facf9fc 5552+ return 0;
5553+
5554+ parent = dget_parent(dentry);
5555+ di_read_lock_parent(parent, AuLock_IR);
027c5e7a 5556+ AuDebugOn(au_digen_test(parent, sigen));
1facf9fc 5557+ au_dbg_verify_gen(parent, sigen);
027c5e7a 5558+ err = au_refresh_dentry(dentry, parent);
1facf9fc 5559+ di_read_unlock(parent, AuLock_IR);
5560+ dput(parent);
027c5e7a 5561+ AuTraceErr(err);
1facf9fc 5562+ return err;
5563+}
5564+
5565+int au_reval_dpath(struct dentry *dentry, unsigned int sigen)
5566+{
5567+ int err;
5568+ struct dentry *d, *parent;
5569+ struct inode *inode;
5570+
027c5e7a 5571+ if (!au_ftest_si(au_sbi(dentry->d_sb), FAILED_REFRESH_DIR))
1facf9fc 5572+ return simple_reval_dpath(dentry, sigen);
5573+
5574+ /* slow loop, keep it simple and stupid */
5575+ /* cf: au_cpup_dirs() */
5576+ err = 0;
5577+ parent = NULL;
027c5e7a 5578+ while (au_digen_test(dentry, sigen)) {
1facf9fc 5579+ d = dentry;
5580+ while (1) {
5581+ dput(parent);
5582+ parent = dget_parent(d);
027c5e7a 5583+ if (!au_digen_test(parent, sigen))
1facf9fc 5584+ break;
5585+ d = parent;
5586+ }
5587+
5588+ inode = d->d_inode;
5589+ if (d != dentry)
027c5e7a 5590+ di_write_lock_child2(d);
1facf9fc 5591+
5592+ /* someone might update our dentry while we were sleeping */
027c5e7a
AM
5593+ if (au_digen_test(d, sigen)) {
5594+ /*
5595+ * todo: consolidate with simple_reval_dpath(),
5596+ * do_refresh() and au_reval_for_attr().
5597+ */
1facf9fc 5598+ di_read_lock_parent(parent, AuLock_IR);
027c5e7a 5599+ err = au_refresh_dentry(d, parent);
1facf9fc 5600+ di_read_unlock(parent, AuLock_IR);
5601+ }
5602+
5603+ if (d != dentry)
5604+ di_write_unlock(d);
5605+ dput(parent);
5606+ if (unlikely(err))
5607+ break;
5608+ }
5609+
5610+ return err;
5611+}
5612+
5613+/*
5614+ * if valid returns 1, otherwise 0.
5615+ */
5616+static int aufs_d_revalidate(struct dentry *dentry, struct nameidata *nd)
5617+{
5618+ int valid, err;
5619+ unsigned int sigen;
5620+ unsigned char do_udba;
5621+ struct super_block *sb;
5622+ struct inode *inode;
5623+
027c5e7a
AM
5624+ /* todo: support rcu-walk? */
5625+ if (nd && (nd->flags & LOOKUP_RCU))
5626+ return -ECHILD;
5627+
5628+ valid = 0;
5629+ if (unlikely(!au_di(dentry)))
5630+ goto out;
5631+
5632+ inode = dentry->d_inode;
5633+ if (inode && is_bad_inode(inode))
5634+ goto out;
5635+
e49829fe 5636+ valid = 1;
1facf9fc 5637+ sb = dentry->d_sb;
e49829fe
JR
5638+ /*
5639+ * todo: very ugly
5640+ * i_mutex of parent dir may be held,
5641+ * but we should not return 'invalid' due to busy.
5642+ */
5643+ err = aufs_read_lock(dentry, AuLock_FLUSH | AuLock_DW | AuLock_NOPLM);
5644+ if (unlikely(err)) {
5645+ valid = err;
027c5e7a 5646+ AuTraceErr(err);
e49829fe
JR
5647+ goto out;
5648+ }
027c5e7a
AM
5649+ if (unlikely(au_dbrange_test(dentry))) {
5650+ err = -EINVAL;
5651+ AuTraceErr(err);
5652+ goto out_dgrade;
1facf9fc 5653+ }
027c5e7a
AM
5654+
5655+ sigen = au_sigen(sb);
5656+ if (au_digen_test(dentry, sigen)) {
1facf9fc 5657+ AuDebugOn(IS_ROOT(dentry));
027c5e7a
AM
5658+ err = au_reval_dpath(dentry, sigen);
5659+ if (unlikely(err)) {
5660+ AuTraceErr(err);
1facf9fc 5661+ goto out_dgrade;
027c5e7a 5662+ }
1facf9fc 5663+ }
5664+ di_downgrade_lock(dentry, AuLock_IR);
5665+
1facf9fc 5666+ err = -EINVAL;
027c5e7a
AM
5667+ if (inode && (IS_DEADDIR(inode) || !inode->i_nlink))
5668+ goto out_inval;
5669+
1facf9fc 5670+ do_udba = !au_opt_test(au_mntflags(sb), UDBA_NONE);
5671+ if (do_udba && inode) {
5672+ aufs_bindex_t bstart = au_ibstart(inode);
027c5e7a 5673+ struct inode *h_inode;
1facf9fc 5674+
027c5e7a
AM
5675+ if (bstart >= 0) {
5676+ h_inode = au_h_iptr(inode, bstart);
5677+ if (h_inode && au_test_higen(inode, h_inode))
5678+ goto out_inval;
5679+ }
1facf9fc 5680+ }
5681+
5682+ err = h_d_revalidate(dentry, inode, nd, do_udba);
027c5e7a 5683+ if (unlikely(!err && do_udba && au_dbstart(dentry) < 0)) {
1facf9fc 5684+ err = -EIO;
027c5e7a
AM
5685+ AuDbg("both of real entry and whiteout found, %.*s, err %d\n",
5686+ AuDLNPair(dentry), err);
5687+ }
e49829fe 5688+ goto out_inval;
1facf9fc 5689+
4f0767ce 5690+out_dgrade:
1facf9fc 5691+ di_downgrade_lock(dentry, AuLock_IR);
e49829fe 5692+out_inval:
1facf9fc 5693+ aufs_read_unlock(dentry, AuLock_IR);
5694+ AuTraceErr(err);
5695+ valid = !err;
e49829fe 5696+out:
027c5e7a 5697+ if (!valid) {
e49829fe 5698+ AuDbg("%.*s invalid, %d\n", AuDLNPair(dentry), valid);
027c5e7a
AM
5699+ d_drop(dentry);
5700+ }
1facf9fc 5701+ return valid;
5702+}
5703+
5704+static void aufs_d_release(struct dentry *dentry)
5705+{
027c5e7a 5706+ if (au_di(dentry)) {
4a4d8108
AM
5707+ au_di_fin(dentry);
5708+ au_hn_di_reinit(dentry);
1facf9fc 5709+ }
1facf9fc 5710+}
5711+
4a4d8108 5712+const struct dentry_operations aufs_dop = {
1facf9fc 5713+ .d_revalidate = aufs_d_revalidate,
5714+ .d_release = aufs_d_release
5715+};
7f207e10
AM
5716diff -urN /usr/share/empty/fs/aufs/dentry.h linux/fs/aufs/dentry.h
5717--- /usr/share/empty/fs/aufs/dentry.h 1970-01-01 01:00:00.000000000 +0100
2cbb1c4b
JR
5718+++ linux/fs/aufs/dentry.h 2011-07-11 11:34:24.072331673 +0200
5719@@ -0,0 +1,238 @@
1facf9fc 5720+/*
027c5e7a 5721+ * Copyright (C) 2005-2011 Junjiro R. Okajima
1facf9fc 5722+ *
5723+ * This program, aufs is free software; you can redistribute it and/or modify
5724+ * it under the terms of the GNU General Public License as published by
5725+ * the Free Software Foundation; either version 2 of the License, or
5726+ * (at your option) any later version.
dece6358
AM
5727+ *
5728+ * This program is distributed in the hope that it will be useful,
5729+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
5730+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
5731+ * GNU General Public License for more details.
5732+ *
5733+ * You should have received a copy of the GNU General Public License
5734+ * along with this program; if not, write to the Free Software
5735+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 5736+ */
5737+
5738+/*
5739+ * lookup and dentry operations
5740+ */
5741+
5742+#ifndef __AUFS_DENTRY_H__
5743+#define __AUFS_DENTRY_H__
5744+
5745+#ifdef __KERNEL__
5746+
dece6358 5747+#include <linux/dcache.h>
1facf9fc 5748+#include <linux/aufs_type.h>
5749+#include "rwsem.h"
5750+
1facf9fc 5751+struct au_hdentry {
5752+ struct dentry *hd_dentry;
027c5e7a 5753+ aufs_bindex_t hd_id;
1facf9fc 5754+};
5755+
5756+struct au_dinfo {
5757+ atomic_t di_generation;
5758+
dece6358 5759+ struct au_rwsem di_rwsem;
1facf9fc 5760+ aufs_bindex_t di_bstart, di_bend, di_bwh, di_bdiropq;
5761+ struct au_hdentry *di_hdentry;
4a4d8108 5762+} ____cacheline_aligned_in_smp;
1facf9fc 5763+
5764+/* ---------------------------------------------------------------------- */
5765+
5766+/* dentry.c */
4a4d8108 5767+extern const struct dentry_operations aufs_dop;
1facf9fc 5768+struct au_branch;
5769+struct dentry *au_lkup_one(struct qstr *name, struct dentry *h_parent,
5770+ struct au_branch *br, struct nameidata *nd);
5771+struct dentry *au_sio_lkup_one(struct qstr *name, struct dentry *parent,
5772+ struct au_branch *br);
5773+int au_h_verify(struct dentry *h_dentry, unsigned int udba, struct inode *h_dir,
5774+ struct dentry *h_parent, struct au_branch *br);
5775+
5776+int au_lkup_dentry(struct dentry *dentry, aufs_bindex_t bstart, mode_t type,
5777+ struct nameidata *nd);
5778+int au_lkup_neg(struct dentry *dentry, aufs_bindex_t bindex);
027c5e7a 5779+int au_refresh_dentry(struct dentry *dentry, struct dentry *parent);
1facf9fc 5780+int au_reval_dpath(struct dentry *dentry, unsigned int sigen);
5781+
5782+/* dinfo.c */
4a4d8108 5783+void au_di_init_once(void *_di);
027c5e7a
AM
5784+struct au_dinfo *au_di_alloc(struct super_block *sb, unsigned int lsc);
5785+void au_di_free(struct au_dinfo *dinfo);
5786+void au_di_swap(struct au_dinfo *a, struct au_dinfo *b);
5787+void au_di_cp(struct au_dinfo *dst, struct au_dinfo *src);
4a4d8108
AM
5788+int au_di_init(struct dentry *dentry);
5789+void au_di_fin(struct dentry *dentry);
1facf9fc 5790+int au_di_realloc(struct au_dinfo *dinfo, int nbr);
5791+
5792+void di_read_lock(struct dentry *d, int flags, unsigned int lsc);
5793+void di_read_unlock(struct dentry *d, int flags);
5794+void di_downgrade_lock(struct dentry *d, int flags);
5795+void di_write_lock(struct dentry *d, unsigned int lsc);
5796+void di_write_unlock(struct dentry *d);
5797+void di_write_lock2_child(struct dentry *d1, struct dentry *d2, int isdir);
5798+void di_write_lock2_parent(struct dentry *d1, struct dentry *d2, int isdir);
5799+void di_write_unlock2(struct dentry *d1, struct dentry *d2);
5800+
5801+struct dentry *au_h_dptr(struct dentry *dentry, aufs_bindex_t bindex);
2cbb1c4b 5802+struct dentry *au_h_d_alias(struct dentry *dentry, aufs_bindex_t bindex);
1facf9fc 5803+aufs_bindex_t au_dbtail(struct dentry *dentry);
5804+aufs_bindex_t au_dbtaildir(struct dentry *dentry);
5805+
5806+void au_set_h_dptr(struct dentry *dentry, aufs_bindex_t bindex,
5807+ struct dentry *h_dentry);
027c5e7a
AM
5808+int au_digen_test(struct dentry *dentry, unsigned int sigen);
5809+int au_dbrange_test(struct dentry *dentry);
1facf9fc 5810+void au_update_digen(struct dentry *dentry);
5811+void au_update_dbrange(struct dentry *dentry, int do_put_zero);
5812+void au_update_dbstart(struct dentry *dentry);
5813+void au_update_dbend(struct dentry *dentry);
5814+int au_find_dbindex(struct dentry *dentry, struct dentry *h_dentry);
5815+
5816+/* ---------------------------------------------------------------------- */
5817+
5818+static inline struct au_dinfo *au_di(struct dentry *dentry)
5819+{
5820+ return dentry->d_fsdata;
5821+}
5822+
5823+/* ---------------------------------------------------------------------- */
5824+
5825+/* lock subclass for dinfo */
5826+enum {
5827+ AuLsc_DI_CHILD, /* child first */
4a4d8108 5828+ AuLsc_DI_CHILD2, /* rename(2), link(2), and cpup at hnotify */
1facf9fc 5829+ AuLsc_DI_CHILD3, /* copyup dirs */
5830+ AuLsc_DI_PARENT,
5831+ AuLsc_DI_PARENT2,
027c5e7a
AM
5832+ AuLsc_DI_PARENT3,
5833+ AuLsc_DI_TMP /* temp for replacing dinfo */
1facf9fc 5834+};
5835+
5836+/*
5837+ * di_read_lock_child, di_write_lock_child,
5838+ * di_read_lock_child2, di_write_lock_child2,
5839+ * di_read_lock_child3, di_write_lock_child3,
5840+ * di_read_lock_parent, di_write_lock_parent,
5841+ * di_read_lock_parent2, di_write_lock_parent2,
5842+ * di_read_lock_parent3, di_write_lock_parent3,
5843+ */
5844+#define AuReadLockFunc(name, lsc) \
5845+static inline void di_read_lock_##name(struct dentry *d, int flags) \
5846+{ di_read_lock(d, flags, AuLsc_DI_##lsc); }
5847+
5848+#define AuWriteLockFunc(name, lsc) \
5849+static inline void di_write_lock_##name(struct dentry *d) \
5850+{ di_write_lock(d, AuLsc_DI_##lsc); }
5851+
5852+#define AuRWLockFuncs(name, lsc) \
5853+ AuReadLockFunc(name, lsc) \
5854+ AuWriteLockFunc(name, lsc)
5855+
5856+AuRWLockFuncs(child, CHILD);
5857+AuRWLockFuncs(child2, CHILD2);
5858+AuRWLockFuncs(child3, CHILD3);
5859+AuRWLockFuncs(parent, PARENT);
5860+AuRWLockFuncs(parent2, PARENT2);
5861+AuRWLockFuncs(parent3, PARENT3);
5862+
5863+#undef AuReadLockFunc
5864+#undef AuWriteLockFunc
5865+#undef AuRWLockFuncs
5866+
5867+#define DiMustNoWaiters(d) AuRwMustNoWaiters(&au_di(d)->di_rwsem)
dece6358
AM
5868+#define DiMustAnyLock(d) AuRwMustAnyLock(&au_di(d)->di_rwsem)
5869+#define DiMustWriteLock(d) AuRwMustWriteLock(&au_di(d)->di_rwsem)
1facf9fc 5870+
5871+/* ---------------------------------------------------------------------- */
5872+
5873+/* todo: memory barrier? */
5874+static inline unsigned int au_digen(struct dentry *d)
5875+{
5876+ return atomic_read(&au_di(d)->di_generation);
5877+}
5878+
5879+static inline void au_h_dentry_init(struct au_hdentry *hdentry)
5880+{
5881+ hdentry->hd_dentry = NULL;
5882+}
5883+
5884+static inline void au_hdput(struct au_hdentry *hd)
5885+{
4a4d8108
AM
5886+ if (hd)
5887+ dput(hd->hd_dentry);
1facf9fc 5888+}
5889+
5890+static inline aufs_bindex_t au_dbstart(struct dentry *dentry)
5891+{
1308ab2a 5892+ DiMustAnyLock(dentry);
1facf9fc 5893+ return au_di(dentry)->di_bstart;
5894+}
5895+
5896+static inline aufs_bindex_t au_dbend(struct dentry *dentry)
5897+{
1308ab2a 5898+ DiMustAnyLock(dentry);
1facf9fc 5899+ return au_di(dentry)->di_bend;
5900+}
5901+
5902+static inline aufs_bindex_t au_dbwh(struct dentry *dentry)
5903+{
1308ab2a 5904+ DiMustAnyLock(dentry);
1facf9fc 5905+ return au_di(dentry)->di_bwh;
5906+}
5907+
5908+static inline aufs_bindex_t au_dbdiropq(struct dentry *dentry)
5909+{
1308ab2a 5910+ DiMustAnyLock(dentry);
1facf9fc 5911+ return au_di(dentry)->di_bdiropq;
5912+}
5913+
5914+/* todo: hard/soft set? */
5915+static inline void au_set_dbstart(struct dentry *dentry, aufs_bindex_t bindex)
5916+{
1308ab2a 5917+ DiMustWriteLock(dentry);
1facf9fc 5918+ au_di(dentry)->di_bstart = bindex;
5919+}
5920+
5921+static inline void au_set_dbend(struct dentry *dentry, aufs_bindex_t bindex)
5922+{
1308ab2a 5923+ DiMustWriteLock(dentry);
1facf9fc 5924+ au_di(dentry)->di_bend = bindex;
5925+}
5926+
5927+static inline void au_set_dbwh(struct dentry *dentry, aufs_bindex_t bindex)
5928+{
1308ab2a 5929+ DiMustWriteLock(dentry);
1facf9fc 5930+ /* dbwh can be outside of bstart - bend range */
5931+ au_di(dentry)->di_bwh = bindex;
5932+}
5933+
5934+static inline void au_set_dbdiropq(struct dentry *dentry, aufs_bindex_t bindex)
5935+{
1308ab2a 5936+ DiMustWriteLock(dentry);
1facf9fc 5937+ au_di(dentry)->di_bdiropq = bindex;
5938+}
5939+
5940+/* ---------------------------------------------------------------------- */
5941+
4a4d8108 5942+#ifdef CONFIG_AUFS_HNOTIFY
1facf9fc 5943+static inline void au_digen_dec(struct dentry *d)
5944+{
e49829fe 5945+ atomic_dec(&au_di(d)->di_generation);
1facf9fc 5946+}
5947+
4a4d8108 5948+static inline void au_hn_di_reinit(struct dentry *dentry)
1facf9fc 5949+{
5950+ dentry->d_fsdata = NULL;
5951+}
5952+#else
4a4d8108
AM
5953+AuStubVoid(au_hn_di_reinit, struct dentry *dentry __maybe_unused)
5954+#endif /* CONFIG_AUFS_HNOTIFY */
1facf9fc 5955+
5956+#endif /* __KERNEL__ */
5957+#endif /* __AUFS_DENTRY_H__ */
7f207e10
AM
5958diff -urN /usr/share/empty/fs/aufs/dinfo.c linux/fs/aufs/dinfo.c
5959--- /usr/share/empty/fs/aufs/dinfo.c 1970-01-01 01:00:00.000000000 +0100
2cbb1c4b
JR
5960+++ linux/fs/aufs/dinfo.c 2011-07-11 11:34:24.072331673 +0200
5961@@ -0,0 +1,543 @@
1facf9fc 5962+/*
027c5e7a 5963+ * Copyright (C) 2005-2011 Junjiro R. Okajima
1facf9fc 5964+ *
5965+ * This program, aufs is free software; you can redistribute it and/or modify
5966+ * it under the terms of the GNU General Public License as published by
5967+ * the Free Software Foundation; either version 2 of the License, or
5968+ * (at your option) any later version.
dece6358
AM
5969+ *
5970+ * This program is distributed in the hope that it will be useful,
5971+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
5972+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
5973+ * GNU General Public License for more details.
5974+ *
5975+ * You should have received a copy of the GNU General Public License
5976+ * along with this program; if not, write to the Free Software
5977+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 5978+ */
5979+
5980+/*
5981+ * dentry private data
5982+ */
5983+
5984+#include "aufs.h"
5985+
e49829fe 5986+void au_di_init_once(void *_dinfo)
4a4d8108 5987+{
e49829fe
JR
5988+ struct au_dinfo *dinfo = _dinfo;
5989+ static struct lock_class_key aufs_di;
4a4d8108 5990+
e49829fe
JR
5991+ au_rw_init(&dinfo->di_rwsem);
5992+ au_rw_class(&dinfo->di_rwsem, &aufs_di);
4a4d8108
AM
5993+}
5994+
027c5e7a 5995+struct au_dinfo *au_di_alloc(struct super_block *sb, unsigned int lsc)
1facf9fc 5996+{
5997+ struct au_dinfo *dinfo;
027c5e7a 5998+ int nbr, i;
1facf9fc 5999+
6000+ dinfo = au_cache_alloc_dinfo();
6001+ if (unlikely(!dinfo))
6002+ goto out;
6003+
1facf9fc 6004+ nbr = au_sbend(sb) + 1;
6005+ if (nbr <= 0)
6006+ nbr = 1;
6007+ dinfo->di_hdentry = kcalloc(nbr, sizeof(*dinfo->di_hdentry), GFP_NOFS);
027c5e7a
AM
6008+ if (dinfo->di_hdentry) {
6009+ au_rw_write_lock_nested(&dinfo->di_rwsem, lsc);
6010+ dinfo->di_bstart = -1;
6011+ dinfo->di_bend = -1;
6012+ dinfo->di_bwh = -1;
6013+ dinfo->di_bdiropq = -1;
6014+ for (i = 0; i < nbr; i++)
6015+ dinfo->di_hdentry[i].hd_id = -1;
6016+ goto out;
6017+ }
1facf9fc 6018+
1facf9fc 6019+ au_cache_free_dinfo(dinfo);
027c5e7a
AM
6020+ dinfo = NULL;
6021+
4f0767ce 6022+out:
027c5e7a 6023+ return dinfo;
1facf9fc 6024+}
6025+
027c5e7a 6026+void au_di_free(struct au_dinfo *dinfo)
4a4d8108 6027+{
4a4d8108
AM
6028+ struct au_hdentry *p;
6029+ aufs_bindex_t bend, bindex;
6030+
6031+ /* dentry may not be revalidated */
027c5e7a 6032+ bindex = dinfo->di_bstart;
4a4d8108 6033+ if (bindex >= 0) {
027c5e7a
AM
6034+ bend = dinfo->di_bend;
6035+ p = dinfo->di_hdentry + bindex;
4a4d8108
AM
6036+ while (bindex++ <= bend)
6037+ au_hdput(p++);
6038+ }
027c5e7a
AM
6039+ kfree(dinfo->di_hdentry);
6040+ au_cache_free_dinfo(dinfo);
6041+}
6042+
6043+void au_di_swap(struct au_dinfo *a, struct au_dinfo *b)
6044+{
6045+ struct au_hdentry *p;
6046+ aufs_bindex_t bi;
6047+
6048+ AuRwMustWriteLock(&a->di_rwsem);
6049+ AuRwMustWriteLock(&b->di_rwsem);
6050+
6051+#define DiSwap(v, name) \
6052+ do { \
6053+ v = a->di_##name; \
6054+ a->di_##name = b->di_##name; \
6055+ b->di_##name = v; \
6056+ } while (0)
6057+
6058+ DiSwap(p, hdentry);
6059+ DiSwap(bi, bstart);
6060+ DiSwap(bi, bend);
6061+ DiSwap(bi, bwh);
6062+ DiSwap(bi, bdiropq);
6063+ /* smp_mb(); */
6064+
6065+#undef DiSwap
6066+}
6067+
6068+void au_di_cp(struct au_dinfo *dst, struct au_dinfo *src)
6069+{
6070+ AuRwMustWriteLock(&dst->di_rwsem);
6071+ AuRwMustWriteLock(&src->di_rwsem);
6072+
6073+ dst->di_bstart = src->di_bstart;
6074+ dst->di_bend = src->di_bend;
6075+ dst->di_bwh = src->di_bwh;
6076+ dst->di_bdiropq = src->di_bdiropq;
6077+ /* smp_mb(); */
6078+}
6079+
6080+int au_di_init(struct dentry *dentry)
6081+{
6082+ int err;
6083+ struct super_block *sb;
6084+ struct au_dinfo *dinfo;
6085+
6086+ err = 0;
6087+ sb = dentry->d_sb;
6088+ dinfo = au_di_alloc(sb, AuLsc_DI_CHILD);
6089+ if (dinfo) {
6090+ atomic_set(&dinfo->di_generation, au_sigen(sb));
6091+ /* smp_mb(); */ /* atomic_set */
6092+ dentry->d_fsdata = dinfo;
6093+ } else
6094+ err = -ENOMEM;
6095+
6096+ return err;
6097+}
6098+
6099+void au_di_fin(struct dentry *dentry)
6100+{
6101+ struct au_dinfo *dinfo;
6102+
6103+ dinfo = au_di(dentry);
6104+ AuRwDestroy(&dinfo->di_rwsem);
6105+ au_di_free(dinfo);
4a4d8108
AM
6106+}
6107+
1facf9fc 6108+int au_di_realloc(struct au_dinfo *dinfo, int nbr)
6109+{
6110+ int err, sz;
6111+ struct au_hdentry *hdp;
6112+
1308ab2a 6113+ AuRwMustWriteLock(&dinfo->di_rwsem);
6114+
1facf9fc 6115+ err = -ENOMEM;
6116+ sz = sizeof(*hdp) * (dinfo->di_bend + 1);
6117+ if (!sz)
6118+ sz = sizeof(*hdp);
6119+ hdp = au_kzrealloc(dinfo->di_hdentry, sz, sizeof(*hdp) * nbr, GFP_NOFS);
6120+ if (hdp) {
6121+ dinfo->di_hdentry = hdp;
6122+ err = 0;
6123+ }
6124+
6125+ return err;
6126+}
6127+
6128+/* ---------------------------------------------------------------------- */
6129+
6130+static void do_ii_write_lock(struct inode *inode, unsigned int lsc)
6131+{
6132+ switch (lsc) {
6133+ case AuLsc_DI_CHILD:
6134+ ii_write_lock_child(inode);
6135+ break;
6136+ case AuLsc_DI_CHILD2:
6137+ ii_write_lock_child2(inode);
6138+ break;
6139+ case AuLsc_DI_CHILD3:
6140+ ii_write_lock_child3(inode);
6141+ break;
6142+ case AuLsc_DI_PARENT:
6143+ ii_write_lock_parent(inode);
6144+ break;
6145+ case AuLsc_DI_PARENT2:
6146+ ii_write_lock_parent2(inode);
6147+ break;
6148+ case AuLsc_DI_PARENT3:
6149+ ii_write_lock_parent3(inode);
6150+ break;
6151+ default:
6152+ BUG();
6153+ }
6154+}
6155+
6156+static void do_ii_read_lock(struct inode *inode, unsigned int lsc)
6157+{
6158+ switch (lsc) {
6159+ case AuLsc_DI_CHILD:
6160+ ii_read_lock_child(inode);
6161+ break;
6162+ case AuLsc_DI_CHILD2:
6163+ ii_read_lock_child2(inode);
6164+ break;
6165+ case AuLsc_DI_CHILD3:
6166+ ii_read_lock_child3(inode);
6167+ break;
6168+ case AuLsc_DI_PARENT:
6169+ ii_read_lock_parent(inode);
6170+ break;
6171+ case AuLsc_DI_PARENT2:
6172+ ii_read_lock_parent2(inode);
6173+ break;
6174+ case AuLsc_DI_PARENT3:
6175+ ii_read_lock_parent3(inode);
6176+ break;
6177+ default:
6178+ BUG();
6179+ }
6180+}
6181+
6182+void di_read_lock(struct dentry *d, int flags, unsigned int lsc)
6183+{
dece6358 6184+ au_rw_read_lock_nested(&au_di(d)->di_rwsem, lsc);
1facf9fc 6185+ if (d->d_inode) {
6186+ if (au_ftest_lock(flags, IW))
6187+ do_ii_write_lock(d->d_inode, lsc);
6188+ else if (au_ftest_lock(flags, IR))
6189+ do_ii_read_lock(d->d_inode, lsc);
6190+ }
6191+}
6192+
6193+void di_read_unlock(struct dentry *d, int flags)
6194+{
6195+ if (d->d_inode) {
027c5e7a
AM
6196+ if (au_ftest_lock(flags, IW)) {
6197+ au_dbg_verify_dinode(d);
1facf9fc 6198+ ii_write_unlock(d->d_inode);
027c5e7a
AM
6199+ } else if (au_ftest_lock(flags, IR)) {
6200+ au_dbg_verify_dinode(d);
1facf9fc 6201+ ii_read_unlock(d->d_inode);
027c5e7a 6202+ }
1facf9fc 6203+ }
dece6358 6204+ au_rw_read_unlock(&au_di(d)->di_rwsem);
1facf9fc 6205+}
6206+
6207+void di_downgrade_lock(struct dentry *d, int flags)
6208+{
1facf9fc 6209+ if (d->d_inode && au_ftest_lock(flags, IR))
6210+ ii_downgrade_lock(d->d_inode);
dece6358 6211+ au_rw_dgrade_lock(&au_di(d)->di_rwsem);
1facf9fc 6212+}
6213+
6214+void di_write_lock(struct dentry *d, unsigned int lsc)
6215+{
dece6358 6216+ au_rw_write_lock_nested(&au_di(d)->di_rwsem, lsc);
1facf9fc 6217+ if (d->d_inode)
6218+ do_ii_write_lock(d->d_inode, lsc);
6219+}
6220+
6221+void di_write_unlock(struct dentry *d)
6222+{
027c5e7a 6223+ au_dbg_verify_dinode(d);
1facf9fc 6224+ if (d->d_inode)
6225+ ii_write_unlock(d->d_inode);
dece6358 6226+ au_rw_write_unlock(&au_di(d)->di_rwsem);
1facf9fc 6227+}
6228+
6229+void di_write_lock2_child(struct dentry *d1, struct dentry *d2, int isdir)
6230+{
6231+ AuDebugOn(d1 == d2
6232+ || d1->d_inode == d2->d_inode
6233+ || d1->d_sb != d2->d_sb);
6234+
6235+ if (isdir && au_test_subdir(d1, d2)) {
6236+ di_write_lock_child(d1);
6237+ di_write_lock_child2(d2);
6238+ } else {
6239+ /* there should be no races */
6240+ di_write_lock_child(d2);
6241+ di_write_lock_child2(d1);
6242+ }
6243+}
6244+
6245+void di_write_lock2_parent(struct dentry *d1, struct dentry *d2, int isdir)
6246+{
6247+ AuDebugOn(d1 == d2
6248+ || d1->d_inode == d2->d_inode
6249+ || d1->d_sb != d2->d_sb);
6250+
6251+ if (isdir && au_test_subdir(d1, d2)) {
6252+ di_write_lock_parent(d1);
6253+ di_write_lock_parent2(d2);
6254+ } else {
6255+ /* there should be no races */
6256+ di_write_lock_parent(d2);
6257+ di_write_lock_parent2(d1);
6258+ }
6259+}
6260+
6261+void di_write_unlock2(struct dentry *d1, struct dentry *d2)
6262+{
6263+ di_write_unlock(d1);
6264+ if (d1->d_inode == d2->d_inode)
dece6358 6265+ au_rw_write_unlock(&au_di(d2)->di_rwsem);
1facf9fc 6266+ else
6267+ di_write_unlock(d2);
6268+}
6269+
6270+/* ---------------------------------------------------------------------- */
6271+
6272+struct dentry *au_h_dptr(struct dentry *dentry, aufs_bindex_t bindex)
6273+{
6274+ struct dentry *d;
6275+
1308ab2a 6276+ DiMustAnyLock(dentry);
6277+
1facf9fc 6278+ if (au_dbstart(dentry) < 0 || bindex < au_dbstart(dentry))
6279+ return NULL;
6280+ AuDebugOn(bindex < 0);
6281+ d = au_di(dentry)->di_hdentry[0 + bindex].hd_dentry;
027c5e7a 6282+ AuDebugOn(d && d->d_count <= 0);
1facf9fc 6283+ return d;
6284+}
6285+
2cbb1c4b
JR
6286+/*
6287+ * extended version of au_h_dptr().
6288+ * returns a hashed and positive h_dentry in bindex, NULL, or error.
6289+ */
6290+struct dentry *au_h_d_alias(struct dentry *dentry, aufs_bindex_t bindex)
6291+{
6292+ struct dentry *h_dentry;
6293+ struct inode *inode, *h_inode;
6294+
6295+ inode = dentry->d_inode;
6296+ AuDebugOn(!inode);
6297+
6298+ h_dentry = NULL;
6299+ if (au_dbstart(dentry) <= bindex
6300+ && bindex <= au_dbend(dentry))
6301+ h_dentry = au_h_dptr(dentry, bindex);
6302+ if (h_dentry && !au_d_hashed_positive(h_dentry)) {
6303+ dget(h_dentry);
6304+ goto out; /* success */
6305+ }
6306+
6307+ AuDebugOn(bindex < au_ibstart(inode));
6308+ AuDebugOn(au_ibend(inode) < bindex);
6309+ h_inode = au_h_iptr(inode, bindex);
6310+ h_dentry = d_find_alias(h_inode);
6311+ if (h_dentry) {
6312+ if (!IS_ERR(h_dentry)) {
6313+ if (!au_d_hashed_positive(h_dentry))
6314+ goto out; /* success */
6315+ dput(h_dentry);
6316+ } else
6317+ goto out;
6318+ }
6319+
6320+ if (au_opt_test(au_mntflags(dentry->d_sb), PLINK)) {
6321+ h_dentry = au_plink_lkup(inode, bindex);
6322+ AuDebugOn(!h_dentry);
6323+ if (!IS_ERR(h_dentry)) {
6324+ if (!au_d_hashed_positive(h_dentry))
6325+ goto out; /* success */
6326+ dput(h_dentry);
6327+ h_dentry = NULL;
6328+ }
6329+ }
6330+
6331+out:
6332+ AuDbgDentry(h_dentry);
6333+ return h_dentry;
6334+}
6335+
1facf9fc 6336+aufs_bindex_t au_dbtail(struct dentry *dentry)
6337+{
6338+ aufs_bindex_t bend, bwh;
6339+
6340+ bend = au_dbend(dentry);
6341+ if (0 <= bend) {
6342+ bwh = au_dbwh(dentry);
6343+ if (!bwh)
6344+ return bwh;
6345+ if (0 < bwh && bwh < bend)
6346+ return bwh - 1;
6347+ }
6348+ return bend;
6349+}
6350+
6351+aufs_bindex_t au_dbtaildir(struct dentry *dentry)
6352+{
6353+ aufs_bindex_t bend, bopq;
6354+
6355+ bend = au_dbtail(dentry);
6356+ if (0 <= bend) {
6357+ bopq = au_dbdiropq(dentry);
6358+ if (0 <= bopq && bopq < bend)
6359+ bend = bopq;
6360+ }
6361+ return bend;
6362+}
6363+
6364+/* ---------------------------------------------------------------------- */
6365+
6366+void au_set_h_dptr(struct dentry *dentry, aufs_bindex_t bindex,
6367+ struct dentry *h_dentry)
6368+{
6369+ struct au_hdentry *hd = au_di(dentry)->di_hdentry + bindex;
027c5e7a 6370+ struct au_branch *br;
1facf9fc 6371+
1308ab2a 6372+ DiMustWriteLock(dentry);
6373+
4a4d8108 6374+ au_hdput(hd);
1facf9fc 6375+ hd->hd_dentry = h_dentry;
027c5e7a
AM
6376+ if (h_dentry) {
6377+ br = au_sbr(dentry->d_sb, bindex);
6378+ hd->hd_id = br->br_id;
6379+ }
6380+}
6381+
6382+int au_dbrange_test(struct dentry *dentry)
6383+{
6384+ int err;
6385+ aufs_bindex_t bstart, bend;
6386+
6387+ err = 0;
6388+ bstart = au_dbstart(dentry);
6389+ bend = au_dbend(dentry);
6390+ if (bstart >= 0)
6391+ AuDebugOn(bend < 0 && bstart > bend);
6392+ else {
6393+ err = -EIO;
6394+ AuDebugOn(bend >= 0);
6395+ }
6396+
6397+ return err;
6398+}
6399+
6400+int au_digen_test(struct dentry *dentry, unsigned int sigen)
6401+{
6402+ int err;
6403+
6404+ err = 0;
6405+ if (unlikely(au_digen(dentry) != sigen
6406+ || au_iigen_test(dentry->d_inode, sigen)))
6407+ err = -EIO;
6408+
6409+ return err;
1facf9fc 6410+}
6411+
6412+void au_update_digen(struct dentry *dentry)
6413+{
6414+ atomic_set(&au_di(dentry)->di_generation, au_sigen(dentry->d_sb));
6415+ /* smp_mb(); */ /* atomic_set */
6416+}
6417+
6418+void au_update_dbrange(struct dentry *dentry, int do_put_zero)
6419+{
6420+ struct au_dinfo *dinfo;
6421+ struct dentry *h_d;
4a4d8108 6422+ struct au_hdentry *hdp;
1facf9fc 6423+
1308ab2a 6424+ DiMustWriteLock(dentry);
6425+
1facf9fc 6426+ dinfo = au_di(dentry);
6427+ if (!dinfo || dinfo->di_bstart < 0)
6428+ return;
6429+
4a4d8108 6430+ hdp = dinfo->di_hdentry;
1facf9fc 6431+ if (do_put_zero) {
6432+ aufs_bindex_t bindex, bend;
6433+
6434+ bend = dinfo->di_bend;
6435+ for (bindex = dinfo->di_bstart; bindex <= bend; bindex++) {
4a4d8108 6436+ h_d = hdp[0 + bindex].hd_dentry;
1facf9fc 6437+ if (h_d && !h_d->d_inode)
6438+ au_set_h_dptr(dentry, bindex, NULL);
6439+ }
6440+ }
6441+
6442+ dinfo->di_bstart = -1;
6443+ while (++dinfo->di_bstart <= dinfo->di_bend)
4a4d8108 6444+ if (hdp[0 + dinfo->di_bstart].hd_dentry)
1facf9fc 6445+ break;
6446+ if (dinfo->di_bstart > dinfo->di_bend) {
6447+ dinfo->di_bstart = -1;
6448+ dinfo->di_bend = -1;
6449+ return;
6450+ }
6451+
6452+ dinfo->di_bend++;
6453+ while (0 <= --dinfo->di_bend)
4a4d8108 6454+ if (hdp[0 + dinfo->di_bend].hd_dentry)
1facf9fc 6455+ break;
6456+ AuDebugOn(dinfo->di_bstart > dinfo->di_bend || dinfo->di_bend < 0);
6457+}
6458+
6459+void au_update_dbstart(struct dentry *dentry)
6460+{
6461+ aufs_bindex_t bindex, bend;
6462+ struct dentry *h_dentry;
6463+
6464+ bend = au_dbend(dentry);
6465+ for (bindex = au_dbstart(dentry); bindex <= bend; bindex++) {
6466+ h_dentry = au_h_dptr(dentry, bindex);
6467+ if (!h_dentry)
6468+ continue;
6469+ if (h_dentry->d_inode) {
6470+ au_set_dbstart(dentry, bindex);
6471+ return;
6472+ }
6473+ au_set_h_dptr(dentry, bindex, NULL);
6474+ }
6475+}
6476+
6477+void au_update_dbend(struct dentry *dentry)
6478+{
6479+ aufs_bindex_t bindex, bstart;
6480+ struct dentry *h_dentry;
6481+
6482+ bstart = au_dbstart(dentry);
7f207e10 6483+ for (bindex = au_dbend(dentry); bindex >= bstart; bindex--) {
1facf9fc 6484+ h_dentry = au_h_dptr(dentry, bindex);
6485+ if (!h_dentry)
6486+ continue;
6487+ if (h_dentry->d_inode) {
6488+ au_set_dbend(dentry, bindex);
6489+ return;
6490+ }
6491+ au_set_h_dptr(dentry, bindex, NULL);
6492+ }
6493+}
6494+
6495+int au_find_dbindex(struct dentry *dentry, struct dentry *h_dentry)
6496+{
6497+ aufs_bindex_t bindex, bend;
6498+
6499+ bend = au_dbend(dentry);
6500+ for (bindex = au_dbstart(dentry); bindex <= bend; bindex++)
6501+ if (au_h_dptr(dentry, bindex) == h_dentry)
6502+ return bindex;
6503+ return -1;
6504+}
7f207e10
AM
6505diff -urN /usr/share/empty/fs/aufs/dir.c linux/fs/aufs/dir.c
6506--- /usr/share/empty/fs/aufs/dir.c 1970-01-01 01:00:00.000000000 +0100
2cbb1c4b 6507+++ linux/fs/aufs/dir.c 2011-07-11 11:34:24.072331673 +0200
027c5e7a 6508@@ -0,0 +1,647 @@
1facf9fc 6509+/*
027c5e7a 6510+ * Copyright (C) 2005-2011 Junjiro R. Okajima
1facf9fc 6511+ *
6512+ * This program, aufs is free software; you can redistribute it and/or modify
6513+ * it under the terms of the GNU General Public License as published by
6514+ * the Free Software Foundation; either version 2 of the License, or
6515+ * (at your option) any later version.
dece6358
AM
6516+ *
6517+ * This program is distributed in the hope that it will be useful,
6518+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
6519+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
6520+ * GNU General Public License for more details.
6521+ *
6522+ * You should have received a copy of the GNU General Public License
6523+ * along with this program; if not, write to the Free Software
6524+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 6525+ */
6526+
6527+/*
6528+ * directory operations
6529+ */
6530+
dece6358 6531+#include <linux/file.h>
1facf9fc 6532+#include <linux/fs_stack.h>
6533+#include "aufs.h"
6534+
6535+void au_add_nlink(struct inode *dir, struct inode *h_dir)
6536+{
6537+ AuDebugOn(!S_ISDIR(dir->i_mode) || !S_ISDIR(h_dir->i_mode));
6538+
6539+ dir->i_nlink += h_dir->i_nlink - 2;
6540+ if (h_dir->i_nlink < 2)
6541+ dir->i_nlink += 2;
6542+}
6543+
6544+void au_sub_nlink(struct inode *dir, struct inode *h_dir)
6545+{
6546+ AuDebugOn(!S_ISDIR(dir->i_mode) || !S_ISDIR(h_dir->i_mode));
6547+
6548+ dir->i_nlink -= h_dir->i_nlink - 2;
6549+ if (h_dir->i_nlink < 2)
6550+ dir->i_nlink -= 2;
6551+}
6552+
1308ab2a 6553+loff_t au_dir_size(struct file *file, struct dentry *dentry)
6554+{
6555+ loff_t sz;
6556+ aufs_bindex_t bindex, bend;
6557+ struct file *h_file;
6558+ struct dentry *h_dentry;
6559+
6560+ sz = 0;
6561+ if (file) {
6562+ AuDebugOn(!file->f_dentry);
6563+ AuDebugOn(!file->f_dentry->d_inode);
6564+ AuDebugOn(!S_ISDIR(file->f_dentry->d_inode->i_mode));
6565+
4a4d8108 6566+ bend = au_fbend_dir(file);
1308ab2a 6567+ for (bindex = au_fbstart(file);
6568+ bindex <= bend && sz < KMALLOC_MAX_SIZE;
6569+ bindex++) {
4a4d8108 6570+ h_file = au_hf_dir(file, bindex);
1308ab2a 6571+ if (h_file
6572+ && h_file->f_dentry
6573+ && h_file->f_dentry->d_inode)
6574+ sz += i_size_read(h_file->f_dentry->d_inode);
6575+ }
6576+ } else {
6577+ AuDebugOn(!dentry);
6578+ AuDebugOn(!dentry->d_inode);
6579+ AuDebugOn(!S_ISDIR(dentry->d_inode->i_mode));
6580+
6581+ bend = au_dbtaildir(dentry);
6582+ for (bindex = au_dbstart(dentry);
6583+ bindex <= bend && sz < KMALLOC_MAX_SIZE;
6584+ bindex++) {
6585+ h_dentry = au_h_dptr(dentry, bindex);
6586+ if (h_dentry && h_dentry->d_inode)
6587+ sz += i_size_read(h_dentry->d_inode);
6588+ }
6589+ }
6590+ if (sz < KMALLOC_MAX_SIZE)
6591+ sz = roundup_pow_of_two(sz);
6592+ if (sz > KMALLOC_MAX_SIZE)
6593+ sz = KMALLOC_MAX_SIZE;
6594+ else if (sz < NAME_MAX) {
6595+ BUILD_BUG_ON(AUFS_RDBLK_DEF < NAME_MAX);
6596+ sz = AUFS_RDBLK_DEF;
6597+ }
6598+ return sz;
6599+}
6600+
1facf9fc 6601+/* ---------------------------------------------------------------------- */
6602+
6603+static int reopen_dir(struct file *file)
6604+{
6605+ int err;
6606+ unsigned int flags;
6607+ aufs_bindex_t bindex, btail, bstart;
6608+ struct dentry *dentry, *h_dentry;
6609+ struct file *h_file;
6610+
6611+ /* open all lower dirs */
6612+ dentry = file->f_dentry;
6613+ bstart = au_dbstart(dentry);
6614+ for (bindex = au_fbstart(file); bindex < bstart; bindex++)
6615+ au_set_h_fptr(file, bindex, NULL);
6616+ au_set_fbstart(file, bstart);
6617+
6618+ btail = au_dbtaildir(dentry);
4a4d8108 6619+ for (bindex = au_fbend_dir(file); btail < bindex; bindex--)
1facf9fc 6620+ au_set_h_fptr(file, bindex, NULL);
4a4d8108 6621+ au_set_fbend_dir(file, btail);
1facf9fc 6622+
4a4d8108 6623+ flags = vfsub_file_flags(file);
1facf9fc 6624+ for (bindex = bstart; bindex <= btail; bindex++) {
6625+ h_dentry = au_h_dptr(dentry, bindex);
6626+ if (!h_dentry)
6627+ continue;
4a4d8108 6628+ h_file = au_hf_dir(file, bindex);
1facf9fc 6629+ if (h_file)
6630+ continue;
6631+
6632+ h_file = au_h_open(dentry, bindex, flags, file);
6633+ err = PTR_ERR(h_file);
6634+ if (IS_ERR(h_file))
6635+ goto out; /* close all? */
6636+ au_set_h_fptr(file, bindex, h_file);
6637+ }
6638+ au_update_figen(file);
6639+ /* todo: necessary? */
6640+ /* file->f_ra = h_file->f_ra; */
6641+ err = 0;
6642+
4f0767ce 6643+out:
1facf9fc 6644+ return err;
6645+}
6646+
6647+static int do_open_dir(struct file *file, int flags)
6648+{
6649+ int err;
6650+ aufs_bindex_t bindex, btail;
6651+ struct dentry *dentry, *h_dentry;
6652+ struct file *h_file;
6653+
1308ab2a 6654+ FiMustWriteLock(file);
6655+
1facf9fc 6656+ dentry = file->f_dentry;
027c5e7a
AM
6657+ err = au_alive_dir(dentry);
6658+ if (unlikely(err))
6659+ goto out;
6660+
1facf9fc 6661+ file->f_version = dentry->d_inode->i_version;
6662+ bindex = au_dbstart(dentry);
6663+ au_set_fbstart(file, bindex);
6664+ btail = au_dbtaildir(dentry);
4a4d8108 6665+ au_set_fbend_dir(file, btail);
1facf9fc 6666+ for (; !err && bindex <= btail; bindex++) {
6667+ h_dentry = au_h_dptr(dentry, bindex);
6668+ if (!h_dentry)
6669+ continue;
6670+
6671+ h_file = au_h_open(dentry, bindex, flags, file);
6672+ if (IS_ERR(h_file)) {
6673+ err = PTR_ERR(h_file);
6674+ break;
6675+ }
6676+ au_set_h_fptr(file, bindex, h_file);
6677+ }
6678+ au_update_figen(file);
6679+ /* todo: necessary? */
6680+ /* file->f_ra = h_file->f_ra; */
6681+ if (!err)
6682+ return 0; /* success */
6683+
6684+ /* close all */
6685+ for (bindex = au_fbstart(file); bindex <= btail; bindex++)
6686+ au_set_h_fptr(file, bindex, NULL);
6687+ au_set_fbstart(file, -1);
4a4d8108
AM
6688+ au_set_fbend_dir(file, -1);
6689+
027c5e7a 6690+out:
1facf9fc 6691+ return err;
6692+}
6693+
6694+static int aufs_open_dir(struct inode *inode __maybe_unused,
6695+ struct file *file)
6696+{
4a4d8108
AM
6697+ int err;
6698+ struct super_block *sb;
6699+ struct au_fidir *fidir;
6700+
6701+ err = -ENOMEM;
6702+ sb = file->f_dentry->d_sb;
6703+ si_read_lock(sb, AuLock_FLUSH);
e49829fe 6704+ fidir = au_fidir_alloc(sb);
4a4d8108
AM
6705+ if (fidir) {
6706+ err = au_do_open(file, do_open_dir, fidir);
6707+ if (unlikely(err))
6708+ kfree(fidir);
6709+ }
6710+ si_read_unlock(sb);
6711+ return err;
1facf9fc 6712+}
6713+
6714+static int aufs_release_dir(struct inode *inode __maybe_unused,
6715+ struct file *file)
6716+{
6717+ struct au_vdir *vdir_cache;
4a4d8108
AM
6718+ struct au_finfo *finfo;
6719+ struct au_fidir *fidir;
6720+ aufs_bindex_t bindex, bend;
1facf9fc 6721+
4a4d8108
AM
6722+ finfo = au_fi(file);
6723+ fidir = finfo->fi_hdir;
6724+ if (fidir) {
0c5527e5
AM
6725+ /* remove me from sb->s_files */
6726+ file_sb_list_del(file);
6727+
4a4d8108
AM
6728+ vdir_cache = fidir->fd_vdir_cache; /* lock-free */
6729+ if (vdir_cache)
6730+ au_vdir_free(vdir_cache);
6731+
6732+ bindex = finfo->fi_btop;
6733+ if (bindex >= 0) {
6734+ /*
6735+ * calls fput() instead of filp_close(),
6736+ * since no dnotify or lock for the lower file.
6737+ */
6738+ bend = fidir->fd_bbot;
6739+ for (; bindex <= bend; bindex++)
6740+ au_set_h_fptr(file, bindex, NULL);
6741+ }
6742+ kfree(fidir);
6743+ finfo->fi_hdir = NULL;
1facf9fc 6744+ }
1facf9fc 6745+ au_finfo_fin(file);
1facf9fc 6746+ return 0;
6747+}
6748+
6749+/* ---------------------------------------------------------------------- */
6750+
4a4d8108
AM
6751+static int au_do_flush_dir(struct file *file, fl_owner_t id)
6752+{
6753+ int err;
6754+ aufs_bindex_t bindex, bend;
6755+ struct file *h_file;
6756+
6757+ err = 0;
6758+ bend = au_fbend_dir(file);
6759+ for (bindex = au_fbstart(file); !err && bindex <= bend; bindex++) {
6760+ h_file = au_hf_dir(file, bindex);
6761+ if (h_file)
6762+ err = vfsub_flush(h_file, id);
6763+ }
6764+ return err;
6765+}
6766+
6767+static int aufs_flush_dir(struct file *file, fl_owner_t id)
6768+{
6769+ return au_do_flush(file, id, au_do_flush_dir);
6770+}
6771+
6772+/* ---------------------------------------------------------------------- */
6773+
1facf9fc 6774+static int au_do_fsync_dir_no_file(struct dentry *dentry, int datasync)
6775+{
6776+ int err;
6777+ aufs_bindex_t bend, bindex;
6778+ struct inode *inode;
6779+ struct super_block *sb;
6780+
6781+ err = 0;
6782+ sb = dentry->d_sb;
6783+ inode = dentry->d_inode;
6784+ IMustLock(inode);
6785+ bend = au_dbend(dentry);
6786+ for (bindex = au_dbstart(dentry); !err && bindex <= bend; bindex++) {
6787+ struct path h_path;
6788+ struct inode *h_inode;
6789+
6790+ if (au_test_ro(sb, bindex, inode))
6791+ continue;
6792+ h_path.dentry = au_h_dptr(dentry, bindex);
6793+ if (!h_path.dentry)
6794+ continue;
6795+ h_inode = h_path.dentry->d_inode;
6796+ if (!h_inode)
6797+ continue;
6798+
6799+ /* no mnt_want_write() */
6800+ /* cf. fs/nsfd/vfs.c and fs/nfsd/nfs4recover.c */
6801+ /* todo: inotiry fired? */
6802+ h_path.mnt = au_sbr_mnt(sb, bindex);
6803+ mutex_lock(&h_inode->i_mutex);
6804+ err = filemap_fdatawrite(h_inode->i_mapping);
6805+ AuDebugOn(!h_inode->i_fop);
6806+ if (!err && h_inode->i_fop->fsync)
b752ccd1 6807+ err = h_inode->i_fop->fsync(NULL, datasync);
1facf9fc 6808+ if (!err)
6809+ err = filemap_fdatawrite(h_inode->i_mapping);
6810+ if (!err)
6811+ vfsub_update_h_iattr(&h_path, /*did*/NULL); /*ignore*/
6812+ mutex_unlock(&h_inode->i_mutex);
6813+ }
6814+
6815+ return err;
6816+}
6817+
6818+static int au_do_fsync_dir(struct file *file, int datasync)
6819+{
6820+ int err;
6821+ aufs_bindex_t bend, bindex;
6822+ struct file *h_file;
6823+ struct super_block *sb;
6824+ struct inode *inode;
6825+ struct mutex *h_mtx;
6826+
6827+ err = au_reval_and_lock_fdi(file, reopen_dir, /*wlock*/1);
6828+ if (unlikely(err))
6829+ goto out;
6830+
6831+ sb = file->f_dentry->d_sb;
6832+ inode = file->f_dentry->d_inode;
4a4d8108 6833+ bend = au_fbend_dir(file);
1facf9fc 6834+ for (bindex = au_fbstart(file); !err && bindex <= bend; bindex++) {
4a4d8108 6835+ h_file = au_hf_dir(file, bindex);
1facf9fc 6836+ if (!h_file || au_test_ro(sb, bindex, inode))
6837+ continue;
6838+
b752ccd1 6839+ err = vfs_fsync(h_file, datasync);
1facf9fc 6840+ if (!err) {
6841+ h_mtx = &h_file->f_dentry->d_inode->i_mutex;
6842+ mutex_lock(h_mtx);
6843+ vfsub_update_h_iattr(&h_file->f_path, /*did*/NULL);
6844+ /*ignore*/
6845+ mutex_unlock(h_mtx);
6846+ }
6847+ }
6848+
4f0767ce 6849+out:
1facf9fc 6850+ return err;
6851+}
6852+
6853+/*
6854+ * @file may be NULL
6855+ */
b752ccd1 6856+static int aufs_fsync_dir(struct file *file, int datasync)
1facf9fc 6857+{
6858+ int err;
b752ccd1 6859+ struct dentry *dentry;
1facf9fc 6860+ struct super_block *sb;
6861+
b752ccd1 6862+ dentry = file->f_dentry;
1facf9fc 6863+ IMustLock(dentry->d_inode);
6864+
6865+ err = 0;
6866+ sb = dentry->d_sb;
6867+ si_noflush_read_lock(sb);
6868+ if (file)
6869+ err = au_do_fsync_dir(file, datasync);
6870+ else {
6871+ di_write_lock_child(dentry);
6872+ err = au_do_fsync_dir_no_file(dentry, datasync);
6873+ }
6874+ au_cpup_attr_timesizes(dentry->d_inode);
6875+ di_write_unlock(dentry);
6876+ if (file)
6877+ fi_write_unlock(file);
6878+
6879+ si_read_unlock(sb);
6880+ return err;
6881+}
6882+
6883+/* ---------------------------------------------------------------------- */
6884+
6885+static int aufs_readdir(struct file *file, void *dirent, filldir_t filldir)
6886+{
6887+ int err;
6888+ struct dentry *dentry;
6889+ struct inode *inode;
6890+ struct super_block *sb;
6891+
6892+ dentry = file->f_dentry;
6893+ inode = dentry->d_inode;
6894+ IMustLock(inode);
6895+
6896+ sb = dentry->d_sb;
6897+ si_read_lock(sb, AuLock_FLUSH);
6898+ err = au_reval_and_lock_fdi(file, reopen_dir, /*wlock*/1);
6899+ if (unlikely(err))
6900+ goto out;
027c5e7a
AM
6901+ err = au_alive_dir(dentry);
6902+ if (!err)
6903+ err = au_vdir_init(file);
1facf9fc 6904+ di_downgrade_lock(dentry, AuLock_IR);
6905+ if (unlikely(err))
6906+ goto out_unlock;
6907+
b752ccd1 6908+ if (!au_test_nfsd()) {
1facf9fc 6909+ err = au_vdir_fill_de(file, dirent, filldir);
6910+ fsstack_copy_attr_atime(inode,
6911+ au_h_iptr(inode, au_ibstart(inode)));
6912+ } else {
6913+ /*
6914+ * nfsd filldir may call lookup_one_len(), vfs_getattr(),
6915+ * encode_fh() and others.
6916+ */
6917+ struct inode *h_inode = au_h_iptr(inode, au_ibstart(inode));
6918+
6919+ di_read_unlock(dentry, AuLock_IR);
6920+ si_read_unlock(sb);
1facf9fc 6921+ err = au_vdir_fill_de(file, dirent, filldir);
1facf9fc 6922+ fsstack_copy_attr_atime(inode, h_inode);
6923+ fi_write_unlock(file);
6924+
6925+ AuTraceErr(err);
6926+ return err;
6927+ }
6928+
4f0767ce 6929+out_unlock:
1facf9fc 6930+ di_read_unlock(dentry, AuLock_IR);
6931+ fi_write_unlock(file);
4f0767ce 6932+out:
1facf9fc 6933+ si_read_unlock(sb);
6934+ return err;
6935+}
6936+
6937+/* ---------------------------------------------------------------------- */
6938+
6939+#define AuTestEmpty_WHONLY 1
dece6358
AM
6940+#define AuTestEmpty_CALLED (1 << 1)
6941+#define AuTestEmpty_SHWH (1 << 2)
1facf9fc 6942+#define au_ftest_testempty(flags, name) ((flags) & AuTestEmpty_##name)
7f207e10
AM
6943+#define au_fset_testempty(flags, name) \
6944+ do { (flags) |= AuTestEmpty_##name; } while (0)
6945+#define au_fclr_testempty(flags, name) \
6946+ do { (flags) &= ~AuTestEmpty_##name; } while (0)
1facf9fc 6947+
dece6358
AM
6948+#ifndef CONFIG_AUFS_SHWH
6949+#undef AuTestEmpty_SHWH
6950+#define AuTestEmpty_SHWH 0
6951+#endif
6952+
1facf9fc 6953+struct test_empty_arg {
1308ab2a 6954+ struct au_nhash *whlist;
1facf9fc 6955+ unsigned int flags;
6956+ int err;
6957+ aufs_bindex_t bindex;
6958+};
6959+
6960+static int test_empty_cb(void *__arg, const char *__name, int namelen,
dece6358
AM
6961+ loff_t offset __maybe_unused, u64 ino,
6962+ unsigned int d_type)
1facf9fc 6963+{
6964+ struct test_empty_arg *arg = __arg;
6965+ char *name = (void *)__name;
6966+
6967+ arg->err = 0;
6968+ au_fset_testempty(arg->flags, CALLED);
6969+ /* smp_mb(); */
6970+ if (name[0] == '.'
6971+ && (namelen == 1 || (name[1] == '.' && namelen == 2)))
6972+ goto out; /* success */
6973+
6974+ if (namelen <= AUFS_WH_PFX_LEN
6975+ || memcmp(name, AUFS_WH_PFX, AUFS_WH_PFX_LEN)) {
6976+ if (au_ftest_testempty(arg->flags, WHONLY)
1308ab2a 6977+ && !au_nhash_test_known_wh(arg->whlist, name, namelen))
1facf9fc 6978+ arg->err = -ENOTEMPTY;
6979+ goto out;
6980+ }
6981+
6982+ name += AUFS_WH_PFX_LEN;
6983+ namelen -= AUFS_WH_PFX_LEN;
1308ab2a 6984+ if (!au_nhash_test_known_wh(arg->whlist, name, namelen))
1facf9fc 6985+ arg->err = au_nhash_append_wh
1308ab2a 6986+ (arg->whlist, name, namelen, ino, d_type, arg->bindex,
dece6358 6987+ au_ftest_testempty(arg->flags, SHWH));
1facf9fc 6988+
4f0767ce 6989+out:
1facf9fc 6990+ /* smp_mb(); */
6991+ AuTraceErr(arg->err);
6992+ return arg->err;
6993+}
6994+
6995+static int do_test_empty(struct dentry *dentry, struct test_empty_arg *arg)
6996+{
6997+ int err;
6998+ struct file *h_file;
6999+
7000+ h_file = au_h_open(dentry, arg->bindex,
7001+ O_RDONLY | O_NONBLOCK | O_DIRECTORY | O_LARGEFILE,
7002+ /*file*/NULL);
7003+ err = PTR_ERR(h_file);
7004+ if (IS_ERR(h_file))
7005+ goto out;
7006+
7007+ err = 0;
7008+ if (!au_opt_test(au_mntflags(dentry->d_sb), UDBA_NONE)
7009+ && !h_file->f_dentry->d_inode->i_nlink)
7010+ goto out_put;
7011+
7012+ do {
7013+ arg->err = 0;
7014+ au_fclr_testempty(arg->flags, CALLED);
7015+ /* smp_mb(); */
7016+ err = vfsub_readdir(h_file, test_empty_cb, arg);
7017+ if (err >= 0)
7018+ err = arg->err;
7019+ } while (!err && au_ftest_testempty(arg->flags, CALLED));
7020+
4f0767ce 7021+out_put:
1facf9fc 7022+ fput(h_file);
7023+ au_sbr_put(dentry->d_sb, arg->bindex);
4f0767ce 7024+out:
1facf9fc 7025+ return err;
7026+}
7027+
7028+struct do_test_empty_args {
7029+ int *errp;
7030+ struct dentry *dentry;
7031+ struct test_empty_arg *arg;
7032+};
7033+
7034+static void call_do_test_empty(void *args)
7035+{
7036+ struct do_test_empty_args *a = args;
7037+ *a->errp = do_test_empty(a->dentry, a->arg);
7038+}
7039+
7040+static int sio_test_empty(struct dentry *dentry, struct test_empty_arg *arg)
7041+{
7042+ int err, wkq_err;
7043+ struct dentry *h_dentry;
7044+ struct inode *h_inode;
7045+
7046+ h_dentry = au_h_dptr(dentry, arg->bindex);
7047+ h_inode = h_dentry->d_inode;
7048+ mutex_lock_nested(&h_inode->i_mutex, AuLsc_I_CHILD);
7049+ err = au_test_h_perm_sio(h_inode, MAY_EXEC | MAY_READ);
7050+ mutex_unlock(&h_inode->i_mutex);
7051+ if (!err)
7052+ err = do_test_empty(dentry, arg);
7053+ else {
7054+ struct do_test_empty_args args = {
7055+ .errp = &err,
7056+ .dentry = dentry,
7057+ .arg = arg
7058+ };
7059+ unsigned int flags = arg->flags;
7060+
7061+ wkq_err = au_wkq_wait(call_do_test_empty, &args);
7062+ if (unlikely(wkq_err))
7063+ err = wkq_err;
7064+ arg->flags = flags;
7065+ }
7066+
7067+ return err;
7068+}
7069+
7070+int au_test_empty_lower(struct dentry *dentry)
7071+{
7072+ int err;
1308ab2a 7073+ unsigned int rdhash;
1facf9fc 7074+ aufs_bindex_t bindex, bstart, btail;
1308ab2a 7075+ struct au_nhash whlist;
1facf9fc 7076+ struct test_empty_arg arg;
1facf9fc 7077+
dece6358
AM
7078+ SiMustAnyLock(dentry->d_sb);
7079+
1308ab2a 7080+ rdhash = au_sbi(dentry->d_sb)->si_rdhash;
7081+ if (!rdhash)
7082+ rdhash = au_rdhash_est(au_dir_size(/*file*/NULL, dentry));
7083+ err = au_nhash_alloc(&whlist, rdhash, GFP_NOFS);
dece6358 7084+ if (unlikely(err))
1facf9fc 7085+ goto out;
7086+
1facf9fc 7087+ arg.flags = 0;
1308ab2a 7088+ arg.whlist = &whlist;
7089+ bstart = au_dbstart(dentry);
dece6358
AM
7090+ if (au_opt_test(au_mntflags(dentry->d_sb), SHWH))
7091+ au_fset_testempty(arg.flags, SHWH);
1facf9fc 7092+ arg.bindex = bstart;
7093+ err = do_test_empty(dentry, &arg);
7094+ if (unlikely(err))
7095+ goto out_whlist;
7096+
7097+ au_fset_testempty(arg.flags, WHONLY);
7098+ btail = au_dbtaildir(dentry);
7099+ for (bindex = bstart + 1; !err && bindex <= btail; bindex++) {
7100+ struct dentry *h_dentry;
7101+
7102+ h_dentry = au_h_dptr(dentry, bindex);
7103+ if (h_dentry && h_dentry->d_inode) {
7104+ arg.bindex = bindex;
7105+ err = do_test_empty(dentry, &arg);
7106+ }
7107+ }
7108+
4f0767ce 7109+out_whlist:
1308ab2a 7110+ au_nhash_wh_free(&whlist);
4f0767ce 7111+out:
1facf9fc 7112+ return err;
7113+}
7114+
7115+int au_test_empty(struct dentry *dentry, struct au_nhash *whlist)
7116+{
7117+ int err;
7118+ struct test_empty_arg arg;
7119+ aufs_bindex_t bindex, btail;
7120+
7121+ err = 0;
1308ab2a 7122+ arg.whlist = whlist;
1facf9fc 7123+ arg.flags = AuTestEmpty_WHONLY;
dece6358
AM
7124+ if (au_opt_test(au_mntflags(dentry->d_sb), SHWH))
7125+ au_fset_testempty(arg.flags, SHWH);
1facf9fc 7126+ btail = au_dbtaildir(dentry);
7127+ for (bindex = au_dbstart(dentry); !err && bindex <= btail; bindex++) {
7128+ struct dentry *h_dentry;
7129+
7130+ h_dentry = au_h_dptr(dentry, bindex);
7131+ if (h_dentry && h_dentry->d_inode) {
7132+ arg.bindex = bindex;
7133+ err = sio_test_empty(dentry, &arg);
7134+ }
7135+ }
7136+
7137+ return err;
7138+}
7139+
7140+/* ---------------------------------------------------------------------- */
7141+
7142+const struct file_operations aufs_dir_fop = {
4a4d8108 7143+ .owner = THIS_MODULE,
027c5e7a 7144+ .llseek = default_llseek,
1facf9fc 7145+ .read = generic_read_dir,
7146+ .readdir = aufs_readdir,
7147+ .unlocked_ioctl = aufs_ioctl_dir,
b752ccd1
AM
7148+#ifdef CONFIG_COMPAT
7149+ .compat_ioctl = aufs_compat_ioctl_dir,
7150+#endif
1facf9fc 7151+ .open = aufs_open_dir,
7152+ .release = aufs_release_dir,
4a4d8108 7153+ .flush = aufs_flush_dir,
1facf9fc 7154+ .fsync = aufs_fsync_dir
7155+};
7f207e10
AM
7156diff -urN /usr/share/empty/fs/aufs/dir.h linux/fs/aufs/dir.h
7157--- /usr/share/empty/fs/aufs/dir.h 1970-01-01 01:00:00.000000000 +0100
2cbb1c4b 7158+++ linux/fs/aufs/dir.h 2011-07-11 11:34:24.072331673 +0200
b752ccd1 7159@@ -0,0 +1,138 @@
1facf9fc 7160+/*
027c5e7a 7161+ * Copyright (C) 2005-2011 Junjiro R. Okajima
1facf9fc 7162+ *
7163+ * This program, aufs is free software; you can redistribute it and/or modify
7164+ * it under the terms of the GNU General Public License as published by
7165+ * the Free Software Foundation; either version 2 of the License, or
7166+ * (at your option) any later version.
dece6358
AM
7167+ *
7168+ * This program is distributed in the hope that it will be useful,
7169+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
7170+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
7171+ * GNU General Public License for more details.
7172+ *
7173+ * You should have received a copy of the GNU General Public License
7174+ * along with this program; if not, write to the Free Software
7175+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 7176+ */
7177+
7178+/*
7179+ * directory operations
7180+ */
7181+
7182+#ifndef __AUFS_DIR_H__
7183+#define __AUFS_DIR_H__
7184+
7185+#ifdef __KERNEL__
7186+
7187+#include <linux/fs.h>
7188+#include <linux/aufs_type.h>
7189+
7190+/* ---------------------------------------------------------------------- */
7191+
7192+/* need to be faster and smaller */
7193+
7194+struct au_nhash {
dece6358
AM
7195+ unsigned int nh_num;
7196+ struct hlist_head *nh_head;
1facf9fc 7197+};
7198+
7199+struct au_vdir_destr {
7200+ unsigned char len;
7201+ unsigned char name[0];
7202+} __packed;
7203+
7204+struct au_vdir_dehstr {
7205+ struct hlist_node hash;
7206+ struct au_vdir_destr *str;
4a4d8108 7207+} ____cacheline_aligned_in_smp;
1facf9fc 7208+
7209+struct au_vdir_de {
7210+ ino_t de_ino;
7211+ unsigned char de_type;
7212+ /* caution: packed */
7213+ struct au_vdir_destr de_str;
7214+} __packed;
7215+
7216+struct au_vdir_wh {
7217+ struct hlist_node wh_hash;
dece6358
AM
7218+#ifdef CONFIG_AUFS_SHWH
7219+ ino_t wh_ino;
1facf9fc 7220+ aufs_bindex_t wh_bindex;
dece6358
AM
7221+ unsigned char wh_type;
7222+#else
7223+ aufs_bindex_t wh_bindex;
7224+#endif
7225+ /* caution: packed */
1facf9fc 7226+ struct au_vdir_destr wh_str;
7227+} __packed;
7228+
7229+union au_vdir_deblk_p {
7230+ unsigned char *deblk;
7231+ struct au_vdir_de *de;
7232+};
7233+
7234+struct au_vdir {
7235+ unsigned char **vd_deblk;
7236+ unsigned long vd_nblk;
1facf9fc 7237+ struct {
7238+ unsigned long ul;
7239+ union au_vdir_deblk_p p;
7240+ } vd_last;
7241+
7242+ unsigned long vd_version;
dece6358 7243+ unsigned int vd_deblk_sz;
1facf9fc 7244+ unsigned long vd_jiffy;
4a4d8108 7245+} ____cacheline_aligned_in_smp;
1facf9fc 7246+
7247+/* ---------------------------------------------------------------------- */
7248+
7249+/* dir.c */
7250+extern const struct file_operations aufs_dir_fop;
7251+void au_add_nlink(struct inode *dir, struct inode *h_dir);
7252+void au_sub_nlink(struct inode *dir, struct inode *h_dir);
1308ab2a 7253+loff_t au_dir_size(struct file *file, struct dentry *dentry);
1facf9fc 7254+int au_test_empty_lower(struct dentry *dentry);
7255+int au_test_empty(struct dentry *dentry, struct au_nhash *whlist);
7256+
7257+/* vdir.c */
1308ab2a 7258+unsigned int au_rdhash_est(loff_t sz);
dece6358
AM
7259+int au_nhash_alloc(struct au_nhash *nhash, unsigned int num_hash, gfp_t gfp);
7260+void au_nhash_wh_free(struct au_nhash *whlist);
1facf9fc 7261+int au_nhash_test_longer_wh(struct au_nhash *whlist, aufs_bindex_t btgt,
7262+ int limit);
dece6358
AM
7263+int au_nhash_test_known_wh(struct au_nhash *whlist, char *name, int nlen);
7264+int au_nhash_append_wh(struct au_nhash *whlist, char *name, int nlen, ino_t ino,
7265+ unsigned int d_type, aufs_bindex_t bindex,
7266+ unsigned char shwh);
1facf9fc 7267+void au_vdir_free(struct au_vdir *vdir);
7268+int au_vdir_init(struct file *file);
7269+int au_vdir_fill_de(struct file *file, void *dirent, filldir_t filldir);
7270+
7271+/* ioctl.c */
7272+long aufs_ioctl_dir(struct file *file, unsigned int cmd, unsigned long arg);
7273+
1308ab2a 7274+#ifdef CONFIG_AUFS_RDU
7275+/* rdu.c */
7276+long au_rdu_ioctl(struct file *file, unsigned int cmd, unsigned long arg);
b752ccd1
AM
7277+#ifdef CONFIG_COMPAT
7278+long au_rdu_compat_ioctl(struct file *file, unsigned int cmd,
7279+ unsigned long arg);
7280+#endif
1308ab2a 7281+#else
7282+static inline long au_rdu_ioctl(struct file *file, unsigned int cmd,
7283+ unsigned long arg)
7284+{
7285+ return -EINVAL;
7286+}
b752ccd1
AM
7287+#ifdef CONFIG_COMPAT
7288+static inline long au_rdu_compat_ioctl(struct file *file, unsigned int cmd,
7289+ unsigned long arg)
7290+{
7291+ return -EINVAL;
7292+}
7293+#endif
1308ab2a 7294+#endif
7295+
1facf9fc 7296+#endif /* __KERNEL__ */
7297+#endif /* __AUFS_DIR_H__ */
7f207e10
AM
7298diff -urN /usr/share/empty/fs/aufs/dynop.c linux/fs/aufs/dynop.c
7299--- /usr/share/empty/fs/aufs/dynop.c 1970-01-01 01:00:00.000000000 +0100
2cbb1c4b
JR
7300+++ linux/fs/aufs/dynop.c 2011-07-11 11:34:24.072331673 +0200
7301@@ -0,0 +1,377 @@
1facf9fc 7302+/*
027c5e7a 7303+ * Copyright (C) 2010-2011 Junjiro R. Okajima
1facf9fc 7304+ *
7305+ * This program, aufs is free software; you can redistribute it and/or modify
7306+ * it under the terms of the GNU General Public License as published by
7307+ * the Free Software Foundation; either version 2 of the License, or
7308+ * (at your option) any later version.
dece6358
AM
7309+ *
7310+ * This program is distributed in the hope that it will be useful,
7311+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
7312+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
7313+ * GNU General Public License for more details.
7314+ *
7315+ * You should have received a copy of the GNU General Public License
7316+ * along with this program; if not, write to the Free Software
7317+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 7318+ */
7319+
7320+/*
4a4d8108 7321+ * dynamically customizable operations for regular files
1facf9fc 7322+ */
7323+
1facf9fc 7324+#include "aufs.h"
7325+
4a4d8108 7326+#define DyPrSym(key) AuDbgSym(key->dk_op.dy_hop)
1facf9fc 7327+
4a4d8108
AM
7328+/*
7329+ * How large will these lists be?
7330+ * Usually just a few elements, 20-30 at most for each, I guess.
7331+ */
7332+static struct au_splhead dynop[AuDyLast];
7333+
7334+static struct au_dykey *dy_gfind_get(struct au_splhead *spl, const void *h_op)
1facf9fc 7335+{
4a4d8108
AM
7336+ struct au_dykey *key, *tmp;
7337+ struct list_head *head;
1facf9fc 7338+
4a4d8108
AM
7339+ key = NULL;
7340+ head = &spl->head;
7341+ rcu_read_lock();
7342+ list_for_each_entry_rcu(tmp, head, dk_list)
7343+ if (tmp->dk_op.dy_hop == h_op) {
7344+ key = tmp;
7345+ kref_get(&key->dk_kref);
7346+ break;
7347+ }
7348+ rcu_read_unlock();
7349+
7350+ return key;
1facf9fc 7351+}
7352+
4a4d8108 7353+static struct au_dykey *dy_bradd(struct au_branch *br, struct au_dykey *key)
1facf9fc 7354+{
4a4d8108
AM
7355+ struct au_dykey **k, *found;
7356+ const void *h_op = key->dk_op.dy_hop;
7357+ int i;
1facf9fc 7358+
4a4d8108
AM
7359+ found = NULL;
7360+ k = br->br_dykey;
7361+ for (i = 0; i < AuBrDynOp; i++)
7362+ if (k[i]) {
7363+ if (k[i]->dk_op.dy_hop == h_op) {
7364+ found = k[i];
7365+ break;
7366+ }
7367+ } else
7368+ break;
7369+ if (!found) {
7370+ spin_lock(&br->br_dykey_lock);
7371+ for (; i < AuBrDynOp; i++)
7372+ if (k[i]) {
7373+ if (k[i]->dk_op.dy_hop == h_op) {
7374+ found = k[i];
7375+ break;
7376+ }
7377+ } else {
7378+ k[i] = key;
7379+ break;
7380+ }
7381+ spin_unlock(&br->br_dykey_lock);
7382+ BUG_ON(i == AuBrDynOp); /* expand the array */
7383+ }
7384+
7385+ return found;
1facf9fc 7386+}
7387+
4a4d8108
AM
7388+/* kref_get() if @key is already added */
7389+static struct au_dykey *dy_gadd(struct au_splhead *spl, struct au_dykey *key)
7390+{
7391+ struct au_dykey *tmp, *found;
7392+ struct list_head *head;
7393+ const void *h_op = key->dk_op.dy_hop;
1facf9fc 7394+
4a4d8108
AM
7395+ found = NULL;
7396+ head = &spl->head;
7397+ spin_lock(&spl->spin);
7398+ list_for_each_entry(tmp, head, dk_list)
7399+ if (tmp->dk_op.dy_hop == h_op) {
7400+ kref_get(&tmp->dk_kref);
7401+ found = tmp;
7402+ break;
7403+ }
7404+ if (!found)
7405+ list_add_rcu(&key->dk_list, head);
7406+ spin_unlock(&spl->spin);
1facf9fc 7407+
4a4d8108
AM
7408+ if (!found)
7409+ DyPrSym(key);
7410+ return found;
7411+}
7412+
7413+static void dy_free_rcu(struct rcu_head *rcu)
1facf9fc 7414+{
4a4d8108
AM
7415+ struct au_dykey *key;
7416+
7417+ key = container_of(rcu, struct au_dykey, dk_rcu);
7418+ DyPrSym(key);
7419+ kfree(key);
1facf9fc 7420+}
7421+
4a4d8108
AM
7422+static void dy_free(struct kref *kref)
7423+{
7424+ struct au_dykey *key;
7425+ struct au_splhead *spl;
1facf9fc 7426+
4a4d8108
AM
7427+ key = container_of(kref, struct au_dykey, dk_kref);
7428+ spl = dynop + key->dk_op.dy_type;
7429+ au_spl_del_rcu(&key->dk_list, spl);
7430+ call_rcu(&key->dk_rcu, dy_free_rcu);
7431+}
7432+
7433+void au_dy_put(struct au_dykey *key)
1facf9fc 7434+{
4a4d8108
AM
7435+ kref_put(&key->dk_kref, dy_free);
7436+}
1facf9fc 7437+
4a4d8108
AM
7438+/* ---------------------------------------------------------------------- */
7439+
7440+#define DyDbgSize(cnt, op) AuDebugOn(cnt != sizeof(op)/sizeof(void *))
7441+
7442+#ifdef CONFIG_AUFS_DEBUG
7443+#define DyDbgDeclare(cnt) unsigned int cnt = 0
4f0767ce 7444+#define DyDbgInc(cnt) do { cnt++; } while (0)
4a4d8108
AM
7445+#else
7446+#define DyDbgDeclare(cnt) do {} while (0)
7447+#define DyDbgInc(cnt) do {} while (0)
7448+#endif
7449+
7450+#define DySet(func, dst, src, h_op, h_sb) do { \
7451+ DyDbgInc(cnt); \
7452+ if (h_op->func) { \
7453+ if (src.func) \
7454+ dst.func = src.func; \
7455+ else \
7456+ AuDbg("%s %s\n", au_sbtype(h_sb), #func); \
7457+ } \
7458+} while (0)
7459+
7460+#define DySetForce(func, dst, src) do { \
7461+ AuDebugOn(!src.func); \
7462+ DyDbgInc(cnt); \
7463+ dst.func = src.func; \
7464+} while (0)
7465+
7466+#define DySetAop(func) \
7467+ DySet(func, dyaop->da_op, aufs_aop, h_aop, h_sb)
7468+#define DySetAopForce(func) \
7469+ DySetForce(func, dyaop->da_op, aufs_aop)
7470+
7471+static void dy_aop(struct au_dykey *key, const void *h_op,
7472+ struct super_block *h_sb __maybe_unused)
7473+{
7474+ struct au_dyaop *dyaop = (void *)key;
7475+ const struct address_space_operations *h_aop = h_op;
7476+ DyDbgDeclare(cnt);
7477+
7478+ AuDbg("%s\n", au_sbtype(h_sb));
7479+
7480+ DySetAop(writepage);
7481+ DySetAopForce(readpage); /* force */
4a4d8108
AM
7482+ DySetAop(writepages);
7483+ DySetAop(set_page_dirty);
7484+ DySetAop(readpages);
7485+ DySetAop(write_begin);
7486+ DySetAop(write_end);
7487+ DySetAop(bmap);
7488+ DySetAop(invalidatepage);
7489+ DySetAop(releasepage);
027c5e7a 7490+ DySetAop(freepage);
4a4d8108
AM
7491+ /* these two will be changed according to an aufs mount option */
7492+ DySetAop(direct_IO);
7493+ DySetAop(get_xip_mem);
7494+ DySetAop(migratepage);
7495+ DySetAop(launder_page);
7496+ DySetAop(is_partially_uptodate);
7497+ DySetAop(error_remove_page);
7498+
7499+ DyDbgSize(cnt, *h_aop);
7500+ dyaop->da_get_xip_mem = h_aop->get_xip_mem;
7501+}
7502+
4a4d8108
AM
7503+/* ---------------------------------------------------------------------- */
7504+
7505+static void dy_bug(struct kref *kref)
7506+{
7507+ BUG();
7508+}
7509+
7510+static struct au_dykey *dy_get(struct au_dynop *op, struct au_branch *br)
7511+{
7512+ struct au_dykey *key, *old;
7513+ struct au_splhead *spl;
b752ccd1 7514+ struct op {
4a4d8108 7515+ unsigned int sz;
b752ccd1
AM
7516+ void (*set)(struct au_dykey *key, const void *h_op,
7517+ struct super_block *h_sb __maybe_unused);
7518+ };
7519+ static const struct op a[] = {
4a4d8108
AM
7520+ [AuDy_AOP] = {
7521+ .sz = sizeof(struct au_dyaop),
b752ccd1 7522+ .set = dy_aop
4a4d8108 7523+ }
b752ccd1
AM
7524+ };
7525+ const struct op *p;
4a4d8108
AM
7526+
7527+ spl = dynop + op->dy_type;
7528+ key = dy_gfind_get(spl, op->dy_hop);
7529+ if (key)
7530+ goto out_add; /* success */
7531+
7532+ p = a + op->dy_type;
7533+ key = kzalloc(p->sz, GFP_NOFS);
7534+ if (unlikely(!key)) {
7535+ key = ERR_PTR(-ENOMEM);
7536+ goto out;
7537+ }
7538+
7539+ key->dk_op.dy_hop = op->dy_hop;
7540+ kref_init(&key->dk_kref);
b752ccd1 7541+ p->set(key, op->dy_hop, br->br_mnt->mnt_sb);
4a4d8108
AM
7542+ old = dy_gadd(spl, key);
7543+ if (old) {
7544+ kfree(key);
7545+ key = old;
7546+ }
7547+
7548+out_add:
7549+ old = dy_bradd(br, key);
7550+ if (old)
7551+ /* its ref-count should never be zero here */
7552+ kref_put(&key->dk_kref, dy_bug);
7553+out:
7554+ return key;
7555+}
7556+
7557+/* ---------------------------------------------------------------------- */
7558+/*
7559+ * Aufs prohibits O_DIRECT by defaut even if the branch supports it.
7560+ * This behaviour is neccessary to return an error from open(O_DIRECT) instead
7561+ * of the succeeding I/O. The dio mount option enables O_DIRECT and makes
7562+ * open(O_DIRECT) always succeed, but the succeeding I/O may return an error.
7563+ * See the aufs manual in detail.
7564+ *
7565+ * To keep this behaviour, aufs has to set NULL to ->get_xip_mem too, and the
7566+ * performance of fadvise() and madvise() may be affected.
7567+ */
7568+static void dy_adx(struct au_dyaop *dyaop, int do_dx)
7569+{
7570+ if (!do_dx) {
7571+ dyaop->da_op.direct_IO = NULL;
7572+ dyaop->da_op.get_xip_mem = NULL;
7573+ } else {
7574+ dyaop->da_op.direct_IO = aufs_aop.direct_IO;
7575+ dyaop->da_op.get_xip_mem = aufs_aop.get_xip_mem;
7576+ if (!dyaop->da_get_xip_mem)
7577+ dyaop->da_op.get_xip_mem = NULL;
7578+ }
7579+}
7580+
7581+static struct au_dyaop *dy_aget(struct au_branch *br,
7582+ const struct address_space_operations *h_aop,
7583+ int do_dx)
7584+{
7585+ struct au_dyaop *dyaop;
7586+ struct au_dynop op;
7587+
7588+ op.dy_type = AuDy_AOP;
7589+ op.dy_haop = h_aop;
7590+ dyaop = (void *)dy_get(&op, br);
7591+ if (IS_ERR(dyaop))
7592+ goto out;
7593+ dy_adx(dyaop, do_dx);
7594+
7595+out:
7596+ return dyaop;
7597+}
7598+
7599+int au_dy_iaop(struct inode *inode, aufs_bindex_t bindex,
7600+ struct inode *h_inode)
7601+{
7602+ int err, do_dx;
7603+ struct super_block *sb;
7604+ struct au_branch *br;
7605+ struct au_dyaop *dyaop;
7606+
7607+ AuDebugOn(!S_ISREG(h_inode->i_mode));
7608+ IiMustWriteLock(inode);
7609+
7610+ sb = inode->i_sb;
7611+ br = au_sbr(sb, bindex);
7612+ do_dx = !!au_opt_test(au_mntflags(sb), DIO);
7613+ dyaop = dy_aget(br, h_inode->i_mapping->a_ops, do_dx);
7614+ err = PTR_ERR(dyaop);
7615+ if (IS_ERR(dyaop))
7616+ /* unnecessary to call dy_fput() */
7617+ goto out;
7618+
7619+ err = 0;
7620+ inode->i_mapping->a_ops = &dyaop->da_op;
7621+
7622+out:
7623+ return err;
7624+}
7625+
b752ccd1
AM
7626+/*
7627+ * Is it safe to replace a_ops during the inode/file is in operation?
7628+ * Yes, I hope so.
7629+ */
7630+int au_dy_irefresh(struct inode *inode)
7631+{
7632+ int err;
7633+ aufs_bindex_t bstart;
7634+ struct inode *h_inode;
7635+
7636+ err = 0;
7637+ if (S_ISREG(inode->i_mode)) {
7638+ bstart = au_ibstart(inode);
7639+ h_inode = au_h_iptr(inode, bstart);
7640+ err = au_dy_iaop(inode, bstart, h_inode);
7641+ }
7642+ return err;
7643+}
7644+
4a4d8108
AM
7645+void au_dy_arefresh(int do_dx)
7646+{
7647+ struct au_splhead *spl;
7648+ struct list_head *head;
7649+ struct au_dykey *key;
7650+
7651+ spl = dynop + AuDy_AOP;
7652+ head = &spl->head;
7653+ spin_lock(&spl->spin);
7654+ list_for_each_entry(key, head, dk_list)
7655+ dy_adx((void *)key, do_dx);
7656+ spin_unlock(&spl->spin);
7657+}
7658+
4a4d8108
AM
7659+/* ---------------------------------------------------------------------- */
7660+
7661+void __init au_dy_init(void)
7662+{
7663+ int i;
7664+
7665+ /* make sure that 'struct au_dykey *' can be any type */
7666+ BUILD_BUG_ON(offsetof(struct au_dyaop, da_key));
4a4d8108
AM
7667+
7668+ for (i = 0; i < AuDyLast; i++)
7669+ au_spl_init(dynop + i);
7670+}
7671+
7672+void au_dy_fin(void)
7673+{
7674+ int i;
7675+
7676+ for (i = 0; i < AuDyLast; i++)
7677+ WARN_ON(!list_empty(&dynop[i].head));
7678+}
7f207e10
AM
7679diff -urN /usr/share/empty/fs/aufs/dynop.h linux/fs/aufs/dynop.h
7680--- /usr/share/empty/fs/aufs/dynop.h 1970-01-01 01:00:00.000000000 +0100
2cbb1c4b
JR
7681+++ linux/fs/aufs/dynop.h 2011-07-11 11:34:24.073331673 +0200
7682@@ -0,0 +1,80 @@
4a4d8108 7683+/*
027c5e7a 7684+ * Copyright (C) 2010-2011 Junjiro R. Okajima
4a4d8108
AM
7685+ *
7686+ * This program, aufs is free software; you can redistribute it and/or modify
7687+ * it under the terms of the GNU General Public License as published by
7688+ * the Free Software Foundation; either version 2 of the License, or
7689+ * (at your option) any later version.
7690+ *
7691+ * This program is distributed in the hope that it will be useful,
7692+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
7693+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
7694+ * GNU General Public License for more details.
7695+ *
7696+ * You should have received a copy of the GNU General Public License
7697+ * along with this program; if not, write to the Free Software
7698+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
7699+ */
7700+
7701+/*
7702+ * dynamically customizable operations (for regular files only)
7703+ */
7704+
7705+#ifndef __AUFS_DYNOP_H__
7706+#define __AUFS_DYNOP_H__
7707+
7708+#ifdef __KERNEL__
7709+
7710+#include <linux/fs.h>
7711+#include <linux/mm.h>
7712+#include <linux/rcupdate.h>
7713+#include <linux/aufs_type.h>
7714+#include "inode.h"
7715+
2cbb1c4b 7716+enum {AuDy_AOP, AuDyLast};
4a4d8108
AM
7717+
7718+struct au_dynop {
7719+ int dy_type;
7720+ union {
7721+ const void *dy_hop;
7722+ const struct address_space_operations *dy_haop;
4a4d8108
AM
7723+ };
7724+};
7725+
7726+struct au_dykey {
7727+ union {
7728+ struct list_head dk_list;
7729+ struct rcu_head dk_rcu;
7730+ };
7731+ struct au_dynop dk_op;
7732+
7733+ /*
7734+ * during I am in the branch local array, kref is gotten. when the
7735+ * branch is removed, kref is put.
7736+ */
7737+ struct kref dk_kref;
7738+};
7739+
7740+/* stop unioning since their sizes are very different from each other */
7741+struct au_dyaop {
7742+ struct au_dykey da_key;
7743+ struct address_space_operations da_op; /* not const */
7744+ int (*da_get_xip_mem)(struct address_space *, pgoff_t, int,
7745+ void **, unsigned long *);
7746+};
7747+
4a4d8108
AM
7748+/* ---------------------------------------------------------------------- */
7749+
7750+/* dynop.c */
7751+struct au_branch;
7752+void au_dy_put(struct au_dykey *key);
7753+int au_dy_iaop(struct inode *inode, aufs_bindex_t bindex,
7754+ struct inode *h_inode);
b752ccd1 7755+int au_dy_irefresh(struct inode *inode);
4a4d8108 7756+void au_dy_arefresh(int do_dio);
4a4d8108
AM
7757+
7758+void __init au_dy_init(void);
7759+void au_dy_fin(void);
7760+
4a4d8108
AM
7761+#endif /* __KERNEL__ */
7762+#endif /* __AUFS_DYNOP_H__ */
7f207e10
AM
7763diff -urN /usr/share/empty/fs/aufs/export.c linux/fs/aufs/export.c
7764--- /usr/share/empty/fs/aufs/export.c 1970-01-01 01:00:00.000000000 +0100
2cbb1c4b
JR
7765+++ linux/fs/aufs/export.c 2011-07-11 11:34:24.073331673 +0200
7766@@ -0,0 +1,805 @@
4a4d8108 7767+/*
027c5e7a 7768+ * Copyright (C) 2005-2011 Junjiro R. Okajima
4a4d8108
AM
7769+ *
7770+ * This program, aufs is free software; you can redistribute it and/or modify
7771+ * it under the terms of the GNU General Public License as published by
7772+ * the Free Software Foundation; either version 2 of the License, or
7773+ * (at your option) any later version.
7774+ *
7775+ * This program is distributed in the hope that it will be useful,
7776+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
7777+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
7778+ * GNU General Public License for more details.
7779+ *
7780+ * You should have received a copy of the GNU General Public License
7781+ * along with this program; if not, write to the Free Software
7782+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
7783+ */
7784+
7785+/*
7786+ * export via nfs
7787+ */
7788+
7789+#include <linux/exportfs.h>
7790+#include <linux/file.h>
7791+#include <linux/mnt_namespace.h>
7792+#include <linux/namei.h>
7793+#include <linux/nsproxy.h>
7794+#include <linux/random.h>
7795+#include <linux/writeback.h>
7796+#include "aufs.h"
7797+
7798+union conv {
7799+#ifdef CONFIG_AUFS_INO_T_64
7800+ __u32 a[2];
7801+#else
7802+ __u32 a[1];
7803+#endif
7804+ ino_t ino;
7805+};
7806+
7807+static ino_t decode_ino(__u32 *a)
7808+{
7809+ union conv u;
7810+
7811+ BUILD_BUG_ON(sizeof(u.ino) != sizeof(u.a));
7812+ u.a[0] = a[0];
7813+#ifdef CONFIG_AUFS_INO_T_64
7814+ u.a[1] = a[1];
7815+#endif
7816+ return u.ino;
7817+}
7818+
7819+static void encode_ino(__u32 *a, ino_t ino)
7820+{
7821+ union conv u;
7822+
7823+ u.ino = ino;
7824+ a[0] = u.a[0];
7825+#ifdef CONFIG_AUFS_INO_T_64
7826+ a[1] = u.a[1];
7827+#endif
7828+}
7829+
7830+/* NFS file handle */
7831+enum {
7832+ Fh_br_id,
7833+ Fh_sigen,
7834+#ifdef CONFIG_AUFS_INO_T_64
7835+ /* support 64bit inode number */
7836+ Fh_ino1,
7837+ Fh_ino2,
7838+ Fh_dir_ino1,
7839+ Fh_dir_ino2,
7840+#else
7841+ Fh_ino1,
7842+ Fh_dir_ino1,
7843+#endif
7844+ Fh_igen,
7845+ Fh_h_type,
7846+ Fh_tail,
7847+
7848+ Fh_ino = Fh_ino1,
7849+ Fh_dir_ino = Fh_dir_ino1
7850+};
7851+
7852+static int au_test_anon(struct dentry *dentry)
7853+{
027c5e7a 7854+ /* note: read d_flags without d_lock */
4a4d8108
AM
7855+ return !!(dentry->d_flags & DCACHE_DISCONNECTED);
7856+}
7857+
7858+/* ---------------------------------------------------------------------- */
7859+/* inode generation external table */
7860+
b752ccd1 7861+void au_xigen_inc(struct inode *inode)
4a4d8108 7862+{
4a4d8108
AM
7863+ loff_t pos;
7864+ ssize_t sz;
7865+ __u32 igen;
7866+ struct super_block *sb;
7867+ struct au_sbinfo *sbinfo;
7868+
4a4d8108 7869+ sb = inode->i_sb;
b752ccd1 7870+ AuDebugOn(!au_opt_test(au_mntflags(sb), XINO));
1facf9fc 7871+
b752ccd1 7872+ sbinfo = au_sbi(sb);
1facf9fc 7873+ pos = inode->i_ino;
7874+ pos *= sizeof(igen);
7875+ igen = inode->i_generation + 1;
1facf9fc 7876+ sz = xino_fwrite(sbinfo->si_xwrite, sbinfo->si_xigen, &igen,
7877+ sizeof(igen), &pos);
7878+ if (sz == sizeof(igen))
b752ccd1 7879+ return; /* success */
1facf9fc 7880+
b752ccd1 7881+ if (unlikely(sz >= 0))
1facf9fc 7882+ AuIOErr("xigen error (%zd)\n", sz);
1facf9fc 7883+}
7884+
7885+int au_xigen_new(struct inode *inode)
7886+{
7887+ int err;
7888+ loff_t pos;
7889+ ssize_t sz;
7890+ struct super_block *sb;
7891+ struct au_sbinfo *sbinfo;
7892+ struct file *file;
7893+
7894+ err = 0;
7895+ /* todo: dirty, at mount time */
7896+ if (inode->i_ino == AUFS_ROOT_INO)
7897+ goto out;
7898+ sb = inode->i_sb;
dece6358 7899+ SiMustAnyLock(sb);
1facf9fc 7900+ if (unlikely(!au_opt_test(au_mntflags(sb), XINO)))
7901+ goto out;
7902+
7903+ err = -EFBIG;
7904+ pos = inode->i_ino;
7905+ if (unlikely(au_loff_max / sizeof(inode->i_generation) - 1 < pos)) {
7906+ AuIOErr1("too large i%lld\n", pos);
7907+ goto out;
7908+ }
7909+ pos *= sizeof(inode->i_generation);
7910+
7911+ err = 0;
7912+ sbinfo = au_sbi(sb);
7913+ file = sbinfo->si_xigen;
7914+ BUG_ON(!file);
7915+
7916+ if (i_size_read(file->f_dentry->d_inode)
7917+ < pos + sizeof(inode->i_generation)) {
7918+ inode->i_generation = atomic_inc_return(&sbinfo->si_xigen_next);
7919+ sz = xino_fwrite(sbinfo->si_xwrite, file, &inode->i_generation,
7920+ sizeof(inode->i_generation), &pos);
7921+ } else
7922+ sz = xino_fread(sbinfo->si_xread, file, &inode->i_generation,
7923+ sizeof(inode->i_generation), &pos);
7924+ if (sz == sizeof(inode->i_generation))
7925+ goto out; /* success */
7926+
7927+ err = sz;
7928+ if (unlikely(sz >= 0)) {
7929+ err = -EIO;
7930+ AuIOErr("xigen error (%zd)\n", sz);
7931+ }
7932+
4f0767ce 7933+out:
1facf9fc 7934+ return err;
7935+}
7936+
7937+int au_xigen_set(struct super_block *sb, struct file *base)
7938+{
7939+ int err;
7940+ struct au_sbinfo *sbinfo;
7941+ struct file *file;
7942+
dece6358
AM
7943+ SiMustWriteLock(sb);
7944+
1facf9fc 7945+ sbinfo = au_sbi(sb);
7946+ file = au_xino_create2(base, sbinfo->si_xigen);
7947+ err = PTR_ERR(file);
7948+ if (IS_ERR(file))
7949+ goto out;
7950+ err = 0;
7951+ if (sbinfo->si_xigen)
7952+ fput(sbinfo->si_xigen);
7953+ sbinfo->si_xigen = file;
7954+
4f0767ce 7955+out:
1facf9fc 7956+ return err;
7957+}
7958+
7959+void au_xigen_clr(struct super_block *sb)
7960+{
7961+ struct au_sbinfo *sbinfo;
7962+
dece6358
AM
7963+ SiMustWriteLock(sb);
7964+
1facf9fc 7965+ sbinfo = au_sbi(sb);
7966+ if (sbinfo->si_xigen) {
7967+ fput(sbinfo->si_xigen);
7968+ sbinfo->si_xigen = NULL;
7969+ }
7970+}
7971+
7972+/* ---------------------------------------------------------------------- */
7973+
7974+static struct dentry *decode_by_ino(struct super_block *sb, ino_t ino,
7975+ ino_t dir_ino)
7976+{
7977+ struct dentry *dentry, *d;
7978+ struct inode *inode;
7979+ unsigned int sigen;
7980+
7981+ dentry = NULL;
7982+ inode = ilookup(sb, ino);
7983+ if (!inode)
7984+ goto out;
7985+
7986+ dentry = ERR_PTR(-ESTALE);
7987+ sigen = au_sigen(sb);
7988+ if (unlikely(is_bad_inode(inode)
7989+ || IS_DEADDIR(inode)
7990+ || sigen != au_iigen(inode)))
7991+ goto out_iput;
7992+
7993+ dentry = NULL;
7994+ if (!dir_ino || S_ISDIR(inode->i_mode))
7995+ dentry = d_find_alias(inode);
7996+ else {
027c5e7a
AM
7997+ spin_lock(&inode->i_lock);
7998+ list_for_each_entry(d, &inode->i_dentry, d_alias) {
7999+ spin_lock(&d->d_lock);
1facf9fc 8000+ if (!au_test_anon(d)
8001+ && d->d_parent->d_inode->i_ino == dir_ino) {
027c5e7a
AM
8002+ dentry = dget_dlock(d);
8003+ spin_unlock(&d->d_lock);
1facf9fc 8004+ break;
8005+ }
027c5e7a
AM
8006+ spin_unlock(&d->d_lock);
8007+ }
8008+ spin_unlock(&inode->i_lock);
1facf9fc 8009+ }
027c5e7a 8010+ if (unlikely(dentry && au_digen_test(dentry, sigen))) {
2cbb1c4b 8011+ /* need to refresh */
1facf9fc 8012+ dput(dentry);
2cbb1c4b 8013+ dentry = NULL;
1facf9fc 8014+ }
8015+
4f0767ce 8016+out_iput:
1facf9fc 8017+ iput(inode);
4f0767ce 8018+out:
2cbb1c4b 8019+ AuTraceErrPtr(dentry);
1facf9fc 8020+ return dentry;
8021+}
8022+
8023+/* ---------------------------------------------------------------------- */
8024+
8025+/* todo: dirty? */
8026+/* if exportfs_decode_fh() passed vfsmount*, we could be happy */
4a4d8108
AM
8027+
8028+struct au_compare_mnt_args {
8029+ /* input */
8030+ struct super_block *sb;
8031+
8032+ /* output */
8033+ struct vfsmount *mnt;
8034+};
8035+
8036+static int au_compare_mnt(struct vfsmount *mnt, void *arg)
8037+{
8038+ struct au_compare_mnt_args *a = arg;
8039+
8040+ if (mnt->mnt_sb != a->sb)
8041+ return 0;
8042+ a->mnt = mntget(mnt);
8043+ return 1;
8044+}
8045+
1facf9fc 8046+static struct vfsmount *au_mnt_get(struct super_block *sb)
8047+{
4a4d8108
AM
8048+ int err;
8049+ struct au_compare_mnt_args args = {
8050+ .sb = sb
8051+ };
1facf9fc 8052+ struct mnt_namespace *ns;
1facf9fc 8053+
0c5527e5 8054+ br_read_lock(vfsmount_lock);
1facf9fc 8055+ /* no get/put ?? */
8056+ AuDebugOn(!current->nsproxy);
8057+ ns = current->nsproxy->mnt_ns;
8058+ AuDebugOn(!ns);
4a4d8108 8059+ err = iterate_mounts(au_compare_mnt, &args, ns->root);
0c5527e5 8060+ br_read_unlock(vfsmount_lock);
4a4d8108
AM
8061+ AuDebugOn(!err);
8062+ AuDebugOn(!args.mnt);
8063+ return args.mnt;
1facf9fc 8064+}
8065+
8066+struct au_nfsd_si_lock {
4a4d8108 8067+ unsigned int sigen;
027c5e7a 8068+ aufs_bindex_t bindex, br_id;
1facf9fc 8069+ unsigned char force_lock;
8070+};
8071+
027c5e7a
AM
8072+static int si_nfsd_read_lock(struct super_block *sb,
8073+ struct au_nfsd_si_lock *nsi_lock)
1facf9fc 8074+{
027c5e7a 8075+ int err;
1facf9fc 8076+ aufs_bindex_t bindex;
8077+
8078+ si_read_lock(sb, AuLock_FLUSH);
8079+
8080+ /* branch id may be wrapped around */
027c5e7a 8081+ err = 0;
1facf9fc 8082+ bindex = au_br_index(sb, nsi_lock->br_id);
8083+ if (bindex >= 0 && nsi_lock->sigen + AUFS_BRANCH_MAX > au_sigen(sb))
8084+ goto out; /* success */
8085+
027c5e7a
AM
8086+ err = -ESTALE;
8087+ bindex = -1;
1facf9fc 8088+ if (!nsi_lock->force_lock)
8089+ si_read_unlock(sb);
1facf9fc 8090+
4f0767ce 8091+out:
027c5e7a
AM
8092+ nsi_lock->bindex = bindex;
8093+ return err;
1facf9fc 8094+}
8095+
8096+struct find_name_by_ino {
8097+ int called, found;
8098+ ino_t ino;
8099+ char *name;
8100+ int namelen;
8101+};
8102+
8103+static int
8104+find_name_by_ino(void *arg, const char *name, int namelen, loff_t offset,
8105+ u64 ino, unsigned int d_type)
8106+{
8107+ struct find_name_by_ino *a = arg;
8108+
8109+ a->called++;
8110+ if (a->ino != ino)
8111+ return 0;
8112+
8113+ memcpy(a->name, name, namelen);
8114+ a->namelen = namelen;
8115+ a->found = 1;
8116+ return 1;
8117+}
8118+
8119+static struct dentry *au_lkup_by_ino(struct path *path, ino_t ino,
8120+ struct au_nfsd_si_lock *nsi_lock)
8121+{
8122+ struct dentry *dentry, *parent;
8123+ struct file *file;
8124+ struct inode *dir;
8125+ struct find_name_by_ino arg;
8126+ int err;
8127+
8128+ parent = path->dentry;
8129+ if (nsi_lock)
8130+ si_read_unlock(parent->d_sb);
4a4d8108 8131+ file = vfsub_dentry_open(path, au_dir_roflags);
1facf9fc 8132+ dentry = (void *)file;
8133+ if (IS_ERR(file))
8134+ goto out;
8135+
8136+ dentry = ERR_PTR(-ENOMEM);
4a4d8108 8137+ arg.name = __getname_gfp(GFP_NOFS);
1facf9fc 8138+ if (unlikely(!arg.name))
8139+ goto out_file;
8140+ arg.ino = ino;
8141+ arg.found = 0;
8142+ do {
8143+ arg.called = 0;
8144+ /* smp_mb(); */
8145+ err = vfsub_readdir(file, find_name_by_ino, &arg);
8146+ } while (!err && !arg.found && arg.called);
8147+ dentry = ERR_PTR(err);
8148+ if (unlikely(err))
8149+ goto out_name;
8150+ dentry = ERR_PTR(-ENOENT);
8151+ if (!arg.found)
8152+ goto out_name;
8153+
8154+ /* do not call au_lkup_one() */
8155+ dir = parent->d_inode;
8156+ mutex_lock(&dir->i_mutex);
8157+ dentry = vfsub_lookup_one_len(arg.name, parent, arg.namelen);
8158+ mutex_unlock(&dir->i_mutex);
8159+ AuTraceErrPtr(dentry);
8160+ if (IS_ERR(dentry))
8161+ goto out_name;
8162+ AuDebugOn(au_test_anon(dentry));
8163+ if (unlikely(!dentry->d_inode)) {
8164+ dput(dentry);
8165+ dentry = ERR_PTR(-ENOENT);
8166+ }
8167+
4f0767ce 8168+out_name:
1facf9fc 8169+ __putname(arg.name);
4f0767ce 8170+out_file:
1facf9fc 8171+ fput(file);
4f0767ce 8172+out:
1facf9fc 8173+ if (unlikely(nsi_lock
8174+ && si_nfsd_read_lock(parent->d_sb, nsi_lock) < 0))
8175+ if (!IS_ERR(dentry)) {
8176+ dput(dentry);
8177+ dentry = ERR_PTR(-ESTALE);
8178+ }
8179+ AuTraceErrPtr(dentry);
8180+ return dentry;
8181+}
8182+
8183+static struct dentry *decode_by_dir_ino(struct super_block *sb, ino_t ino,
8184+ ino_t dir_ino,
8185+ struct au_nfsd_si_lock *nsi_lock)
8186+{
8187+ struct dentry *dentry;
8188+ struct path path;
8189+
8190+ if (dir_ino != AUFS_ROOT_INO) {
8191+ path.dentry = decode_by_ino(sb, dir_ino, 0);
8192+ dentry = path.dentry;
8193+ if (!path.dentry || IS_ERR(path.dentry))
8194+ goto out;
8195+ AuDebugOn(au_test_anon(path.dentry));
8196+ } else
8197+ path.dentry = dget(sb->s_root);
8198+
8199+ path.mnt = au_mnt_get(sb);
8200+ dentry = au_lkup_by_ino(&path, ino, nsi_lock);
8201+ path_put(&path);
8202+
4f0767ce 8203+out:
1facf9fc 8204+ AuTraceErrPtr(dentry);
8205+ return dentry;
8206+}
8207+
8208+/* ---------------------------------------------------------------------- */
8209+
8210+static int h_acceptable(void *expv, struct dentry *dentry)
8211+{
8212+ return 1;
8213+}
8214+
8215+static char *au_build_path(struct dentry *h_parent, struct path *h_rootpath,
8216+ char *buf, int len, struct super_block *sb)
8217+{
8218+ char *p;
8219+ int n;
8220+ struct path path;
8221+
8222+ p = d_path(h_rootpath, buf, len);
8223+ if (IS_ERR(p))
8224+ goto out;
8225+ n = strlen(p);
8226+
8227+ path.mnt = h_rootpath->mnt;
8228+ path.dentry = h_parent;
8229+ p = d_path(&path, buf, len);
8230+ if (IS_ERR(p))
8231+ goto out;
8232+ if (n != 1)
8233+ p += n;
8234+
8235+ path.mnt = au_mnt_get(sb);
8236+ path.dentry = sb->s_root;
8237+ p = d_path(&path, buf, len - strlen(p));
8238+ mntput(path.mnt);
8239+ if (IS_ERR(p))
8240+ goto out;
8241+ if (n != 1)
8242+ p[strlen(p)] = '/';
8243+
4f0767ce 8244+out:
1facf9fc 8245+ AuTraceErrPtr(p);
8246+ return p;
8247+}
8248+
8249+static
027c5e7a
AM
8250+struct dentry *decode_by_path(struct super_block *sb, ino_t ino, __u32 *fh,
8251+ int fh_len, struct au_nfsd_si_lock *nsi_lock)
1facf9fc 8252+{
8253+ struct dentry *dentry, *h_parent, *root;
8254+ struct super_block *h_sb;
8255+ char *pathname, *p;
8256+ struct vfsmount *h_mnt;
8257+ struct au_branch *br;
8258+ int err;
8259+ struct path path;
8260+
027c5e7a 8261+ br = au_sbr(sb, nsi_lock->bindex);
1facf9fc 8262+ h_mnt = br->br_mnt;
8263+ h_sb = h_mnt->mnt_sb;
8264+ /* todo: call lower fh_to_dentry()? fh_to_parent()? */
8265+ h_parent = exportfs_decode_fh(h_mnt, (void *)(fh + Fh_tail),
8266+ fh_len - Fh_tail, fh[Fh_h_type],
8267+ h_acceptable, /*context*/NULL);
8268+ dentry = h_parent;
8269+ if (unlikely(!h_parent || IS_ERR(h_parent))) {
8270+ AuWarn1("%s decode_fh failed, %ld\n",
8271+ au_sbtype(h_sb), PTR_ERR(h_parent));
8272+ goto out;
8273+ }
8274+ dentry = NULL;
8275+ if (unlikely(au_test_anon(h_parent))) {
8276+ AuWarn1("%s decode_fh returned a disconnected dentry\n",
8277+ au_sbtype(h_sb));
8278+ goto out_h_parent;
8279+ }
8280+
8281+ dentry = ERR_PTR(-ENOMEM);
8282+ pathname = (void *)__get_free_page(GFP_NOFS);
8283+ if (unlikely(!pathname))
8284+ goto out_h_parent;
8285+
8286+ root = sb->s_root;
8287+ path.mnt = h_mnt;
8288+ di_read_lock_parent(root, !AuLock_IR);
027c5e7a 8289+ path.dentry = au_h_dptr(root, nsi_lock->bindex);
1facf9fc 8290+ di_read_unlock(root, !AuLock_IR);
8291+ p = au_build_path(h_parent, &path, pathname, PAGE_SIZE, sb);
8292+ dentry = (void *)p;
8293+ if (IS_ERR(p))
8294+ goto out_pathname;
8295+
8296+ si_read_unlock(sb);
8297+ err = vfsub_kern_path(p, LOOKUP_FOLLOW | LOOKUP_DIRECTORY, &path);
8298+ dentry = ERR_PTR(err);
8299+ if (unlikely(err))
8300+ goto out_relock;
8301+
8302+ dentry = ERR_PTR(-ENOENT);
8303+ AuDebugOn(au_test_anon(path.dentry));
8304+ if (unlikely(!path.dentry->d_inode))
8305+ goto out_path;
8306+
8307+ if (ino != path.dentry->d_inode->i_ino)
8308+ dentry = au_lkup_by_ino(&path, ino, /*nsi_lock*/NULL);
8309+ else
8310+ dentry = dget(path.dentry);
8311+
4f0767ce 8312+out_path:
1facf9fc 8313+ path_put(&path);
4f0767ce 8314+out_relock:
1facf9fc 8315+ if (unlikely(si_nfsd_read_lock(sb, nsi_lock) < 0))
8316+ if (!IS_ERR(dentry)) {
8317+ dput(dentry);
8318+ dentry = ERR_PTR(-ESTALE);
8319+ }
4f0767ce 8320+out_pathname:
1facf9fc 8321+ free_page((unsigned long)pathname);
4f0767ce 8322+out_h_parent:
1facf9fc 8323+ dput(h_parent);
4f0767ce 8324+out:
1facf9fc 8325+ AuTraceErrPtr(dentry);
8326+ return dentry;
8327+}
8328+
8329+/* ---------------------------------------------------------------------- */
8330+
8331+static struct dentry *
8332+aufs_fh_to_dentry(struct super_block *sb, struct fid *fid, int fh_len,
8333+ int fh_type)
8334+{
8335+ struct dentry *dentry;
8336+ __u32 *fh = fid->raw;
027c5e7a 8337+ struct au_branch *br;
1facf9fc 8338+ ino_t ino, dir_ino;
1facf9fc 8339+ struct au_nfsd_si_lock nsi_lock = {
1facf9fc 8340+ .force_lock = 0
8341+ };
8342+
1facf9fc 8343+ dentry = ERR_PTR(-ESTALE);
4a4d8108
AM
8344+ /* it should never happen, but the file handle is unreliable */
8345+ if (unlikely(fh_len < Fh_tail))
8346+ goto out;
8347+ nsi_lock.sigen = fh[Fh_sigen];
8348+ nsi_lock.br_id = fh[Fh_br_id];
8349+
1facf9fc 8350+ /* branch id may be wrapped around */
027c5e7a
AM
8351+ br = NULL;
8352+ if (unlikely(si_nfsd_read_lock(sb, &nsi_lock)))
1facf9fc 8353+ goto out;
8354+ nsi_lock.force_lock = 1;
8355+
8356+ /* is this inode still cached? */
8357+ ino = decode_ino(fh + Fh_ino);
4a4d8108
AM
8358+ /* it should never happen */
8359+ if (unlikely(ino == AUFS_ROOT_INO))
8360+ goto out;
8361+
1facf9fc 8362+ dir_ino = decode_ino(fh + Fh_dir_ino);
8363+ dentry = decode_by_ino(sb, ino, dir_ino);
8364+ if (IS_ERR(dentry))
8365+ goto out_unlock;
8366+ if (dentry)
8367+ goto accept;
8368+
8369+ /* is the parent dir cached? */
027c5e7a
AM
8370+ br = au_sbr(sb, nsi_lock.bindex);
8371+ atomic_inc(&br->br_count);
1facf9fc 8372+ dentry = decode_by_dir_ino(sb, ino, dir_ino, &nsi_lock);
8373+ if (IS_ERR(dentry))
8374+ goto out_unlock;
8375+ if (dentry)
8376+ goto accept;
8377+
8378+ /* lookup path */
027c5e7a 8379+ dentry = decode_by_path(sb, ino, fh, fh_len, &nsi_lock);
1facf9fc 8380+ if (IS_ERR(dentry))
8381+ goto out_unlock;
8382+ if (unlikely(!dentry))
8383+ /* todo?: make it ESTALE */
8384+ goto out_unlock;
8385+
4f0767ce 8386+accept:
027c5e7a
AM
8387+ if (!au_digen_test(dentry, au_sigen(sb))
8388+ && dentry->d_inode->i_generation == fh[Fh_igen])
1facf9fc 8389+ goto out_unlock; /* success */
8390+
8391+ dput(dentry);
8392+ dentry = ERR_PTR(-ESTALE);
4f0767ce 8393+out_unlock:
027c5e7a
AM
8394+ if (br)
8395+ atomic_dec(&br->br_count);
1facf9fc 8396+ si_read_unlock(sb);
4f0767ce 8397+out:
1facf9fc 8398+ AuTraceErrPtr(dentry);
8399+ return dentry;
8400+}
8401+
8402+#if 0 /* reserved for future use */
8403+/* support subtreecheck option */
8404+static struct dentry *aufs_fh_to_parent(struct super_block *sb, struct fid *fid,
8405+ int fh_len, int fh_type)
8406+{
8407+ struct dentry *parent;
8408+ __u32 *fh = fid->raw;
8409+ ino_t dir_ino;
8410+
8411+ dir_ino = decode_ino(fh + Fh_dir_ino);
8412+ parent = decode_by_ino(sb, dir_ino, 0);
8413+ if (IS_ERR(parent))
8414+ goto out;
8415+ if (!parent)
8416+ parent = decode_by_path(sb, au_br_index(sb, fh[Fh_br_id]),
8417+ dir_ino, fh, fh_len);
8418+
4f0767ce 8419+out:
1facf9fc 8420+ AuTraceErrPtr(parent);
8421+ return parent;
8422+}
8423+#endif
8424+
8425+/* ---------------------------------------------------------------------- */
8426+
8427+static int aufs_encode_fh(struct dentry *dentry, __u32 *fh, int *max_len,
8428+ int connectable)
8429+{
8430+ int err;
8431+ aufs_bindex_t bindex, bend;
8432+ struct super_block *sb, *h_sb;
8433+ struct inode *inode;
8434+ struct dentry *parent, *h_parent;
8435+ struct au_branch *br;
8436+
8437+ AuDebugOn(au_test_anon(dentry));
8438+
8439+ parent = NULL;
8440+ err = -ENOSPC;
8441+ if (unlikely(*max_len <= Fh_tail)) {
8442+ AuWarn1("NFSv2 client (max_len %d)?\n", *max_len);
8443+ goto out;
8444+ }
8445+
8446+ err = FILEID_ROOT;
8447+ if (IS_ROOT(dentry)) {
8448+ AuDebugOn(dentry->d_inode->i_ino != AUFS_ROOT_INO);
8449+ goto out;
8450+ }
8451+
1facf9fc 8452+ h_parent = NULL;
027c5e7a
AM
8453+ err = aufs_read_lock(dentry, AuLock_FLUSH | AuLock_IR | AuLock_GEN);
8454+ if (unlikely(err))
8455+ goto out;
8456+
1facf9fc 8457+ inode = dentry->d_inode;
8458+ AuDebugOn(!inode);
027c5e7a 8459+ sb = dentry->d_sb;
1facf9fc 8460+#ifdef CONFIG_AUFS_DEBUG
8461+ if (unlikely(!au_opt_test(au_mntflags(sb), XINO)))
8462+ AuWarn1("NFS-exporting requires xino\n");
8463+#endif
027c5e7a
AM
8464+ err = -EIO;
8465+ parent = dget_parent(dentry);
8466+ di_read_lock_parent(parent, !AuLock_IR);
1facf9fc 8467+ bend = au_dbtaildir(parent);
8468+ for (bindex = au_dbstart(parent); bindex <= bend; bindex++) {
8469+ h_parent = au_h_dptr(parent, bindex);
8470+ if (h_parent) {
8471+ dget(h_parent);
8472+ break;
8473+ }
8474+ }
8475+ if (unlikely(!h_parent))
8476+ goto out_unlock;
8477+
8478+ err = -EPERM;
8479+ br = au_sbr(sb, bindex);
8480+ h_sb = br->br_mnt->mnt_sb;
8481+ if (unlikely(!h_sb->s_export_op)) {
8482+ AuErr1("%s branch is not exportable\n", au_sbtype(h_sb));
8483+ goto out_dput;
8484+ }
8485+
8486+ fh[Fh_br_id] = br->br_id;
8487+ fh[Fh_sigen] = au_sigen(sb);
8488+ encode_ino(fh + Fh_ino, inode->i_ino);
8489+ encode_ino(fh + Fh_dir_ino, parent->d_inode->i_ino);
8490+ fh[Fh_igen] = inode->i_generation;
8491+
8492+ *max_len -= Fh_tail;
8493+ fh[Fh_h_type] = exportfs_encode_fh(h_parent, (void *)(fh + Fh_tail),
8494+ max_len,
8495+ /*connectable or subtreecheck*/0);
8496+ err = fh[Fh_h_type];
8497+ *max_len += Fh_tail;
8498+ /* todo: macros? */
8499+ if (err != 255)
8500+ err = 99;
8501+ else
8502+ AuWarn1("%s encode_fh failed\n", au_sbtype(h_sb));
8503+
4f0767ce 8504+out_dput:
1facf9fc 8505+ dput(h_parent);
4f0767ce 8506+out_unlock:
1facf9fc 8507+ di_read_unlock(parent, !AuLock_IR);
8508+ dput(parent);
8509+ aufs_read_unlock(dentry, AuLock_IR);
4f0767ce 8510+out:
1facf9fc 8511+ if (unlikely(err < 0))
8512+ err = 255;
8513+ return err;
8514+}
8515+
8516+/* ---------------------------------------------------------------------- */
8517+
4a4d8108
AM
8518+static int aufs_commit_metadata(struct inode *inode)
8519+{
8520+ int err;
8521+ aufs_bindex_t bindex;
8522+ struct super_block *sb;
8523+ struct inode *h_inode;
8524+ int (*f)(struct inode *inode);
8525+
8526+ sb = inode->i_sb;
e49829fe 8527+ si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLMW);
4a4d8108
AM
8528+ ii_write_lock_child(inode);
8529+ bindex = au_ibstart(inode);
8530+ AuDebugOn(bindex < 0);
8531+ h_inode = au_h_iptr(inode, bindex);
8532+
8533+ f = h_inode->i_sb->s_export_op->commit_metadata;
8534+ if (f)
8535+ err = f(h_inode);
8536+ else {
8537+ struct writeback_control wbc = {
8538+ .sync_mode = WB_SYNC_ALL,
8539+ .nr_to_write = 0 /* metadata only */
8540+ };
8541+
8542+ err = sync_inode(h_inode, &wbc);
8543+ }
8544+
8545+ au_cpup_attr_timesizes(inode);
8546+ ii_write_unlock(inode);
8547+ si_read_unlock(sb);
8548+ return err;
8549+}
8550+
8551+/* ---------------------------------------------------------------------- */
8552+
1facf9fc 8553+static struct export_operations aufs_export_op = {
4a4d8108 8554+ .fh_to_dentry = aufs_fh_to_dentry,
1facf9fc 8555+ /* .fh_to_parent = aufs_fh_to_parent, */
4a4d8108
AM
8556+ .encode_fh = aufs_encode_fh,
8557+ .commit_metadata = aufs_commit_metadata
1facf9fc 8558+};
8559+
8560+void au_export_init(struct super_block *sb)
8561+{
8562+ struct au_sbinfo *sbinfo;
8563+ __u32 u;
8564+
8565+ sb->s_export_op = &aufs_export_op;
8566+ sbinfo = au_sbi(sb);
8567+ sbinfo->si_xigen = NULL;
8568+ get_random_bytes(&u, sizeof(u));
8569+ BUILD_BUG_ON(sizeof(u) != sizeof(int));
8570+ atomic_set(&sbinfo->si_xigen_next, u);
8571+}
7f207e10
AM
8572diff -urN /usr/share/empty/fs/aufs/file.c linux/fs/aufs/file.c
8573--- /usr/share/empty/fs/aufs/file.c 1970-01-01 01:00:00.000000000 +0100
2cbb1c4b
JR
8574+++ linux/fs/aufs/file.c 2011-07-11 11:34:24.073331673 +0200
8575@@ -0,0 +1,676 @@
1facf9fc 8576+/*
027c5e7a 8577+ * Copyright (C) 2005-2011 Junjiro R. Okajima
1facf9fc 8578+ *
8579+ * This program, aufs is free software; you can redistribute it and/or modify
8580+ * it under the terms of the GNU General Public License as published by
8581+ * the Free Software Foundation; either version 2 of the License, or
8582+ * (at your option) any later version.
dece6358
AM
8583+ *
8584+ * This program is distributed in the hope that it will be useful,
8585+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
8586+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
8587+ * GNU General Public License for more details.
8588+ *
8589+ * You should have received a copy of the GNU General Public License
8590+ * along with this program; if not, write to the Free Software
8591+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 8592+ */
8593+
8594+/*
4a4d8108 8595+ * handling file/dir, and address_space operation
1facf9fc 8596+ */
8597+
dece6358 8598+#include <linux/file.h>
4a4d8108
AM
8599+#include <linux/fsnotify.h>
8600+#include <linux/namei.h>
8601+#include <linux/pagemap.h>
1facf9fc 8602+#include "aufs.h"
8603+
4a4d8108
AM
8604+/* drop flags for writing */
8605+unsigned int au_file_roflags(unsigned int flags)
8606+{
8607+ flags &= ~(O_WRONLY | O_RDWR | O_APPEND | O_CREAT | O_TRUNC);
8608+ flags |= O_RDONLY | O_NOATIME;
8609+ return flags;
8610+}
8611+
8612+/* common functions to regular file and dir */
8613+struct file *au_h_open(struct dentry *dentry, aufs_bindex_t bindex, int flags,
8614+ struct file *file)
1facf9fc 8615+{
1308ab2a 8616+ struct file *h_file;
4a4d8108
AM
8617+ struct dentry *h_dentry;
8618+ struct inode *h_inode;
8619+ struct super_block *sb;
8620+ struct au_branch *br;
8621+ struct path h_path;
8622+ int err, exec_flag;
1facf9fc 8623+
4a4d8108
AM
8624+ /* a race condition can happen between open and unlink/rmdir */
8625+ h_file = ERR_PTR(-ENOENT);
8626+ h_dentry = au_h_dptr(dentry, bindex);
b752ccd1 8627+ if (au_test_nfsd() && !h_dentry)
4a4d8108
AM
8628+ goto out;
8629+ h_inode = h_dentry->d_inode;
b752ccd1 8630+ if (au_test_nfsd() && !h_inode)
4a4d8108 8631+ goto out;
027c5e7a
AM
8632+ spin_lock(&h_dentry->d_lock);
8633+ err = (!d_unhashed(dentry) && d_unlinked(h_dentry))
8634+ || !h_inode
8635+ /* || !dentry->d_inode->i_nlink */
8636+ ;
8637+ spin_unlock(&h_dentry->d_lock);
8638+ if (unlikely(err))
4a4d8108 8639+ goto out;
1facf9fc 8640+
4a4d8108
AM
8641+ sb = dentry->d_sb;
8642+ br = au_sbr(sb, bindex);
8643+ h_file = ERR_PTR(-EACCES);
2cbb1c4b 8644+ exec_flag = flags & __FMODE_EXEC;
4a4d8108 8645+ if (exec_flag && (br->br_mnt->mnt_flags & MNT_NOEXEC))
027c5e7a 8646+ goto out;
1facf9fc 8647+
4a4d8108
AM
8648+ /* drop flags for writing */
8649+ if (au_test_ro(sb, bindex, dentry->d_inode))
8650+ flags = au_file_roflags(flags);
8651+ flags &= ~O_CREAT;
8652+ atomic_inc(&br->br_count);
8653+ h_path.dentry = h_dentry;
8654+ h_path.mnt = br->br_mnt;
8655+ if (!au_special_file(h_inode->i_mode))
8656+ h_file = vfsub_dentry_open(&h_path, flags);
8657+ else {
8658+ /* this block depends upon the configuration */
8659+ di_read_unlock(dentry, AuLock_IR);
8660+ fi_write_unlock(file);
8661+ si_read_unlock(sb);
8662+ h_file = vfsub_dentry_open(&h_path, flags);
8663+ si_noflush_read_lock(sb);
8664+ fi_write_lock(file);
8665+ di_read_lock_child(dentry, AuLock_IR);
dece6358 8666+ }
4a4d8108
AM
8667+ if (IS_ERR(h_file))
8668+ goto out_br;
dece6358 8669+
4a4d8108
AM
8670+ if (exec_flag) {
8671+ err = deny_write_access(h_file);
8672+ if (unlikely(err)) {
8673+ fput(h_file);
8674+ h_file = ERR_PTR(err);
8675+ goto out_br;
8676+ }
8677+ }
953406b4 8678+ fsnotify_open(h_file);
4a4d8108 8679+ goto out; /* success */
1facf9fc 8680+
4f0767ce 8681+out_br:
4a4d8108 8682+ atomic_dec(&br->br_count);
4f0767ce 8683+out:
4a4d8108
AM
8684+ return h_file;
8685+}
1308ab2a 8686+
4a4d8108
AM
8687+int au_do_open(struct file *file, int (*open)(struct file *file, int flags),
8688+ struct au_fidir *fidir)
1facf9fc 8689+{
dece6358 8690+ int err;
1facf9fc 8691+ struct dentry *dentry;
1308ab2a 8692+
4a4d8108
AM
8693+ err = au_finfo_init(file, fidir);
8694+ if (unlikely(err))
8695+ goto out;
1facf9fc 8696+
8697+ dentry = file->f_dentry;
4a4d8108
AM
8698+ di_read_lock_child(dentry, AuLock_IR);
8699+ err = open(file, vfsub_file_flags(file));
8700+ di_read_unlock(dentry, AuLock_IR);
1facf9fc 8701+
4a4d8108
AM
8702+ fi_write_unlock(file);
8703+ if (unlikely(err)) {
8704+ au_fi(file)->fi_hdir = NULL;
8705+ au_finfo_fin(file);
1308ab2a 8706+ }
4a4d8108 8707+
4f0767ce 8708+out:
1308ab2a 8709+ return err;
8710+}
dece6358 8711+
4a4d8108 8712+int au_reopen_nondir(struct file *file)
1308ab2a 8713+{
4a4d8108
AM
8714+ int err;
8715+ aufs_bindex_t bstart;
8716+ struct dentry *dentry;
8717+ struct file *h_file, *h_file_tmp;
1308ab2a 8718+
4a4d8108
AM
8719+ dentry = file->f_dentry;
8720+ AuDebugOn(au_special_file(dentry->d_inode->i_mode));
8721+ bstart = au_dbstart(dentry);
8722+ h_file_tmp = NULL;
8723+ if (au_fbstart(file) == bstart) {
8724+ h_file = au_hf_top(file);
8725+ if (file->f_mode == h_file->f_mode)
8726+ return 0; /* success */
8727+ h_file_tmp = h_file;
8728+ get_file(h_file_tmp);
8729+ au_set_h_fptr(file, bstart, NULL);
8730+ }
8731+ AuDebugOn(au_fi(file)->fi_hdir);
8732+ AuDebugOn(au_fbstart(file) < bstart);
1308ab2a 8733+
4a4d8108
AM
8734+ h_file = au_h_open(dentry, bstart, vfsub_file_flags(file) & ~O_TRUNC,
8735+ file);
8736+ err = PTR_ERR(h_file);
8737+ if (IS_ERR(h_file))
8738+ goto out; /* todo: close all? */
8739+
8740+ err = 0;
8741+ au_set_fbstart(file, bstart);
8742+ au_set_h_fptr(file, bstart, h_file);
8743+ au_update_figen(file);
8744+ /* todo: necessary? */
8745+ /* file->f_ra = h_file->f_ra; */
8746+
4f0767ce 8747+out:
4a4d8108
AM
8748+ if (h_file_tmp)
8749+ fput(h_file_tmp);
8750+ return err;
1facf9fc 8751+}
8752+
1308ab2a 8753+/* ---------------------------------------------------------------------- */
8754+
4a4d8108
AM
8755+static int au_reopen_wh(struct file *file, aufs_bindex_t btgt,
8756+ struct dentry *hi_wh)
1facf9fc 8757+{
4a4d8108
AM
8758+ int err;
8759+ aufs_bindex_t bstart;
8760+ struct au_dinfo *dinfo;
8761+ struct dentry *h_dentry;
8762+ struct au_hdentry *hdp;
1facf9fc 8763+
4a4d8108
AM
8764+ dinfo = au_di(file->f_dentry);
8765+ AuRwMustWriteLock(&dinfo->di_rwsem);
dece6358 8766+
4a4d8108
AM
8767+ bstart = dinfo->di_bstart;
8768+ dinfo->di_bstart = btgt;
8769+ hdp = dinfo->di_hdentry;
8770+ h_dentry = hdp[0 + btgt].hd_dentry;
8771+ hdp[0 + btgt].hd_dentry = hi_wh;
8772+ err = au_reopen_nondir(file);
8773+ hdp[0 + btgt].hd_dentry = h_dentry;
8774+ dinfo->di_bstart = bstart;
1facf9fc 8775+
1facf9fc 8776+ return err;
8777+}
8778+
4a4d8108
AM
8779+static int au_ready_to_write_wh(struct file *file, loff_t len,
8780+ aufs_bindex_t bcpup)
1facf9fc 8781+{
4a4d8108 8782+ int err;
027c5e7a
AM
8783+ struct inode *inode, *h_inode;
8784+ struct dentry *dentry, *h_dentry, *hi_wh;
1facf9fc 8785+
dece6358 8786+ dentry = file->f_dentry;
4a4d8108 8787+ au_update_dbstart(dentry);
dece6358 8788+ inode = dentry->d_inode;
027c5e7a
AM
8789+ h_inode = NULL;
8790+ if (au_dbstart(dentry) <= bcpup && au_dbend(dentry) >= bcpup) {
8791+ h_dentry = au_h_dptr(dentry, bcpup);
8792+ if (h_dentry)
8793+ h_inode = h_dentry->d_inode;
8794+ }
4a4d8108 8795+ hi_wh = au_hi_wh(inode, bcpup);
027c5e7a 8796+ if (!hi_wh && !h_inode)
4a4d8108
AM
8797+ err = au_sio_cpup_wh(dentry, bcpup, len, file);
8798+ else
8799+ /* already copied-up after unlink */
8800+ err = au_reopen_wh(file, bcpup, hi_wh);
1facf9fc 8801+
4a4d8108
AM
8802+ if (!err
8803+ && inode->i_nlink > 1
8804+ && au_opt_test(au_mntflags(dentry->d_sb), PLINK))
8805+ au_plink_append(inode, bcpup, au_h_dptr(dentry, bcpup));
1308ab2a 8806+
dece6358 8807+ return err;
1facf9fc 8808+}
8809+
4a4d8108
AM
8810+/*
8811+ * prepare the @file for writing.
8812+ */
8813+int au_ready_to_write(struct file *file, loff_t len, struct au_pin *pin)
1facf9fc 8814+{
4a4d8108 8815+ int err;
027c5e7a 8816+ aufs_bindex_t bstart, bcpup, dbstart;
4a4d8108
AM
8817+ struct dentry *dentry, *parent, *h_dentry;
8818+ struct inode *h_inode, *inode;
1facf9fc 8819+ struct super_block *sb;
4a4d8108 8820+ struct file *h_file;
1facf9fc 8821+
8822+ dentry = file->f_dentry;
1facf9fc 8823+ sb = dentry->d_sb;
4a4d8108
AM
8824+ inode = dentry->d_inode;
8825+ AuDebugOn(au_special_file(inode->i_mode));
8826+ bstart = au_fbstart(file);
8827+ err = au_test_ro(sb, bstart, inode);
8828+ if (!err && (au_hf_top(file)->f_mode & FMODE_WRITE)) {
8829+ err = au_pin(pin, dentry, bstart, AuOpt_UDBA_NONE, /*flags*/0);
1facf9fc 8830+ goto out;
4a4d8108 8831+ }
1facf9fc 8832+
027c5e7a 8833+ /* need to cpup or reopen */
4a4d8108
AM
8834+ parent = dget_parent(dentry);
8835+ di_write_lock_parent(parent);
8836+ err = AuWbrCopyup(au_sbi(sb), dentry);
8837+ bcpup = err;
8838+ if (unlikely(err < 0))
8839+ goto out_dgrade;
8840+ err = 0;
8841+
027c5e7a 8842+ if (!d_unhashed(dentry) && !au_h_dptr(parent, bcpup)) {
4a4d8108 8843+ err = au_cpup_dirs(dentry, bcpup);
1facf9fc 8844+ if (unlikely(err))
4a4d8108
AM
8845+ goto out_dgrade;
8846+ }
8847+
8848+ err = au_pin(pin, dentry, bcpup, AuOpt_UDBA_NONE,
8849+ AuPin_DI_LOCKED | AuPin_MNT_WRITE);
8850+ if (unlikely(err))
8851+ goto out_dgrade;
8852+
8853+ h_dentry = au_hf_top(file)->f_dentry;
8854+ h_inode = h_dentry->d_inode;
027c5e7a
AM
8855+ dbstart = au_dbstart(dentry);
8856+ if (dbstart <= bcpup) {
8857+ h_dentry = au_h_dptr(dentry, bcpup);
8858+ AuDebugOn(!h_dentry);
8859+ h_inode = h_dentry->d_inode;
8860+ AuDebugOn(!h_inode);
8861+ bstart = bcpup;
8862+ }
8863+
8864+ if (dbstart <= bcpup /* just reopen */
8865+ || !d_unhashed(dentry) /* copyup and reopen */
8866+ ) {
8867+ mutex_lock_nested(&h_inode->i_mutex, AuLsc_I_CHILD);
8868+ h_file = au_h_open_pre(dentry, bstart);
8869+ if (IS_ERR(h_file)) {
8870+ err = PTR_ERR(h_file);
8871+ h_file = NULL;
8872+ } else {
8873+ di_downgrade_lock(parent, AuLock_IR);
8874+ if (dbstart > bcpup)
8875+ err = au_sio_cpup_simple(dentry, bcpup, len,
8876+ AuCpup_DTIME);
8877+ if (!err)
8878+ err = au_reopen_nondir(file);
8879+ }
8880+ mutex_unlock(&h_inode->i_mutex);
8881+ au_h_open_post(dentry, bstart, h_file);
8882+ } else { /* copyup as wh and reopen */
8883+ /*
8884+ * since writable hfsplus branch is not supported,
8885+ * h_open_pre/post() are unnecessary.
8886+ */
8887+ mutex_lock_nested(&h_inode->i_mutex, AuLsc_I_CHILD);
4a4d8108
AM
8888+ err = au_ready_to_write_wh(file, len, bcpup);
8889+ di_downgrade_lock(parent, AuLock_IR);
027c5e7a 8890+ mutex_unlock(&h_inode->i_mutex);
4a4d8108 8891+ }
4a4d8108
AM
8892+
8893+ if (!err) {
8894+ au_pin_set_parent_lflag(pin, /*lflag*/0);
8895+ goto out_dput; /* success */
8896+ }
8897+ au_unpin(pin);
8898+ goto out_unlock;
1facf9fc 8899+
4f0767ce 8900+out_dgrade:
4a4d8108 8901+ di_downgrade_lock(parent, AuLock_IR);
4f0767ce 8902+out_unlock:
4a4d8108 8903+ di_read_unlock(parent, AuLock_IR);
4f0767ce 8904+out_dput:
4a4d8108 8905+ dput(parent);
4f0767ce 8906+out:
1facf9fc 8907+ return err;
8908+}
8909+
4a4d8108
AM
8910+/* ---------------------------------------------------------------------- */
8911+
8912+int au_do_flush(struct file *file, fl_owner_t id,
8913+ int (*flush)(struct file *file, fl_owner_t id))
1facf9fc 8914+{
4a4d8108 8915+ int err;
1308ab2a 8916+ struct dentry *dentry;
1facf9fc 8917+ struct super_block *sb;
4a4d8108 8918+ struct inode *inode;
1facf9fc 8919+
1facf9fc 8920+ dentry = file->f_dentry;
8921+ sb = dentry->d_sb;
dece6358 8922+ inode = dentry->d_inode;
4a4d8108
AM
8923+ si_noflush_read_lock(sb);
8924+ fi_read_lock(file);
b752ccd1 8925+ ii_read_lock_child(inode);
1facf9fc 8926+
4a4d8108
AM
8927+ err = flush(file, id);
8928+ au_cpup_attr_timesizes(inode);
1facf9fc 8929+
b752ccd1 8930+ ii_read_unlock(inode);
4a4d8108 8931+ fi_read_unlock(file);
1308ab2a 8932+ si_read_unlock(sb);
dece6358 8933+ return err;
1facf9fc 8934+}
8935+
4a4d8108
AM
8936+/* ---------------------------------------------------------------------- */
8937+
8938+static int au_file_refresh_by_inode(struct file *file, int *need_reopen)
1facf9fc 8939+{
4a4d8108
AM
8940+ int err;
8941+ aufs_bindex_t bstart;
8942+ struct au_pin pin;
8943+ struct au_finfo *finfo;
8944+ struct dentry *dentry, *parent, *hi_wh;
8945+ struct inode *inode;
1facf9fc 8946+ struct super_block *sb;
8947+
4a4d8108
AM
8948+ FiMustWriteLock(file);
8949+
8950+ err = 0;
8951+ finfo = au_fi(file);
1308ab2a 8952+ dentry = file->f_dentry;
8953+ sb = dentry->d_sb;
4a4d8108
AM
8954+ inode = dentry->d_inode;
8955+ bstart = au_ibstart(inode);
027c5e7a 8956+ if (bstart == finfo->fi_btop || IS_ROOT(dentry))
1308ab2a 8957+ goto out;
dece6358 8958+
4a4d8108
AM
8959+ parent = dget_parent(dentry);
8960+ if (au_test_ro(sb, bstart, inode)) {
8961+ di_read_lock_parent(parent, !AuLock_IR);
8962+ err = AuWbrCopyup(au_sbi(sb), dentry);
8963+ bstart = err;
8964+ di_read_unlock(parent, !AuLock_IR);
8965+ if (unlikely(err < 0))
8966+ goto out_parent;
8967+ err = 0;
1facf9fc 8968+ }
1facf9fc 8969+
4a4d8108
AM
8970+ di_read_lock_parent(parent, AuLock_IR);
8971+ hi_wh = au_hi_wh(inode, bstart);
7f207e10
AM
8972+ if (!S_ISDIR(inode->i_mode)
8973+ && au_opt_test(au_mntflags(sb), PLINK)
4a4d8108
AM
8974+ && au_plink_test(inode)
8975+ && !d_unhashed(dentry)) {
8976+ err = au_test_and_cpup_dirs(dentry, bstart);
8977+ if (unlikely(err))
8978+ goto out_unlock;
8979+
8980+ /* always superio. */
8981+ err = au_pin(&pin, dentry, bstart, AuOpt_UDBA_NONE,
8982+ AuPin_DI_LOCKED | AuPin_MNT_WRITE);
8983+ if (!err)
8984+ err = au_sio_cpup_simple(dentry, bstart, -1,
8985+ AuCpup_DTIME);
8986+ au_unpin(&pin);
8987+ } else if (hi_wh) {
8988+ /* already copied-up after unlink */
8989+ err = au_reopen_wh(file, bstart, hi_wh);
8990+ *need_reopen = 0;
8991+ }
1facf9fc 8992+
4f0767ce 8993+out_unlock:
4a4d8108 8994+ di_read_unlock(parent, AuLock_IR);
4f0767ce 8995+out_parent:
4a4d8108 8996+ dput(parent);
4f0767ce 8997+out:
1308ab2a 8998+ return err;
dece6358 8999+}
1facf9fc 9000+
4a4d8108 9001+static void au_do_refresh_dir(struct file *file)
dece6358 9002+{
4a4d8108
AM
9003+ aufs_bindex_t bindex, bend, new_bindex, brid;
9004+ struct au_hfile *p, tmp, *q;
9005+ struct au_finfo *finfo;
1308ab2a 9006+ struct super_block *sb;
4a4d8108 9007+ struct au_fidir *fidir;
1facf9fc 9008+
4a4d8108 9009+ FiMustWriteLock(file);
1facf9fc 9010+
4a4d8108
AM
9011+ sb = file->f_dentry->d_sb;
9012+ finfo = au_fi(file);
9013+ fidir = finfo->fi_hdir;
9014+ AuDebugOn(!fidir);
9015+ p = fidir->fd_hfile + finfo->fi_btop;
9016+ brid = p->hf_br->br_id;
9017+ bend = fidir->fd_bbot;
9018+ for (bindex = finfo->fi_btop; bindex <= bend; bindex++, p++) {
9019+ if (!p->hf_file)
9020+ continue;
1308ab2a 9021+
4a4d8108
AM
9022+ new_bindex = au_br_index(sb, p->hf_br->br_id);
9023+ if (new_bindex == bindex)
9024+ continue;
9025+ if (new_bindex < 0) {
9026+ au_set_h_fptr(file, bindex, NULL);
9027+ continue;
9028+ }
1308ab2a 9029+
4a4d8108
AM
9030+ /* swap two lower inode, and loop again */
9031+ q = fidir->fd_hfile + new_bindex;
9032+ tmp = *q;
9033+ *q = *p;
9034+ *p = tmp;
9035+ if (tmp.hf_file) {
9036+ bindex--;
9037+ p--;
9038+ }
9039+ }
1308ab2a 9040+
4a4d8108 9041+ p = fidir->fd_hfile;
027c5e7a 9042+ if (!au_test_mmapped(file) && !d_unlinked(file->f_dentry)) {
4a4d8108
AM
9043+ bend = au_sbend(sb);
9044+ for (finfo->fi_btop = 0; finfo->fi_btop <= bend;
9045+ finfo->fi_btop++, p++)
9046+ if (p->hf_file) {
9047+ if (p->hf_file->f_dentry
9048+ && p->hf_file->f_dentry->d_inode)
9049+ break;
9050+ else
9051+ au_hfput(p, file);
9052+ }
9053+ } else {
9054+ bend = au_br_index(sb, brid);
9055+ for (finfo->fi_btop = 0; finfo->fi_btop < bend;
9056+ finfo->fi_btop++, p++)
9057+ if (p->hf_file)
9058+ au_hfput(p, file);
9059+ bend = au_sbend(sb);
9060+ }
1308ab2a 9061+
4a4d8108
AM
9062+ p = fidir->fd_hfile + bend;
9063+ for (fidir->fd_bbot = bend; fidir->fd_bbot >= finfo->fi_btop;
9064+ fidir->fd_bbot--, p--)
9065+ if (p->hf_file) {
9066+ if (p->hf_file->f_dentry
9067+ && p->hf_file->f_dentry->d_inode)
9068+ break;
9069+ else
9070+ au_hfput(p, file);
9071+ }
9072+ AuDebugOn(fidir->fd_bbot < finfo->fi_btop);
1308ab2a 9073+}
9074+
4a4d8108
AM
9075+/*
9076+ * after branch manipulating, refresh the file.
9077+ */
9078+static int refresh_file(struct file *file, int (*reopen)(struct file *file))
1facf9fc 9079+{
4a4d8108
AM
9080+ int err, need_reopen;
9081+ aufs_bindex_t bend, bindex;
9082+ struct dentry *dentry;
1308ab2a 9083+ struct au_finfo *finfo;
4a4d8108 9084+ struct au_hfile *hfile;
1facf9fc 9085+
4a4d8108 9086+ dentry = file->f_dentry;
1308ab2a 9087+ finfo = au_fi(file);
4a4d8108
AM
9088+ if (!finfo->fi_hdir) {
9089+ hfile = &finfo->fi_htop;
9090+ AuDebugOn(!hfile->hf_file);
9091+ bindex = au_br_index(dentry->d_sb, hfile->hf_br->br_id);
9092+ AuDebugOn(bindex < 0);
9093+ if (bindex != finfo->fi_btop)
9094+ au_set_fbstart(file, bindex);
9095+ } else {
9096+ err = au_fidir_realloc(finfo, au_sbend(dentry->d_sb) + 1);
9097+ if (unlikely(err))
9098+ goto out;
9099+ au_do_refresh_dir(file);
9100+ }
1facf9fc 9101+
4a4d8108
AM
9102+ err = 0;
9103+ need_reopen = 1;
9104+ if (!au_test_mmapped(file))
9105+ err = au_file_refresh_by_inode(file, &need_reopen);
027c5e7a 9106+ if (!err && need_reopen && !d_unlinked(dentry))
4a4d8108
AM
9107+ err = reopen(file);
9108+ if (!err) {
9109+ au_update_figen(file);
9110+ goto out; /* success */
9111+ }
9112+
9113+ /* error, close all lower files */
9114+ if (finfo->fi_hdir) {
9115+ bend = au_fbend_dir(file);
9116+ for (bindex = au_fbstart(file); bindex <= bend; bindex++)
9117+ au_set_h_fptr(file, bindex, NULL);
9118+ }
1facf9fc 9119+
4f0767ce 9120+out:
1facf9fc 9121+ return err;
9122+}
9123+
4a4d8108
AM
9124+/* common function to regular file and dir */
9125+int au_reval_and_lock_fdi(struct file *file, int (*reopen)(struct file *file),
9126+ int wlock)
dece6358 9127+{
1308ab2a 9128+ int err;
4a4d8108
AM
9129+ unsigned int sigen, figen;
9130+ aufs_bindex_t bstart;
9131+ unsigned char pseudo_link;
9132+ struct dentry *dentry;
9133+ struct inode *inode;
1facf9fc 9134+
4a4d8108
AM
9135+ err = 0;
9136+ dentry = file->f_dentry;
9137+ inode = dentry->d_inode;
9138+ AuDebugOn(au_special_file(inode->i_mode));
9139+ sigen = au_sigen(dentry->d_sb);
9140+ fi_write_lock(file);
9141+ figen = au_figen(file);
9142+ di_write_lock_child(dentry);
9143+ bstart = au_dbstart(dentry);
9144+ pseudo_link = (bstart != au_ibstart(inode));
9145+ if (sigen == figen && !pseudo_link && au_fbstart(file) == bstart) {
9146+ if (!wlock) {
9147+ di_downgrade_lock(dentry, AuLock_IR);
9148+ fi_downgrade_lock(file);
9149+ }
9150+ goto out; /* success */
9151+ }
dece6358 9152+
4a4d8108 9153+ AuDbg("sigen %d, figen %d\n", sigen, figen);
027c5e7a 9154+ if (au_digen_test(dentry, sigen)) {
4a4d8108 9155+ err = au_reval_dpath(dentry, sigen);
027c5e7a 9156+ AuDebugOn(!err && au_digen_test(dentry, sigen));
4a4d8108 9157+ }
dece6358 9158+
027c5e7a
AM
9159+ if (!err)
9160+ err = refresh_file(file, reopen);
4a4d8108
AM
9161+ if (!err) {
9162+ if (!wlock) {
9163+ di_downgrade_lock(dentry, AuLock_IR);
9164+ fi_downgrade_lock(file);
9165+ }
9166+ } else {
9167+ di_write_unlock(dentry);
9168+ fi_write_unlock(file);
9169+ }
1facf9fc 9170+
4f0767ce 9171+out:
1308ab2a 9172+ return err;
9173+}
1facf9fc 9174+
4a4d8108
AM
9175+/* ---------------------------------------------------------------------- */
9176+
9177+/* cf. aufs_nopage() */
9178+/* for madvise(2) */
9179+static int aufs_readpage(struct file *file __maybe_unused, struct page *page)
1308ab2a 9180+{
4a4d8108
AM
9181+ unlock_page(page);
9182+ return 0;
9183+}
1facf9fc 9184+
4a4d8108
AM
9185+/* it will never be called, but necessary to support O_DIRECT */
9186+static ssize_t aufs_direct_IO(int rw, struct kiocb *iocb,
9187+ const struct iovec *iov, loff_t offset,
9188+ unsigned long nr_segs)
9189+{ BUG(); return 0; }
1facf9fc 9190+
4a4d8108
AM
9191+/*
9192+ * it will never be called, but madvise and fadvise behaves differently
9193+ * when get_xip_mem is defined
9194+ */
9195+static int aufs_get_xip_mem(struct address_space *mapping, pgoff_t pgoff,
9196+ int create, void **kmem, unsigned long *pfn)
9197+{ BUG(); return 0; }
1facf9fc 9198+
4a4d8108
AM
9199+/* they will never be called. */
9200+#ifdef CONFIG_AUFS_DEBUG
9201+static int aufs_write_begin(struct file *file, struct address_space *mapping,
9202+ loff_t pos, unsigned len, unsigned flags,
9203+ struct page **pagep, void **fsdata)
9204+{ AuUnsupport(); return 0; }
9205+static int aufs_write_end(struct file *file, struct address_space *mapping,
9206+ loff_t pos, unsigned len, unsigned copied,
9207+ struct page *page, void *fsdata)
9208+{ AuUnsupport(); return 0; }
9209+static int aufs_writepage(struct page *page, struct writeback_control *wbc)
9210+{ AuUnsupport(); return 0; }
1308ab2a 9211+
4a4d8108
AM
9212+static int aufs_set_page_dirty(struct page *page)
9213+{ AuUnsupport(); return 0; }
9214+static void aufs_invalidatepage(struct page *page, unsigned long offset)
9215+{ AuUnsupport(); }
9216+static int aufs_releasepage(struct page *page, gfp_t gfp)
9217+{ AuUnsupport(); return 0; }
9218+static int aufs_migratepage(struct address_space *mapping, struct page *newpage,
9219+ struct page *page)
9220+{ AuUnsupport(); return 0; }
9221+static int aufs_launder_page(struct page *page)
9222+{ AuUnsupport(); return 0; }
9223+static int aufs_is_partially_uptodate(struct page *page,
9224+ read_descriptor_t *desc,
9225+ unsigned long from)
9226+{ AuUnsupport(); return 0; }
9227+static int aufs_error_remove_page(struct address_space *mapping,
9228+ struct page *page)
9229+{ AuUnsupport(); return 0; }
9230+#endif /* CONFIG_AUFS_DEBUG */
9231+
9232+const struct address_space_operations aufs_aop = {
9233+ .readpage = aufs_readpage,
9234+ .direct_IO = aufs_direct_IO,
9235+ .get_xip_mem = aufs_get_xip_mem,
9236+#ifdef CONFIG_AUFS_DEBUG
9237+ .writepage = aufs_writepage,
4a4d8108
AM
9238+ /* no writepages, because of writepage */
9239+ .set_page_dirty = aufs_set_page_dirty,
9240+ /* no readpages, because of readpage */
9241+ .write_begin = aufs_write_begin,
9242+ .write_end = aufs_write_end,
9243+ /* no bmap, no block device */
9244+ .invalidatepage = aufs_invalidatepage,
9245+ .releasepage = aufs_releasepage,
9246+ .migratepage = aufs_migratepage,
9247+ .launder_page = aufs_launder_page,
9248+ .is_partially_uptodate = aufs_is_partially_uptodate,
9249+ .error_remove_page = aufs_error_remove_page
9250+#endif /* CONFIG_AUFS_DEBUG */
dece6358 9251+};
7f207e10
AM
9252diff -urN /usr/share/empty/fs/aufs/file.h linux/fs/aufs/file.h
9253--- /usr/share/empty/fs/aufs/file.h 1970-01-01 01:00:00.000000000 +0100
2cbb1c4b
JR
9254+++ linux/fs/aufs/file.h 2011-07-11 11:34:24.073331673 +0200
9255@@ -0,0 +1,293 @@
4a4d8108 9256+/*
027c5e7a 9257+ * Copyright (C) 2005-2011 Junjiro R. Okajima
4a4d8108
AM
9258+ *
9259+ * This program, aufs is free software; you can redistribute it and/or modify
9260+ * it under the terms of the GNU General Public License as published by
9261+ * the Free Software Foundation; either version 2 of the License, or
9262+ * (at your option) any later version.
9263+ *
9264+ * This program is distributed in the hope that it will be useful,
9265+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
9266+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
9267+ * GNU General Public License for more details.
9268+ *
9269+ * You should have received a copy of the GNU General Public License
9270+ * along with this program; if not, write to the Free Software
9271+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
9272+ */
1facf9fc 9273+
4a4d8108
AM
9274+/*
9275+ * file operations
9276+ */
1facf9fc 9277+
4a4d8108
AM
9278+#ifndef __AUFS_FILE_H__
9279+#define __AUFS_FILE_H__
1facf9fc 9280+
4a4d8108 9281+#ifdef __KERNEL__
1facf9fc 9282+
2cbb1c4b 9283+#include <linux/file.h>
4a4d8108
AM
9284+#include <linux/fs.h>
9285+#include <linux/poll.h>
9286+#include <linux/aufs_type.h>
9287+#include "rwsem.h"
1facf9fc 9288+
4a4d8108
AM
9289+struct au_branch;
9290+struct au_hfile {
9291+ struct file *hf_file;
9292+ struct au_branch *hf_br;
9293+};
1facf9fc 9294+
4a4d8108
AM
9295+struct au_vdir;
9296+struct au_fidir {
9297+ aufs_bindex_t fd_bbot;
9298+ aufs_bindex_t fd_nent;
9299+ struct au_vdir *fd_vdir_cache;
9300+ struct au_hfile fd_hfile[];
9301+};
1facf9fc 9302+
4a4d8108 9303+static inline int au_fidir_sz(int nent)
dece6358 9304+{
4f0767ce
JR
9305+ AuDebugOn(nent < 0);
9306+ return sizeof(struct au_fidir) + sizeof(struct au_hfile) * nent;
4a4d8108 9307+}
1facf9fc 9308+
4a4d8108
AM
9309+struct au_finfo {
9310+ atomic_t fi_generation;
dece6358 9311+
4a4d8108
AM
9312+ struct au_rwsem fi_rwsem;
9313+ aufs_bindex_t fi_btop;
9314+
9315+ /* do not union them */
9316+ struct { /* for non-dir */
9317+ struct au_hfile fi_htop;
2cbb1c4b 9318+ atomic_t fi_mmapped;
4a4d8108
AM
9319+ };
9320+ struct au_fidir *fi_hdir; /* for dir only */
9321+} ____cacheline_aligned_in_smp;
1facf9fc 9322+
4a4d8108 9323+/* ---------------------------------------------------------------------- */
1facf9fc 9324+
4a4d8108
AM
9325+/* file.c */
9326+extern const struct address_space_operations aufs_aop;
9327+unsigned int au_file_roflags(unsigned int flags);
9328+struct file *au_h_open(struct dentry *dentry, aufs_bindex_t bindex, int flags,
9329+ struct file *file);
9330+int au_do_open(struct file *file, int (*open)(struct file *file, int flags),
9331+ struct au_fidir *fidir);
9332+int au_reopen_nondir(struct file *file);
9333+struct au_pin;
9334+int au_ready_to_write(struct file *file, loff_t len, struct au_pin *pin);
9335+int au_reval_and_lock_fdi(struct file *file, int (*reopen)(struct file *file),
9336+ int wlock);
9337+int au_do_flush(struct file *file, fl_owner_t id,
9338+ int (*flush)(struct file *file, fl_owner_t id));
1facf9fc 9339+
4a4d8108
AM
9340+/* poll.c */
9341+#ifdef CONFIG_AUFS_POLL
9342+unsigned int aufs_poll(struct file *file, poll_table *wait);
9343+#endif
1facf9fc 9344+
4a4d8108
AM
9345+#ifdef CONFIG_AUFS_BR_HFSPLUS
9346+/* hfsplus.c */
9347+struct file *au_h_open_pre(struct dentry *dentry, aufs_bindex_t bindex);
9348+void au_h_open_post(struct dentry *dentry, aufs_bindex_t bindex,
9349+ struct file *h_file);
9350+#else
9351+static inline
9352+struct file *au_h_open_pre(struct dentry *dentry, aufs_bindex_t bindex)
dece6358 9353+{
4a4d8108
AM
9354+ return NULL;
9355+}
1facf9fc 9356+
4a4d8108
AM
9357+AuStubVoid(au_h_open_post, struct dentry *dentry, aufs_bindex_t bindex,
9358+ struct file *h_file);
9359+#endif
1facf9fc 9360+
4a4d8108
AM
9361+/* f_op.c */
9362+extern const struct file_operations aufs_file_fop;
4a4d8108
AM
9363+int au_do_open_nondir(struct file *file, int flags);
9364+int aufs_release_nondir(struct inode *inode __maybe_unused, struct file *file);
9365+
9366+#ifdef CONFIG_AUFS_SP_IATTR
9367+/* f_op_sp.c */
9368+int au_special_file(umode_t mode);
9369+void au_init_special_fop(struct inode *inode, umode_t mode, dev_t rdev);
9370+#else
9371+AuStubInt0(au_special_file, umode_t mode)
9372+static inline void au_init_special_fop(struct inode *inode, umode_t mode,
9373+ dev_t rdev)
9374+{
9375+ init_special_inode(inode, mode, rdev);
9376+}
9377+#endif
1facf9fc 9378+
4a4d8108
AM
9379+/* finfo.c */
9380+void au_hfput(struct au_hfile *hf, struct file *file);
9381+void au_set_h_fptr(struct file *file, aufs_bindex_t bindex,
9382+ struct file *h_file);
1facf9fc 9383+
4a4d8108 9384+void au_update_figen(struct file *file);
4a4d8108
AM
9385+struct au_fidir *au_fidir_alloc(struct super_block *sb);
9386+int au_fidir_realloc(struct au_finfo *finfo, int nbr);
1facf9fc 9387+
4a4d8108
AM
9388+void au_fi_init_once(void *_fi);
9389+void au_finfo_fin(struct file *file);
9390+int au_finfo_init(struct file *file, struct au_fidir *fidir);
1facf9fc 9391+
4a4d8108
AM
9392+/* ioctl.c */
9393+long aufs_ioctl_nondir(struct file *file, unsigned int cmd, unsigned long arg);
b752ccd1
AM
9394+#ifdef CONFIG_COMPAT
9395+long aufs_compat_ioctl_dir(struct file *file, unsigned int cmd,
9396+ unsigned long arg);
9397+#endif
1facf9fc 9398+
4a4d8108 9399+/* ---------------------------------------------------------------------- */
1facf9fc 9400+
4a4d8108
AM
9401+static inline struct au_finfo *au_fi(struct file *file)
9402+{
9403+ return file->private_data;
9404+}
1facf9fc 9405+
4a4d8108 9406+/* ---------------------------------------------------------------------- */
1facf9fc 9407+
4a4d8108
AM
9408+/*
9409+ * fi_read_lock, fi_write_lock,
9410+ * fi_read_unlock, fi_write_unlock, fi_downgrade_lock
9411+ */
9412+AuSimpleRwsemFuncs(fi, struct file *f, &au_fi(f)->fi_rwsem);
1308ab2a 9413+
4a4d8108
AM
9414+#define FiMustNoWaiters(f) AuRwMustNoWaiters(&au_fi(f)->fi_rwsem)
9415+#define FiMustAnyLock(f) AuRwMustAnyLock(&au_fi(f)->fi_rwsem)
9416+#define FiMustWriteLock(f) AuRwMustWriteLock(&au_fi(f)->fi_rwsem)
1facf9fc 9417+
1308ab2a 9418+/* ---------------------------------------------------------------------- */
9419+
4a4d8108
AM
9420+/* todo: hard/soft set? */
9421+static inline aufs_bindex_t au_fbstart(struct file *file)
dece6358 9422+{
4a4d8108
AM
9423+ FiMustAnyLock(file);
9424+ return au_fi(file)->fi_btop;
9425+}
dece6358 9426+
4a4d8108
AM
9427+static inline aufs_bindex_t au_fbend_dir(struct file *file)
9428+{
9429+ FiMustAnyLock(file);
9430+ AuDebugOn(!au_fi(file)->fi_hdir);
9431+ return au_fi(file)->fi_hdir->fd_bbot;
9432+}
1facf9fc 9433+
4a4d8108
AM
9434+static inline struct au_vdir *au_fvdir_cache(struct file *file)
9435+{
9436+ FiMustAnyLock(file);
9437+ AuDebugOn(!au_fi(file)->fi_hdir);
9438+ return au_fi(file)->fi_hdir->fd_vdir_cache;
9439+}
1facf9fc 9440+
4a4d8108
AM
9441+static inline void au_set_fbstart(struct file *file, aufs_bindex_t bindex)
9442+{
9443+ FiMustWriteLock(file);
9444+ au_fi(file)->fi_btop = bindex;
9445+}
1facf9fc 9446+
4a4d8108
AM
9447+static inline void au_set_fbend_dir(struct file *file, aufs_bindex_t bindex)
9448+{
9449+ FiMustWriteLock(file);
9450+ AuDebugOn(!au_fi(file)->fi_hdir);
9451+ au_fi(file)->fi_hdir->fd_bbot = bindex;
9452+}
1308ab2a 9453+
4a4d8108
AM
9454+static inline void au_set_fvdir_cache(struct file *file,
9455+ struct au_vdir *vdir_cache)
9456+{
9457+ FiMustWriteLock(file);
9458+ AuDebugOn(!au_fi(file)->fi_hdir);
9459+ au_fi(file)->fi_hdir->fd_vdir_cache = vdir_cache;
9460+}
dece6358 9461+
4a4d8108
AM
9462+static inline struct file *au_hf_top(struct file *file)
9463+{
9464+ FiMustAnyLock(file);
9465+ AuDebugOn(au_fi(file)->fi_hdir);
9466+ return au_fi(file)->fi_htop.hf_file;
9467+}
1facf9fc 9468+
4a4d8108
AM
9469+static inline struct file *au_hf_dir(struct file *file, aufs_bindex_t bindex)
9470+{
9471+ FiMustAnyLock(file);
9472+ AuDebugOn(!au_fi(file)->fi_hdir);
9473+ return au_fi(file)->fi_hdir->fd_hfile[0 + bindex].hf_file;
dece6358
AM
9474+}
9475+
4a4d8108
AM
9476+/* todo: memory barrier? */
9477+static inline unsigned int au_figen(struct file *f)
dece6358 9478+{
4a4d8108
AM
9479+ return atomic_read(&au_fi(f)->fi_generation);
9480+}
dece6358 9481+
2cbb1c4b
JR
9482+static inline void au_set_mmapped(struct file *f)
9483+{
9484+ if (atomic_inc_return(&au_fi(f)->fi_mmapped))
9485+ return;
9486+ pr_warning("fi_mmapped wrapped around\n");
9487+ while (!atomic_inc_return(&au_fi(f)->fi_mmapped))
9488+ ;
9489+}
9490+
9491+static inline void au_unset_mmapped(struct file *f)
9492+{
9493+ atomic_dec(&au_fi(f)->fi_mmapped);
9494+}
9495+
4a4d8108
AM
9496+static inline int au_test_mmapped(struct file *f)
9497+{
2cbb1c4b
JR
9498+ return atomic_read(&au_fi(f)->fi_mmapped);
9499+}
9500+
9501+/* customize vma->vm_file */
9502+
9503+static inline void au_do_vm_file_reset(struct vm_area_struct *vma,
9504+ struct file *file)
9505+{
9506+ fput(vma->vm_file);
9507+ get_file(file);
9508+ vma->vm_file = file;
9509+}
9510+
9511+#ifdef CONFIG_MMU
9512+#define AuDbgVmRegion(file, vma) do {} while (0)
9513+
9514+static inline void au_vm_file_reset(struct vm_area_struct *vma,
9515+ struct file *file)
9516+{
9517+ au_do_vm_file_reset(vma, file);
9518+}
9519+#else
9520+#define AuDbgVmRegion(file, vma) \
9521+ AuDebugOn((vma)->vm_region && (vma)->vm_region->vm_file != (file))
9522+
9523+static inline void au_vm_file_reset(struct vm_area_struct *vma,
9524+ struct file *file)
9525+{
9526+ au_do_vm_file_reset(vma, file);
9527+ fput(vma->vm_region->vm_file);
9528+ get_file(file);
9529+ vma->vm_region->vm_file = file;
9530+}
9531+#endif /* CONFIG_MMU */
9532+
9533+/* handle vma->vm_prfile */
9534+static inline void au_vm_prfile_set(struct vm_area_struct *vma,
9535+ struct file *file)
9536+{
9537+#ifdef CONFIG_AUFS_PROC_MAP
9538+ get_file(file);
9539+ vma->vm_prfile = file;
9540+#ifndef CONFIG_MMU
9541+ get_file(file);
9542+ vma->vm_region->vm_prfile = file;
9543+#endif
9544+#endif
4a4d8108 9545+}
1308ab2a 9546+
4a4d8108
AM
9547+#endif /* __KERNEL__ */
9548+#endif /* __AUFS_FILE_H__ */
7f207e10
AM
9549diff -urN /usr/share/empty/fs/aufs/finfo.c linux/fs/aufs/finfo.c
9550--- /usr/share/empty/fs/aufs/finfo.c 1970-01-01 01:00:00.000000000 +0100
2cbb1c4b
JR
9551+++ linux/fs/aufs/finfo.c 2011-07-11 11:34:24.074331673 +0200
9552@@ -0,0 +1,153 @@
4a4d8108 9553+/*
027c5e7a 9554+ * Copyright (C) 2005-2011 Junjiro R. Okajima
4a4d8108
AM
9555+ *
9556+ * This program, aufs is free software; you can redistribute it and/or modify
9557+ * it under the terms of the GNU General Public License as published by
9558+ * the Free Software Foundation; either version 2 of the License, or
9559+ * (at your option) any later version.
9560+ *
9561+ * This program is distributed in the hope that it will be useful,
9562+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
9563+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
9564+ * GNU General Public License for more details.
9565+ *
9566+ * You should have received a copy of the GNU General Public License
9567+ * along with this program; if not, write to the Free Software
9568+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
9569+ */
1308ab2a 9570+
4a4d8108
AM
9571+/*
9572+ * file private data
9573+ */
1facf9fc 9574+
4a4d8108
AM
9575+#include <linux/file.h>
9576+#include "aufs.h"
1facf9fc 9577+
4a4d8108
AM
9578+void au_hfput(struct au_hfile *hf, struct file *file)
9579+{
9580+ /* todo: direct access f_flags */
2cbb1c4b 9581+ if (vfsub_file_flags(file) & __FMODE_EXEC)
4a4d8108
AM
9582+ allow_write_access(hf->hf_file);
9583+ fput(hf->hf_file);
9584+ hf->hf_file = NULL;
e49829fe 9585+ atomic_dec(&hf->hf_br->br_count);
4a4d8108
AM
9586+ hf->hf_br = NULL;
9587+}
1facf9fc 9588+
4a4d8108
AM
9589+void au_set_h_fptr(struct file *file, aufs_bindex_t bindex, struct file *val)
9590+{
9591+ struct au_finfo *finfo = au_fi(file);
9592+ struct au_hfile *hf;
9593+ struct au_fidir *fidir;
9594+
9595+ fidir = finfo->fi_hdir;
9596+ if (!fidir) {
9597+ AuDebugOn(finfo->fi_btop != bindex);
9598+ hf = &finfo->fi_htop;
9599+ } else
9600+ hf = fidir->fd_hfile + bindex;
9601+
9602+ if (hf && hf->hf_file)
9603+ au_hfput(hf, file);
9604+ if (val) {
9605+ FiMustWriteLock(file);
9606+ hf->hf_file = val;
9607+ hf->hf_br = au_sbr(file->f_dentry->d_sb, bindex);
1308ab2a 9608+ }
4a4d8108 9609+}
1facf9fc 9610+
4a4d8108
AM
9611+void au_update_figen(struct file *file)
9612+{
9613+ atomic_set(&au_fi(file)->fi_generation, au_digen(file->f_dentry));
9614+ /* smp_mb(); */ /* atomic_set */
1facf9fc 9615+}
9616+
4a4d8108
AM
9617+/* ---------------------------------------------------------------------- */
9618+
4a4d8108
AM
9619+struct au_fidir *au_fidir_alloc(struct super_block *sb)
9620+{
9621+ struct au_fidir *fidir;
9622+ int nbr;
9623+
9624+ nbr = au_sbend(sb) + 1;
9625+ if (nbr < 2)
9626+ nbr = 2; /* initial allocate for 2 branches */
9627+ fidir = kzalloc(au_fidir_sz(nbr), GFP_NOFS);
9628+ if (fidir) {
9629+ fidir->fd_bbot = -1;
9630+ fidir->fd_nent = nbr;
9631+ fidir->fd_vdir_cache = NULL;
9632+ }
9633+
9634+ return fidir;
9635+}
9636+
9637+int au_fidir_realloc(struct au_finfo *finfo, int nbr)
9638+{
9639+ int err;
9640+ struct au_fidir *fidir, *p;
9641+
9642+ AuRwMustWriteLock(&finfo->fi_rwsem);
9643+ fidir = finfo->fi_hdir;
9644+ AuDebugOn(!fidir);
9645+
9646+ err = -ENOMEM;
9647+ p = au_kzrealloc(fidir, au_fidir_sz(fidir->fd_nent), au_fidir_sz(nbr),
9648+ GFP_NOFS);
9649+ if (p) {
9650+ p->fd_nent = nbr;
9651+ finfo->fi_hdir = p;
9652+ err = 0;
9653+ }
1facf9fc 9654+
dece6358 9655+ return err;
1facf9fc 9656+}
1308ab2a 9657+
9658+/* ---------------------------------------------------------------------- */
9659+
4a4d8108 9660+void au_finfo_fin(struct file *file)
1308ab2a 9661+{
4a4d8108
AM
9662+ struct au_finfo *finfo;
9663+
7f207e10
AM
9664+ au_nfiles_dec(file->f_dentry->d_sb);
9665+
4a4d8108
AM
9666+ finfo = au_fi(file);
9667+ AuDebugOn(finfo->fi_hdir);
9668+ AuRwDestroy(&finfo->fi_rwsem);
9669+ au_cache_free_finfo(finfo);
1308ab2a 9670+}
1308ab2a 9671+
e49829fe 9672+void au_fi_init_once(void *_finfo)
4a4d8108 9673+{
e49829fe 9674+ struct au_finfo *finfo = _finfo;
2cbb1c4b 9675+ static struct lock_class_key aufs_fi;
1308ab2a 9676+
e49829fe
JR
9677+ au_rw_init(&finfo->fi_rwsem);
9678+ au_rw_class(&finfo->fi_rwsem, &aufs_fi);
4a4d8108 9679+}
1308ab2a 9680+
4a4d8108
AM
9681+int au_finfo_init(struct file *file, struct au_fidir *fidir)
9682+{
9683+ int err;
9684+ struct au_finfo *finfo;
9685+ struct dentry *dentry;
9686+
9687+ err = -ENOMEM;
9688+ dentry = file->f_dentry;
9689+ finfo = au_cache_alloc_finfo();
9690+ if (unlikely(!finfo))
9691+ goto out;
9692+
9693+ err = 0;
7f207e10 9694+ au_nfiles_inc(dentry->d_sb);
4a4d8108
AM
9695+ au_rw_write_lock(&finfo->fi_rwsem);
9696+ finfo->fi_btop = -1;
9697+ finfo->fi_hdir = fidir;
9698+ atomic_set(&finfo->fi_generation, au_digen(dentry));
9699+ /* smp_mb(); */ /* atomic_set */
9700+
9701+ file->private_data = finfo;
9702+
9703+out:
9704+ return err;
9705+}
7f207e10
AM
9706diff -urN /usr/share/empty/fs/aufs/f_op.c linux/fs/aufs/f_op.c
9707--- /usr/share/empty/fs/aufs/f_op.c 1970-01-01 01:00:00.000000000 +0100
2cbb1c4b
JR
9708+++ linux/fs/aufs/f_op.c 2011-07-11 11:34:24.073331673 +0200
9709@@ -0,0 +1,728 @@
dece6358 9710+/*
027c5e7a 9711+ * Copyright (C) 2005-2011 Junjiro R. Okajima
dece6358
AM
9712+ *
9713+ * This program, aufs is free software; you can redistribute it and/or modify
9714+ * it under the terms of the GNU General Public License as published by
9715+ * the Free Software Foundation; either version 2 of the License, or
9716+ * (at your option) any later version.
9717+ *
9718+ * This program is distributed in the hope that it will be useful,
9719+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
9720+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
9721+ * GNU General Public License for more details.
9722+ *
9723+ * You should have received a copy of the GNU General Public License
9724+ * along with this program; if not, write to the Free Software
9725+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
9726+ */
1facf9fc 9727+
9728+/*
4a4d8108 9729+ * file and vm operations
1facf9fc 9730+ */
dece6358
AM
9731+
9732+#include <linux/file.h>
4a4d8108
AM
9733+#include <linux/fs_stack.h>
9734+#include <linux/mman.h>
9735+#include <linux/mm.h>
9736+#include <linux/security.h>
dece6358
AM
9737+#include "aufs.h"
9738+
4a4d8108 9739+int au_do_open_nondir(struct file *file, int flags)
1facf9fc 9740+{
4a4d8108
AM
9741+ int err;
9742+ aufs_bindex_t bindex;
9743+ struct file *h_file;
9744+ struct dentry *dentry;
9745+ struct au_finfo *finfo;
9746+
9747+ FiMustWriteLock(file);
9748+
4a4d8108 9749+ dentry = file->f_dentry;
027c5e7a
AM
9750+ err = au_d_alive(dentry);
9751+ if (unlikely(err))
9752+ goto out;
9753+
4a4d8108
AM
9754+ finfo = au_fi(file);
9755+ memset(&finfo->fi_htop, 0, sizeof(finfo->fi_htop));
2cbb1c4b 9756+ atomic_set(&finfo->fi_mmapped, 0);
4a4d8108
AM
9757+ bindex = au_dbstart(dentry);
9758+ h_file = au_h_open(dentry, bindex, flags, file);
9759+ if (IS_ERR(h_file))
9760+ err = PTR_ERR(h_file);
9761+ else {
9762+ au_set_fbstart(file, bindex);
9763+ au_set_h_fptr(file, bindex, h_file);
9764+ au_update_figen(file);
9765+ /* todo: necessary? */
9766+ /* file->f_ra = h_file->f_ra; */
9767+ }
027c5e7a
AM
9768+
9769+out:
4a4d8108 9770+ return err;
1facf9fc 9771+}
9772+
4a4d8108
AM
9773+static int aufs_open_nondir(struct inode *inode __maybe_unused,
9774+ struct file *file)
1facf9fc 9775+{
4a4d8108 9776+ int err;
1308ab2a 9777+ struct super_block *sb;
1facf9fc 9778+
2cbb1c4b 9779+ AuDbg("%.*s, f_flags 0x%x, f_mode 0x%x\n",
4a4d8108
AM
9780+ AuDLNPair(file->f_dentry), vfsub_file_flags(file),
9781+ file->f_mode);
1facf9fc 9782+
4a4d8108
AM
9783+ sb = file->f_dentry->d_sb;
9784+ si_read_lock(sb, AuLock_FLUSH);
9785+ err = au_do_open(file, au_do_open_nondir, /*fidir*/NULL);
9786+ si_read_unlock(sb);
9787+ return err;
9788+}
1facf9fc 9789+
4a4d8108
AM
9790+int aufs_release_nondir(struct inode *inode __maybe_unused, struct file *file)
9791+{
9792+ struct au_finfo *finfo;
9793+ aufs_bindex_t bindex;
1facf9fc 9794+
4a4d8108
AM
9795+ finfo = au_fi(file);
9796+ bindex = finfo->fi_btop;
0c5527e5
AM
9797+ if (bindex >= 0) {
9798+ /* remove me from sb->s_files */
9799+ file_sb_list_del(file);
4a4d8108 9800+ au_set_h_fptr(file, bindex, NULL);
0c5527e5 9801+ }
7f207e10 9802+
4a4d8108
AM
9803+ au_finfo_fin(file);
9804+ return 0;
1facf9fc 9805+}
9806+
4a4d8108
AM
9807+/* ---------------------------------------------------------------------- */
9808+
9809+static int au_do_flush_nondir(struct file *file, fl_owner_t id)
dece6358 9810+{
1308ab2a 9811+ int err;
4a4d8108
AM
9812+ struct file *h_file;
9813+
9814+ err = 0;
9815+ h_file = au_hf_top(file);
9816+ if (h_file)
9817+ err = vfsub_flush(h_file, id);
9818+ return err;
9819+}
9820+
9821+static int aufs_flush_nondir(struct file *file, fl_owner_t id)
9822+{
9823+ return au_do_flush(file, id, au_do_flush_nondir);
9824+}
9825+
9826+/* ---------------------------------------------------------------------- */
9827+
9828+static ssize_t aufs_read(struct file *file, char __user *buf, size_t count,
9829+ loff_t *ppos)
9830+{
9831+ ssize_t err;
dece6358 9832+ struct dentry *dentry;
4a4d8108 9833+ struct file *h_file;
dece6358 9834+ struct super_block *sb;
1facf9fc 9835+
dece6358
AM
9836+ dentry = file->f_dentry;
9837+ sb = dentry->d_sb;
e49829fe 9838+ si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLMW);
4a4d8108 9839+ err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/0);
dece6358
AM
9840+ if (unlikely(err))
9841+ goto out;
1facf9fc 9842+
4a4d8108
AM
9843+ h_file = au_hf_top(file);
9844+ err = vfsub_read_u(h_file, buf, count, ppos);
9845+ /* todo: necessary? */
9846+ /* file->f_ra = h_file->f_ra; */
9847+ fsstack_copy_attr_atime(dentry->d_inode, h_file->f_dentry->d_inode);
1308ab2a 9848+
4a4d8108
AM
9849+ di_read_unlock(dentry, AuLock_IR);
9850+ fi_read_unlock(file);
4f0767ce 9851+out:
dece6358
AM
9852+ si_read_unlock(sb);
9853+ return err;
9854+}
1facf9fc 9855+
e49829fe
JR
9856+/*
9857+ * todo: very ugly
9858+ * it locks both of i_mutex and si_rwsem for read in safe.
9859+ * if the plink maintenance mode continues forever (that is the problem),
9860+ * may loop forever.
9861+ */
9862+static void au_mtx_and_read_lock(struct inode *inode)
9863+{
9864+ int err;
9865+ struct super_block *sb = inode->i_sb;
9866+
9867+ while (1) {
9868+ mutex_lock(&inode->i_mutex);
9869+ err = si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLM);
9870+ if (!err)
9871+ break;
9872+ mutex_unlock(&inode->i_mutex);
9873+ si_read_lock(sb, AuLock_NOPLMW);
9874+ si_read_unlock(sb);
9875+ }
9876+}
9877+
4a4d8108
AM
9878+static ssize_t aufs_write(struct file *file, const char __user *ubuf,
9879+ size_t count, loff_t *ppos)
dece6358 9880+{
4a4d8108
AM
9881+ ssize_t err;
9882+ struct au_pin pin;
dece6358 9883+ struct dentry *dentry;
4a4d8108 9884+ struct inode *inode;
4a4d8108
AM
9885+ struct file *h_file;
9886+ char __user *buf = (char __user *)ubuf;
1facf9fc 9887+
dece6358 9888+ dentry = file->f_dentry;
4a4d8108 9889+ inode = dentry->d_inode;
e49829fe 9890+ au_mtx_and_read_lock(inode);
1facf9fc 9891+
4a4d8108
AM
9892+ err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/1);
9893+ if (unlikely(err))
9894+ goto out;
1facf9fc 9895+
4a4d8108
AM
9896+ err = au_ready_to_write(file, -1, &pin);
9897+ di_downgrade_lock(dentry, AuLock_IR);
9898+ if (unlikely(err))
9899+ goto out_unlock;
1facf9fc 9900+
4a4d8108
AM
9901+ h_file = au_hf_top(file);
9902+ au_unpin(&pin);
9903+ err = vfsub_write_u(h_file, buf, count, ppos);
9904+ au_cpup_attr_timesizes(inode);
9905+ inode->i_mode = h_file->f_dentry->d_inode->i_mode;
1facf9fc 9906+
4f0767ce 9907+out_unlock:
4a4d8108
AM
9908+ di_read_unlock(dentry, AuLock_IR);
9909+ fi_write_unlock(file);
4f0767ce 9910+out:
e49829fe 9911+ si_read_unlock(inode->i_sb);
4a4d8108 9912+ mutex_unlock(&inode->i_mutex);
dece6358
AM
9913+ return err;
9914+}
1facf9fc 9915+
4a4d8108
AM
9916+static ssize_t au_do_aio(struct file *h_file, int rw, struct kiocb *kio,
9917+ const struct iovec *iov, unsigned long nv, loff_t pos)
dece6358 9918+{
4a4d8108
AM
9919+ ssize_t err;
9920+ struct file *file;
9921+ ssize_t (*func)(struct kiocb *, const struct iovec *, unsigned long,
9922+ loff_t);
1facf9fc 9923+
4a4d8108
AM
9924+ err = security_file_permission(h_file, rw);
9925+ if (unlikely(err))
9926+ goto out;
1facf9fc 9927+
4a4d8108
AM
9928+ err = -ENOSYS;
9929+ func = NULL;
9930+ if (rw == MAY_READ)
9931+ func = h_file->f_op->aio_read;
9932+ else if (rw == MAY_WRITE)
9933+ func = h_file->f_op->aio_write;
9934+ if (func) {
9935+ file = kio->ki_filp;
9936+ kio->ki_filp = h_file;
2cbb1c4b 9937+ lockdep_off();
4a4d8108 9938+ err = func(kio, iov, nv, pos);
2cbb1c4b 9939+ lockdep_on();
4a4d8108
AM
9940+ kio->ki_filp = file;
9941+ } else
9942+ /* currently there is no such fs */
9943+ WARN_ON_ONCE(1);
1facf9fc 9944+
4f0767ce 9945+out:
dece6358
AM
9946+ return err;
9947+}
1facf9fc 9948+
4a4d8108
AM
9949+static ssize_t aufs_aio_read(struct kiocb *kio, const struct iovec *iov,
9950+ unsigned long nv, loff_t pos)
1facf9fc 9951+{
4a4d8108
AM
9952+ ssize_t err;
9953+ struct file *file, *h_file;
9954+ struct dentry *dentry;
dece6358 9955+ struct super_block *sb;
1facf9fc 9956+
4a4d8108 9957+ file = kio->ki_filp;
dece6358 9958+ dentry = file->f_dentry;
1308ab2a 9959+ sb = dentry->d_sb;
e49829fe 9960+ si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLMW);
4a4d8108
AM
9961+ err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/0);
9962+ if (unlikely(err))
9963+ goto out;
9964+
9965+ h_file = au_hf_top(file);
9966+ err = au_do_aio(h_file, MAY_READ, kio, iov, nv, pos);
9967+ /* todo: necessary? */
9968+ /* file->f_ra = h_file->f_ra; */
9969+ fsstack_copy_attr_atime(dentry->d_inode, h_file->f_dentry->d_inode);
9970+ di_read_unlock(dentry, AuLock_IR);
9971+ fi_read_unlock(file);
1facf9fc 9972+
4f0767ce 9973+out:
4a4d8108 9974+ si_read_unlock(sb);
1308ab2a 9975+ return err;
9976+}
1facf9fc 9977+
4a4d8108
AM
9978+static ssize_t aufs_aio_write(struct kiocb *kio, const struct iovec *iov,
9979+ unsigned long nv, loff_t pos)
1308ab2a 9980+{
4a4d8108
AM
9981+ ssize_t err;
9982+ struct au_pin pin;
9983+ struct dentry *dentry;
9984+ struct inode *inode;
4a4d8108 9985+ struct file *file, *h_file;
1308ab2a 9986+
4a4d8108 9987+ file = kio->ki_filp;
1308ab2a 9988+ dentry = file->f_dentry;
1308ab2a 9989+ inode = dentry->d_inode;
e49829fe
JR
9990+ au_mtx_and_read_lock(inode);
9991+
4a4d8108
AM
9992+ err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/1);
9993+ if (unlikely(err))
1308ab2a 9994+ goto out;
1facf9fc 9995+
4a4d8108
AM
9996+ err = au_ready_to_write(file, -1, &pin);
9997+ di_downgrade_lock(dentry, AuLock_IR);
dece6358 9998+ if (unlikely(err))
4a4d8108 9999+ goto out_unlock;
1facf9fc 10000+
4a4d8108
AM
10001+ au_unpin(&pin);
10002+ h_file = au_hf_top(file);
10003+ err = au_do_aio(h_file, MAY_WRITE, kio, iov, nv, pos);
10004+ au_cpup_attr_timesizes(inode);
10005+ inode->i_mode = h_file->f_dentry->d_inode->i_mode;
1facf9fc 10006+
4f0767ce 10007+out_unlock:
4a4d8108
AM
10008+ di_read_unlock(dentry, AuLock_IR);
10009+ fi_write_unlock(file);
4f0767ce 10010+out:
e49829fe 10011+ si_read_unlock(inode->i_sb);
4a4d8108 10012+ mutex_unlock(&inode->i_mutex);
dece6358 10013+ return err;
1facf9fc 10014+}
10015+
4a4d8108
AM
10016+static ssize_t aufs_splice_read(struct file *file, loff_t *ppos,
10017+ struct pipe_inode_info *pipe, size_t len,
10018+ unsigned int flags)
1facf9fc 10019+{
4a4d8108
AM
10020+ ssize_t err;
10021+ struct file *h_file;
10022+ struct dentry *dentry;
dece6358 10023+ struct super_block *sb;
1facf9fc 10024+
dece6358 10025+ dentry = file->f_dentry;
dece6358 10026+ sb = dentry->d_sb;
e49829fe 10027+ si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLMW);
4a4d8108
AM
10028+ err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/0);
10029+ if (unlikely(err))
dece6358 10030+ goto out;
1facf9fc 10031+
4a4d8108
AM
10032+ err = -EINVAL;
10033+ h_file = au_hf_top(file);
10034+ if (au_test_loopback_kthread()) {
10035+ file->f_mapping = h_file->f_mapping;
10036+ smp_mb(); /* unnecessary? */
1308ab2a 10037+ }
4a4d8108
AM
10038+ err = vfsub_splice_to(h_file, ppos, pipe, len, flags);
10039+ /* todo: necessasry? */
10040+ /* file->f_ra = h_file->f_ra; */
10041+ fsstack_copy_attr_atime(dentry->d_inode, h_file->f_dentry->d_inode);
1facf9fc 10042+
4a4d8108
AM
10043+ di_read_unlock(dentry, AuLock_IR);
10044+ fi_read_unlock(file);
1facf9fc 10045+
4f0767ce 10046+out:
4a4d8108 10047+ si_read_unlock(sb);
dece6358 10048+ return err;
1facf9fc 10049+}
10050+
4a4d8108
AM
10051+static ssize_t
10052+aufs_splice_write(struct pipe_inode_info *pipe, struct file *file, loff_t *ppos,
10053+ size_t len, unsigned int flags)
1facf9fc 10054+{
4a4d8108
AM
10055+ ssize_t err;
10056+ struct au_pin pin;
10057+ struct dentry *dentry;
10058+ struct inode *inode;
4a4d8108 10059+ struct file *h_file;
1facf9fc 10060+
4a4d8108
AM
10061+ dentry = file->f_dentry;
10062+ inode = dentry->d_inode;
e49829fe 10063+ au_mtx_and_read_lock(inode);
4a4d8108
AM
10064+ err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/1);
10065+ if (unlikely(err))
10066+ goto out;
1facf9fc 10067+
4a4d8108
AM
10068+ err = au_ready_to_write(file, -1, &pin);
10069+ di_downgrade_lock(dentry, AuLock_IR);
10070+ if (unlikely(err))
10071+ goto out_unlock;
1facf9fc 10072+
4a4d8108
AM
10073+ h_file = au_hf_top(file);
10074+ au_unpin(&pin);
10075+ err = vfsub_splice_from(pipe, h_file, ppos, len, flags);
10076+ au_cpup_attr_timesizes(inode);
10077+ inode->i_mode = h_file->f_dentry->d_inode->i_mode;
1facf9fc 10078+
4f0767ce 10079+out_unlock:
4a4d8108
AM
10080+ di_read_unlock(dentry, AuLock_IR);
10081+ fi_write_unlock(file);
4f0767ce 10082+out:
e49829fe 10083+ si_read_unlock(inode->i_sb);
4a4d8108
AM
10084+ mutex_unlock(&inode->i_mutex);
10085+ return err;
10086+}
1facf9fc 10087+
4a4d8108
AM
10088+/* ---------------------------------------------------------------------- */
10089+
4a4d8108
AM
10090+/* cf. linux/include/linux/mman.h: calc_vm_prot_bits() */
10091+#define AuConv_VM_PROT(f, b) _calc_vm_trans(f, VM_##b, PROT_##b)
1308ab2a 10092+
4a4d8108 10093+static unsigned long au_arch_prot_conv(unsigned long flags)
dece6358 10094+{
4a4d8108
AM
10095+ /* currently ppc64 only */
10096+#ifdef CONFIG_PPC64
10097+ /* cf. linux/arch/powerpc/include/asm/mman.h */
10098+ AuDebugOn(arch_calc_vm_prot_bits(-1) != VM_SAO);
10099+ return AuConv_VM_PROT(flags, SAO);
10100+#else
10101+ AuDebugOn(arch_calc_vm_prot_bits(-1));
10102+ return 0;
10103+#endif
dece6358
AM
10104+}
10105+
4a4d8108 10106+static unsigned long au_prot_conv(unsigned long flags)
dece6358 10107+{
4a4d8108
AM
10108+ return AuConv_VM_PROT(flags, READ)
10109+ | AuConv_VM_PROT(flags, WRITE)
10110+ | AuConv_VM_PROT(flags, EXEC)
10111+ | au_arch_prot_conv(flags);
dece6358
AM
10112+}
10113+
4a4d8108
AM
10114+/* cf. linux/include/linux/mman.h: calc_vm_flag_bits() */
10115+#define AuConv_VM_MAP(f, b) _calc_vm_trans(f, VM_##b, MAP_##b)
dece6358 10116+
4a4d8108 10117+static unsigned long au_flag_conv(unsigned long flags)
dece6358 10118+{
4a4d8108
AM
10119+ return AuConv_VM_MAP(flags, GROWSDOWN)
10120+ | AuConv_VM_MAP(flags, DENYWRITE)
10121+ | AuConv_VM_MAP(flags, EXECUTABLE)
10122+ | AuConv_VM_MAP(flags, LOCKED);
dece6358 10123+}
1308ab2a 10124+/*
4a4d8108
AM
10125+ * This is another ugly approach to keep the lock order, particularly
10126+ * mm->mmap_sem and aufs rwsem. The previous approach was reverted and you can
10127+ * find it in git-log, if you want.
1308ab2a 10128+ *
4a4d8108
AM
10129+ * native readdir: i_mutex, copy_to_user, mmap_sem
10130+ * aufs readdir: i_mutex, rwsem, nested-i_mutex, copy_to_user, mmap_sem
1308ab2a 10131+ *
4a4d8108
AM
10132+ * Before aufs_mmap() mmap_sem is acquired already, but aufs_mmap() has to
10133+ * acquire aufs rwsem. It introduces a circular locking dependency.
10134+ * To address this problem, aufs_mmap() delegates the part which requires aufs
10135+ * rwsem to its internal workqueue.
1308ab2a 10136+ */
10137+
4a4d8108
AM
10138+struct au_mmap_pre_args {
10139+ /* input */
10140+ struct file *file;
10141+ struct vm_area_struct *vma;
1308ab2a 10142+
4a4d8108
AM
10143+ /* output */
10144+ int *errp;
10145+ struct file *h_file;
10146+ struct au_branch *br;
4a4d8108 10147+};
dece6358 10148+
4a4d8108 10149+static int au_mmap_pre(struct file *file, struct vm_area_struct *vma,
2cbb1c4b 10150+ struct file **h_file, struct au_branch **br)
dece6358 10151+{
4a4d8108
AM
10152+ int err;
10153+ aufs_bindex_t bstart;
10154+ const unsigned char wlock
10155+ = !!(file->f_mode & FMODE_WRITE) && (vma->vm_flags & VM_SHARED);
10156+ struct dentry *dentry;
10157+ struct super_block *sb;
1308ab2a 10158+
4a4d8108
AM
10159+ dentry = file->f_dentry;
10160+ sb = dentry->d_sb;
e49829fe 10161+ si_read_lock(sb, AuLock_NOPLMW);
4a4d8108
AM
10162+ err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/1);
10163+ if (unlikely(err))
10164+ goto out;
10165+
4a4d8108
AM
10166+ if (wlock) {
10167+ struct au_pin pin;
10168+
10169+ err = au_ready_to_write(file, -1, &pin);
10170+ di_write_unlock(dentry);
10171+ if (unlikely(err))
10172+ goto out_unlock;
10173+ au_unpin(&pin);
10174+ } else
10175+ di_write_unlock(dentry);
10176+ bstart = au_fbstart(file);
10177+ *br = au_sbr(sb, bstart);
10178+ *h_file = au_hf_top(file);
10179+ get_file(*h_file);
2cbb1c4b 10180+ au_set_mmapped(file);
4a4d8108
AM
10181+
10182+out_unlock:
10183+ fi_write_unlock(file);
10184+out:
10185+ si_read_unlock(sb);
10186+ return err;
dece6358
AM
10187+}
10188+
4a4d8108 10189+static void au_call_mmap_pre(void *args)
dece6358 10190+{
4a4d8108 10191+ struct au_mmap_pre_args *a = args;
2cbb1c4b 10192+ *a->errp = au_mmap_pre(a->file, a->vma, &a->h_file, &a->br);
dece6358
AM
10193+}
10194+
4a4d8108 10195+static int aufs_mmap(struct file *file, struct vm_area_struct *vma)
dece6358 10196+{
4a4d8108 10197+ int err, wkq_err;
2cbb1c4b 10198+ unsigned long prot;
4a4d8108
AM
10199+ struct au_mmap_pre_args args = {
10200+ .file = file,
10201+ .vma = vma,
10202+ .errp = &err
10203+ };
10204+
2cbb1c4b 10205+ AuDbgVmRegion(file, vma);
b752ccd1 10206+ wkq_err = au_wkq_wait_pre(au_call_mmap_pre, &args);
4a4d8108
AM
10207+ if (unlikely(wkq_err))
10208+ err = wkq_err;
10209+ if (unlikely(err))
10210+ goto out;
1308ab2a 10211+
2cbb1c4b
JR
10212+ au_vm_file_reset(vma, args.h_file);
10213+ prot = au_prot_conv(vma->vm_flags);
10214+ err = security_file_mmap(args.h_file, /*reqprot*/prot, prot,
10215+ au_flag_conv(vma->vm_flags), vma->vm_start, 0);
4a4d8108 10216+ if (unlikely(err))
2cbb1c4b 10217+ goto out_reset;
4a4d8108 10218+
2cbb1c4b
JR
10219+ err = args.h_file->f_op->mmap(args.h_file, vma);
10220+ if (unlikely(err))
10221+ goto out_reset;
4a4d8108 10222+
2cbb1c4b 10223+ au_vm_prfile_set(vma, file);
4a4d8108
AM
10224+ vfsub_file_accessed(args.h_file);
10225+ /* update without lock, I don't think it a problem */
2cbb1c4b
JR
10226+ fsstack_copy_attr_atime(file->f_dentry->d_inode,
10227+ args.h_file->f_dentry->d_inode);
10228+ goto out_fput; /* success */
4a4d8108 10229+
2cbb1c4b
JR
10230+out_reset:
10231+ au_unset_mmapped(file);
10232+ au_vm_file_reset(vma, file);
10233+out_fput:
4a4d8108 10234+ fput(args.h_file);
4f0767ce 10235+out:
4a4d8108
AM
10236+ return err;
10237+}
10238+
10239+/* ---------------------------------------------------------------------- */
10240+
b752ccd1 10241+static int aufs_fsync_nondir(struct file *file, int datasync)
4a4d8108
AM
10242+{
10243+ int err;
10244+ struct au_pin pin;
b752ccd1 10245+ struct dentry *dentry;
4a4d8108
AM
10246+ struct inode *inode;
10247+ struct file *h_file;
10248+ struct super_block *sb;
10249+
b752ccd1 10250+ dentry = file->f_dentry;
4a4d8108
AM
10251+ inode = dentry->d_inode;
10252+ IMustLock(file->f_mapping->host);
10253+ if (inode != file->f_mapping->host) {
10254+ mutex_unlock(&file->f_mapping->host->i_mutex);
10255+ mutex_lock(&inode->i_mutex);
10256+ }
10257+ IMustLock(inode);
10258+
10259+ sb = dentry->d_sb;
e49829fe
JR
10260+ err = si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLM);
10261+ if (unlikely(err))
10262+ goto out;
4a4d8108
AM
10263+
10264+ err = 0; /* -EBADF; */ /* posix? */
10265+ if (unlikely(!(file->f_mode & FMODE_WRITE)))
e49829fe 10266+ goto out_si;
4a4d8108
AM
10267+ err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/1);
10268+ if (unlikely(err))
e49829fe 10269+ goto out_si;
4a4d8108
AM
10270+
10271+ err = au_ready_to_write(file, -1, &pin);
10272+ di_downgrade_lock(dentry, AuLock_IR);
10273+ if (unlikely(err))
10274+ goto out_unlock;
10275+ au_unpin(&pin);
10276+
10277+ err = -EINVAL;
10278+ h_file = au_hf_top(file);
10279+ if (h_file->f_op && h_file->f_op->fsync) {
4a4d8108
AM
10280+ struct mutex *h_mtx;
10281+
10282+ /*
10283+ * no filemap_fdatawrite() since aufs file has no its own
10284+ * mapping, but dir.
10285+ */
b752ccd1 10286+ h_mtx = &h_file->f_dentry->d_inode->i_mutex;
4a4d8108 10287+ mutex_lock_nested(h_mtx, AuLsc_I_CHILD);
b752ccd1 10288+ err = h_file->f_op->fsync(h_file, datasync);
4a4d8108
AM
10289+ if (!err)
10290+ vfsub_update_h_iattr(&h_file->f_path, /*did*/NULL);
10291+ /*ignore*/
10292+ au_cpup_attr_timesizes(inode);
10293+ mutex_unlock(h_mtx);
10294+ }
10295+
4f0767ce 10296+out_unlock:
4a4d8108 10297+ di_read_unlock(dentry, AuLock_IR);
1308ab2a 10298+ fi_write_unlock(file);
e49829fe 10299+out_si:
953406b4 10300+ si_read_unlock(sb);
e49829fe 10301+out:
4a4d8108
AM
10302+ if (inode != file->f_mapping->host) {
10303+ mutex_unlock(&inode->i_mutex);
10304+ mutex_lock(&file->f_mapping->host->i_mutex);
10305+ }
10306+ return err;
dece6358
AM
10307+}
10308+
4a4d8108
AM
10309+/* no one supports this operation, currently */
10310+#if 0
10311+static int aufs_aio_fsync_nondir(struct kiocb *kio, int datasync)
dece6358 10312+{
4a4d8108
AM
10313+ int err;
10314+ struct au_pin pin;
1308ab2a 10315+ struct dentry *dentry;
4a4d8108
AM
10316+ struct inode *inode;
10317+ struct file *file, *h_file;
1308ab2a 10318+
4a4d8108 10319+ file = kio->ki_filp;
1308ab2a 10320+ dentry = file->f_dentry;
4a4d8108 10321+ inode = dentry->d_inode;
e49829fe 10322+ au_mtx_and_read_lock(inode);
4a4d8108
AM
10323+
10324+ err = 0; /* -EBADF; */ /* posix? */
10325+ if (unlikely(!(file->f_mode & FMODE_WRITE)))
10326+ goto out;
10327+ err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/1);
10328+ if (unlikely(err))
1308ab2a 10329+ goto out;
10330+
4a4d8108
AM
10331+ err = au_ready_to_write(file, -1, &pin);
10332+ di_downgrade_lock(dentry, AuLock_IR);
10333+ if (unlikely(err))
10334+ goto out_unlock;
10335+ au_unpin(&pin);
1308ab2a 10336+
4a4d8108
AM
10337+ err = -ENOSYS;
10338+ h_file = au_hf_top(file);
10339+ if (h_file->f_op && h_file->f_op->aio_fsync) {
10340+ struct dentry *h_d;
10341+ struct mutex *h_mtx;
1308ab2a 10342+
4a4d8108
AM
10343+ h_d = h_file->f_dentry;
10344+ h_mtx = &h_d->d_inode->i_mutex;
10345+ if (!is_sync_kiocb(kio)) {
10346+ get_file(h_file);
10347+ fput(file);
10348+ }
10349+ kio->ki_filp = h_file;
10350+ err = h_file->f_op->aio_fsync(kio, datasync);
10351+ mutex_lock_nested(h_mtx, AuLsc_I_CHILD);
10352+ if (!err)
10353+ vfsub_update_h_iattr(&h_file->f_path, /*did*/NULL);
10354+ /*ignore*/
10355+ au_cpup_attr_timesizes(inode);
10356+ mutex_unlock(h_mtx);
10357+ }
1308ab2a 10358+
4f0767ce 10359+out_unlock:
4a4d8108
AM
10360+ di_read_unlock(dentry, AuLock_IR);
10361+ fi_write_unlock(file);
4f0767ce 10362+out:
e49829fe 10363+ si_read_unlock(inode->sb);
4a4d8108
AM
10364+ mutex_unlock(&inode->i_mutex);
10365+ return err;
dece6358 10366+}
4a4d8108 10367+#endif
dece6358 10368+
4a4d8108 10369+static int aufs_fasync(int fd, struct file *file, int flag)
dece6358 10370+{
4a4d8108
AM
10371+ int err;
10372+ struct file *h_file;
10373+ struct dentry *dentry;
10374+ struct super_block *sb;
1308ab2a 10375+
4a4d8108
AM
10376+ dentry = file->f_dentry;
10377+ sb = dentry->d_sb;
e49829fe 10378+ si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLMW);
4a4d8108
AM
10379+ err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/0);
10380+ if (unlikely(err))
10381+ goto out;
10382+
10383+ h_file = au_hf_top(file);
10384+ if (h_file->f_op && h_file->f_op->fasync)
10385+ err = h_file->f_op->fasync(fd, h_file, flag);
10386+
10387+ di_read_unlock(dentry, AuLock_IR);
10388+ fi_read_unlock(file);
1308ab2a 10389+
4f0767ce 10390+out:
4a4d8108 10391+ si_read_unlock(sb);
1308ab2a 10392+ return err;
dece6358 10393+}
4a4d8108
AM
10394+
10395+/* ---------------------------------------------------------------------- */
10396+
10397+/* no one supports this operation, currently */
10398+#if 0
10399+static ssize_t aufs_sendpage(struct file *file, struct page *page, int offset,
10400+ size_t len, loff_t *pos , int more)
10401+{
10402+}
10403+#endif
10404+
10405+/* ---------------------------------------------------------------------- */
10406+
10407+const struct file_operations aufs_file_fop = {
10408+ .owner = THIS_MODULE,
2cbb1c4b 10409+
027c5e7a 10410+ .llseek = default_llseek,
4a4d8108
AM
10411+
10412+ .read = aufs_read,
10413+ .write = aufs_write,
10414+ .aio_read = aufs_aio_read,
10415+ .aio_write = aufs_aio_write,
10416+#ifdef CONFIG_AUFS_POLL
10417+ .poll = aufs_poll,
10418+#endif
10419+ .unlocked_ioctl = aufs_ioctl_nondir,
b752ccd1
AM
10420+#ifdef CONFIG_COMPAT
10421+ .compat_ioctl = aufs_ioctl_nondir, /* same */
10422+#endif
4a4d8108
AM
10423+ .mmap = aufs_mmap,
10424+ .open = aufs_open_nondir,
10425+ .flush = aufs_flush_nondir,
10426+ .release = aufs_release_nondir,
10427+ .fsync = aufs_fsync_nondir,
10428+ /* .aio_fsync = aufs_aio_fsync_nondir, */
10429+ .fasync = aufs_fasync,
10430+ /* .sendpage = aufs_sendpage, */
10431+ .splice_write = aufs_splice_write,
10432+ .splice_read = aufs_splice_read,
10433+#if 0
10434+ .aio_splice_write = aufs_aio_splice_write,
10435+ .aio_splice_read = aufs_aio_splice_read
10436+#endif
10437+};
7f207e10
AM
10438diff -urN /usr/share/empty/fs/aufs/f_op_sp.c linux/fs/aufs/f_op_sp.c
10439--- /usr/share/empty/fs/aufs/f_op_sp.c 1970-01-01 01:00:00.000000000 +0100
2cbb1c4b 10440+++ linux/fs/aufs/f_op_sp.c 2011-07-11 11:34:24.073331673 +0200
e49829fe 10441@@ -0,0 +1,299 @@
1308ab2a 10442+/*
027c5e7a 10443+ * Copyright (C) 2005-2011 Junjiro R. Okajima
1308ab2a 10444+ *
10445+ * This program, aufs is free software; you can redistribute it and/or modify
10446+ * it under the terms of the GNU General Public License as published by
10447+ * the Free Software Foundation; either version 2 of the License, or
10448+ * (at your option) any later version.
10449+ *
10450+ * This program is distributed in the hope that it will be useful,
10451+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
10452+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10453+ * GNU General Public License for more details.
10454+ *
10455+ * You should have received a copy of the GNU General Public License
10456+ * along with this program; if not, write to the Free Software
10457+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
10458+ */
dece6358 10459+
1308ab2a 10460+/*
4a4d8108
AM
10461+ * file operations for special files.
10462+ * while they exist in aufs virtually,
10463+ * their file I/O is handled out of aufs.
1308ab2a 10464+ */
10465+
4a4d8108
AM
10466+#include <linux/fs_stack.h>
10467+#include "aufs.h"
1308ab2a 10468+
4a4d8108
AM
10469+static ssize_t aufs_aio_read_sp(struct kiocb *kio, const struct iovec *iov,
10470+ unsigned long nv, loff_t pos)
dece6358 10471+{
4a4d8108
AM
10472+ ssize_t err;
10473+ aufs_bindex_t bstart;
10474+ unsigned char wbr;
10475+ struct file *file, *h_file;
10476+ struct super_block *sb;
1308ab2a 10477+
4a4d8108
AM
10478+ file = kio->ki_filp;
10479+ sb = file->f_dentry->d_sb;
10480+ si_read_lock(sb, AuLock_FLUSH);
10481+ fi_read_lock(file);
10482+ bstart = au_fbstart(file);
10483+ h_file = au_hf_top(file);
10484+ fi_read_unlock(file);
10485+ wbr = !!au_br_writable(au_sbr(sb, bstart)->br_perm);
10486+ si_read_unlock(sb);
10487+
10488+ /* do not change the file in kio */
10489+ AuDebugOn(!h_file->f_op || !h_file->f_op->aio_read);
10490+ err = h_file->f_op->aio_read(kio, iov, nv, pos);
10491+ if (err > 0 && wbr)
10492+ file_accessed(h_file);
10493+
10494+ return err;
10495+}
10496+
10497+static ssize_t aufs_aio_write_sp(struct kiocb *kio, const struct iovec *iov,
10498+ unsigned long nv, loff_t pos)
10499+{
10500+ ssize_t err;
10501+ aufs_bindex_t bstart;
10502+ unsigned char wbr;
10503+ struct super_block *sb;
10504+ struct file *file, *h_file;
10505+
10506+ file = kio->ki_filp;
10507+ sb = file->f_dentry->d_sb;
10508+ si_read_lock(sb, AuLock_FLUSH);
10509+ fi_read_lock(file);
10510+ bstart = au_fbstart(file);
10511+ h_file = au_hf_top(file);
10512+ fi_read_unlock(file);
10513+ wbr = !!au_br_writable(au_sbr(sb, bstart)->br_perm);
10514+ si_read_unlock(sb);
10515+
10516+ /* do not change the file in kio */
10517+ AuDebugOn(!h_file->f_op || !h_file->f_op->aio_write);
10518+ err = h_file->f_op->aio_write(kio, iov, nv, pos);
10519+ if (err > 0 && wbr)
10520+ file_update_time(h_file);
10521+
10522+ return err;
10523+}
10524+
10525+/* ---------------------------------------------------------------------- */
10526+
10527+static int aufs_release_sp(struct inode *inode, struct file *file)
10528+{
10529+ int err;
10530+ struct file *h_file;
10531+
10532+ fi_read_lock(file);
10533+ h_file = au_hf_top(file);
10534+ fi_read_unlock(file);
10535+ /* close this fifo in aufs */
10536+ err = h_file->f_op->release(inode, file); /* ignore */
10537+ aufs_release_nondir(inode, file); /* ignore */
10538+ return err;
10539+}
10540+
10541+/* ---------------------------------------------------------------------- */
10542+
10543+/* currently, support only FIFO */
4f0767ce
JR
10544+enum {
10545+ AuSp_FIFO, AuSp_FIFO_R, AuSp_FIFO_W, AuSp_FIFO_RW,
10546+ /* AuSp_SOCK, AuSp_CHR, AuSp_BLK, */
10547+ AuSp_Last
10548+};
4a4d8108
AM
10549+static int aufs_open_sp(struct inode *inode, struct file *file);
10550+static struct au_sp_fop {
10551+ int done;
10552+ struct file_operations fop; /* not 'const' */
10553+ spinlock_t spin;
10554+} au_sp_fop[AuSp_Last] = {
10555+ [AuSp_FIFO] = {
10556+ .fop = {
10557+ .owner = THIS_MODULE,
10558+ .open = aufs_open_sp
10559+ }
10560+ }
10561+};
10562+
10563+static void au_init_fop_sp(struct file *file)
10564+{
10565+ struct au_sp_fop *p;
10566+ int i;
10567+ struct file *h_file;
10568+
10569+ p = au_sp_fop;
10570+ if (unlikely(!p->done)) {
10571+ /* initialize first time only */
10572+ static DEFINE_SPINLOCK(spin);
10573+
10574+ spin_lock(&spin);
10575+ if (!p->done) {
10576+ BUILD_BUG_ON(sizeof(au_sp_fop)/sizeof(*au_sp_fop)
10577+ != AuSp_Last);
10578+ for (i = 0; i < AuSp_Last; i++)
10579+ spin_lock_init(&p[i].spin);
10580+ p->done = 1;
10581+ }
10582+ spin_unlock(&spin);
10583+ }
10584+
10585+ switch (file->f_mode & (FMODE_READ | FMODE_WRITE)) {
10586+ case FMODE_READ:
10587+ i = AuSp_FIFO_R;
10588+ break;
10589+ case FMODE_WRITE:
10590+ i = AuSp_FIFO_W;
10591+ break;
10592+ case FMODE_READ | FMODE_WRITE:
10593+ i = AuSp_FIFO_RW;
10594+ break;
10595+ default:
10596+ BUG();
10597+ }
10598+
10599+ p += i;
10600+ if (unlikely(!p->done)) {
10601+ /* initialize first time only */
10602+ h_file = au_hf_top(file);
10603+ spin_lock(&p->spin);
10604+ if (!p->done) {
10605+ p->fop = *h_file->f_op;
10606+ p->fop.owner = THIS_MODULE;
10607+ if (p->fop.aio_read)
10608+ p->fop.aio_read = aufs_aio_read_sp;
10609+ if (p->fop.aio_write)
10610+ p->fop.aio_write = aufs_aio_write_sp;
10611+ p->fop.release = aufs_release_sp;
10612+ p->done = 1;
10613+ }
10614+ spin_unlock(&p->spin);
10615+ }
10616+ file->f_op = &p->fop;
10617+}
10618+
10619+static int au_cpup_sp(struct dentry *dentry)
10620+{
10621+ int err;
10622+ aufs_bindex_t bcpup;
10623+ struct au_pin pin;
10624+ struct au_wr_dir_args wr_dir_args = {
10625+ .force_btgt = -1,
10626+ .flags = 0
10627+ };
10628+
10629+ AuDbg("%.*s\n", AuDLNPair(dentry));
10630+
10631+ di_read_unlock(dentry, AuLock_IR);
10632+ di_write_lock_child(dentry);
10633+ err = au_wr_dir(dentry, /*src_dentry*/NULL, &wr_dir_args);
10634+ if (unlikely(err < 0))
10635+ goto out;
10636+ bcpup = err;
10637+ err = 0;
10638+ if (bcpup == au_dbstart(dentry))
10639+ goto out; /* success */
10640+
10641+ err = au_pin(&pin, dentry, bcpup, au_opt_udba(dentry->d_sb),
10642+ AuPin_MNT_WRITE);
10643+ if (!err) {
10644+ err = au_sio_cpup_simple(dentry, bcpup, -1, AuCpup_DTIME);
10645+ au_unpin(&pin);
10646+ }
10647+
4f0767ce 10648+out:
4a4d8108
AM
10649+ di_downgrade_lock(dentry, AuLock_IR);
10650+ return err;
10651+}
10652+
10653+static int au_do_open_sp(struct file *file, int flags)
10654+{
10655+ int err;
10656+ struct dentry *dentry;
10657+ struct super_block *sb;
10658+ struct file *h_file;
10659+ struct inode *h_inode;
10660+
10661+ dentry = file->f_dentry;
10662+ AuDbg("%.*s\n", AuDLNPair(dentry));
10663+
10664+ /*
10665+ * try copying-up.
10666+ * operate on the ro branch is not an error.
10667+ */
10668+ au_cpup_sp(dentry); /* ignore */
10669+
10670+ /* prepare h_file */
10671+ err = au_do_open_nondir(file, vfsub_file_flags(file));
10672+ if (unlikely(err))
10673+ goto out;
10674+
10675+ sb = dentry->d_sb;
10676+ h_file = au_hf_top(file);
10677+ h_inode = h_file->f_dentry->d_inode;
10678+ di_read_unlock(dentry, AuLock_IR);
10679+ fi_write_unlock(file);
10680+ si_read_unlock(sb);
10681+ /* open this fifo in aufs */
10682+ err = h_inode->i_fop->open(file->f_dentry->d_inode, file);
10683+ si_noflush_read_lock(sb);
10684+ fi_write_lock(file);
10685+ di_read_lock_child(dentry, AuLock_IR);
10686+ if (!err)
10687+ au_init_fop_sp(file);
4a4d8108 10688+
4f0767ce 10689+out:
4a4d8108
AM
10690+ return err;
10691+}
10692+
10693+static int aufs_open_sp(struct inode *inode, struct file *file)
10694+{
10695+ int err;
10696+ struct super_block *sb;
10697+
10698+ sb = file->f_dentry->d_sb;
10699+ si_read_lock(sb, AuLock_FLUSH);
10700+ err = au_do_open(file, au_do_open_sp, /*fidir*/NULL);
10701+ si_read_unlock(sb);
10702+ return err;
10703+}
10704+
10705+/* ---------------------------------------------------------------------- */
10706+
10707+void au_init_special_fop(struct inode *inode, umode_t mode, dev_t rdev)
10708+{
10709+ init_special_inode(inode, mode, rdev);
10710+
10711+ switch (mode & S_IFMT) {
10712+ case S_IFIFO:
10713+ inode->i_fop = &au_sp_fop[AuSp_FIFO].fop;
10714+ /*FALLTHROUGH*/
10715+ case S_IFCHR:
10716+ case S_IFBLK:
10717+ case S_IFSOCK:
10718+ break;
10719+ default:
10720+ AuDebugOn(1);
10721+ }
10722+}
10723+
10724+int au_special_file(umode_t mode)
10725+{
10726+ int ret;
10727+
10728+ ret = 0;
10729+ switch (mode & S_IFMT) {
10730+ case S_IFIFO:
10731+#if 0
10732+ case S_IFCHR:
10733+ case S_IFBLK:
10734+ case S_IFSOCK:
10735+#endif
10736+ ret = 1;
10737+ }
10738+
10739+ return ret;
10740+}
7f207e10
AM
10741diff -urN /usr/share/empty/fs/aufs/fstype.h linux/fs/aufs/fstype.h
10742--- /usr/share/empty/fs/aufs/fstype.h 1970-01-01 01:00:00.000000000 +0100
2cbb1c4b 10743+++ linux/fs/aufs/fstype.h 2011-07-11 11:34:24.074331673 +0200
4a4d8108
AM
10744@@ -0,0 +1,497 @@
10745+/*
027c5e7a 10746+ * Copyright (C) 2005-2011 Junjiro R. Okajima
4a4d8108
AM
10747+ *
10748+ * This program, aufs is free software; you can redistribute it and/or modify
10749+ * it under the terms of the GNU General Public License as published by
10750+ * the Free Software Foundation; either version 2 of the License, or
10751+ * (at your option) any later version.
10752+ *
10753+ * This program is distributed in the hope that it will be useful,
10754+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
10755+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10756+ * GNU General Public License for more details.
10757+ *
10758+ * You should have received a copy of the GNU General Public License
10759+ * along with this program; if not, write to the Free Software
10760+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
10761+ */
10762+
10763+/*
10764+ * judging filesystem type
10765+ */
10766+
10767+#ifndef __AUFS_FSTYPE_H__
10768+#define __AUFS_FSTYPE_H__
10769+
10770+#ifdef __KERNEL__
10771+
10772+#include <linux/fs.h>
10773+#include <linux/magic.h>
10774+#include <linux/romfs_fs.h>
10775+#include <linux/aufs_type.h>
10776+
10777+static inline int au_test_aufs(struct super_block *sb)
10778+{
10779+ return sb->s_magic == AUFS_SUPER_MAGIC;
10780+}
10781+
10782+static inline const char *au_sbtype(struct super_block *sb)
10783+{
10784+ return sb->s_type->name;
10785+}
1308ab2a 10786+
10787+static inline int au_test_iso9660(struct super_block *sb __maybe_unused)
10788+{
10789+#if defined(CONFIG_ROMFS_FS) || defined(CONFIG_ROMFS_FS_MODULE)
10790+ return sb->s_magic == ROMFS_MAGIC;
dece6358
AM
10791+#else
10792+ return 0;
10793+#endif
10794+}
10795+
1308ab2a 10796+static inline int au_test_romfs(struct super_block *sb __maybe_unused)
dece6358 10797+{
1308ab2a 10798+#if defined(CONFIG_ISO9660_FS) || defined(CONFIG_ISO9660_FS_MODULE)
10799+ return sb->s_magic == ISOFS_SUPER_MAGIC;
dece6358
AM
10800+#else
10801+ return 0;
10802+#endif
10803+}
10804+
1308ab2a 10805+static inline int au_test_cramfs(struct super_block *sb __maybe_unused)
dece6358 10806+{
1308ab2a 10807+#if defined(CONFIG_CRAMFS) || defined(CONFIG_CRAMFS_MODULE)
10808+ return sb->s_magic == CRAMFS_MAGIC;
10809+#endif
10810+ return 0;
10811+}
10812+
10813+static inline int au_test_nfs(struct super_block *sb __maybe_unused)
10814+{
10815+#if defined(CONFIG_NFS_FS) || defined(CONFIG_NFS_FS_MODULE)
10816+ return sb->s_magic == NFS_SUPER_MAGIC;
dece6358
AM
10817+#else
10818+ return 0;
10819+#endif
10820+}
10821+
1308ab2a 10822+static inline int au_test_fuse(struct super_block *sb __maybe_unused)
dece6358 10823+{
1308ab2a 10824+#if defined(CONFIG_FUSE_FS) || defined(CONFIG_FUSE_FS_MODULE)
10825+ return sb->s_magic == FUSE_SUPER_MAGIC;
dece6358
AM
10826+#else
10827+ return 0;
10828+#endif
10829+}
10830+
1308ab2a 10831+static inline int au_test_xfs(struct super_block *sb __maybe_unused)
dece6358 10832+{
1308ab2a 10833+#if defined(CONFIG_XFS_FS) || defined(CONFIG_XFS_FS_MODULE)
10834+ return sb->s_magic == XFS_SB_MAGIC;
dece6358
AM
10835+#else
10836+ return 0;
10837+#endif
10838+}
10839+
1308ab2a 10840+static inline int au_test_tmpfs(struct super_block *sb __maybe_unused)
dece6358 10841+{
1308ab2a 10842+#ifdef CONFIG_TMPFS
10843+ return sb->s_magic == TMPFS_MAGIC;
10844+#else
10845+ return 0;
dece6358 10846+#endif
dece6358
AM
10847+}
10848+
1308ab2a 10849+static inline int au_test_ecryptfs(struct super_block *sb __maybe_unused)
1facf9fc 10850+{
1308ab2a 10851+#if defined(CONFIG_ECRYPT_FS) || defined(CONFIG_ECRYPT_FS_MODULE)
10852+ return !strcmp(au_sbtype(sb), "ecryptfs");
10853+#else
10854+ return 0;
10855+#endif
1facf9fc 10856+}
10857+
1308ab2a 10858+static inline int au_test_smbfs(struct super_block *sb __maybe_unused)
1facf9fc 10859+{
1308ab2a 10860+#if defined(CONFIG_SMB_FS) || defined(CONFIG_SMB_FS_MODULE)
10861+ return sb->s_magic == SMB_SUPER_MAGIC;
10862+#else
10863+ return 0;
1facf9fc 10864+#endif
1facf9fc 10865+}
10866+
1308ab2a 10867+static inline int au_test_ocfs2(struct super_block *sb __maybe_unused)
1facf9fc 10868+{
1308ab2a 10869+#if defined(CONFIG_OCFS2_FS) || defined(CONFIG_OCFS2_FS_MODULE)
10870+ return sb->s_magic == OCFS2_SUPER_MAGIC;
10871+#else
10872+ return 0;
10873+#endif
1facf9fc 10874+}
10875+
1308ab2a 10876+static inline int au_test_ocfs2_dlmfs(struct super_block *sb __maybe_unused)
1facf9fc 10877+{
1308ab2a 10878+#if defined(CONFIG_OCFS2_FS_O2CB) || defined(CONFIG_OCFS2_FS_O2CB_MODULE)
10879+ return sb->s_magic == DLMFS_MAGIC;
10880+#else
10881+ return 0;
10882+#endif
1facf9fc 10883+}
10884+
1308ab2a 10885+static inline int au_test_coda(struct super_block *sb __maybe_unused)
1facf9fc 10886+{
1308ab2a 10887+#if defined(CONFIG_CODA_FS) || defined(CONFIG_CODA_FS_MODULE)
10888+ return sb->s_magic == CODA_SUPER_MAGIC;
10889+#else
10890+ return 0;
10891+#endif
10892+}
10893+
10894+static inline int au_test_v9fs(struct super_block *sb __maybe_unused)
10895+{
10896+#if defined(CONFIG_9P_FS) || defined(CONFIG_9P_FS_MODULE)
10897+ return sb->s_magic == V9FS_MAGIC;
10898+#else
10899+ return 0;
10900+#endif
10901+}
10902+
10903+static inline int au_test_ext4(struct super_block *sb __maybe_unused)
10904+{
10905+#if defined(CONFIG_EXT4DEV_FS) || defined(CONFIG_EXT4DEV_FS_MODULE)
10906+ return sb->s_magic == EXT4_SUPER_MAGIC;
10907+#else
10908+ return 0;
10909+#endif
10910+}
10911+
10912+static inline int au_test_sysv(struct super_block *sb __maybe_unused)
10913+{
10914+#if defined(CONFIG_SYSV_FS) || defined(CONFIG_SYSV_FS_MODULE)
10915+ return !strcmp(au_sbtype(sb), "sysv");
10916+#else
10917+ return 0;
10918+#endif
10919+}
10920+
10921+static inline int au_test_ramfs(struct super_block *sb)
10922+{
10923+ return sb->s_magic == RAMFS_MAGIC;
10924+}
10925+
10926+static inline int au_test_ubifs(struct super_block *sb __maybe_unused)
10927+{
10928+#if defined(CONFIG_UBIFS_FS) || defined(CONFIG_UBIFS_FS_MODULE)
10929+ return sb->s_magic == UBIFS_SUPER_MAGIC;
10930+#else
10931+ return 0;
10932+#endif
10933+}
10934+
10935+static inline int au_test_procfs(struct super_block *sb __maybe_unused)
10936+{
10937+#ifdef CONFIG_PROC_FS
10938+ return sb->s_magic == PROC_SUPER_MAGIC;
10939+#else
10940+ return 0;
10941+#endif
10942+}
10943+
10944+static inline int au_test_sysfs(struct super_block *sb __maybe_unused)
10945+{
10946+#ifdef CONFIG_SYSFS
10947+ return sb->s_magic == SYSFS_MAGIC;
10948+#else
10949+ return 0;
10950+#endif
10951+}
10952+
10953+static inline int au_test_configfs(struct super_block *sb __maybe_unused)
10954+{
10955+#if defined(CONFIG_CONFIGFS_FS) || defined(CONFIG_CONFIGFS_FS_MODULE)
10956+ return sb->s_magic == CONFIGFS_MAGIC;
10957+#else
10958+ return 0;
10959+#endif
10960+}
10961+
10962+static inline int au_test_minix(struct super_block *sb __maybe_unused)
10963+{
10964+#if defined(CONFIG_MINIX_FS) || defined(CONFIG_MINIX_FS_MODULE)
10965+ return sb->s_magic == MINIX3_SUPER_MAGIC
10966+ || sb->s_magic == MINIX2_SUPER_MAGIC
10967+ || sb->s_magic == MINIX2_SUPER_MAGIC2
10968+ || sb->s_magic == MINIX_SUPER_MAGIC
10969+ || sb->s_magic == MINIX_SUPER_MAGIC2;
10970+#else
10971+ return 0;
10972+#endif
10973+}
10974+
10975+static inline int au_test_cifs(struct super_block *sb __maybe_unused)
10976+{
10977+#if defined(CONFIG_CIFS_FS) || defined(CONFIGCIFS_FS_MODULE)
10978+ return sb->s_magic == CIFS_MAGIC_NUMBER;
10979+#else
10980+ return 0;
10981+#endif
10982+}
10983+
10984+static inline int au_test_fat(struct super_block *sb __maybe_unused)
10985+{
10986+#if defined(CONFIG_FAT_FS) || defined(CONFIG_FAT_FS_MODULE)
10987+ return sb->s_magic == MSDOS_SUPER_MAGIC;
10988+#else
10989+ return 0;
10990+#endif
10991+}
10992+
10993+static inline int au_test_msdos(struct super_block *sb)
10994+{
10995+ return au_test_fat(sb);
10996+}
10997+
10998+static inline int au_test_vfat(struct super_block *sb)
10999+{
11000+ return au_test_fat(sb);
11001+}
11002+
11003+static inline int au_test_securityfs(struct super_block *sb __maybe_unused)
11004+{
11005+#ifdef CONFIG_SECURITYFS
11006+ return sb->s_magic == SECURITYFS_MAGIC;
11007+#else
11008+ return 0;
11009+#endif
11010+}
11011+
11012+static inline int au_test_squashfs(struct super_block *sb __maybe_unused)
11013+{
11014+#if defined(CONFIG_SQUASHFS) || defined(CONFIG_SQUASHFS_MODULE)
11015+ return sb->s_magic == SQUASHFS_MAGIC;
11016+#else
11017+ return 0;
11018+#endif
11019+}
11020+
11021+static inline int au_test_btrfs(struct super_block *sb __maybe_unused)
11022+{
11023+#if defined(CONFIG_BTRFS_FS) || defined(CONFIG_BTRFS_FS_MODULE)
11024+ return sb->s_magic == BTRFS_SUPER_MAGIC;
11025+#else
11026+ return 0;
11027+#endif
11028+}
11029+
11030+static inline int au_test_xenfs(struct super_block *sb __maybe_unused)
11031+{
11032+#if defined(CONFIG_XENFS) || defined(CONFIG_XENFS_MODULE)
11033+ return sb->s_magic == XENFS_SUPER_MAGIC;
11034+#else
11035+ return 0;
11036+#endif
11037+}
11038+
11039+static inline int au_test_debugfs(struct super_block *sb __maybe_unused)
11040+{
11041+#ifdef CONFIG_DEBUG_FS
11042+ return sb->s_magic == DEBUGFS_MAGIC;
11043+#else
11044+ return 0;
11045+#endif
11046+}
11047+
11048+static inline int au_test_nilfs(struct super_block *sb __maybe_unused)
11049+{
11050+#if defined(CONFIG_NILFS) || defined(CONFIG_NILFS_MODULE)
11051+ return sb->s_magic == NILFS_SUPER_MAGIC;
11052+#else
11053+ return 0;
11054+#endif
11055+}
11056+
4a4d8108
AM
11057+static inline int au_test_hfsplus(struct super_block *sb __maybe_unused)
11058+{
11059+#if defined(CONFIG_HFSPLUS_FS) || defined(CONFIG_HFSPLUS_FS_MODULE)
11060+ return sb->s_magic == HFSPLUS_SUPER_MAGIC;
11061+#else
11062+ return 0;
11063+#endif
11064+}
11065+
1308ab2a 11066+/* ---------------------------------------------------------------------- */
11067+/*
11068+ * they can't be an aufs branch.
11069+ */
11070+static inline int au_test_fs_unsuppoted(struct super_block *sb)
11071+{
11072+ return
11073+#ifndef CONFIG_AUFS_BR_RAMFS
11074+ au_test_ramfs(sb) ||
11075+#endif
11076+ au_test_procfs(sb)
11077+ || au_test_sysfs(sb)
11078+ || au_test_configfs(sb)
11079+ || au_test_debugfs(sb)
11080+ || au_test_securityfs(sb)
11081+ || au_test_xenfs(sb)
11082+ || au_test_ecryptfs(sb)
11083+ /* || !strcmp(au_sbtype(sb), "unionfs") */
11084+ || au_test_aufs(sb); /* will be supported in next version */
11085+}
11086+
11087+/*
11088+ * If the filesystem supports NFS-export, then it has to support NULL as
11089+ * a nameidata parameter for ->create(), ->lookup() and ->d_revalidate().
11090+ * We can apply this principle when we handle a lower filesystem.
11091+ */
11092+static inline int au_test_fs_null_nd(struct super_block *sb)
11093+{
11094+ return !!sb->s_export_op;
11095+}
11096+
11097+static inline int au_test_fs_remote(struct super_block *sb)
11098+{
11099+ return !au_test_tmpfs(sb)
11100+#ifdef CONFIG_AUFS_BR_RAMFS
11101+ && !au_test_ramfs(sb)
11102+#endif
11103+ && !(sb->s_type->fs_flags & FS_REQUIRES_DEV);
11104+}
11105+
11106+/* ---------------------------------------------------------------------- */
11107+
11108+/*
11109+ * Note: these functions (below) are created after reading ->getattr() in all
11110+ * filesystems under linux/fs. it means we have to do so in every update...
11111+ */
11112+
11113+/*
11114+ * some filesystems require getattr to refresh the inode attributes before
11115+ * referencing.
11116+ * in most cases, we can rely on the inode attribute in NFS (or every remote fs)
11117+ * and leave the work for d_revalidate()
11118+ */
11119+static inline int au_test_fs_refresh_iattr(struct super_block *sb)
11120+{
11121+ return au_test_nfs(sb)
11122+ || au_test_fuse(sb)
11123+ /* || au_test_smbfs(sb) */ /* untested */
11124+ /* || au_test_ocfs2(sb) */ /* untested */
11125+ /* || au_test_btrfs(sb) */ /* untested */
11126+ /* || au_test_coda(sb) */ /* untested */
11127+ /* || au_test_v9fs(sb) */ /* untested */
11128+ ;
11129+}
11130+
11131+/*
11132+ * filesystems which don't maintain i_size or i_blocks.
11133+ */
11134+static inline int au_test_fs_bad_iattr_size(struct super_block *sb)
11135+{
11136+ return au_test_xfs(sb)
4a4d8108
AM
11137+ || au_test_btrfs(sb)
11138+ || au_test_ubifs(sb)
11139+ || au_test_hfsplus(sb) /* maintained, but incorrect */
1308ab2a 11140+ /* || au_test_ext4(sb) */ /* untested */
11141+ /* || au_test_ocfs2(sb) */ /* untested */
11142+ /* || au_test_ocfs2_dlmfs(sb) */ /* untested */
11143+ /* || au_test_sysv(sb) */ /* untested */
1308ab2a 11144+ /* || au_test_minix(sb) */ /* untested */
11145+ ;
11146+}
11147+
11148+/*
11149+ * filesystems which don't store the correct value in some of their inode
11150+ * attributes.
11151+ */
11152+static inline int au_test_fs_bad_iattr(struct super_block *sb)
11153+{
11154+ return au_test_fs_bad_iattr_size(sb)
11155+ /* || au_test_cifs(sb) */ /* untested */
11156+ || au_test_fat(sb)
11157+ || au_test_msdos(sb)
11158+ || au_test_vfat(sb);
1facf9fc 11159+}
11160+
11161+/* they don't check i_nlink in link(2) */
11162+static inline int au_test_fs_no_limit_nlink(struct super_block *sb)
11163+{
11164+ return au_test_tmpfs(sb)
11165+#ifdef CONFIG_AUFS_BR_RAMFS
11166+ || au_test_ramfs(sb)
11167+#endif
4a4d8108
AM
11168+ || au_test_ubifs(sb)
11169+ || au_test_btrfs(sb)
11170+ || au_test_hfsplus(sb);
1facf9fc 11171+}
11172+
11173+/*
11174+ * filesystems which sets S_NOATIME and S_NOCMTIME.
11175+ */
11176+static inline int au_test_fs_notime(struct super_block *sb)
11177+{
11178+ return au_test_nfs(sb)
11179+ || au_test_fuse(sb)
dece6358 11180+ || au_test_ubifs(sb)
1facf9fc 11181+ /* || au_test_cifs(sb) */ /* untested */
1facf9fc 11182+ ;
11183+}
11184+
11185+/*
11186+ * filesystems which requires replacing i_mapping.
11187+ */
11188+static inline int au_test_fs_bad_mapping(struct super_block *sb)
11189+{
dece6358
AM
11190+ return au_test_fuse(sb)
11191+ || au_test_ubifs(sb);
1facf9fc 11192+}
11193+
11194+/* temporary support for i#1 in cramfs */
11195+static inline int au_test_fs_unique_ino(struct inode *inode)
11196+{
11197+ if (au_test_cramfs(inode->i_sb))
11198+ return inode->i_ino != 1;
11199+ return 1;
11200+}
11201+
11202+/* ---------------------------------------------------------------------- */
11203+
11204+/*
11205+ * the filesystem where the xino files placed must support i/o after unlink and
11206+ * maintain i_size and i_blocks.
11207+ */
11208+static inline int au_test_fs_bad_xino(struct super_block *sb)
11209+{
11210+ return au_test_fs_remote(sb)
11211+ || au_test_fs_bad_iattr_size(sb)
11212+#ifdef CONFIG_AUFS_BR_RAMFS
11213+ || !(au_test_ramfs(sb) || au_test_fs_null_nd(sb))
11214+#else
11215+ || !au_test_fs_null_nd(sb) /* to keep xino code simple */
11216+#endif
11217+ /* don't want unnecessary work for xino */
11218+ || au_test_aufs(sb)
1308ab2a 11219+ || au_test_ecryptfs(sb)
11220+ || au_test_nilfs(sb);
1facf9fc 11221+}
11222+
11223+static inline int au_test_fs_trunc_xino(struct super_block *sb)
11224+{
11225+ return au_test_tmpfs(sb)
11226+ || au_test_ramfs(sb);
11227+}
11228+
11229+/*
11230+ * test if the @sb is real-readonly.
11231+ */
11232+static inline int au_test_fs_rr(struct super_block *sb)
11233+{
11234+ return au_test_squashfs(sb)
11235+ || au_test_iso9660(sb)
11236+ || au_test_cramfs(sb)
11237+ || au_test_romfs(sb);
11238+}
11239+
11240+#endif /* __KERNEL__ */
11241+#endif /* __AUFS_FSTYPE_H__ */
7f207e10
AM
11242diff -urN /usr/share/empty/fs/aufs/hfsnotify.c linux/fs/aufs/hfsnotify.c
11243--- /usr/share/empty/fs/aufs/hfsnotify.c 1970-01-01 01:00:00.000000000 +0100
2cbb1c4b 11244+++ linux/fs/aufs/hfsnotify.c 2011-07-11 11:34:24.074331673 +0200
027c5e7a 11245@@ -0,0 +1,247 @@
1facf9fc 11246+/*
027c5e7a 11247+ * Copyright (C) 2005-2011 Junjiro R. Okajima
1facf9fc 11248+ *
11249+ * This program, aufs is free software; you can redistribute it and/or modify
11250+ * it under the terms of the GNU General Public License as published by
11251+ * the Free Software Foundation; either version 2 of the License, or
11252+ * (at your option) any later version.
dece6358
AM
11253+ *
11254+ * This program is distributed in the hope that it will be useful,
11255+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
11256+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11257+ * GNU General Public License for more details.
11258+ *
11259+ * You should have received a copy of the GNU General Public License
11260+ * along with this program; if not, write to the Free Software
11261+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 11262+ */
11263+
11264+/*
4a4d8108 11265+ * fsnotify for the lower directories
1facf9fc 11266+ */
11267+
11268+#include "aufs.h"
11269+
4a4d8108
AM
11270+/* FS_IN_IGNORED is unnecessary */
11271+static const __u32 AuHfsnMask = (FS_MOVED_TO | FS_MOVED_FROM | FS_DELETE
11272+ | FS_CREATE | FS_EVENT_ON_CHILD);
7f207e10 11273+static DECLARE_WAIT_QUEUE_HEAD(au_hfsn_wq);
1facf9fc 11274+
0c5527e5 11275+static void au_hfsn_free_mark(struct fsnotify_mark *mark)
1facf9fc 11276+{
0c5527e5
AM
11277+ struct au_hnotify *hn = container_of(mark, struct au_hnotify,
11278+ hn_mark);
4a4d8108 11279+ AuDbg("here\n");
7f207e10
AM
11280+ hn->hn_mark_dead = 1;
11281+ smp_mb();
11282+ wake_up_all(&au_hfsn_wq);
4a4d8108 11283+}
1facf9fc 11284+
027c5e7a 11285+static int au_hfsn_alloc(struct au_hinode *hinode)
4a4d8108 11286+{
027c5e7a
AM
11287+ struct au_hnotify *hn;
11288+ struct super_block *sb;
11289+ struct au_branch *br;
0c5527e5 11290+ struct fsnotify_mark *mark;
027c5e7a 11291+ aufs_bindex_t bindex;
1facf9fc 11292+
027c5e7a
AM
11293+ hn = hinode->hi_notify;
11294+ sb = hn->hn_aufs_inode->i_sb;
11295+ bindex = au_br_index(sb, hinode->hi_id);
11296+ br = au_sbr(sb, bindex);
7f207e10 11297+ hn->hn_mark_dead = 0;
0c5527e5
AM
11298+ mark = &hn->hn_mark;
11299+ fsnotify_init_mark(mark, au_hfsn_free_mark);
11300+ mark->mask = AuHfsnMask;
7f207e10
AM
11301+ /*
11302+ * by udba rename or rmdir, aufs assign a new inode to the known
11303+ * h_inode, so specify 1 to allow dups.
11304+ */
027c5e7a
AM
11305+ return fsnotify_add_mark(mark, br->br_hfsn_group, hinode->hi_inode,
11306+ /*mnt*/NULL, /*allow_dups*/1);
1facf9fc 11307+}
11308+
027c5e7a 11309+static void au_hfsn_free(struct au_hinode *hinode)
1facf9fc 11310+{
027c5e7a 11311+ struct au_hnotify *hn;
0c5527e5 11312+ struct fsnotify_mark *mark;
953406b4 11313+
027c5e7a 11314+ hn = hinode->hi_notify;
0c5527e5
AM
11315+ mark = &hn->hn_mark;
11316+ fsnotify_destroy_mark(mark);
11317+ fsnotify_put_mark(mark);
7f207e10
AM
11318+
11319+ /* TODO: bad approach */
11320+ wait_event(au_hfsn_wq, hn->hn_mark_dead);
1facf9fc 11321+}
11322+
11323+/* ---------------------------------------------------------------------- */
11324+
4a4d8108 11325+static void au_hfsn_ctl(struct au_hinode *hinode, int do_set)
1facf9fc 11326+{
0c5527e5 11327+ struct fsnotify_mark *mark;
1facf9fc 11328+
0c5527e5
AM
11329+ mark = &hinode->hi_notify->hn_mark;
11330+ spin_lock(&mark->lock);
1facf9fc 11331+ if (do_set) {
0c5527e5
AM
11332+ AuDebugOn(mark->mask & AuHfsnMask);
11333+ mark->mask |= AuHfsnMask;
1facf9fc 11334+ } else {
0c5527e5
AM
11335+ AuDebugOn(!(mark->mask & AuHfsnMask));
11336+ mark->mask &= ~AuHfsnMask;
1facf9fc 11337+ }
0c5527e5 11338+ spin_unlock(&mark->lock);
4a4d8108 11339+ /* fsnotify_recalc_inode_mask(hinode->hi_inode); */
1facf9fc 11340+}
11341+
4a4d8108 11342+/* ---------------------------------------------------------------------- */
1facf9fc 11343+
4a4d8108
AM
11344+/* #define AuDbgHnotify */
11345+#ifdef AuDbgHnotify
11346+static char *au_hfsn_name(u32 mask)
11347+{
11348+#ifdef CONFIG_AUFS_DEBUG
11349+#define test_ret(flag) if (mask & flag) \
11350+ return #flag;
11351+ test_ret(FS_ACCESS);
11352+ test_ret(FS_MODIFY);
11353+ test_ret(FS_ATTRIB);
11354+ test_ret(FS_CLOSE_WRITE);
11355+ test_ret(FS_CLOSE_NOWRITE);
11356+ test_ret(FS_OPEN);
11357+ test_ret(FS_MOVED_FROM);
11358+ test_ret(FS_MOVED_TO);
11359+ test_ret(FS_CREATE);
11360+ test_ret(FS_DELETE);
11361+ test_ret(FS_DELETE_SELF);
11362+ test_ret(FS_MOVE_SELF);
11363+ test_ret(FS_UNMOUNT);
11364+ test_ret(FS_Q_OVERFLOW);
11365+ test_ret(FS_IN_IGNORED);
11366+ test_ret(FS_IN_ISDIR);
11367+ test_ret(FS_IN_ONESHOT);
11368+ test_ret(FS_EVENT_ON_CHILD);
11369+ return "";
11370+#undef test_ret
11371+#else
11372+ return "??";
11373+#endif
1facf9fc 11374+}
4a4d8108 11375+#endif
1facf9fc 11376+
11377+/* ---------------------------------------------------------------------- */
11378+
4a4d8108 11379+static int au_hfsn_handle_event(struct fsnotify_group *group,
0c5527e5
AM
11380+ struct fsnotify_mark *inode_mark,
11381+ struct fsnotify_mark *vfsmount_mark,
4a4d8108 11382+ struct fsnotify_event *event)
1facf9fc 11383+{
11384+ int err;
4a4d8108
AM
11385+ struct au_hnotify *hnotify;
11386+ struct inode *h_dir, *h_inode;
11387+ __u32 mask;
4a4d8108
AM
11388+ struct qstr h_child_qstr = {
11389+ .name = event->file_name,
11390+ .len = event->name_len
11391+ };
11392+
11393+ AuDebugOn(event->data_type != FSNOTIFY_EVENT_INODE);
1facf9fc 11394+
11395+ err = 0;
0c5527e5 11396+ /* if FS_UNMOUNT happens, there must be another bug */
4a4d8108
AM
11397+ mask = event->mask;
11398+ AuDebugOn(mask & FS_UNMOUNT);
0c5527e5 11399+ if (mask & (FS_IN_IGNORED | FS_UNMOUNT))
1facf9fc 11400+ goto out;
1facf9fc 11401+
4a4d8108
AM
11402+ h_dir = event->to_tell;
11403+ h_inode = event->inode;
11404+#ifdef AuDbgHnotify
11405+ au_debug(1);
11406+ if (1 || h_child_qstr.len != sizeof(AUFS_XINO_FNAME) - 1
11407+ || strncmp(h_child_qstr.name, AUFS_XINO_FNAME, h_child_qstr.len)) {
11408+ AuDbg("i%lu, mask 0x%x %s, hcname %.*s, hi%lu\n",
11409+ h_dir->i_ino, mask, au_hfsn_name(mask),
11410+ AuLNPair(&h_child_qstr), h_inode ? h_inode->i_ino : 0);
11411+ /* WARN_ON(1); */
1facf9fc 11412+ }
4a4d8108 11413+ au_debug(0);
1facf9fc 11414+#endif
4a4d8108 11415+
0c5527e5
AM
11416+ AuDebugOn(!inode_mark);
11417+ hnotify = container_of(inode_mark, struct au_hnotify, hn_mark);
11418+ err = au_hnotify(h_dir, hnotify, mask, &h_child_qstr, h_inode);
1facf9fc 11419+
4a4d8108
AM
11420+out:
11421+ return err;
11422+}
1facf9fc 11423+
027c5e7a 11424+/* isn't it waste to ask every registered 'group'? */
7f207e10 11425+/* copied from linux/fs/notify/inotify/inotify_fsnotiry.c */
4a4d8108 11426+/* it should be exported to modules */
7f207e10
AM
11427+static bool au_hfsn_should_send_event(struct fsnotify_group *group,
11428+ struct inode *h_inode,
0c5527e5
AM
11429+ struct fsnotify_mark *inode_mark,
11430+ struct fsnotify_mark *vfsmount_mark,
11431+ __u32 mask, void *data, int data_type)
4a4d8108 11432+{
4a4d8108 11433+ mask = (mask & ~FS_EVENT_ON_CHILD);
7f207e10 11434+ return inode_mark->mask & mask;
4a4d8108
AM
11435+}
11436+
11437+static struct fsnotify_ops au_hfsn_ops = {
11438+ .should_send_event = au_hfsn_should_send_event,
11439+ .handle_event = au_hfsn_handle_event
11440+};
11441+
11442+/* ---------------------------------------------------------------------- */
11443+
027c5e7a
AM
11444+static void au_hfsn_fin_br(struct au_branch *br)
11445+{
11446+ if (br->br_hfsn_group)
11447+ fsnotify_put_group(br->br_hfsn_group);
11448+}
11449+
11450+static int au_hfsn_init_br(struct au_branch *br, int perm)
11451+{
11452+ br->br_hfsn_group = NULL;
11453+ br->br_hfsn_ops = au_hfsn_ops;
11454+ return 0;
11455+}
11456+
11457+static int au_hfsn_reset_br(unsigned int udba, struct au_branch *br, int perm)
4a4d8108
AM
11458+{
11459+ int err;
1facf9fc 11460+
4a4d8108 11461+ err = 0;
027c5e7a
AM
11462+ if (udba != AuOpt_UDBA_HNOTIFY
11463+ || !au_br_hnotifyable(perm)) {
11464+ au_hfsn_fin_br(br);
11465+ br->br_hfsn_group = NULL;
11466+ goto out;
11467+ }
11468+
11469+ if (br->br_hfsn_group)
11470+ goto out;
11471+
11472+ br->br_hfsn_group = fsnotify_alloc_group(&br->br_hfsn_ops);
11473+ if (IS_ERR(br->br_hfsn_group)) {
11474+ err = PTR_ERR(br->br_hfsn_group);
0c5527e5 11475+ pr_err("fsnotify_alloc_group() failed, %d\n", err);
027c5e7a 11476+ br->br_hfsn_group = NULL;
4a4d8108 11477+ }
1facf9fc 11478+
027c5e7a 11479+out:
1facf9fc 11480+ AuTraceErr(err);
11481+ return err;
11482+}
11483+
4a4d8108
AM
11484+const struct au_hnotify_op au_hnotify_op = {
11485+ .ctl = au_hfsn_ctl,
11486+ .alloc = au_hfsn_alloc,
11487+ .free = au_hfsn_free,
1facf9fc 11488+
027c5e7a
AM
11489+ .reset_br = au_hfsn_reset_br,
11490+ .fin_br = au_hfsn_fin_br,
11491+ .init_br = au_hfsn_init_br
4a4d8108 11492+};
7f207e10
AM
11493diff -urN /usr/share/empty/fs/aufs/hfsplus.c linux/fs/aufs/hfsplus.c
11494--- /usr/share/empty/fs/aufs/hfsplus.c 1970-01-01 01:00:00.000000000 +0100
2cbb1c4b 11495+++ linux/fs/aufs/hfsplus.c 2011-07-11 11:34:24.074331673 +0200
4a4d8108
AM
11496@@ -0,0 +1,58 @@
11497+/*
027c5e7a 11498+ * Copyright (C) 2010-2011 Junjiro R. Okajima
4a4d8108
AM
11499+ *
11500+ * This program, aufs is free software; you can redistribute it and/or modify
11501+ * it under the terms of the GNU General Public License as published by
11502+ * the Free Software Foundation; either version 2 of the License, or
11503+ * (at your option) any later version.
11504+ *
11505+ * This program is distributed in the hope that it will be useful,
11506+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
11507+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11508+ * GNU General Public License for more details.
11509+ *
11510+ * You should have received a copy of the GNU General Public License
11511+ * along with this program; if not, write to the Free Software
11512+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
11513+ */
1facf9fc 11514+
4a4d8108
AM
11515+/*
11516+ * special support for filesystems which aqucires an inode mutex
11517+ * at final closing a file, eg, hfsplus.
11518+ *
11519+ * This trick is very simple and stupid, just to open the file before really
11520+ * neceeary open to tell hfsplus that this is not the final closing.
11521+ * The caller should call au_h_open_pre() after acquiring the inode mutex,
11522+ * and au_h_open_post() after releasing it.
11523+ */
1facf9fc 11524+
4a4d8108
AM
11525+#include <linux/file.h>
11526+#include "aufs.h"
1facf9fc 11527+
4a4d8108
AM
11528+struct file *au_h_open_pre(struct dentry *dentry, aufs_bindex_t bindex)
11529+{
11530+ struct file *h_file;
11531+ struct dentry *h_dentry;
1facf9fc 11532+
4a4d8108
AM
11533+ h_dentry = au_h_dptr(dentry, bindex);
11534+ AuDebugOn(!h_dentry);
11535+ AuDebugOn(!h_dentry->d_inode);
11536+ IMustLock(h_dentry->d_inode);
11537+
11538+ h_file = NULL;
11539+ if (au_test_hfsplus(h_dentry->d_sb)
11540+ && S_ISREG(h_dentry->d_inode->i_mode))
11541+ h_file = au_h_open(dentry, bindex,
11542+ O_RDONLY | O_NOATIME | O_LARGEFILE,
11543+ /*file*/NULL);
11544+ return h_file;
1facf9fc 11545+}
11546+
4a4d8108
AM
11547+void au_h_open_post(struct dentry *dentry, aufs_bindex_t bindex,
11548+ struct file *h_file)
11549+{
11550+ if (h_file) {
11551+ fput(h_file);
11552+ au_sbr_put(dentry->d_sb, bindex);
11553+ }
11554+}
7f207e10
AM
11555diff -urN /usr/share/empty/fs/aufs/hnotify.c linux/fs/aufs/hnotify.c
11556--- /usr/share/empty/fs/aufs/hnotify.c 1970-01-01 01:00:00.000000000 +0100
2cbb1c4b 11557+++ linux/fs/aufs/hnotify.c 2011-07-11 11:34:24.074331673 +0200
027c5e7a 11558@@ -0,0 +1,709 @@
e49829fe 11559+/*
027c5e7a 11560+ * Copyright (C) 2005-2011 Junjiro R. Okajima
e49829fe
JR
11561+ *
11562+ * This program, aufs is free software; you can redistribute it and/or modify
11563+ * it under the terms of the GNU General Public License as published by
11564+ * the Free Software Foundation; either version 2 of the License, or
11565+ * (at your option) any later version.
11566+ *
11567+ * This program is distributed in the hope that it will be useful,
11568+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
11569+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11570+ * GNU General Public License for more details.
11571+ *
11572+ * You should have received a copy of the GNU General Public License
11573+ * along with this program; if not, write to the Free Software
11574+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
11575+ */
11576+
11577+/*
7f207e10 11578+ * abstraction to notify the direct changes on lower directories
e49829fe
JR
11579+ */
11580+
11581+#include "aufs.h"
11582+
027c5e7a 11583+int au_hn_alloc(struct au_hinode *hinode, struct inode *inode)
e49829fe
JR
11584+{
11585+ int err;
7f207e10 11586+ struct au_hnotify *hn;
1facf9fc 11587+
4a4d8108
AM
11588+ err = -ENOMEM;
11589+ hn = au_cache_alloc_hnotify();
11590+ if (hn) {
11591+ hn->hn_aufs_inode = inode;
027c5e7a
AM
11592+ hinode->hi_notify = hn;
11593+ err = au_hnotify_op.alloc(hinode);
11594+ AuTraceErr(err);
11595+ if (unlikely(err)) {
11596+ hinode->hi_notify = NULL;
4a4d8108
AM
11597+ au_cache_free_hnotify(hn);
11598+ /*
11599+ * The upper dir was removed by udba, but the same named
11600+ * dir left. In this case, aufs assignes a new inode
11601+ * number and set the monitor again.
11602+ * For the lower dir, the old monitnor is still left.
11603+ */
11604+ if (err == -EEXIST)
11605+ err = 0;
11606+ }
1308ab2a 11607+ }
1308ab2a 11608+
027c5e7a 11609+ AuTraceErr(err);
1308ab2a 11610+ return err;
dece6358 11611+}
1facf9fc 11612+
4a4d8108 11613+void au_hn_free(struct au_hinode *hinode)
dece6358 11614+{
4a4d8108 11615+ struct au_hnotify *hn;
1facf9fc 11616+
4a4d8108
AM
11617+ hn = hinode->hi_notify;
11618+ if (hn) {
027c5e7a 11619+ au_hnotify_op.free(hinode);
4a4d8108
AM
11620+ au_cache_free_hnotify(hn);
11621+ hinode->hi_notify = NULL;
11622+ }
11623+}
dece6358 11624+
4a4d8108 11625+/* ---------------------------------------------------------------------- */
dece6358 11626+
4a4d8108
AM
11627+void au_hn_ctl(struct au_hinode *hinode, int do_set)
11628+{
11629+ if (hinode->hi_notify)
11630+ au_hnotify_op.ctl(hinode, do_set);
11631+}
11632+
11633+void au_hn_reset(struct inode *inode, unsigned int flags)
11634+{
11635+ aufs_bindex_t bindex, bend;
11636+ struct inode *hi;
11637+ struct dentry *iwhdentry;
1facf9fc 11638+
1308ab2a 11639+ bend = au_ibend(inode);
4a4d8108
AM
11640+ for (bindex = au_ibstart(inode); bindex <= bend; bindex++) {
11641+ hi = au_h_iptr(inode, bindex);
11642+ if (!hi)
11643+ continue;
1308ab2a 11644+
4a4d8108
AM
11645+ /* mutex_lock_nested(&hi->i_mutex, AuLsc_I_CHILD); */
11646+ iwhdentry = au_hi_wh(inode, bindex);
11647+ if (iwhdentry)
11648+ dget(iwhdentry);
11649+ au_igrab(hi);
11650+ au_set_h_iptr(inode, bindex, NULL, 0);
11651+ au_set_h_iptr(inode, bindex, au_igrab(hi),
11652+ flags & ~AuHi_XINO);
11653+ iput(hi);
11654+ dput(iwhdentry);
11655+ /* mutex_unlock(&hi->i_mutex); */
1facf9fc 11656+ }
1facf9fc 11657+}
11658+
1308ab2a 11659+/* ---------------------------------------------------------------------- */
1facf9fc 11660+
4a4d8108 11661+static int hn_xino(struct inode *inode, struct inode *h_inode)
1facf9fc 11662+{
4a4d8108
AM
11663+ int err;
11664+ aufs_bindex_t bindex, bend, bfound, bstart;
11665+ struct inode *h_i;
1facf9fc 11666+
4a4d8108
AM
11667+ err = 0;
11668+ if (unlikely(inode->i_ino == AUFS_ROOT_INO)) {
11669+ pr_warning("branch root dir was changed\n");
11670+ goto out;
11671+ }
1facf9fc 11672+
4a4d8108
AM
11673+ bfound = -1;
11674+ bend = au_ibend(inode);
11675+ bstart = au_ibstart(inode);
11676+#if 0 /* reserved for future use */
11677+ if (bindex == bend) {
11678+ /* keep this ino in rename case */
11679+ goto out;
11680+ }
11681+#endif
11682+ for (bindex = bstart; bindex <= bend; bindex++)
11683+ if (au_h_iptr(inode, bindex) == h_inode) {
11684+ bfound = bindex;
11685+ break;
11686+ }
11687+ if (bfound < 0)
1308ab2a 11688+ goto out;
1facf9fc 11689+
4a4d8108
AM
11690+ for (bindex = bstart; bindex <= bend; bindex++) {
11691+ h_i = au_h_iptr(inode, bindex);
11692+ if (!h_i)
11693+ continue;
1facf9fc 11694+
4a4d8108
AM
11695+ err = au_xino_write(inode->i_sb, bindex, h_i->i_ino, /*ino*/0);
11696+ /* ignore this error */
11697+ /* bad action? */
1facf9fc 11698+ }
1facf9fc 11699+
4a4d8108 11700+ /* children inode number will be broken */
1facf9fc 11701+
4f0767ce 11702+out:
4a4d8108
AM
11703+ AuTraceErr(err);
11704+ return err;
1facf9fc 11705+}
11706+
4a4d8108 11707+static int hn_gen_tree(struct dentry *dentry)
1facf9fc 11708+{
4a4d8108
AM
11709+ int err, i, j, ndentry;
11710+ struct au_dcsub_pages dpages;
11711+ struct au_dpage *dpage;
11712+ struct dentry **dentries;
1facf9fc 11713+
4a4d8108
AM
11714+ err = au_dpages_init(&dpages, GFP_NOFS);
11715+ if (unlikely(err))
11716+ goto out;
11717+ err = au_dcsub_pages(&dpages, dentry, NULL, NULL);
11718+ if (unlikely(err))
11719+ goto out_dpages;
1facf9fc 11720+
4a4d8108
AM
11721+ for (i = 0; i < dpages.ndpage; i++) {
11722+ dpage = dpages.dpages + i;
11723+ dentries = dpage->dentries;
11724+ ndentry = dpage->ndentry;
11725+ for (j = 0; j < ndentry; j++) {
11726+ struct dentry *d;
11727+
11728+ d = dentries[j];
11729+ if (IS_ROOT(d))
11730+ continue;
11731+
4a4d8108
AM
11732+ au_digen_dec(d);
11733+ if (d->d_inode)
11734+ /* todo: reset children xino?
11735+ cached children only? */
11736+ au_iigen_dec(d->d_inode);
1308ab2a 11737+ }
dece6358 11738+ }
1facf9fc 11739+
4f0767ce 11740+out_dpages:
4a4d8108 11741+ au_dpages_free(&dpages);
dece6358 11742+
027c5e7a 11743+#if 0
4a4d8108
AM
11744+ /* discard children */
11745+ dentry_unhash(dentry);
11746+ dput(dentry);
027c5e7a 11747+#endif
4f0767ce 11748+out:
dece6358
AM
11749+ return err;
11750+}
11751+
1308ab2a 11752+/*
4a4d8108 11753+ * return 0 if processed.
1308ab2a 11754+ */
4a4d8108
AM
11755+static int hn_gen_by_inode(char *name, unsigned int nlen, struct inode *inode,
11756+ const unsigned int isdir)
dece6358 11757+{
1308ab2a 11758+ int err;
4a4d8108
AM
11759+ struct dentry *d;
11760+ struct qstr *dname;
1facf9fc 11761+
4a4d8108
AM
11762+ err = 1;
11763+ if (unlikely(inode->i_ino == AUFS_ROOT_INO)) {
11764+ pr_warning("branch root dir was changed\n");
11765+ err = 0;
11766+ goto out;
11767+ }
dece6358 11768+
4a4d8108
AM
11769+ if (!isdir) {
11770+ AuDebugOn(!name);
11771+ au_iigen_dec(inode);
027c5e7a 11772+ spin_lock(&inode->i_lock);
4a4d8108 11773+ list_for_each_entry(d, &inode->i_dentry, d_alias) {
027c5e7a 11774+ spin_lock(&d->d_lock);
4a4d8108
AM
11775+ dname = &d->d_name;
11776+ if (dname->len != nlen
027c5e7a
AM
11777+ && memcmp(dname->name, name, nlen)) {
11778+ spin_unlock(&d->d_lock);
4a4d8108 11779+ continue;
027c5e7a 11780+ }
4a4d8108 11781+ err = 0;
4a4d8108
AM
11782+ au_digen_dec(d);
11783+ spin_unlock(&d->d_lock);
11784+ break;
1facf9fc 11785+ }
027c5e7a 11786+ spin_unlock(&inode->i_lock);
1308ab2a 11787+ } else {
027c5e7a 11788+ au_fset_si(au_sbi(inode->i_sb), FAILED_REFRESH_DIR);
4a4d8108
AM
11789+ d = d_find_alias(inode);
11790+ if (!d) {
11791+ au_iigen_dec(inode);
11792+ goto out;
11793+ }
1facf9fc 11794+
027c5e7a 11795+ spin_lock(&d->d_lock);
4a4d8108 11796+ dname = &d->d_name;
027c5e7a
AM
11797+ if (dname->len == nlen && !memcmp(dname->name, name, nlen)) {
11798+ spin_unlock(&d->d_lock);
4a4d8108 11799+ err = hn_gen_tree(d);
027c5e7a
AM
11800+ spin_lock(&d->d_lock);
11801+ }
11802+ spin_unlock(&d->d_lock);
4a4d8108
AM
11803+ dput(d);
11804+ }
1facf9fc 11805+
4f0767ce 11806+out:
4a4d8108 11807+ AuTraceErr(err);
1308ab2a 11808+ return err;
11809+}
dece6358 11810+
4a4d8108 11811+static int hn_gen_by_name(struct dentry *dentry, const unsigned int isdir)
1facf9fc 11812+{
4a4d8108
AM
11813+ int err;
11814+ struct inode *inode;
1facf9fc 11815+
4a4d8108
AM
11816+ inode = dentry->d_inode;
11817+ if (IS_ROOT(dentry)
11818+ /* || (inode && inode->i_ino == AUFS_ROOT_INO) */
11819+ ) {
11820+ pr_warning("branch root dir was changed\n");
11821+ return 0;
11822+ }
1308ab2a 11823+
4a4d8108
AM
11824+ err = 0;
11825+ if (!isdir) {
4a4d8108
AM
11826+ au_digen_dec(dentry);
11827+ if (inode)
11828+ au_iigen_dec(inode);
11829+ } else {
027c5e7a 11830+ au_fset_si(au_sbi(dentry->d_sb), FAILED_REFRESH_DIR);
4a4d8108
AM
11831+ if (inode)
11832+ err = hn_gen_tree(dentry);
11833+ }
11834+
11835+ AuTraceErr(err);
11836+ return err;
1facf9fc 11837+}
11838+
4a4d8108 11839+/* ---------------------------------------------------------------------- */
1facf9fc 11840+
4a4d8108
AM
11841+/* hnotify job flags */
11842+#define AuHnJob_XINO0 1
11843+#define AuHnJob_GEN (1 << 1)
11844+#define AuHnJob_DIRENT (1 << 2)
11845+#define AuHnJob_ISDIR (1 << 3)
11846+#define AuHnJob_TRYXINO0 (1 << 4)
11847+#define AuHnJob_MNTPNT (1 << 5)
11848+#define au_ftest_hnjob(flags, name) ((flags) & AuHnJob_##name)
7f207e10
AM
11849+#define au_fset_hnjob(flags, name) \
11850+ do { (flags) |= AuHnJob_##name; } while (0)
11851+#define au_fclr_hnjob(flags, name) \
11852+ do { (flags) &= ~AuHnJob_##name; } while (0)
1facf9fc 11853+
4a4d8108
AM
11854+enum {
11855+ AuHn_CHILD,
11856+ AuHn_PARENT,
11857+ AuHnLast
11858+};
1facf9fc 11859+
4a4d8108
AM
11860+struct au_hnotify_args {
11861+ struct inode *h_dir, *dir, *h_child_inode;
11862+ u32 mask;
11863+ unsigned int flags[AuHnLast];
11864+ unsigned int h_child_nlen;
11865+ char h_child_name[];
11866+};
1facf9fc 11867+
4a4d8108
AM
11868+struct hn_job_args {
11869+ unsigned int flags;
11870+ struct inode *inode, *h_inode, *dir, *h_dir;
11871+ struct dentry *dentry;
11872+ char *h_name;
11873+ int h_nlen;
11874+};
1308ab2a 11875+
4a4d8108
AM
11876+static int hn_job(struct hn_job_args *a)
11877+{
11878+ const unsigned int isdir = au_ftest_hnjob(a->flags, ISDIR);
1308ab2a 11879+
4a4d8108
AM
11880+ /* reset xino */
11881+ if (au_ftest_hnjob(a->flags, XINO0) && a->inode)
11882+ hn_xino(a->inode, a->h_inode); /* ignore this error */
1308ab2a 11883+
4a4d8108
AM
11884+ if (au_ftest_hnjob(a->flags, TRYXINO0)
11885+ && a->inode
11886+ && a->h_inode) {
11887+ mutex_lock_nested(&a->h_inode->i_mutex, AuLsc_I_CHILD);
11888+ if (!a->h_inode->i_nlink)
11889+ hn_xino(a->inode, a->h_inode); /* ignore this error */
11890+ mutex_unlock(&a->h_inode->i_mutex);
1308ab2a 11891+ }
1facf9fc 11892+
4a4d8108
AM
11893+ /* make the generation obsolete */
11894+ if (au_ftest_hnjob(a->flags, GEN)) {
11895+ int err = -1;
11896+ if (a->inode)
11897+ err = hn_gen_by_inode(a->h_name, a->h_nlen, a->inode,
11898+ isdir);
11899+ if (err && a->dentry)
11900+ hn_gen_by_name(a->dentry, isdir);
11901+ /* ignore this error */
1facf9fc 11902+ }
1facf9fc 11903+
4a4d8108
AM
11904+ /* make dir entries obsolete */
11905+ if (au_ftest_hnjob(a->flags, DIRENT) && a->inode) {
11906+ struct au_vdir *vdir;
1facf9fc 11907+
4a4d8108
AM
11908+ vdir = au_ivdir(a->inode);
11909+ if (vdir)
11910+ vdir->vd_jiffy = 0;
11911+ /* IMustLock(a->inode); */
11912+ /* a->inode->i_version++; */
11913+ }
1facf9fc 11914+
4a4d8108
AM
11915+ /* can do nothing but warn */
11916+ if (au_ftest_hnjob(a->flags, MNTPNT)
11917+ && a->dentry
11918+ && d_mountpoint(a->dentry))
11919+ pr_warning("mount-point %.*s is removed or renamed\n",
11920+ AuDLNPair(a->dentry));
1facf9fc 11921+
4a4d8108 11922+ return 0;
1308ab2a 11923+}
1facf9fc 11924+
1308ab2a 11925+/* ---------------------------------------------------------------------- */
1facf9fc 11926+
4a4d8108
AM
11927+static struct dentry *lookup_wlock_by_name(char *name, unsigned int nlen,
11928+ struct inode *dir)
1308ab2a 11929+{
4a4d8108
AM
11930+ struct dentry *dentry, *d, *parent;
11931+ struct qstr *dname;
1308ab2a 11932+
4a4d8108
AM
11933+ parent = d_find_alias(dir);
11934+ if (!parent)
11935+ return NULL;
1308ab2a 11936+
4a4d8108 11937+ dentry = NULL;
027c5e7a 11938+ spin_lock(&parent->d_lock);
4a4d8108
AM
11939+ list_for_each_entry(d, &parent->d_subdirs, d_u.d_child) {
11940+ /* AuDbg("%.*s\n", AuDLNPair(d)); */
027c5e7a 11941+ spin_lock_nested(&d->d_lock, DENTRY_D_LOCK_NESTED);
4a4d8108
AM
11942+ dname = &d->d_name;
11943+ if (dname->len != nlen || memcmp(dname->name, name, nlen))
027c5e7a
AM
11944+ goto cont_unlock;
11945+ if (au_di(d))
11946+ au_digen_dec(d);
11947+ else
11948+ goto cont_unlock;
11949+ if (d->d_count) {
11950+ dentry = dget_dlock(d);
4a4d8108 11951+ spin_unlock(&d->d_lock);
027c5e7a 11952+ break;
dece6358 11953+ }
1facf9fc 11954+
027c5e7a
AM
11955+ cont_unlock:
11956+ spin_unlock(&d->d_lock);
1308ab2a 11957+ }
027c5e7a 11958+ spin_unlock(&parent->d_lock);
4a4d8108 11959+ dput(parent);
1facf9fc 11960+
4a4d8108
AM
11961+ if (dentry)
11962+ di_write_lock_child(dentry);
1308ab2a 11963+
4a4d8108
AM
11964+ return dentry;
11965+}
dece6358 11966+
4a4d8108
AM
11967+static struct inode *lookup_wlock_by_ino(struct super_block *sb,
11968+ aufs_bindex_t bindex, ino_t h_ino)
11969+{
11970+ struct inode *inode;
11971+ ino_t ino;
11972+ int err;
11973+
11974+ inode = NULL;
11975+ err = au_xino_read(sb, bindex, h_ino, &ino);
11976+ if (!err && ino)
11977+ inode = ilookup(sb, ino);
11978+ if (!inode)
11979+ goto out;
11980+
11981+ if (unlikely(inode->i_ino == AUFS_ROOT_INO)) {
11982+ pr_warning("wrong root branch\n");
11983+ iput(inode);
11984+ inode = NULL;
11985+ goto out;
1308ab2a 11986+ }
11987+
4a4d8108 11988+ ii_write_lock_child(inode);
1308ab2a 11989+
4f0767ce 11990+out:
4a4d8108 11991+ return inode;
dece6358
AM
11992+}
11993+
4a4d8108 11994+static void au_hn_bh(void *_args)
1facf9fc 11995+{
4a4d8108
AM
11996+ struct au_hnotify_args *a = _args;
11997+ struct super_block *sb;
11998+ aufs_bindex_t bindex, bend, bfound;
11999+ unsigned char xino, try_iput;
1facf9fc 12000+ int err;
1308ab2a 12001+ struct inode *inode;
4a4d8108
AM
12002+ ino_t h_ino;
12003+ struct hn_job_args args;
12004+ struct dentry *dentry;
12005+ struct au_sbinfo *sbinfo;
1facf9fc 12006+
4a4d8108
AM
12007+ AuDebugOn(!_args);
12008+ AuDebugOn(!a->h_dir);
12009+ AuDebugOn(!a->dir);
12010+ AuDebugOn(!a->mask);
12011+ AuDbg("mask 0x%x, i%lu, hi%lu, hci%lu\n",
12012+ a->mask, a->dir->i_ino, a->h_dir->i_ino,
12013+ a->h_child_inode ? a->h_child_inode->i_ino : 0);
1facf9fc 12014+
4a4d8108
AM
12015+ inode = NULL;
12016+ dentry = NULL;
12017+ /*
12018+ * do not lock a->dir->i_mutex here
12019+ * because of d_revalidate() may cause a deadlock.
12020+ */
12021+ sb = a->dir->i_sb;
12022+ AuDebugOn(!sb);
12023+ sbinfo = au_sbi(sb);
12024+ AuDebugOn(!sbinfo);
7f207e10 12025+ si_write_lock(sb, AuLock_NOPLMW);
1facf9fc 12026+
4a4d8108
AM
12027+ ii_read_lock_parent(a->dir);
12028+ bfound = -1;
12029+ bend = au_ibend(a->dir);
12030+ for (bindex = au_ibstart(a->dir); bindex <= bend; bindex++)
12031+ if (au_h_iptr(a->dir, bindex) == a->h_dir) {
12032+ bfound = bindex;
12033+ break;
12034+ }
12035+ ii_read_unlock(a->dir);
12036+ if (unlikely(bfound < 0))
12037+ goto out;
1facf9fc 12038+
4a4d8108
AM
12039+ xino = !!au_opt_test(au_mntflags(sb), XINO);
12040+ h_ino = 0;
12041+ if (a->h_child_inode)
12042+ h_ino = a->h_child_inode->i_ino;
1facf9fc 12043+
4a4d8108
AM
12044+ if (a->h_child_nlen
12045+ && (au_ftest_hnjob(a->flags[AuHn_CHILD], GEN)
12046+ || au_ftest_hnjob(a->flags[AuHn_CHILD], MNTPNT)))
12047+ dentry = lookup_wlock_by_name(a->h_child_name, a->h_child_nlen,
12048+ a->dir);
12049+ try_iput = 0;
12050+ if (dentry)
12051+ inode = dentry->d_inode;
12052+ if (xino && !inode && h_ino
12053+ && (au_ftest_hnjob(a->flags[AuHn_CHILD], XINO0)
12054+ || au_ftest_hnjob(a->flags[AuHn_CHILD], TRYXINO0)
12055+ || au_ftest_hnjob(a->flags[AuHn_CHILD], GEN))) {
12056+ inode = lookup_wlock_by_ino(sb, bfound, h_ino);
12057+ try_iput = 1;
12058+ }
1facf9fc 12059+
4a4d8108
AM
12060+ args.flags = a->flags[AuHn_CHILD];
12061+ args.dentry = dentry;
12062+ args.inode = inode;
12063+ args.h_inode = a->h_child_inode;
12064+ args.dir = a->dir;
12065+ args.h_dir = a->h_dir;
12066+ args.h_name = a->h_child_name;
12067+ args.h_nlen = a->h_child_nlen;
12068+ err = hn_job(&args);
12069+ if (dentry) {
027c5e7a 12070+ if (au_di(dentry))
4a4d8108
AM
12071+ di_write_unlock(dentry);
12072+ dput(dentry);
12073+ }
12074+ if (inode && try_iput) {
12075+ ii_write_unlock(inode);
12076+ iput(inode);
12077+ }
1facf9fc 12078+
4a4d8108
AM
12079+ ii_write_lock_parent(a->dir);
12080+ args.flags = a->flags[AuHn_PARENT];
12081+ args.dentry = NULL;
12082+ args.inode = a->dir;
12083+ args.h_inode = a->h_dir;
12084+ args.dir = NULL;
12085+ args.h_dir = NULL;
12086+ args.h_name = NULL;
12087+ args.h_nlen = 0;
12088+ err = hn_job(&args);
12089+ ii_write_unlock(a->dir);
1facf9fc 12090+
4f0767ce 12091+out:
4a4d8108
AM
12092+ iput(a->h_child_inode);
12093+ iput(a->h_dir);
12094+ iput(a->dir);
027c5e7a
AM
12095+ si_write_unlock(sb);
12096+ au_nwt_done(&sbinfo->si_nowait);
1308ab2a 12097+ kfree(a);
dece6358 12098+}
1facf9fc 12099+
4a4d8108
AM
12100+/* ---------------------------------------------------------------------- */
12101+
12102+int au_hnotify(struct inode *h_dir, struct au_hnotify *hnotify, u32 mask,
12103+ struct qstr *h_child_qstr, struct inode *h_child_inode)
dece6358 12104+{
4a4d8108
AM
12105+ int err, len;
12106+ unsigned int flags[AuHnLast];
12107+ unsigned char isdir, isroot, wh;
12108+ struct inode *dir;
12109+ struct au_hnotify_args *args;
12110+ char *p, *h_child_name;
dece6358 12111+
1308ab2a 12112+ err = 0;
4a4d8108
AM
12113+ AuDebugOn(!hnotify || !hnotify->hn_aufs_inode);
12114+ dir = igrab(hnotify->hn_aufs_inode);
12115+ if (!dir)
12116+ goto out;
1facf9fc 12117+
4a4d8108
AM
12118+ isroot = (dir->i_ino == AUFS_ROOT_INO);
12119+ wh = 0;
12120+ h_child_name = (void *)h_child_qstr->name;
12121+ len = h_child_qstr->len;
12122+ if (h_child_name) {
12123+ if (len > AUFS_WH_PFX_LEN
12124+ && !memcmp(h_child_name, AUFS_WH_PFX, AUFS_WH_PFX_LEN)) {
12125+ h_child_name += AUFS_WH_PFX_LEN;
12126+ len -= AUFS_WH_PFX_LEN;
12127+ wh = 1;
12128+ }
1facf9fc 12129+ }
dece6358 12130+
4a4d8108
AM
12131+ isdir = 0;
12132+ if (h_child_inode)
12133+ isdir = !!S_ISDIR(h_child_inode->i_mode);
12134+ flags[AuHn_PARENT] = AuHnJob_ISDIR;
12135+ flags[AuHn_CHILD] = 0;
12136+ if (isdir)
12137+ flags[AuHn_CHILD] = AuHnJob_ISDIR;
12138+ au_fset_hnjob(flags[AuHn_PARENT], DIRENT);
12139+ au_fset_hnjob(flags[AuHn_CHILD], GEN);
12140+ switch (mask & FS_EVENTS_POSS_ON_CHILD) {
12141+ case FS_MOVED_FROM:
12142+ case FS_MOVED_TO:
12143+ au_fset_hnjob(flags[AuHn_CHILD], XINO0);
12144+ au_fset_hnjob(flags[AuHn_CHILD], MNTPNT);
12145+ /*FALLTHROUGH*/
12146+ case FS_CREATE:
12147+ AuDebugOn(!h_child_name || !h_child_inode);
12148+ break;
1facf9fc 12149+
4a4d8108
AM
12150+ case FS_DELETE:
12151+ /*
12152+ * aufs never be able to get this child inode.
12153+ * revalidation should be in d_revalidate()
12154+ * by checking i_nlink, i_generation or d_unhashed().
12155+ */
12156+ AuDebugOn(!h_child_name);
12157+ au_fset_hnjob(flags[AuHn_CHILD], TRYXINO0);
12158+ au_fset_hnjob(flags[AuHn_CHILD], MNTPNT);
12159+ break;
dece6358 12160+
4a4d8108
AM
12161+ default:
12162+ AuDebugOn(1);
12163+ }
1308ab2a 12164+
4a4d8108
AM
12165+ if (wh)
12166+ h_child_inode = NULL;
1308ab2a 12167+
4a4d8108
AM
12168+ err = -ENOMEM;
12169+ /* iput() and kfree() will be called in au_hnotify() */
4a4d8108 12170+ args = kmalloc(sizeof(*args) + len + 1, GFP_NOFS);
4a4d8108
AM
12171+ if (unlikely(!args)) {
12172+ AuErr1("no memory\n");
12173+ iput(dir);
12174+ goto out;
12175+ }
12176+ args->flags[AuHn_PARENT] = flags[AuHn_PARENT];
12177+ args->flags[AuHn_CHILD] = flags[AuHn_CHILD];
12178+ args->mask = mask;
12179+ args->dir = dir;
12180+ args->h_dir = igrab(h_dir);
12181+ if (h_child_inode)
12182+ h_child_inode = igrab(h_child_inode); /* can be NULL */
12183+ args->h_child_inode = h_child_inode;
12184+ args->h_child_nlen = len;
12185+ if (len) {
12186+ p = (void *)args;
12187+ p += sizeof(*args);
12188+ memcpy(p, h_child_name, len);
12189+ p[len] = 0;
1308ab2a 12190+ }
1308ab2a 12191+
4a4d8108 12192+ err = au_wkq_nowait(au_hn_bh, args, dir->i_sb);
4a4d8108
AM
12193+ if (unlikely(err)) {
12194+ pr_err("wkq %d\n", err);
12195+ iput(args->h_child_inode);
12196+ iput(args->h_dir);
12197+ iput(args->dir);
12198+ kfree(args);
1facf9fc 12199+ }
1facf9fc 12200+
4a4d8108 12201+out:
1facf9fc 12202+ return err;
12203+}
12204+
027c5e7a
AM
12205+/* ---------------------------------------------------------------------- */
12206+
12207+int au_hnotify_reset_br(unsigned int udba, struct au_branch *br, int perm)
12208+{
12209+ int err;
12210+
12211+ AuDebugOn(!(udba & AuOptMask_UDBA));
12212+
12213+ err = 0;
12214+ if (au_hnotify_op.reset_br)
12215+ err = au_hnotify_op.reset_br(udba, br, perm);
12216+
12217+ return err;
12218+}
12219+
12220+int au_hnotify_init_br(struct au_branch *br, int perm)
12221+{
12222+ int err;
12223+
12224+ err = 0;
12225+ if (au_hnotify_op.init_br)
12226+ err = au_hnotify_op.init_br(br, perm);
12227+
12228+ return err;
12229+}
12230+
12231+void au_hnotify_fin_br(struct au_branch *br)
12232+{
12233+ if (au_hnotify_op.fin_br)
12234+ au_hnotify_op.fin_br(br);
12235+}
12236+
4a4d8108
AM
12237+static void au_hn_destroy_cache(void)
12238+{
12239+ kmem_cache_destroy(au_cachep[AuCache_HNOTIFY]);
12240+ au_cachep[AuCache_HNOTIFY] = NULL;
12241+}
1308ab2a 12242+
4a4d8108 12243+int __init au_hnotify_init(void)
1facf9fc 12244+{
1308ab2a 12245+ int err;
1308ab2a 12246+
4a4d8108
AM
12247+ err = -ENOMEM;
12248+ au_cachep[AuCache_HNOTIFY] = AuCache(au_hnotify);
12249+ if (au_cachep[AuCache_HNOTIFY]) {
027c5e7a
AM
12250+ err = 0;
12251+ if (au_hnotify_op.init)
12252+ err = au_hnotify_op.init();
4a4d8108
AM
12253+ if (unlikely(err))
12254+ au_hn_destroy_cache();
1308ab2a 12255+ }
1308ab2a 12256+ AuTraceErr(err);
4a4d8108 12257+ return err;
1308ab2a 12258+}
12259+
4a4d8108 12260+void au_hnotify_fin(void)
1308ab2a 12261+{
027c5e7a
AM
12262+ if (au_hnotify_op.fin)
12263+ au_hnotify_op.fin();
4a4d8108
AM
12264+ /* cf. au_cache_fin() */
12265+ if (au_cachep[AuCache_HNOTIFY])
12266+ au_hn_destroy_cache();
dece6358 12267+}
7f207e10
AM
12268diff -urN /usr/share/empty/fs/aufs/iinfo.c linux/fs/aufs/iinfo.c
12269--- /usr/share/empty/fs/aufs/iinfo.c 1970-01-01 01:00:00.000000000 +0100
2cbb1c4b 12270+++ linux/fs/aufs/iinfo.c 2011-07-11 11:34:24.075331673 +0200
027c5e7a 12271@@ -0,0 +1,264 @@
dece6358 12272+/*
027c5e7a 12273+ * Copyright (C) 2005-2011 Junjiro R. Okajima
dece6358
AM
12274+ *
12275+ * This program, aufs is free software; you can redistribute it and/or modify
12276+ * it under the terms of the GNU General Public License as published by
12277+ * the Free Software Foundation; either version 2 of the License, or
12278+ * (at your option) any later version.
12279+ *
12280+ * This program is distributed in the hope that it will be useful,
12281+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
12282+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12283+ * GNU General Public License for more details.
12284+ *
12285+ * You should have received a copy of the GNU General Public License
12286+ * along with this program; if not, write to the Free Software
12287+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
12288+ */
1facf9fc 12289+
dece6358 12290+/*
4a4d8108 12291+ * inode private data
dece6358 12292+ */
1facf9fc 12293+
1308ab2a 12294+#include "aufs.h"
1facf9fc 12295+
4a4d8108 12296+struct inode *au_h_iptr(struct inode *inode, aufs_bindex_t bindex)
1308ab2a 12297+{
4a4d8108 12298+ struct inode *h_inode;
1facf9fc 12299+
4a4d8108 12300+ IiMustAnyLock(inode);
1facf9fc 12301+
4a4d8108
AM
12302+ h_inode = au_ii(inode)->ii_hinode[0 + bindex].hi_inode;
12303+ AuDebugOn(h_inode && atomic_read(&h_inode->i_count) <= 0);
12304+ return h_inode;
12305+}
1facf9fc 12306+
4a4d8108
AM
12307+/* todo: hard/soft set? */
12308+void au_hiput(struct au_hinode *hinode)
12309+{
12310+ au_hn_free(hinode);
12311+ dput(hinode->hi_whdentry);
12312+ iput(hinode->hi_inode);
12313+}
1facf9fc 12314+
4a4d8108
AM
12315+unsigned int au_hi_flags(struct inode *inode, int isdir)
12316+{
12317+ unsigned int flags;
12318+ const unsigned int mnt_flags = au_mntflags(inode->i_sb);
1facf9fc 12319+
4a4d8108
AM
12320+ flags = 0;
12321+ if (au_opt_test(mnt_flags, XINO))
12322+ au_fset_hi(flags, XINO);
12323+ if (isdir && au_opt_test(mnt_flags, UDBA_HNOTIFY))
12324+ au_fset_hi(flags, HNOTIFY);
12325+ return flags;
1facf9fc 12326+}
12327+
4a4d8108
AM
12328+void au_set_h_iptr(struct inode *inode, aufs_bindex_t bindex,
12329+ struct inode *h_inode, unsigned int flags)
1308ab2a 12330+{
4a4d8108
AM
12331+ struct au_hinode *hinode;
12332+ struct inode *hi;
12333+ struct au_iinfo *iinfo = au_ii(inode);
1facf9fc 12334+
4a4d8108 12335+ IiMustWriteLock(inode);
dece6358 12336+
4a4d8108
AM
12337+ hinode = iinfo->ii_hinode + bindex;
12338+ hi = hinode->hi_inode;
12339+ AuDebugOn(h_inode && atomic_read(&h_inode->i_count) <= 0);
12340+
12341+ if (hi)
12342+ au_hiput(hinode);
12343+ hinode->hi_inode = h_inode;
12344+ if (h_inode) {
12345+ int err;
12346+ struct super_block *sb = inode->i_sb;
12347+ struct au_branch *br;
12348+
027c5e7a
AM
12349+ AuDebugOn(inode->i_mode
12350+ && (h_inode->i_mode & S_IFMT)
12351+ != (inode->i_mode & S_IFMT));
4a4d8108
AM
12352+ if (bindex == iinfo->ii_bstart)
12353+ au_cpup_igen(inode, h_inode);
12354+ br = au_sbr(sb, bindex);
12355+ hinode->hi_id = br->br_id;
12356+ if (au_ftest_hi(flags, XINO)) {
12357+ err = au_xino_write(sb, bindex, h_inode->i_ino,
12358+ inode->i_ino);
12359+ if (unlikely(err))
12360+ AuIOErr1("failed au_xino_write() %d\n", err);
12361+ }
12362+
12363+ if (au_ftest_hi(flags, HNOTIFY)
12364+ && au_br_hnotifyable(br->br_perm)) {
027c5e7a 12365+ err = au_hn_alloc(hinode, inode);
4a4d8108
AM
12366+ if (unlikely(err))
12367+ AuIOErr1("au_hn_alloc() %d\n", err);
1308ab2a 12368+ }
12369+ }
4a4d8108 12370+}
dece6358 12371+
4a4d8108
AM
12372+void au_set_hi_wh(struct inode *inode, aufs_bindex_t bindex,
12373+ struct dentry *h_wh)
12374+{
12375+ struct au_hinode *hinode;
dece6358 12376+
4a4d8108
AM
12377+ IiMustWriteLock(inode);
12378+
12379+ hinode = au_ii(inode)->ii_hinode + bindex;
12380+ AuDebugOn(hinode->hi_whdentry);
12381+ hinode->hi_whdentry = h_wh;
1facf9fc 12382+}
12383+
4a4d8108 12384+void au_update_iigen(struct inode *inode)
1308ab2a 12385+{
4a4d8108
AM
12386+ atomic_set(&au_ii(inode)->ii_generation, au_sigen(inode->i_sb));
12387+ /* smp_mb(); */ /* atomic_set */
12388+}
1facf9fc 12389+
4a4d8108
AM
12390+/* it may be called at remount time, too */
12391+void au_update_ibrange(struct inode *inode, int do_put_zero)
12392+{
12393+ struct au_iinfo *iinfo;
027c5e7a 12394+ aufs_bindex_t bindex, bend;
1facf9fc 12395+
4a4d8108 12396+ iinfo = au_ii(inode);
027c5e7a 12397+ if (!iinfo)
4a4d8108 12398+ return;
1facf9fc 12399+
4a4d8108 12400+ IiMustWriteLock(inode);
1facf9fc 12401+
027c5e7a 12402+ if (do_put_zero && iinfo->ii_bstart >= 0) {
4a4d8108
AM
12403+ for (bindex = iinfo->ii_bstart; bindex <= iinfo->ii_bend;
12404+ bindex++) {
12405+ struct inode *h_i;
1facf9fc 12406+
4a4d8108 12407+ h_i = iinfo->ii_hinode[0 + bindex].hi_inode;
027c5e7a
AM
12408+ if (h_i && !h_i->i_nlink)
12409+ au_set_h_iptr(inode, bindex, NULL, 0);
12410+ }
4a4d8108
AM
12411+ }
12412+
027c5e7a
AM
12413+ iinfo->ii_bstart = -1;
12414+ iinfo->ii_bend = -1;
12415+ bend = au_sbend(inode->i_sb);
12416+ for (bindex = 0; bindex <= bend; bindex++)
12417+ if (iinfo->ii_hinode[0 + bindex].hi_inode) {
12418+ iinfo->ii_bstart = bindex;
4a4d8108 12419+ break;
027c5e7a
AM
12420+ }
12421+ if (iinfo->ii_bstart >= 0)
12422+ for (bindex = bend; bindex >= iinfo->ii_bstart; bindex--)
12423+ if (iinfo->ii_hinode[0 + bindex].hi_inode) {
12424+ iinfo->ii_bend = bindex;
12425+ break;
12426+ }
12427+ AuDebugOn(iinfo->ii_bstart > iinfo->ii_bend);
1308ab2a 12428+}
1facf9fc 12429+
dece6358 12430+/* ---------------------------------------------------------------------- */
1facf9fc 12431+
4a4d8108 12432+void au_icntnr_init_once(void *_c)
dece6358 12433+{
4a4d8108
AM
12434+ struct au_icntnr *c = _c;
12435+ struct au_iinfo *iinfo = &c->iinfo;
e49829fe 12436+ static struct lock_class_key aufs_ii;
1facf9fc 12437+
4a4d8108 12438+ au_rw_init(&iinfo->ii_rwsem);
e49829fe 12439+ au_rw_class(&iinfo->ii_rwsem, &aufs_ii);
4a4d8108
AM
12440+ inode_init_once(&c->vfs_inode);
12441+}
1facf9fc 12442+
4a4d8108
AM
12443+int au_iinfo_init(struct inode *inode)
12444+{
12445+ struct au_iinfo *iinfo;
12446+ struct super_block *sb;
12447+ int nbr, i;
1facf9fc 12448+
4a4d8108
AM
12449+ sb = inode->i_sb;
12450+ iinfo = &(container_of(inode, struct au_icntnr, vfs_inode)->iinfo);
12451+ nbr = au_sbend(sb) + 1;
12452+ if (unlikely(nbr <= 0))
12453+ nbr = 1;
12454+ iinfo->ii_hinode = kcalloc(nbr, sizeof(*iinfo->ii_hinode), GFP_NOFS);
12455+ if (iinfo->ii_hinode) {
7f207e10 12456+ au_ninodes_inc(sb);
4a4d8108
AM
12457+ for (i = 0; i < nbr; i++)
12458+ iinfo->ii_hinode[i].hi_id = -1;
1facf9fc 12459+
4a4d8108
AM
12460+ atomic_set(&iinfo->ii_generation, au_sigen(sb));
12461+ /* smp_mb(); */ /* atomic_set */
12462+ iinfo->ii_bstart = -1;
12463+ iinfo->ii_bend = -1;
12464+ iinfo->ii_vdir = NULL;
12465+ return 0;
1308ab2a 12466+ }
4a4d8108
AM
12467+ return -ENOMEM;
12468+}
1facf9fc 12469+
4a4d8108
AM
12470+int au_ii_realloc(struct au_iinfo *iinfo, int nbr)
12471+{
12472+ int err, sz;
12473+ struct au_hinode *hip;
1facf9fc 12474+
4a4d8108
AM
12475+ AuRwMustWriteLock(&iinfo->ii_rwsem);
12476+
12477+ err = -ENOMEM;
12478+ sz = sizeof(*hip) * (iinfo->ii_bend + 1);
12479+ if (!sz)
12480+ sz = sizeof(*hip);
12481+ hip = au_kzrealloc(iinfo->ii_hinode, sz, sizeof(*hip) * nbr, GFP_NOFS);
12482+ if (hip) {
12483+ iinfo->ii_hinode = hip;
12484+ err = 0;
1308ab2a 12485+ }
4a4d8108 12486+
1308ab2a 12487+ return err;
1facf9fc 12488+}
12489+
4a4d8108 12490+void au_iinfo_fin(struct inode *inode)
1facf9fc 12491+{
4a4d8108
AM
12492+ struct au_iinfo *iinfo;
12493+ struct au_hinode *hi;
12494+ struct super_block *sb;
b752ccd1
AM
12495+ aufs_bindex_t bindex, bend;
12496+ const unsigned char unlinked = !inode->i_nlink;
1308ab2a 12497+
4a4d8108
AM
12498+ iinfo = au_ii(inode);
12499+ /* bad_inode case */
12500+ if (!iinfo)
12501+ return;
1308ab2a 12502+
b752ccd1 12503+ sb = inode->i_sb;
7f207e10 12504+ au_ninodes_dec(sb);
b752ccd1
AM
12505+ if (si_pid_test(sb))
12506+ au_xino_delete_inode(inode, unlinked);
12507+ else {
12508+ /*
12509+ * it is safe to hide the dependency between sbinfo and
12510+ * sb->s_umount.
12511+ */
12512+ lockdep_off();
12513+ si_noflush_read_lock(sb);
12514+ au_xino_delete_inode(inode, unlinked);
12515+ si_read_unlock(sb);
12516+ lockdep_on();
12517+ }
12518+
4a4d8108
AM
12519+ if (iinfo->ii_vdir)
12520+ au_vdir_free(iinfo->ii_vdir);
1308ab2a 12521+
b752ccd1
AM
12522+ bindex = iinfo->ii_bstart;
12523+ if (bindex >= 0) {
12524+ hi = iinfo->ii_hinode + bindex;
4a4d8108 12525+ bend = iinfo->ii_bend;
b752ccd1
AM
12526+ while (bindex++ <= bend) {
12527+ if (hi->hi_inode)
4a4d8108 12528+ au_hiput(hi);
4a4d8108
AM
12529+ hi++;
12530+ }
12531+ }
4a4d8108 12532+ kfree(iinfo->ii_hinode);
027c5e7a 12533+ iinfo->ii_hinode = NULL;
4a4d8108 12534+ AuRwDestroy(&iinfo->ii_rwsem);
dece6358 12535+}
7f207e10
AM
12536diff -urN /usr/share/empty/fs/aufs/inode.c linux/fs/aufs/inode.c
12537--- /usr/share/empty/fs/aufs/inode.c 1970-01-01 01:00:00.000000000 +0100
2cbb1c4b 12538+++ linux/fs/aufs/inode.c 2011-07-11 11:34:24.075331673 +0200
027c5e7a 12539@@ -0,0 +1,471 @@
4a4d8108 12540+/*
027c5e7a 12541+ * Copyright (C) 2005-2011 Junjiro R. Okajima
4a4d8108
AM
12542+ *
12543+ * This program, aufs is free software; you can redistribute it and/or modify
12544+ * it under the terms of the GNU General Public License as published by
12545+ * the Free Software Foundation; either version 2 of the License, or
12546+ * (at your option) any later version.
12547+ *
12548+ * This program is distributed in the hope that it will be useful,
12549+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
12550+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12551+ * GNU General Public License for more details.
12552+ *
12553+ * You should have received a copy of the GNU General Public License
12554+ * along with this program; if not, write to the Free Software
12555+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
12556+ */
1facf9fc 12557+
4a4d8108
AM
12558+/*
12559+ * inode functions
12560+ */
1facf9fc 12561+
4a4d8108 12562+#include "aufs.h"
1308ab2a 12563+
4a4d8108
AM
12564+struct inode *au_igrab(struct inode *inode)
12565+{
12566+ if (inode) {
12567+ AuDebugOn(!atomic_read(&inode->i_count));
027c5e7a 12568+ ihold(inode);
1facf9fc 12569+ }
4a4d8108
AM
12570+ return inode;
12571+}
1facf9fc 12572+
4a4d8108
AM
12573+static void au_refresh_hinode_attr(struct inode *inode, int do_version)
12574+{
12575+ au_cpup_attr_all(inode, /*force*/0);
12576+ au_update_iigen(inode);
12577+ if (do_version)
12578+ inode->i_version++;
dece6358 12579+}
1facf9fc 12580+
027c5e7a 12581+static int au_ii_refresh(struct inode *inode, int *update)
dece6358 12582+{
4a4d8108 12583+ int err, e;
027c5e7a 12584+ umode_t type;
4a4d8108 12585+ aufs_bindex_t bindex, new_bindex;
1308ab2a 12586+ struct super_block *sb;
4a4d8108 12587+ struct au_iinfo *iinfo;
027c5e7a 12588+ struct au_hinode *p, *q, tmp;
1facf9fc 12589+
4a4d8108 12590+ IiMustWriteLock(inode);
1facf9fc 12591+
027c5e7a 12592+ *update = 0;
4a4d8108 12593+ sb = inode->i_sb;
027c5e7a 12594+ type = inode->i_mode & S_IFMT;
4a4d8108
AM
12595+ iinfo = au_ii(inode);
12596+ err = au_ii_realloc(iinfo, au_sbend(sb) + 1);
12597+ if (unlikely(err))
1308ab2a 12598+ goto out;
1facf9fc 12599+
027c5e7a 12600+ AuDebugOn(iinfo->ii_bstart < 0);
4a4d8108 12601+ p = iinfo->ii_hinode + iinfo->ii_bstart;
4a4d8108
AM
12602+ for (bindex = iinfo->ii_bstart; bindex <= iinfo->ii_bend;
12603+ bindex++, p++) {
12604+ if (!p->hi_inode)
12605+ continue;
1facf9fc 12606+
027c5e7a 12607+ AuDebugOn(type != (p->hi_inode->i_mode & S_IFMT));
4a4d8108
AM
12608+ new_bindex = au_br_index(sb, p->hi_id);
12609+ if (new_bindex == bindex)
12610+ continue;
1facf9fc 12611+
4a4d8108 12612+ if (new_bindex < 0) {
027c5e7a 12613+ *update = 1;
4a4d8108
AM
12614+ au_hiput(p);
12615+ p->hi_inode = NULL;
12616+ continue;
1308ab2a 12617+ }
4a4d8108
AM
12618+
12619+ if (new_bindex < iinfo->ii_bstart)
12620+ iinfo->ii_bstart = new_bindex;
12621+ if (iinfo->ii_bend < new_bindex)
12622+ iinfo->ii_bend = new_bindex;
12623+ /* swap two lower inode, and loop again */
12624+ q = iinfo->ii_hinode + new_bindex;
12625+ tmp = *q;
12626+ *q = *p;
12627+ *p = tmp;
12628+ if (tmp.hi_inode) {
12629+ bindex--;
12630+ p--;
1308ab2a 12631+ }
12632+ }
4a4d8108
AM
12633+ au_update_ibrange(inode, /*do_put_zero*/0);
12634+ e = au_dy_irefresh(inode);
12635+ if (unlikely(e && !err))
12636+ err = e;
1facf9fc 12637+
4f0767ce 12638+out:
027c5e7a
AM
12639+ AuTraceErr(err);
12640+ return err;
12641+}
12642+
12643+int au_refresh_hinode_self(struct inode *inode)
12644+{
12645+ int err, update;
12646+
12647+ err = au_ii_refresh(inode, &update);
12648+ if (!err)
12649+ au_refresh_hinode_attr(inode, update && S_ISDIR(inode->i_mode));
12650+
12651+ AuTraceErr(err);
4a4d8108
AM
12652+ return err;
12653+}
1facf9fc 12654+
4a4d8108
AM
12655+int au_refresh_hinode(struct inode *inode, struct dentry *dentry)
12656+{
027c5e7a 12657+ int err, e, update;
4a4d8108 12658+ unsigned int flags;
027c5e7a 12659+ umode_t mode;
4a4d8108 12660+ aufs_bindex_t bindex, bend;
027c5e7a 12661+ unsigned char isdir;
4a4d8108
AM
12662+ struct au_hinode *p;
12663+ struct au_iinfo *iinfo;
1facf9fc 12664+
027c5e7a 12665+ err = au_ii_refresh(inode, &update);
4a4d8108
AM
12666+ if (unlikely(err))
12667+ goto out;
12668+
12669+ update = 0;
12670+ iinfo = au_ii(inode);
12671+ p = iinfo->ii_hinode + iinfo->ii_bstart;
027c5e7a
AM
12672+ mode = (inode->i_mode & S_IFMT);
12673+ isdir = S_ISDIR(mode);
4a4d8108
AM
12674+ flags = au_hi_flags(inode, isdir);
12675+ bend = au_dbend(dentry);
12676+ for (bindex = au_dbstart(dentry); bindex <= bend; bindex++) {
12677+ struct inode *h_i;
12678+ struct dentry *h_d;
12679+
12680+ h_d = au_h_dptr(dentry, bindex);
12681+ if (!h_d || !h_d->d_inode)
12682+ continue;
12683+
027c5e7a 12684+ AuDebugOn(mode != (h_d->d_inode->i_mode & S_IFMT));
4a4d8108
AM
12685+ if (iinfo->ii_bstart <= bindex && bindex <= iinfo->ii_bend) {
12686+ h_i = au_h_iptr(inode, bindex);
12687+ if (h_i) {
12688+ if (h_i == h_d->d_inode)
12689+ continue;
12690+ err = -EIO;
12691+ break;
12692+ }
12693+ }
12694+ if (bindex < iinfo->ii_bstart)
12695+ iinfo->ii_bstart = bindex;
12696+ if (iinfo->ii_bend < bindex)
12697+ iinfo->ii_bend = bindex;
12698+ au_set_h_iptr(inode, bindex, au_igrab(h_d->d_inode), flags);
12699+ update = 1;
1308ab2a 12700+ }
4a4d8108
AM
12701+ au_update_ibrange(inode, /*do_put_zero*/0);
12702+ e = au_dy_irefresh(inode);
12703+ if (unlikely(e && !err))
12704+ err = e;
027c5e7a
AM
12705+ if (!err)
12706+ au_refresh_hinode_attr(inode, update && isdir);
4a4d8108 12707+
4f0767ce 12708+out:
4a4d8108 12709+ AuTraceErr(err);
1308ab2a 12710+ return err;
dece6358
AM
12711+}
12712+
4a4d8108 12713+static int set_inode(struct inode *inode, struct dentry *dentry)
dece6358 12714+{
4a4d8108
AM
12715+ int err;
12716+ unsigned int flags;
12717+ umode_t mode;
12718+ aufs_bindex_t bindex, bstart, btail;
12719+ unsigned char isdir;
12720+ struct dentry *h_dentry;
12721+ struct inode *h_inode;
12722+ struct au_iinfo *iinfo;
dece6358 12723+
4a4d8108 12724+ IiMustWriteLock(inode);
dece6358 12725+
4a4d8108
AM
12726+ err = 0;
12727+ isdir = 0;
12728+ bstart = au_dbstart(dentry);
12729+ h_inode = au_h_dptr(dentry, bstart)->d_inode;
12730+ mode = h_inode->i_mode;
12731+ switch (mode & S_IFMT) {
12732+ case S_IFREG:
12733+ btail = au_dbtail(dentry);
12734+ inode->i_op = &aufs_iop;
12735+ inode->i_fop = &aufs_file_fop;
12736+ err = au_dy_iaop(inode, bstart, h_inode);
12737+ if (unlikely(err))
12738+ goto out;
12739+ break;
12740+ case S_IFDIR:
12741+ isdir = 1;
12742+ btail = au_dbtaildir(dentry);
12743+ inode->i_op = &aufs_dir_iop;
12744+ inode->i_fop = &aufs_dir_fop;
12745+ break;
12746+ case S_IFLNK:
12747+ btail = au_dbtail(dentry);
12748+ inode->i_op = &aufs_symlink_iop;
12749+ break;
12750+ case S_IFBLK:
12751+ case S_IFCHR:
12752+ case S_IFIFO:
12753+ case S_IFSOCK:
12754+ btail = au_dbtail(dentry);
12755+ inode->i_op = &aufs_iop;
12756+ au_init_special_fop(inode, mode, h_inode->i_rdev);
12757+ break;
12758+ default:
12759+ AuIOErr("Unknown file type 0%o\n", mode);
12760+ err = -EIO;
1308ab2a 12761+ goto out;
4a4d8108 12762+ }
dece6358 12763+
4a4d8108
AM
12764+ /* do not set hnotify for whiteouted dirs (SHWH mode) */
12765+ flags = au_hi_flags(inode, isdir);
12766+ if (au_opt_test(au_mntflags(dentry->d_sb), SHWH)
12767+ && au_ftest_hi(flags, HNOTIFY)
12768+ && dentry->d_name.len > AUFS_WH_PFX_LEN
12769+ && !memcmp(dentry->d_name.name, AUFS_WH_PFX, AUFS_WH_PFX_LEN))
12770+ au_fclr_hi(flags, HNOTIFY);
12771+ iinfo = au_ii(inode);
12772+ iinfo->ii_bstart = bstart;
12773+ iinfo->ii_bend = btail;
12774+ for (bindex = bstart; bindex <= btail; bindex++) {
12775+ h_dentry = au_h_dptr(dentry, bindex);
12776+ if (h_dentry)
12777+ au_set_h_iptr(inode, bindex,
12778+ au_igrab(h_dentry->d_inode), flags);
12779+ }
12780+ au_cpup_attr_all(inode, /*force*/1);
dece6358 12781+
4f0767ce 12782+out:
4a4d8108
AM
12783+ return err;
12784+}
dece6358 12785+
027c5e7a
AM
12786+/*
12787+ * successful returns with iinfo write_locked
12788+ * minus: errno
12789+ * zero: success, matched
12790+ * plus: no error, but unmatched
12791+ */
12792+static int reval_inode(struct inode *inode, struct dentry *dentry)
4a4d8108
AM
12793+{
12794+ int err;
12795+ aufs_bindex_t bindex, bend;
12796+ struct inode *h_inode, *h_dinode;
dece6358 12797+
4a4d8108
AM
12798+ /*
12799+ * before this function, if aufs got any iinfo lock, it must be only
12800+ * one, the parent dir.
12801+ * it can happen by UDBA and the obsoleted inode number.
12802+ */
12803+ err = -EIO;
12804+ if (unlikely(inode->i_ino == parent_ino(dentry)))
12805+ goto out;
12806+
027c5e7a 12807+ err = 1;
4a4d8108
AM
12808+ ii_write_lock_new_child(inode);
12809+ h_dinode = au_h_dptr(dentry, au_dbstart(dentry))->d_inode;
12810+ bend = au_ibend(inode);
12811+ for (bindex = au_ibstart(inode); bindex <= bend; bindex++) {
12812+ h_inode = au_h_iptr(inode, bindex);
12813+ if (h_inode && h_inode == h_dinode) {
4a4d8108 12814+ err = 0;
027c5e7a 12815+ if (au_iigen_test(inode, au_digen(dentry)))
4a4d8108
AM
12816+ err = au_refresh_hinode(inode, dentry);
12817+ break;
1308ab2a 12818+ }
1facf9fc 12819+ }
dece6358 12820+
4a4d8108
AM
12821+ if (unlikely(err))
12822+ ii_write_unlock(inode);
4f0767ce 12823+out:
1facf9fc 12824+ return err;
12825+}
1facf9fc 12826+
4a4d8108
AM
12827+int au_ino(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino,
12828+ unsigned int d_type, ino_t *ino)
1facf9fc 12829+{
4a4d8108
AM
12830+ int err;
12831+ struct mutex *mtx;
1facf9fc 12832+
b752ccd1 12833+ /* prevent hardlinked inode number from race condition */
4a4d8108 12834+ mtx = NULL;
b752ccd1 12835+ if (d_type != DT_DIR) {
4a4d8108
AM
12836+ mtx = &au_sbr(sb, bindex)->br_xino.xi_nondir_mtx;
12837+ mutex_lock(mtx);
12838+ }
12839+ err = au_xino_read(sb, bindex, h_ino, ino);
12840+ if (unlikely(err))
12841+ goto out;
1308ab2a 12842+
4a4d8108
AM
12843+ if (!*ino) {
12844+ err = -EIO;
12845+ *ino = au_xino_new_ino(sb);
12846+ if (unlikely(!*ino))
1facf9fc 12847+ goto out;
4a4d8108
AM
12848+ err = au_xino_write(sb, bindex, h_ino, *ino);
12849+ if (unlikely(err))
1308ab2a 12850+ goto out;
1308ab2a 12851+ }
1facf9fc 12852+
4f0767ce 12853+out:
b752ccd1 12854+ if (mtx)
4a4d8108 12855+ mutex_unlock(mtx);
1facf9fc 12856+ return err;
12857+}
12858+
4a4d8108
AM
12859+/* successful returns with iinfo write_locked */
12860+/* todo: return with unlocked? */
12861+struct inode *au_new_inode(struct dentry *dentry, int must_new)
1facf9fc 12862+{
b752ccd1 12863+ struct inode *inode, *h_inode;
4a4d8108
AM
12864+ struct dentry *h_dentry;
12865+ struct super_block *sb;
b752ccd1 12866+ struct mutex *mtx;
4a4d8108 12867+ ino_t h_ino, ino;
027c5e7a 12868+ int err;
4a4d8108 12869+ aufs_bindex_t bstart;
1facf9fc 12870+
4a4d8108
AM
12871+ sb = dentry->d_sb;
12872+ bstart = au_dbstart(dentry);
12873+ h_dentry = au_h_dptr(dentry, bstart);
b752ccd1
AM
12874+ h_inode = h_dentry->d_inode;
12875+ h_ino = h_inode->i_ino;
12876+
12877+ /*
12878+ * stop 'race'-ing between hardlinks under different
12879+ * parents.
12880+ */
12881+ mtx = NULL;
12882+ if (!S_ISDIR(h_inode->i_mode))
12883+ mtx = &au_sbr(sb, bstart)->br_xino.xi_nondir_mtx;
12884+
4f0767ce 12885+new_ino:
b752ccd1
AM
12886+ if (mtx)
12887+ mutex_lock(mtx);
4a4d8108
AM
12888+ err = au_xino_read(sb, bstart, h_ino, &ino);
12889+ inode = ERR_PTR(err);
12890+ if (unlikely(err))
12891+ goto out;
b752ccd1 12892+
4a4d8108
AM
12893+ if (!ino) {
12894+ ino = au_xino_new_ino(sb);
12895+ if (unlikely(!ino)) {
12896+ inode = ERR_PTR(-EIO);
dece6358
AM
12897+ goto out;
12898+ }
12899+ }
1facf9fc 12900+
4a4d8108
AM
12901+ AuDbg("i%lu\n", (unsigned long)ino);
12902+ inode = au_iget_locked(sb, ino);
12903+ err = PTR_ERR(inode);
12904+ if (IS_ERR(inode))
1facf9fc 12905+ goto out;
1facf9fc 12906+
4a4d8108
AM
12907+ AuDbg("%lx, new %d\n", inode->i_state, !!(inode->i_state & I_NEW));
12908+ if (inode->i_state & I_NEW) {
12909+ ii_write_lock_new_child(inode);
12910+ err = set_inode(inode, dentry);
12911+ if (!err) {
12912+ unlock_new_inode(inode);
12913+ goto out; /* success */
12914+ }
1308ab2a 12915+
027c5e7a
AM
12916+ /*
12917+ * iget_failed() calls iput(), but we need to call
12918+ * ii_write_unlock() after iget_failed(). so dirty hack for
12919+ * i_count.
12920+ */
12921+ atomic_inc(&inode->i_count);
4a4d8108 12922+ iget_failed(inode);
027c5e7a
AM
12923+ ii_write_unlock(inode);
12924+ au_xino_write(sb, bstart, h_ino, /*ino*/0);
12925+ /* ignore this error */
12926+ goto out_iput;
12927+ } else if (!must_new && !IS_DEADDIR(inode) && inode->i_nlink) {
b752ccd1
AM
12928+ /*
12929+ * horrible race condition between lookup, readdir and copyup
12930+ * (or something).
12931+ */
12932+ if (mtx)
12933+ mutex_unlock(mtx);
027c5e7a
AM
12934+ err = reval_inode(inode, dentry);
12935+ if (unlikely(err < 0)) {
12936+ mtx = NULL;
12937+ goto out_iput;
12938+ }
12939+
b752ccd1
AM
12940+ if (!err) {
12941+ mtx = NULL;
4a4d8108 12942+ goto out; /* success */
b752ccd1
AM
12943+ } else if (mtx)
12944+ mutex_lock(mtx);
4a4d8108
AM
12945+ }
12946+
12947+ if (unlikely(au_test_fs_unique_ino(h_dentry->d_inode)))
12948+ AuWarn1("Warning: Un-notified UDBA or repeatedly renamed dir,"
12949+ " b%d, %s, %.*s, hi%lu, i%lu.\n",
12950+ bstart, au_sbtype(h_dentry->d_sb), AuDLNPair(dentry),
12951+ (unsigned long)h_ino, (unsigned long)ino);
12952+ ino = 0;
12953+ err = au_xino_write(sb, bstart, h_ino, /*ino*/0);
12954+ if (!err) {
12955+ iput(inode);
b752ccd1
AM
12956+ if (mtx)
12957+ mutex_unlock(mtx);
4a4d8108
AM
12958+ goto new_ino;
12959+ }
1308ab2a 12960+
4f0767ce 12961+out_iput:
4a4d8108 12962+ iput(inode);
4a4d8108 12963+ inode = ERR_PTR(err);
4f0767ce 12964+out:
b752ccd1
AM
12965+ if (mtx)
12966+ mutex_unlock(mtx);
4a4d8108 12967+ return inode;
1facf9fc 12968+}
12969+
4a4d8108 12970+/* ---------------------------------------------------------------------- */
1facf9fc 12971+
4a4d8108
AM
12972+int au_test_ro(struct super_block *sb, aufs_bindex_t bindex,
12973+ struct inode *inode)
12974+{
12975+ int err;
1facf9fc 12976+
4a4d8108 12977+ err = au_br_rdonly(au_sbr(sb, bindex));
1facf9fc 12978+
4a4d8108
AM
12979+ /* pseudo-link after flushed may happen out of bounds */
12980+ if (!err
12981+ && inode
12982+ && au_ibstart(inode) <= bindex
12983+ && bindex <= au_ibend(inode)) {
12984+ /*
12985+ * permission check is unnecessary since vfsub routine
12986+ * will be called later
12987+ */
12988+ struct inode *hi = au_h_iptr(inode, bindex);
12989+ if (hi)
12990+ err = IS_IMMUTABLE(hi) ? -EROFS : 0;
1facf9fc 12991+ }
12992+
4a4d8108
AM
12993+ return err;
12994+}
dece6358 12995+
4a4d8108
AM
12996+int au_test_h_perm(struct inode *h_inode, int mask)
12997+{
12998+ if (!current_fsuid())
12999+ return 0;
13000+ return inode_permission(h_inode, mask);
13001+}
1facf9fc 13002+
4a4d8108
AM
13003+int au_test_h_perm_sio(struct inode *h_inode, int mask)
13004+{
13005+ if (au_test_nfs(h_inode->i_sb)
13006+ && (mask & MAY_WRITE)
13007+ && S_ISDIR(h_inode->i_mode))
13008+ mask |= MAY_READ; /* force permission check */
13009+ return au_test_h_perm(h_inode, mask);
1facf9fc 13010+}
7f207e10
AM
13011diff -urN /usr/share/empty/fs/aufs/inode.h linux/fs/aufs/inode.h
13012--- /usr/share/empty/fs/aufs/inode.h 1970-01-01 01:00:00.000000000 +0100
2cbb1c4b 13013+++ linux/fs/aufs/inode.h 2011-07-11 11:34:24.075331673 +0200
027c5e7a 13014@@ -0,0 +1,546 @@
4a4d8108 13015+/*
027c5e7a 13016+ * Copyright (C) 2005-2011 Junjiro R. Okajima
4a4d8108
AM
13017+ *
13018+ * This program, aufs is free software; you can redistribute it and/or modify
13019+ * it under the terms of the GNU General Public License as published by
13020+ * the Free Software Foundation; either version 2 of the License, or
13021+ * (at your option) any later version.
13022+ *
13023+ * This program is distributed in the hope that it will be useful,
13024+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
13025+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13026+ * GNU General Public License for more details.
13027+ *
13028+ * You should have received a copy of the GNU General Public License
13029+ * along with this program; if not, write to the Free Software
13030+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
13031+ */
1facf9fc 13032+
1308ab2a 13033+/*
4a4d8108 13034+ * inode operations
1308ab2a 13035+ */
dece6358 13036+
4a4d8108
AM
13037+#ifndef __AUFS_INODE_H__
13038+#define __AUFS_INODE_H__
dece6358 13039+
4a4d8108 13040+#ifdef __KERNEL__
1308ab2a 13041+
4a4d8108
AM
13042+#include <linux/fs.h>
13043+#include <linux/fsnotify.h>
13044+#include <linux/aufs_type.h>
13045+#include "rwsem.h"
1308ab2a 13046+
4a4d8108 13047+struct vfsmount;
1facf9fc 13048+
4a4d8108
AM
13049+struct au_hnotify {
13050+#ifdef CONFIG_AUFS_HNOTIFY
13051+#ifdef CONFIG_AUFS_HFSNOTIFY
7f207e10 13052+ /* never use fsnotify_add_vfsmount_mark() */
0c5527e5 13053+ struct fsnotify_mark hn_mark;
7f207e10 13054+ int hn_mark_dead;
4a4d8108 13055+#endif
7f207e10 13056+ struct inode *hn_aufs_inode; /* no get/put */
4a4d8108
AM
13057+#endif
13058+} ____cacheline_aligned_in_smp;
1facf9fc 13059+
4a4d8108
AM
13060+struct au_hinode {
13061+ struct inode *hi_inode;
13062+ aufs_bindex_t hi_id;
13063+#ifdef CONFIG_AUFS_HNOTIFY
13064+ struct au_hnotify *hi_notify;
13065+#endif
dece6358 13066+
4a4d8108
AM
13067+ /* reference to the copied-up whiteout with get/put */
13068+ struct dentry *hi_whdentry;
13069+};
dece6358 13070+
4a4d8108
AM
13071+struct au_vdir;
13072+struct au_iinfo {
13073+ atomic_t ii_generation;
13074+ struct super_block *ii_hsb1; /* no get/put */
1facf9fc 13075+
4a4d8108
AM
13076+ struct au_rwsem ii_rwsem;
13077+ aufs_bindex_t ii_bstart, ii_bend;
13078+ __u32 ii_higen;
13079+ struct au_hinode *ii_hinode;
13080+ struct au_vdir *ii_vdir;
13081+};
1facf9fc 13082+
4a4d8108
AM
13083+struct au_icntnr {
13084+ struct au_iinfo iinfo;
13085+ struct inode vfs_inode;
13086+} ____cacheline_aligned_in_smp;
1308ab2a 13087+
4a4d8108
AM
13088+/* au_pin flags */
13089+#define AuPin_DI_LOCKED 1
13090+#define AuPin_MNT_WRITE (1 << 1)
13091+#define au_ftest_pin(flags, name) ((flags) & AuPin_##name)
7f207e10
AM
13092+#define au_fset_pin(flags, name) \
13093+ do { (flags) |= AuPin_##name; } while (0)
13094+#define au_fclr_pin(flags, name) \
13095+ do { (flags) &= ~AuPin_##name; } while (0)
4a4d8108
AM
13096+
13097+struct au_pin {
13098+ /* input */
13099+ struct dentry *dentry;
13100+ unsigned int udba;
13101+ unsigned char lsc_di, lsc_hi, flags;
13102+ aufs_bindex_t bindex;
13103+
13104+ /* output */
13105+ struct dentry *parent;
13106+ struct au_hinode *hdir;
13107+ struct vfsmount *h_mnt;
13108+};
1facf9fc 13109+
1308ab2a 13110+/* ---------------------------------------------------------------------- */
13111+
4a4d8108 13112+static inline struct au_iinfo *au_ii(struct inode *inode)
1facf9fc 13113+{
4a4d8108 13114+ struct au_iinfo *iinfo;
1facf9fc 13115+
4a4d8108
AM
13116+ iinfo = &(container_of(inode, struct au_icntnr, vfs_inode)->iinfo);
13117+ if (iinfo->ii_hinode)
13118+ return iinfo;
13119+ return NULL; /* debugging bad_inode case */
13120+}
1facf9fc 13121+
4a4d8108 13122+/* ---------------------------------------------------------------------- */
1facf9fc 13123+
4a4d8108
AM
13124+/* inode.c */
13125+struct inode *au_igrab(struct inode *inode);
027c5e7a 13126+int au_refresh_hinode_self(struct inode *inode);
4a4d8108
AM
13127+int au_refresh_hinode(struct inode *inode, struct dentry *dentry);
13128+int au_ino(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino,
13129+ unsigned int d_type, ino_t *ino);
13130+struct inode *au_new_inode(struct dentry *dentry, int must_new);
13131+int au_test_ro(struct super_block *sb, aufs_bindex_t bindex,
13132+ struct inode *inode);
13133+int au_test_h_perm(struct inode *h_inode, int mask);
13134+int au_test_h_perm_sio(struct inode *h_inode, int mask);
1facf9fc 13135+
4a4d8108
AM
13136+static inline int au_wh_ino(struct super_block *sb, aufs_bindex_t bindex,
13137+ ino_t h_ino, unsigned int d_type, ino_t *ino)
13138+{
13139+#ifdef CONFIG_AUFS_SHWH
13140+ return au_ino(sb, bindex, h_ino, d_type, ino);
13141+#else
13142+ return 0;
13143+#endif
13144+}
1facf9fc 13145+
4a4d8108
AM
13146+/* i_op.c */
13147+extern struct inode_operations aufs_iop, aufs_symlink_iop, aufs_dir_iop;
1308ab2a 13148+
4a4d8108
AM
13149+/* au_wr_dir flags */
13150+#define AuWrDir_ADD_ENTRY 1
13151+#define AuWrDir_ISDIR (1 << 1)
13152+#define au_ftest_wrdir(flags, name) ((flags) & AuWrDir_##name)
7f207e10
AM
13153+#define au_fset_wrdir(flags, name) \
13154+ do { (flags) |= AuWrDir_##name; } while (0)
13155+#define au_fclr_wrdir(flags, name) \
13156+ do { (flags) &= ~AuWrDir_##name; } while (0)
1facf9fc 13157+
4a4d8108
AM
13158+struct au_wr_dir_args {
13159+ aufs_bindex_t force_btgt;
13160+ unsigned char flags;
13161+};
13162+int au_wr_dir(struct dentry *dentry, struct dentry *src_dentry,
13163+ struct au_wr_dir_args *args);
dece6358 13164+
4a4d8108
AM
13165+struct dentry *au_pinned_h_parent(struct au_pin *pin);
13166+void au_pin_init(struct au_pin *pin, struct dentry *dentry,
13167+ aufs_bindex_t bindex, int lsc_di, int lsc_hi,
13168+ unsigned int udba, unsigned char flags);
13169+int au_pin(struct au_pin *pin, struct dentry *dentry, aufs_bindex_t bindex,
13170+ unsigned int udba, unsigned char flags) __must_check;
13171+int au_do_pin(struct au_pin *pin) __must_check;
13172+void au_unpin(struct au_pin *pin);
1facf9fc 13173+
4a4d8108
AM
13174+/* i_op_add.c */
13175+int au_may_add(struct dentry *dentry, aufs_bindex_t bindex,
13176+ struct dentry *h_parent, int isdir);
13177+int aufs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev);
13178+int aufs_symlink(struct inode *dir, struct dentry *dentry, const char *symname);
13179+int aufs_create(struct inode *dir, struct dentry *dentry, int mode,
13180+ struct nameidata *nd);
13181+int aufs_link(struct dentry *src_dentry, struct inode *dir,
13182+ struct dentry *dentry);
13183+int aufs_mkdir(struct inode *dir, struct dentry *dentry, int mode);
1facf9fc 13184+
4a4d8108
AM
13185+/* i_op_del.c */
13186+int au_wr_dir_need_wh(struct dentry *dentry, int isdir, aufs_bindex_t *bcpup);
13187+int au_may_del(struct dentry *dentry, aufs_bindex_t bindex,
13188+ struct dentry *h_parent, int isdir);
13189+int aufs_unlink(struct inode *dir, struct dentry *dentry);
13190+int aufs_rmdir(struct inode *dir, struct dentry *dentry);
1308ab2a 13191+
4a4d8108
AM
13192+/* i_op_ren.c */
13193+int au_wbr(struct dentry *dentry, aufs_bindex_t btgt);
13194+int aufs_rename(struct inode *src_dir, struct dentry *src_dentry,
13195+ struct inode *dir, struct dentry *dentry);
1facf9fc 13196+
4a4d8108
AM
13197+/* iinfo.c */
13198+struct inode *au_h_iptr(struct inode *inode, aufs_bindex_t bindex);
13199+void au_hiput(struct au_hinode *hinode);
13200+void au_set_hi_wh(struct inode *inode, aufs_bindex_t bindex,
13201+ struct dentry *h_wh);
13202+unsigned int au_hi_flags(struct inode *inode, int isdir);
1308ab2a 13203+
4a4d8108
AM
13204+/* hinode flags */
13205+#define AuHi_XINO 1
13206+#define AuHi_HNOTIFY (1 << 1)
13207+#define au_ftest_hi(flags, name) ((flags) & AuHi_##name)
7f207e10
AM
13208+#define au_fset_hi(flags, name) \
13209+ do { (flags) |= AuHi_##name; } while (0)
13210+#define au_fclr_hi(flags, name) \
13211+ do { (flags) &= ~AuHi_##name; } while (0)
1facf9fc 13212+
4a4d8108
AM
13213+#ifndef CONFIG_AUFS_HNOTIFY
13214+#undef AuHi_HNOTIFY
13215+#define AuHi_HNOTIFY 0
13216+#endif
1facf9fc 13217+
4a4d8108
AM
13218+void au_set_h_iptr(struct inode *inode, aufs_bindex_t bindex,
13219+ struct inode *h_inode, unsigned int flags);
1facf9fc 13220+
4a4d8108
AM
13221+void au_update_iigen(struct inode *inode);
13222+void au_update_ibrange(struct inode *inode, int do_put_zero);
1facf9fc 13223+
4a4d8108
AM
13224+void au_icntnr_init_once(void *_c);
13225+int au_iinfo_init(struct inode *inode);
13226+void au_iinfo_fin(struct inode *inode);
13227+int au_ii_realloc(struct au_iinfo *iinfo, int nbr);
1308ab2a 13228+
e49829fe 13229+#ifdef CONFIG_PROC_FS
4a4d8108 13230+/* plink.c */
e49829fe
JR
13231+int au_plink_maint(struct super_block *sb, int flags);
13232+void au_plink_maint_leave(struct au_sbinfo *sbinfo);
13233+int au_plink_maint_enter(struct super_block *sb);
4a4d8108
AM
13234+#ifdef CONFIG_AUFS_DEBUG
13235+void au_plink_list(struct super_block *sb);
13236+#else
13237+AuStubVoid(au_plink_list, struct super_block *sb)
13238+#endif
13239+int au_plink_test(struct inode *inode);
13240+struct dentry *au_plink_lkup(struct inode *inode, aufs_bindex_t bindex);
13241+void au_plink_append(struct inode *inode, aufs_bindex_t bindex,
13242+ struct dentry *h_dentry);
e49829fe
JR
13243+void au_plink_put(struct super_block *sb, int verbose);
13244+void au_plink_clean(struct super_block *sb, int verbose);
4a4d8108 13245+void au_plink_half_refresh(struct super_block *sb, aufs_bindex_t br_id);
e49829fe
JR
13246+#else
13247+AuStubInt0(au_plink_maint, struct super_block *sb, int flags);
13248+AuStubVoid(au_plink_maint_leave, struct au_sbinfo *sbinfo);
13249+AuStubInt0(au_plink_maint_enter, struct super_block *sb);
13250+AuStubVoid(au_plink_list, struct super_block *sb);
13251+AuStubInt0(au_plink_test, struct inode *inode);
13252+AuStub(struct dentry *, au_plink_lkup, return NULL,
13253+ struct inode *inode, aufs_bindex_t bindex);
13254+AuStubVoid(au_plink_append, struct inode *inode, aufs_bindex_t bindex,
13255+ struct dentry *h_dentry);
13256+AuStubVoid(au_plink_put, struct super_block *sb, int verbose);
13257+AuStubVoid(au_plink_clean, struct super_block *sb, int verbose);
13258+AuStubVoid(au_plink_half_refresh, struct super_block *sb, aufs_bindex_t br_id);
13259+#endif /* CONFIG_PROC_FS */
1facf9fc 13260+
4a4d8108 13261+/* ---------------------------------------------------------------------- */
1308ab2a 13262+
4a4d8108
AM
13263+/* lock subclass for iinfo */
13264+enum {
13265+ AuLsc_II_CHILD, /* child first */
13266+ AuLsc_II_CHILD2, /* rename(2), link(2), and cpup at hnotify */
13267+ AuLsc_II_CHILD3, /* copyup dirs */
13268+ AuLsc_II_PARENT, /* see AuLsc_I_PARENT in vfsub.h */
13269+ AuLsc_II_PARENT2,
13270+ AuLsc_II_PARENT3, /* copyup dirs */
13271+ AuLsc_II_NEW_CHILD
13272+};
1308ab2a 13273+
1facf9fc 13274+/*
4a4d8108
AM
13275+ * ii_read_lock_child, ii_write_lock_child,
13276+ * ii_read_lock_child2, ii_write_lock_child2,
13277+ * ii_read_lock_child3, ii_write_lock_child3,
13278+ * ii_read_lock_parent, ii_write_lock_parent,
13279+ * ii_read_lock_parent2, ii_write_lock_parent2,
13280+ * ii_read_lock_parent3, ii_write_lock_parent3,
13281+ * ii_read_lock_new_child, ii_write_lock_new_child,
1facf9fc 13282+ */
4a4d8108
AM
13283+#define AuReadLockFunc(name, lsc) \
13284+static inline void ii_read_lock_##name(struct inode *i) \
13285+{ \
13286+ au_rw_read_lock_nested(&au_ii(i)->ii_rwsem, AuLsc_II_##lsc); \
13287+}
13288+
13289+#define AuWriteLockFunc(name, lsc) \
13290+static inline void ii_write_lock_##name(struct inode *i) \
13291+{ \
13292+ au_rw_write_lock_nested(&au_ii(i)->ii_rwsem, AuLsc_II_##lsc); \
13293+}
13294+
13295+#define AuRWLockFuncs(name, lsc) \
13296+ AuReadLockFunc(name, lsc) \
13297+ AuWriteLockFunc(name, lsc)
13298+
13299+AuRWLockFuncs(child, CHILD);
13300+AuRWLockFuncs(child2, CHILD2);
13301+AuRWLockFuncs(child3, CHILD3);
13302+AuRWLockFuncs(parent, PARENT);
13303+AuRWLockFuncs(parent2, PARENT2);
13304+AuRWLockFuncs(parent3, PARENT3);
13305+AuRWLockFuncs(new_child, NEW_CHILD);
13306+
13307+#undef AuReadLockFunc
13308+#undef AuWriteLockFunc
13309+#undef AuRWLockFuncs
1facf9fc 13310+
13311+/*
4a4d8108 13312+ * ii_read_unlock, ii_write_unlock, ii_downgrade_lock
1facf9fc 13313+ */
4a4d8108 13314+AuSimpleUnlockRwsemFuncs(ii, struct inode *i, &au_ii(i)->ii_rwsem);
1facf9fc 13315+
4a4d8108
AM
13316+#define IiMustNoWaiters(i) AuRwMustNoWaiters(&au_ii(i)->ii_rwsem)
13317+#define IiMustAnyLock(i) AuRwMustAnyLock(&au_ii(i)->ii_rwsem)
13318+#define IiMustWriteLock(i) AuRwMustWriteLock(&au_ii(i)->ii_rwsem)
1facf9fc 13319+
4a4d8108 13320+/* ---------------------------------------------------------------------- */
1308ab2a 13321+
027c5e7a
AM
13322+static inline void au_icntnr_init(struct au_icntnr *c)
13323+{
13324+#ifdef CONFIG_AUFS_DEBUG
13325+ c->vfs_inode.i_mode = 0;
13326+#endif
13327+}
13328+
4a4d8108
AM
13329+static inline unsigned int au_iigen(struct inode *inode)
13330+{
13331+ return atomic_read(&au_ii(inode)->ii_generation);
13332+}
1308ab2a 13333+
4a4d8108
AM
13334+/* tiny test for inode number */
13335+/* tmpfs generation is too rough */
13336+static inline int au_test_higen(struct inode *inode, struct inode *h_inode)
13337+{
13338+ struct au_iinfo *iinfo;
1308ab2a 13339+
4a4d8108
AM
13340+ iinfo = au_ii(inode);
13341+ AuRwMustAnyLock(&iinfo->ii_rwsem);
13342+ return !(iinfo->ii_hsb1 == h_inode->i_sb
13343+ && iinfo->ii_higen == h_inode->i_generation);
13344+}
1308ab2a 13345+
4a4d8108
AM
13346+static inline void au_iigen_dec(struct inode *inode)
13347+{
e49829fe 13348+ atomic_dec(&au_ii(inode)->ii_generation);
027c5e7a
AM
13349+}
13350+
13351+static inline int au_iigen_test(struct inode *inode, unsigned int sigen)
13352+{
13353+ int err;
13354+
13355+ err = 0;
13356+ if (unlikely(inode && au_iigen(inode) != sigen))
13357+ err = -EIO;
13358+
13359+ return err;
4a4d8108 13360+}
1308ab2a 13361+
4a4d8108 13362+/* ---------------------------------------------------------------------- */
1308ab2a 13363+
4a4d8108
AM
13364+static inline aufs_bindex_t au_ii_br_id(struct inode *inode,
13365+ aufs_bindex_t bindex)
13366+{
13367+ IiMustAnyLock(inode);
13368+ return au_ii(inode)->ii_hinode[0 + bindex].hi_id;
13369+}
1308ab2a 13370+
4a4d8108
AM
13371+static inline aufs_bindex_t au_ibstart(struct inode *inode)
13372+{
13373+ IiMustAnyLock(inode);
13374+ return au_ii(inode)->ii_bstart;
13375+}
1308ab2a 13376+
4a4d8108
AM
13377+static inline aufs_bindex_t au_ibend(struct inode *inode)
13378+{
13379+ IiMustAnyLock(inode);
13380+ return au_ii(inode)->ii_bend;
13381+}
1308ab2a 13382+
4a4d8108
AM
13383+static inline struct au_vdir *au_ivdir(struct inode *inode)
13384+{
13385+ IiMustAnyLock(inode);
13386+ return au_ii(inode)->ii_vdir;
13387+}
1308ab2a 13388+
4a4d8108
AM
13389+static inline struct dentry *au_hi_wh(struct inode *inode, aufs_bindex_t bindex)
13390+{
13391+ IiMustAnyLock(inode);
13392+ return au_ii(inode)->ii_hinode[0 + bindex].hi_whdentry;
13393+}
1308ab2a 13394+
4a4d8108 13395+static inline void au_set_ibstart(struct inode *inode, aufs_bindex_t bindex)
1308ab2a 13396+{
4a4d8108
AM
13397+ IiMustWriteLock(inode);
13398+ au_ii(inode)->ii_bstart = bindex;
13399+}
1308ab2a 13400+
4a4d8108
AM
13401+static inline void au_set_ibend(struct inode *inode, aufs_bindex_t bindex)
13402+{
13403+ IiMustWriteLock(inode);
13404+ au_ii(inode)->ii_bend = bindex;
1308ab2a 13405+}
13406+
4a4d8108
AM
13407+static inline void au_set_ivdir(struct inode *inode, struct au_vdir *vdir)
13408+{
13409+ IiMustWriteLock(inode);
13410+ au_ii(inode)->ii_vdir = vdir;
13411+}
1facf9fc 13412+
4a4d8108 13413+static inline struct au_hinode *au_hi(struct inode *inode, aufs_bindex_t bindex)
1308ab2a 13414+{
4a4d8108
AM
13415+ IiMustAnyLock(inode);
13416+ return au_ii(inode)->ii_hinode + bindex;
13417+}
dece6358 13418+
4a4d8108 13419+/* ---------------------------------------------------------------------- */
1facf9fc 13420+
4a4d8108
AM
13421+static inline struct dentry *au_pinned_parent(struct au_pin *pin)
13422+{
13423+ if (pin)
13424+ return pin->parent;
13425+ return NULL;
1facf9fc 13426+}
13427+
4a4d8108 13428+static inline struct inode *au_pinned_h_dir(struct au_pin *pin)
1facf9fc 13429+{
4a4d8108
AM
13430+ if (pin && pin->hdir)
13431+ return pin->hdir->hi_inode;
13432+ return NULL;
1308ab2a 13433+}
1facf9fc 13434+
4a4d8108
AM
13435+static inline struct au_hinode *au_pinned_hdir(struct au_pin *pin)
13436+{
13437+ if (pin)
13438+ return pin->hdir;
13439+ return NULL;
13440+}
1facf9fc 13441+
4a4d8108 13442+static inline void au_pin_set_dentry(struct au_pin *pin, struct dentry *dentry)
1308ab2a 13443+{
4a4d8108
AM
13444+ if (pin)
13445+ pin->dentry = dentry;
13446+}
1308ab2a 13447+
4a4d8108
AM
13448+static inline void au_pin_set_parent_lflag(struct au_pin *pin,
13449+ unsigned char lflag)
13450+{
13451+ if (pin) {
7f207e10 13452+ if (lflag)
4a4d8108 13453+ au_fset_pin(pin->flags, DI_LOCKED);
7f207e10 13454+ else
4a4d8108 13455+ au_fclr_pin(pin->flags, DI_LOCKED);
1308ab2a 13456+ }
4a4d8108
AM
13457+}
13458+
13459+static inline void au_pin_set_parent(struct au_pin *pin, struct dentry *parent)
13460+{
13461+ if (pin) {
13462+ dput(pin->parent);
13463+ pin->parent = dget(parent);
1facf9fc 13464+ }
4a4d8108 13465+}
1facf9fc 13466+
4a4d8108
AM
13467+/* ---------------------------------------------------------------------- */
13468+
027c5e7a 13469+struct au_branch;
4a4d8108
AM
13470+#ifdef CONFIG_AUFS_HNOTIFY
13471+struct au_hnotify_op {
13472+ void (*ctl)(struct au_hinode *hinode, int do_set);
027c5e7a
AM
13473+ int (*alloc)(struct au_hinode *hinode);
13474+ void (*free)(struct au_hinode *hinode);
4a4d8108
AM
13475+
13476+ void (*fin)(void);
13477+ int (*init)(void);
027c5e7a
AM
13478+
13479+ int (*reset_br)(unsigned int udba, struct au_branch *br, int perm);
13480+ void (*fin_br)(struct au_branch *br);
13481+ int (*init_br)(struct au_branch *br, int perm);
4a4d8108
AM
13482+};
13483+
13484+/* hnotify.c */
027c5e7a 13485+int au_hn_alloc(struct au_hinode *hinode, struct inode *inode);
4a4d8108
AM
13486+void au_hn_free(struct au_hinode *hinode);
13487+void au_hn_ctl(struct au_hinode *hinode, int do_set);
13488+void au_hn_reset(struct inode *inode, unsigned int flags);
13489+int au_hnotify(struct inode *h_dir, struct au_hnotify *hnotify, u32 mask,
13490+ struct qstr *h_child_qstr, struct inode *h_child_inode);
027c5e7a
AM
13491+int au_hnotify_reset_br(unsigned int udba, struct au_branch *br, int perm);
13492+int au_hnotify_init_br(struct au_branch *br, int perm);
13493+void au_hnotify_fin_br(struct au_branch *br);
4a4d8108
AM
13494+int __init au_hnotify_init(void);
13495+void au_hnotify_fin(void);
13496+
7f207e10 13497+/* hfsnotify.c */
4a4d8108
AM
13498+extern const struct au_hnotify_op au_hnotify_op;
13499+
13500+static inline
13501+void au_hn_init(struct au_hinode *hinode)
13502+{
13503+ hinode->hi_notify = NULL;
1308ab2a 13504+}
13505+
4a4d8108
AM
13506+#else
13507+static inline
13508+int au_hn_alloc(struct au_hinode *hinode __maybe_unused,
027c5e7a 13509+ struct inode *inode __maybe_unused)
1308ab2a 13510+{
4a4d8108
AM
13511+ return -EOPNOTSUPP;
13512+}
1308ab2a 13513+
4a4d8108
AM
13514+AuStubVoid(au_hn_free, struct au_hinode *hinode __maybe_unused)
13515+AuStubVoid(au_hn_ctl, struct au_hinode *hinode __maybe_unused,
13516+ int do_set __maybe_unused)
13517+AuStubVoid(au_hn_reset, struct inode *inode __maybe_unused,
13518+ unsigned int flags __maybe_unused)
027c5e7a
AM
13519+AuStubInt0(au_hnotify_reset_br, unsigned int udba __maybe_unused,
13520+ struct au_branch *br __maybe_unused,
13521+ int perm __maybe_unused)
13522+AuStubInt0(au_hnotify_init_br, struct au_branch *br __maybe_unused,
13523+ int perm __maybe_unused)
13524+AuStubVoid(au_hnotify_fin_br, struct au_branch *br __maybe_unused)
4a4d8108
AM
13525+AuStubInt0(__init au_hnotify_init, void)
13526+AuStubVoid(au_hnotify_fin, void)
13527+AuStubVoid(au_hn_init, struct au_hinode *hinode __maybe_unused)
13528+#endif /* CONFIG_AUFS_HNOTIFY */
13529+
13530+static inline void au_hn_suspend(struct au_hinode *hdir)
13531+{
13532+ au_hn_ctl(hdir, /*do_set*/0);
1308ab2a 13533+}
13534+
4a4d8108 13535+static inline void au_hn_resume(struct au_hinode *hdir)
1308ab2a 13536+{
4a4d8108
AM
13537+ au_hn_ctl(hdir, /*do_set*/1);
13538+}
1308ab2a 13539+
4a4d8108
AM
13540+static inline void au_hn_imtx_lock(struct au_hinode *hdir)
13541+{
13542+ mutex_lock(&hdir->hi_inode->i_mutex);
13543+ au_hn_suspend(hdir);
13544+}
dece6358 13545+
4a4d8108
AM
13546+static inline void au_hn_imtx_lock_nested(struct au_hinode *hdir,
13547+ unsigned int sc __maybe_unused)
13548+{
13549+ mutex_lock_nested(&hdir->hi_inode->i_mutex, sc);
13550+ au_hn_suspend(hdir);
1facf9fc 13551+}
1facf9fc 13552+
4a4d8108
AM
13553+static inline void au_hn_imtx_unlock(struct au_hinode *hdir)
13554+{
13555+ au_hn_resume(hdir);
13556+ mutex_unlock(&hdir->hi_inode->i_mutex);
13557+}
13558+
13559+#endif /* __KERNEL__ */
13560+#endif /* __AUFS_INODE_H__ */
7f207e10
AM
13561diff -urN /usr/share/empty/fs/aufs/ioctl.c linux/fs/aufs/ioctl.c
13562--- /usr/share/empty/fs/aufs/ioctl.c 1970-01-01 01:00:00.000000000 +0100
2cbb1c4b 13563+++ linux/fs/aufs/ioctl.c 2011-07-11 11:34:24.075331673 +0200
027c5e7a 13564@@ -0,0 +1,158 @@
4a4d8108 13565+/*
027c5e7a 13566+ * Copyright (C) 2005-2011 Junjiro R. Okajima
4a4d8108
AM
13567+ *
13568+ * This program, aufs is free software; you can redistribute it and/or modify
13569+ * it under the terms of the GNU General Public License as published by
13570+ * the Free Software Foundation; either version 2 of the License, or
13571+ * (at your option) any later version.
13572+ *
13573+ * This program is distributed in the hope that it will be useful,
13574+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
13575+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13576+ * GNU General Public License for more details.
13577+ *
13578+ * You should have received a copy of the GNU General Public License
13579+ * along with this program; if not, write to the Free Software
13580+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
13581+ */
13582+
13583+/*
13584+ * ioctl
13585+ * plink-management and readdir in userspace.
13586+ * assist the pathconf(3) wrapper library.
13587+ */
13588+
13589+#include <linux/file.h>
13590+#include "aufs.h"
13591+
13592+static int au_wbr_fd(struct path *path)
13593+{
13594+ int err, fd;
13595+ aufs_bindex_t wbi, bindex, bend;
13596+ struct file *h_file;
13597+ struct super_block *sb;
13598+ struct dentry *root;
13599+ struct au_branch *wbr;
13600+
13601+ err = get_unused_fd();
13602+ if (unlikely(err < 0))
13603+ goto out;
13604+ fd = err;
13605+
13606+ wbi = 0;
13607+ sb = path->dentry->d_sb;
13608+ root = sb->s_root;
13609+ aufs_read_lock(root, AuLock_IR);
13610+ wbr = au_sbr(sb, wbi);
13611+ if (!(path->mnt->mnt_flags & MNT_READONLY)
13612+ && !au_br_writable(wbr->br_perm)) {
13613+ bend = au_sbend(sb);
13614+ for (bindex = 1; bindex <= bend; bindex++) {
13615+ wbr = au_sbr(sb, bindex);
13616+ if (au_br_writable(wbr->br_perm)) {
13617+ wbi = bindex;
13618+ break;
13619+ }
13620+ }
13621+ wbr = au_sbr(sb, wbi);
13622+ }
13623+ AuDbg("wbi %d\n", wbi);
13624+ h_file = au_h_open(root, wbi, O_RDONLY | O_DIRECTORY | O_LARGEFILE,
13625+ NULL);
13626+ aufs_read_unlock(root, AuLock_IR);
13627+ err = PTR_ERR(h_file);
13628+ if (IS_ERR(h_file))
13629+ goto out_fd;
13630+
13631+ atomic_dec(&wbr->br_count); /* cf. au_h_open() */
13632+ fd_install(fd, h_file);
13633+ err = fd;
13634+ goto out; /* success */
13635+
4f0767ce 13636+out_fd:
4a4d8108 13637+ put_unused_fd(fd);
4f0767ce 13638+out:
4a4d8108
AM
13639+ return err;
13640+}
13641+
13642+/* ---------------------------------------------------------------------- */
13643+
13644+long aufs_ioctl_dir(struct file *file, unsigned int cmd, unsigned long arg)
13645+{
13646+ long err;
13647+
13648+ switch (cmd) {
4a4d8108
AM
13649+ case AUFS_CTL_RDU:
13650+ case AUFS_CTL_RDU_INO:
13651+ err = au_rdu_ioctl(file, cmd, arg);
13652+ break;
13653+
13654+ case AUFS_CTL_WBR_FD:
13655+ err = au_wbr_fd(&file->f_path);
13656+ break;
13657+
027c5e7a
AM
13658+ case AUFS_CTL_IBUSY:
13659+ err = au_ibusy_ioctl(file, arg);
13660+ break;
13661+
4a4d8108
AM
13662+ default:
13663+ /* do not call the lower */
13664+ AuDbg("0x%x\n", cmd);
13665+ err = -ENOTTY;
13666+ }
13667+
13668+ AuTraceErr(err);
13669+ return err;
13670+}
13671+
13672+long aufs_ioctl_nondir(struct file *file, unsigned int cmd, unsigned long arg)
13673+{
13674+ long err;
13675+
13676+ switch (cmd) {
13677+ case AUFS_CTL_WBR_FD:
13678+ err = au_wbr_fd(&file->f_path);
13679+ break;
13680+
13681+ default:
13682+ /* do not call the lower */
13683+ AuDbg("0x%x\n", cmd);
13684+ err = -ENOTTY;
13685+ }
13686+
13687+ AuTraceErr(err);
13688+ return err;
13689+}
b752ccd1
AM
13690+
13691+#ifdef CONFIG_COMPAT
13692+long aufs_compat_ioctl_dir(struct file *file, unsigned int cmd,
13693+ unsigned long arg)
13694+{
13695+ long err;
13696+
13697+ switch (cmd) {
13698+ case AUFS_CTL_RDU:
13699+ case AUFS_CTL_RDU_INO:
13700+ err = au_rdu_compat_ioctl(file, cmd, arg);
13701+ break;
13702+
027c5e7a
AM
13703+ case AUFS_CTL_IBUSY:
13704+ err = au_ibusy_compat_ioctl(file, arg);
13705+ break;
13706+
b752ccd1
AM
13707+ default:
13708+ err = aufs_ioctl_dir(file, cmd, arg);
13709+ }
13710+
13711+ AuTraceErr(err);
13712+ return err;
13713+}
13714+
13715+#if 0 /* unused yet */
13716+long aufs_compat_ioctl_nondir(struct file *file, unsigned int cmd,
13717+ unsigned long arg)
13718+{
13719+ return aufs_ioctl_nondir(file, cmd, (unsigned long)compat_ptr(arg));
13720+}
13721+#endif
13722+#endif
7f207e10
AM
13723diff -urN /usr/share/empty/fs/aufs/i_op_add.c linux/fs/aufs/i_op_add.c
13724--- /usr/share/empty/fs/aufs/i_op_add.c 1970-01-01 01:00:00.000000000 +0100
2cbb1c4b
JR
13725+++ linux/fs/aufs/i_op_add.c 2011-07-11 11:34:24.074331673 +0200
13726@@ -0,0 +1,711 @@
4a4d8108 13727+/*
027c5e7a 13728+ * Copyright (C) 2005-2011 Junjiro R. Okajima
4a4d8108
AM
13729+ *
13730+ * This program, aufs is free software; you can redistribute it and/or modify
13731+ * it under the terms of the GNU General Public License as published by
13732+ * the Free Software Foundation; either version 2 of the License, or
13733+ * (at your option) any later version.
13734+ *
13735+ * This program is distributed in the hope that it will be useful,
13736+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
13737+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13738+ * GNU General Public License for more details.
13739+ *
13740+ * You should have received a copy of the GNU General Public License
13741+ * along with this program; if not, write to the Free Software
13742+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
13743+ */
13744+
13745+/*
13746+ * inode operations (add entry)
13747+ */
13748+
13749+#include "aufs.h"
13750+
13751+/*
13752+ * final procedure of adding a new entry, except link(2).
13753+ * remove whiteout, instantiate, copyup the parent dir's times and size
13754+ * and update version.
13755+ * if it failed, re-create the removed whiteout.
13756+ */
13757+static int epilog(struct inode *dir, aufs_bindex_t bindex,
13758+ struct dentry *wh_dentry, struct dentry *dentry)
13759+{
13760+ int err, rerr;
13761+ aufs_bindex_t bwh;
13762+ struct path h_path;
13763+ struct inode *inode, *h_dir;
13764+ struct dentry *wh;
13765+
13766+ bwh = -1;
13767+ if (wh_dentry) {
13768+ h_dir = wh_dentry->d_parent->d_inode; /* dir inode is locked */
13769+ IMustLock(h_dir);
13770+ AuDebugOn(au_h_iptr(dir, bindex) != h_dir);
13771+ bwh = au_dbwh(dentry);
13772+ h_path.dentry = wh_dentry;
13773+ h_path.mnt = au_sbr_mnt(dir->i_sb, bindex);
13774+ err = au_wh_unlink_dentry(au_h_iptr(dir, bindex), &h_path,
13775+ dentry);
13776+ if (unlikely(err))
13777+ goto out;
13778+ }
13779+
13780+ inode = au_new_inode(dentry, /*must_new*/1);
13781+ if (!IS_ERR(inode)) {
13782+ d_instantiate(dentry, inode);
13783+ dir = dentry->d_parent->d_inode; /* dir inode is locked */
13784+ IMustLock(dir);
13785+ if (au_ibstart(dir) == au_dbstart(dentry))
13786+ au_cpup_attr_timesizes(dir);
13787+ dir->i_version++;
13788+ return 0; /* success */
13789+ }
13790+
13791+ err = PTR_ERR(inode);
13792+ if (!wh_dentry)
13793+ goto out;
13794+
13795+ /* revert */
13796+ /* dir inode is locked */
13797+ wh = au_wh_create(dentry, bwh, wh_dentry->d_parent);
13798+ rerr = PTR_ERR(wh);
13799+ if (IS_ERR(wh)) {
13800+ AuIOErr("%.*s reverting whiteout failed(%d, %d)\n",
13801+ AuDLNPair(dentry), err, rerr);
13802+ err = -EIO;
13803+ } else
13804+ dput(wh);
13805+
4f0767ce 13806+out:
4a4d8108
AM
13807+ return err;
13808+}
13809+
027c5e7a
AM
13810+static int au_d_may_add(struct dentry *dentry)
13811+{
13812+ int err;
13813+
13814+ err = 0;
13815+ if (unlikely(d_unhashed(dentry)))
13816+ err = -ENOENT;
13817+ if (unlikely(dentry->d_inode))
13818+ err = -EEXIST;
13819+ return err;
13820+}
13821+
4a4d8108
AM
13822+/*
13823+ * simple tests for the adding inode operations.
13824+ * following the checks in vfs, plus the parent-child relationship.
13825+ */
13826+int au_may_add(struct dentry *dentry, aufs_bindex_t bindex,
13827+ struct dentry *h_parent, int isdir)
13828+{
13829+ int err;
13830+ umode_t h_mode;
13831+ struct dentry *h_dentry;
13832+ struct inode *h_inode;
13833+
13834+ err = -ENAMETOOLONG;
13835+ if (unlikely(dentry->d_name.len > AUFS_MAX_NAMELEN))
13836+ goto out;
13837+
13838+ h_dentry = au_h_dptr(dentry, bindex);
13839+ h_inode = h_dentry->d_inode;
13840+ if (!dentry->d_inode) {
13841+ err = -EEXIST;
13842+ if (unlikely(h_inode))
13843+ goto out;
13844+ } else {
13845+ /* rename(2) case */
13846+ err = -EIO;
13847+ if (unlikely(!h_inode || !h_inode->i_nlink))
13848+ goto out;
13849+
13850+ h_mode = h_inode->i_mode;
13851+ if (!isdir) {
13852+ err = -EISDIR;
13853+ if (unlikely(S_ISDIR(h_mode)))
13854+ goto out;
13855+ } else if (unlikely(!S_ISDIR(h_mode))) {
13856+ err = -ENOTDIR;
13857+ goto out;
13858+ }
13859+ }
13860+
13861+ err = 0;
13862+ /* expected parent dir is locked */
13863+ if (unlikely(h_parent != h_dentry->d_parent))
13864+ err = -EIO;
13865+
4f0767ce 13866+out:
4a4d8108
AM
13867+ AuTraceErr(err);
13868+ return err;
13869+}
13870+
13871+/*
13872+ * initial procedure of adding a new entry.
13873+ * prepare writable branch and the parent dir, lock it,
13874+ * and lookup whiteout for the new entry.
13875+ */
13876+static struct dentry*
13877+lock_hdir_lkup_wh(struct dentry *dentry, struct au_dtime *dt,
13878+ struct dentry *src_dentry, struct au_pin *pin,
13879+ struct au_wr_dir_args *wr_dir_args)
13880+{
13881+ struct dentry *wh_dentry, *h_parent;
13882+ struct super_block *sb;
13883+ struct au_branch *br;
13884+ int err;
13885+ unsigned int udba;
13886+ aufs_bindex_t bcpup;
13887+
13888+ AuDbg("%.*s\n", AuDLNPair(dentry));
13889+
13890+ err = au_wr_dir(dentry, src_dentry, wr_dir_args);
13891+ bcpup = err;
13892+ wh_dentry = ERR_PTR(err);
13893+ if (unlikely(err < 0))
13894+ goto out;
13895+
13896+ sb = dentry->d_sb;
13897+ udba = au_opt_udba(sb);
13898+ err = au_pin(pin, dentry, bcpup, udba,
13899+ AuPin_DI_LOCKED | AuPin_MNT_WRITE);
13900+ wh_dentry = ERR_PTR(err);
13901+ if (unlikely(err))
13902+ goto out;
13903+
13904+ h_parent = au_pinned_h_parent(pin);
13905+ if (udba != AuOpt_UDBA_NONE
13906+ && au_dbstart(dentry) == bcpup)
13907+ err = au_may_add(dentry, bcpup, h_parent,
13908+ au_ftest_wrdir(wr_dir_args->flags, ISDIR));
13909+ else if (unlikely(dentry->d_name.len > AUFS_MAX_NAMELEN))
13910+ err = -ENAMETOOLONG;
13911+ wh_dentry = ERR_PTR(err);
13912+ if (unlikely(err))
13913+ goto out_unpin;
13914+
13915+ br = au_sbr(sb, bcpup);
13916+ if (dt) {
13917+ struct path tmp = {
13918+ .dentry = h_parent,
13919+ .mnt = br->br_mnt
13920+ };
13921+ au_dtime_store(dt, au_pinned_parent(pin), &tmp);
13922+ }
13923+
13924+ wh_dentry = NULL;
13925+ if (bcpup != au_dbwh(dentry))
13926+ goto out; /* success */
13927+
13928+ wh_dentry = au_wh_lkup(h_parent, &dentry->d_name, br);
13929+
4f0767ce 13930+out_unpin:
4a4d8108
AM
13931+ if (IS_ERR(wh_dentry))
13932+ au_unpin(pin);
4f0767ce 13933+out:
4a4d8108
AM
13934+ return wh_dentry;
13935+}
13936+
13937+/* ---------------------------------------------------------------------- */
13938+
13939+enum { Mknod, Symlink, Creat };
13940+struct simple_arg {
13941+ int type;
13942+ union {
13943+ struct {
13944+ int mode;
13945+ struct nameidata *nd;
13946+ } c;
13947+ struct {
13948+ const char *symname;
13949+ } s;
13950+ struct {
13951+ int mode;
13952+ dev_t dev;
13953+ } m;
13954+ } u;
13955+};
13956+
13957+static int add_simple(struct inode *dir, struct dentry *dentry,
13958+ struct simple_arg *arg)
13959+{
13960+ int err;
13961+ aufs_bindex_t bstart;
13962+ unsigned char created;
13963+ struct au_dtime dt;
13964+ struct au_pin pin;
13965+ struct path h_path;
13966+ struct dentry *wh_dentry, *parent;
13967+ struct inode *h_dir;
13968+ struct au_wr_dir_args wr_dir_args = {
13969+ .force_btgt = -1,
13970+ .flags = AuWrDir_ADD_ENTRY
13971+ };
13972+
13973+ AuDbg("%.*s\n", AuDLNPair(dentry));
13974+ IMustLock(dir);
13975+
13976+ parent = dentry->d_parent; /* dir inode is locked */
027c5e7a
AM
13977+ err = aufs_read_lock(dentry, AuLock_DW | AuLock_GEN);
13978+ if (unlikely(err))
13979+ goto out;
13980+ err = au_d_may_add(dentry);
13981+ if (unlikely(err))
13982+ goto out_unlock;
4a4d8108
AM
13983+ di_write_lock_parent(parent);
13984+ wh_dentry = lock_hdir_lkup_wh(dentry, &dt, /*src_dentry*/NULL, &pin,
13985+ &wr_dir_args);
13986+ err = PTR_ERR(wh_dentry);
13987+ if (IS_ERR(wh_dentry))
027c5e7a 13988+ goto out_parent;
4a4d8108
AM
13989+
13990+ bstart = au_dbstart(dentry);
13991+ h_path.dentry = au_h_dptr(dentry, bstart);
13992+ h_path.mnt = au_sbr_mnt(dentry->d_sb, bstart);
13993+ h_dir = au_pinned_h_dir(&pin);
13994+ switch (arg->type) {
13995+ case Creat:
13996+ err = vfsub_create(h_dir, &h_path, arg->u.c.mode);
13997+ break;
13998+ case Symlink:
13999+ err = vfsub_symlink(h_dir, &h_path, arg->u.s.symname);
14000+ break;
14001+ case Mknod:
14002+ err = vfsub_mknod(h_dir, &h_path, arg->u.m.mode, arg->u.m.dev);
14003+ break;
14004+ default:
14005+ BUG();
14006+ }
14007+ created = !err;
14008+ if (!err)
14009+ err = epilog(dir, bstart, wh_dentry, dentry);
14010+
14011+ /* revert */
14012+ if (unlikely(created && err && h_path.dentry->d_inode)) {
14013+ int rerr;
14014+ rerr = vfsub_unlink(h_dir, &h_path, /*force*/0);
14015+ if (rerr) {
14016+ AuIOErr("%.*s revert failure(%d, %d)\n",
14017+ AuDLNPair(dentry), err, rerr);
14018+ err = -EIO;
14019+ }
14020+ au_dtime_revert(&dt);
4a4d8108
AM
14021+ }
14022+
14023+ au_unpin(&pin);
14024+ dput(wh_dentry);
14025+
027c5e7a
AM
14026+out_parent:
14027+ di_write_unlock(parent);
14028+out_unlock:
4a4d8108
AM
14029+ if (unlikely(err)) {
14030+ au_update_dbstart(dentry);
14031+ d_drop(dentry);
14032+ }
4a4d8108 14033+ aufs_read_unlock(dentry, AuLock_DW);
027c5e7a 14034+out:
4a4d8108
AM
14035+ return err;
14036+}
14037+
14038+int aufs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev)
14039+{
14040+ struct simple_arg arg = {
14041+ .type = Mknod,
14042+ .u.m = {
14043+ .mode = mode,
14044+ .dev = dev
14045+ }
14046+ };
14047+ return add_simple(dir, dentry, &arg);
14048+}
14049+
14050+int aufs_symlink(struct inode *dir, struct dentry *dentry, const char *symname)
14051+{
14052+ struct simple_arg arg = {
14053+ .type = Symlink,
14054+ .u.s.symname = symname
14055+ };
14056+ return add_simple(dir, dentry, &arg);
14057+}
14058+
14059+int aufs_create(struct inode *dir, struct dentry *dentry, int mode,
14060+ struct nameidata *nd)
14061+{
14062+ struct simple_arg arg = {
14063+ .type = Creat,
14064+ .u.c = {
14065+ .mode = mode,
14066+ .nd = nd
14067+ }
14068+ };
14069+ return add_simple(dir, dentry, &arg);
14070+}
14071+
14072+/* ---------------------------------------------------------------------- */
14073+
14074+struct au_link_args {
14075+ aufs_bindex_t bdst, bsrc;
14076+ struct au_pin pin;
14077+ struct path h_path;
14078+ struct dentry *src_parent, *parent;
14079+};
14080+
14081+static int au_cpup_before_link(struct dentry *src_dentry,
14082+ struct au_link_args *a)
14083+{
14084+ int err;
14085+ struct dentry *h_src_dentry;
14086+ struct mutex *h_mtx;
14087+ struct file *h_file;
14088+
14089+ di_read_lock_parent(a->src_parent, AuLock_IR);
14090+ err = au_test_and_cpup_dirs(src_dentry, a->bdst);
14091+ if (unlikely(err))
14092+ goto out;
14093+
14094+ h_src_dentry = au_h_dptr(src_dentry, a->bsrc);
14095+ h_mtx = &h_src_dentry->d_inode->i_mutex;
14096+ err = au_pin(&a->pin, src_dentry, a->bdst,
14097+ au_opt_udba(src_dentry->d_sb),
14098+ AuPin_DI_LOCKED | AuPin_MNT_WRITE);
14099+ if (unlikely(err))
14100+ goto out;
14101+ mutex_lock_nested(h_mtx, AuLsc_I_CHILD);
14102+ h_file = au_h_open_pre(src_dentry, a->bsrc);
14103+ if (IS_ERR(h_file)) {
14104+ err = PTR_ERR(h_file);
14105+ h_file = NULL;
14106+ } else
14107+ err = au_sio_cpup_simple(src_dentry, a->bdst, a->bsrc,
14108+ AuCpup_DTIME /* | AuCpup_KEEPLINO */);
14109+ mutex_unlock(h_mtx);
14110+ au_h_open_post(src_dentry, a->bsrc, h_file);
14111+ au_unpin(&a->pin);
14112+
4f0767ce 14113+out:
4a4d8108
AM
14114+ di_read_unlock(a->src_parent, AuLock_IR);
14115+ return err;
14116+}
14117+
14118+static int au_cpup_or_link(struct dentry *src_dentry, struct au_link_args *a)
14119+{
14120+ int err;
14121+ unsigned char plink;
14122+ struct inode *h_inode, *inode;
14123+ struct dentry *h_src_dentry;
14124+ struct super_block *sb;
14125+ struct file *h_file;
14126+
14127+ plink = 0;
14128+ h_inode = NULL;
14129+ sb = src_dentry->d_sb;
14130+ inode = src_dentry->d_inode;
14131+ if (au_ibstart(inode) <= a->bdst)
14132+ h_inode = au_h_iptr(inode, a->bdst);
14133+ if (!h_inode || !h_inode->i_nlink) {
14134+ /* copyup src_dentry as the name of dentry. */
14135+ au_set_dbstart(src_dentry, a->bdst);
14136+ au_set_h_dptr(src_dentry, a->bdst, dget(a->h_path.dentry));
14137+ h_inode = au_h_dptr(src_dentry, a->bsrc)->d_inode;
14138+ mutex_lock_nested(&h_inode->i_mutex, AuLsc_I_CHILD);
14139+ h_file = au_h_open_pre(src_dentry, a->bsrc);
14140+ if (IS_ERR(h_file)) {
14141+ err = PTR_ERR(h_file);
14142+ h_file = NULL;
14143+ } else
14144+ err = au_sio_cpup_single(src_dentry, a->bdst, a->bsrc,
14145+ -1, AuCpup_KEEPLINO,
14146+ a->parent);
14147+ mutex_unlock(&h_inode->i_mutex);
14148+ au_h_open_post(src_dentry, a->bsrc, h_file);
14149+ au_set_h_dptr(src_dentry, a->bdst, NULL);
14150+ au_set_dbstart(src_dentry, a->bsrc);
14151+ } else {
14152+ /* the inode of src_dentry already exists on a.bdst branch */
14153+ h_src_dentry = d_find_alias(h_inode);
14154+ if (!h_src_dentry && au_plink_test(inode)) {
14155+ plink = 1;
14156+ h_src_dentry = au_plink_lkup(inode, a->bdst);
14157+ err = PTR_ERR(h_src_dentry);
14158+ if (IS_ERR(h_src_dentry))
14159+ goto out;
14160+
14161+ if (unlikely(!h_src_dentry->d_inode)) {
14162+ dput(h_src_dentry);
14163+ h_src_dentry = NULL;
14164+ }
14165+
14166+ }
14167+ if (h_src_dentry) {
14168+ err = vfsub_link(h_src_dentry, au_pinned_h_dir(&a->pin),
14169+ &a->h_path);
14170+ dput(h_src_dentry);
14171+ } else {
14172+ AuIOErr("no dentry found for hi%lu on b%d\n",
14173+ h_inode->i_ino, a->bdst);
14174+ err = -EIO;
14175+ }
14176+ }
14177+
14178+ if (!err && !plink)
14179+ au_plink_append(inode, a->bdst, a->h_path.dentry);
14180+
14181+out:
2cbb1c4b 14182+ AuTraceErr(err);
4a4d8108
AM
14183+ return err;
14184+}
14185+
14186+int aufs_link(struct dentry *src_dentry, struct inode *dir,
14187+ struct dentry *dentry)
14188+{
14189+ int err, rerr;
14190+ struct au_dtime dt;
14191+ struct au_link_args *a;
14192+ struct dentry *wh_dentry, *h_src_dentry;
14193+ struct inode *inode;
14194+ struct super_block *sb;
14195+ struct au_wr_dir_args wr_dir_args = {
14196+ /* .force_btgt = -1, */
14197+ .flags = AuWrDir_ADD_ENTRY
14198+ };
14199+
14200+ IMustLock(dir);
14201+ inode = src_dentry->d_inode;
14202+ IMustLock(inode);
14203+
4a4d8108
AM
14204+ err = -ENOMEM;
14205+ a = kzalloc(sizeof(*a), GFP_NOFS);
14206+ if (unlikely(!a))
14207+ goto out;
14208+
14209+ a->parent = dentry->d_parent; /* dir inode is locked */
027c5e7a
AM
14210+ err = aufs_read_and_write_lock2(dentry, src_dentry,
14211+ AuLock_NOPLM | AuLock_GEN);
e49829fe
JR
14212+ if (unlikely(err))
14213+ goto out_kfree;
027c5e7a
AM
14214+ err = au_d_hashed_positive(src_dentry);
14215+ if (unlikely(err))
14216+ goto out_unlock;
14217+ err = au_d_may_add(dentry);
14218+ if (unlikely(err))
14219+ goto out_unlock;
e49829fe 14220+
4a4d8108 14221+ a->src_parent = dget_parent(src_dentry);
2cbb1c4b 14222+ wr_dir_args.force_btgt = au_ibstart(inode);
4a4d8108
AM
14223+
14224+ di_write_lock_parent(a->parent);
14225+ wr_dir_args.force_btgt = au_wbr(dentry, wr_dir_args.force_btgt);
14226+ wh_dentry = lock_hdir_lkup_wh(dentry, &dt, src_dentry, &a->pin,
14227+ &wr_dir_args);
14228+ err = PTR_ERR(wh_dentry);
14229+ if (IS_ERR(wh_dentry))
027c5e7a 14230+ goto out_parent;
4a4d8108
AM
14231+
14232+ err = 0;
14233+ sb = dentry->d_sb;
14234+ a->bdst = au_dbstart(dentry);
14235+ a->h_path.dentry = au_h_dptr(dentry, a->bdst);
14236+ a->h_path.mnt = au_sbr_mnt(sb, a->bdst);
2cbb1c4b
JR
14237+ a->bsrc = au_ibstart(inode);
14238+ h_src_dentry = au_h_d_alias(src_dentry, a->bsrc);
14239+ if (!h_src_dentry) {
14240+ a->bsrc = au_dbstart(src_dentry);
14241+ h_src_dentry = au_h_d_alias(src_dentry, a->bsrc);
14242+ AuDebugOn(!h_src_dentry);
14243+ } else if (IS_ERR(h_src_dentry))
14244+ goto out_parent;
14245+
4a4d8108
AM
14246+ if (au_opt_test(au_mntflags(sb), PLINK)) {
14247+ if (a->bdst < a->bsrc
14248+ /* && h_src_dentry->d_sb != a->h_path.dentry->d_sb */)
14249+ err = au_cpup_or_link(src_dentry, a);
2cbb1c4b 14250+ else
4a4d8108
AM
14251+ err = vfsub_link(h_src_dentry, au_pinned_h_dir(&a->pin),
14252+ &a->h_path);
2cbb1c4b 14253+ dput(h_src_dentry);
4a4d8108
AM
14254+ } else {
14255+ /*
14256+ * copyup src_dentry to the branch we process,
14257+ * and then link(2) to it.
14258+ */
2cbb1c4b 14259+ dput(h_src_dentry);
4a4d8108
AM
14260+ if (a->bdst < a->bsrc
14261+ /* && h_src_dentry->d_sb != a->h_path.dentry->d_sb */) {
14262+ au_unpin(&a->pin);
14263+ di_write_unlock(a->parent);
14264+ err = au_cpup_before_link(src_dentry, a);
14265+ di_write_lock_parent(a->parent);
14266+ if (!err)
14267+ err = au_pin(&a->pin, dentry, a->bdst,
14268+ au_opt_udba(sb),
14269+ AuPin_DI_LOCKED | AuPin_MNT_WRITE);
14270+ if (unlikely(err))
14271+ goto out_wh;
14272+ }
14273+ if (!err) {
14274+ h_src_dentry = au_h_dptr(src_dentry, a->bdst);
14275+ err = -ENOENT;
14276+ if (h_src_dentry && h_src_dentry->d_inode)
14277+ err = vfsub_link(h_src_dentry,
14278+ au_pinned_h_dir(&a->pin),
14279+ &a->h_path);
14280+ }
14281+ }
14282+ if (unlikely(err))
14283+ goto out_unpin;
14284+
14285+ if (wh_dentry) {
14286+ a->h_path.dentry = wh_dentry;
14287+ err = au_wh_unlink_dentry(au_pinned_h_dir(&a->pin), &a->h_path,
14288+ dentry);
14289+ if (unlikely(err))
14290+ goto out_revert;
14291+ }
14292+
14293+ dir->i_version++;
14294+ if (au_ibstart(dir) == au_dbstart(dentry))
14295+ au_cpup_attr_timesizes(dir);
14296+ inc_nlink(inode);
14297+ inode->i_ctime = dir->i_ctime;
027c5e7a
AM
14298+ d_instantiate(dentry, au_igrab(inode));
14299+ if (d_unhashed(a->h_path.dentry))
4a4d8108
AM
14300+ /* some filesystem calls d_drop() */
14301+ d_drop(dentry);
14302+ goto out_unpin; /* success */
14303+
4f0767ce 14304+out_revert:
4a4d8108 14305+ rerr = vfsub_unlink(au_pinned_h_dir(&a->pin), &a->h_path, /*force*/0);
027c5e7a
AM
14306+ if (unlikely(rerr)) {
14307+ AuIOErr("%.*s reverting failed(%d, %d)\n",
14308+ AuDLNPair(dentry), err, rerr);
14309+ err = -EIO;
14310+ }
4a4d8108 14311+ au_dtime_revert(&dt);
4f0767ce 14312+out_unpin:
4a4d8108 14313+ au_unpin(&a->pin);
4f0767ce 14314+out_wh:
4a4d8108 14315+ dput(wh_dentry);
027c5e7a
AM
14316+out_parent:
14317+ di_write_unlock(a->parent);
14318+ dput(a->src_parent);
4f0767ce 14319+out_unlock:
4a4d8108
AM
14320+ if (unlikely(err)) {
14321+ au_update_dbstart(dentry);
14322+ d_drop(dentry);
14323+ }
4a4d8108 14324+ aufs_read_and_write_unlock2(dentry, src_dentry);
e49829fe 14325+out_kfree:
4a4d8108 14326+ kfree(a);
4f0767ce 14327+out:
4a4d8108
AM
14328+ return err;
14329+}
14330+
14331+int aufs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
14332+{
14333+ int err, rerr;
14334+ aufs_bindex_t bindex;
14335+ unsigned char diropq;
14336+ struct path h_path;
14337+ struct dentry *wh_dentry, *parent, *opq_dentry;
14338+ struct mutex *h_mtx;
14339+ struct super_block *sb;
14340+ struct {
14341+ struct au_pin pin;
14342+ struct au_dtime dt;
14343+ } *a; /* reduce the stack usage */
14344+ struct au_wr_dir_args wr_dir_args = {
14345+ .force_btgt = -1,
14346+ .flags = AuWrDir_ADD_ENTRY | AuWrDir_ISDIR
14347+ };
14348+
14349+ IMustLock(dir);
14350+
14351+ err = -ENOMEM;
14352+ a = kmalloc(sizeof(*a), GFP_NOFS);
14353+ if (unlikely(!a))
14354+ goto out;
14355+
027c5e7a
AM
14356+ err = aufs_read_lock(dentry, AuLock_DW | AuLock_GEN);
14357+ if (unlikely(err))
14358+ goto out_free;
14359+ err = au_d_may_add(dentry);
14360+ if (unlikely(err))
14361+ goto out_unlock;
14362+
4a4d8108
AM
14363+ parent = dentry->d_parent; /* dir inode is locked */
14364+ di_write_lock_parent(parent);
14365+ wh_dentry = lock_hdir_lkup_wh(dentry, &a->dt, /*src_dentry*/NULL,
14366+ &a->pin, &wr_dir_args);
14367+ err = PTR_ERR(wh_dentry);
14368+ if (IS_ERR(wh_dentry))
027c5e7a 14369+ goto out_parent;
4a4d8108
AM
14370+
14371+ sb = dentry->d_sb;
14372+ bindex = au_dbstart(dentry);
14373+ h_path.dentry = au_h_dptr(dentry, bindex);
14374+ h_path.mnt = au_sbr_mnt(sb, bindex);
14375+ err = vfsub_mkdir(au_pinned_h_dir(&a->pin), &h_path, mode);
14376+ if (unlikely(err))
027c5e7a 14377+ goto out_unpin;
4a4d8108
AM
14378+
14379+ /* make the dir opaque */
14380+ diropq = 0;
14381+ h_mtx = &h_path.dentry->d_inode->i_mutex;
14382+ if (wh_dentry
14383+ || au_opt_test(au_mntflags(sb), ALWAYS_DIROPQ)) {
14384+ mutex_lock_nested(h_mtx, AuLsc_I_CHILD);
14385+ opq_dentry = au_diropq_create(dentry, bindex);
14386+ mutex_unlock(h_mtx);
14387+ err = PTR_ERR(opq_dentry);
14388+ if (IS_ERR(opq_dentry))
14389+ goto out_dir;
14390+ dput(opq_dentry);
14391+ diropq = 1;
14392+ }
14393+
14394+ err = epilog(dir, bindex, wh_dentry, dentry);
14395+ if (!err) {
14396+ inc_nlink(dir);
027c5e7a 14397+ goto out_unpin; /* success */
4a4d8108
AM
14398+ }
14399+
14400+ /* revert */
14401+ if (diropq) {
14402+ AuLabel(revert opq);
14403+ mutex_lock_nested(h_mtx, AuLsc_I_CHILD);
14404+ rerr = au_diropq_remove(dentry, bindex);
14405+ mutex_unlock(h_mtx);
14406+ if (rerr) {
14407+ AuIOErr("%.*s reverting diropq failed(%d, %d)\n",
14408+ AuDLNPair(dentry), err, rerr);
14409+ err = -EIO;
14410+ }
14411+ }
14412+
4f0767ce 14413+out_dir:
4a4d8108
AM
14414+ AuLabel(revert dir);
14415+ rerr = vfsub_rmdir(au_pinned_h_dir(&a->pin), &h_path);
14416+ if (rerr) {
14417+ AuIOErr("%.*s reverting dir failed(%d, %d)\n",
14418+ AuDLNPair(dentry), err, rerr);
14419+ err = -EIO;
14420+ }
4a4d8108 14421+ au_dtime_revert(&a->dt);
027c5e7a 14422+out_unpin:
4a4d8108
AM
14423+ au_unpin(&a->pin);
14424+ dput(wh_dentry);
027c5e7a
AM
14425+out_parent:
14426+ di_write_unlock(parent);
14427+out_unlock:
4a4d8108
AM
14428+ if (unlikely(err)) {
14429+ au_update_dbstart(dentry);
14430+ d_drop(dentry);
14431+ }
4a4d8108 14432+ aufs_read_unlock(dentry, AuLock_DW);
027c5e7a 14433+out_free:
4a4d8108 14434+ kfree(a);
4f0767ce 14435+out:
4a4d8108
AM
14436+ return err;
14437+}
7f207e10
AM
14438diff -urN /usr/share/empty/fs/aufs/i_op.c linux/fs/aufs/i_op.c
14439--- /usr/share/empty/fs/aufs/i_op.c 1970-01-01 01:00:00.000000000 +0100
2cbb1c4b 14440+++ linux/fs/aufs/i_op.c 2011-07-11 11:34:24.074331673 +0200
027c5e7a 14441@@ -0,0 +1,976 @@
4a4d8108 14442+/*
027c5e7a 14443+ * Copyright (C) 2005-2011 Junjiro R. Okajima
4a4d8108
AM
14444+ *
14445+ * This program, aufs is free software; you can redistribute it and/or modify
14446+ * it under the terms of the GNU General Public License as published by
14447+ * the Free Software Foundation; either version 2 of the License, or
14448+ * (at your option) any later version.
14449+ *
14450+ * This program is distributed in the hope that it will be useful,
14451+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
14452+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14453+ * GNU General Public License for more details.
14454+ *
14455+ * You should have received a copy of the GNU General Public License
14456+ * along with this program; if not, write to the Free Software
14457+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
14458+ */
1facf9fc 14459+
1308ab2a 14460+/*
4a4d8108 14461+ * inode operations (except add/del/rename)
1308ab2a 14462+ */
4a4d8108
AM
14463+
14464+#include <linux/device_cgroup.h>
14465+#include <linux/fs_stack.h>
14466+#include <linux/mm.h>
14467+#include <linux/namei.h>
14468+#include <linux/security.h>
14469+#include <linux/uaccess.h>
14470+#include "aufs.h"
14471+
027c5e7a 14472+static int h_permission(struct inode *h_inode, int mask, unsigned int flags,
4a4d8108 14473+ struct vfsmount *h_mnt, int brperm)
1facf9fc 14474+{
1308ab2a 14475+ int err;
4a4d8108 14476+ const unsigned char write_mask = !!(mask & (MAY_WRITE | MAY_APPEND));
1facf9fc 14477+
4a4d8108
AM
14478+ err = -EACCES;
14479+ if ((write_mask && IS_IMMUTABLE(h_inode))
14480+ || ((mask & MAY_EXEC)
14481+ && S_ISREG(h_inode->i_mode)
14482+ && ((h_mnt->mnt_flags & MNT_NOEXEC)
14483+ || !(h_inode->i_mode & S_IXUGO))))
14484+ goto out;
14485+
14486+ /*
14487+ * - skip the lower fs test in the case of write to ro branch.
14488+ * - nfs dir permission write check is optimized, but a policy for
14489+ * link/rename requires a real check.
14490+ */
14491+ if ((write_mask && !au_br_writable(brperm))
14492+ || (au_test_nfs(h_inode->i_sb) && S_ISDIR(h_inode->i_mode)
14493+ && write_mask && !(mask & MAY_READ))
14494+ || !h_inode->i_op->permission) {
14495+ /* AuLabel(generic_permission); */
027c5e7a 14496+ err = generic_permission(h_inode, mask, flags,
4a4d8108 14497+ h_inode->i_op->check_acl);
1308ab2a 14498+ } else {
4a4d8108 14499+ /* AuLabel(h_inode->permission); */
027c5e7a 14500+ err = h_inode->i_op->permission(h_inode, mask, flags);
4a4d8108
AM
14501+ AuTraceErr(err);
14502+ }
1facf9fc 14503+
4a4d8108
AM
14504+ if (!err)
14505+ err = devcgroup_inode_permission(h_inode, mask);
7f207e10 14506+ if (!err)
4a4d8108 14507+ err = security_inode_permission(h_inode, mask);
4a4d8108
AM
14508+
14509+#if 0
14510+ if (!err) {
14511+ /* todo: do we need to call ima_path_check()? */
14512+ struct path h_path = {
14513+ .dentry =
14514+ .mnt = h_mnt
14515+ };
14516+ err = ima_path_check(&h_path,
14517+ mask & (MAY_READ | MAY_WRITE | MAY_EXEC),
14518+ IMA_COUNT_LEAVE);
1308ab2a 14519+ }
4a4d8108 14520+#endif
dece6358 14521+
4f0767ce 14522+out:
1308ab2a 14523+ return err;
14524+}
dece6358 14525+
027c5e7a 14526+static int aufs_permission(struct inode *inode, int mask, unsigned int flags)
1308ab2a 14527+{
14528+ int err;
4a4d8108
AM
14529+ aufs_bindex_t bindex, bend;
14530+ const unsigned char isdir = !!S_ISDIR(inode->i_mode),
14531+ write_mask = !!(mask & (MAY_WRITE | MAY_APPEND));
14532+ struct inode *h_inode;
14533+ struct super_block *sb;
14534+ struct au_branch *br;
1facf9fc 14535+
027c5e7a
AM
14536+ /* todo: support rcu-walk? */
14537+ if (flags & IPERM_FLAG_RCU)
14538+ return -ECHILD;
14539+
4a4d8108
AM
14540+ sb = inode->i_sb;
14541+ si_read_lock(sb, AuLock_FLUSH);
14542+ ii_read_lock_child(inode);
027c5e7a
AM
14543+#if 0
14544+ err = au_iigen_test(inode, au_sigen(sb));
14545+ if (unlikely(err))
14546+ goto out;
14547+#endif
dece6358 14548+
4a4d8108
AM
14549+ if (!isdir || write_mask) {
14550+ err = au_busy_or_stale();
14551+ h_inode = au_h_iptr(inode, au_ibstart(inode));
14552+ if (unlikely(!h_inode
14553+ || (h_inode->i_mode & S_IFMT)
14554+ != (inode->i_mode & S_IFMT)))
14555+ goto out;
1facf9fc 14556+
4a4d8108
AM
14557+ err = 0;
14558+ bindex = au_ibstart(inode);
14559+ br = au_sbr(sb, bindex);
027c5e7a
AM
14560+ err = h_permission(h_inode, mask, flags, br->br_mnt,
14561+ br->br_perm);
4a4d8108
AM
14562+ if (write_mask
14563+ && !err
14564+ && !special_file(h_inode->i_mode)) {
14565+ /* test whether the upper writable branch exists */
14566+ err = -EROFS;
14567+ for (; bindex >= 0; bindex--)
14568+ if (!au_br_rdonly(au_sbr(sb, bindex))) {
14569+ err = 0;
14570+ break;
14571+ }
14572+ }
14573+ goto out;
14574+ }
dece6358 14575+
4a4d8108 14576+ /* non-write to dir */
1308ab2a 14577+ err = 0;
4a4d8108
AM
14578+ bend = au_ibend(inode);
14579+ for (bindex = au_ibstart(inode); !err && bindex <= bend; bindex++) {
14580+ h_inode = au_h_iptr(inode, bindex);
14581+ if (h_inode) {
14582+ err = au_busy_or_stale();
14583+ if (unlikely(!S_ISDIR(h_inode->i_mode)))
14584+ break;
14585+
14586+ br = au_sbr(sb, bindex);
027c5e7a 14587+ err = h_permission(h_inode, mask, flags, br->br_mnt,
4a4d8108
AM
14588+ br->br_perm);
14589+ }
14590+ }
1308ab2a 14591+
4f0767ce 14592+out:
4a4d8108
AM
14593+ ii_read_unlock(inode);
14594+ si_read_unlock(sb);
1308ab2a 14595+ return err;
14596+}
14597+
4a4d8108 14598+/* ---------------------------------------------------------------------- */
1facf9fc 14599+
4a4d8108
AM
14600+static struct dentry *aufs_lookup(struct inode *dir, struct dentry *dentry,
14601+ struct nameidata *nd)
14602+{
14603+ struct dentry *ret, *parent;
b752ccd1 14604+ struct inode *inode;
4a4d8108
AM
14605+ struct super_block *sb;
14606+ int err, npositive;
dece6358 14607+
4a4d8108 14608+ IMustLock(dir);
1308ab2a 14609+
4a4d8108 14610+ sb = dir->i_sb;
7f207e10
AM
14611+ err = si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLM);
14612+ ret = ERR_PTR(err);
14613+ if (unlikely(err))
14614+ goto out;
14615+
4a4d8108
AM
14616+ ret = ERR_PTR(-ENAMETOOLONG);
14617+ if (unlikely(dentry->d_name.len > AUFS_MAX_NAMELEN))
7f207e10 14618+ goto out_si;
4a4d8108
AM
14619+ err = au_di_init(dentry);
14620+ ret = ERR_PTR(err);
14621+ if (unlikely(err))
7f207e10 14622+ goto out_si;
1308ab2a 14623+
027c5e7a 14624+ npositive = 0; /* suppress a warning */
4a4d8108
AM
14625+ parent = dentry->d_parent; /* dir inode is locked */
14626+ di_read_lock_parent(parent, AuLock_IR);
027c5e7a
AM
14627+ err = au_alive_dir(parent);
14628+ if (!err)
14629+ err = au_digen_test(parent, au_sigen(sb));
14630+ if (!err) {
14631+ npositive = au_lkup_dentry(dentry, au_dbstart(parent),
14632+ /*type*/0, nd);
14633+ err = npositive;
14634+ }
4a4d8108 14635+ di_read_unlock(parent, AuLock_IR);
4a4d8108
AM
14636+ ret = ERR_PTR(err);
14637+ if (unlikely(err < 0))
14638+ goto out_unlock;
1308ab2a 14639+
4a4d8108
AM
14640+ inode = NULL;
14641+ if (npositive) {
b752ccd1 14642+ inode = au_new_inode(dentry, /*must_new*/0);
4a4d8108 14643+ ret = (void *)inode;
1facf9fc 14644+ }
4a4d8108
AM
14645+ if (IS_ERR(inode))
14646+ goto out_unlock;
14647+
14648+ ret = d_splice_alias(inode, dentry);
7f207e10 14649+ if (unlikely(IS_ERR(ret) && inode)) {
4a4d8108 14650+ ii_write_unlock(inode);
7f207e10
AM
14651+ iput(inode);
14652+ }
1facf9fc 14653+
4f0767ce 14654+out_unlock:
4a4d8108 14655+ di_write_unlock(dentry);
7f207e10 14656+out_si:
4a4d8108 14657+ si_read_unlock(sb);
7f207e10 14658+out:
4a4d8108
AM
14659+ return ret;
14660+}
1facf9fc 14661+
4a4d8108 14662+/* ---------------------------------------------------------------------- */
1facf9fc 14663+
4a4d8108
AM
14664+static int au_wr_dir_cpup(struct dentry *dentry, struct dentry *parent,
14665+ const unsigned char add_entry, aufs_bindex_t bcpup,
14666+ aufs_bindex_t bstart)
14667+{
14668+ int err;
14669+ struct dentry *h_parent;
14670+ struct inode *h_dir;
1facf9fc 14671+
027c5e7a 14672+ if (add_entry)
4a4d8108 14673+ IMustLock(parent->d_inode);
027c5e7a 14674+ else
4a4d8108
AM
14675+ di_write_lock_parent(parent);
14676+
14677+ err = 0;
14678+ if (!au_h_dptr(parent, bcpup)) {
14679+ if (bstart < bcpup)
14680+ err = au_cpdown_dirs(dentry, bcpup);
14681+ else
14682+ err = au_cpup_dirs(dentry, bcpup);
14683+ }
14684+ if (!err && add_entry) {
14685+ h_parent = au_h_dptr(parent, bcpup);
14686+ h_dir = h_parent->d_inode;
14687+ mutex_lock_nested(&h_dir->i_mutex, AuLsc_I_PARENT);
14688+ err = au_lkup_neg(dentry, bcpup);
14689+ /* todo: no unlock here */
14690+ mutex_unlock(&h_dir->i_mutex);
027c5e7a
AM
14691+
14692+ AuDbg("bcpup %d\n", bcpup);
14693+ if (!err) {
14694+ if (!dentry->d_inode)
14695+ au_set_h_dptr(dentry, bstart, NULL);
4a4d8108
AM
14696+ au_update_dbrange(dentry, /*do_put_zero*/0);
14697+ }
1308ab2a 14698+ }
1facf9fc 14699+
4a4d8108
AM
14700+ if (!add_entry)
14701+ di_write_unlock(parent);
14702+ if (!err)
14703+ err = bcpup; /* success */
1308ab2a 14704+
027c5e7a 14705+ AuTraceErr(err);
4a4d8108
AM
14706+ return err;
14707+}
1facf9fc 14708+
4a4d8108
AM
14709+/*
14710+ * decide the branch and the parent dir where we will create a new entry.
14711+ * returns new bindex or an error.
14712+ * copyup the parent dir if needed.
14713+ */
14714+int au_wr_dir(struct dentry *dentry, struct dentry *src_dentry,
14715+ struct au_wr_dir_args *args)
14716+{
14717+ int err;
14718+ aufs_bindex_t bcpup, bstart, src_bstart;
14719+ const unsigned char add_entry = !!au_ftest_wrdir(args->flags,
14720+ ADD_ENTRY);
14721+ struct super_block *sb;
14722+ struct dentry *parent;
14723+ struct au_sbinfo *sbinfo;
1facf9fc 14724+
4a4d8108
AM
14725+ sb = dentry->d_sb;
14726+ sbinfo = au_sbi(sb);
14727+ parent = dget_parent(dentry);
14728+ bstart = au_dbstart(dentry);
14729+ bcpup = bstart;
14730+ if (args->force_btgt < 0) {
14731+ if (src_dentry) {
14732+ src_bstart = au_dbstart(src_dentry);
14733+ if (src_bstart < bstart)
14734+ bcpup = src_bstart;
14735+ } else if (add_entry) {
14736+ err = AuWbrCreate(sbinfo, dentry,
14737+ au_ftest_wrdir(args->flags, ISDIR));
14738+ bcpup = err;
14739+ }
1facf9fc 14740+
4a4d8108
AM
14741+ if (bcpup < 0 || au_test_ro(sb, bcpup, dentry->d_inode)) {
14742+ if (add_entry)
14743+ err = AuWbrCopyup(sbinfo, dentry);
14744+ else {
14745+ if (!IS_ROOT(dentry)) {
14746+ di_read_lock_parent(parent, !AuLock_IR);
14747+ err = AuWbrCopyup(sbinfo, dentry);
14748+ di_read_unlock(parent, !AuLock_IR);
14749+ } else
14750+ err = AuWbrCopyup(sbinfo, dentry);
14751+ }
14752+ bcpup = err;
14753+ if (unlikely(err < 0))
14754+ goto out;
14755+ }
14756+ } else {
14757+ bcpup = args->force_btgt;
14758+ AuDebugOn(au_test_ro(sb, bcpup, dentry->d_inode));
1308ab2a 14759+ }
027c5e7a 14760+
4a4d8108
AM
14761+ AuDbg("bstart %d, bcpup %d\n", bstart, bcpup);
14762+ err = bcpup;
14763+ if (bcpup == bstart)
14764+ goto out; /* success */
4a4d8108
AM
14765+
14766+ /* copyup the new parent into the branch we process */
14767+ err = au_wr_dir_cpup(dentry, parent, add_entry, bcpup, bstart);
027c5e7a
AM
14768+ if (err >= 0) {
14769+ if (!dentry->d_inode) {
14770+ au_set_h_dptr(dentry, bstart, NULL);
14771+ au_set_dbstart(dentry, bcpup);
14772+ au_set_dbend(dentry, bcpup);
14773+ }
14774+ AuDebugOn(add_entry && !au_h_dptr(dentry, bcpup));
14775+ }
4a4d8108 14776+
4f0767ce 14777+out:
4a4d8108 14778+ dput(parent);
dece6358
AM
14779+ return err;
14780+}
1facf9fc 14781+
1308ab2a 14782+/* ---------------------------------------------------------------------- */
14783+
4a4d8108 14784+struct dentry *au_pinned_h_parent(struct au_pin *pin)
1308ab2a 14785+{
4a4d8108
AM
14786+ if (pin && pin->parent)
14787+ return au_h_dptr(pin->parent, pin->bindex);
14788+ return NULL;
dece6358 14789+}
1facf9fc 14790+
4a4d8108 14791+void au_unpin(struct au_pin *p)
dece6358 14792+{
e49829fe 14793+ if (p->h_mnt && au_ftest_pin(p->flags, MNT_WRITE))
4a4d8108
AM
14794+ mnt_drop_write(p->h_mnt);
14795+ if (!p->hdir)
14796+ return;
1facf9fc 14797+
4a4d8108
AM
14798+ au_hn_imtx_unlock(p->hdir);
14799+ if (!au_ftest_pin(p->flags, DI_LOCKED))
14800+ di_read_unlock(p->parent, AuLock_IR);
14801+ iput(p->hdir->hi_inode);
14802+ dput(p->parent);
14803+ p->parent = NULL;
14804+ p->hdir = NULL;
14805+ p->h_mnt = NULL;
14806+}
1308ab2a 14807+
4a4d8108
AM
14808+int au_do_pin(struct au_pin *p)
14809+{
14810+ int err;
14811+ struct super_block *sb;
14812+ struct dentry *h_dentry, *h_parent;
14813+ struct au_branch *br;
14814+ struct inode *h_dir;
14815+
14816+ err = 0;
14817+ sb = p->dentry->d_sb;
14818+ br = au_sbr(sb, p->bindex);
14819+ if (IS_ROOT(p->dentry)) {
14820+ if (au_ftest_pin(p->flags, MNT_WRITE)) {
14821+ p->h_mnt = br->br_mnt;
14822+ err = mnt_want_write(p->h_mnt);
14823+ if (unlikely(err)) {
14824+ au_fclr_pin(p->flags, MNT_WRITE);
14825+ goto out_err;
14826+ }
14827+ }
dece6358 14828+ goto out;
1facf9fc 14829+ }
14830+
4a4d8108
AM
14831+ h_dentry = NULL;
14832+ if (p->bindex <= au_dbend(p->dentry))
14833+ h_dentry = au_h_dptr(p->dentry, p->bindex);
dece6358 14834+
4a4d8108
AM
14835+ p->parent = dget_parent(p->dentry);
14836+ if (!au_ftest_pin(p->flags, DI_LOCKED))
14837+ di_read_lock(p->parent, AuLock_IR, p->lsc_di);
dece6358 14838+
4a4d8108
AM
14839+ h_dir = NULL;
14840+ h_parent = au_h_dptr(p->parent, p->bindex);
14841+ p->hdir = au_hi(p->parent->d_inode, p->bindex);
14842+ if (p->hdir)
14843+ h_dir = p->hdir->hi_inode;
dece6358 14844+
b752ccd1
AM
14845+ /*
14846+ * udba case, or
14847+ * if DI_LOCKED is not set, then p->parent may be different
14848+ * and h_parent can be NULL.
14849+ */
14850+ if (unlikely(!p->hdir || !h_dir || !h_parent)) {
e49829fe 14851+ err = -EBUSY;
4a4d8108
AM
14852+ if (!au_ftest_pin(p->flags, DI_LOCKED))
14853+ di_read_unlock(p->parent, AuLock_IR);
14854+ dput(p->parent);
14855+ p->parent = NULL;
14856+ goto out_err;
14857+ }
1308ab2a 14858+
4a4d8108
AM
14859+ au_igrab(h_dir);
14860+ au_hn_imtx_lock_nested(p->hdir, p->lsc_hi);
1308ab2a 14861+
4a4d8108
AM
14862+ if (unlikely(p->hdir->hi_inode != h_parent->d_inode)) {
14863+ err = -EBUSY;
14864+ goto out_unpin;
14865+ }
14866+ if (h_dentry) {
14867+ err = au_h_verify(h_dentry, p->udba, h_dir, h_parent, br);
14868+ if (unlikely(err)) {
14869+ au_fclr_pin(p->flags, MNT_WRITE);
14870+ goto out_unpin;
14871+ }
1facf9fc 14872+ }
dece6358 14873+
4a4d8108
AM
14874+ if (au_ftest_pin(p->flags, MNT_WRITE)) {
14875+ p->h_mnt = br->br_mnt;
14876+ err = mnt_want_write(p->h_mnt);
dece6358 14877+ if (unlikely(err)) {
4a4d8108
AM
14878+ au_fclr_pin(p->flags, MNT_WRITE);
14879+ goto out_unpin;
dece6358
AM
14880+ }
14881+ }
4a4d8108
AM
14882+ goto out; /* success */
14883+
4f0767ce 14884+out_unpin:
4a4d8108 14885+ au_unpin(p);
4f0767ce 14886+out_err:
4a4d8108
AM
14887+ pr_err("err %d\n", err);
14888+ err = au_busy_or_stale();
4f0767ce 14889+out:
1facf9fc 14890+ return err;
14891+}
14892+
4a4d8108
AM
14893+void au_pin_init(struct au_pin *p, struct dentry *dentry,
14894+ aufs_bindex_t bindex, int lsc_di, int lsc_hi,
14895+ unsigned int udba, unsigned char flags)
14896+{
14897+ p->dentry = dentry;
14898+ p->udba = udba;
14899+ p->lsc_di = lsc_di;
14900+ p->lsc_hi = lsc_hi;
14901+ p->flags = flags;
14902+ p->bindex = bindex;
14903+
14904+ p->parent = NULL;
14905+ p->hdir = NULL;
14906+ p->h_mnt = NULL;
14907+}
14908+
14909+int au_pin(struct au_pin *pin, struct dentry *dentry, aufs_bindex_t bindex,
14910+ unsigned int udba, unsigned char flags)
14911+{
14912+ au_pin_init(pin, dentry, bindex, AuLsc_DI_PARENT, AuLsc_I_PARENT2,
14913+ udba, flags);
14914+ return au_do_pin(pin);
14915+}
14916+
dece6358
AM
14917+/* ---------------------------------------------------------------------- */
14918+
1308ab2a 14919+/*
4a4d8108
AM
14920+ * ->setattr() and ->getattr() are called in various cases.
14921+ * chmod, stat: dentry is revalidated.
14922+ * fchmod, fstat: file and dentry are not revalidated, additionally they may be
14923+ * unhashed.
14924+ * for ->setattr(), ia->ia_file is passed from ftruncate only.
1308ab2a 14925+ */
027c5e7a 14926+/* todo: consolidate with do_refresh() and simple_reval_dpath() */
4a4d8108 14927+static int au_reval_for_attr(struct dentry *dentry, unsigned int sigen)
1facf9fc 14928+{
4a4d8108
AM
14929+ int err;
14930+ struct inode *inode;
14931+ struct dentry *parent;
1facf9fc 14932+
1308ab2a 14933+ err = 0;
4a4d8108 14934+ inode = dentry->d_inode;
027c5e7a 14935+ if (au_digen_test(dentry, sigen)) {
4a4d8108
AM
14936+ parent = dget_parent(dentry);
14937+ di_read_lock_parent(parent, AuLock_IR);
027c5e7a 14938+ err = au_refresh_dentry(dentry, parent);
4a4d8108
AM
14939+ di_read_unlock(parent, AuLock_IR);
14940+ dput(parent);
dece6358 14941+ }
1facf9fc 14942+
4a4d8108 14943+ AuTraceErr(err);
1308ab2a 14944+ return err;
14945+}
dece6358 14946+
4a4d8108
AM
14947+#define AuIcpup_DID_CPUP 1
14948+#define au_ftest_icpup(flags, name) ((flags) & AuIcpup_##name)
7f207e10
AM
14949+#define au_fset_icpup(flags, name) \
14950+ do { (flags) |= AuIcpup_##name; } while (0)
14951+#define au_fclr_icpup(flags, name) \
14952+ do { (flags) &= ~AuIcpup_##name; } while (0)
1308ab2a 14953+
4a4d8108
AM
14954+struct au_icpup_args {
14955+ unsigned char flags;
14956+ unsigned char pin_flags;
14957+ aufs_bindex_t btgt;
14958+ unsigned int udba;
14959+ struct au_pin pin;
14960+ struct path h_path;
14961+ struct inode *h_inode;
14962+};
1308ab2a 14963+
4a4d8108
AM
14964+static int au_pin_and_icpup(struct dentry *dentry, struct iattr *ia,
14965+ struct au_icpup_args *a)
1308ab2a 14966+{
14967+ int err;
4a4d8108 14968+ loff_t sz;
e49829fe 14969+ aufs_bindex_t bstart, ibstart;
4a4d8108
AM
14970+ struct dentry *hi_wh, *parent;
14971+ struct inode *inode;
14972+ struct file *h_file;
14973+ struct au_wr_dir_args wr_dir_args = {
14974+ .force_btgt = -1,
14975+ .flags = 0
14976+ };
14977+
14978+ bstart = au_dbstart(dentry);
14979+ inode = dentry->d_inode;
14980+ if (S_ISDIR(inode->i_mode))
14981+ au_fset_wrdir(wr_dir_args.flags, ISDIR);
14982+ /* plink or hi_wh() case */
e49829fe 14983+ ibstart = au_ibstart(inode);
027c5e7a 14984+ if (bstart != ibstart && !au_test_ro(inode->i_sb, ibstart, inode))
e49829fe 14985+ wr_dir_args.force_btgt = ibstart;
4a4d8108
AM
14986+ err = au_wr_dir(dentry, /*src_dentry*/NULL, &wr_dir_args);
14987+ if (unlikely(err < 0))
14988+ goto out;
14989+ a->btgt = err;
14990+ if (err != bstart)
14991+ au_fset_icpup(a->flags, DID_CPUP);
14992+
14993+ err = 0;
14994+ a->pin_flags = AuPin_MNT_WRITE;
14995+ parent = NULL;
14996+ if (!IS_ROOT(dentry)) {
14997+ au_fset_pin(a->pin_flags, DI_LOCKED);
14998+ parent = dget_parent(dentry);
14999+ di_write_lock_parent(parent);
15000+ }
15001+
15002+ err = au_pin(&a->pin, dentry, a->btgt, a->udba, a->pin_flags);
15003+ if (unlikely(err))
15004+ goto out_parent;
15005+
15006+ a->h_path.dentry = au_h_dptr(dentry, bstart);
15007+ a->h_inode = a->h_path.dentry->d_inode;
15008+ mutex_lock_nested(&a->h_inode->i_mutex, AuLsc_I_CHILD);
15009+ sz = -1;
15010+ if ((ia->ia_valid & ATTR_SIZE) && ia->ia_size < i_size_read(a->h_inode))
15011+ sz = ia->ia_size;
15012+
15013+ h_file = NULL;
15014+ hi_wh = NULL;
027c5e7a 15015+ if (au_ftest_icpup(a->flags, DID_CPUP) && d_unlinked(dentry)) {
4a4d8108
AM
15016+ hi_wh = au_hi_wh(inode, a->btgt);
15017+ if (!hi_wh) {
15018+ err = au_sio_cpup_wh(dentry, a->btgt, sz, /*file*/NULL);
15019+ if (unlikely(err))
15020+ goto out_unlock;
15021+ hi_wh = au_hi_wh(inode, a->btgt);
15022+ /* todo: revalidate hi_wh? */
15023+ }
15024+ }
15025+
15026+ if (parent) {
15027+ au_pin_set_parent_lflag(&a->pin, /*lflag*/0);
15028+ di_downgrade_lock(parent, AuLock_IR);
15029+ dput(parent);
15030+ parent = NULL;
15031+ }
15032+ if (!au_ftest_icpup(a->flags, DID_CPUP))
15033+ goto out; /* success */
15034+
15035+ if (!d_unhashed(dentry)) {
15036+ h_file = au_h_open_pre(dentry, bstart);
15037+ if (IS_ERR(h_file)) {
15038+ err = PTR_ERR(h_file);
15039+ h_file = NULL;
15040+ } else
15041+ err = au_sio_cpup_simple(dentry, a->btgt, sz,
15042+ AuCpup_DTIME);
15043+ if (!err)
15044+ a->h_path.dentry = au_h_dptr(dentry, a->btgt);
15045+ } else if (!hi_wh)
15046+ a->h_path.dentry = au_h_dptr(dentry, a->btgt);
15047+ else
15048+ a->h_path.dentry = hi_wh; /* do not dget here */
1308ab2a 15049+
4f0767ce 15050+out_unlock:
4a4d8108
AM
15051+ mutex_unlock(&a->h_inode->i_mutex);
15052+ au_h_open_post(dentry, bstart, h_file);
15053+ a->h_inode = a->h_path.dentry->d_inode;
dece6358 15054+ if (!err) {
4a4d8108 15055+ mutex_lock_nested(&a->h_inode->i_mutex, AuLsc_I_CHILD);
dece6358 15056+ goto out; /* success */
1facf9fc 15057+ }
dece6358 15058+
4a4d8108 15059+ au_unpin(&a->pin);
4f0767ce 15060+out_parent:
4a4d8108
AM
15061+ if (parent) {
15062+ di_write_unlock(parent);
15063+ dput(parent);
15064+ }
4f0767ce 15065+out:
1facf9fc 15066+ return err;
15067+}
15068+
4a4d8108 15069+static int aufs_setattr(struct dentry *dentry, struct iattr *ia)
1facf9fc 15070+{
4a4d8108
AM
15071+ int err;
15072+ struct inode *inode;
15073+ struct super_block *sb;
15074+ struct file *file;
15075+ struct au_icpup_args *a;
1facf9fc 15076+
4a4d8108
AM
15077+ inode = dentry->d_inode;
15078+ IMustLock(inode);
dece6358 15079+
4a4d8108
AM
15080+ err = -ENOMEM;
15081+ a = kzalloc(sizeof(*a), GFP_NOFS);
15082+ if (unlikely(!a))
15083+ goto out;
1facf9fc 15084+
4a4d8108
AM
15085+ if (ia->ia_valid & (ATTR_KILL_SUID | ATTR_KILL_SGID))
15086+ ia->ia_valid &= ~ATTR_MODE;
dece6358 15087+
4a4d8108
AM
15088+ file = NULL;
15089+ sb = dentry->d_sb;
e49829fe
JR
15090+ err = si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLM);
15091+ if (unlikely(err))
15092+ goto out_kfree;
15093+
4a4d8108
AM
15094+ if (ia->ia_valid & ATTR_FILE) {
15095+ /* currently ftruncate(2) only */
15096+ AuDebugOn(!S_ISREG(inode->i_mode));
15097+ file = ia->ia_file;
15098+ err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/1);
15099+ if (unlikely(err))
15100+ goto out_si;
15101+ ia->ia_file = au_hf_top(file);
15102+ a->udba = AuOpt_UDBA_NONE;
15103+ } else {
15104+ /* fchmod() doesn't pass ia_file */
15105+ a->udba = au_opt_udba(sb);
027c5e7a
AM
15106+ di_write_lock_child(dentry);
15107+ /* no d_unlinked(), to set UDBA_NONE for root */
4a4d8108
AM
15108+ if (d_unhashed(dentry))
15109+ a->udba = AuOpt_UDBA_NONE;
4a4d8108
AM
15110+ if (a->udba != AuOpt_UDBA_NONE) {
15111+ AuDebugOn(IS_ROOT(dentry));
15112+ err = au_reval_for_attr(dentry, au_sigen(sb));
15113+ if (unlikely(err))
15114+ goto out_dentry;
15115+ }
dece6358 15116+ }
dece6358 15117+
4a4d8108
AM
15118+ err = au_pin_and_icpup(dentry, ia, a);
15119+ if (unlikely(err < 0))
15120+ goto out_dentry;
15121+ if (au_ftest_icpup(a->flags, DID_CPUP)) {
15122+ ia->ia_file = NULL;
15123+ ia->ia_valid &= ~ATTR_FILE;
1308ab2a 15124+ }
dece6358 15125+
4a4d8108
AM
15126+ a->h_path.mnt = au_sbr_mnt(sb, a->btgt);
15127+ if ((ia->ia_valid & (ATTR_MODE | ATTR_CTIME))
15128+ == (ATTR_MODE | ATTR_CTIME)) {
15129+ err = security_path_chmod(a->h_path.dentry, a->h_path.mnt,
15130+ ia->ia_mode);
15131+ if (unlikely(err))
15132+ goto out_unlock;
15133+ } else if ((ia->ia_valid & (ATTR_UID | ATTR_GID))
15134+ && (ia->ia_valid & ATTR_CTIME)) {
15135+ err = security_path_chown(&a->h_path, ia->ia_uid, ia->ia_gid);
15136+ if (unlikely(err))
15137+ goto out_unlock;
15138+ }
dece6358 15139+
4a4d8108
AM
15140+ if (ia->ia_valid & ATTR_SIZE) {
15141+ struct file *f;
1308ab2a 15142+
953406b4 15143+ if (ia->ia_size < i_size_read(inode))
4a4d8108 15144+ /* unmap only */
953406b4 15145+ truncate_setsize(inode, ia->ia_size);
1308ab2a 15146+
4a4d8108
AM
15147+ f = NULL;
15148+ if (ia->ia_valid & ATTR_FILE)
15149+ f = ia->ia_file;
15150+ mutex_unlock(&a->h_inode->i_mutex);
15151+ err = vfsub_trunc(&a->h_path, ia->ia_size, ia->ia_valid, f);
15152+ mutex_lock_nested(&a->h_inode->i_mutex, AuLsc_I_CHILD);
15153+ } else
15154+ err = vfsub_notify_change(&a->h_path, ia);
15155+ if (!err)
15156+ au_cpup_attr_changeable(inode);
1308ab2a 15157+
4f0767ce 15158+out_unlock:
4a4d8108
AM
15159+ mutex_unlock(&a->h_inode->i_mutex);
15160+ au_unpin(&a->pin);
027c5e7a
AM
15161+ if (unlikely(err))
15162+ au_update_dbstart(dentry);
4f0767ce 15163+out_dentry:
4a4d8108
AM
15164+ di_write_unlock(dentry);
15165+ if (file) {
15166+ fi_write_unlock(file);
15167+ ia->ia_file = file;
15168+ ia->ia_valid |= ATTR_FILE;
15169+ }
4f0767ce 15170+out_si:
4a4d8108 15171+ si_read_unlock(sb);
e49829fe 15172+out_kfree:
4a4d8108 15173+ kfree(a);
4f0767ce 15174+out:
4a4d8108
AM
15175+ AuTraceErr(err);
15176+ return err;
1facf9fc 15177+}
15178+
4a4d8108
AM
15179+static void au_refresh_iattr(struct inode *inode, struct kstat *st,
15180+ unsigned int nlink)
1facf9fc 15181+{
4a4d8108
AM
15182+ inode->i_mode = st->mode;
15183+ inode->i_uid = st->uid;
15184+ inode->i_gid = st->gid;
15185+ inode->i_atime = st->atime;
15186+ inode->i_mtime = st->mtime;
15187+ inode->i_ctime = st->ctime;
1facf9fc 15188+
4a4d8108
AM
15189+ au_cpup_attr_nlink(inode, /*force*/0);
15190+ if (S_ISDIR(inode->i_mode)) {
15191+ inode->i_nlink -= nlink;
15192+ inode->i_nlink += st->nlink;
15193+ }
1facf9fc 15194+
4a4d8108
AM
15195+ spin_lock(&inode->i_lock);
15196+ inode->i_blocks = st->blocks;
15197+ i_size_write(inode, st->size);
15198+ spin_unlock(&inode->i_lock);
1facf9fc 15199+}
15200+
4a4d8108
AM
15201+static int aufs_getattr(struct vfsmount *mnt __maybe_unused,
15202+ struct dentry *dentry, struct kstat *st)
1facf9fc 15203+{
4a4d8108
AM
15204+ int err;
15205+ unsigned int mnt_flags;
15206+ aufs_bindex_t bindex;
15207+ unsigned char udba_none, positive;
15208+ struct super_block *sb, *h_sb;
15209+ struct inode *inode;
15210+ struct vfsmount *h_mnt;
15211+ struct dentry *h_dentry;
1facf9fc 15212+
4a4d8108
AM
15213+ sb = dentry->d_sb;
15214+ inode = dentry->d_inode;
7f207e10
AM
15215+ err = si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLM);
15216+ if (unlikely(err))
15217+ goto out;
4a4d8108
AM
15218+ mnt_flags = au_mntflags(sb);
15219+ udba_none = !!au_opt_test(mnt_flags, UDBA_NONE);
1facf9fc 15220+
4a4d8108 15221+ /* support fstat(2) */
027c5e7a 15222+ if (!d_unlinked(dentry) && !udba_none) {
4a4d8108 15223+ unsigned int sigen = au_sigen(sb);
027c5e7a
AM
15224+ err = au_digen_test(dentry, sigen);
15225+ if (!err) {
4a4d8108 15226+ di_read_lock_child(dentry, AuLock_IR);
027c5e7a
AM
15227+ err = au_dbrange_test(dentry);
15228+ if (unlikely(err))
15229+ goto out_unlock;
15230+ } else {
4a4d8108
AM
15231+ AuDebugOn(IS_ROOT(dentry));
15232+ di_write_lock_child(dentry);
027c5e7a
AM
15233+ err = au_dbrange_test(dentry);
15234+ if (!err)
15235+ err = au_reval_for_attr(dentry, sigen);
4a4d8108
AM
15236+ di_downgrade_lock(dentry, AuLock_IR);
15237+ if (unlikely(err))
7f207e10 15238+ goto out_unlock;
4a4d8108
AM
15239+ }
15240+ } else
15241+ di_read_lock_child(dentry, AuLock_IR);
1facf9fc 15242+
4a4d8108
AM
15243+ bindex = au_ibstart(inode);
15244+ h_mnt = au_sbr_mnt(sb, bindex);
15245+ h_sb = h_mnt->mnt_sb;
15246+ if (!au_test_fs_bad_iattr(h_sb) && udba_none)
15247+ goto out_fill; /* success */
1facf9fc 15248+
4a4d8108
AM
15249+ h_dentry = NULL;
15250+ if (au_dbstart(dentry) == bindex)
15251+ h_dentry = dget(au_h_dptr(dentry, bindex));
15252+ else if (au_opt_test(mnt_flags, PLINK) && au_plink_test(inode)) {
15253+ h_dentry = au_plink_lkup(inode, bindex);
15254+ if (IS_ERR(h_dentry))
15255+ goto out_fill; /* pretending success */
15256+ }
15257+ /* illegally overlapped or something */
15258+ if (unlikely(!h_dentry))
15259+ goto out_fill; /* pretending success */
15260+
15261+ positive = !!h_dentry->d_inode;
15262+ if (positive)
15263+ err = vfs_getattr(h_mnt, h_dentry, st);
15264+ dput(h_dentry);
15265+ if (!err) {
15266+ if (positive)
15267+ au_refresh_iattr(inode, st, h_dentry->d_inode->i_nlink);
15268+ goto out_fill; /* success */
1facf9fc 15269+ }
7f207e10
AM
15270+ AuTraceErr(err);
15271+ goto out_unlock;
4a4d8108 15272+
4f0767ce 15273+out_fill:
4a4d8108 15274+ generic_fillattr(inode, st);
7f207e10 15275+out_unlock:
4a4d8108
AM
15276+ di_read_unlock(dentry, AuLock_IR);
15277+ si_read_unlock(sb);
7f207e10
AM
15278+out:
15279+ AuTraceErr(err);
4a4d8108 15280+ return err;
1facf9fc 15281+}
15282+
15283+/* ---------------------------------------------------------------------- */
15284+
4a4d8108
AM
15285+static int h_readlink(struct dentry *dentry, int bindex, char __user *buf,
15286+ int bufsiz)
1facf9fc 15287+{
15288+ int err;
4a4d8108
AM
15289+ struct super_block *sb;
15290+ struct dentry *h_dentry;
1facf9fc 15291+
4a4d8108
AM
15292+ err = -EINVAL;
15293+ h_dentry = au_h_dptr(dentry, bindex);
15294+ if (unlikely(!h_dentry->d_inode->i_op->readlink))
15295+ goto out;
1facf9fc 15296+
4a4d8108
AM
15297+ err = security_inode_readlink(h_dentry);
15298+ if (unlikely(err))
dece6358 15299+ goto out;
1facf9fc 15300+
4a4d8108
AM
15301+ sb = dentry->d_sb;
15302+ if (!au_test_ro(sb, bindex, dentry->d_inode)) {
15303+ vfsub_touch_atime(au_sbr_mnt(sb, bindex), h_dentry);
15304+ fsstack_copy_attr_atime(dentry->d_inode, h_dentry->d_inode);
1facf9fc 15305+ }
4a4d8108 15306+ err = h_dentry->d_inode->i_op->readlink(h_dentry, buf, bufsiz);
1facf9fc 15307+
4f0767ce 15308+out:
4a4d8108
AM
15309+ return err;
15310+}
1facf9fc 15311+
4a4d8108
AM
15312+static int aufs_readlink(struct dentry *dentry, char __user *buf, int bufsiz)
15313+{
15314+ int err;
1facf9fc 15315+
027c5e7a
AM
15316+ err = aufs_read_lock(dentry, AuLock_IR | AuLock_GEN);
15317+ if (unlikely(err))
15318+ goto out;
15319+ err = au_d_hashed_positive(dentry);
15320+ if (!err)
15321+ err = h_readlink(dentry, au_dbstart(dentry), buf, bufsiz);
4a4d8108 15322+ aufs_read_unlock(dentry, AuLock_IR);
1facf9fc 15323+
027c5e7a 15324+out:
4a4d8108
AM
15325+ return err;
15326+}
1facf9fc 15327+
4a4d8108
AM
15328+static void *aufs_follow_link(struct dentry *dentry, struct nameidata *nd)
15329+{
15330+ int err;
4a4d8108 15331+ mm_segment_t old_fs;
b752ccd1
AM
15332+ union {
15333+ char *k;
15334+ char __user *u;
15335+ } buf;
1facf9fc 15336+
4a4d8108 15337+ err = -ENOMEM;
b752ccd1
AM
15338+ buf.k = __getname_gfp(GFP_NOFS);
15339+ if (unlikely(!buf.k))
4a4d8108 15340+ goto out;
1facf9fc 15341+
027c5e7a
AM
15342+ err = aufs_read_lock(dentry, AuLock_IR | AuLock_GEN);
15343+ if (unlikely(err))
15344+ goto out_name;
15345+
15346+ err = au_d_hashed_positive(dentry);
15347+ if (!err) {
15348+ old_fs = get_fs();
15349+ set_fs(KERNEL_DS);
15350+ err = h_readlink(dentry, au_dbstart(dentry), buf.u, PATH_MAX);
15351+ set_fs(old_fs);
15352+ }
4a4d8108 15353+ aufs_read_unlock(dentry, AuLock_IR);
1facf9fc 15354+
4a4d8108 15355+ if (err >= 0) {
b752ccd1 15356+ buf.k[err] = 0;
4a4d8108 15357+ /* will be freed by put_link */
b752ccd1 15358+ nd_set_link(nd, buf.k);
4a4d8108 15359+ return NULL; /* success */
1308ab2a 15360+ }
1facf9fc 15361+
027c5e7a
AM
15362+out_name:
15363+ __putname(buf.k);
4f0767ce 15364+out:
4a4d8108
AM
15365+ path_put(&nd->path);
15366+ AuTraceErr(err);
15367+ return ERR_PTR(err);
15368+}
1facf9fc 15369+
4a4d8108
AM
15370+static void aufs_put_link(struct dentry *dentry __maybe_unused,
15371+ struct nameidata *nd, void *cookie __maybe_unused)
15372+{
15373+ __putname(nd_get_link(nd));
15374+}
1facf9fc 15375+
4a4d8108 15376+/* ---------------------------------------------------------------------- */
1facf9fc 15377+
4a4d8108
AM
15378+static void aufs_truncate_range(struct inode *inode __maybe_unused,
15379+ loff_t start __maybe_unused,
15380+ loff_t end __maybe_unused)
15381+{
15382+ AuUnsupport();
15383+}
1facf9fc 15384+
4a4d8108 15385+/* ---------------------------------------------------------------------- */
1308ab2a 15386+
4a4d8108
AM
15387+struct inode_operations aufs_symlink_iop = {
15388+ .permission = aufs_permission,
15389+ .setattr = aufs_setattr,
15390+ .getattr = aufs_getattr,
15391+ .readlink = aufs_readlink,
15392+ .follow_link = aufs_follow_link,
15393+ .put_link = aufs_put_link
15394+};
15395+
15396+struct inode_operations aufs_dir_iop = {
15397+ .create = aufs_create,
15398+ .lookup = aufs_lookup,
15399+ .link = aufs_link,
15400+ .unlink = aufs_unlink,
15401+ .symlink = aufs_symlink,
15402+ .mkdir = aufs_mkdir,
15403+ .rmdir = aufs_rmdir,
15404+ .mknod = aufs_mknod,
15405+ .rename = aufs_rename,
15406+
15407+ .permission = aufs_permission,
15408+ .setattr = aufs_setattr,
15409+ .getattr = aufs_getattr
15410+};
15411+
15412+struct inode_operations aufs_iop = {
15413+ .permission = aufs_permission,
15414+ .setattr = aufs_setattr,
15415+ .getattr = aufs_getattr,
15416+ .truncate_range = aufs_truncate_range
15417+};
7f207e10
AM
15418diff -urN /usr/share/empty/fs/aufs/i_op_del.c linux/fs/aufs/i_op_del.c
15419--- /usr/share/empty/fs/aufs/i_op_del.c 1970-01-01 01:00:00.000000000 +0100
2cbb1c4b 15420+++ linux/fs/aufs/i_op_del.c 2011-07-11 11:34:24.075331673 +0200
027c5e7a 15421@@ -0,0 +1,481 @@
1facf9fc 15422+/*
027c5e7a 15423+ * Copyright (C) 2005-2011 Junjiro R. Okajima
1facf9fc 15424+ *
15425+ * This program, aufs is free software; you can redistribute it and/or modify
15426+ * it under the terms of the GNU General Public License as published by
15427+ * the Free Software Foundation; either version 2 of the License, or
15428+ * (at your option) any later version.
dece6358
AM
15429+ *
15430+ * This program is distributed in the hope that it will be useful,
15431+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
15432+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15433+ * GNU General Public License for more details.
15434+ *
15435+ * You should have received a copy of the GNU General Public License
15436+ * along with this program; if not, write to the Free Software
15437+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 15438+ */
15439+
15440+/*
4a4d8108 15441+ * inode operations (del entry)
1308ab2a 15442+ */
dece6358 15443+
1308ab2a 15444+#include "aufs.h"
dece6358 15445+
4a4d8108
AM
15446+/*
15447+ * decide if a new whiteout for @dentry is necessary or not.
15448+ * when it is necessary, prepare the parent dir for the upper branch whose
15449+ * branch index is @bcpup for creation. the actual creation of the whiteout will
15450+ * be done by caller.
15451+ * return value:
15452+ * 0: wh is unnecessary
15453+ * plus: wh is necessary
15454+ * minus: error
15455+ */
15456+int au_wr_dir_need_wh(struct dentry *dentry, int isdir, aufs_bindex_t *bcpup)
1308ab2a 15457+{
4a4d8108
AM
15458+ int need_wh, err;
15459+ aufs_bindex_t bstart;
15460+ struct super_block *sb;
dece6358 15461+
4a4d8108
AM
15462+ sb = dentry->d_sb;
15463+ bstart = au_dbstart(dentry);
15464+ if (*bcpup < 0) {
15465+ *bcpup = bstart;
15466+ if (au_test_ro(sb, bstart, dentry->d_inode)) {
15467+ err = AuWbrCopyup(au_sbi(sb), dentry);
15468+ *bcpup = err;
15469+ if (unlikely(err < 0))
15470+ goto out;
15471+ }
15472+ } else
15473+ AuDebugOn(bstart < *bcpup
15474+ || au_test_ro(sb, *bcpup, dentry->d_inode));
15475+ AuDbg("bcpup %d, bstart %d\n", *bcpup, bstart);
1308ab2a 15476+
4a4d8108
AM
15477+ if (*bcpup != bstart) {
15478+ err = au_cpup_dirs(dentry, *bcpup);
15479+ if (unlikely(err))
15480+ goto out;
15481+ need_wh = 1;
15482+ } else {
027c5e7a 15483+ struct au_dinfo *dinfo, *tmp;
4a4d8108 15484+
027c5e7a
AM
15485+ need_wh = -ENOMEM;
15486+ dinfo = au_di(dentry);
15487+ tmp = au_di_alloc(sb, AuLsc_DI_TMP);
15488+ if (tmp) {
15489+ au_di_cp(tmp, dinfo);
15490+ au_di_swap(tmp, dinfo);
15491+ /* returns the number of positive dentries */
15492+ need_wh = au_lkup_dentry(dentry, bstart + 1, /*type*/0,
15493+ /*nd*/NULL);
15494+ au_di_swap(tmp, dinfo);
15495+ au_rw_write_unlock(&tmp->di_rwsem);
15496+ au_di_free(tmp);
4a4d8108
AM
15497+ }
15498+ }
15499+ AuDbg("need_wh %d\n", need_wh);
15500+ err = need_wh;
15501+
4f0767ce 15502+out:
4a4d8108 15503+ return err;
1facf9fc 15504+}
15505+
4a4d8108
AM
15506+/*
15507+ * simple tests for the del-entry operations.
15508+ * following the checks in vfs, plus the parent-child relationship.
15509+ */
15510+int au_may_del(struct dentry *dentry, aufs_bindex_t bindex,
15511+ struct dentry *h_parent, int isdir)
1facf9fc 15512+{
4a4d8108
AM
15513+ int err;
15514+ umode_t h_mode;
15515+ struct dentry *h_dentry, *h_latest;
1308ab2a 15516+ struct inode *h_inode;
1facf9fc 15517+
4a4d8108
AM
15518+ h_dentry = au_h_dptr(dentry, bindex);
15519+ h_inode = h_dentry->d_inode;
15520+ if (dentry->d_inode) {
15521+ err = -ENOENT;
15522+ if (unlikely(!h_inode || !h_inode->i_nlink))
15523+ goto out;
1facf9fc 15524+
4a4d8108
AM
15525+ h_mode = h_inode->i_mode;
15526+ if (!isdir) {
15527+ err = -EISDIR;
15528+ if (unlikely(S_ISDIR(h_mode)))
15529+ goto out;
15530+ } else if (unlikely(!S_ISDIR(h_mode))) {
15531+ err = -ENOTDIR;
15532+ goto out;
15533+ }
15534+ } else {
15535+ /* rename(2) case */
15536+ err = -EIO;
15537+ if (unlikely(h_inode))
15538+ goto out;
15539+ }
1facf9fc 15540+
4a4d8108
AM
15541+ err = -ENOENT;
15542+ /* expected parent dir is locked */
15543+ if (unlikely(h_parent != h_dentry->d_parent))
15544+ goto out;
15545+ err = 0;
15546+
15547+ /*
15548+ * rmdir a dir may break the consistency on some filesystem.
15549+ * let's try heavy test.
15550+ */
15551+ err = -EACCES;
15552+ if (unlikely(au_test_h_perm(h_parent->d_inode, MAY_EXEC | MAY_WRITE)))
15553+ goto out;
15554+
15555+ h_latest = au_sio_lkup_one(&dentry->d_name, h_parent,
15556+ au_sbr(dentry->d_sb, bindex));
15557+ err = -EIO;
15558+ if (IS_ERR(h_latest))
15559+ goto out;
15560+ if (h_latest == h_dentry)
15561+ err = 0;
15562+ dput(h_latest);
15563+
4f0767ce 15564+out:
4a4d8108 15565+ return err;
1308ab2a 15566+}
1facf9fc 15567+
4a4d8108
AM
15568+/*
15569+ * decide the branch where we operate for @dentry. the branch index will be set
15570+ * @rbcpup. after diciding it, 'pin' it and store the timestamps of the parent
15571+ * dir for reverting.
15572+ * when a new whiteout is necessary, create it.
15573+ */
15574+static struct dentry*
15575+lock_hdir_create_wh(struct dentry *dentry, int isdir, aufs_bindex_t *rbcpup,
15576+ struct au_dtime *dt, struct au_pin *pin)
1308ab2a 15577+{
4a4d8108
AM
15578+ struct dentry *wh_dentry;
15579+ struct super_block *sb;
15580+ struct path h_path;
15581+ int err, need_wh;
15582+ unsigned int udba;
15583+ aufs_bindex_t bcpup;
dece6358 15584+
4a4d8108
AM
15585+ need_wh = au_wr_dir_need_wh(dentry, isdir, rbcpup);
15586+ wh_dentry = ERR_PTR(need_wh);
15587+ if (unlikely(need_wh < 0))
15588+ goto out;
15589+
15590+ sb = dentry->d_sb;
15591+ udba = au_opt_udba(sb);
15592+ bcpup = *rbcpup;
15593+ err = au_pin(pin, dentry, bcpup, udba,
15594+ AuPin_DI_LOCKED | AuPin_MNT_WRITE);
15595+ wh_dentry = ERR_PTR(err);
15596+ if (unlikely(err))
15597+ goto out;
15598+
15599+ h_path.dentry = au_pinned_h_parent(pin);
15600+ if (udba != AuOpt_UDBA_NONE
15601+ && au_dbstart(dentry) == bcpup) {
15602+ err = au_may_del(dentry, bcpup, h_path.dentry, isdir);
15603+ wh_dentry = ERR_PTR(err);
15604+ if (unlikely(err))
15605+ goto out_unpin;
15606+ }
15607+
15608+ h_path.mnt = au_sbr_mnt(sb, bcpup);
15609+ au_dtime_store(dt, au_pinned_parent(pin), &h_path);
15610+ wh_dentry = NULL;
15611+ if (!need_wh)
15612+ goto out; /* success, no need to create whiteout */
15613+
15614+ wh_dentry = au_wh_create(dentry, bcpup, h_path.dentry);
15615+ if (IS_ERR(wh_dentry))
15616+ goto out_unpin;
15617+
15618+ /* returns with the parent is locked and wh_dentry is dget-ed */
15619+ goto out; /* success */
15620+
4f0767ce 15621+out_unpin:
4a4d8108 15622+ au_unpin(pin);
4f0767ce 15623+out:
4a4d8108 15624+ return wh_dentry;
1facf9fc 15625+}
15626+
4a4d8108
AM
15627+/*
15628+ * when removing a dir, rename it to a unique temporary whiteout-ed name first
15629+ * in order to be revertible and save time for removing many child whiteouts
15630+ * under the dir.
15631+ * returns 1 when there are too many child whiteout and caller should remove
15632+ * them asynchronously. returns 0 when the number of children is enough small to
15633+ * remove now or the branch fs is a remote fs.
15634+ * otherwise return an error.
15635+ */
15636+static int renwh_and_rmdir(struct dentry *dentry, aufs_bindex_t bindex,
15637+ struct au_nhash *whlist, struct inode *dir)
1facf9fc 15638+{
4a4d8108
AM
15639+ int rmdir_later, err, dirwh;
15640+ struct dentry *h_dentry;
15641+ struct super_block *sb;
15642+
15643+ sb = dentry->d_sb;
15644+ SiMustAnyLock(sb);
15645+ h_dentry = au_h_dptr(dentry, bindex);
15646+ err = au_whtmp_ren(h_dentry, au_sbr(sb, bindex));
15647+ if (unlikely(err))
15648+ goto out;
15649+
15650+ /* stop monitoring */
15651+ au_hn_free(au_hi(dentry->d_inode, bindex));
15652+
15653+ if (!au_test_fs_remote(h_dentry->d_sb)) {
15654+ dirwh = au_sbi(sb)->si_dirwh;
15655+ rmdir_later = (dirwh <= 1);
15656+ if (!rmdir_later)
15657+ rmdir_later = au_nhash_test_longer_wh(whlist, bindex,
15658+ dirwh);
15659+ if (rmdir_later)
15660+ return rmdir_later;
15661+ }
1facf9fc 15662+
4a4d8108
AM
15663+ err = au_whtmp_rmdir(dir, bindex, h_dentry, whlist);
15664+ if (unlikely(err)) {
15665+ AuIOErr("rmdir %.*s, b%d failed, %d. ignored\n",
15666+ AuDLNPair(h_dentry), bindex, err);
15667+ err = 0;
15668+ }
dece6358 15669+
4f0767ce 15670+out:
4a4d8108
AM
15671+ AuTraceErr(err);
15672+ return err;
15673+}
1308ab2a 15674+
4a4d8108
AM
15675+/*
15676+ * final procedure for deleting a entry.
15677+ * maintain dentry and iattr.
15678+ */
15679+static void epilog(struct inode *dir, struct dentry *dentry,
15680+ aufs_bindex_t bindex)
15681+{
15682+ struct inode *inode;
1308ab2a 15683+
4a4d8108
AM
15684+ inode = dentry->d_inode;
15685+ d_drop(dentry);
15686+ inode->i_ctime = dir->i_ctime;
1308ab2a 15687+
4a4d8108
AM
15688+ if (au_ibstart(dir) == bindex)
15689+ au_cpup_attr_timesizes(dir);
15690+ dir->i_version++;
1facf9fc 15691+}
15692+
4a4d8108
AM
15693+/*
15694+ * when an error happened, remove the created whiteout and revert everything.
15695+ */
7f207e10
AM
15696+static int do_revert(int err, struct inode *dir, aufs_bindex_t bindex,
15697+ aufs_bindex_t bwh, struct dentry *wh_dentry,
15698+ struct dentry *dentry, struct au_dtime *dt)
1facf9fc 15699+{
4a4d8108
AM
15700+ int rerr;
15701+ struct path h_path = {
15702+ .dentry = wh_dentry,
7f207e10 15703+ .mnt = au_sbr_mnt(dir->i_sb, bindex)
4a4d8108 15704+ };
dece6358 15705+
7f207e10 15706+ rerr = au_wh_unlink_dentry(au_h_iptr(dir, bindex), &h_path, dentry);
4a4d8108
AM
15707+ if (!rerr) {
15708+ au_set_dbwh(dentry, bwh);
15709+ au_dtime_revert(dt);
15710+ return 0;
15711+ }
dece6358 15712+
4a4d8108
AM
15713+ AuIOErr("%.*s reverting whiteout failed(%d, %d)\n",
15714+ AuDLNPair(dentry), err, rerr);
15715+ return -EIO;
1facf9fc 15716+}
15717+
4a4d8108 15718+/* ---------------------------------------------------------------------- */
1facf9fc 15719+
4a4d8108 15720+int aufs_unlink(struct inode *dir, struct dentry *dentry)
1308ab2a 15721+{
4a4d8108
AM
15722+ int err;
15723+ aufs_bindex_t bwh, bindex, bstart;
15724+ struct au_dtime dt;
15725+ struct au_pin pin;
15726+ struct path h_path;
15727+ struct inode *inode, *h_dir;
15728+ struct dentry *parent, *wh_dentry;
1facf9fc 15729+
4a4d8108 15730+ IMustLock(dir);
027c5e7a
AM
15731+
15732+ err = aufs_read_lock(dentry, AuLock_DW | AuLock_GEN);
15733+ if (unlikely(err))
15734+ goto out;
15735+ err = au_d_hashed_positive(dentry);
15736+ if (unlikely(err))
15737+ goto out_unlock;
4a4d8108 15738+ inode = dentry->d_inode;
4a4d8108 15739+ IMustLock(inode);
027c5e7a
AM
15740+ err = -EISDIR;
15741+ if (unlikely(S_ISDIR(inode->i_mode)))
15742+ goto out_unlock; /* possible? */
1facf9fc 15743+
4a4d8108
AM
15744+ bstart = au_dbstart(dentry);
15745+ bwh = au_dbwh(dentry);
15746+ bindex = -1;
027c5e7a
AM
15747+ parent = dentry->d_parent; /* dir inode is locked */
15748+ di_write_lock_parent(parent);
4a4d8108
AM
15749+ wh_dentry = lock_hdir_create_wh(dentry, /*isdir*/0, &bindex, &dt, &pin);
15750+ err = PTR_ERR(wh_dentry);
15751+ if (IS_ERR(wh_dentry))
027c5e7a 15752+ goto out_parent;
1facf9fc 15753+
4a4d8108
AM
15754+ h_path.mnt = au_sbr_mnt(dentry->d_sb, bstart);
15755+ h_path.dentry = au_h_dptr(dentry, bstart);
15756+ dget(h_path.dentry);
15757+ if (bindex == bstart) {
15758+ h_dir = au_pinned_h_dir(&pin);
15759+ err = vfsub_unlink(h_dir, &h_path, /*force*/0);
15760+ } else {
15761+ /* dir inode is locked */
15762+ h_dir = wh_dentry->d_parent->d_inode;
15763+ IMustLock(h_dir);
15764+ err = 0;
15765+ }
dece6358 15766+
4a4d8108 15767+ if (!err) {
7f207e10 15768+ vfsub_drop_nlink(inode);
4a4d8108
AM
15769+ epilog(dir, dentry, bindex);
15770+
15771+ /* update target timestamps */
15772+ if (bindex == bstart) {
15773+ vfsub_update_h_iattr(&h_path, /*did*/NULL); /*ignore*/
15774+ inode->i_ctime = h_path.dentry->d_inode->i_ctime;
15775+ } else
15776+ /* todo: this timestamp may be reverted later */
15777+ inode->i_ctime = h_dir->i_ctime;
027c5e7a 15778+ goto out_unpin; /* success */
1facf9fc 15779+ }
15780+
4a4d8108
AM
15781+ /* revert */
15782+ if (wh_dentry) {
15783+ int rerr;
15784+
7f207e10 15785+ rerr = do_revert(err, dir, bindex, bwh, wh_dentry, dentry, &dt);
4a4d8108
AM
15786+ if (rerr)
15787+ err = rerr;
dece6358 15788+ }
1facf9fc 15789+
027c5e7a 15790+out_unpin:
4a4d8108
AM
15791+ au_unpin(&pin);
15792+ dput(wh_dentry);
15793+ dput(h_path.dentry);
027c5e7a 15794+out_parent:
4a4d8108 15795+ di_write_unlock(parent);
027c5e7a 15796+out_unlock:
4a4d8108 15797+ aufs_read_unlock(dentry, AuLock_DW);
027c5e7a 15798+out:
4a4d8108 15799+ return err;
dece6358
AM
15800+}
15801+
4a4d8108 15802+int aufs_rmdir(struct inode *dir, struct dentry *dentry)
1308ab2a 15803+{
4a4d8108
AM
15804+ int err, rmdir_later;
15805+ aufs_bindex_t bwh, bindex, bstart;
15806+ struct au_dtime dt;
15807+ struct au_pin pin;
15808+ struct inode *inode;
15809+ struct dentry *parent, *wh_dentry, *h_dentry;
15810+ struct au_whtmp_rmdir *args;
1facf9fc 15811+
4a4d8108 15812+ IMustLock(dir);
027c5e7a
AM
15813+
15814+ err = aufs_read_lock(dentry, AuLock_DW | AuLock_FLUSH | AuLock_GEN);
15815+ if (unlikely(err))
4a4d8108 15816+ goto out;
027c5e7a
AM
15817+
15818+ /* VFS already unhashes it */
15819+ inode = dentry->d_inode;
15820+ err = -ENOENT;
15821+ if (unlikely(!inode || !inode->i_nlink
15822+ || IS_DEADDIR(inode)))
15823+ goto out_unlock;
4a4d8108 15824+ IMustLock(inode);
027c5e7a
AM
15825+ err = -ENOTDIR;
15826+ if (unlikely(!S_ISDIR(inode->i_mode)))
15827+ goto out_unlock; /* possible? */
dece6358 15828+
4a4d8108
AM
15829+ err = -ENOMEM;
15830+ args = au_whtmp_rmdir_alloc(dir->i_sb, GFP_NOFS);
15831+ if (unlikely(!args))
15832+ goto out_unlock;
dece6358 15833+
4a4d8108
AM
15834+ parent = dentry->d_parent; /* dir inode is locked */
15835+ di_write_lock_parent(parent);
15836+ err = au_test_empty(dentry, &args->whlist);
15837+ if (unlikely(err))
027c5e7a 15838+ goto out_parent;
1facf9fc 15839+
4a4d8108
AM
15840+ bstart = au_dbstart(dentry);
15841+ bwh = au_dbwh(dentry);
15842+ bindex = -1;
15843+ wh_dentry = lock_hdir_create_wh(dentry, /*isdir*/1, &bindex, &dt, &pin);
15844+ err = PTR_ERR(wh_dentry);
15845+ if (IS_ERR(wh_dentry))
027c5e7a 15846+ goto out_parent;
1facf9fc 15847+
4a4d8108
AM
15848+ h_dentry = au_h_dptr(dentry, bstart);
15849+ dget(h_dentry);
15850+ rmdir_later = 0;
15851+ if (bindex == bstart) {
15852+ err = renwh_and_rmdir(dentry, bstart, &args->whlist, dir);
15853+ if (err > 0) {
15854+ rmdir_later = err;
15855+ err = 0;
15856+ }
15857+ } else {
15858+ /* stop monitoring */
15859+ au_hn_free(au_hi(inode, bstart));
15860+
15861+ /* dir inode is locked */
15862+ IMustLock(wh_dentry->d_parent->d_inode);
1facf9fc 15863+ err = 0;
15864+ }
15865+
4a4d8108 15866+ if (!err) {
027c5e7a 15867+ vfsub_dead_dir(inode);
4a4d8108
AM
15868+ au_set_dbdiropq(dentry, -1);
15869+ epilog(dir, dentry, bindex);
1308ab2a 15870+
4a4d8108
AM
15871+ if (rmdir_later) {
15872+ au_whtmp_kick_rmdir(dir, bstart, h_dentry, args);
15873+ args = NULL;
15874+ }
1308ab2a 15875+
4a4d8108 15876+ goto out_unpin; /* success */
1facf9fc 15877+ }
15878+
4a4d8108
AM
15879+ /* revert */
15880+ AuLabel(revert);
15881+ if (wh_dentry) {
15882+ int rerr;
1308ab2a 15883+
7f207e10 15884+ rerr = do_revert(err, dir, bindex, bwh, wh_dentry, dentry, &dt);
4a4d8108
AM
15885+ if (rerr)
15886+ err = rerr;
1facf9fc 15887+ }
15888+
4f0767ce 15889+out_unpin:
4a4d8108
AM
15890+ au_unpin(&pin);
15891+ dput(wh_dentry);
15892+ dput(h_dentry);
027c5e7a 15893+out_parent:
4a4d8108
AM
15894+ di_write_unlock(parent);
15895+ if (args)
15896+ au_whtmp_rmdir_free(args);
4f0767ce 15897+out_unlock:
4a4d8108 15898+ aufs_read_unlock(dentry, AuLock_DW);
4f0767ce 15899+out:
4a4d8108
AM
15900+ AuTraceErr(err);
15901+ return err;
dece6358 15902+}
7f207e10
AM
15903diff -urN /usr/share/empty/fs/aufs/i_op_ren.c linux/fs/aufs/i_op_ren.c
15904--- /usr/share/empty/fs/aufs/i_op_ren.c 1970-01-01 01:00:00.000000000 +0100
2cbb1c4b 15905+++ linux/fs/aufs/i_op_ren.c 2011-07-11 11:34:24.075331673 +0200
027c5e7a 15906@@ -0,0 +1,1017 @@
1facf9fc 15907+/*
027c5e7a 15908+ * Copyright (C) 2005-2011 Junjiro R. Okajima
1facf9fc 15909+ *
15910+ * This program, aufs is free software; you can redistribute it and/or modify
15911+ * it under the terms of the GNU General Public License as published by
15912+ * the Free Software Foundation; either version 2 of the License, or
15913+ * (at your option) any later version.
dece6358
AM
15914+ *
15915+ * This program is distributed in the hope that it will be useful,
15916+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
15917+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15918+ * GNU General Public License for more details.
15919+ *
15920+ * You should have received a copy of the GNU General Public License
15921+ * along with this program; if not, write to the Free Software
15922+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 15923+ */
15924+
15925+/*
4a4d8108
AM
15926+ * inode operation (rename entry)
15927+ * todo: this is crazy monster
1facf9fc 15928+ */
15929+
15930+#include "aufs.h"
15931+
4a4d8108
AM
15932+enum { AuSRC, AuDST, AuSrcDst };
15933+enum { AuPARENT, AuCHILD, AuParentChild };
1facf9fc 15934+
4a4d8108
AM
15935+#define AuRen_ISDIR 1
15936+#define AuRen_ISSAMEDIR (1 << 1)
15937+#define AuRen_WHSRC (1 << 2)
15938+#define AuRen_WHDST (1 << 3)
15939+#define AuRen_MNT_WRITE (1 << 4)
15940+#define AuRen_DT_DSTDIR (1 << 5)
15941+#define AuRen_DIROPQ (1 << 6)
15942+#define AuRen_CPUP (1 << 7)
15943+#define au_ftest_ren(flags, name) ((flags) & AuRen_##name)
7f207e10
AM
15944+#define au_fset_ren(flags, name) \
15945+ do { (flags) |= AuRen_##name; } while (0)
15946+#define au_fclr_ren(flags, name) \
15947+ do { (flags) &= ~AuRen_##name; } while (0)
1facf9fc 15948+
4a4d8108
AM
15949+struct au_ren_args {
15950+ struct {
15951+ struct dentry *dentry, *h_dentry, *parent, *h_parent,
15952+ *wh_dentry;
15953+ struct inode *dir, *inode;
15954+ struct au_hinode *hdir;
15955+ struct au_dtime dt[AuParentChild];
15956+ aufs_bindex_t bstart;
15957+ } sd[AuSrcDst];
1facf9fc 15958+
4a4d8108
AM
15959+#define src_dentry sd[AuSRC].dentry
15960+#define src_dir sd[AuSRC].dir
15961+#define src_inode sd[AuSRC].inode
15962+#define src_h_dentry sd[AuSRC].h_dentry
15963+#define src_parent sd[AuSRC].parent
15964+#define src_h_parent sd[AuSRC].h_parent
15965+#define src_wh_dentry sd[AuSRC].wh_dentry
15966+#define src_hdir sd[AuSRC].hdir
15967+#define src_h_dir sd[AuSRC].hdir->hi_inode
15968+#define src_dt sd[AuSRC].dt
15969+#define src_bstart sd[AuSRC].bstart
1facf9fc 15970+
4a4d8108
AM
15971+#define dst_dentry sd[AuDST].dentry
15972+#define dst_dir sd[AuDST].dir
15973+#define dst_inode sd[AuDST].inode
15974+#define dst_h_dentry sd[AuDST].h_dentry
15975+#define dst_parent sd[AuDST].parent
15976+#define dst_h_parent sd[AuDST].h_parent
15977+#define dst_wh_dentry sd[AuDST].wh_dentry
15978+#define dst_hdir sd[AuDST].hdir
15979+#define dst_h_dir sd[AuDST].hdir->hi_inode
15980+#define dst_dt sd[AuDST].dt
15981+#define dst_bstart sd[AuDST].bstart
15982+
15983+ struct dentry *h_trap;
15984+ struct au_branch *br;
15985+ struct au_hinode *src_hinode;
15986+ struct path h_path;
15987+ struct au_nhash whlist;
027c5e7a 15988+ aufs_bindex_t btgt, src_bwh, src_bdiropq;
1facf9fc 15989+
1308ab2a 15990+ unsigned int flags;
1facf9fc 15991+
4a4d8108
AM
15992+ struct au_whtmp_rmdir *thargs;
15993+ struct dentry *h_dst;
15994+};
1308ab2a 15995+
4a4d8108 15996+/* ---------------------------------------------------------------------- */
1308ab2a 15997+
4a4d8108
AM
15998+/*
15999+ * functions for reverting.
16000+ * when an error happened in a single rename systemcall, we should revert
16001+ * everything as if nothing happend.
16002+ * we don't need to revert the copied-up/down the parent dir since they are
16003+ * harmless.
16004+ */
1facf9fc 16005+
4a4d8108
AM
16006+#define RevertFailure(fmt, ...) do { \
16007+ AuIOErr("revert failure: " fmt " (%d, %d)\n", \
16008+ ##__VA_ARGS__, err, rerr); \
16009+ err = -EIO; \
16010+} while (0)
1facf9fc 16011+
4a4d8108 16012+static void au_ren_rev_diropq(int err, struct au_ren_args *a)
1facf9fc 16013+{
4a4d8108 16014+ int rerr;
1facf9fc 16015+
4a4d8108
AM
16016+ au_hn_imtx_lock_nested(a->src_hinode, AuLsc_I_CHILD);
16017+ rerr = au_diropq_remove(a->src_dentry, a->btgt);
16018+ au_hn_imtx_unlock(a->src_hinode);
027c5e7a 16019+ au_set_dbdiropq(a->src_dentry, a->src_bdiropq);
4a4d8108
AM
16020+ if (rerr)
16021+ RevertFailure("remove diropq %.*s", AuDLNPair(a->src_dentry));
16022+}
1facf9fc 16023+
4a4d8108
AM
16024+static void au_ren_rev_rename(int err, struct au_ren_args *a)
16025+{
16026+ int rerr;
1facf9fc 16027+
4a4d8108
AM
16028+ a->h_path.dentry = au_lkup_one(&a->src_dentry->d_name, a->src_h_parent,
16029+ a->br, /*nd*/NULL);
16030+ rerr = PTR_ERR(a->h_path.dentry);
16031+ if (IS_ERR(a->h_path.dentry)) {
16032+ RevertFailure("au_lkup_one %.*s", AuDLNPair(a->src_dentry));
16033+ return;
1facf9fc 16034+ }
16035+
4a4d8108
AM
16036+ rerr = vfsub_rename(a->dst_h_dir,
16037+ au_h_dptr(a->src_dentry, a->btgt),
16038+ a->src_h_dir, &a->h_path);
16039+ d_drop(a->h_path.dentry);
16040+ dput(a->h_path.dentry);
16041+ /* au_set_h_dptr(a->src_dentry, a->btgt, NULL); */
16042+ if (rerr)
16043+ RevertFailure("rename %.*s", AuDLNPair(a->src_dentry));
1facf9fc 16044+}
16045+
4a4d8108 16046+static void au_ren_rev_cpup(int err, struct au_ren_args *a)
1facf9fc 16047+{
4a4d8108 16048+ int rerr;
1facf9fc 16049+
4a4d8108
AM
16050+ a->h_path.dentry = a->dst_h_dentry;
16051+ rerr = vfsub_unlink(a->dst_h_dir, &a->h_path, /*force*/0);
16052+ au_set_h_dptr(a->src_dentry, a->btgt, NULL);
16053+ au_set_dbstart(a->src_dentry, a->src_bstart);
16054+ if (rerr)
16055+ RevertFailure("unlink %.*s", AuDLNPair(a->dst_h_dentry));
1facf9fc 16056+}
16057+
4a4d8108 16058+static void au_ren_rev_whtmp(int err, struct au_ren_args *a)
1facf9fc 16059+{
4a4d8108 16060+ int rerr;
dece6358 16061+
4a4d8108
AM
16062+ a->h_path.dentry = au_lkup_one(&a->dst_dentry->d_name, a->dst_h_parent,
16063+ a->br, /*nd*/NULL);
16064+ rerr = PTR_ERR(a->h_path.dentry);
16065+ if (IS_ERR(a->h_path.dentry)) {
16066+ RevertFailure("lookup %.*s", AuDLNPair(a->dst_dentry));
16067+ return;
16068+ }
16069+ if (a->h_path.dentry->d_inode) {
16070+ d_drop(a->h_path.dentry);
16071+ dput(a->h_path.dentry);
16072+ return;
dece6358
AM
16073+ }
16074+
4a4d8108
AM
16075+ rerr = vfsub_rename(a->dst_h_dir, a->h_dst, a->dst_h_dir, &a->h_path);
16076+ d_drop(a->h_path.dentry);
16077+ dput(a->h_path.dentry);
16078+ if (!rerr)
16079+ au_set_h_dptr(a->dst_dentry, a->btgt, dget(a->h_dst));
16080+ else
16081+ RevertFailure("rename %.*s", AuDLNPair(a->h_dst));
16082+}
1308ab2a 16083+
4a4d8108
AM
16084+static void au_ren_rev_whsrc(int err, struct au_ren_args *a)
16085+{
16086+ int rerr;
1308ab2a 16087+
4a4d8108
AM
16088+ a->h_path.dentry = a->src_wh_dentry;
16089+ rerr = au_wh_unlink_dentry(a->src_h_dir, &a->h_path, a->src_dentry);
027c5e7a 16090+ au_set_dbwh(a->src_dentry, a->src_bwh);
4a4d8108
AM
16091+ if (rerr)
16092+ RevertFailure("unlink %.*s", AuDLNPair(a->src_wh_dentry));
16093+}
4a4d8108 16094+#undef RevertFailure
1facf9fc 16095+
1308ab2a 16096+/* ---------------------------------------------------------------------- */
16097+
4a4d8108
AM
16098+/*
16099+ * when we have to copyup the renaming entry, do it with the rename-target name
16100+ * in order to minimize the cost (the later actual rename is unnecessary).
16101+ * otherwise rename it on the target branch.
16102+ */
16103+static int au_ren_or_cpup(struct au_ren_args *a)
1facf9fc 16104+{
dece6358 16105+ int err;
4a4d8108 16106+ struct dentry *d;
1facf9fc 16107+
4a4d8108
AM
16108+ d = a->src_dentry;
16109+ if (au_dbstart(d) == a->btgt) {
16110+ a->h_path.dentry = a->dst_h_dentry;
16111+ if (au_ftest_ren(a->flags, DIROPQ)
16112+ && au_dbdiropq(d) == a->btgt)
16113+ au_fclr_ren(a->flags, DIROPQ);
16114+ AuDebugOn(au_dbstart(d) != a->btgt);
16115+ err = vfsub_rename(a->src_h_dir, au_h_dptr(d, a->btgt),
16116+ a->dst_h_dir, &a->h_path);
16117+ } else {
16118+ struct mutex *h_mtx = &a->src_h_dentry->d_inode->i_mutex;
16119+ struct file *h_file;
1308ab2a 16120+
4a4d8108
AM
16121+ au_fset_ren(a->flags, CPUP);
16122+ mutex_lock_nested(h_mtx, AuLsc_I_CHILD);
16123+ au_set_dbstart(d, a->btgt);
16124+ au_set_h_dptr(d, a->btgt, dget(a->dst_h_dentry));
16125+ h_file = au_h_open_pre(d, a->src_bstart);
16126+ if (IS_ERR(h_file)) {
16127+ err = PTR_ERR(h_file);
16128+ h_file = NULL;
16129+ } else
16130+ err = au_sio_cpup_single(d, a->btgt, a->src_bstart, -1,
16131+ !AuCpup_DTIME, a->dst_parent);
16132+ mutex_unlock(h_mtx);
16133+ au_h_open_post(d, a->src_bstart, h_file);
16134+ if (!err) {
16135+ d = a->dst_dentry;
16136+ au_set_h_dptr(d, a->btgt, NULL);
16137+ au_update_dbstart(d);
16138+ } else {
16139+ au_set_h_dptr(d, a->btgt, NULL);
16140+ au_set_dbstart(d, a->src_bstart);
16141+ }
1308ab2a 16142+ }
027c5e7a
AM
16143+ if (!err && a->h_dst)
16144+ /* it will be set to dinfo later */
16145+ dget(a->h_dst);
1facf9fc 16146+
dece6358
AM
16147+ return err;
16148+}
1facf9fc 16149+
4a4d8108
AM
16150+/* cf. aufs_rmdir() */
16151+static int au_ren_del_whtmp(struct au_ren_args *a)
dece6358 16152+{
4a4d8108
AM
16153+ int err;
16154+ struct inode *dir;
1facf9fc 16155+
4a4d8108
AM
16156+ dir = a->dst_dir;
16157+ SiMustAnyLock(dir->i_sb);
16158+ if (!au_nhash_test_longer_wh(&a->whlist, a->btgt,
16159+ au_sbi(dir->i_sb)->si_dirwh)
16160+ || au_test_fs_remote(a->h_dst->d_sb)) {
16161+ err = au_whtmp_rmdir(dir, a->btgt, a->h_dst, &a->whlist);
16162+ if (unlikely(err))
16163+ pr_warning("failed removing whtmp dir %.*s (%d), "
16164+ "ignored.\n", AuDLNPair(a->h_dst), err);
16165+ } else {
16166+ au_nhash_wh_free(&a->thargs->whlist);
16167+ a->thargs->whlist = a->whlist;
16168+ a->whlist.nh_num = 0;
16169+ au_whtmp_kick_rmdir(dir, a->btgt, a->h_dst, a->thargs);
16170+ dput(a->h_dst);
16171+ a->thargs = NULL;
16172+ }
16173+
16174+ return 0;
1308ab2a 16175+}
1facf9fc 16176+
4a4d8108
AM
16177+/* make it 'opaque' dir. */
16178+static int au_ren_diropq(struct au_ren_args *a)
16179+{
16180+ int err;
16181+ struct dentry *diropq;
1facf9fc 16182+
4a4d8108 16183+ err = 0;
027c5e7a 16184+ a->src_bdiropq = au_dbdiropq(a->src_dentry);
4a4d8108
AM
16185+ a->src_hinode = au_hi(a->src_inode, a->btgt);
16186+ au_hn_imtx_lock_nested(a->src_hinode, AuLsc_I_CHILD);
16187+ diropq = au_diropq_create(a->src_dentry, a->btgt);
16188+ au_hn_imtx_unlock(a->src_hinode);
16189+ if (IS_ERR(diropq))
16190+ err = PTR_ERR(diropq);
16191+ dput(diropq);
1facf9fc 16192+
4a4d8108
AM
16193+ return err;
16194+}
1facf9fc 16195+
4a4d8108
AM
16196+static int do_rename(struct au_ren_args *a)
16197+{
16198+ int err;
16199+ struct dentry *d, *h_d;
1facf9fc 16200+
4a4d8108
AM
16201+ /* prepare workqueue args for asynchronous rmdir */
16202+ h_d = a->dst_h_dentry;
16203+ if (au_ftest_ren(a->flags, ISDIR) && h_d->d_inode) {
16204+ err = -ENOMEM;
16205+ a->thargs = au_whtmp_rmdir_alloc(a->src_dentry->d_sb, GFP_NOFS);
16206+ if (unlikely(!a->thargs))
16207+ goto out;
16208+ a->h_dst = dget(h_d);
16209+ }
1facf9fc 16210+
4a4d8108
AM
16211+ /* create whiteout for src_dentry */
16212+ if (au_ftest_ren(a->flags, WHSRC)) {
027c5e7a
AM
16213+ a->src_bwh = au_dbwh(a->src_dentry);
16214+ AuDebugOn(a->src_bwh >= 0);
4a4d8108
AM
16215+ a->src_wh_dentry
16216+ = au_wh_create(a->src_dentry, a->btgt, a->src_h_parent);
16217+ err = PTR_ERR(a->src_wh_dentry);
16218+ if (IS_ERR(a->src_wh_dentry))
16219+ goto out_thargs;
16220+ }
1facf9fc 16221+
4a4d8108
AM
16222+ /* lookup whiteout for dentry */
16223+ if (au_ftest_ren(a->flags, WHDST)) {
16224+ h_d = au_wh_lkup(a->dst_h_parent, &a->dst_dentry->d_name,
16225+ a->br);
16226+ err = PTR_ERR(h_d);
16227+ if (IS_ERR(h_d))
16228+ goto out_whsrc;
16229+ if (!h_d->d_inode)
16230+ dput(h_d);
16231+ else
16232+ a->dst_wh_dentry = h_d;
16233+ }
1facf9fc 16234+
4a4d8108
AM
16235+ /* rename dentry to tmpwh */
16236+ if (a->thargs) {
16237+ err = au_whtmp_ren(a->dst_h_dentry, a->br);
16238+ if (unlikely(err))
16239+ goto out_whdst;
dece6358 16240+
4a4d8108
AM
16241+ d = a->dst_dentry;
16242+ au_set_h_dptr(d, a->btgt, NULL);
16243+ err = au_lkup_neg(d, a->btgt);
16244+ if (unlikely(err))
16245+ goto out_whtmp;
16246+ a->dst_h_dentry = au_h_dptr(d, a->btgt);
16247+ }
1facf9fc 16248+
4a4d8108
AM
16249+ /* cpup src */
16250+ if (a->dst_h_dentry->d_inode && a->src_bstart != a->btgt) {
16251+ struct mutex *h_mtx = &a->src_h_dentry->d_inode->i_mutex;
16252+ struct file *h_file;
1facf9fc 16253+
4a4d8108
AM
16254+ mutex_lock_nested(h_mtx, AuLsc_I_CHILD);
16255+ AuDebugOn(au_dbstart(a->src_dentry) != a->src_bstart);
16256+ h_file = au_h_open_pre(a->src_dentry, a->src_bstart);
16257+ if (IS_ERR(h_file)) {
16258+ err = PTR_ERR(h_file);
16259+ h_file = NULL;
16260+ } else
16261+ err = au_sio_cpup_simple(a->src_dentry, a->btgt, -1,
16262+ !AuCpup_DTIME);
16263+ mutex_unlock(h_mtx);
16264+ au_h_open_post(a->src_dentry, a->src_bstart, h_file);
16265+ if (unlikely(err))
16266+ goto out_whtmp;
16267+ }
1facf9fc 16268+
4a4d8108
AM
16269+ /* rename by vfs_rename or cpup */
16270+ d = a->dst_dentry;
16271+ if (au_ftest_ren(a->flags, ISDIR)
16272+ && (a->dst_wh_dentry
16273+ || au_dbdiropq(d) == a->btgt
16274+ /* hide the lower to keep xino */
16275+ || a->btgt < au_dbend(d)
16276+ || au_opt_test(au_mntflags(d->d_sb), ALWAYS_DIROPQ)))
16277+ au_fset_ren(a->flags, DIROPQ);
16278+ err = au_ren_or_cpup(a);
16279+ if (unlikely(err))
16280+ /* leave the copied-up one */
16281+ goto out_whtmp;
1308ab2a 16282+
4a4d8108
AM
16283+ /* make dir opaque */
16284+ if (au_ftest_ren(a->flags, DIROPQ)) {
16285+ err = au_ren_diropq(a);
16286+ if (unlikely(err))
16287+ goto out_rename;
16288+ }
1308ab2a 16289+
4a4d8108
AM
16290+ /* update target timestamps */
16291+ AuDebugOn(au_dbstart(a->src_dentry) != a->btgt);
16292+ a->h_path.dentry = au_h_dptr(a->src_dentry, a->btgt);
16293+ vfsub_update_h_iattr(&a->h_path, /*did*/NULL); /*ignore*/
16294+ a->src_inode->i_ctime = a->h_path.dentry->d_inode->i_ctime;
1facf9fc 16295+
4a4d8108
AM
16296+ /* remove whiteout for dentry */
16297+ if (a->dst_wh_dentry) {
16298+ a->h_path.dentry = a->dst_wh_dentry;
16299+ err = au_wh_unlink_dentry(a->dst_h_dir, &a->h_path,
16300+ a->dst_dentry);
16301+ if (unlikely(err))
16302+ goto out_diropq;
16303+ }
1facf9fc 16304+
4a4d8108
AM
16305+ /* remove whtmp */
16306+ if (a->thargs)
16307+ au_ren_del_whtmp(a); /* ignore this error */
1308ab2a 16308+
4a4d8108
AM
16309+ err = 0;
16310+ goto out_success;
16311+
4f0767ce 16312+out_diropq:
4a4d8108
AM
16313+ if (au_ftest_ren(a->flags, DIROPQ))
16314+ au_ren_rev_diropq(err, a);
4f0767ce 16315+out_rename:
4a4d8108
AM
16316+ if (!au_ftest_ren(a->flags, CPUP))
16317+ au_ren_rev_rename(err, a);
16318+ else
16319+ au_ren_rev_cpup(err, a);
027c5e7a 16320+ dput(a->h_dst);
4f0767ce 16321+out_whtmp:
4a4d8108
AM
16322+ if (a->thargs)
16323+ au_ren_rev_whtmp(err, a);
4f0767ce 16324+out_whdst:
4a4d8108
AM
16325+ dput(a->dst_wh_dentry);
16326+ a->dst_wh_dentry = NULL;
4f0767ce 16327+out_whsrc:
4a4d8108
AM
16328+ if (a->src_wh_dentry)
16329+ au_ren_rev_whsrc(err, a);
4f0767ce 16330+out_success:
4a4d8108
AM
16331+ dput(a->src_wh_dentry);
16332+ dput(a->dst_wh_dentry);
4f0767ce 16333+out_thargs:
4a4d8108
AM
16334+ if (a->thargs) {
16335+ dput(a->h_dst);
16336+ au_whtmp_rmdir_free(a->thargs);
16337+ a->thargs = NULL;
16338+ }
4f0767ce 16339+out:
4a4d8108 16340+ return err;
dece6358 16341+}
1facf9fc 16342+
1308ab2a 16343+/* ---------------------------------------------------------------------- */
1facf9fc 16344+
4a4d8108
AM
16345+/*
16346+ * test if @dentry dir can be rename destination or not.
16347+ * success means, it is a logically empty dir.
16348+ */
16349+static int may_rename_dstdir(struct dentry *dentry, struct au_nhash *whlist)
1308ab2a 16350+{
4a4d8108 16351+ return au_test_empty(dentry, whlist);
1308ab2a 16352+}
1facf9fc 16353+
4a4d8108
AM
16354+/*
16355+ * test if @dentry dir can be rename source or not.
16356+ * if it can, return 0 and @children is filled.
16357+ * success means,
16358+ * - it is a logically empty dir.
16359+ * - or, it exists on writable branch and has no children including whiteouts
16360+ * on the lower branch.
16361+ */
16362+static int may_rename_srcdir(struct dentry *dentry, aufs_bindex_t btgt)
16363+{
16364+ int err;
16365+ unsigned int rdhash;
16366+ aufs_bindex_t bstart;
1facf9fc 16367+
4a4d8108
AM
16368+ bstart = au_dbstart(dentry);
16369+ if (bstart != btgt) {
16370+ struct au_nhash whlist;
dece6358 16371+
4a4d8108
AM
16372+ SiMustAnyLock(dentry->d_sb);
16373+ rdhash = au_sbi(dentry->d_sb)->si_rdhash;
16374+ if (!rdhash)
16375+ rdhash = au_rdhash_est(au_dir_size(/*file*/NULL,
16376+ dentry));
16377+ err = au_nhash_alloc(&whlist, rdhash, GFP_NOFS);
16378+ if (unlikely(err))
16379+ goto out;
16380+ err = au_test_empty(dentry, &whlist);
16381+ au_nhash_wh_free(&whlist);
16382+ goto out;
16383+ }
dece6358 16384+
4a4d8108
AM
16385+ if (bstart == au_dbtaildir(dentry))
16386+ return 0; /* success */
dece6358 16387+
4a4d8108 16388+ err = au_test_empty_lower(dentry);
1facf9fc 16389+
4f0767ce 16390+out:
4a4d8108
AM
16391+ if (err == -ENOTEMPTY) {
16392+ AuWarn1("renaming dir who has child(ren) on multiple branches,"
16393+ " is not supported\n");
16394+ err = -EXDEV;
16395+ }
16396+ return err;
16397+}
1308ab2a 16398+
4a4d8108
AM
16399+/* side effect: sets whlist and h_dentry */
16400+static int au_ren_may_dir(struct au_ren_args *a)
1308ab2a 16401+{
4a4d8108
AM
16402+ int err;
16403+ unsigned int rdhash;
16404+ struct dentry *d;
1facf9fc 16405+
4a4d8108
AM
16406+ d = a->dst_dentry;
16407+ SiMustAnyLock(d->d_sb);
1facf9fc 16408+
4a4d8108
AM
16409+ err = 0;
16410+ if (au_ftest_ren(a->flags, ISDIR) && a->dst_inode) {
16411+ rdhash = au_sbi(d->d_sb)->si_rdhash;
16412+ if (!rdhash)
16413+ rdhash = au_rdhash_est(au_dir_size(/*file*/NULL, d));
16414+ err = au_nhash_alloc(&a->whlist, rdhash, GFP_NOFS);
16415+ if (unlikely(err))
16416+ goto out;
1308ab2a 16417+
4a4d8108
AM
16418+ au_set_dbstart(d, a->dst_bstart);
16419+ err = may_rename_dstdir(d, &a->whlist);
16420+ au_set_dbstart(d, a->btgt);
16421+ }
16422+ a->dst_h_dentry = au_h_dptr(d, au_dbstart(d));
16423+ if (unlikely(err))
16424+ goto out;
16425+
16426+ d = a->src_dentry;
16427+ a->src_h_dentry = au_h_dptr(d, au_dbstart(d));
16428+ if (au_ftest_ren(a->flags, ISDIR)) {
16429+ err = may_rename_srcdir(d, a->btgt);
16430+ if (unlikely(err)) {
16431+ au_nhash_wh_free(&a->whlist);
16432+ a->whlist.nh_num = 0;
16433+ }
16434+ }
4f0767ce 16435+out:
4a4d8108 16436+ return err;
1facf9fc 16437+}
16438+
4a4d8108 16439+/* ---------------------------------------------------------------------- */
1facf9fc 16440+
4a4d8108
AM
16441+/*
16442+ * simple tests for rename.
16443+ * following the checks in vfs, plus the parent-child relationship.
16444+ */
16445+static int au_may_ren(struct au_ren_args *a)
16446+{
16447+ int err, isdir;
16448+ struct inode *h_inode;
1facf9fc 16449+
4a4d8108
AM
16450+ if (a->src_bstart == a->btgt) {
16451+ err = au_may_del(a->src_dentry, a->btgt, a->src_h_parent,
16452+ au_ftest_ren(a->flags, ISDIR));
16453+ if (unlikely(err))
16454+ goto out;
16455+ err = -EINVAL;
16456+ if (unlikely(a->src_h_dentry == a->h_trap))
16457+ goto out;
16458+ }
1facf9fc 16459+
4a4d8108
AM
16460+ err = 0;
16461+ if (a->dst_bstart != a->btgt)
16462+ goto out;
1facf9fc 16463+
027c5e7a
AM
16464+ err = -ENOTEMPTY;
16465+ if (unlikely(a->dst_h_dentry == a->h_trap))
16466+ goto out;
16467+
4a4d8108
AM
16468+ err = -EIO;
16469+ h_inode = a->dst_h_dentry->d_inode;
16470+ isdir = !!au_ftest_ren(a->flags, ISDIR);
16471+ if (!a->dst_dentry->d_inode) {
16472+ if (unlikely(h_inode))
16473+ goto out;
16474+ err = au_may_add(a->dst_dentry, a->btgt, a->dst_h_parent,
16475+ isdir);
16476+ } else {
16477+ if (unlikely(!h_inode || !h_inode->i_nlink))
16478+ goto out;
16479+ err = au_may_del(a->dst_dentry, a->btgt, a->dst_h_parent,
16480+ isdir);
16481+ if (unlikely(err))
16482+ goto out;
4a4d8108 16483+ }
1facf9fc 16484+
4f0767ce 16485+out:
4a4d8108
AM
16486+ if (unlikely(err == -ENOENT || err == -EEXIST))
16487+ err = -EIO;
16488+ AuTraceErr(err);
16489+ return err;
16490+}
1facf9fc 16491+
1308ab2a 16492+/* ---------------------------------------------------------------------- */
1facf9fc 16493+
4a4d8108
AM
16494+/*
16495+ * locking order
16496+ * (VFS)
16497+ * - src_dir and dir by lock_rename()
16498+ * - inode if exitsts
16499+ * (aufs)
16500+ * - lock all
16501+ * + src_dentry and dentry by aufs_read_and_write_lock2() which calls,
16502+ * + si_read_lock
16503+ * + di_write_lock2_child()
16504+ * + di_write_lock_child()
16505+ * + ii_write_lock_child()
16506+ * + di_write_lock_child2()
16507+ * + ii_write_lock_child2()
16508+ * + src_parent and parent
16509+ * + di_write_lock_parent()
16510+ * + ii_write_lock_parent()
16511+ * + di_write_lock_parent2()
16512+ * + ii_write_lock_parent2()
16513+ * + lower src_dir and dir by vfsub_lock_rename()
16514+ * + verify the every relationships between child and parent. if any
16515+ * of them failed, unlock all and return -EBUSY.
16516+ */
16517+static void au_ren_unlock(struct au_ren_args *a)
1308ab2a 16518+{
4a4d8108
AM
16519+ struct super_block *sb;
16520+
16521+ sb = a->dst_dentry->d_sb;
16522+ if (au_ftest_ren(a->flags, MNT_WRITE))
16523+ mnt_drop_write(a->br->br_mnt);
16524+ vfsub_unlock_rename(a->src_h_parent, a->src_hdir,
16525+ a->dst_h_parent, a->dst_hdir);
1308ab2a 16526+}
16527+
4a4d8108 16528+static int au_ren_lock(struct au_ren_args *a)
1308ab2a 16529+{
4a4d8108
AM
16530+ int err;
16531+ unsigned int udba;
1308ab2a 16532+
4a4d8108
AM
16533+ err = 0;
16534+ a->src_h_parent = au_h_dptr(a->src_parent, a->btgt);
16535+ a->src_hdir = au_hi(a->src_dir, a->btgt);
16536+ a->dst_h_parent = au_h_dptr(a->dst_parent, a->btgt);
16537+ a->dst_hdir = au_hi(a->dst_dir, a->btgt);
16538+ a->h_trap = vfsub_lock_rename(a->src_h_parent, a->src_hdir,
16539+ a->dst_h_parent, a->dst_hdir);
16540+ udba = au_opt_udba(a->src_dentry->d_sb);
16541+ if (unlikely(a->src_hdir->hi_inode != a->src_h_parent->d_inode
16542+ || a->dst_hdir->hi_inode != a->dst_h_parent->d_inode))
16543+ err = au_busy_or_stale();
16544+ if (!err && au_dbstart(a->src_dentry) == a->btgt)
16545+ err = au_h_verify(a->src_h_dentry, udba,
16546+ a->src_h_parent->d_inode, a->src_h_parent,
16547+ a->br);
16548+ if (!err && au_dbstart(a->dst_dentry) == a->btgt)
16549+ err = au_h_verify(a->dst_h_dentry, udba,
16550+ a->dst_h_parent->d_inode, a->dst_h_parent,
16551+ a->br);
16552+ if (!err) {
16553+ err = mnt_want_write(a->br->br_mnt);
16554+ if (unlikely(err))
16555+ goto out_unlock;
16556+ au_fset_ren(a->flags, MNT_WRITE);
16557+ goto out; /* success */
16558+ }
16559+
16560+ err = au_busy_or_stale();
16561+
4f0767ce 16562+out_unlock:
4a4d8108 16563+ au_ren_unlock(a);
4f0767ce 16564+out:
4a4d8108 16565+ return err;
1facf9fc 16566+}
16567+
16568+/* ---------------------------------------------------------------------- */
16569+
4a4d8108 16570+static void au_ren_refresh_dir(struct au_ren_args *a)
1facf9fc 16571+{
4a4d8108 16572+ struct inode *dir;
dece6358 16573+
4a4d8108
AM
16574+ dir = a->dst_dir;
16575+ dir->i_version++;
16576+ if (au_ftest_ren(a->flags, ISDIR)) {
16577+ /* is this updating defined in POSIX? */
16578+ au_cpup_attr_timesizes(a->src_inode);
16579+ au_cpup_attr_nlink(dir, /*force*/1);
4a4d8108 16580+ }
027c5e7a 16581+
4a4d8108
AM
16582+ if (au_ibstart(dir) == a->btgt)
16583+ au_cpup_attr_timesizes(dir);
dece6358 16584+
4a4d8108
AM
16585+ if (au_ftest_ren(a->flags, ISSAMEDIR))
16586+ return;
dece6358 16587+
4a4d8108
AM
16588+ dir = a->src_dir;
16589+ dir->i_version++;
16590+ if (au_ftest_ren(a->flags, ISDIR))
16591+ au_cpup_attr_nlink(dir, /*force*/1);
16592+ if (au_ibstart(dir) == a->btgt)
16593+ au_cpup_attr_timesizes(dir);
1facf9fc 16594+}
16595+
4a4d8108 16596+static void au_ren_refresh(struct au_ren_args *a)
1facf9fc 16597+{
4a4d8108
AM
16598+ aufs_bindex_t bend, bindex;
16599+ struct dentry *d, *h_d;
16600+ struct inode *i, *h_i;
16601+ struct super_block *sb;
dece6358 16602+
027c5e7a
AM
16603+ d = a->dst_dentry;
16604+ d_drop(d);
16605+ if (a->h_dst)
16606+ /* already dget-ed by au_ren_or_cpup() */
16607+ au_set_h_dptr(d, a->btgt, a->h_dst);
16608+
16609+ i = a->dst_inode;
16610+ if (i) {
16611+ if (!au_ftest_ren(a->flags, ISDIR))
16612+ vfsub_drop_nlink(i);
16613+ else {
16614+ vfsub_dead_dir(i);
16615+ au_cpup_attr_timesizes(i);
16616+ }
16617+ au_update_dbrange(d, /*do_put_zero*/1);
16618+ } else {
16619+ bend = a->btgt;
16620+ for (bindex = au_dbstart(d); bindex < bend; bindex++)
16621+ au_set_h_dptr(d, bindex, NULL);
16622+ bend = au_dbend(d);
16623+ for (bindex = a->btgt + 1; bindex <= bend; bindex++)
16624+ au_set_h_dptr(d, bindex, NULL);
16625+ au_update_dbrange(d, /*do_put_zero*/0);
16626+ }
16627+
4a4d8108
AM
16628+ d = a->src_dentry;
16629+ au_set_dbwh(d, -1);
16630+ bend = au_dbend(d);
16631+ for (bindex = a->btgt + 1; bindex <= bend; bindex++) {
16632+ h_d = au_h_dptr(d, bindex);
16633+ if (h_d)
16634+ au_set_h_dptr(d, bindex, NULL);
16635+ }
16636+ au_set_dbend(d, a->btgt);
16637+
16638+ sb = d->d_sb;
16639+ i = a->src_inode;
16640+ if (au_opt_test(au_mntflags(sb), PLINK) && au_plink_test(i))
16641+ return; /* success */
16642+
16643+ bend = au_ibend(i);
16644+ for (bindex = a->btgt + 1; bindex <= bend; bindex++) {
16645+ h_i = au_h_iptr(i, bindex);
16646+ if (h_i) {
16647+ au_xino_write(sb, bindex, h_i->i_ino, /*ino*/0);
16648+ /* ignore this error */
16649+ au_set_h_iptr(i, bindex, NULL, 0);
16650+ }
16651+ }
16652+ au_set_ibend(i, a->btgt);
1308ab2a 16653+}
dece6358 16654+
4a4d8108
AM
16655+/* ---------------------------------------------------------------------- */
16656+
16657+/* mainly for link(2) and rename(2) */
16658+int au_wbr(struct dentry *dentry, aufs_bindex_t btgt)
1308ab2a 16659+{
4a4d8108
AM
16660+ aufs_bindex_t bdiropq, bwh;
16661+ struct dentry *parent;
16662+ struct au_branch *br;
16663+
16664+ parent = dentry->d_parent;
16665+ IMustLock(parent->d_inode); /* dir is locked */
16666+
16667+ bdiropq = au_dbdiropq(parent);
16668+ bwh = au_dbwh(dentry);
16669+ br = au_sbr(dentry->d_sb, btgt);
16670+ if (au_br_rdonly(br)
16671+ || (0 <= bdiropq && bdiropq < btgt)
16672+ || (0 <= bwh && bwh < btgt))
16673+ btgt = -1;
16674+
16675+ AuDbg("btgt %d\n", btgt);
16676+ return btgt;
1facf9fc 16677+}
16678+
4a4d8108
AM
16679+/* sets src_bstart, dst_bstart and btgt */
16680+static int au_ren_wbr(struct au_ren_args *a)
1facf9fc 16681+{
4a4d8108
AM
16682+ int err;
16683+ struct au_wr_dir_args wr_dir_args = {
16684+ /* .force_btgt = -1, */
16685+ .flags = AuWrDir_ADD_ENTRY
16686+ };
dece6358 16687+
4a4d8108
AM
16688+ a->src_bstart = au_dbstart(a->src_dentry);
16689+ a->dst_bstart = au_dbstart(a->dst_dentry);
16690+ if (au_ftest_ren(a->flags, ISDIR))
16691+ au_fset_wrdir(wr_dir_args.flags, ISDIR);
16692+ wr_dir_args.force_btgt = a->src_bstart;
16693+ if (a->dst_inode && a->dst_bstart < a->src_bstart)
16694+ wr_dir_args.force_btgt = a->dst_bstart;
16695+ wr_dir_args.force_btgt = au_wbr(a->dst_dentry, wr_dir_args.force_btgt);
16696+ err = au_wr_dir(a->dst_dentry, a->src_dentry, &wr_dir_args);
16697+ a->btgt = err;
dece6358 16698+
4a4d8108 16699+ return err;
1facf9fc 16700+}
16701+
4a4d8108 16702+static void au_ren_dt(struct au_ren_args *a)
1facf9fc 16703+{
4a4d8108
AM
16704+ a->h_path.dentry = a->src_h_parent;
16705+ au_dtime_store(a->src_dt + AuPARENT, a->src_parent, &a->h_path);
16706+ if (!au_ftest_ren(a->flags, ISSAMEDIR)) {
16707+ a->h_path.dentry = a->dst_h_parent;
16708+ au_dtime_store(a->dst_dt + AuPARENT, a->dst_parent, &a->h_path);
16709+ }
1facf9fc 16710+
4a4d8108
AM
16711+ au_fclr_ren(a->flags, DT_DSTDIR);
16712+ if (!au_ftest_ren(a->flags, ISDIR))
16713+ return;
dece6358 16714+
4a4d8108
AM
16715+ a->h_path.dentry = a->src_h_dentry;
16716+ au_dtime_store(a->src_dt + AuCHILD, a->src_dentry, &a->h_path);
16717+ if (a->dst_h_dentry->d_inode) {
16718+ au_fset_ren(a->flags, DT_DSTDIR);
16719+ a->h_path.dentry = a->dst_h_dentry;
16720+ au_dtime_store(a->dst_dt + AuCHILD, a->dst_dentry, &a->h_path);
16721+ }
1308ab2a 16722+}
dece6358 16723+
4a4d8108 16724+static void au_ren_rev_dt(int err, struct au_ren_args *a)
1308ab2a 16725+{
4a4d8108
AM
16726+ struct dentry *h_d;
16727+ struct mutex *h_mtx;
16728+
16729+ au_dtime_revert(a->src_dt + AuPARENT);
16730+ if (!au_ftest_ren(a->flags, ISSAMEDIR))
16731+ au_dtime_revert(a->dst_dt + AuPARENT);
16732+
16733+ if (au_ftest_ren(a->flags, ISDIR) && err != -EIO) {
16734+ h_d = a->src_dt[AuCHILD].dt_h_path.dentry;
16735+ h_mtx = &h_d->d_inode->i_mutex;
16736+ mutex_lock_nested(h_mtx, AuLsc_I_CHILD);
16737+ au_dtime_revert(a->src_dt + AuCHILD);
16738+ mutex_unlock(h_mtx);
16739+
16740+ if (au_ftest_ren(a->flags, DT_DSTDIR)) {
16741+ h_d = a->dst_dt[AuCHILD].dt_h_path.dentry;
16742+ h_mtx = &h_d->d_inode->i_mutex;
16743+ mutex_lock_nested(h_mtx, AuLsc_I_CHILD);
16744+ au_dtime_revert(a->dst_dt + AuCHILD);
16745+ mutex_unlock(h_mtx);
1facf9fc 16746+ }
16747+ }
16748+}
16749+
4a4d8108
AM
16750+/* ---------------------------------------------------------------------- */
16751+
16752+int aufs_rename(struct inode *_src_dir, struct dentry *_src_dentry,
16753+ struct inode *_dst_dir, struct dentry *_dst_dentry)
1facf9fc 16754+{
e49829fe 16755+ int err, flags;
4a4d8108
AM
16756+ /* reduce stack space */
16757+ struct au_ren_args *a;
16758+
16759+ AuDbg("%.*s, %.*s\n", AuDLNPair(_src_dentry), AuDLNPair(_dst_dentry));
16760+ IMustLock(_src_dir);
16761+ IMustLock(_dst_dir);
16762+
16763+ err = -ENOMEM;
16764+ BUILD_BUG_ON(sizeof(*a) > PAGE_SIZE);
16765+ a = kzalloc(sizeof(*a), GFP_NOFS);
16766+ if (unlikely(!a))
16767+ goto out;
16768+
16769+ a->src_dir = _src_dir;
16770+ a->src_dentry = _src_dentry;
16771+ a->src_inode = a->src_dentry->d_inode;
16772+ a->src_parent = a->src_dentry->d_parent; /* dir inode is locked */
16773+ a->dst_dir = _dst_dir;
16774+ a->dst_dentry = _dst_dentry;
16775+ a->dst_inode = a->dst_dentry->d_inode;
16776+ a->dst_parent = a->dst_dentry->d_parent; /* dir inode is locked */
16777+ if (a->dst_inode) {
16778+ IMustLock(a->dst_inode);
16779+ au_igrab(a->dst_inode);
1facf9fc 16780+ }
1facf9fc 16781+
4a4d8108 16782+ err = -ENOTDIR;
027c5e7a 16783+ flags = AuLock_FLUSH | AuLock_NOPLM | AuLock_GEN;
4a4d8108
AM
16784+ if (S_ISDIR(a->src_inode->i_mode)) {
16785+ au_fset_ren(a->flags, ISDIR);
16786+ if (unlikely(a->dst_inode && !S_ISDIR(a->dst_inode->i_mode)))
16787+ goto out_free;
e49829fe
JR
16788+ err = aufs_read_and_write_lock2(a->dst_dentry, a->src_dentry,
16789+ AuLock_DIR | flags);
4a4d8108 16790+ } else
e49829fe
JR
16791+ err = aufs_read_and_write_lock2(a->dst_dentry, a->src_dentry,
16792+ flags);
16793+ if (unlikely(err))
16794+ goto out_free;
1facf9fc 16795+
027c5e7a
AM
16796+ err = au_d_hashed_positive(a->src_dentry);
16797+ if (unlikely(err))
16798+ goto out_unlock;
16799+ err = -ENOENT;
16800+ if (a->dst_inode) {
16801+ /*
16802+ * If it is a dir, VFS unhash dst_dentry before this
16803+ * function. It means we cannot rely upon d_unhashed().
16804+ */
16805+ if (unlikely(!a->dst_inode->i_nlink))
16806+ goto out_unlock;
16807+ if (!S_ISDIR(a->dst_inode->i_mode)) {
16808+ err = au_d_hashed_positive(a->dst_dentry);
16809+ if (unlikely(err))
16810+ goto out_unlock;
16811+ } else if (unlikely(IS_DEADDIR(a->dst_inode)))
16812+ goto out_unlock;
16813+ } else if (unlikely(d_unhashed(a->dst_dentry)))
16814+ goto out_unlock;
16815+
4a4d8108
AM
16816+ au_fset_ren(a->flags, ISSAMEDIR); /* temporary */
16817+ di_write_lock_parent(a->dst_parent);
1facf9fc 16818+
4a4d8108
AM
16819+ /* which branch we process */
16820+ err = au_ren_wbr(a);
16821+ if (unlikely(err < 0))
027c5e7a 16822+ goto out_parent;
4a4d8108
AM
16823+ a->br = au_sbr(a->dst_dentry->d_sb, a->btgt);
16824+ a->h_path.mnt = a->br->br_mnt;
1facf9fc 16825+
4a4d8108
AM
16826+ /* are they available to be renamed */
16827+ err = au_ren_may_dir(a);
16828+ if (unlikely(err))
16829+ goto out_children;
1facf9fc 16830+
4a4d8108
AM
16831+ /* prepare the writable parent dir on the same branch */
16832+ if (a->dst_bstart == a->btgt) {
16833+ au_fset_ren(a->flags, WHDST);
16834+ } else {
16835+ err = au_cpup_dirs(a->dst_dentry, a->btgt);
16836+ if (unlikely(err))
16837+ goto out_children;
16838+ }
1facf9fc 16839+
4a4d8108
AM
16840+ if (a->src_dir != a->dst_dir) {
16841+ /*
16842+ * this temporary unlock is safe,
16843+ * because both dir->i_mutex are locked.
16844+ */
16845+ di_write_unlock(a->dst_parent);
16846+ di_write_lock_parent(a->src_parent);
16847+ err = au_wr_dir_need_wh(a->src_dentry,
16848+ au_ftest_ren(a->flags, ISDIR),
16849+ &a->btgt);
16850+ di_write_unlock(a->src_parent);
16851+ di_write_lock2_parent(a->src_parent, a->dst_parent, /*isdir*/1);
16852+ au_fclr_ren(a->flags, ISSAMEDIR);
16853+ } else
16854+ err = au_wr_dir_need_wh(a->src_dentry,
16855+ au_ftest_ren(a->flags, ISDIR),
16856+ &a->btgt);
16857+ if (unlikely(err < 0))
16858+ goto out_children;
16859+ if (err)
16860+ au_fset_ren(a->flags, WHSRC);
1facf9fc 16861+
4a4d8108
AM
16862+ /* lock them all */
16863+ err = au_ren_lock(a);
16864+ if (unlikely(err))
16865+ goto out_children;
1facf9fc 16866+
4a4d8108
AM
16867+ if (!au_opt_test(au_mntflags(a->dst_dir->i_sb), UDBA_NONE))
16868+ err = au_may_ren(a);
16869+ else if (unlikely(a->dst_dentry->d_name.len > AUFS_MAX_NAMELEN))
16870+ err = -ENAMETOOLONG;
16871+ if (unlikely(err))
16872+ goto out_hdir;
1facf9fc 16873+
4a4d8108
AM
16874+ /* store timestamps to be revertible */
16875+ au_ren_dt(a);
1facf9fc 16876+
4a4d8108
AM
16877+ /* here we go */
16878+ err = do_rename(a);
16879+ if (unlikely(err))
16880+ goto out_dt;
16881+
16882+ /* update dir attributes */
16883+ au_ren_refresh_dir(a);
16884+
16885+ /* dput/iput all lower dentries */
16886+ au_ren_refresh(a);
16887+
16888+ goto out_hdir; /* success */
16889+
4f0767ce 16890+out_dt:
4a4d8108 16891+ au_ren_rev_dt(err, a);
4f0767ce 16892+out_hdir:
4a4d8108 16893+ au_ren_unlock(a);
4f0767ce 16894+out_children:
4a4d8108 16895+ au_nhash_wh_free(&a->whlist);
027c5e7a
AM
16896+ if (err && a->dst_inode && a->dst_bstart != a->btgt) {
16897+ AuDbg("bstart %d, btgt %d\n", a->dst_bstart, a->btgt);
16898+ au_set_h_dptr(a->dst_dentry, a->btgt, NULL);
16899+ au_set_dbstart(a->dst_dentry, a->dst_bstart);
4a4d8108 16900+ }
027c5e7a 16901+out_parent:
4a4d8108
AM
16902+ if (!err)
16903+ d_move(a->src_dentry, a->dst_dentry);
027c5e7a
AM
16904+ else {
16905+ au_update_dbstart(a->dst_dentry);
16906+ if (!a->dst_inode)
16907+ d_drop(a->dst_dentry);
16908+ }
4a4d8108
AM
16909+ if (au_ftest_ren(a->flags, ISSAMEDIR))
16910+ di_write_unlock(a->dst_parent);
16911+ else
16912+ di_write_unlock2(a->src_parent, a->dst_parent);
027c5e7a 16913+out_unlock:
4a4d8108 16914+ aufs_read_and_write_unlock2(a->dst_dentry, a->src_dentry);
4f0767ce 16915+out_free:
4a4d8108
AM
16916+ iput(a->dst_inode);
16917+ if (a->thargs)
16918+ au_whtmp_rmdir_free(a->thargs);
16919+ kfree(a);
4f0767ce 16920+out:
4a4d8108
AM
16921+ AuTraceErr(err);
16922+ return err;
1308ab2a 16923+}
7f207e10
AM
16924diff -urN /usr/share/empty/fs/aufs/Kconfig linux/fs/aufs/Kconfig
16925--- /usr/share/empty/fs/aufs/Kconfig 1970-01-01 01:00:00.000000000 +0100
2cbb1c4b
JR
16926+++ linux/fs/aufs/Kconfig 2011-07-11 11:34:24.070331673 +0200
16927@@ -0,0 +1,203 @@
4a4d8108
AM
16928+config AUFS_FS
16929+ tristate "Aufs (Advanced multi layered unification filesystem) support"
16930+ depends on EXPERIMENTAL
16931+ help
16932+ Aufs is a stackable unification filesystem such as Unionfs,
16933+ which unifies several directories and provides a merged single
16934+ directory.
16935+ In the early days, aufs was entirely re-designed and
16936+ re-implemented Unionfs Version 1.x series. Introducing many
16937+ original ideas, approaches and improvements, it becomes totally
16938+ different from Unionfs while keeping the basic features.
1facf9fc 16939+
4a4d8108
AM
16940+if AUFS_FS
16941+choice
16942+ prompt "Maximum number of branches"
16943+ default AUFS_BRANCH_MAX_127
16944+ help
16945+ Specifies the maximum number of branches (or member directories)
16946+ in a single aufs. The larger value consumes more system
16947+ resources and has a minor impact to performance.
16948+config AUFS_BRANCH_MAX_127
16949+ bool "127"
16950+ help
16951+ Specifies the maximum number of branches (or member directories)
16952+ in a single aufs. The larger value consumes more system
16953+ resources and has a minor impact to performance.
16954+config AUFS_BRANCH_MAX_511
16955+ bool "511"
16956+ help
16957+ Specifies the maximum number of branches (or member directories)
16958+ in a single aufs. The larger value consumes more system
16959+ resources and has a minor impact to performance.
16960+config AUFS_BRANCH_MAX_1023
16961+ bool "1023"
16962+ help
16963+ Specifies the maximum number of branches (or member directories)
16964+ in a single aufs. The larger value consumes more system
16965+ resources and has a minor impact to performance.
16966+config AUFS_BRANCH_MAX_32767
16967+ bool "32767"
16968+ help
16969+ Specifies the maximum number of branches (or member directories)
16970+ in a single aufs. The larger value consumes more system
16971+ resources and has a minor impact to performance.
16972+endchoice
1facf9fc 16973+
e49829fe
JR
16974+config AUFS_SBILIST
16975+ bool
16976+ depends on AUFS_MAGIC_SYSRQ || PROC_FS
16977+ default y
16978+ help
16979+ Automatic configuration for internal use.
16980+ When aufs supports Magic SysRq or /proc, enabled automatically.
16981+
4a4d8108
AM
16982+config AUFS_HNOTIFY
16983+ bool "Detect direct branch access (bypassing aufs)"
16984+ help
16985+ If you want to modify files on branches directly, eg. bypassing aufs,
16986+ and want aufs to detect the changes of them fully, then enable this
16987+ option and use 'udba=notify' mount option.
7f207e10 16988+ Currently there is only one available configuration, "fsnotify".
4a4d8108
AM
16989+ It will have a negative impact to the performance.
16990+ See detail in aufs.5.
dece6358 16991+
4a4d8108
AM
16992+choice
16993+ prompt "method" if AUFS_HNOTIFY
16994+ default AUFS_HFSNOTIFY
16995+config AUFS_HFSNOTIFY
16996+ bool "fsnotify"
16997+ select FSNOTIFY
4a4d8108 16998+endchoice
1facf9fc 16999+
4a4d8108
AM
17000+config AUFS_EXPORT
17001+ bool "NFS-exportable aufs"
2cbb1c4b 17002+ depends on EXPORTFS
4a4d8108
AM
17003+ help
17004+ If you want to export your mounted aufs via NFS, then enable this
17005+ option. There are several requirements for this configuration.
17006+ See detail in aufs.5.
1facf9fc 17007+
4a4d8108
AM
17008+config AUFS_INO_T_64
17009+ bool
17010+ depends on AUFS_EXPORT
17011+ depends on 64BIT && !(ALPHA || S390)
17012+ default y
17013+ help
17014+ Automatic configuration for internal use.
17015+ /* typedef unsigned long/int __kernel_ino_t */
17016+ /* alpha and s390x are int */
1facf9fc 17017+
4a4d8108
AM
17018+config AUFS_RDU
17019+ bool "Readdir in userspace"
17020+ help
17021+ Aufs has two methods to provide a merged view for a directory,
17022+ by a user-space library and by kernel-space natively. The latter
17023+ is always enabled but sometimes large and slow.
17024+ If you enable this option, install the library in aufs2-util
17025+ package, and set some environment variables for your readdir(3),
17026+ then the work will be handled in user-space which generally
17027+ shows better performance in most cases.
17028+ See detail in aufs.5.
1facf9fc 17029+
2cbb1c4b
JR
17030+config AUFS_PROC_MAP
17031+ bool "support for /proc/maps and lsof(1)"
17032+ depends on PROC_FS
17033+ help
17034+ When you issue mmap(2) in aufs, it is actually a direct mmap(2)
17035+ call to the file on the branch fs since the file in aufs is
17036+ purely virtual. And the file path printed in /proc/maps (and
17037+ others) will be the path on the branch fs. In most cases, it
17038+ does no harm. But some utilities like lsof(1) may confuse since
17039+ the utility or user may expect the file path in aufs to be
17040+ printed.
17041+ To address this issue, aufs provides a patch which introduces a
17042+ new member called vm_prfile into struct vm_are_struct. The patch
17043+ is meaningless without enabling this configuration since nobody
17044+ sets the new vm_prfile member.
17045+ If you don't apply the patch, then enabling this configuration
17046+ will cause a compile error.
17047+ This approach is fragile since if someone else make some changes
17048+ around vm_file, then vm_prfile may not work anymore. As a
17049+ workaround such case, aufs provides this configuration. If you
17050+ disable it, then lsof(1) may produce incorrect result but the
17051+ problem will be gone even if the aufs patch is applied (I hope).
17052+
4a4d8108
AM
17053+config AUFS_SP_IATTR
17054+ bool "Respect the attributes (mtime/ctime mainly) of special files"
17055+ help
17056+ When you write something to a special file, some attributes of it
17057+ (mtime/ctime mainly) may be updated. Generally such updates are
17058+ less important (actually some device drivers and NFS ignore
17059+ it). But some applications (such like test program) requires
17060+ such updates. If you need these updates, then enable this
17061+ configuration which introduces some overhead.
17062+ Currently this configuration handles FIFO only.
1facf9fc 17063+
4a4d8108
AM
17064+config AUFS_SHWH
17065+ bool "Show whiteouts"
17066+ help
17067+ If you want to make the whiteouts in aufs visible, then enable
17068+ this option and specify 'shwh' mount option. Although it may
17069+ sounds like philosophy or something, but in technically it
17070+ simply shows the name of whiteout with keeping its behaviour.
1facf9fc 17071+
4a4d8108
AM
17072+config AUFS_BR_RAMFS
17073+ bool "Ramfs (initramfs/rootfs) as an aufs branch"
17074+ help
17075+ If you want to use ramfs as an aufs branch fs, then enable this
17076+ option. Generally tmpfs is recommended.
17077+ Aufs prohibited them to be a branch fs by default, because
17078+ initramfs becomes unusable after switch_root or something
17079+ generally. If you sets initramfs as an aufs branch and boot your
17080+ system by switch_root, you will meet a problem easily since the
17081+ files in initramfs may be inaccessible.
17082+ Unless you are going to use ramfs as an aufs branch fs without
17083+ switch_root or something, leave it N.
1facf9fc 17084+
4a4d8108
AM
17085+config AUFS_BR_FUSE
17086+ bool "Fuse fs as an aufs branch"
17087+ depends on FUSE_FS
17088+ select AUFS_POLL
17089+ help
17090+ If you want to use fuse-based userspace filesystem as an aufs
17091+ branch fs, then enable this option.
17092+ It implements the internal poll(2) operation which is
17093+ implemented by fuse only (curretnly).
1facf9fc 17094+
4a4d8108
AM
17095+config AUFS_POLL
17096+ bool
17097+ help
17098+ Automatic configuration for internal use.
1facf9fc 17099+
4a4d8108
AM
17100+config AUFS_BR_HFSPLUS
17101+ bool "Hfsplus as an aufs branch"
17102+ depends on HFSPLUS_FS
17103+ default y
17104+ help
17105+ If you want to use hfsplus fs as an aufs branch fs, then enable
17106+ this option. This option introduces a small overhead at
17107+ copying-up a file on hfsplus.
1facf9fc 17108+
4a4d8108
AM
17109+config AUFS_BDEV_LOOP
17110+ bool
17111+ depends on BLK_DEV_LOOP
17112+ default y
17113+ help
17114+ Automatic configuration for internal use.
17115+ Convert =[ym] into =y.
1308ab2a 17116+
4a4d8108
AM
17117+config AUFS_DEBUG
17118+ bool "Debug aufs"
17119+ help
17120+ Enable this to compile aufs internal debug code.
17121+ It will have a negative impact to the performance.
17122+
17123+config AUFS_MAGIC_SYSRQ
17124+ bool
17125+ depends on AUFS_DEBUG && MAGIC_SYSRQ
17126+ default y
17127+ help
17128+ Automatic configuration for internal use.
17129+ When aufs supports Magic SysRq, enabled automatically.
17130+endif
7f207e10
AM
17131diff -urN /usr/share/empty/fs/aufs/loop.c linux/fs/aufs/loop.c
17132--- /usr/share/empty/fs/aufs/loop.c 1970-01-01 01:00:00.000000000 +0100
2cbb1c4b 17133+++ linux/fs/aufs/loop.c 2011-07-11 11:34:24.075331673 +0200
b752ccd1 17134@@ -0,0 +1,63 @@
1facf9fc 17135+/*
027c5e7a 17136+ * Copyright (C) 2005-2011 Junjiro R. Okajima
1facf9fc 17137+ *
17138+ * This program, aufs is free software; you can redistribute it and/or modify
17139+ * it under the terms of the GNU General Public License as published by
17140+ * the Free Software Foundation; either version 2 of the License, or
17141+ * (at your option) any later version.
dece6358
AM
17142+ *
17143+ * This program is distributed in the hope that it will be useful,
17144+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
17145+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17146+ * GNU General Public License for more details.
17147+ *
17148+ * You should have received a copy of the GNU General Public License
17149+ * along with this program; if not, write to the Free Software
17150+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 17151+ */
17152+
17153+/*
17154+ * support for loopback block device as a branch
17155+ */
17156+
17157+#include <linux/loop.h>
17158+#include "aufs.h"
17159+
17160+/*
17161+ * test if two lower dentries have overlapping branches.
17162+ */
b752ccd1 17163+int au_test_loopback_overlap(struct super_block *sb, struct dentry *h_adding)
1facf9fc 17164+{
b752ccd1 17165+ struct super_block *h_sb;
1facf9fc 17166+ struct loop_device *l;
17167+
b752ccd1
AM
17168+ h_sb = h_adding->d_sb;
17169+ if (MAJOR(h_sb->s_dev) != LOOP_MAJOR)
1facf9fc 17170+ return 0;
17171+
b752ccd1
AM
17172+ l = h_sb->s_bdev->bd_disk->private_data;
17173+ h_adding = l->lo_backing_file->f_dentry;
17174+ /*
17175+ * h_adding can be local NFS.
17176+ * in this case aufs cannot detect the loop.
17177+ */
17178+ if (unlikely(h_adding->d_sb == sb))
1facf9fc 17179+ return 1;
b752ccd1 17180+ return !!au_test_subdir(h_adding, sb->s_root);
1facf9fc 17181+}
17182+
17183+/* true if a kernel thread named 'loop[0-9].*' accesses a file */
17184+int au_test_loopback_kthread(void)
17185+{
b752ccd1
AM
17186+ int ret;
17187+ struct task_struct *tsk = current;
17188+
17189+ ret = 0;
17190+ if (tsk->flags & PF_KTHREAD) {
17191+ const char c = tsk->comm[4];
17192+ ret = ('0' <= c && c <= '9'
17193+ && !strncmp(tsk->comm, "loop", 4));
17194+ }
1facf9fc 17195+
b752ccd1 17196+ return ret;
1facf9fc 17197+}
7f207e10
AM
17198diff -urN /usr/share/empty/fs/aufs/loop.h linux/fs/aufs/loop.h
17199--- /usr/share/empty/fs/aufs/loop.h 1970-01-01 01:00:00.000000000 +0100
2cbb1c4b 17200+++ linux/fs/aufs/loop.h 2011-07-11 11:34:24.075331673 +0200
b752ccd1 17201@@ -0,0 +1,42 @@
1facf9fc 17202+/*
027c5e7a 17203+ * Copyright (C) 2005-2011 Junjiro R. Okajima
1facf9fc 17204+ *
17205+ * This program, aufs is free software; you can redistribute it and/or modify
17206+ * it under the terms of the GNU General Public License as published by
17207+ * the Free Software Foundation; either version 2 of the License, or
17208+ * (at your option) any later version.
dece6358
AM
17209+ *
17210+ * This program is distributed in the hope that it will be useful,
17211+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
17212+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17213+ * GNU General Public License for more details.
17214+ *
17215+ * You should have received a copy of the GNU General Public License
17216+ * along with this program; if not, write to the Free Software
17217+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 17218+ */
17219+
17220+/*
17221+ * support for loopback mount as a branch
17222+ */
17223+
17224+#ifndef __AUFS_LOOP_H__
17225+#define __AUFS_LOOP_H__
17226+
17227+#ifdef __KERNEL__
17228+
dece6358
AM
17229+struct dentry;
17230+struct super_block;
1facf9fc 17231+
17232+#ifdef CONFIG_AUFS_BDEV_LOOP
17233+/* loop.c */
b752ccd1 17234+int au_test_loopback_overlap(struct super_block *sb, struct dentry *h_adding);
1facf9fc 17235+int au_test_loopback_kthread(void);
17236+#else
4a4d8108 17237+AuStubInt0(au_test_loopback_overlap, struct super_block *sb,
b752ccd1 17238+ struct dentry *h_adding)
4a4d8108 17239+AuStubInt0(au_test_loopback_kthread, void)
1facf9fc 17240+#endif /* BLK_DEV_LOOP */
17241+
17242+#endif /* __KERNEL__ */
17243+#endif /* __AUFS_LOOP_H__ */
7f207e10
AM
17244diff -urN /usr/share/empty/fs/aufs/magic.mk linux/fs/aufs/magic.mk
17245--- /usr/share/empty/fs/aufs/magic.mk 1970-01-01 01:00:00.000000000 +0100
2cbb1c4b 17246+++ linux/fs/aufs/magic.mk 2011-07-11 11:34:24.076331673 +0200
4a4d8108 17247@@ -0,0 +1,54 @@
1facf9fc 17248+
17249+# defined in ${srctree}/fs/fuse/inode.c
17250+# tristate
17251+ifdef CONFIG_FUSE_FS
17252+ccflags-y += -DFUSE_SUPER_MAGIC=0x65735546
17253+endif
17254+
17255+# defined in ${srctree}/fs/ocfs2/ocfs2_fs.h
17256+# tristate
17257+ifdef CONFIG_OCFS2_FS
17258+ccflags-y += -DOCFS2_SUPER_MAGIC=0x7461636f
17259+endif
17260+
17261+# defined in ${srctree}/fs/ocfs2/dlm/userdlm.h
17262+# tristate
17263+ifdef CONFIG_OCFS2_FS_O2CB
17264+ccflags-y += -DDLMFS_MAGIC=0x76a9f425
17265+endif
17266+
1facf9fc 17267+# defined in ${srctree}/fs/cifs/cifsfs.c
17268+# tristate
17269+ifdef CONFIG_CIFS_FS
17270+ccflags-y += -DCIFS_MAGIC_NUMBER=0xFF534D42
17271+endif
17272+
17273+# defined in ${srctree}/fs/xfs/xfs_sb.h
17274+# tristate
17275+ifdef CONFIG_XFS_FS
17276+ccflags-y += -DXFS_SB_MAGIC=0x58465342
17277+endif
17278+
17279+# defined in ${srctree}/fs/configfs/mount.c
17280+# tristate
17281+ifdef CONFIG_CONFIGFS_FS
17282+ccflags-y += -DCONFIGFS_MAGIC=0x62656570
17283+endif
17284+
17285+# defined in ${srctree}/fs/9p/v9fs.h
17286+# tristate
17287+ifdef CONFIG_9P_FS
17288+ccflags-y += -DV9FS_MAGIC=0x01021997
17289+endif
17290+
17291+# defined in ${srctree}/fs/ubifs/ubifs.h
17292+# tristate
17293+ifdef CONFIG_UBIFS_FS
17294+ccflags-y += -DUBIFS_SUPER_MAGIC=0x24051905
17295+endif
4a4d8108
AM
17296+
17297+# defined in ${srctree}/fs/hfsplus/hfsplus_raw.h
17298+# tristate
17299+ifdef CONFIG_HFSPLUS_FS
17300+ccflags-y += -DHFSPLUS_SUPER_MAGIC=0x482b
17301+endif
7f207e10
AM
17302diff -urN /usr/share/empty/fs/aufs/Makefile linux/fs/aufs/Makefile
17303--- /usr/share/empty/fs/aufs/Makefile 1970-01-01 01:00:00.000000000 +0100
2cbb1c4b 17304+++ linux/fs/aufs/Makefile 2011-07-11 11:34:24.070331673 +0200
7f207e10 17305@@ -0,0 +1,38 @@
4a4d8108
AM
17306+
17307+include ${src}/magic.mk
17308+ifeq (${CONFIG_AUFS_FS},m)
17309+include ${src}/conf.mk
17310+endif
17311+-include ${src}/priv_def.mk
17312+
17313+# cf. include/linux/kernel.h
17314+# enable pr_debug
17315+ccflags-y += -DDEBUG
7f207e10
AM
17316+# sparse doesn't allow spaces
17317+ccflags-y += -D'pr_fmt(fmt)=AUFS_NAME"\040%s:%d:%s[%d]:\040"fmt,__func__,__LINE__,current->comm,current->pid'
4a4d8108
AM
17318+
17319+obj-$(CONFIG_AUFS_FS) += aufs.o
17320+aufs-y := module.o sbinfo.o super.o branch.o xino.o sysaufs.o opts.o \
17321+ wkq.o vfsub.o dcsub.o \
e49829fe 17322+ cpup.o whout.o wbr_policy.o \
4a4d8108
AM
17323+ dinfo.o dentry.o \
17324+ dynop.o \
17325+ finfo.o file.o f_op.o \
17326+ dir.o vdir.o \
17327+ iinfo.o inode.o i_op.o i_op_add.o i_op_del.o i_op_ren.o \
17328+ ioctl.o
17329+
17330+# all are boolean
e49829fe 17331+aufs-$(CONFIG_PROC_FS) += procfs.o plink.o
4a4d8108
AM
17332+aufs-$(CONFIG_SYSFS) += sysfs.o
17333+aufs-$(CONFIG_DEBUG_FS) += dbgaufs.o
17334+aufs-$(CONFIG_AUFS_BDEV_LOOP) += loop.o
17335+aufs-$(CONFIG_AUFS_HNOTIFY) += hnotify.o
17336+aufs-$(CONFIG_AUFS_HFSNOTIFY) += hfsnotify.o
4a4d8108
AM
17337+aufs-$(CONFIG_AUFS_EXPORT) += export.o
17338+aufs-$(CONFIG_AUFS_POLL) += poll.o
17339+aufs-$(CONFIG_AUFS_RDU) += rdu.o
17340+aufs-$(CONFIG_AUFS_SP_IATTR) += f_op_sp.o
17341+aufs-$(CONFIG_AUFS_BR_HFSPLUS) += hfsplus.o
17342+aufs-$(CONFIG_AUFS_DEBUG) += debug.o
17343+aufs-$(CONFIG_AUFS_MAGIC_SYSRQ) += sysrq.o
7f207e10
AM
17344diff -urN /usr/share/empty/fs/aufs/module.c linux/fs/aufs/module.c
17345--- /usr/share/empty/fs/aufs/module.c 1970-01-01 01:00:00.000000000 +0100
2cbb1c4b 17346+++ linux/fs/aufs/module.c 2011-07-11 11:34:24.076331673 +0200
027c5e7a 17347@@ -0,0 +1,183 @@
1facf9fc 17348+/*
027c5e7a 17349+ * Copyright (C) 2005-2011 Junjiro R. Okajima
1facf9fc 17350+ *
17351+ * This program, aufs is free software; you can redistribute it and/or modify
17352+ * it under the terms of the GNU General Public License as published by
17353+ * the Free Software Foundation; either version 2 of the License, or
17354+ * (at your option) any later version.
dece6358
AM
17355+ *
17356+ * This program is distributed in the hope that it will be useful,
17357+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
17358+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17359+ * GNU General Public License for more details.
17360+ *
17361+ * You should have received a copy of the GNU General Public License
17362+ * along with this program; if not, write to the Free Software
17363+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 17364+ */
17365+
17366+/*
17367+ * module global variables and operations
17368+ */
17369+
17370+#include <linux/module.h>
17371+#include <linux/seq_file.h>
17372+#include "aufs.h"
17373+
17374+void *au_kzrealloc(void *p, unsigned int nused, unsigned int new_sz, gfp_t gfp)
17375+{
17376+ if (new_sz <= nused)
17377+ return p;
17378+
17379+ p = krealloc(p, new_sz, gfp);
17380+ if (p)
17381+ memset(p + nused, 0, new_sz - nused);
17382+ return p;
17383+}
17384+
17385+/* ---------------------------------------------------------------------- */
17386+
17387+/*
17388+ * aufs caches
17389+ */
17390+struct kmem_cache *au_cachep[AuCache_Last];
17391+static int __init au_cache_init(void)
17392+{
4a4d8108 17393+ au_cachep[AuCache_DINFO] = AuCacheCtor(au_dinfo, au_di_init_once);
1facf9fc 17394+ if (au_cachep[AuCache_DINFO])
027c5e7a 17395+ /* SLAB_DESTROY_BY_RCU */
4a4d8108
AM
17396+ au_cachep[AuCache_ICNTNR] = AuCacheCtor(au_icntnr,
17397+ au_icntnr_init_once);
1facf9fc 17398+ if (au_cachep[AuCache_ICNTNR])
4a4d8108
AM
17399+ au_cachep[AuCache_FINFO] = AuCacheCtor(au_finfo,
17400+ au_fi_init_once);
1facf9fc 17401+ if (au_cachep[AuCache_FINFO])
17402+ au_cachep[AuCache_VDIR] = AuCache(au_vdir);
17403+ if (au_cachep[AuCache_VDIR])
17404+ au_cachep[AuCache_DEHSTR] = AuCache(au_vdir_dehstr);
17405+ if (au_cachep[AuCache_DEHSTR])
17406+ return 0;
17407+
17408+ return -ENOMEM;
17409+}
17410+
17411+static void au_cache_fin(void)
17412+{
17413+ int i;
4a4d8108
AM
17414+
17415+ /* including AuCache_HNOTIFY */
1facf9fc 17416+ for (i = 0; i < AuCache_Last; i++)
17417+ if (au_cachep[i]) {
17418+ kmem_cache_destroy(au_cachep[i]);
17419+ au_cachep[i] = NULL;
17420+ }
17421+}
17422+
17423+/* ---------------------------------------------------------------------- */
17424+
17425+int au_dir_roflags;
17426+
e49829fe
JR
17427+#ifdef CONFIG_AUFS_SBILIST
17428+struct au_splhead au_sbilist;
17429+#endif
17430+
1facf9fc 17431+/*
17432+ * functions for module interface.
17433+ */
17434+MODULE_LICENSE("GPL");
17435+/* MODULE_LICENSE("GPL v2"); */
dece6358 17436+MODULE_AUTHOR("Junjiro R. Okajima <aufs-users@lists.sourceforge.net>");
1facf9fc 17437+MODULE_DESCRIPTION(AUFS_NAME
17438+ " -- Advanced multi layered unification filesystem");
17439+MODULE_VERSION(AUFS_VERSION);
17440+
1facf9fc 17441+/* this module parameter has no meaning when SYSFS is disabled */
17442+int sysaufs_brs = 1;
17443+MODULE_PARM_DESC(brs, "use <sysfs>/fs/aufs/si_*/brN");
17444+module_param_named(brs, sysaufs_brs, int, S_IRUGO);
17445+
17446+/* ---------------------------------------------------------------------- */
17447+
17448+static char au_esc_chars[0x20 + 3]; /* 0x01-0x20, backslash, del, and NULL */
17449+
17450+int au_seq_path(struct seq_file *seq, struct path *path)
17451+{
17452+ return seq_path(seq, path, au_esc_chars);
17453+}
17454+
17455+/* ---------------------------------------------------------------------- */
17456+
17457+static int __init aufs_init(void)
17458+{
17459+ int err, i;
17460+ char *p;
17461+
17462+ p = au_esc_chars;
17463+ for (i = 1; i <= ' '; i++)
17464+ *p++ = i;
17465+ *p++ = '\\';
17466+ *p++ = '\x7f';
17467+ *p = 0;
17468+
17469+ au_dir_roflags = au_file_roflags(O_DIRECTORY | O_LARGEFILE);
17470+
e49829fe 17471+ au_sbilist_init();
1facf9fc 17472+ sysaufs_brs_init();
17473+ au_debug_init();
4a4d8108 17474+ au_dy_init();
1facf9fc 17475+ err = sysaufs_init();
17476+ if (unlikely(err))
17477+ goto out;
e49829fe 17478+ err = au_procfs_init();
4f0767ce 17479+ if (unlikely(err))
953406b4 17480+ goto out_sysaufs;
e49829fe
JR
17481+ err = au_wkq_init();
17482+ if (unlikely(err))
17483+ goto out_procfs;
4a4d8108 17484+ err = au_hnotify_init();
1facf9fc 17485+ if (unlikely(err))
17486+ goto out_wkq;
17487+ err = au_sysrq_init();
17488+ if (unlikely(err))
17489+ goto out_hin;
17490+ err = au_cache_init();
17491+ if (unlikely(err))
17492+ goto out_sysrq;
17493+ err = register_filesystem(&aufs_fs_type);
17494+ if (unlikely(err))
17495+ goto out_cache;
4a4d8108
AM
17496+ /* since we define pr_fmt, call printk directly */
17497+ printk(KERN_INFO AUFS_NAME " " AUFS_VERSION "\n");
1facf9fc 17498+ goto out; /* success */
17499+
4f0767ce 17500+out_cache:
1facf9fc 17501+ au_cache_fin();
4f0767ce 17502+out_sysrq:
1facf9fc 17503+ au_sysrq_fin();
4f0767ce 17504+out_hin:
4a4d8108 17505+ au_hnotify_fin();
4f0767ce 17506+out_wkq:
1facf9fc 17507+ au_wkq_fin();
e49829fe
JR
17508+out_procfs:
17509+ au_procfs_fin();
4f0767ce 17510+out_sysaufs:
1facf9fc 17511+ sysaufs_fin();
4a4d8108 17512+ au_dy_fin();
4f0767ce 17513+out:
1facf9fc 17514+ return err;
17515+}
17516+
17517+static void __exit aufs_exit(void)
17518+{
17519+ unregister_filesystem(&aufs_fs_type);
17520+ au_cache_fin();
17521+ au_sysrq_fin();
4a4d8108 17522+ au_hnotify_fin();
1facf9fc 17523+ au_wkq_fin();
e49829fe 17524+ au_procfs_fin();
1facf9fc 17525+ sysaufs_fin();
4a4d8108 17526+ au_dy_fin();
1facf9fc 17527+}
17528+
17529+module_init(aufs_init);
17530+module_exit(aufs_exit);
7f207e10
AM
17531diff -urN /usr/share/empty/fs/aufs/module.h linux/fs/aufs/module.h
17532--- /usr/share/empty/fs/aufs/module.h 1970-01-01 01:00:00.000000000 +0100
2cbb1c4b 17533+++ linux/fs/aufs/module.h 2011-07-11 11:34:24.076331673 +0200
e49829fe 17534@@ -0,0 +1,91 @@
1facf9fc 17535+/*
027c5e7a 17536+ * Copyright (C) 2005-2011 Junjiro R. Okajima
1facf9fc 17537+ *
17538+ * This program, aufs is free software; you can redistribute it and/or modify
17539+ * it under the terms of the GNU General Public License as published by
17540+ * the Free Software Foundation; either version 2 of the License, or
17541+ * (at your option) any later version.
dece6358
AM
17542+ *
17543+ * This program is distributed in the hope that it will be useful,
17544+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
17545+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17546+ * GNU General Public License for more details.
17547+ *
17548+ * You should have received a copy of the GNU General Public License
17549+ * along with this program; if not, write to the Free Software
17550+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 17551+ */
17552+
17553+/*
17554+ * module initialization and module-global
17555+ */
17556+
17557+#ifndef __AUFS_MODULE_H__
17558+#define __AUFS_MODULE_H__
17559+
17560+#ifdef __KERNEL__
17561+
17562+#include <linux/slab.h>
17563+
dece6358
AM
17564+struct path;
17565+struct seq_file;
17566+
1facf9fc 17567+/* module parameters */
1facf9fc 17568+extern int sysaufs_brs;
17569+
17570+/* ---------------------------------------------------------------------- */
17571+
17572+extern int au_dir_roflags;
17573+
17574+void *au_kzrealloc(void *p, unsigned int nused, unsigned int new_sz, gfp_t gfp);
17575+int au_seq_path(struct seq_file *seq, struct path *path);
17576+
e49829fe
JR
17577+#ifdef CONFIG_PROC_FS
17578+/* procfs.c */
17579+int __init au_procfs_init(void);
17580+void au_procfs_fin(void);
17581+#else
17582+AuStubInt0(au_procfs_init, void);
17583+AuStubVoid(au_procfs_fin, void);
17584+#endif
17585+
4f0767ce
JR
17586+/* ---------------------------------------------------------------------- */
17587+
17588+/* kmem cache */
1facf9fc 17589+enum {
17590+ AuCache_DINFO,
17591+ AuCache_ICNTNR,
17592+ AuCache_FINFO,
17593+ AuCache_VDIR,
17594+ AuCache_DEHSTR,
4a4d8108
AM
17595+#ifdef CONFIG_AUFS_HNOTIFY
17596+ AuCache_HNOTIFY,
1facf9fc 17597+#endif
17598+ AuCache_Last
17599+};
17600+
4a4d8108
AM
17601+#define AuCacheFlags (SLAB_RECLAIM_ACCOUNT | SLAB_MEM_SPREAD)
17602+#define AuCache(type) KMEM_CACHE(type, AuCacheFlags)
17603+#define AuCacheCtor(type, ctor) \
17604+ kmem_cache_create(#type, sizeof(struct type), \
17605+ __alignof__(struct type), AuCacheFlags, ctor)
1facf9fc 17606+
17607+extern struct kmem_cache *au_cachep[];
17608+
17609+#define AuCacheFuncs(name, index) \
4a4d8108 17610+static inline struct au_##name *au_cache_alloc_##name(void) \
1facf9fc 17611+{ return kmem_cache_alloc(au_cachep[AuCache_##index], GFP_NOFS); } \
4a4d8108 17612+static inline void au_cache_free_##name(struct au_##name *p) \
1facf9fc 17613+{ kmem_cache_free(au_cachep[AuCache_##index], p); }
17614+
17615+AuCacheFuncs(dinfo, DINFO);
17616+AuCacheFuncs(icntnr, ICNTNR);
17617+AuCacheFuncs(finfo, FINFO);
17618+AuCacheFuncs(vdir, VDIR);
4a4d8108
AM
17619+AuCacheFuncs(vdir_dehstr, DEHSTR);
17620+#ifdef CONFIG_AUFS_HNOTIFY
17621+AuCacheFuncs(hnotify, HNOTIFY);
17622+#endif
1facf9fc 17623+
4a4d8108
AM
17624+#endif /* __KERNEL__ */
17625+#endif /* __AUFS_MODULE_H__ */
7f207e10
AM
17626diff -urN /usr/share/empty/fs/aufs/opts.c linux/fs/aufs/opts.c
17627--- /usr/share/empty/fs/aufs/opts.c 1970-01-01 01:00:00.000000000 +0100
2cbb1c4b 17628+++ linux/fs/aufs/opts.c 2011-07-11 11:34:24.076331673 +0200
027c5e7a 17629@@ -0,0 +1,1595 @@
1facf9fc 17630+/*
027c5e7a 17631+ * Copyright (C) 2005-2011 Junjiro R. Okajima
1facf9fc 17632+ *
17633+ * This program, aufs is free software; you can redistribute it and/or modify
17634+ * it under the terms of the GNU General Public License as published by
17635+ * the Free Software Foundation; either version 2 of the License, or
17636+ * (at your option) any later version.
dece6358
AM
17637+ *
17638+ * This program is distributed in the hope that it will be useful,
17639+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
17640+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17641+ * GNU General Public License for more details.
17642+ *
17643+ * You should have received a copy of the GNU General Public License
17644+ * along with this program; if not, write to the Free Software
17645+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 17646+ */
17647+
17648+/*
17649+ * mount options/flags
17650+ */
17651+
dece6358 17652+#include <linux/file.h>
e49829fe 17653+#include <linux/jiffies.h>
dece6358 17654+#include <linux/namei.h>
1facf9fc 17655+#include <linux/types.h> /* a distribution requires */
17656+#include <linux/parser.h>
17657+#include "aufs.h"
17658+
17659+/* ---------------------------------------------------------------------- */
17660+
17661+enum {
17662+ Opt_br,
17663+ Opt_add, Opt_del, Opt_mod, Opt_reorder, Opt_append, Opt_prepend,
17664+ Opt_idel, Opt_imod, Opt_ireorder,
17665+ Opt_dirwh, Opt_rdcache, Opt_rdblk, Opt_rdhash, Opt_rendir,
dece6358 17666+ Opt_rdblk_def, Opt_rdhash_def,
1facf9fc 17667+ Opt_xino, Opt_zxino, Opt_noxino,
17668+ Opt_trunc_xino, Opt_trunc_xino_v, Opt_notrunc_xino,
17669+ Opt_trunc_xino_path, Opt_itrunc_xino,
17670+ Opt_trunc_xib, Opt_notrunc_xib,
dece6358 17671+ Opt_shwh, Opt_noshwh,
1facf9fc 17672+ Opt_plink, Opt_noplink, Opt_list_plink,
17673+ Opt_udba,
4a4d8108 17674+ Opt_dio, Opt_nodio,
1facf9fc 17675+ /* Opt_lock, Opt_unlock, */
17676+ Opt_cmd, Opt_cmd_args,
17677+ Opt_diropq_a, Opt_diropq_w,
17678+ Opt_warn_perm, Opt_nowarn_perm,
17679+ Opt_wbr_copyup, Opt_wbr_create,
17680+ Opt_refrof, Opt_norefrof,
17681+ Opt_verbose, Opt_noverbose,
17682+ Opt_sum, Opt_nosum, Opt_wsum,
17683+ Opt_tail, Opt_ignore, Opt_ignore_silent, Opt_err
17684+};
17685+
17686+static match_table_t options = {
17687+ {Opt_br, "br=%s"},
17688+ {Opt_br, "br:%s"},
17689+
17690+ {Opt_add, "add=%d:%s"},
17691+ {Opt_add, "add:%d:%s"},
17692+ {Opt_add, "ins=%d:%s"},
17693+ {Opt_add, "ins:%d:%s"},
17694+ {Opt_append, "append=%s"},
17695+ {Opt_append, "append:%s"},
17696+ {Opt_prepend, "prepend=%s"},
17697+ {Opt_prepend, "prepend:%s"},
17698+
17699+ {Opt_del, "del=%s"},
17700+ {Opt_del, "del:%s"},
17701+ /* {Opt_idel, "idel:%d"}, */
17702+ {Opt_mod, "mod=%s"},
17703+ {Opt_mod, "mod:%s"},
17704+ /* {Opt_imod, "imod:%d:%s"}, */
17705+
17706+ {Opt_dirwh, "dirwh=%d"},
17707+
17708+ {Opt_xino, "xino=%s"},
17709+ {Opt_noxino, "noxino"},
17710+ {Opt_trunc_xino, "trunc_xino"},
17711+ {Opt_trunc_xino_v, "trunc_xino_v=%d:%d"},
17712+ {Opt_notrunc_xino, "notrunc_xino"},
17713+ {Opt_trunc_xino_path, "trunc_xino=%s"},
17714+ {Opt_itrunc_xino, "itrunc_xino=%d"},
17715+ /* {Opt_zxino, "zxino=%s"}, */
17716+ {Opt_trunc_xib, "trunc_xib"},
17717+ {Opt_notrunc_xib, "notrunc_xib"},
17718+
e49829fe 17719+#ifdef CONFIG_PROC_FS
1facf9fc 17720+ {Opt_plink, "plink"},
e49829fe
JR
17721+#else
17722+ {Opt_ignore_silent, "plink"},
17723+#endif
17724+
1facf9fc 17725+ {Opt_noplink, "noplink"},
e49829fe 17726+
1facf9fc 17727+#ifdef CONFIG_AUFS_DEBUG
17728+ {Opt_list_plink, "list_plink"},
17729+#endif
17730+
17731+ {Opt_udba, "udba=%s"},
17732+
4a4d8108
AM
17733+ {Opt_dio, "dio"},
17734+ {Opt_nodio, "nodio"},
17735+
1facf9fc 17736+ {Opt_diropq_a, "diropq=always"},
17737+ {Opt_diropq_a, "diropq=a"},
17738+ {Opt_diropq_w, "diropq=whiteouted"},
17739+ {Opt_diropq_w, "diropq=w"},
17740+
17741+ {Opt_warn_perm, "warn_perm"},
17742+ {Opt_nowarn_perm, "nowarn_perm"},
17743+
17744+ /* keep them temporary */
17745+ {Opt_ignore_silent, "coo=%s"},
17746+ {Opt_ignore_silent, "nodlgt"},
17747+ {Opt_ignore_silent, "nodirperm1"},
1facf9fc 17748+ {Opt_ignore_silent, "clean_plink"},
17749+
dece6358
AM
17750+#ifdef CONFIG_AUFS_SHWH
17751+ {Opt_shwh, "shwh"},
17752+#endif
17753+ {Opt_noshwh, "noshwh"},
17754+
1facf9fc 17755+ {Opt_rendir, "rendir=%d"},
17756+
17757+ {Opt_refrof, "refrof"},
17758+ {Opt_norefrof, "norefrof"},
17759+
17760+ {Opt_verbose, "verbose"},
17761+ {Opt_verbose, "v"},
17762+ {Opt_noverbose, "noverbose"},
17763+ {Opt_noverbose, "quiet"},
17764+ {Opt_noverbose, "q"},
17765+ {Opt_noverbose, "silent"},
17766+
17767+ {Opt_sum, "sum"},
17768+ {Opt_nosum, "nosum"},
17769+ {Opt_wsum, "wsum"},
17770+
17771+ {Opt_rdcache, "rdcache=%d"},
17772+ {Opt_rdblk, "rdblk=%d"},
dece6358 17773+ {Opt_rdblk_def, "rdblk=def"},
1facf9fc 17774+ {Opt_rdhash, "rdhash=%d"},
dece6358 17775+ {Opt_rdhash_def, "rdhash=def"},
1facf9fc 17776+
17777+ {Opt_wbr_create, "create=%s"},
17778+ {Opt_wbr_create, "create_policy=%s"},
17779+ {Opt_wbr_copyup, "cpup=%s"},
17780+ {Opt_wbr_copyup, "copyup=%s"},
17781+ {Opt_wbr_copyup, "copyup_policy=%s"},
17782+
17783+ /* internal use for the scripts */
17784+ {Opt_ignore_silent, "si=%s"},
17785+
17786+ {Opt_br, "dirs=%s"},
17787+ {Opt_ignore, "debug=%d"},
17788+ {Opt_ignore, "delete=whiteout"},
17789+ {Opt_ignore, "delete=all"},
17790+ {Opt_ignore, "imap=%s"},
17791+
1308ab2a 17792+ /* temporary workaround, due to old mount(8)? */
17793+ {Opt_ignore_silent, "relatime"},
17794+
1facf9fc 17795+ {Opt_err, NULL}
17796+};
17797+
17798+/* ---------------------------------------------------------------------- */
17799+
17800+static const char *au_parser_pattern(int val, struct match_token *token)
17801+{
17802+ while (token->pattern) {
17803+ if (token->token == val)
17804+ return token->pattern;
17805+ token++;
17806+ }
17807+ BUG();
17808+ return "??";
17809+}
17810+
17811+/* ---------------------------------------------------------------------- */
17812+
17813+static match_table_t brperms = {
17814+ {AuBrPerm_RO, AUFS_BRPERM_RO},
17815+ {AuBrPerm_RR, AUFS_BRPERM_RR},
17816+ {AuBrPerm_RW, AUFS_BRPERM_RW},
17817+
17818+ {AuBrPerm_ROWH, AUFS_BRPERM_ROWH},
17819+ {AuBrPerm_RRWH, AUFS_BRPERM_RRWH},
17820+ {AuBrPerm_RWNoLinkWH, AUFS_BRPERM_RWNLWH},
17821+
17822+ {AuBrPerm_ROWH, "nfsro"},
17823+ {AuBrPerm_RO, NULL}
17824+};
17825+
4a4d8108 17826+static int noinline_for_stack br_perm_val(char *perm)
1facf9fc 17827+{
17828+ int val;
17829+ substring_t args[MAX_OPT_ARGS];
17830+
17831+ val = match_token(perm, brperms, args);
17832+ return val;
17833+}
17834+
17835+const char *au_optstr_br_perm(int brperm)
17836+{
17837+ return au_parser_pattern(brperm, (void *)brperms);
17838+}
17839+
17840+/* ---------------------------------------------------------------------- */
17841+
17842+static match_table_t udbalevel = {
17843+ {AuOpt_UDBA_REVAL, "reval"},
17844+ {AuOpt_UDBA_NONE, "none"},
4a4d8108
AM
17845+#ifdef CONFIG_AUFS_HNOTIFY
17846+ {AuOpt_UDBA_HNOTIFY, "notify"}, /* abstraction */
17847+#ifdef CONFIG_AUFS_HFSNOTIFY
17848+ {AuOpt_UDBA_HNOTIFY, "fsnotify"},
4a4d8108 17849+#endif
1facf9fc 17850+#endif
17851+ {-1, NULL}
17852+};
17853+
4a4d8108 17854+static int noinline_for_stack udba_val(char *str)
1facf9fc 17855+{
17856+ substring_t args[MAX_OPT_ARGS];
17857+
7f207e10 17858+ return match_token(str, udbalevel, args);
1facf9fc 17859+}
17860+
17861+const char *au_optstr_udba(int udba)
17862+{
17863+ return au_parser_pattern(udba, (void *)udbalevel);
17864+}
17865+
17866+/* ---------------------------------------------------------------------- */
17867+
17868+static match_table_t au_wbr_create_policy = {
17869+ {AuWbrCreate_TDP, "tdp"},
17870+ {AuWbrCreate_TDP, "top-down-parent"},
17871+ {AuWbrCreate_RR, "rr"},
17872+ {AuWbrCreate_RR, "round-robin"},
17873+ {AuWbrCreate_MFS, "mfs"},
17874+ {AuWbrCreate_MFS, "most-free-space"},
17875+ {AuWbrCreate_MFSV, "mfs:%d"},
17876+ {AuWbrCreate_MFSV, "most-free-space:%d"},
17877+
17878+ {AuWbrCreate_MFSRR, "mfsrr:%d"},
17879+ {AuWbrCreate_MFSRRV, "mfsrr:%d:%d"},
17880+ {AuWbrCreate_PMFS, "pmfs"},
17881+ {AuWbrCreate_PMFSV, "pmfs:%d"},
17882+
17883+ {-1, NULL}
17884+};
17885+
dece6358
AM
17886+/*
17887+ * cf. linux/lib/parser.c and cmdline.c
17888+ * gave up calling memparse() since it uses simple_strtoull() instead of
17889+ * strict_...().
17890+ */
4a4d8108
AM
17891+static int noinline_for_stack
17892+au_match_ull(substring_t *s, unsigned long long *result)
1facf9fc 17893+{
17894+ int err;
17895+ unsigned int len;
17896+ char a[32];
17897+
17898+ err = -ERANGE;
17899+ len = s->to - s->from;
17900+ if (len + 1 <= sizeof(a)) {
17901+ memcpy(a, s->from, len);
17902+ a[len] = '\0';
17903+ err = strict_strtoull(a, 0, result);
17904+ }
17905+ return err;
17906+}
17907+
17908+static int au_wbr_mfs_wmark(substring_t *arg, char *str,
17909+ struct au_opt_wbr_create *create)
17910+{
17911+ int err;
17912+ unsigned long long ull;
17913+
17914+ err = 0;
17915+ if (!au_match_ull(arg, &ull))
17916+ create->mfsrr_watermark = ull;
17917+ else {
4a4d8108 17918+ pr_err("bad integer in %s\n", str);
1facf9fc 17919+ err = -EINVAL;
17920+ }
17921+
17922+ return err;
17923+}
17924+
17925+static int au_wbr_mfs_sec(substring_t *arg, char *str,
17926+ struct au_opt_wbr_create *create)
17927+{
17928+ int n, err;
17929+
17930+ err = 0;
027c5e7a 17931+ if (!match_int(arg, &n) && 0 <= n && n <= AUFS_MFS_MAX_SEC)
1facf9fc 17932+ create->mfs_second = n;
17933+ else {
4a4d8108 17934+ pr_err("bad integer in %s\n", str);
1facf9fc 17935+ err = -EINVAL;
17936+ }
17937+
17938+ return err;
17939+}
17940+
4a4d8108
AM
17941+static int noinline_for_stack
17942+au_wbr_create_val(char *str, struct au_opt_wbr_create *create)
1facf9fc 17943+{
17944+ int err, e;
17945+ substring_t args[MAX_OPT_ARGS];
17946+
17947+ err = match_token(str, au_wbr_create_policy, args);
17948+ create->wbr_create = err;
17949+ switch (err) {
17950+ case AuWbrCreate_MFSRRV:
17951+ e = au_wbr_mfs_wmark(&args[0], str, create);
17952+ if (!e)
17953+ e = au_wbr_mfs_sec(&args[1], str, create);
17954+ if (unlikely(e))
17955+ err = e;
17956+ break;
17957+ case AuWbrCreate_MFSRR:
17958+ e = au_wbr_mfs_wmark(&args[0], str, create);
17959+ if (unlikely(e)) {
17960+ err = e;
17961+ break;
17962+ }
17963+ /*FALLTHROUGH*/
17964+ case AuWbrCreate_MFS:
17965+ case AuWbrCreate_PMFS:
027c5e7a 17966+ create->mfs_second = AUFS_MFS_DEF_SEC;
1facf9fc 17967+ break;
17968+ case AuWbrCreate_MFSV:
17969+ case AuWbrCreate_PMFSV:
17970+ e = au_wbr_mfs_sec(&args[0], str, create);
17971+ if (unlikely(e))
17972+ err = e;
17973+ break;
17974+ }
17975+
17976+ return err;
17977+}
17978+
17979+const char *au_optstr_wbr_create(int wbr_create)
17980+{
17981+ return au_parser_pattern(wbr_create, (void *)au_wbr_create_policy);
17982+}
17983+
17984+static match_table_t au_wbr_copyup_policy = {
17985+ {AuWbrCopyup_TDP, "tdp"},
17986+ {AuWbrCopyup_TDP, "top-down-parent"},
17987+ {AuWbrCopyup_BUP, "bup"},
17988+ {AuWbrCopyup_BUP, "bottom-up-parent"},
17989+ {AuWbrCopyup_BU, "bu"},
17990+ {AuWbrCopyup_BU, "bottom-up"},
17991+ {-1, NULL}
17992+};
17993+
4a4d8108 17994+static int noinline_for_stack au_wbr_copyup_val(char *str)
1facf9fc 17995+{
17996+ substring_t args[MAX_OPT_ARGS];
17997+
17998+ return match_token(str, au_wbr_copyup_policy, args);
17999+}
18000+
18001+const char *au_optstr_wbr_copyup(int wbr_copyup)
18002+{
18003+ return au_parser_pattern(wbr_copyup, (void *)au_wbr_copyup_policy);
18004+}
18005+
18006+/* ---------------------------------------------------------------------- */
18007+
18008+static const int lkup_dirflags = LOOKUP_FOLLOW | LOOKUP_DIRECTORY;
18009+
18010+static void dump_opts(struct au_opts *opts)
18011+{
18012+#ifdef CONFIG_AUFS_DEBUG
18013+ /* reduce stack space */
18014+ union {
18015+ struct au_opt_add *add;
18016+ struct au_opt_del *del;
18017+ struct au_opt_mod *mod;
18018+ struct au_opt_xino *xino;
18019+ struct au_opt_xino_itrunc *xino_itrunc;
18020+ struct au_opt_wbr_create *create;
18021+ } u;
18022+ struct au_opt *opt;
18023+
18024+ opt = opts->opt;
18025+ while (opt->type != Opt_tail) {
18026+ switch (opt->type) {
18027+ case Opt_add:
18028+ u.add = &opt->add;
18029+ AuDbg("add {b%d, %s, 0x%x, %p}\n",
18030+ u.add->bindex, u.add->pathname, u.add->perm,
18031+ u.add->path.dentry);
18032+ break;
18033+ case Opt_del:
18034+ case Opt_idel:
18035+ u.del = &opt->del;
18036+ AuDbg("del {%s, %p}\n",
18037+ u.del->pathname, u.del->h_path.dentry);
18038+ break;
18039+ case Opt_mod:
18040+ case Opt_imod:
18041+ u.mod = &opt->mod;
18042+ AuDbg("mod {%s, 0x%x, %p}\n",
18043+ u.mod->path, u.mod->perm, u.mod->h_root);
18044+ break;
18045+ case Opt_append:
18046+ u.add = &opt->add;
18047+ AuDbg("append {b%d, %s, 0x%x, %p}\n",
18048+ u.add->bindex, u.add->pathname, u.add->perm,
18049+ u.add->path.dentry);
18050+ break;
18051+ case Opt_prepend:
18052+ u.add = &opt->add;
18053+ AuDbg("prepend {b%d, %s, 0x%x, %p}\n",
18054+ u.add->bindex, u.add->pathname, u.add->perm,
18055+ u.add->path.dentry);
18056+ break;
18057+ case Opt_dirwh:
18058+ AuDbg("dirwh %d\n", opt->dirwh);
18059+ break;
18060+ case Opt_rdcache:
18061+ AuDbg("rdcache %d\n", opt->rdcache);
18062+ break;
18063+ case Opt_rdblk:
18064+ AuDbg("rdblk %u\n", opt->rdblk);
18065+ break;
dece6358
AM
18066+ case Opt_rdblk_def:
18067+ AuDbg("rdblk_def\n");
18068+ break;
1facf9fc 18069+ case Opt_rdhash:
18070+ AuDbg("rdhash %u\n", opt->rdhash);
18071+ break;
dece6358
AM
18072+ case Opt_rdhash_def:
18073+ AuDbg("rdhash_def\n");
18074+ break;
1facf9fc 18075+ case Opt_xino:
18076+ u.xino = &opt->xino;
18077+ AuDbg("xino {%s %.*s}\n",
18078+ u.xino->path,
18079+ AuDLNPair(u.xino->file->f_dentry));
18080+ break;
18081+ case Opt_trunc_xino:
18082+ AuLabel(trunc_xino);
18083+ break;
18084+ case Opt_notrunc_xino:
18085+ AuLabel(notrunc_xino);
18086+ break;
18087+ case Opt_trunc_xino_path:
18088+ case Opt_itrunc_xino:
18089+ u.xino_itrunc = &opt->xino_itrunc;
18090+ AuDbg("trunc_xino %d\n", u.xino_itrunc->bindex);
18091+ break;
18092+
18093+ case Opt_noxino:
18094+ AuLabel(noxino);
18095+ break;
18096+ case Opt_trunc_xib:
18097+ AuLabel(trunc_xib);
18098+ break;
18099+ case Opt_notrunc_xib:
18100+ AuLabel(notrunc_xib);
18101+ break;
dece6358
AM
18102+ case Opt_shwh:
18103+ AuLabel(shwh);
18104+ break;
18105+ case Opt_noshwh:
18106+ AuLabel(noshwh);
18107+ break;
1facf9fc 18108+ case Opt_plink:
18109+ AuLabel(plink);
18110+ break;
18111+ case Opt_noplink:
18112+ AuLabel(noplink);
18113+ break;
18114+ case Opt_list_plink:
18115+ AuLabel(list_plink);
18116+ break;
18117+ case Opt_udba:
18118+ AuDbg("udba %d, %s\n",
18119+ opt->udba, au_optstr_udba(opt->udba));
18120+ break;
4a4d8108
AM
18121+ case Opt_dio:
18122+ AuLabel(dio);
18123+ break;
18124+ case Opt_nodio:
18125+ AuLabel(nodio);
18126+ break;
1facf9fc 18127+ case Opt_diropq_a:
18128+ AuLabel(diropq_a);
18129+ break;
18130+ case Opt_diropq_w:
18131+ AuLabel(diropq_w);
18132+ break;
18133+ case Opt_warn_perm:
18134+ AuLabel(warn_perm);
18135+ break;
18136+ case Opt_nowarn_perm:
18137+ AuLabel(nowarn_perm);
18138+ break;
18139+ case Opt_refrof:
18140+ AuLabel(refrof);
18141+ break;
18142+ case Opt_norefrof:
18143+ AuLabel(norefrof);
18144+ break;
18145+ case Opt_verbose:
18146+ AuLabel(verbose);
18147+ break;
18148+ case Opt_noverbose:
18149+ AuLabel(noverbose);
18150+ break;
18151+ case Opt_sum:
18152+ AuLabel(sum);
18153+ break;
18154+ case Opt_nosum:
18155+ AuLabel(nosum);
18156+ break;
18157+ case Opt_wsum:
18158+ AuLabel(wsum);
18159+ break;
18160+ case Opt_wbr_create:
18161+ u.create = &opt->wbr_create;
18162+ AuDbg("create %d, %s\n", u.create->wbr_create,
18163+ au_optstr_wbr_create(u.create->wbr_create));
18164+ switch (u.create->wbr_create) {
18165+ case AuWbrCreate_MFSV:
18166+ case AuWbrCreate_PMFSV:
18167+ AuDbg("%d sec\n", u.create->mfs_second);
18168+ break;
18169+ case AuWbrCreate_MFSRR:
18170+ AuDbg("%llu watermark\n",
18171+ u.create->mfsrr_watermark);
18172+ break;
18173+ case AuWbrCreate_MFSRRV:
18174+ AuDbg("%llu watermark, %d sec\n",
18175+ u.create->mfsrr_watermark,
18176+ u.create->mfs_second);
18177+ break;
18178+ }
18179+ break;
18180+ case Opt_wbr_copyup:
18181+ AuDbg("copyup %d, %s\n", opt->wbr_copyup,
18182+ au_optstr_wbr_copyup(opt->wbr_copyup));
18183+ break;
18184+ default:
18185+ BUG();
18186+ }
18187+ opt++;
18188+ }
18189+#endif
18190+}
18191+
18192+void au_opts_free(struct au_opts *opts)
18193+{
18194+ struct au_opt *opt;
18195+
18196+ opt = opts->opt;
18197+ while (opt->type != Opt_tail) {
18198+ switch (opt->type) {
18199+ case Opt_add:
18200+ case Opt_append:
18201+ case Opt_prepend:
18202+ path_put(&opt->add.path);
18203+ break;
18204+ case Opt_del:
18205+ case Opt_idel:
18206+ path_put(&opt->del.h_path);
18207+ break;
18208+ case Opt_mod:
18209+ case Opt_imod:
18210+ dput(opt->mod.h_root);
18211+ break;
18212+ case Opt_xino:
18213+ fput(opt->xino.file);
18214+ break;
18215+ }
18216+ opt++;
18217+ }
18218+}
18219+
18220+static int opt_add(struct au_opt *opt, char *opt_str, unsigned long sb_flags,
18221+ aufs_bindex_t bindex)
18222+{
18223+ int err;
18224+ struct au_opt_add *add = &opt->add;
18225+ char *p;
18226+
18227+ add->bindex = bindex;
18228+ add->perm = AuBrPerm_Last;
18229+ add->pathname = opt_str;
18230+ p = strchr(opt_str, '=');
18231+ if (p) {
18232+ *p++ = 0;
18233+ if (*p)
18234+ add->perm = br_perm_val(p);
18235+ }
18236+
18237+ err = vfsub_kern_path(add->pathname, lkup_dirflags, &add->path);
18238+ if (!err) {
18239+ if (!p) {
18240+ add->perm = AuBrPerm_RO;
18241+ if (au_test_fs_rr(add->path.dentry->d_sb))
18242+ add->perm = AuBrPerm_RR;
18243+ else if (!bindex && !(sb_flags & MS_RDONLY))
18244+ add->perm = AuBrPerm_RW;
18245+ }
18246+ opt->type = Opt_add;
18247+ goto out;
18248+ }
4a4d8108 18249+ pr_err("lookup failed %s (%d)\n", add->pathname, err);
1facf9fc 18250+ err = -EINVAL;
18251+
4f0767ce 18252+out:
1facf9fc 18253+ return err;
18254+}
18255+
18256+static int au_opts_parse_del(struct au_opt_del *del, substring_t args[])
18257+{
18258+ int err;
18259+
18260+ del->pathname = args[0].from;
18261+ AuDbg("del path %s\n", del->pathname);
18262+
18263+ err = vfsub_kern_path(del->pathname, lkup_dirflags, &del->h_path);
18264+ if (unlikely(err))
4a4d8108 18265+ pr_err("lookup failed %s (%d)\n", del->pathname, err);
1facf9fc 18266+
18267+ return err;
18268+}
18269+
18270+#if 0 /* reserved for future use */
18271+static int au_opts_parse_idel(struct super_block *sb, aufs_bindex_t bindex,
18272+ struct au_opt_del *del, substring_t args[])
18273+{
18274+ int err;
18275+ struct dentry *root;
18276+
18277+ err = -EINVAL;
18278+ root = sb->s_root;
18279+ aufs_read_lock(root, AuLock_FLUSH);
18280+ if (bindex < 0 || au_sbend(sb) < bindex) {
4a4d8108 18281+ pr_err("out of bounds, %d\n", bindex);
1facf9fc 18282+ goto out;
18283+ }
18284+
18285+ err = 0;
18286+ del->h_path.dentry = dget(au_h_dptr(root, bindex));
18287+ del->h_path.mnt = mntget(au_sbr_mnt(sb, bindex));
18288+
4f0767ce 18289+out:
1facf9fc 18290+ aufs_read_unlock(root, !AuLock_IR);
18291+ return err;
18292+}
18293+#endif
18294+
4a4d8108
AM
18295+static int noinline_for_stack
18296+au_opts_parse_mod(struct au_opt_mod *mod, substring_t args[])
1facf9fc 18297+{
18298+ int err;
18299+ struct path path;
18300+ char *p;
18301+
18302+ err = -EINVAL;
18303+ mod->path = args[0].from;
18304+ p = strchr(mod->path, '=');
18305+ if (unlikely(!p)) {
4a4d8108 18306+ pr_err("no permssion %s\n", args[0].from);
1facf9fc 18307+ goto out;
18308+ }
18309+
18310+ *p++ = 0;
18311+ err = vfsub_kern_path(mod->path, lkup_dirflags, &path);
18312+ if (unlikely(err)) {
4a4d8108 18313+ pr_err("lookup failed %s (%d)\n", mod->path, err);
1facf9fc 18314+ goto out;
18315+ }
18316+
18317+ mod->perm = br_perm_val(p);
18318+ AuDbg("mod path %s, perm 0x%x, %s\n", mod->path, mod->perm, p);
18319+ mod->h_root = dget(path.dentry);
18320+ path_put(&path);
18321+
4f0767ce 18322+out:
1facf9fc 18323+ return err;
18324+}
18325+
18326+#if 0 /* reserved for future use */
18327+static int au_opts_parse_imod(struct super_block *sb, aufs_bindex_t bindex,
18328+ struct au_opt_mod *mod, substring_t args[])
18329+{
18330+ int err;
18331+ struct dentry *root;
18332+
18333+ err = -EINVAL;
18334+ root = sb->s_root;
18335+ aufs_read_lock(root, AuLock_FLUSH);
18336+ if (bindex < 0 || au_sbend(sb) < bindex) {
4a4d8108 18337+ pr_err("out of bounds, %d\n", bindex);
1facf9fc 18338+ goto out;
18339+ }
18340+
18341+ err = 0;
18342+ mod->perm = br_perm_val(args[1].from);
18343+ AuDbg("mod path %s, perm 0x%x, %s\n",
18344+ mod->path, mod->perm, args[1].from);
18345+ mod->h_root = dget(au_h_dptr(root, bindex));
18346+
4f0767ce 18347+out:
1facf9fc 18348+ aufs_read_unlock(root, !AuLock_IR);
18349+ return err;
18350+}
18351+#endif
18352+
18353+static int au_opts_parse_xino(struct super_block *sb, struct au_opt_xino *xino,
18354+ substring_t args[])
18355+{
18356+ int err;
18357+ struct file *file;
18358+
18359+ file = au_xino_create(sb, args[0].from, /*silent*/0);
18360+ err = PTR_ERR(file);
18361+ if (IS_ERR(file))
18362+ goto out;
18363+
18364+ err = -EINVAL;
18365+ if (unlikely(file->f_dentry->d_sb == sb)) {
18366+ fput(file);
4a4d8108 18367+ pr_err("%s must be outside\n", args[0].from);
1facf9fc 18368+ goto out;
18369+ }
18370+
18371+ err = 0;
18372+ xino->file = file;
18373+ xino->path = args[0].from;
18374+
4f0767ce 18375+out:
1facf9fc 18376+ return err;
18377+}
18378+
4a4d8108
AM
18379+static int noinline_for_stack
18380+au_opts_parse_xino_itrunc_path(struct super_block *sb,
18381+ struct au_opt_xino_itrunc *xino_itrunc,
18382+ substring_t args[])
1facf9fc 18383+{
18384+ int err;
18385+ aufs_bindex_t bend, bindex;
18386+ struct path path;
18387+ struct dentry *root;
18388+
18389+ err = vfsub_kern_path(args[0].from, lkup_dirflags, &path);
18390+ if (unlikely(err)) {
4a4d8108 18391+ pr_err("lookup failed %s (%d)\n", args[0].from, err);
1facf9fc 18392+ goto out;
18393+ }
18394+
18395+ xino_itrunc->bindex = -1;
18396+ root = sb->s_root;
18397+ aufs_read_lock(root, AuLock_FLUSH);
18398+ bend = au_sbend(sb);
18399+ for (bindex = 0; bindex <= bend; bindex++) {
18400+ if (au_h_dptr(root, bindex) == path.dentry) {
18401+ xino_itrunc->bindex = bindex;
18402+ break;
18403+ }
18404+ }
18405+ aufs_read_unlock(root, !AuLock_IR);
18406+ path_put(&path);
18407+
18408+ if (unlikely(xino_itrunc->bindex < 0)) {
4a4d8108 18409+ pr_err("no such branch %s\n", args[0].from);
1facf9fc 18410+ err = -EINVAL;
18411+ }
18412+
4f0767ce 18413+out:
1facf9fc 18414+ return err;
18415+}
18416+
18417+/* called without aufs lock */
18418+int au_opts_parse(struct super_block *sb, char *str, struct au_opts *opts)
18419+{
18420+ int err, n, token;
18421+ aufs_bindex_t bindex;
18422+ unsigned char skipped;
18423+ struct dentry *root;
18424+ struct au_opt *opt, *opt_tail;
18425+ char *opt_str;
18426+ /* reduce the stack space */
18427+ union {
18428+ struct au_opt_xino_itrunc *xino_itrunc;
18429+ struct au_opt_wbr_create *create;
18430+ } u;
18431+ struct {
18432+ substring_t args[MAX_OPT_ARGS];
18433+ } *a;
18434+
18435+ err = -ENOMEM;
18436+ a = kmalloc(sizeof(*a), GFP_NOFS);
18437+ if (unlikely(!a))
18438+ goto out;
18439+
18440+ root = sb->s_root;
18441+ err = 0;
18442+ bindex = 0;
18443+ opt = opts->opt;
18444+ opt_tail = opt + opts->max_opt - 1;
18445+ opt->type = Opt_tail;
18446+ while (!err && (opt_str = strsep(&str, ",")) && *opt_str) {
18447+ err = -EINVAL;
18448+ skipped = 0;
18449+ token = match_token(opt_str, options, a->args);
18450+ switch (token) {
18451+ case Opt_br:
18452+ err = 0;
18453+ while (!err && (opt_str = strsep(&a->args[0].from, ":"))
18454+ && *opt_str) {
18455+ err = opt_add(opt, opt_str, opts->sb_flags,
18456+ bindex++);
18457+ if (unlikely(!err && ++opt > opt_tail)) {
18458+ err = -E2BIG;
18459+ break;
18460+ }
18461+ opt->type = Opt_tail;
18462+ skipped = 1;
18463+ }
18464+ break;
18465+ case Opt_add:
18466+ if (unlikely(match_int(&a->args[0], &n))) {
4a4d8108 18467+ pr_err("bad integer in %s\n", opt_str);
1facf9fc 18468+ break;
18469+ }
18470+ bindex = n;
18471+ err = opt_add(opt, a->args[1].from, opts->sb_flags,
18472+ bindex);
18473+ if (!err)
18474+ opt->type = token;
18475+ break;
18476+ case Opt_append:
18477+ err = opt_add(opt, a->args[0].from, opts->sb_flags,
18478+ /*dummy bindex*/1);
18479+ if (!err)
18480+ opt->type = token;
18481+ break;
18482+ case Opt_prepend:
18483+ err = opt_add(opt, a->args[0].from, opts->sb_flags,
18484+ /*bindex*/0);
18485+ if (!err)
18486+ opt->type = token;
18487+ break;
18488+ case Opt_del:
18489+ err = au_opts_parse_del(&opt->del, a->args);
18490+ if (!err)
18491+ opt->type = token;
18492+ break;
18493+#if 0 /* reserved for future use */
18494+ case Opt_idel:
18495+ del->pathname = "(indexed)";
18496+ if (unlikely(match_int(&args[0], &n))) {
4a4d8108 18497+ pr_err("bad integer in %s\n", opt_str);
1facf9fc 18498+ break;
18499+ }
18500+ err = au_opts_parse_idel(sb, n, &opt->del, a->args);
18501+ if (!err)
18502+ opt->type = token;
18503+ break;
18504+#endif
18505+ case Opt_mod:
18506+ err = au_opts_parse_mod(&opt->mod, a->args);
18507+ if (!err)
18508+ opt->type = token;
18509+ break;
18510+#ifdef IMOD /* reserved for future use */
18511+ case Opt_imod:
18512+ u.mod->path = "(indexed)";
18513+ if (unlikely(match_int(&a->args[0], &n))) {
4a4d8108 18514+ pr_err("bad integer in %s\n", opt_str);
1facf9fc 18515+ break;
18516+ }
18517+ err = au_opts_parse_imod(sb, n, &opt->mod, a->args);
18518+ if (!err)
18519+ opt->type = token;
18520+ break;
18521+#endif
18522+ case Opt_xino:
18523+ err = au_opts_parse_xino(sb, &opt->xino, a->args);
18524+ if (!err)
18525+ opt->type = token;
18526+ break;
18527+
18528+ case Opt_trunc_xino_path:
18529+ err = au_opts_parse_xino_itrunc_path
18530+ (sb, &opt->xino_itrunc, a->args);
18531+ if (!err)
18532+ opt->type = token;
18533+ break;
18534+
18535+ case Opt_itrunc_xino:
18536+ u.xino_itrunc = &opt->xino_itrunc;
18537+ if (unlikely(match_int(&a->args[0], &n))) {
4a4d8108 18538+ pr_err("bad integer in %s\n", opt_str);
1facf9fc 18539+ break;
18540+ }
18541+ u.xino_itrunc->bindex = n;
18542+ aufs_read_lock(root, AuLock_FLUSH);
18543+ if (n < 0 || au_sbend(sb) < n) {
4a4d8108 18544+ pr_err("out of bounds, %d\n", n);
1facf9fc 18545+ aufs_read_unlock(root, !AuLock_IR);
18546+ break;
18547+ }
18548+ aufs_read_unlock(root, !AuLock_IR);
18549+ err = 0;
18550+ opt->type = token;
18551+ break;
18552+
18553+ case Opt_dirwh:
18554+ if (unlikely(match_int(&a->args[0], &opt->dirwh)))
18555+ break;
18556+ err = 0;
18557+ opt->type = token;
18558+ break;
18559+
18560+ case Opt_rdcache:
027c5e7a
AM
18561+ if (unlikely(match_int(&a->args[0], &n))) {
18562+ pr_err("bad integer in %s\n", opt_str);
1facf9fc 18563+ break;
027c5e7a
AM
18564+ }
18565+ if (unlikely(n > AUFS_RDCACHE_MAX)) {
18566+ pr_err("rdcache must be smaller than %d\n",
18567+ AUFS_RDCACHE_MAX);
18568+ break;
18569+ }
18570+ opt->rdcache = n;
1facf9fc 18571+ err = 0;
18572+ opt->type = token;
18573+ break;
18574+ case Opt_rdblk:
18575+ if (unlikely(match_int(&a->args[0], &n)
1308ab2a 18576+ || n < 0
1facf9fc 18577+ || n > KMALLOC_MAX_SIZE)) {
4a4d8108 18578+ pr_err("bad integer in %s\n", opt_str);
1facf9fc 18579+ break;
18580+ }
1308ab2a 18581+ if (unlikely(n && n < NAME_MAX)) {
4a4d8108
AM
18582+ pr_err("rdblk must be larger than %d\n",
18583+ NAME_MAX);
1facf9fc 18584+ break;
18585+ }
18586+ opt->rdblk = n;
18587+ err = 0;
18588+ opt->type = token;
18589+ break;
18590+ case Opt_rdhash:
18591+ if (unlikely(match_int(&a->args[0], &n)
1308ab2a 18592+ || n < 0
1facf9fc 18593+ || n * sizeof(struct hlist_head)
18594+ > KMALLOC_MAX_SIZE)) {
4a4d8108 18595+ pr_err("bad integer in %s\n", opt_str);
1facf9fc 18596+ break;
18597+ }
18598+ opt->rdhash = n;
18599+ err = 0;
18600+ opt->type = token;
18601+ break;
18602+
18603+ case Opt_trunc_xino:
18604+ case Opt_notrunc_xino:
18605+ case Opt_noxino:
18606+ case Opt_trunc_xib:
18607+ case Opt_notrunc_xib:
dece6358
AM
18608+ case Opt_shwh:
18609+ case Opt_noshwh:
1facf9fc 18610+ case Opt_plink:
18611+ case Opt_noplink:
18612+ case Opt_list_plink:
4a4d8108
AM
18613+ case Opt_dio:
18614+ case Opt_nodio:
1facf9fc 18615+ case Opt_diropq_a:
18616+ case Opt_diropq_w:
18617+ case Opt_warn_perm:
18618+ case Opt_nowarn_perm:
18619+ case Opt_refrof:
18620+ case Opt_norefrof:
18621+ case Opt_verbose:
18622+ case Opt_noverbose:
18623+ case Opt_sum:
18624+ case Opt_nosum:
18625+ case Opt_wsum:
dece6358
AM
18626+ case Opt_rdblk_def:
18627+ case Opt_rdhash_def:
1facf9fc 18628+ err = 0;
18629+ opt->type = token;
18630+ break;
18631+
18632+ case Opt_udba:
18633+ opt->udba = udba_val(a->args[0].from);
18634+ if (opt->udba >= 0) {
18635+ err = 0;
18636+ opt->type = token;
18637+ } else
4a4d8108 18638+ pr_err("wrong value, %s\n", opt_str);
1facf9fc 18639+ break;
18640+
18641+ case Opt_wbr_create:
18642+ u.create = &opt->wbr_create;
18643+ u.create->wbr_create
18644+ = au_wbr_create_val(a->args[0].from, u.create);
18645+ if (u.create->wbr_create >= 0) {
18646+ err = 0;
18647+ opt->type = token;
18648+ } else
4a4d8108 18649+ pr_err("wrong value, %s\n", opt_str);
1facf9fc 18650+ break;
18651+ case Opt_wbr_copyup:
18652+ opt->wbr_copyup = au_wbr_copyup_val(a->args[0].from);
18653+ if (opt->wbr_copyup >= 0) {
18654+ err = 0;
18655+ opt->type = token;
18656+ } else
4a4d8108 18657+ pr_err("wrong value, %s\n", opt_str);
1facf9fc 18658+ break;
18659+
18660+ case Opt_ignore:
4a4d8108 18661+ pr_warning("ignored %s\n", opt_str);
1facf9fc 18662+ /*FALLTHROUGH*/
18663+ case Opt_ignore_silent:
18664+ skipped = 1;
18665+ err = 0;
18666+ break;
18667+ case Opt_err:
4a4d8108 18668+ pr_err("unknown option %s\n", opt_str);
1facf9fc 18669+ break;
18670+ }
18671+
18672+ if (!err && !skipped) {
18673+ if (unlikely(++opt > opt_tail)) {
18674+ err = -E2BIG;
18675+ opt--;
18676+ opt->type = Opt_tail;
18677+ break;
18678+ }
18679+ opt->type = Opt_tail;
18680+ }
18681+ }
18682+
18683+ kfree(a);
18684+ dump_opts(opts);
18685+ if (unlikely(err))
18686+ au_opts_free(opts);
18687+
4f0767ce 18688+out:
1facf9fc 18689+ return err;
18690+}
18691+
18692+static int au_opt_wbr_create(struct super_block *sb,
18693+ struct au_opt_wbr_create *create)
18694+{
18695+ int err;
18696+ struct au_sbinfo *sbinfo;
18697+
dece6358
AM
18698+ SiMustWriteLock(sb);
18699+
1facf9fc 18700+ err = 1; /* handled */
18701+ sbinfo = au_sbi(sb);
18702+ if (sbinfo->si_wbr_create_ops->fin) {
18703+ err = sbinfo->si_wbr_create_ops->fin(sb);
18704+ if (!err)
18705+ err = 1;
18706+ }
18707+
18708+ sbinfo->si_wbr_create = create->wbr_create;
18709+ sbinfo->si_wbr_create_ops = au_wbr_create_ops + create->wbr_create;
18710+ switch (create->wbr_create) {
18711+ case AuWbrCreate_MFSRRV:
18712+ case AuWbrCreate_MFSRR:
18713+ sbinfo->si_wbr_mfs.mfsrr_watermark = create->mfsrr_watermark;
18714+ /*FALLTHROUGH*/
18715+ case AuWbrCreate_MFS:
18716+ case AuWbrCreate_MFSV:
18717+ case AuWbrCreate_PMFS:
18718+ case AuWbrCreate_PMFSV:
e49829fe
JR
18719+ sbinfo->si_wbr_mfs.mfs_expire
18720+ = msecs_to_jiffies(create->mfs_second * MSEC_PER_SEC);
1facf9fc 18721+ break;
18722+ }
18723+
18724+ if (sbinfo->si_wbr_create_ops->init)
18725+ sbinfo->si_wbr_create_ops->init(sb); /* ignore */
18726+
18727+ return err;
18728+}
18729+
18730+/*
18731+ * returns,
18732+ * plus: processed without an error
18733+ * zero: unprocessed
18734+ */
18735+static int au_opt_simple(struct super_block *sb, struct au_opt *opt,
18736+ struct au_opts *opts)
18737+{
18738+ int err;
18739+ struct au_sbinfo *sbinfo;
18740+
dece6358
AM
18741+ SiMustWriteLock(sb);
18742+
1facf9fc 18743+ err = 1; /* handled */
18744+ sbinfo = au_sbi(sb);
18745+ switch (opt->type) {
18746+ case Opt_udba:
18747+ sbinfo->si_mntflags &= ~AuOptMask_UDBA;
18748+ sbinfo->si_mntflags |= opt->udba;
18749+ opts->given_udba |= opt->udba;
18750+ break;
18751+
18752+ case Opt_plink:
18753+ au_opt_set(sbinfo->si_mntflags, PLINK);
18754+ break;
18755+ case Opt_noplink:
18756+ if (au_opt_test(sbinfo->si_mntflags, PLINK))
e49829fe 18757+ au_plink_put(sb, /*verbose*/1);
1facf9fc 18758+ au_opt_clr(sbinfo->si_mntflags, PLINK);
18759+ break;
18760+ case Opt_list_plink:
18761+ if (au_opt_test(sbinfo->si_mntflags, PLINK))
18762+ au_plink_list(sb);
18763+ break;
18764+
4a4d8108
AM
18765+ case Opt_dio:
18766+ au_opt_set(sbinfo->si_mntflags, DIO);
18767+ au_fset_opts(opts->flags, REFRESH_DYAOP);
18768+ break;
18769+ case Opt_nodio:
18770+ au_opt_clr(sbinfo->si_mntflags, DIO);
18771+ au_fset_opts(opts->flags, REFRESH_DYAOP);
18772+ break;
18773+
1facf9fc 18774+ case Opt_diropq_a:
18775+ au_opt_set(sbinfo->si_mntflags, ALWAYS_DIROPQ);
18776+ break;
18777+ case Opt_diropq_w:
18778+ au_opt_clr(sbinfo->si_mntflags, ALWAYS_DIROPQ);
18779+ break;
18780+
18781+ case Opt_warn_perm:
18782+ au_opt_set(sbinfo->si_mntflags, WARN_PERM);
18783+ break;
18784+ case Opt_nowarn_perm:
18785+ au_opt_clr(sbinfo->si_mntflags, WARN_PERM);
18786+ break;
18787+
18788+ case Opt_refrof:
18789+ au_opt_set(sbinfo->si_mntflags, REFROF);
18790+ break;
18791+ case Opt_norefrof:
18792+ au_opt_clr(sbinfo->si_mntflags, REFROF);
18793+ break;
18794+
18795+ case Opt_verbose:
18796+ au_opt_set(sbinfo->si_mntflags, VERBOSE);
18797+ break;
18798+ case Opt_noverbose:
18799+ au_opt_clr(sbinfo->si_mntflags, VERBOSE);
18800+ break;
18801+
18802+ case Opt_sum:
18803+ au_opt_set(sbinfo->si_mntflags, SUM);
18804+ break;
18805+ case Opt_wsum:
18806+ au_opt_clr(sbinfo->si_mntflags, SUM);
18807+ au_opt_set(sbinfo->si_mntflags, SUM_W);
18808+ case Opt_nosum:
18809+ au_opt_clr(sbinfo->si_mntflags, SUM);
18810+ au_opt_clr(sbinfo->si_mntflags, SUM_W);
18811+ break;
18812+
18813+ case Opt_wbr_create:
18814+ err = au_opt_wbr_create(sb, &opt->wbr_create);
18815+ break;
18816+ case Opt_wbr_copyup:
18817+ sbinfo->si_wbr_copyup = opt->wbr_copyup;
18818+ sbinfo->si_wbr_copyup_ops = au_wbr_copyup_ops + opt->wbr_copyup;
18819+ break;
18820+
18821+ case Opt_dirwh:
18822+ sbinfo->si_dirwh = opt->dirwh;
18823+ break;
18824+
18825+ case Opt_rdcache:
e49829fe
JR
18826+ sbinfo->si_rdcache
18827+ = msecs_to_jiffies(opt->rdcache * MSEC_PER_SEC);
1facf9fc 18828+ break;
18829+ case Opt_rdblk:
18830+ sbinfo->si_rdblk = opt->rdblk;
18831+ break;
dece6358
AM
18832+ case Opt_rdblk_def:
18833+ sbinfo->si_rdblk = AUFS_RDBLK_DEF;
18834+ break;
1facf9fc 18835+ case Opt_rdhash:
18836+ sbinfo->si_rdhash = opt->rdhash;
18837+ break;
dece6358
AM
18838+ case Opt_rdhash_def:
18839+ sbinfo->si_rdhash = AUFS_RDHASH_DEF;
18840+ break;
18841+
18842+ case Opt_shwh:
18843+ au_opt_set(sbinfo->si_mntflags, SHWH);
18844+ break;
18845+ case Opt_noshwh:
18846+ au_opt_clr(sbinfo->si_mntflags, SHWH);
18847+ break;
1facf9fc 18848+
18849+ case Opt_trunc_xino:
18850+ au_opt_set(sbinfo->si_mntflags, TRUNC_XINO);
18851+ break;
18852+ case Opt_notrunc_xino:
18853+ au_opt_clr(sbinfo->si_mntflags, TRUNC_XINO);
18854+ break;
18855+
18856+ case Opt_trunc_xino_path:
18857+ case Opt_itrunc_xino:
18858+ err = au_xino_trunc(sb, opt->xino_itrunc.bindex);
18859+ if (!err)
18860+ err = 1;
18861+ break;
18862+
18863+ case Opt_trunc_xib:
18864+ au_fset_opts(opts->flags, TRUNC_XIB);
18865+ break;
18866+ case Opt_notrunc_xib:
18867+ au_fclr_opts(opts->flags, TRUNC_XIB);
18868+ break;
18869+
18870+ default:
18871+ err = 0;
18872+ break;
18873+ }
18874+
18875+ return err;
18876+}
18877+
18878+/*
18879+ * returns tri-state.
18880+ * plus: processed without an error
18881+ * zero: unprocessed
18882+ * minus: error
18883+ */
18884+static int au_opt_br(struct super_block *sb, struct au_opt *opt,
18885+ struct au_opts *opts)
18886+{
18887+ int err, do_refresh;
18888+
18889+ err = 0;
18890+ switch (opt->type) {
18891+ case Opt_append:
18892+ opt->add.bindex = au_sbend(sb) + 1;
18893+ if (opt->add.bindex < 0)
18894+ opt->add.bindex = 0;
18895+ goto add;
18896+ case Opt_prepend:
18897+ opt->add.bindex = 0;
18898+ add:
18899+ case Opt_add:
18900+ err = au_br_add(sb, &opt->add,
18901+ au_ftest_opts(opts->flags, REMOUNT));
18902+ if (!err) {
18903+ err = 1;
027c5e7a 18904+ au_fset_opts(opts->flags, REFRESH);
1facf9fc 18905+ }
18906+ break;
18907+
18908+ case Opt_del:
18909+ case Opt_idel:
18910+ err = au_br_del(sb, &opt->del,
18911+ au_ftest_opts(opts->flags, REMOUNT));
18912+ if (!err) {
18913+ err = 1;
18914+ au_fset_opts(opts->flags, TRUNC_XIB);
027c5e7a 18915+ au_fset_opts(opts->flags, REFRESH);
1facf9fc 18916+ }
18917+ break;
18918+
18919+ case Opt_mod:
18920+ case Opt_imod:
18921+ err = au_br_mod(sb, &opt->mod,
18922+ au_ftest_opts(opts->flags, REMOUNT),
18923+ &do_refresh);
18924+ if (!err) {
18925+ err = 1;
027c5e7a
AM
18926+ if (do_refresh)
18927+ au_fset_opts(opts->flags, REFRESH);
1facf9fc 18928+ }
18929+ break;
18930+ }
18931+
18932+ return err;
18933+}
18934+
18935+static int au_opt_xino(struct super_block *sb, struct au_opt *opt,
18936+ struct au_opt_xino **opt_xino,
18937+ struct au_opts *opts)
18938+{
18939+ int err;
18940+ aufs_bindex_t bend, bindex;
18941+ struct dentry *root, *parent, *h_root;
18942+
18943+ err = 0;
18944+ switch (opt->type) {
18945+ case Opt_xino:
18946+ err = au_xino_set(sb, &opt->xino,
18947+ !!au_ftest_opts(opts->flags, REMOUNT));
18948+ if (unlikely(err))
18949+ break;
18950+
18951+ *opt_xino = &opt->xino;
18952+ au_xino_brid_set(sb, -1);
18953+
18954+ /* safe d_parent access */
18955+ parent = opt->xino.file->f_dentry->d_parent;
18956+ root = sb->s_root;
18957+ bend = au_sbend(sb);
18958+ for (bindex = 0; bindex <= bend; bindex++) {
18959+ h_root = au_h_dptr(root, bindex);
18960+ if (h_root == parent) {
18961+ au_xino_brid_set(sb, au_sbr_id(sb, bindex));
18962+ break;
18963+ }
18964+ }
18965+ break;
18966+
18967+ case Opt_noxino:
18968+ au_xino_clr(sb);
18969+ au_xino_brid_set(sb, -1);
18970+ *opt_xino = (void *)-1;
18971+ break;
18972+ }
18973+
18974+ return err;
18975+}
18976+
18977+int au_opts_verify(struct super_block *sb, unsigned long sb_flags,
18978+ unsigned int pending)
18979+{
18980+ int err;
18981+ aufs_bindex_t bindex, bend;
18982+ unsigned char do_plink, skip, do_free;
18983+ struct au_branch *br;
18984+ struct au_wbr *wbr;
18985+ struct dentry *root;
18986+ struct inode *dir, *h_dir;
18987+ struct au_sbinfo *sbinfo;
18988+ struct au_hinode *hdir;
18989+
dece6358
AM
18990+ SiMustAnyLock(sb);
18991+
1facf9fc 18992+ sbinfo = au_sbi(sb);
18993+ AuDebugOn(!(sbinfo->si_mntflags & AuOptMask_UDBA));
18994+
dece6358
AM
18995+ if (!(sb_flags & MS_RDONLY)) {
18996+ if (unlikely(!au_br_writable(au_sbr_perm(sb, 0))))
4a4d8108 18997+ pr_warning("first branch should be rw\n");
dece6358 18998+ if (unlikely(au_opt_test(sbinfo->si_mntflags, SHWH)))
4a4d8108 18999+ pr_warning("shwh should be used with ro\n");
dece6358 19000+ }
1facf9fc 19001+
4a4d8108 19002+ if (au_opt_test((sbinfo->si_mntflags | pending), UDBA_HNOTIFY)
1facf9fc 19003+ && !au_opt_test(sbinfo->si_mntflags, XINO))
4a4d8108 19004+ pr_warning("udba=*notify requires xino\n");
1facf9fc 19005+
19006+ err = 0;
19007+ root = sb->s_root;
4a4d8108 19008+ dir = root->d_inode;
1facf9fc 19009+ do_plink = !!au_opt_test(sbinfo->si_mntflags, PLINK);
19010+ bend = au_sbend(sb);
19011+ for (bindex = 0; !err && bindex <= bend; bindex++) {
19012+ skip = 0;
19013+ h_dir = au_h_iptr(dir, bindex);
19014+ br = au_sbr(sb, bindex);
19015+ do_free = 0;
19016+
19017+ wbr = br->br_wbr;
19018+ if (wbr)
19019+ wbr_wh_read_lock(wbr);
19020+
19021+ switch (br->br_perm) {
19022+ case AuBrPerm_RO:
19023+ case AuBrPerm_ROWH:
19024+ case AuBrPerm_RR:
19025+ case AuBrPerm_RRWH:
19026+ do_free = !!wbr;
19027+ skip = (!wbr
19028+ || (!wbr->wbr_whbase
19029+ && !wbr->wbr_plink
19030+ && !wbr->wbr_orph));
19031+ break;
19032+
19033+ case AuBrPerm_RWNoLinkWH:
19034+ /* skip = (!br->br_whbase && !br->br_orph); */
19035+ skip = (!wbr || !wbr->wbr_whbase);
19036+ if (skip && wbr) {
19037+ if (do_plink)
19038+ skip = !!wbr->wbr_plink;
19039+ else
19040+ skip = !wbr->wbr_plink;
19041+ }
19042+ break;
19043+
19044+ case AuBrPerm_RW:
19045+ /* skip = (br->br_whbase && br->br_ohph); */
19046+ skip = (wbr && wbr->wbr_whbase);
19047+ if (skip) {
19048+ if (do_plink)
19049+ skip = !!wbr->wbr_plink;
19050+ else
19051+ skip = !wbr->wbr_plink;
19052+ }
19053+ break;
19054+
19055+ default:
19056+ BUG();
19057+ }
19058+ if (wbr)
19059+ wbr_wh_read_unlock(wbr);
19060+
19061+ if (skip)
19062+ continue;
19063+
19064+ hdir = au_hi(dir, bindex);
4a4d8108 19065+ au_hn_imtx_lock_nested(hdir, AuLsc_I_PARENT);
1facf9fc 19066+ if (wbr)
19067+ wbr_wh_write_lock(wbr);
19068+ err = au_wh_init(au_h_dptr(root, bindex), br, sb);
19069+ if (wbr)
19070+ wbr_wh_write_unlock(wbr);
4a4d8108 19071+ au_hn_imtx_unlock(hdir);
1facf9fc 19072+
19073+ if (!err && do_free) {
19074+ kfree(wbr);
19075+ br->br_wbr = NULL;
19076+ }
19077+ }
19078+
19079+ return err;
19080+}
19081+
19082+int au_opts_mount(struct super_block *sb, struct au_opts *opts)
19083+{
19084+ int err;
19085+ unsigned int tmp;
027c5e7a 19086+ aufs_bindex_t bindex, bend;
1facf9fc 19087+ struct au_opt *opt;
19088+ struct au_opt_xino *opt_xino, xino;
19089+ struct au_sbinfo *sbinfo;
027c5e7a 19090+ struct au_branch *br;
1facf9fc 19091+
dece6358
AM
19092+ SiMustWriteLock(sb);
19093+
1facf9fc 19094+ err = 0;
19095+ opt_xino = NULL;
19096+ opt = opts->opt;
19097+ while (err >= 0 && opt->type != Opt_tail)
19098+ err = au_opt_simple(sb, opt++, opts);
19099+ if (err > 0)
19100+ err = 0;
19101+ else if (unlikely(err < 0))
19102+ goto out;
19103+
19104+ /* disable xino and udba temporary */
19105+ sbinfo = au_sbi(sb);
19106+ tmp = sbinfo->si_mntflags;
19107+ au_opt_clr(sbinfo->si_mntflags, XINO);
19108+ au_opt_set_udba(sbinfo->si_mntflags, UDBA_REVAL);
19109+
19110+ opt = opts->opt;
19111+ while (err >= 0 && opt->type != Opt_tail)
19112+ err = au_opt_br(sb, opt++, opts);
19113+ if (err > 0)
19114+ err = 0;
19115+ else if (unlikely(err < 0))
19116+ goto out;
19117+
19118+ bend = au_sbend(sb);
19119+ if (unlikely(bend < 0)) {
19120+ err = -EINVAL;
4a4d8108 19121+ pr_err("no branches\n");
1facf9fc 19122+ goto out;
19123+ }
19124+
19125+ if (au_opt_test(tmp, XINO))
19126+ au_opt_set(sbinfo->si_mntflags, XINO);
19127+ opt = opts->opt;
19128+ while (!err && opt->type != Opt_tail)
19129+ err = au_opt_xino(sb, opt++, &opt_xino, opts);
19130+ if (unlikely(err))
19131+ goto out;
19132+
19133+ err = au_opts_verify(sb, sb->s_flags, tmp);
19134+ if (unlikely(err))
19135+ goto out;
19136+
19137+ /* restore xino */
19138+ if (au_opt_test(tmp, XINO) && !opt_xino) {
19139+ xino.file = au_xino_def(sb);
19140+ err = PTR_ERR(xino.file);
19141+ if (IS_ERR(xino.file))
19142+ goto out;
19143+
19144+ err = au_xino_set(sb, &xino, /*remount*/0);
19145+ fput(xino.file);
19146+ if (unlikely(err))
19147+ goto out;
19148+ }
19149+
19150+ /* restore udba */
027c5e7a 19151+ tmp &= AuOptMask_UDBA;
1facf9fc 19152+ sbinfo->si_mntflags &= ~AuOptMask_UDBA;
027c5e7a
AM
19153+ sbinfo->si_mntflags |= tmp;
19154+ bend = au_sbend(sb);
19155+ for (bindex = 0; bindex <= bend; bindex++) {
19156+ br = au_sbr(sb, bindex);
19157+ err = au_hnotify_reset_br(tmp, br, br->br_perm);
19158+ if (unlikely(err))
19159+ AuIOErr("hnotify failed on br %d, %d, ignored\n",
19160+ bindex, err);
19161+ /* go on even if err */
19162+ }
4a4d8108 19163+ if (au_opt_test(tmp, UDBA_HNOTIFY)) {
1facf9fc 19164+ struct inode *dir = sb->s_root->d_inode;
4a4d8108 19165+ au_hn_reset(dir, au_hi_flags(dir, /*isdir*/1) & ~AuHi_XINO);
1facf9fc 19166+ }
19167+
4f0767ce 19168+out:
1facf9fc 19169+ return err;
19170+}
19171+
19172+int au_opts_remount(struct super_block *sb, struct au_opts *opts)
19173+{
19174+ int err, rerr;
19175+ struct inode *dir;
19176+ struct au_opt_xino *opt_xino;
19177+ struct au_opt *opt;
19178+ struct au_sbinfo *sbinfo;
19179+
dece6358
AM
19180+ SiMustWriteLock(sb);
19181+
1facf9fc 19182+ dir = sb->s_root->d_inode;
19183+ sbinfo = au_sbi(sb);
19184+ err = 0;
19185+ opt_xino = NULL;
19186+ opt = opts->opt;
19187+ while (err >= 0 && opt->type != Opt_tail) {
19188+ err = au_opt_simple(sb, opt, opts);
19189+ if (!err)
19190+ err = au_opt_br(sb, opt, opts);
19191+ if (!err)
19192+ err = au_opt_xino(sb, opt, &opt_xino, opts);
19193+ opt++;
19194+ }
19195+ if (err > 0)
19196+ err = 0;
19197+ AuTraceErr(err);
19198+ /* go on even err */
19199+
19200+ rerr = au_opts_verify(sb, opts->sb_flags, /*pending*/0);
19201+ if (unlikely(rerr && !err))
19202+ err = rerr;
19203+
19204+ if (au_ftest_opts(opts->flags, TRUNC_XIB)) {
19205+ rerr = au_xib_trunc(sb);
19206+ if (unlikely(rerr && !err))
19207+ err = rerr;
19208+ }
19209+
19210+ /* will be handled by the caller */
027c5e7a 19211+ if (!au_ftest_opts(opts->flags, REFRESH)
1facf9fc 19212+ && (opts->given_udba || au_opt_test(sbinfo->si_mntflags, XINO)))
027c5e7a 19213+ au_fset_opts(opts->flags, REFRESH);
1facf9fc 19214+
19215+ AuDbg("status 0x%x\n", opts->flags);
19216+ return err;
19217+}
19218+
19219+/* ---------------------------------------------------------------------- */
19220+
19221+unsigned int au_opt_udba(struct super_block *sb)
19222+{
19223+ return au_mntflags(sb) & AuOptMask_UDBA;
19224+}
7f207e10
AM
19225diff -urN /usr/share/empty/fs/aufs/opts.h linux/fs/aufs/opts.h
19226--- /usr/share/empty/fs/aufs/opts.h 1970-01-01 01:00:00.000000000 +0100
2cbb1c4b 19227+++ linux/fs/aufs/opts.h 2011-07-11 11:34:24.076331673 +0200
027c5e7a 19228@@ -0,0 +1,210 @@
1facf9fc 19229+/*
027c5e7a 19230+ * Copyright (C) 2005-2011 Junjiro R. Okajima
1facf9fc 19231+ *
19232+ * This program, aufs is free software; you can redistribute it and/or modify
19233+ * it under the terms of the GNU General Public License as published by
19234+ * the Free Software Foundation; either version 2 of the License, or
19235+ * (at your option) any later version.
dece6358
AM
19236+ *
19237+ * This program is distributed in the hope that it will be useful,
19238+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
19239+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19240+ * GNU General Public License for more details.
19241+ *
19242+ * You should have received a copy of the GNU General Public License
19243+ * along with this program; if not, write to the Free Software
19244+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 19245+ */
19246+
19247+/*
19248+ * mount options/flags
19249+ */
19250+
19251+#ifndef __AUFS_OPTS_H__
19252+#define __AUFS_OPTS_H__
19253+
19254+#ifdef __KERNEL__
19255+
dece6358 19256+#include <linux/path.h>
1facf9fc 19257+#include <linux/aufs_type.h>
19258+
dece6358
AM
19259+struct file;
19260+struct super_block;
19261+
1facf9fc 19262+/* ---------------------------------------------------------------------- */
19263+
19264+/* mount flags */
19265+#define AuOpt_XINO 1 /* external inode number bitmap
19266+ and translation table */
19267+#define AuOpt_TRUNC_XINO (1 << 1) /* truncate xino files */
19268+#define AuOpt_UDBA_NONE (1 << 2) /* users direct branch access */
19269+#define AuOpt_UDBA_REVAL (1 << 3)
4a4d8108 19270+#define AuOpt_UDBA_HNOTIFY (1 << 4)
dece6358
AM
19271+#define AuOpt_SHWH (1 << 5) /* show whiteout */
19272+#define AuOpt_PLINK (1 << 6) /* pseudo-link */
19273+#define AuOpt_DIRPERM1 (1 << 7) /* unimplemented */
19274+#define AuOpt_REFROF (1 << 8) /* unimplemented */
19275+#define AuOpt_ALWAYS_DIROPQ (1 << 9) /* policy to creating diropq */
19276+#define AuOpt_SUM (1 << 10) /* summation for statfs(2) */
19277+#define AuOpt_SUM_W (1 << 11) /* unimplemented */
19278+#define AuOpt_WARN_PERM (1 << 12) /* warn when add-branch */
19279+#define AuOpt_VERBOSE (1 << 13) /* busy inode when del-branch */
4a4d8108 19280+#define AuOpt_DIO (1 << 14) /* direct io */
1facf9fc 19281+
4a4d8108
AM
19282+#ifndef CONFIG_AUFS_HNOTIFY
19283+#undef AuOpt_UDBA_HNOTIFY
19284+#define AuOpt_UDBA_HNOTIFY 0
1facf9fc 19285+#endif
dece6358
AM
19286+#ifndef CONFIG_AUFS_SHWH
19287+#undef AuOpt_SHWH
19288+#define AuOpt_SHWH 0
19289+#endif
1facf9fc 19290+
19291+#define AuOpt_Def (AuOpt_XINO \
19292+ | AuOpt_UDBA_REVAL \
19293+ | AuOpt_PLINK \
19294+ /* | AuOpt_DIRPERM1 */ \
19295+ | AuOpt_WARN_PERM)
19296+#define AuOptMask_UDBA (AuOpt_UDBA_NONE \
19297+ | AuOpt_UDBA_REVAL \
4a4d8108 19298+ | AuOpt_UDBA_HNOTIFY)
1facf9fc 19299+
19300+#define au_opt_test(flags, name) (flags & AuOpt_##name)
19301+#define au_opt_set(flags, name) do { \
19302+ BUILD_BUG_ON(AuOpt_##name & AuOptMask_UDBA); \
19303+ ((flags) |= AuOpt_##name); \
19304+} while (0)
19305+#define au_opt_set_udba(flags, name) do { \
19306+ (flags) &= ~AuOptMask_UDBA; \
19307+ ((flags) |= AuOpt_##name); \
19308+} while (0)
7f207e10
AM
19309+#define au_opt_clr(flags, name) do { \
19310+ ((flags) &= ~AuOpt_##name); \
19311+} while (0)
1facf9fc 19312+
e49829fe
JR
19313+static inline unsigned int au_opts_plink(unsigned int mntflags)
19314+{
19315+#ifdef CONFIG_PROC_FS
19316+ return mntflags;
19317+#else
19318+ return mntflags & ~AuOpt_PLINK;
19319+#endif
19320+}
19321+
1facf9fc 19322+/* ---------------------------------------------------------------------- */
19323+
19324+/* policies to select one among multiple writable branches */
19325+enum {
19326+ AuWbrCreate_TDP, /* top down parent */
19327+ AuWbrCreate_RR, /* round robin */
19328+ AuWbrCreate_MFS, /* most free space */
19329+ AuWbrCreate_MFSV, /* mfs with seconds */
19330+ AuWbrCreate_MFSRR, /* mfs then rr */
19331+ AuWbrCreate_MFSRRV, /* mfs then rr with seconds */
19332+ AuWbrCreate_PMFS, /* parent and mfs */
19333+ AuWbrCreate_PMFSV, /* parent and mfs with seconds */
19334+
19335+ AuWbrCreate_Def = AuWbrCreate_TDP
19336+};
19337+
19338+enum {
19339+ AuWbrCopyup_TDP, /* top down parent */
19340+ AuWbrCopyup_BUP, /* bottom up parent */
19341+ AuWbrCopyup_BU, /* bottom up */
19342+
19343+ AuWbrCopyup_Def = AuWbrCopyup_TDP
19344+};
19345+
19346+/* ---------------------------------------------------------------------- */
19347+
19348+struct au_opt_add {
19349+ aufs_bindex_t bindex;
19350+ char *pathname;
19351+ int perm;
19352+ struct path path;
19353+};
19354+
19355+struct au_opt_del {
19356+ char *pathname;
19357+ struct path h_path;
19358+};
19359+
19360+struct au_opt_mod {
19361+ char *path;
19362+ int perm;
19363+ struct dentry *h_root;
19364+};
19365+
19366+struct au_opt_xino {
19367+ char *path;
19368+ struct file *file;
19369+};
19370+
19371+struct au_opt_xino_itrunc {
19372+ aufs_bindex_t bindex;
19373+};
19374+
19375+struct au_opt_wbr_create {
19376+ int wbr_create;
19377+ int mfs_second;
19378+ unsigned long long mfsrr_watermark;
19379+};
19380+
19381+struct au_opt {
19382+ int type;
19383+ union {
19384+ struct au_opt_xino xino;
19385+ struct au_opt_xino_itrunc xino_itrunc;
19386+ struct au_opt_add add;
19387+ struct au_opt_del del;
19388+ struct au_opt_mod mod;
19389+ int dirwh;
19390+ int rdcache;
19391+ unsigned int rdblk;
19392+ unsigned int rdhash;
19393+ int udba;
19394+ struct au_opt_wbr_create wbr_create;
19395+ int wbr_copyup;
19396+ };
19397+};
19398+
19399+/* opts flags */
19400+#define AuOpts_REMOUNT 1
027c5e7a
AM
19401+#define AuOpts_REFRESH (1 << 1)
19402+#define AuOpts_TRUNC_XIB (1 << 2)
19403+#define AuOpts_REFRESH_DYAOP (1 << 3)
1facf9fc 19404+#define au_ftest_opts(flags, name) ((flags) & AuOpts_##name)
7f207e10
AM
19405+#define au_fset_opts(flags, name) \
19406+ do { (flags) |= AuOpts_##name; } while (0)
19407+#define au_fclr_opts(flags, name) \
19408+ do { (flags) &= ~AuOpts_##name; } while (0)
1facf9fc 19409+
19410+struct au_opts {
19411+ struct au_opt *opt;
19412+ int max_opt;
19413+
19414+ unsigned int given_udba;
19415+ unsigned int flags;
19416+ unsigned long sb_flags;
19417+};
19418+
19419+/* ---------------------------------------------------------------------- */
19420+
19421+const char *au_optstr_br_perm(int brperm);
19422+const char *au_optstr_udba(int udba);
19423+const char *au_optstr_wbr_copyup(int wbr_copyup);
19424+const char *au_optstr_wbr_create(int wbr_create);
19425+
19426+void au_opts_free(struct au_opts *opts);
19427+int au_opts_parse(struct super_block *sb, char *str, struct au_opts *opts);
19428+int au_opts_verify(struct super_block *sb, unsigned long sb_flags,
19429+ unsigned int pending);
19430+int au_opts_mount(struct super_block *sb, struct au_opts *opts);
19431+int au_opts_remount(struct super_block *sb, struct au_opts *opts);
19432+
19433+unsigned int au_opt_udba(struct super_block *sb);
19434+
19435+/* ---------------------------------------------------------------------- */
19436+
19437+#endif /* __KERNEL__ */
19438+#endif /* __AUFS_OPTS_H__ */
7f207e10
AM
19439diff -urN /usr/share/empty/fs/aufs/plink.c linux/fs/aufs/plink.c
19440--- /usr/share/empty/fs/aufs/plink.c 1970-01-01 01:00:00.000000000 +0100
2cbb1c4b 19441+++ linux/fs/aufs/plink.c 2011-07-11 11:34:24.076331673 +0200
027c5e7a 19442@@ -0,0 +1,515 @@
1facf9fc 19443+/*
027c5e7a 19444+ * Copyright (C) 2005-2011 Junjiro R. Okajima
1facf9fc 19445+ *
19446+ * This program, aufs is free software; you can redistribute it and/or modify
19447+ * it under the terms of the GNU General Public License as published by
19448+ * the Free Software Foundation; either version 2 of the License, or
19449+ * (at your option) any later version.
dece6358
AM
19450+ *
19451+ * This program is distributed in the hope that it will be useful,
19452+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
19453+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19454+ * GNU General Public License for more details.
19455+ *
19456+ * You should have received a copy of the GNU General Public License
19457+ * along with this program; if not, write to the Free Software
19458+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 19459+ */
19460+
19461+/*
19462+ * pseudo-link
19463+ */
19464+
19465+#include "aufs.h"
19466+
19467+/*
e49829fe 19468+ * the pseudo-link maintenance mode.
1facf9fc 19469+ * during a user process maintains the pseudo-links,
19470+ * prohibit adding a new plink and branch manipulation.
e49829fe
JR
19471+ *
19472+ * Flags
19473+ * NOPLM:
19474+ * For entry functions which will handle plink, and i_mutex is already held
19475+ * in VFS.
19476+ * They cannot wait and should return an error at once.
19477+ * Callers has to check the error.
19478+ * NOPLMW:
19479+ * For entry functions which will handle plink, but i_mutex is not held
19480+ * in VFS.
19481+ * They can wait the plink maintenance mode to finish.
19482+ *
19483+ * They behave like F_SETLK and F_SETLKW.
19484+ * If the caller never handle plink, then both flags are unnecessary.
1facf9fc 19485+ */
e49829fe
JR
19486+
19487+int au_plink_maint(struct super_block *sb, int flags)
1facf9fc 19488+{
e49829fe
JR
19489+ int err;
19490+ pid_t pid, ppid;
19491+ struct au_sbinfo *sbi;
dece6358
AM
19492+
19493+ SiMustAnyLock(sb);
19494+
e49829fe
JR
19495+ err = 0;
19496+ if (!au_opt_test(au_mntflags(sb), PLINK))
19497+ goto out;
19498+
19499+ sbi = au_sbi(sb);
19500+ pid = sbi->si_plink_maint_pid;
19501+ if (!pid || pid == current->pid)
19502+ goto out;
19503+
19504+ /* todo: it highly depends upon /sbin/mount.aufs */
19505+ rcu_read_lock();
19506+ ppid = task_pid_vnr(rcu_dereference(current->real_parent));
19507+ rcu_read_unlock();
19508+ if (pid == ppid)
19509+ goto out;
19510+
19511+ if (au_ftest_lock(flags, NOPLMW)) {
027c5e7a
AM
19512+ /* if there is no i_mutex lock in VFS, we don't need to wait */
19513+ /* AuDebugOn(!lockdep_depth(current)); */
e49829fe
JR
19514+ while (sbi->si_plink_maint_pid) {
19515+ si_read_unlock(sb);
19516+ /* gave up wake_up_bit() */
19517+ wait_event(sbi->si_plink_wq, !sbi->si_plink_maint_pid);
19518+
19519+ if (au_ftest_lock(flags, FLUSH))
19520+ au_nwt_flush(&sbi->si_nowait);
19521+ si_noflush_read_lock(sb);
19522+ }
19523+ } else if (au_ftest_lock(flags, NOPLM)) {
19524+ AuDbg("ppid %d, pid %d\n", ppid, pid);
19525+ err = -EAGAIN;
19526+ }
19527+
19528+out:
19529+ return err;
4a4d8108
AM
19530+}
19531+
e49829fe 19532+void au_plink_maint_leave(struct au_sbinfo *sbinfo)
4a4d8108 19533+{
4a4d8108 19534+ spin_lock(&sbinfo->si_plink_maint_lock);
027c5e7a 19535+ sbinfo->si_plink_maint_pid = 0;
4a4d8108 19536+ spin_unlock(&sbinfo->si_plink_maint_lock);
027c5e7a 19537+ wake_up_all(&sbinfo->si_plink_wq);
4a4d8108
AM
19538+}
19539+
e49829fe 19540+int au_plink_maint_enter(struct super_block *sb)
4a4d8108
AM
19541+{
19542+ int err;
4a4d8108
AM
19543+ struct au_sbinfo *sbinfo;
19544+
19545+ err = 0;
4a4d8108
AM
19546+ sbinfo = au_sbi(sb);
19547+ /* make sure i am the only one in this fs */
e49829fe
JR
19548+ si_write_lock(sb, AuLock_FLUSH);
19549+ if (au_opt_test(au_mntflags(sb), PLINK)) {
19550+ spin_lock(&sbinfo->si_plink_maint_lock);
19551+ if (!sbinfo->si_plink_maint_pid)
19552+ sbinfo->si_plink_maint_pid = current->pid;
19553+ else
19554+ err = -EBUSY;
19555+ spin_unlock(&sbinfo->si_plink_maint_lock);
19556+ }
4a4d8108
AM
19557+ si_write_unlock(sb);
19558+
19559+ return err;
1facf9fc 19560+}
19561+
19562+/* ---------------------------------------------------------------------- */
19563+
19564+struct pseudo_link {
4a4d8108
AM
19565+ union {
19566+ struct list_head list;
19567+ struct rcu_head rcu;
19568+ };
1facf9fc 19569+ struct inode *inode;
19570+};
19571+
19572+#ifdef CONFIG_AUFS_DEBUG
19573+void au_plink_list(struct super_block *sb)
19574+{
19575+ struct au_sbinfo *sbinfo;
19576+ struct list_head *plink_list;
19577+ struct pseudo_link *plink;
19578+
dece6358
AM
19579+ SiMustAnyLock(sb);
19580+
1facf9fc 19581+ sbinfo = au_sbi(sb);
19582+ AuDebugOn(!au_opt_test(au_mntflags(sb), PLINK));
e49829fe 19583+ AuDebugOn(au_plink_maint(sb, AuLock_NOPLM));
1facf9fc 19584+
19585+ plink_list = &sbinfo->si_plink.head;
4a4d8108
AM
19586+ rcu_read_lock();
19587+ list_for_each_entry_rcu(plink, plink_list, list)
1facf9fc 19588+ AuDbg("%lu\n", plink->inode->i_ino);
4a4d8108 19589+ rcu_read_unlock();
1facf9fc 19590+}
19591+#endif
19592+
19593+/* is the inode pseudo-linked? */
19594+int au_plink_test(struct inode *inode)
19595+{
19596+ int found;
19597+ struct au_sbinfo *sbinfo;
19598+ struct list_head *plink_list;
19599+ struct pseudo_link *plink;
19600+
19601+ sbinfo = au_sbi(inode->i_sb);
dece6358 19602+ AuRwMustAnyLock(&sbinfo->si_rwsem);
1facf9fc 19603+ AuDebugOn(!au_opt_test(au_mntflags(inode->i_sb), PLINK));
e49829fe 19604+ AuDebugOn(au_plink_maint(inode->i_sb, AuLock_NOPLM));
1facf9fc 19605+
19606+ found = 0;
19607+ plink_list = &sbinfo->si_plink.head;
4a4d8108
AM
19608+ rcu_read_lock();
19609+ list_for_each_entry_rcu(plink, plink_list, list)
1facf9fc 19610+ if (plink->inode == inode) {
19611+ found = 1;
19612+ break;
19613+ }
4a4d8108 19614+ rcu_read_unlock();
1facf9fc 19615+ return found;
19616+}
19617+
19618+/* ---------------------------------------------------------------------- */
19619+
19620+/*
19621+ * generate a name for plink.
19622+ * the file will be stored under AUFS_WH_PLINKDIR.
19623+ */
19624+/* 20 is max digits length of ulong 64 */
19625+#define PLINK_NAME_LEN ((20 + 1) * 2)
19626+
19627+static int plink_name(char *name, int len, struct inode *inode,
19628+ aufs_bindex_t bindex)
19629+{
19630+ int rlen;
19631+ struct inode *h_inode;
19632+
19633+ h_inode = au_h_iptr(inode, bindex);
19634+ rlen = snprintf(name, len, "%lu.%lu", inode->i_ino, h_inode->i_ino);
19635+ return rlen;
19636+}
19637+
7f207e10
AM
19638+struct au_do_plink_lkup_args {
19639+ struct dentry **errp;
19640+ struct qstr *tgtname;
19641+ struct dentry *h_parent;
19642+ struct au_branch *br;
19643+};
19644+
19645+static struct dentry *au_do_plink_lkup(struct qstr *tgtname,
19646+ struct dentry *h_parent,
19647+ struct au_branch *br)
19648+{
19649+ struct dentry *h_dentry;
19650+ struct mutex *h_mtx;
19651+
19652+ h_mtx = &h_parent->d_inode->i_mutex;
19653+ mutex_lock_nested(h_mtx, AuLsc_I_CHILD2);
19654+ h_dentry = au_lkup_one(tgtname, h_parent, br, /*nd*/NULL);
19655+ mutex_unlock(h_mtx);
19656+ return h_dentry;
19657+}
19658+
19659+static void au_call_do_plink_lkup(void *args)
19660+{
19661+ struct au_do_plink_lkup_args *a = args;
19662+ *a->errp = au_do_plink_lkup(a->tgtname, a->h_parent, a->br);
19663+}
19664+
1facf9fc 19665+/* lookup the plink-ed @inode under the branch at @bindex */
19666+struct dentry *au_plink_lkup(struct inode *inode, aufs_bindex_t bindex)
19667+{
19668+ struct dentry *h_dentry, *h_parent;
19669+ struct au_branch *br;
19670+ struct inode *h_dir;
7f207e10 19671+ int wkq_err;
1facf9fc 19672+ char a[PLINK_NAME_LEN];
19673+ struct qstr tgtname = {
19674+ .name = a
19675+ };
19676+
e49829fe
JR
19677+ AuDebugOn(au_plink_maint(inode->i_sb, AuLock_NOPLM));
19678+
1facf9fc 19679+ br = au_sbr(inode->i_sb, bindex);
19680+ h_parent = br->br_wbr->wbr_plink;
19681+ h_dir = h_parent->d_inode;
19682+ tgtname.len = plink_name(a, sizeof(a), inode, bindex);
19683+
7f207e10
AM
19684+ if (current_fsuid()) {
19685+ struct au_do_plink_lkup_args args = {
19686+ .errp = &h_dentry,
19687+ .tgtname = &tgtname,
19688+ .h_parent = h_parent,
19689+ .br = br
19690+ };
19691+
19692+ wkq_err = au_wkq_wait(au_call_do_plink_lkup, &args);
19693+ if (unlikely(wkq_err))
19694+ h_dentry = ERR_PTR(wkq_err);
19695+ } else
19696+ h_dentry = au_do_plink_lkup(&tgtname, h_parent, br);
19697+
1facf9fc 19698+ return h_dentry;
19699+}
19700+
19701+/* create a pseudo-link */
19702+static int do_whplink(struct qstr *tgt, struct dentry *h_parent,
19703+ struct dentry *h_dentry, struct au_branch *br)
19704+{
19705+ int err;
19706+ struct path h_path = {
19707+ .mnt = br->br_mnt
19708+ };
19709+ struct inode *h_dir;
19710+
19711+ h_dir = h_parent->d_inode;
7f207e10 19712+ mutex_lock_nested(&h_dir->i_mutex, AuLsc_I_CHILD2);
4f0767ce 19713+again:
1facf9fc 19714+ h_path.dentry = au_lkup_one(tgt, h_parent, br, /*nd*/NULL);
19715+ err = PTR_ERR(h_path.dentry);
19716+ if (IS_ERR(h_path.dentry))
19717+ goto out;
19718+
19719+ err = 0;
19720+ /* wh.plink dir is not monitored */
7f207e10 19721+ /* todo: is it really safe? */
1facf9fc 19722+ if (h_path.dentry->d_inode
19723+ && h_path.dentry->d_inode != h_dentry->d_inode) {
19724+ err = vfsub_unlink(h_dir, &h_path, /*force*/0);
19725+ dput(h_path.dentry);
19726+ h_path.dentry = NULL;
19727+ if (!err)
19728+ goto again;
19729+ }
19730+ if (!err && !h_path.dentry->d_inode)
19731+ err = vfsub_link(h_dentry, h_dir, &h_path);
19732+ dput(h_path.dentry);
19733+
4f0767ce 19734+out:
7f207e10 19735+ mutex_unlock(&h_dir->i_mutex);
1facf9fc 19736+ return err;
19737+}
19738+
19739+struct do_whplink_args {
19740+ int *errp;
19741+ struct qstr *tgt;
19742+ struct dentry *h_parent;
19743+ struct dentry *h_dentry;
19744+ struct au_branch *br;
19745+};
19746+
19747+static void call_do_whplink(void *args)
19748+{
19749+ struct do_whplink_args *a = args;
19750+ *a->errp = do_whplink(a->tgt, a->h_parent, a->h_dentry, a->br);
19751+}
19752+
19753+static int whplink(struct dentry *h_dentry, struct inode *inode,
19754+ aufs_bindex_t bindex, struct au_branch *br)
19755+{
19756+ int err, wkq_err;
19757+ struct au_wbr *wbr;
19758+ struct dentry *h_parent;
19759+ struct inode *h_dir;
19760+ char a[PLINK_NAME_LEN];
19761+ struct qstr tgtname = {
19762+ .name = a
19763+ };
19764+
19765+ wbr = au_sbr(inode->i_sb, bindex)->br_wbr;
19766+ h_parent = wbr->wbr_plink;
19767+ h_dir = h_parent->d_inode;
19768+ tgtname.len = plink_name(a, sizeof(a), inode, bindex);
19769+
19770+ /* always superio. */
b752ccd1 19771+ if (current_fsuid()) {
1facf9fc 19772+ struct do_whplink_args args = {
19773+ .errp = &err,
19774+ .tgt = &tgtname,
19775+ .h_parent = h_parent,
19776+ .h_dentry = h_dentry,
19777+ .br = br
19778+ };
19779+ wkq_err = au_wkq_wait(call_do_whplink, &args);
19780+ if (unlikely(wkq_err))
19781+ err = wkq_err;
19782+ } else
19783+ err = do_whplink(&tgtname, h_parent, h_dentry, br);
1facf9fc 19784+
19785+ return err;
19786+}
19787+
19788+/* free a single plink */
19789+static void do_put_plink(struct pseudo_link *plink, int do_del)
19790+{
1facf9fc 19791+ if (do_del)
19792+ list_del(&plink->list);
4a4d8108
AM
19793+ iput(plink->inode);
19794+ kfree(plink);
19795+}
19796+
19797+static void do_put_plink_rcu(struct rcu_head *rcu)
19798+{
19799+ struct pseudo_link *plink;
19800+
19801+ plink = container_of(rcu, struct pseudo_link, rcu);
19802+ iput(plink->inode);
1facf9fc 19803+ kfree(plink);
19804+}
19805+
19806+/*
19807+ * create a new pseudo-link for @h_dentry on @bindex.
19808+ * the linked inode is held in aufs @inode.
19809+ */
19810+void au_plink_append(struct inode *inode, aufs_bindex_t bindex,
19811+ struct dentry *h_dentry)
19812+{
19813+ struct super_block *sb;
19814+ struct au_sbinfo *sbinfo;
19815+ struct list_head *plink_list;
4a4d8108 19816+ struct pseudo_link *plink, *tmp;
1facf9fc 19817+ int found, err, cnt;
19818+
19819+ sb = inode->i_sb;
19820+ sbinfo = au_sbi(sb);
19821+ AuDebugOn(!au_opt_test(au_mntflags(sb), PLINK));
e49829fe 19822+ AuDebugOn(au_plink_maint(sb, AuLock_NOPLM));
1facf9fc 19823+
1facf9fc 19824+ cnt = 0;
19825+ found = 0;
19826+ plink_list = &sbinfo->si_plink.head;
4a4d8108
AM
19827+ rcu_read_lock();
19828+ list_for_each_entry_rcu(plink, plink_list, list) {
1facf9fc 19829+ cnt++;
19830+ if (plink->inode == inode) {
19831+ found = 1;
19832+ break;
19833+ }
19834+ }
4a4d8108
AM
19835+ rcu_read_unlock();
19836+ if (found)
1facf9fc 19837+ return;
4a4d8108
AM
19838+
19839+ tmp = kmalloc(sizeof(*plink), GFP_NOFS);
19840+ if (tmp)
19841+ tmp->inode = au_igrab(inode);
19842+ else {
19843+ err = -ENOMEM;
19844+ goto out;
1facf9fc 19845+ }
19846+
4a4d8108
AM
19847+ spin_lock(&sbinfo->si_plink.spin);
19848+ list_for_each_entry(plink, plink_list, list) {
19849+ if (plink->inode == inode) {
19850+ found = 1;
19851+ break;
19852+ }
1facf9fc 19853+ }
4a4d8108
AM
19854+ if (!found)
19855+ list_add_rcu(&tmp->list, plink_list);
1facf9fc 19856+ spin_unlock(&sbinfo->si_plink.spin);
4a4d8108
AM
19857+ if (!found) {
19858+ cnt++;
19859+ WARN_ONCE(cnt > AUFS_PLINK_WARN,
19860+ "unexpectedly many pseudo links, %d\n", cnt);
1facf9fc 19861+ err = whplink(h_dentry, inode, bindex, au_sbr(sb, bindex));
4a4d8108
AM
19862+ } else {
19863+ do_put_plink(tmp, 0);
19864+ return;
1facf9fc 19865+ }
19866+
4a4d8108 19867+out:
1facf9fc 19868+ if (unlikely(err)) {
4a4d8108
AM
19869+ pr_warning("err %d, damaged pseudo link.\n", err);
19870+ if (tmp) {
19871+ au_spl_del_rcu(&tmp->list, &sbinfo->si_plink);
19872+ call_rcu(&tmp->rcu, do_put_plink_rcu);
19873+ }
1facf9fc 19874+ }
19875+}
19876+
19877+/* free all plinks */
e49829fe 19878+void au_plink_put(struct super_block *sb, int verbose)
1facf9fc 19879+{
19880+ struct au_sbinfo *sbinfo;
19881+ struct list_head *plink_list;
19882+ struct pseudo_link *plink, *tmp;
19883+
dece6358
AM
19884+ SiMustWriteLock(sb);
19885+
1facf9fc 19886+ sbinfo = au_sbi(sb);
19887+ AuDebugOn(!au_opt_test(au_mntflags(sb), PLINK));
e49829fe 19888+ AuDebugOn(au_plink_maint(sb, AuLock_NOPLM));
1facf9fc 19889+
19890+ plink_list = &sbinfo->si_plink.head;
19891+ /* no spin_lock since sbinfo is write-locked */
e49829fe 19892+ WARN(verbose && !list_empty(plink_list), "pseudo-link is not flushed");
1facf9fc 19893+ list_for_each_entry_safe(plink, tmp, plink_list, list)
19894+ do_put_plink(plink, 0);
19895+ INIT_LIST_HEAD(plink_list);
19896+}
19897+
e49829fe
JR
19898+void au_plink_clean(struct super_block *sb, int verbose)
19899+{
19900+ struct dentry *root;
19901+
19902+ root = sb->s_root;
19903+ aufs_write_lock(root);
19904+ if (au_opt_test(au_mntflags(sb), PLINK))
19905+ au_plink_put(sb, verbose);
19906+ aufs_write_unlock(root);
19907+}
19908+
1facf9fc 19909+/* free the plinks on a branch specified by @br_id */
19910+void au_plink_half_refresh(struct super_block *sb, aufs_bindex_t br_id)
19911+{
19912+ struct au_sbinfo *sbinfo;
19913+ struct list_head *plink_list;
19914+ struct pseudo_link *plink, *tmp;
19915+ struct inode *inode;
19916+ aufs_bindex_t bstart, bend, bindex;
19917+ unsigned char do_put;
19918+
dece6358
AM
19919+ SiMustWriteLock(sb);
19920+
1facf9fc 19921+ sbinfo = au_sbi(sb);
19922+ AuDebugOn(!au_opt_test(au_mntflags(sb), PLINK));
e49829fe 19923+ AuDebugOn(au_plink_maint(sb, AuLock_NOPLM));
1facf9fc 19924+
19925+ plink_list = &sbinfo->si_plink.head;
19926+ /* no spin_lock since sbinfo is write-locked */
19927+ list_for_each_entry_safe(plink, tmp, plink_list, list) {
19928+ do_put = 0;
19929+ inode = au_igrab(plink->inode);
19930+ ii_write_lock_child(inode);
19931+ bstart = au_ibstart(inode);
19932+ bend = au_ibend(inode);
19933+ if (bstart >= 0) {
19934+ for (bindex = bstart; bindex <= bend; bindex++) {
19935+ if (!au_h_iptr(inode, bindex)
19936+ || au_ii_br_id(inode, bindex) != br_id)
19937+ continue;
19938+ au_set_h_iptr(inode, bindex, NULL, 0);
19939+ do_put = 1;
19940+ break;
19941+ }
19942+ } else
19943+ do_put_plink(plink, 1);
19944+
dece6358
AM
19945+ if (do_put) {
19946+ for (bindex = bstart; bindex <= bend; bindex++)
19947+ if (au_h_iptr(inode, bindex)) {
19948+ do_put = 0;
19949+ break;
19950+ }
19951+ if (do_put)
19952+ do_put_plink(plink, 1);
19953+ }
19954+ ii_write_unlock(inode);
19955+ iput(inode);
19956+ }
19957+}
7f207e10
AM
19958diff -urN /usr/share/empty/fs/aufs/poll.c linux/fs/aufs/poll.c
19959--- /usr/share/empty/fs/aufs/poll.c 1970-01-01 01:00:00.000000000 +0100
2cbb1c4b 19960+++ linux/fs/aufs/poll.c 2011-07-11 11:34:24.076331673 +0200
dece6358
AM
19961@@ -0,0 +1,56 @@
19962+/*
027c5e7a 19963+ * Copyright (C) 2005-2011 Junjiro R. Okajima
dece6358
AM
19964+ *
19965+ * This program, aufs is free software; you can redistribute it and/or modify
19966+ * it under the terms of the GNU General Public License as published by
19967+ * the Free Software Foundation; either version 2 of the License, or
19968+ * (at your option) any later version.
19969+ *
19970+ * This program is distributed in the hope that it will be useful,
19971+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
19972+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19973+ * GNU General Public License for more details.
19974+ *
19975+ * You should have received a copy of the GNU General Public License
19976+ * along with this program; if not, write to the Free Software
19977+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19978+ */
19979+
1308ab2a 19980+/*
19981+ * poll operation
19982+ * There is only one filesystem which implements ->poll operation, currently.
19983+ */
19984+
19985+#include "aufs.h"
19986+
19987+unsigned int aufs_poll(struct file *file, poll_table *wait)
19988+{
19989+ unsigned int mask;
19990+ int err;
19991+ struct file *h_file;
19992+ struct dentry *dentry;
19993+ struct super_block *sb;
19994+
19995+ /* We should pretend an error happened. */
19996+ mask = POLLERR /* | POLLIN | POLLOUT */;
19997+ dentry = file->f_dentry;
19998+ sb = dentry->d_sb;
e49829fe 19999+ si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLMW);
1308ab2a 20000+ err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/0);
20001+ if (unlikely(err))
20002+ goto out;
20003+
20004+ /* it is not an error if h_file has no operation */
20005+ mask = DEFAULT_POLLMASK;
4a4d8108 20006+ h_file = au_hf_top(file);
1308ab2a 20007+ if (h_file->f_op && h_file->f_op->poll)
20008+ mask = h_file->f_op->poll(h_file, wait);
20009+
20010+ di_read_unlock(dentry, AuLock_IR);
20011+ fi_read_unlock(file);
20012+
4f0767ce 20013+out:
1308ab2a 20014+ si_read_unlock(sb);
20015+ AuTraceErr((int)mask);
20016+ return mask;
20017+}
7f207e10
AM
20018diff -urN /usr/share/empty/fs/aufs/procfs.c linux/fs/aufs/procfs.c
20019--- /usr/share/empty/fs/aufs/procfs.c 1970-01-01 01:00:00.000000000 +0100
2cbb1c4b 20020+++ linux/fs/aufs/procfs.c 2011-07-11 11:34:24.076331673 +0200
e49829fe
JR
20021@@ -0,0 +1,169 @@
20022+/*
027c5e7a 20023+ * Copyright (C) 2010-2011 Junjiro R. Okajima
e49829fe
JR
20024+ *
20025+ * This program, aufs is free software; you can redistribute it and/or modify
20026+ * it under the terms of the GNU General Public License as published by
20027+ * the Free Software Foundation; either version 2 of the License, or
20028+ * (at your option) any later version.
20029+ *
20030+ * This program is distributed in the hope that it will be useful,
20031+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
20032+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20033+ * GNU General Public License for more details.
20034+ *
20035+ * You should have received a copy of the GNU General Public License
20036+ * along with this program; if not, write to the Free Software
20037+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
20038+ */
20039+
20040+/*
20041+ * procfs interfaces
20042+ */
20043+
20044+#include <linux/proc_fs.h>
20045+#include "aufs.h"
20046+
20047+static int au_procfs_plm_release(struct inode *inode, struct file *file)
20048+{
20049+ struct au_sbinfo *sbinfo;
20050+
20051+ sbinfo = file->private_data;
20052+ if (sbinfo) {
20053+ au_plink_maint_leave(sbinfo);
20054+ kobject_put(&sbinfo->si_kobj);
20055+ }
20056+
20057+ return 0;
20058+}
20059+
20060+static void au_procfs_plm_write_clean(struct file *file)
20061+{
20062+ struct au_sbinfo *sbinfo;
20063+
20064+ sbinfo = file->private_data;
20065+ if (sbinfo)
20066+ au_plink_clean(sbinfo->si_sb, /*verbose*/0);
20067+}
20068+
20069+static int au_procfs_plm_write_si(struct file *file, unsigned long id)
20070+{
20071+ int err;
20072+ struct super_block *sb;
20073+ struct au_sbinfo *sbinfo;
20074+
20075+ err = -EBUSY;
20076+ if (unlikely(file->private_data))
20077+ goto out;
20078+
20079+ sb = NULL;
20080+ spin_lock(&au_sbilist.spin);
20081+ list_for_each_entry(sbinfo, &au_sbilist.head, si_list)
20082+ if (id == sysaufs_si_id(sbinfo)) {
20083+ kobject_get(&sbinfo->si_kobj);
20084+ sb = sbinfo->si_sb;
20085+ break;
20086+ }
20087+ spin_unlock(&au_sbilist.spin);
20088+
20089+ err = -EINVAL;
20090+ if (unlikely(!sb))
20091+ goto out;
20092+
20093+ err = au_plink_maint_enter(sb);
20094+ if (!err)
20095+ /* keep kobject_get() */
20096+ file->private_data = sbinfo;
20097+ else
20098+ kobject_put(&sbinfo->si_kobj);
20099+out:
20100+ return err;
20101+}
20102+
20103+/*
20104+ * Accept a valid "si=xxxx" only.
20105+ * Once it is accepted successfully, accept "clean" too.
20106+ */
20107+static ssize_t au_procfs_plm_write(struct file *file, const char __user *ubuf,
20108+ size_t count, loff_t *ppos)
20109+{
20110+ ssize_t err;
20111+ unsigned long id;
20112+ /* last newline is allowed */
20113+ char buf[3 + sizeof(unsigned long) * 2 + 1];
20114+
20115+ err = -EACCES;
20116+ if (unlikely(!capable(CAP_SYS_ADMIN)))
20117+ goto out;
20118+
20119+ err = -EINVAL;
20120+ if (unlikely(count > sizeof(buf)))
20121+ goto out;
20122+
20123+ err = copy_from_user(buf, ubuf, count);
20124+ if (unlikely(err)) {
20125+ err = -EFAULT;
20126+ goto out;
20127+ }
20128+ buf[count] = 0;
20129+
20130+ err = -EINVAL;
20131+ if (!strcmp("clean", buf)) {
20132+ au_procfs_plm_write_clean(file);
20133+ goto out_success;
20134+ } else if (unlikely(strncmp("si=", buf, 3)))
20135+ goto out;
20136+
20137+ err = strict_strtoul(buf + 3, 16, &id);
20138+ if (unlikely(err))
20139+ goto out;
20140+
20141+ err = au_procfs_plm_write_si(file, id);
20142+ if (unlikely(err))
20143+ goto out;
20144+
20145+out_success:
20146+ err = count; /* success */
20147+out:
20148+ return err;
20149+}
20150+
20151+static const struct file_operations au_procfs_plm_fop = {
20152+ .write = au_procfs_plm_write,
20153+ .release = au_procfs_plm_release,
20154+ .owner = THIS_MODULE
20155+};
20156+
20157+/* ---------------------------------------------------------------------- */
20158+
20159+static struct proc_dir_entry *au_procfs_dir;
20160+
20161+void au_procfs_fin(void)
20162+{
20163+ remove_proc_entry(AUFS_PLINK_MAINT_NAME, au_procfs_dir);
20164+ remove_proc_entry(AUFS_PLINK_MAINT_DIR, NULL);
20165+}
20166+
20167+int __init au_procfs_init(void)
20168+{
20169+ int err;
20170+ struct proc_dir_entry *entry;
20171+
20172+ err = -ENOMEM;
20173+ au_procfs_dir = proc_mkdir(AUFS_PLINK_MAINT_DIR, NULL);
20174+ if (unlikely(!au_procfs_dir))
20175+ goto out;
20176+
20177+ entry = proc_create(AUFS_PLINK_MAINT_NAME, S_IFREG | S_IWUSR,
20178+ au_procfs_dir, &au_procfs_plm_fop);
20179+ if (unlikely(!entry))
20180+ goto out_dir;
20181+
20182+ err = 0;
20183+ goto out; /* success */
20184+
20185+
20186+out_dir:
20187+ remove_proc_entry(AUFS_PLINK_MAINT_DIR, NULL);
20188+out:
20189+ return err;
20190+}
7f207e10
AM
20191diff -urN /usr/share/empty/fs/aufs/rdu.c linux/fs/aufs/rdu.c
20192--- /usr/share/empty/fs/aufs/rdu.c 1970-01-01 01:00:00.000000000 +0100
2cbb1c4b 20193+++ linux/fs/aufs/rdu.c 2011-07-11 11:34:24.076331673 +0200
027c5e7a 20194@@ -0,0 +1,383 @@
1308ab2a 20195+/*
027c5e7a 20196+ * Copyright (C) 2005-2011 Junjiro R. Okajima
1308ab2a 20197+ *
20198+ * This program, aufs is free software; you can redistribute it and/or modify
20199+ * it under the terms of the GNU General Public License as published by
20200+ * the Free Software Foundation; either version 2 of the License, or
20201+ * (at your option) any later version.
20202+ *
20203+ * This program is distributed in the hope that it will be useful,
20204+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
20205+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20206+ * GNU General Public License for more details.
20207+ *
20208+ * You should have received a copy of the GNU General Public License
20209+ * along with this program; if not, write to the Free Software
20210+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
20211+ */
20212+
20213+/*
20214+ * readdir in userspace.
20215+ */
20216+
b752ccd1 20217+#include <linux/compat.h>
4a4d8108 20218+#include <linux/fs_stack.h>
1308ab2a 20219+#include <linux/security.h>
20220+#include <linux/uaccess.h>
20221+#include <linux/aufs_type.h>
20222+#include "aufs.h"
20223+
20224+/* bits for struct aufs_rdu.flags */
20225+#define AuRdu_CALLED 1
20226+#define AuRdu_CONT (1 << 1)
20227+#define AuRdu_FULL (1 << 2)
20228+#define au_ftest_rdu(flags, name) ((flags) & AuRdu_##name)
7f207e10
AM
20229+#define au_fset_rdu(flags, name) \
20230+ do { (flags) |= AuRdu_##name; } while (0)
20231+#define au_fclr_rdu(flags, name) \
20232+ do { (flags) &= ~AuRdu_##name; } while (0)
1308ab2a 20233+
20234+struct au_rdu_arg {
20235+ struct aufs_rdu *rdu;
20236+ union au_rdu_ent_ul ent;
20237+ unsigned long end;
20238+
20239+ struct super_block *sb;
20240+ int err;
20241+};
20242+
20243+static int au_rdu_fill(void *__arg, const char *name, int nlen,
20244+ loff_t offset, u64 h_ino, unsigned int d_type)
20245+{
20246+ int err, len;
20247+ struct au_rdu_arg *arg = __arg;
20248+ struct aufs_rdu *rdu = arg->rdu;
20249+ struct au_rdu_ent ent;
20250+
20251+ err = 0;
20252+ arg->err = 0;
20253+ au_fset_rdu(rdu->cookie.flags, CALLED);
20254+ len = au_rdu_len(nlen);
20255+ if (arg->ent.ul + len < arg->end) {
20256+ ent.ino = h_ino;
20257+ ent.bindex = rdu->cookie.bindex;
20258+ ent.type = d_type;
20259+ ent.nlen = nlen;
4a4d8108
AM
20260+ if (unlikely(nlen > AUFS_MAX_NAMELEN))
20261+ ent.type = DT_UNKNOWN;
1308ab2a 20262+
20263+ err = -EFAULT;
20264+ if (copy_to_user(arg->ent.e, &ent, sizeof(ent)))
20265+ goto out;
20266+ if (copy_to_user(arg->ent.e->name, name, nlen))
20267+ goto out;
20268+ /* the terminating NULL */
20269+ if (__put_user(0, arg->ent.e->name + nlen))
20270+ goto out;
20271+ err = 0;
20272+ /* AuDbg("%p, %.*s\n", arg->ent.p, nlen, name); */
20273+ arg->ent.ul += len;
20274+ rdu->rent++;
20275+ } else {
20276+ err = -EFAULT;
20277+ au_fset_rdu(rdu->cookie.flags, FULL);
20278+ rdu->full = 1;
20279+ rdu->tail = arg->ent;
20280+ }
20281+
4f0767ce 20282+out:
1308ab2a 20283+ /* AuTraceErr(err); */
20284+ return err;
20285+}
20286+
20287+static int au_rdu_do(struct file *h_file, struct au_rdu_arg *arg)
20288+{
20289+ int err;
20290+ loff_t offset;
20291+ struct au_rdu_cookie *cookie = &arg->rdu->cookie;
20292+
20293+ offset = vfsub_llseek(h_file, cookie->h_pos, SEEK_SET);
20294+ err = offset;
20295+ if (unlikely(offset != cookie->h_pos))
20296+ goto out;
20297+
20298+ err = 0;
20299+ do {
20300+ arg->err = 0;
20301+ au_fclr_rdu(cookie->flags, CALLED);
20302+ /* smp_mb(); */
20303+ err = vfsub_readdir(h_file, au_rdu_fill, arg);
20304+ if (err >= 0)
20305+ err = arg->err;
20306+ } while (!err
20307+ && au_ftest_rdu(cookie->flags, CALLED)
20308+ && !au_ftest_rdu(cookie->flags, FULL));
20309+ cookie->h_pos = h_file->f_pos;
20310+
4f0767ce 20311+out:
1308ab2a 20312+ AuTraceErr(err);
20313+ return err;
20314+}
20315+
20316+static int au_rdu(struct file *file, struct aufs_rdu *rdu)
20317+{
20318+ int err;
20319+ aufs_bindex_t bend;
20320+ struct au_rdu_arg arg;
20321+ struct dentry *dentry;
20322+ struct inode *inode;
20323+ struct file *h_file;
20324+ struct au_rdu_cookie *cookie = &rdu->cookie;
20325+
20326+ err = !access_ok(VERIFY_WRITE, rdu->ent.e, rdu->sz);
20327+ if (unlikely(err)) {
20328+ err = -EFAULT;
20329+ AuTraceErr(err);
20330+ goto out;
20331+ }
20332+ rdu->rent = 0;
20333+ rdu->tail = rdu->ent;
20334+ rdu->full = 0;
20335+ arg.rdu = rdu;
20336+ arg.ent = rdu->ent;
20337+ arg.end = arg.ent.ul;
20338+ arg.end += rdu->sz;
20339+
20340+ err = -ENOTDIR;
20341+ if (unlikely(!file->f_op || !file->f_op->readdir))
20342+ goto out;
20343+
20344+ err = security_file_permission(file, MAY_READ);
20345+ AuTraceErr(err);
20346+ if (unlikely(err))
20347+ goto out;
20348+
20349+ dentry = file->f_dentry;
20350+ inode = dentry->d_inode;
20351+#if 1
20352+ mutex_lock(&inode->i_mutex);
20353+#else
20354+ err = mutex_lock_killable(&inode->i_mutex);
20355+ AuTraceErr(err);
20356+ if (unlikely(err))
20357+ goto out;
20358+#endif
1308ab2a 20359+
20360+ arg.sb = inode->i_sb;
e49829fe
JR
20361+ err = si_read_lock(arg.sb, AuLock_FLUSH | AuLock_NOPLM);
20362+ if (unlikely(err))
20363+ goto out_mtx;
027c5e7a
AM
20364+ err = au_alive_dir(dentry);
20365+ if (unlikely(err))
20366+ goto out_si;
e49829fe 20367+ /* todo: reval? */
1308ab2a 20368+ fi_read_lock(file);
20369+
20370+ err = -EAGAIN;
20371+ if (unlikely(au_ftest_rdu(cookie->flags, CONT)
20372+ && cookie->generation != au_figen(file)))
20373+ goto out_unlock;
20374+
20375+ err = 0;
20376+ if (!rdu->blk) {
20377+ rdu->blk = au_sbi(arg.sb)->si_rdblk;
20378+ if (!rdu->blk)
20379+ rdu->blk = au_dir_size(file, /*dentry*/NULL);
20380+ }
20381+ bend = au_fbstart(file);
20382+ if (cookie->bindex < bend)
20383+ cookie->bindex = bend;
4a4d8108 20384+ bend = au_fbend_dir(file);
1308ab2a 20385+ /* AuDbg("b%d, b%d\n", cookie->bindex, bend); */
20386+ for (; !err && cookie->bindex <= bend;
20387+ cookie->bindex++, cookie->h_pos = 0) {
4a4d8108 20388+ h_file = au_hf_dir(file, cookie->bindex);
1308ab2a 20389+ if (!h_file)
20390+ continue;
20391+
20392+ au_fclr_rdu(cookie->flags, FULL);
20393+ err = au_rdu_do(h_file, &arg);
20394+ AuTraceErr(err);
20395+ if (unlikely(au_ftest_rdu(cookie->flags, FULL) || err))
20396+ break;
20397+ }
20398+ AuDbg("rent %llu\n", rdu->rent);
20399+
20400+ if (!err && !au_ftest_rdu(cookie->flags, CONT)) {
20401+ rdu->shwh = !!au_opt_test(au_sbi(arg.sb)->si_mntflags, SHWH);
20402+ au_fset_rdu(cookie->flags, CONT);
20403+ cookie->generation = au_figen(file);
20404+ }
20405+
20406+ ii_read_lock_child(inode);
20407+ fsstack_copy_attr_atime(inode, au_h_iptr(inode, au_ibstart(inode)));
20408+ ii_read_unlock(inode);
20409+
4f0767ce 20410+out_unlock:
1308ab2a 20411+ fi_read_unlock(file);
027c5e7a 20412+out_si:
1308ab2a 20413+ si_read_unlock(arg.sb);
4f0767ce 20414+out_mtx:
1308ab2a 20415+ mutex_unlock(&inode->i_mutex);
4f0767ce 20416+out:
1308ab2a 20417+ AuTraceErr(err);
20418+ return err;
20419+}
20420+
20421+static int au_rdu_ino(struct file *file, struct aufs_rdu *rdu)
20422+{
20423+ int err;
20424+ ino_t ino;
20425+ unsigned long long nent;
20426+ union au_rdu_ent_ul *u;
20427+ struct au_rdu_ent ent;
20428+ struct super_block *sb;
20429+
20430+ err = 0;
20431+ nent = rdu->nent;
20432+ u = &rdu->ent;
20433+ sb = file->f_dentry->d_sb;
20434+ si_read_lock(sb, AuLock_FLUSH);
20435+ while (nent-- > 0) {
1308ab2a 20436+ err = copy_from_user(&ent, u->e, sizeof(ent));
4a4d8108
AM
20437+ if (!err)
20438+ err = !access_ok(VERIFY_WRITE, &u->e->ino, sizeof(ino));
1308ab2a 20439+ if (unlikely(err)) {
20440+ err = -EFAULT;
20441+ AuTraceErr(err);
20442+ break;
20443+ }
20444+
20445+ /* AuDbg("b%d, i%llu\n", ent.bindex, ent.ino); */
20446+ if (!ent.wh)
20447+ err = au_ino(sb, ent.bindex, ent.ino, ent.type, &ino);
20448+ else
20449+ err = au_wh_ino(sb, ent.bindex, ent.ino, ent.type,
20450+ &ino);
20451+ if (unlikely(err)) {
20452+ AuTraceErr(err);
20453+ break;
20454+ }
20455+
20456+ err = __put_user(ino, &u->e->ino);
20457+ if (unlikely(err)) {
20458+ err = -EFAULT;
20459+ AuTraceErr(err);
20460+ break;
20461+ }
20462+ u->ul += au_rdu_len(ent.nlen);
20463+ }
20464+ si_read_unlock(sb);
20465+
20466+ return err;
20467+}
20468+
20469+/* ---------------------------------------------------------------------- */
20470+
20471+static int au_rdu_verify(struct aufs_rdu *rdu)
20472+{
b752ccd1 20473+ AuDbg("rdu{%llu, %p, %u | %u | %llu, %u, %u | "
1308ab2a 20474+ "%llu, b%d, 0x%x, g%u}\n",
b752ccd1 20475+ rdu->sz, rdu->ent.e, rdu->verify[AufsCtlRduV_SZ],
1308ab2a 20476+ rdu->blk,
20477+ rdu->rent, rdu->shwh, rdu->full,
20478+ rdu->cookie.h_pos, rdu->cookie.bindex, rdu->cookie.flags,
20479+ rdu->cookie.generation);
dece6358 20480+
b752ccd1 20481+ if (rdu->verify[AufsCtlRduV_SZ] == sizeof(*rdu))
1308ab2a 20482+ return 0;
dece6358 20483+
b752ccd1
AM
20484+ AuDbg("%u:%u\n",
20485+ rdu->verify[AufsCtlRduV_SZ], (unsigned int)sizeof(*rdu));
1308ab2a 20486+ return -EINVAL;
20487+}
20488+
20489+long au_rdu_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
dece6358 20490+{
1308ab2a 20491+ long err, e;
20492+ struct aufs_rdu rdu;
20493+ void __user *p = (void __user *)arg;
dece6358 20494+
1308ab2a 20495+ err = copy_from_user(&rdu, p, sizeof(rdu));
20496+ if (unlikely(err)) {
20497+ err = -EFAULT;
20498+ AuTraceErr(err);
20499+ goto out;
20500+ }
20501+ err = au_rdu_verify(&rdu);
dece6358
AM
20502+ if (unlikely(err))
20503+ goto out;
20504+
1308ab2a 20505+ switch (cmd) {
20506+ case AUFS_CTL_RDU:
20507+ err = au_rdu(file, &rdu);
20508+ if (unlikely(err))
20509+ break;
dece6358 20510+
1308ab2a 20511+ e = copy_to_user(p, &rdu, sizeof(rdu));
20512+ if (unlikely(e)) {
20513+ err = -EFAULT;
20514+ AuTraceErr(err);
20515+ }
20516+ break;
20517+ case AUFS_CTL_RDU_INO:
20518+ err = au_rdu_ino(file, &rdu);
20519+ break;
20520+
20521+ default:
4a4d8108 20522+ /* err = -ENOTTY; */
1308ab2a 20523+ err = -EINVAL;
20524+ }
dece6358 20525+
4f0767ce 20526+out:
1308ab2a 20527+ AuTraceErr(err);
20528+ return err;
1facf9fc 20529+}
b752ccd1
AM
20530+
20531+#ifdef CONFIG_COMPAT
20532+long au_rdu_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
20533+{
20534+ long err, e;
20535+ struct aufs_rdu rdu;
20536+ void __user *p = compat_ptr(arg);
20537+
20538+ /* todo: get_user()? */
20539+ err = copy_from_user(&rdu, p, sizeof(rdu));
20540+ if (unlikely(err)) {
20541+ err = -EFAULT;
20542+ AuTraceErr(err);
20543+ goto out;
20544+ }
20545+ rdu.ent.e = compat_ptr(rdu.ent.ul);
20546+ err = au_rdu_verify(&rdu);
20547+ if (unlikely(err))
20548+ goto out;
20549+
20550+ switch (cmd) {
20551+ case AUFS_CTL_RDU:
20552+ err = au_rdu(file, &rdu);
20553+ if (unlikely(err))
20554+ break;
20555+
20556+ rdu.ent.ul = ptr_to_compat(rdu.ent.e);
20557+ rdu.tail.ul = ptr_to_compat(rdu.tail.e);
20558+ e = copy_to_user(p, &rdu, sizeof(rdu));
20559+ if (unlikely(e)) {
20560+ err = -EFAULT;
20561+ AuTraceErr(err);
20562+ }
20563+ break;
20564+ case AUFS_CTL_RDU_INO:
20565+ err = au_rdu_ino(file, &rdu);
20566+ break;
20567+
20568+ default:
20569+ /* err = -ENOTTY; */
20570+ err = -EINVAL;
20571+ }
20572+
4f0767ce 20573+out:
b752ccd1
AM
20574+ AuTraceErr(err);
20575+ return err;
20576+}
20577+#endif
7f207e10
AM
20578diff -urN /usr/share/empty/fs/aufs/rwsem.h linux/fs/aufs/rwsem.h
20579--- /usr/share/empty/fs/aufs/rwsem.h 1970-01-01 01:00:00.000000000 +0100
2cbb1c4b 20580+++ linux/fs/aufs/rwsem.h 2011-07-11 11:34:24.077331673 +0200
e49829fe 20581@@ -0,0 +1,189 @@
1facf9fc 20582+/*
027c5e7a 20583+ * Copyright (C) 2005-2011 Junjiro R. Okajima
1facf9fc 20584+ *
20585+ * This program, aufs is free software; you can redistribute it and/or modify
20586+ * it under the terms of the GNU General Public License as published by
20587+ * the Free Software Foundation; either version 2 of the License, or
20588+ * (at your option) any later version.
dece6358
AM
20589+ *
20590+ * This program is distributed in the hope that it will be useful,
20591+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
20592+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20593+ * GNU General Public License for more details.
20594+ *
20595+ * You should have received a copy of the GNU General Public License
20596+ * along with this program; if not, write to the Free Software
20597+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 20598+ */
20599+
20600+/*
20601+ * simple read-write semaphore wrappers
20602+ */
20603+
20604+#ifndef __AUFS_RWSEM_H__
20605+#define __AUFS_RWSEM_H__
20606+
20607+#ifdef __KERNEL__
20608+
dece6358 20609+#include <linux/rwsem.h>
4a4d8108 20610+#include "debug.h"
dece6358
AM
20611+
20612+struct au_rwsem {
20613+ struct rw_semaphore rwsem;
20614+#ifdef CONFIG_AUFS_DEBUG
20615+ /* just for debugging, not almighty counter */
20616+ atomic_t rcnt, wcnt;
20617+#endif
20618+};
20619+
20620+#ifdef CONFIG_AUFS_DEBUG
20621+#define AuDbgCntInit(rw) do { \
20622+ atomic_set(&(rw)->rcnt, 0); \
20623+ atomic_set(&(rw)->wcnt, 0); \
20624+ smp_mb(); /* atomic set */ \
20625+} while (0)
20626+
e49829fe 20627+#define AuDbgRcntInc(rw) atomic_inc(&(rw)->rcnt)
dece6358 20628+#define AuDbgRcntDec(rw) WARN_ON(atomic_dec_return(&(rw)->rcnt) < 0)
e49829fe 20629+#define AuDbgWcntInc(rw) atomic_inc(&(rw)->wcnt)
dece6358
AM
20630+#define AuDbgWcntDec(rw) WARN_ON(atomic_dec_return(&(rw)->wcnt) < 0)
20631+#else
20632+#define AuDbgCntInit(rw) do {} while (0)
20633+#define AuDbgRcntInc(rw) do {} while (0)
20634+#define AuDbgRcntDec(rw) do {} while (0)
20635+#define AuDbgWcntInc(rw) do {} while (0)
20636+#define AuDbgWcntDec(rw) do {} while (0)
20637+#endif /* CONFIG_AUFS_DEBUG */
20638+
20639+/* to debug easier, do not make them inlined functions */
20640+#define AuRwMustNoWaiters(rw) AuDebugOn(!list_empty(&(rw)->rwsem.wait_list))
20641+/* rwsem_is_locked() is unusable */
20642+#define AuRwMustReadLock(rw) AuDebugOn(atomic_read(&(rw)->rcnt) <= 0)
20643+#define AuRwMustWriteLock(rw) AuDebugOn(atomic_read(&(rw)->wcnt) <= 0)
20644+#define AuRwMustAnyLock(rw) AuDebugOn(atomic_read(&(rw)->rcnt) <= 0 \
20645+ && atomic_read(&(rw)->wcnt) <= 0)
20646+#define AuRwDestroy(rw) AuDebugOn(atomic_read(&(rw)->rcnt) \
20647+ || atomic_read(&(rw)->wcnt))
20648+
e49829fe
JR
20649+#define au_rw_class(rw, key) lockdep_set_class(&(rw)->rwsem, key)
20650+
dece6358
AM
20651+static inline void au_rw_init(struct au_rwsem *rw)
20652+{
20653+ AuDbgCntInit(rw);
20654+ init_rwsem(&rw->rwsem);
20655+}
20656+
20657+static inline void au_rw_init_wlock(struct au_rwsem *rw)
20658+{
20659+ au_rw_init(rw);
20660+ down_write(&rw->rwsem);
20661+ AuDbgWcntInc(rw);
20662+}
20663+
20664+static inline void au_rw_init_wlock_nested(struct au_rwsem *rw,
20665+ unsigned int lsc)
20666+{
20667+ au_rw_init(rw);
20668+ down_write_nested(&rw->rwsem, lsc);
20669+ AuDbgWcntInc(rw);
20670+}
20671+
20672+static inline void au_rw_read_lock(struct au_rwsem *rw)
20673+{
20674+ down_read(&rw->rwsem);
20675+ AuDbgRcntInc(rw);
20676+}
20677+
20678+static inline void au_rw_read_lock_nested(struct au_rwsem *rw, unsigned int lsc)
20679+{
20680+ down_read_nested(&rw->rwsem, lsc);
20681+ AuDbgRcntInc(rw);
20682+}
20683+
20684+static inline void au_rw_read_unlock(struct au_rwsem *rw)
20685+{
20686+ AuRwMustReadLock(rw);
20687+ AuDbgRcntDec(rw);
20688+ up_read(&rw->rwsem);
20689+}
20690+
20691+static inline void au_rw_dgrade_lock(struct au_rwsem *rw)
20692+{
20693+ AuRwMustWriteLock(rw);
20694+ AuDbgRcntInc(rw);
20695+ AuDbgWcntDec(rw);
20696+ downgrade_write(&rw->rwsem);
20697+}
20698+
20699+static inline void au_rw_write_lock(struct au_rwsem *rw)
20700+{
20701+ down_write(&rw->rwsem);
20702+ AuDbgWcntInc(rw);
20703+}
20704+
20705+static inline void au_rw_write_lock_nested(struct au_rwsem *rw,
20706+ unsigned int lsc)
20707+{
20708+ down_write_nested(&rw->rwsem, lsc);
20709+ AuDbgWcntInc(rw);
20710+}
1facf9fc 20711+
dece6358
AM
20712+static inline void au_rw_write_unlock(struct au_rwsem *rw)
20713+{
20714+ AuRwMustWriteLock(rw);
20715+ AuDbgWcntDec(rw);
20716+ up_write(&rw->rwsem);
20717+}
20718+
20719+/* why is not _nested version defined */
20720+static inline int au_rw_read_trylock(struct au_rwsem *rw)
20721+{
20722+ int ret = down_read_trylock(&rw->rwsem);
20723+ if (ret)
20724+ AuDbgRcntInc(rw);
20725+ return ret;
20726+}
20727+
20728+static inline int au_rw_write_trylock(struct au_rwsem *rw)
20729+{
20730+ int ret = down_write_trylock(&rw->rwsem);
20731+ if (ret)
20732+ AuDbgWcntInc(rw);
20733+ return ret;
20734+}
20735+
20736+#undef AuDbgCntInit
20737+#undef AuDbgRcntInc
20738+#undef AuDbgRcntDec
20739+#undef AuDbgWcntInc
20740+#undef AuDbgWcntDec
1facf9fc 20741+
20742+#define AuSimpleLockRwsemFuncs(prefix, param, rwsem) \
20743+static inline void prefix##_read_lock(param) \
dece6358 20744+{ au_rw_read_lock(rwsem); } \
1facf9fc 20745+static inline void prefix##_write_lock(param) \
dece6358 20746+{ au_rw_write_lock(rwsem); } \
1facf9fc 20747+static inline int prefix##_read_trylock(param) \
dece6358 20748+{ return au_rw_read_trylock(rwsem); } \
1facf9fc 20749+static inline int prefix##_write_trylock(param) \
dece6358 20750+{ return au_rw_write_trylock(rwsem); }
1facf9fc 20751+/* why is not _nested version defined */
20752+/* static inline void prefix##_read_trylock_nested(param, lsc)
dece6358 20753+{ au_rw_read_trylock_nested(rwsem, lsc)); }
1facf9fc 20754+static inline void prefix##_write_trylock_nestd(param, lsc)
dece6358 20755+{ au_rw_write_trylock_nested(rwsem, lsc); } */
1facf9fc 20756+
20757+#define AuSimpleUnlockRwsemFuncs(prefix, param, rwsem) \
20758+static inline void prefix##_read_unlock(param) \
dece6358 20759+{ au_rw_read_unlock(rwsem); } \
1facf9fc 20760+static inline void prefix##_write_unlock(param) \
dece6358 20761+{ au_rw_write_unlock(rwsem); } \
1facf9fc 20762+static inline void prefix##_downgrade_lock(param) \
dece6358 20763+{ au_rw_dgrade_lock(rwsem); }
1facf9fc 20764+
20765+#define AuSimpleRwsemFuncs(prefix, param, rwsem) \
20766+ AuSimpleLockRwsemFuncs(prefix, param, rwsem) \
20767+ AuSimpleUnlockRwsemFuncs(prefix, param, rwsem)
20768+
20769+#endif /* __KERNEL__ */
20770+#endif /* __AUFS_RWSEM_H__ */
7f207e10
AM
20771diff -urN /usr/share/empty/fs/aufs/sbinfo.c linux/fs/aufs/sbinfo.c
20772--- /usr/share/empty/fs/aufs/sbinfo.c 1970-01-01 01:00:00.000000000 +0100
2cbb1c4b 20773+++ linux/fs/aufs/sbinfo.c 2011-07-11 11:34:24.077331673 +0200
027c5e7a 20774@@ -0,0 +1,344 @@
1facf9fc 20775+/*
027c5e7a 20776+ * Copyright (C) 2005-2011 Junjiro R. Okajima
1facf9fc 20777+ *
20778+ * This program, aufs is free software; you can redistribute it and/or modify
20779+ * it under the terms of the GNU General Public License as published by
20780+ * the Free Software Foundation; either version 2 of the License, or
20781+ * (at your option) any later version.
dece6358
AM
20782+ *
20783+ * This program is distributed in the hope that it will be useful,
20784+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
20785+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20786+ * GNU General Public License for more details.
20787+ *
20788+ * You should have received a copy of the GNU General Public License
20789+ * along with this program; if not, write to the Free Software
20790+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 20791+ */
20792+
20793+/*
20794+ * superblock private data
20795+ */
20796+
e49829fe 20797+#include <linux/jiffies.h>
1facf9fc 20798+#include "aufs.h"
20799+
20800+/*
20801+ * they are necessary regardless sysfs is disabled.
20802+ */
20803+void au_si_free(struct kobject *kobj)
20804+{
20805+ struct au_sbinfo *sbinfo;
b752ccd1 20806+ char *locked __maybe_unused; /* debug only */
1facf9fc 20807+
20808+ sbinfo = container_of(kobj, struct au_sbinfo, si_kobj);
20809+ AuDebugOn(!list_empty(&sbinfo->si_plink.head));
e49829fe 20810+ AuDebugOn(atomic_read(&sbinfo->si_nowait.nw_len));
1facf9fc 20811+
e49829fe 20812+ au_rw_write_lock(&sbinfo->si_rwsem);
1facf9fc 20813+ au_br_free(sbinfo);
e49829fe 20814+ au_rw_write_unlock(&sbinfo->si_rwsem);
b752ccd1
AM
20815+
20816+ AuDebugOn(radix_tree_gang_lookup
20817+ (&sbinfo->au_si_pid.tree, (void **)&locked,
20818+ /*first_index*/PID_MAX_DEFAULT - 1,
20819+ /*max_items*/sizeof(locked)/sizeof(*locked)));
20820+
1facf9fc 20821+ kfree(sbinfo->si_branch);
b752ccd1 20822+ kfree(sbinfo->au_si_pid.bitmap);
1facf9fc 20823+ mutex_destroy(&sbinfo->si_xib_mtx);
dece6358 20824+ AuRwDestroy(&sbinfo->si_rwsem);
1facf9fc 20825+
20826+ kfree(sbinfo);
20827+}
20828+
20829+int au_si_alloc(struct super_block *sb)
20830+{
20831+ int err;
20832+ struct au_sbinfo *sbinfo;
e49829fe 20833+ static struct lock_class_key aufs_si;
1facf9fc 20834+
20835+ err = -ENOMEM;
4a4d8108 20836+ sbinfo = kzalloc(sizeof(*sbinfo), GFP_NOFS);
1facf9fc 20837+ if (unlikely(!sbinfo))
20838+ goto out;
20839+
b752ccd1
AM
20840+ BUILD_BUG_ON(sizeof(unsigned long) !=
20841+ sizeof(*sbinfo->au_si_pid.bitmap));
20842+ sbinfo->au_si_pid.bitmap = kcalloc(BITS_TO_LONGS(PID_MAX_DEFAULT),
20843+ sizeof(*sbinfo->au_si_pid.bitmap),
20844+ GFP_NOFS);
20845+ if (unlikely(!sbinfo->au_si_pid.bitmap))
20846+ goto out_sbinfo;
20847+
1facf9fc 20848+ /* will be reallocated separately */
20849+ sbinfo->si_branch = kzalloc(sizeof(*sbinfo->si_branch), GFP_NOFS);
20850+ if (unlikely(!sbinfo->si_branch))
b752ccd1 20851+ goto out_pidmap;
1facf9fc 20852+
1facf9fc 20853+ err = sysaufs_si_init(sbinfo);
20854+ if (unlikely(err))
20855+ goto out_br;
20856+
20857+ au_nwt_init(&sbinfo->si_nowait);
dece6358 20858+ au_rw_init_wlock(&sbinfo->si_rwsem);
e49829fe 20859+ au_rw_class(&sbinfo->si_rwsem, &aufs_si);
b752ccd1
AM
20860+ spin_lock_init(&sbinfo->au_si_pid.tree_lock);
20861+ INIT_RADIX_TREE(&sbinfo->au_si_pid.tree, GFP_ATOMIC | __GFP_NOFAIL);
20862+
7f207e10 20863+ atomic_long_set(&sbinfo->si_ninodes, 0);
7f207e10
AM
20864+ atomic_long_set(&sbinfo->si_nfiles, 0);
20865+
1facf9fc 20866+ sbinfo->si_bend = -1;
1facf9fc 20867+
20868+ sbinfo->si_wbr_copyup = AuWbrCopyup_Def;
20869+ sbinfo->si_wbr_create = AuWbrCreate_Def;
4a4d8108
AM
20870+ sbinfo->si_wbr_copyup_ops = au_wbr_copyup_ops + sbinfo->si_wbr_copyup;
20871+ sbinfo->si_wbr_create_ops = au_wbr_create_ops + sbinfo->si_wbr_create;
1facf9fc 20872+
e49829fe 20873+ sbinfo->si_mntflags = au_opts_plink(AuOpt_Def);
1facf9fc 20874+
1facf9fc 20875+ mutex_init(&sbinfo->si_xib_mtx);
1facf9fc 20876+ sbinfo->si_xino_brid = -1;
20877+ /* leave si_xib_last_pindex and si_xib_next_bit */
20878+
e49829fe 20879+ sbinfo->si_rdcache = msecs_to_jiffies(AUFS_RDCACHE_DEF * MSEC_PER_SEC);
1facf9fc 20880+ sbinfo->si_rdblk = AUFS_RDBLK_DEF;
20881+ sbinfo->si_rdhash = AUFS_RDHASH_DEF;
20882+ sbinfo->si_dirwh = AUFS_DIRWH_DEF;
20883+
20884+ au_spl_init(&sbinfo->si_plink);
20885+ init_waitqueue_head(&sbinfo->si_plink_wq);
4a4d8108 20886+ spin_lock_init(&sbinfo->si_plink_maint_lock);
1facf9fc 20887+
20888+ /* leave other members for sysaufs and si_mnt. */
20889+ sbinfo->si_sb = sb;
20890+ sb->s_fs_info = sbinfo;
b752ccd1 20891+ si_pid_set(sb);
1facf9fc 20892+ au_debug_sbinfo_init(sbinfo);
20893+ return 0; /* success */
20894+
4f0767ce 20895+out_br:
1facf9fc 20896+ kfree(sbinfo->si_branch);
4f0767ce 20897+out_pidmap:
b752ccd1 20898+ kfree(sbinfo->au_si_pid.bitmap);
4f0767ce 20899+out_sbinfo:
1facf9fc 20900+ kfree(sbinfo);
4f0767ce 20901+out:
1facf9fc 20902+ return err;
20903+}
20904+
20905+int au_sbr_realloc(struct au_sbinfo *sbinfo, int nbr)
20906+{
20907+ int err, sz;
20908+ struct au_branch **brp;
20909+
dece6358
AM
20910+ AuRwMustWriteLock(&sbinfo->si_rwsem);
20911+
1facf9fc 20912+ err = -ENOMEM;
20913+ sz = sizeof(*brp) * (sbinfo->si_bend + 1);
20914+ if (unlikely(!sz))
20915+ sz = sizeof(*brp);
20916+ brp = au_kzrealloc(sbinfo->si_branch, sz, sizeof(*brp) * nbr, GFP_NOFS);
20917+ if (brp) {
20918+ sbinfo->si_branch = brp;
20919+ err = 0;
20920+ }
20921+
20922+ return err;
20923+}
20924+
20925+/* ---------------------------------------------------------------------- */
20926+
20927+unsigned int au_sigen_inc(struct super_block *sb)
20928+{
20929+ unsigned int gen;
20930+
dece6358
AM
20931+ SiMustWriteLock(sb);
20932+
1facf9fc 20933+ gen = ++au_sbi(sb)->si_generation;
20934+ au_update_digen(sb->s_root);
20935+ au_update_iigen(sb->s_root->d_inode);
20936+ sb->s_root->d_inode->i_version++;
20937+ return gen;
20938+}
20939+
20940+aufs_bindex_t au_new_br_id(struct super_block *sb)
20941+{
20942+ aufs_bindex_t br_id;
20943+ int i;
20944+ struct au_sbinfo *sbinfo;
20945+
dece6358
AM
20946+ SiMustWriteLock(sb);
20947+
1facf9fc 20948+ sbinfo = au_sbi(sb);
20949+ for (i = 0; i <= AUFS_BRANCH_MAX; i++) {
20950+ br_id = ++sbinfo->si_last_br_id;
7f207e10 20951+ AuDebugOn(br_id < 0);
1facf9fc 20952+ if (br_id && au_br_index(sb, br_id) < 0)
20953+ return br_id;
20954+ }
20955+
20956+ return -1;
20957+}
20958+
20959+/* ---------------------------------------------------------------------- */
20960+
e49829fe
JR
20961+/* it is ok that new 'nwt' tasks are appended while we are sleeping */
20962+int si_read_lock(struct super_block *sb, int flags)
20963+{
20964+ int err;
20965+
20966+ err = 0;
20967+ if (au_ftest_lock(flags, FLUSH))
20968+ au_nwt_flush(&au_sbi(sb)->si_nowait);
20969+
20970+ si_noflush_read_lock(sb);
20971+ err = au_plink_maint(sb, flags);
20972+ if (unlikely(err))
20973+ si_read_unlock(sb);
20974+
20975+ return err;
20976+}
20977+
20978+int si_write_lock(struct super_block *sb, int flags)
20979+{
20980+ int err;
20981+
20982+ if (au_ftest_lock(flags, FLUSH))
20983+ au_nwt_flush(&au_sbi(sb)->si_nowait);
20984+
20985+ si_noflush_write_lock(sb);
20986+ err = au_plink_maint(sb, flags);
20987+ if (unlikely(err))
20988+ si_write_unlock(sb);
20989+
20990+ return err;
20991+}
20992+
1facf9fc 20993+/* dentry and super_block lock. call at entry point */
e49829fe 20994+int aufs_read_lock(struct dentry *dentry, int flags)
1facf9fc 20995+{
e49829fe 20996+ int err;
027c5e7a 20997+ struct super_block *sb;
e49829fe 20998+
027c5e7a
AM
20999+ sb = dentry->d_sb;
21000+ err = si_read_lock(sb, flags);
21001+ if (unlikely(err))
21002+ goto out;
21003+
21004+ if (au_ftest_lock(flags, DW))
21005+ di_write_lock_child(dentry);
21006+ else
21007+ di_read_lock_child(dentry, flags);
21008+
21009+ if (au_ftest_lock(flags, GEN)) {
21010+ err = au_digen_test(dentry, au_sigen(sb));
21011+ AuDebugOn(!err && au_dbrange_test(dentry));
21012+ if (unlikely(err))
21013+ aufs_read_unlock(dentry, flags);
e49829fe
JR
21014+ }
21015+
027c5e7a 21016+out:
e49829fe 21017+ return err;
1facf9fc 21018+}
21019+
21020+void aufs_read_unlock(struct dentry *dentry, int flags)
21021+{
21022+ if (au_ftest_lock(flags, DW))
21023+ di_write_unlock(dentry);
21024+ else
21025+ di_read_unlock(dentry, flags);
21026+ si_read_unlock(dentry->d_sb);
21027+}
21028+
21029+void aufs_write_lock(struct dentry *dentry)
21030+{
e49829fe 21031+ si_write_lock(dentry->d_sb, AuLock_FLUSH | AuLock_NOPLMW);
1facf9fc 21032+ di_write_lock_child(dentry);
21033+}
21034+
21035+void aufs_write_unlock(struct dentry *dentry)
21036+{
21037+ di_write_unlock(dentry);
21038+ si_write_unlock(dentry->d_sb);
21039+}
21040+
e49829fe 21041+int aufs_read_and_write_lock2(struct dentry *d1, struct dentry *d2, int flags)
1facf9fc 21042+{
e49829fe 21043+ int err;
027c5e7a
AM
21044+ unsigned int sigen;
21045+ struct super_block *sb;
e49829fe 21046+
027c5e7a
AM
21047+ sb = d1->d_sb;
21048+ err = si_read_lock(sb, flags);
21049+ if (unlikely(err))
21050+ goto out;
21051+
21052+ di_write_lock2_child(d1, d2, au_ftest_lock(flags, DIR));
21053+
21054+ if (au_ftest_lock(flags, GEN)) {
21055+ sigen = au_sigen(sb);
21056+ err = au_digen_test(d1, sigen);
21057+ AuDebugOn(!err && au_dbrange_test(d1));
21058+ if (!err) {
21059+ err = au_digen_test(d2, sigen);
21060+ AuDebugOn(!err && au_dbrange_test(d2));
21061+ }
21062+ if (unlikely(err))
21063+ aufs_read_and_write_unlock2(d1, d2);
21064+ }
21065+
21066+out:
e49829fe 21067+ return err;
1facf9fc 21068+}
21069+
21070+void aufs_read_and_write_unlock2(struct dentry *d1, struct dentry *d2)
21071+{
21072+ di_write_unlock2(d1, d2);
21073+ si_read_unlock(d1->d_sb);
21074+}
b752ccd1
AM
21075+
21076+/* ---------------------------------------------------------------------- */
21077+
21078+int si_pid_test_slow(struct super_block *sb)
21079+{
21080+ void *p;
21081+
21082+ rcu_read_lock();
21083+ p = radix_tree_lookup(&au_sbi(sb)->au_si_pid.tree, current->pid);
21084+ rcu_read_unlock();
21085+
027c5e7a 21086+ return (long)!!p;
b752ccd1
AM
21087+}
21088+
21089+void si_pid_set_slow(struct super_block *sb)
21090+{
21091+ int err;
21092+ struct au_sbinfo *sbinfo;
21093+
21094+ AuDebugOn(si_pid_test_slow(sb));
21095+
21096+ sbinfo = au_sbi(sb);
21097+ err = radix_tree_preload(GFP_NOFS | __GFP_NOFAIL);
21098+ AuDebugOn(err);
21099+ spin_lock(&sbinfo->au_si_pid.tree_lock);
21100+ err = radix_tree_insert(&sbinfo->au_si_pid.tree, current->pid,
027c5e7a 21101+ /*any valid ptr*/sb);
b752ccd1
AM
21102+ spin_unlock(&sbinfo->au_si_pid.tree_lock);
21103+ AuDebugOn(err);
21104+ radix_tree_preload_end();
21105+}
21106+
21107+void si_pid_clr_slow(struct super_block *sb)
21108+{
21109+ void *p;
21110+ struct au_sbinfo *sbinfo;
21111+
21112+ AuDebugOn(!si_pid_test_slow(sb));
21113+
21114+ sbinfo = au_sbi(sb);
21115+ spin_lock(&sbinfo->au_si_pid.tree_lock);
21116+ p = radix_tree_delete(&sbinfo->au_si_pid.tree, current->pid);
21117+ spin_unlock(&sbinfo->au_si_pid.tree_lock);
b752ccd1 21118+}
7f207e10
AM
21119diff -urN /usr/share/empty/fs/aufs/spl.h linux/fs/aufs/spl.h
21120--- /usr/share/empty/fs/aufs/spl.h 1970-01-01 01:00:00.000000000 +0100
2cbb1c4b 21121+++ linux/fs/aufs/spl.h 2011-07-11 11:34:24.077331673 +0200
4a4d8108 21122@@ -0,0 +1,66 @@
1facf9fc 21123+/*
027c5e7a 21124+ * Copyright (C) 2005-2011 Junjiro R. Okajima
1facf9fc 21125+ *
21126+ * This program, aufs is free software; you can redistribute it and/or modify
21127+ * it under the terms of the GNU General Public License as published by
21128+ * the Free Software Foundation; either version 2 of the License, or
21129+ * (at your option) any later version.
dece6358
AM
21130+ *
21131+ * This program is distributed in the hope that it will be useful,
21132+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
21133+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21134+ * GNU General Public License for more details.
21135+ *
21136+ * You should have received a copy of the GNU General Public License
21137+ * along with this program; if not, write to the Free Software
21138+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 21139+ */
21140+
21141+/*
21142+ * simple list protected by a spinlock
21143+ */
21144+
21145+#ifndef __AUFS_SPL_H__
21146+#define __AUFS_SPL_H__
21147+
21148+#ifdef __KERNEL__
21149+
dece6358
AM
21150+#include <linux/spinlock.h>
21151+#include <linux/list.h>
4a4d8108 21152+#include <linux/rculist.h>
1facf9fc 21153+
21154+struct au_splhead {
21155+ spinlock_t spin;
21156+ struct list_head head;
21157+};
21158+
21159+static inline void au_spl_init(struct au_splhead *spl)
21160+{
21161+ spin_lock_init(&spl->spin);
21162+ INIT_LIST_HEAD(&spl->head);
21163+}
21164+
21165+static inline void au_spl_add(struct list_head *list, struct au_splhead *spl)
21166+{
21167+ spin_lock(&spl->spin);
21168+ list_add(list, &spl->head);
21169+ spin_unlock(&spl->spin);
21170+}
21171+
21172+static inline void au_spl_del(struct list_head *list, struct au_splhead *spl)
21173+{
21174+ spin_lock(&spl->spin);
21175+ list_del(list);
21176+ spin_unlock(&spl->spin);
21177+}
21178+
4a4d8108
AM
21179+static inline void au_spl_del_rcu(struct list_head *list,
21180+ struct au_splhead *spl)
21181+{
21182+ spin_lock(&spl->spin);
21183+ list_del_rcu(list);
21184+ spin_unlock(&spl->spin);
21185+}
21186+
1facf9fc 21187+#endif /* __KERNEL__ */
21188+#endif /* __AUFS_SPL_H__ */
7f207e10
AM
21189diff -urN /usr/share/empty/fs/aufs/super.c linux/fs/aufs/super.c
21190--- /usr/share/empty/fs/aufs/super.c 1970-01-01 01:00:00.000000000 +0100
2cbb1c4b
JR
21191+++ linux/fs/aufs/super.c 2011-07-11 11:34:24.077331673 +0200
21192@@ -0,0 +1,930 @@
1facf9fc 21193+/*
027c5e7a 21194+ * Copyright (C) 2005-2011 Junjiro R. Okajima
1facf9fc 21195+ *
21196+ * This program, aufs is free software; you can redistribute it and/or modify
21197+ * it under the terms of the GNU General Public License as published by
21198+ * the Free Software Foundation; either version 2 of the License, or
21199+ * (at your option) any later version.
dece6358
AM
21200+ *
21201+ * This program is distributed in the hope that it will be useful,
21202+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
21203+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21204+ * GNU General Public License for more details.
21205+ *
21206+ * You should have received a copy of the GNU General Public License
21207+ * along with this program; if not, write to the Free Software
21208+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 21209+ */
21210+
21211+/*
21212+ * mount and super_block operations
21213+ */
21214+
21215+#include <linux/buffer_head.h>
e49829fe 21216+#include <linux/jiffies.h>
dece6358 21217+#include <linux/module.h>
1facf9fc 21218+#include <linux/seq_file.h>
21219+#include <linux/statfs.h>
7f207e10
AM
21220+#include <linux/vmalloc.h>
21221+#include <linux/writeback.h>
1facf9fc 21222+#include "aufs.h"
21223+
21224+/*
21225+ * super_operations
21226+ */
21227+static struct inode *aufs_alloc_inode(struct super_block *sb __maybe_unused)
21228+{
21229+ struct au_icntnr *c;
21230+
21231+ c = au_cache_alloc_icntnr();
21232+ if (c) {
027c5e7a 21233+ au_icntnr_init(c);
1facf9fc 21234+ c->vfs_inode.i_version = 1; /* sigen(sb); */
21235+ c->iinfo.ii_hinode = NULL;
21236+ return &c->vfs_inode;
21237+ }
21238+ return NULL;
21239+}
21240+
027c5e7a
AM
21241+static void aufs_destroy_inode_cb(struct rcu_head *head)
21242+{
21243+ struct inode *inode = container_of(head, struct inode, i_rcu);
21244+
21245+ INIT_LIST_HEAD(&inode->i_dentry);
21246+ au_cache_free_icntnr(container_of(inode, struct au_icntnr, vfs_inode));
21247+}
21248+
1facf9fc 21249+static void aufs_destroy_inode(struct inode *inode)
21250+{
21251+ au_iinfo_fin(inode);
027c5e7a 21252+ call_rcu(&inode->i_rcu, aufs_destroy_inode_cb);
1facf9fc 21253+}
21254+
21255+struct inode *au_iget_locked(struct super_block *sb, ino_t ino)
21256+{
21257+ struct inode *inode;
21258+ int err;
21259+
21260+ inode = iget_locked(sb, ino);
21261+ if (unlikely(!inode)) {
21262+ inode = ERR_PTR(-ENOMEM);
21263+ goto out;
21264+ }
21265+ if (!(inode->i_state & I_NEW))
21266+ goto out;
21267+
21268+ err = au_xigen_new(inode);
21269+ if (!err)
21270+ err = au_iinfo_init(inode);
21271+ if (!err)
21272+ inode->i_version++;
21273+ else {
21274+ iget_failed(inode);
21275+ inode = ERR_PTR(err);
21276+ }
21277+
4f0767ce 21278+out:
1facf9fc 21279+ /* never return NULL */
21280+ AuDebugOn(!inode);
21281+ AuTraceErrPtr(inode);
21282+ return inode;
21283+}
21284+
21285+/* lock free root dinfo */
21286+static int au_show_brs(struct seq_file *seq, struct super_block *sb)
21287+{
21288+ int err;
21289+ aufs_bindex_t bindex, bend;
21290+ struct path path;
4a4d8108 21291+ struct au_hdentry *hdp;
1facf9fc 21292+ struct au_branch *br;
21293+
21294+ err = 0;
21295+ bend = au_sbend(sb);
4a4d8108 21296+ hdp = au_di(sb->s_root)->di_hdentry;
1facf9fc 21297+ for (bindex = 0; !err && bindex <= bend; bindex++) {
21298+ br = au_sbr(sb, bindex);
21299+ path.mnt = br->br_mnt;
4a4d8108 21300+ path.dentry = hdp[bindex].hd_dentry;
1facf9fc 21301+ err = au_seq_path(seq, &path);
21302+ if (err > 0)
21303+ err = seq_printf(seq, "=%s",
21304+ au_optstr_br_perm(br->br_perm));
21305+ if (!err && bindex != bend)
21306+ err = seq_putc(seq, ':');
21307+ }
21308+
21309+ return err;
21310+}
21311+
21312+static void au_show_wbr_create(struct seq_file *m, int v,
21313+ struct au_sbinfo *sbinfo)
21314+{
21315+ const char *pat;
21316+
dece6358
AM
21317+ AuRwMustAnyLock(&sbinfo->si_rwsem);
21318+
1facf9fc 21319+ seq_printf(m, ",create=");
21320+ pat = au_optstr_wbr_create(v);
21321+ switch (v) {
21322+ case AuWbrCreate_TDP:
21323+ case AuWbrCreate_RR:
21324+ case AuWbrCreate_MFS:
21325+ case AuWbrCreate_PMFS:
21326+ seq_printf(m, pat);
21327+ break;
21328+ case AuWbrCreate_MFSV:
21329+ seq_printf(m, /*pat*/"mfs:%lu",
e49829fe
JR
21330+ jiffies_to_msecs(sbinfo->si_wbr_mfs.mfs_expire)
21331+ / MSEC_PER_SEC);
1facf9fc 21332+ break;
21333+ case AuWbrCreate_PMFSV:
21334+ seq_printf(m, /*pat*/"pmfs:%lu",
e49829fe
JR
21335+ jiffies_to_msecs(sbinfo->si_wbr_mfs.mfs_expire)
21336+ / MSEC_PER_SEC);
1facf9fc 21337+ break;
21338+ case AuWbrCreate_MFSRR:
21339+ seq_printf(m, /*pat*/"mfsrr:%llu",
21340+ sbinfo->si_wbr_mfs.mfsrr_watermark);
21341+ break;
21342+ case AuWbrCreate_MFSRRV:
21343+ seq_printf(m, /*pat*/"mfsrr:%llu:%lu",
21344+ sbinfo->si_wbr_mfs.mfsrr_watermark,
e49829fe
JR
21345+ jiffies_to_msecs(sbinfo->si_wbr_mfs.mfs_expire)
21346+ / MSEC_PER_SEC);
1facf9fc 21347+ break;
21348+ }
21349+}
21350+
21351+static int au_show_xino(struct seq_file *seq, struct vfsmount *mnt)
21352+{
21353+#ifdef CONFIG_SYSFS
21354+ return 0;
21355+#else
21356+ int err;
21357+ const int len = sizeof(AUFS_XINO_FNAME) - 1;
21358+ aufs_bindex_t bindex, brid;
21359+ struct super_block *sb;
21360+ struct qstr *name;
21361+ struct file *f;
21362+ struct dentry *d, *h_root;
4a4d8108 21363+ struct au_hdentry *hdp;
1facf9fc 21364+
dece6358
AM
21365+ AuRwMustAnyLock(&sbinfo->si_rwsem);
21366+
1facf9fc 21367+ err = 0;
21368+ sb = mnt->mnt_sb;
21369+ f = au_sbi(sb)->si_xib;
21370+ if (!f)
21371+ goto out;
21372+
21373+ /* stop printing the default xino path on the first writable branch */
21374+ h_root = NULL;
21375+ brid = au_xino_brid(sb);
21376+ if (brid >= 0) {
21377+ bindex = au_br_index(sb, brid);
4a4d8108
AM
21378+ hdp = au_di(sb->s_root)->di_hdentry;
21379+ h_root = hdp[0 + bindex].hd_dentry;
1facf9fc 21380+ }
21381+ d = f->f_dentry;
21382+ name = &d->d_name;
21383+ /* safe ->d_parent because the file is unlinked */
21384+ if (d->d_parent == h_root
21385+ && name->len == len
21386+ && !memcmp(name->name, AUFS_XINO_FNAME, len))
21387+ goto out;
21388+
21389+ seq_puts(seq, ",xino=");
21390+ err = au_xino_path(seq, f);
21391+
4f0767ce 21392+out:
1facf9fc 21393+ return err;
21394+#endif
21395+}
21396+
21397+/* seq_file will re-call me in case of too long string */
21398+static int aufs_show_options(struct seq_file *m, struct vfsmount *mnt)
21399+{
027c5e7a 21400+ int err;
1facf9fc 21401+ unsigned int mnt_flags, v;
21402+ struct super_block *sb;
21403+ struct au_sbinfo *sbinfo;
21404+
21405+#define AuBool(name, str) do { \
21406+ v = au_opt_test(mnt_flags, name); \
21407+ if (v != au_opt_test(AuOpt_Def, name)) \
21408+ seq_printf(m, ",%s" #str, v ? "" : "no"); \
21409+} while (0)
21410+
21411+#define AuStr(name, str) do { \
21412+ v = mnt_flags & AuOptMask_##name; \
21413+ if (v != (AuOpt_Def & AuOptMask_##name)) \
21414+ seq_printf(m, "," #str "=%s", au_optstr_##str(v)); \
21415+} while (0)
21416+
21417+#define AuUInt(name, str, val) do { \
21418+ if (val != AUFS_##name##_DEF) \
21419+ seq_printf(m, "," #str "=%u", val); \
21420+} while (0)
21421+
21422+ /* lock free root dinfo */
21423+ sb = mnt->mnt_sb;
21424+ si_noflush_read_lock(sb);
21425+ sbinfo = au_sbi(sb);
21426+ seq_printf(m, ",si=%lx", sysaufs_si_id(sbinfo));
21427+
21428+ mnt_flags = au_mntflags(sb);
21429+ if (au_opt_test(mnt_flags, XINO)) {
21430+ err = au_show_xino(m, mnt);
21431+ if (unlikely(err))
21432+ goto out;
21433+ } else
21434+ seq_puts(m, ",noxino");
21435+
21436+ AuBool(TRUNC_XINO, trunc_xino);
21437+ AuStr(UDBA, udba);
dece6358 21438+ AuBool(SHWH, shwh);
1facf9fc 21439+ AuBool(PLINK, plink);
4a4d8108 21440+ AuBool(DIO, dio);
1facf9fc 21441+ /* AuBool(DIRPERM1, dirperm1); */
21442+ /* AuBool(REFROF, refrof); */
21443+
21444+ v = sbinfo->si_wbr_create;
21445+ if (v != AuWbrCreate_Def)
21446+ au_show_wbr_create(m, v, sbinfo);
21447+
21448+ v = sbinfo->si_wbr_copyup;
21449+ if (v != AuWbrCopyup_Def)
21450+ seq_printf(m, ",cpup=%s", au_optstr_wbr_copyup(v));
21451+
21452+ v = au_opt_test(mnt_flags, ALWAYS_DIROPQ);
21453+ if (v != au_opt_test(AuOpt_Def, ALWAYS_DIROPQ))
21454+ seq_printf(m, ",diropq=%c", v ? 'a' : 'w');
21455+
21456+ AuUInt(DIRWH, dirwh, sbinfo->si_dirwh);
21457+
027c5e7a
AM
21458+ v = jiffies_to_msecs(sbinfo->si_rdcache) / MSEC_PER_SEC;
21459+ AuUInt(RDCACHE, rdcache, v);
1facf9fc 21460+
21461+ AuUInt(RDBLK, rdblk, sbinfo->si_rdblk);
21462+ AuUInt(RDHASH, rdhash, sbinfo->si_rdhash);
21463+
21464+ AuBool(SUM, sum);
21465+ /* AuBool(SUM_W, wsum); */
21466+ AuBool(WARN_PERM, warn_perm);
21467+ AuBool(VERBOSE, verbose);
21468+
4f0767ce 21469+out:
1facf9fc 21470+ /* be sure to print "br:" last */
21471+ if (!sysaufs_brs) {
21472+ seq_puts(m, ",br:");
21473+ au_show_brs(m, sb);
21474+ }
21475+ si_read_unlock(sb);
21476+ return 0;
21477+
1facf9fc 21478+#undef AuBool
21479+#undef AuStr
4a4d8108 21480+#undef AuUInt
1facf9fc 21481+}
21482+
21483+/* ---------------------------------------------------------------------- */
21484+
21485+/* sum mode which returns the summation for statfs(2) */
21486+
21487+static u64 au_add_till_max(u64 a, u64 b)
21488+{
21489+ u64 old;
21490+
21491+ old = a;
21492+ a += b;
21493+ if (old < a)
21494+ return a;
21495+ return ULLONG_MAX;
21496+}
21497+
21498+static int au_statfs_sum(struct super_block *sb, struct kstatfs *buf)
21499+{
21500+ int err;
21501+ u64 blocks, bfree, bavail, files, ffree;
21502+ aufs_bindex_t bend, bindex, i;
21503+ unsigned char shared;
7f207e10 21504+ struct path h_path;
1facf9fc 21505+ struct super_block *h_sb;
21506+
21507+ blocks = 0;
21508+ bfree = 0;
21509+ bavail = 0;
21510+ files = 0;
21511+ ffree = 0;
21512+
21513+ err = 0;
21514+ bend = au_sbend(sb);
21515+ for (bindex = bend; bindex >= 0; bindex--) {
7f207e10
AM
21516+ h_path.mnt = au_sbr_mnt(sb, bindex);
21517+ h_sb = h_path.mnt->mnt_sb;
1facf9fc 21518+ shared = 0;
21519+ for (i = bindex + 1; !shared && i <= bend; i++)
21520+ shared = (au_sbr_sb(sb, i) == h_sb);
21521+ if (shared)
21522+ continue;
21523+
21524+ /* sb->s_root for NFS is unreliable */
7f207e10
AM
21525+ h_path.dentry = h_path.mnt->mnt_root;
21526+ err = vfs_statfs(&h_path, buf);
1facf9fc 21527+ if (unlikely(err))
21528+ goto out;
21529+
21530+ blocks = au_add_till_max(blocks, buf->f_blocks);
21531+ bfree = au_add_till_max(bfree, buf->f_bfree);
21532+ bavail = au_add_till_max(bavail, buf->f_bavail);
21533+ files = au_add_till_max(files, buf->f_files);
21534+ ffree = au_add_till_max(ffree, buf->f_ffree);
21535+ }
21536+
21537+ buf->f_blocks = blocks;
21538+ buf->f_bfree = bfree;
21539+ buf->f_bavail = bavail;
21540+ buf->f_files = files;
21541+ buf->f_ffree = ffree;
21542+
4f0767ce 21543+out:
1facf9fc 21544+ return err;
21545+}
21546+
21547+static int aufs_statfs(struct dentry *dentry, struct kstatfs *buf)
21548+{
21549+ int err;
7f207e10 21550+ struct path h_path;
1facf9fc 21551+ struct super_block *sb;
21552+
21553+ /* lock free root dinfo */
21554+ sb = dentry->d_sb;
21555+ si_noflush_read_lock(sb);
7f207e10 21556+ if (!au_opt_test(au_mntflags(sb), SUM)) {
1facf9fc 21557+ /* sb->s_root for NFS is unreliable */
7f207e10
AM
21558+ h_path.mnt = au_sbr_mnt(sb, 0);
21559+ h_path.dentry = h_path.mnt->mnt_root;
21560+ err = vfs_statfs(&h_path, buf);
21561+ } else
1facf9fc 21562+ err = au_statfs_sum(sb, buf);
21563+ si_read_unlock(sb);
21564+
21565+ if (!err) {
21566+ buf->f_type = AUFS_SUPER_MAGIC;
4a4d8108 21567+ buf->f_namelen = AUFS_MAX_NAMELEN;
1facf9fc 21568+ memset(&buf->f_fsid, 0, sizeof(buf->f_fsid));
21569+ }
21570+ /* buf->f_bsize = buf->f_blocks = buf->f_bfree = buf->f_bavail = -1; */
21571+
21572+ return err;
21573+}
21574+
21575+/* ---------------------------------------------------------------------- */
21576+
1facf9fc 21577+/* final actions when unmounting a file system */
21578+static void aufs_put_super(struct super_block *sb)
21579+{
21580+ struct au_sbinfo *sbinfo;
21581+
21582+ sbinfo = au_sbi(sb);
21583+ if (!sbinfo)
21584+ return;
21585+
1facf9fc 21586+ dbgaufs_si_fin(sbinfo);
21587+ kobject_put(&sbinfo->si_kobj);
21588+}
21589+
21590+/* ---------------------------------------------------------------------- */
21591+
7f207e10
AM
21592+void au_array_free(void *array)
21593+{
21594+ if (array) {
21595+ if (!is_vmalloc_addr(array))
21596+ kfree(array);
21597+ else
21598+ vfree(array);
21599+ }
21600+}
21601+
21602+void *au_array_alloc(unsigned long long *hint, au_arraycb_t cb, void *arg)
21603+{
21604+ void *array;
21605+ unsigned long long n;
21606+
21607+ array = NULL;
21608+ n = 0;
21609+ if (!*hint)
21610+ goto out;
21611+
21612+ if (*hint > ULLONG_MAX / sizeof(array)) {
21613+ array = ERR_PTR(-EMFILE);
21614+ pr_err("hint %llu\n", *hint);
21615+ goto out;
21616+ }
21617+
21618+ array = kmalloc(sizeof(array) * *hint, GFP_NOFS);
21619+ if (unlikely(!array))
21620+ array = vmalloc(sizeof(array) * *hint);
21621+ if (unlikely(!array)) {
21622+ array = ERR_PTR(-ENOMEM);
21623+ goto out;
21624+ }
21625+
21626+ n = cb(array, *hint, arg);
21627+ AuDebugOn(n > *hint);
21628+
21629+out:
21630+ *hint = n;
21631+ return array;
21632+}
21633+
21634+static unsigned long long au_iarray_cb(void *a,
21635+ unsigned long long max __maybe_unused,
21636+ void *arg)
21637+{
21638+ unsigned long long n;
21639+ struct inode **p, *inode;
21640+ struct list_head *head;
21641+
21642+ n = 0;
21643+ p = a;
21644+ head = arg;
2cbb1c4b 21645+ spin_lock(&inode_sb_list_lock);
7f207e10
AM
21646+ list_for_each_entry(inode, head, i_sb_list) {
21647+ if (!is_bad_inode(inode)
21648+ && au_ii(inode)->ii_bstart >= 0) {
2cbb1c4b
JR
21649+ spin_lock(&inode->i_lock);
21650+ if (atomic_read(&inode->i_count)) {
21651+ au_igrab(inode);
21652+ *p++ = inode;
21653+ n++;
21654+ AuDebugOn(n > max);
21655+ }
21656+ spin_unlock(&inode->i_lock);
7f207e10
AM
21657+ }
21658+ }
2cbb1c4b 21659+ spin_unlock(&inode_sb_list_lock);
7f207e10
AM
21660+
21661+ return n;
21662+}
21663+
21664+struct inode **au_iarray_alloc(struct super_block *sb, unsigned long long *max)
21665+{
21666+ *max = atomic_long_read(&au_sbi(sb)->si_ninodes);
21667+ return au_array_alloc(max, au_iarray_cb, &sb->s_inodes);
21668+}
21669+
21670+void au_iarray_free(struct inode **a, unsigned long long max)
21671+{
21672+ unsigned long long ull;
21673+
21674+ for (ull = 0; ull < max; ull++)
21675+ iput(a[ull]);
21676+ au_array_free(a);
21677+}
21678+
21679+/* ---------------------------------------------------------------------- */
21680+
1facf9fc 21681+/*
21682+ * refresh dentry and inode at remount time.
21683+ */
027c5e7a
AM
21684+/* todo: consolidate with simple_reval_dpath() and au_reval_for_attr() */
21685+static int au_do_refresh(struct dentry *dentry, unsigned int dir_flags,
21686+ struct dentry *parent)
1facf9fc 21687+{
21688+ int err;
1facf9fc 21689+
21690+ di_write_lock_child(dentry);
1facf9fc 21691+ di_read_lock_parent(parent, AuLock_IR);
027c5e7a
AM
21692+ err = au_refresh_dentry(dentry, parent);
21693+ if (!err && dir_flags)
21694+ au_hn_reset(dentry->d_inode, dir_flags);
1facf9fc 21695+ di_read_unlock(parent, AuLock_IR);
1facf9fc 21696+ di_write_unlock(dentry);
21697+
21698+ return err;
21699+}
21700+
027c5e7a
AM
21701+static int au_do_refresh_d(struct dentry *dentry, unsigned int sigen,
21702+ struct au_sbinfo *sbinfo,
21703+ const unsigned int dir_flags)
1facf9fc 21704+{
027c5e7a
AM
21705+ int err;
21706+ struct dentry *parent;
21707+ struct inode *inode;
21708+
21709+ err = 0;
21710+ parent = dget_parent(dentry);
21711+ if (!au_digen_test(parent, sigen) && au_digen_test(dentry, sigen)) {
21712+ inode = dentry->d_inode;
21713+ if (inode) {
21714+ if (!S_ISDIR(inode->i_mode))
21715+ err = au_do_refresh(dentry, /*dir_flags*/0,
21716+ parent);
21717+ else {
21718+ err = au_do_refresh(dentry, dir_flags, parent);
21719+ if (unlikely(err))
21720+ au_fset_si(sbinfo, FAILED_REFRESH_DIR);
21721+ }
21722+ } else
21723+ err = au_do_refresh(dentry, /*dir_flags*/0, parent);
21724+ AuDbgDentry(dentry);
21725+ }
21726+ dput(parent);
21727+
21728+ AuTraceErr(err);
21729+ return err;
1facf9fc 21730+}
21731+
027c5e7a 21732+static int au_refresh_d(struct super_block *sb)
1facf9fc 21733+{
21734+ int err, i, j, ndentry, e;
027c5e7a 21735+ unsigned int sigen;
1facf9fc 21736+ struct au_dcsub_pages dpages;
21737+ struct au_dpage *dpage;
027c5e7a
AM
21738+ struct dentry **dentries, *d;
21739+ struct au_sbinfo *sbinfo;
21740+ struct dentry *root = sb->s_root;
21741+ const unsigned int dir_flags = au_hi_flags(root->d_inode, /*isdir*/1);
1facf9fc 21742+
027c5e7a
AM
21743+ err = au_dpages_init(&dpages, GFP_NOFS);
21744+ if (unlikely(err))
1facf9fc 21745+ goto out;
027c5e7a
AM
21746+ err = au_dcsub_pages(&dpages, root, NULL, NULL);
21747+ if (unlikely(err))
1facf9fc 21748+ goto out_dpages;
1facf9fc 21749+
027c5e7a
AM
21750+ sigen = au_sigen(sb);
21751+ sbinfo = au_sbi(sb);
21752+ for (i = 0; i < dpages.ndpage; i++) {
1facf9fc 21753+ dpage = dpages.dpages + i;
21754+ dentries = dpage->dentries;
21755+ ndentry = dpage->ndentry;
027c5e7a 21756+ for (j = 0; j < ndentry; j++) {
1facf9fc 21757+ d = dentries[j];
027c5e7a
AM
21758+ e = au_do_refresh_d(d, sigen, sbinfo, dir_flags);
21759+ if (unlikely(e && !err))
21760+ err = e;
21761+ /* go on even err */
1facf9fc 21762+ }
21763+ }
21764+
4f0767ce 21765+out_dpages:
1facf9fc 21766+ au_dpages_free(&dpages);
4f0767ce 21767+out:
1facf9fc 21768+ return err;
21769+}
21770+
027c5e7a 21771+static int au_refresh_i(struct super_block *sb)
1facf9fc 21772+{
027c5e7a
AM
21773+ int err, e;
21774+ unsigned int sigen;
21775+ unsigned long long max, ull;
21776+ struct inode *inode, **array;
1facf9fc 21777+
027c5e7a
AM
21778+ array = au_iarray_alloc(sb, &max);
21779+ err = PTR_ERR(array);
21780+ if (IS_ERR(array))
21781+ goto out;
1facf9fc 21782+
21783+ err = 0;
027c5e7a
AM
21784+ sigen = au_sigen(sb);
21785+ for (ull = 0; ull < max; ull++) {
21786+ inode = array[ull];
21787+ if (au_iigen(inode) != sigen) {
1facf9fc 21788+ ii_write_lock_child(inode);
027c5e7a 21789+ e = au_refresh_hinode_self(inode);
1facf9fc 21790+ ii_write_unlock(inode);
21791+ if (unlikely(e)) {
027c5e7a 21792+ pr_err("error %d, i%lu\n", e, inode->i_ino);
1facf9fc 21793+ if (!err)
21794+ err = e;
21795+ /* go on even if err */
21796+ }
21797+ }
1facf9fc 21798+ }
21799+
027c5e7a 21800+ au_iarray_free(array, max);
1facf9fc 21801+
4f0767ce 21802+out:
1facf9fc 21803+ return err;
21804+}
21805+
027c5e7a 21806+static void au_remount_refresh(struct super_block *sb)
1facf9fc 21807+{
027c5e7a
AM
21808+ int err, e;
21809+ unsigned int udba;
21810+ aufs_bindex_t bindex, bend;
1facf9fc 21811+ struct dentry *root;
21812+ struct inode *inode;
027c5e7a 21813+ struct au_branch *br;
1facf9fc 21814+
21815+ au_sigen_inc(sb);
027c5e7a 21816+ au_fclr_si(au_sbi(sb), FAILED_REFRESH_DIR);
1facf9fc 21817+
21818+ root = sb->s_root;
21819+ DiMustNoWaiters(root);
21820+ inode = root->d_inode;
21821+ IiMustNoWaiters(inode);
1facf9fc 21822+
027c5e7a
AM
21823+ udba = au_opt_udba(sb);
21824+ bend = au_sbend(sb);
21825+ for (bindex = 0; bindex <= bend; bindex++) {
21826+ br = au_sbr(sb, bindex);
21827+ err = au_hnotify_reset_br(udba, br, br->br_perm);
1facf9fc 21828+ if (unlikely(err))
027c5e7a
AM
21829+ AuIOErr("hnotify failed on br %d, %d, ignored\n",
21830+ bindex, err);
21831+ /* go on even if err */
1facf9fc 21832+ }
027c5e7a 21833+ au_hn_reset(inode, au_hi_flags(inode, /*isdir*/1));
1facf9fc 21834+
027c5e7a
AM
21835+ di_write_unlock(root);
21836+ err = au_refresh_d(sb);
21837+ e = au_refresh_i(sb);
21838+ if (unlikely(e && !err))
21839+ err = e;
1facf9fc 21840+ /* aufs_write_lock() calls ..._child() */
21841+ di_write_lock_child(root);
027c5e7a
AM
21842+
21843+ au_cpup_attr_all(inode, /*force*/1);
21844+
21845+ if (unlikely(err))
21846+ AuIOErr("refresh failed, ignored, %d\n", err);
1facf9fc 21847+}
21848+
21849+/* stop extra interpretation of errno in mount(8), and strange error messages */
21850+static int cvt_err(int err)
21851+{
21852+ AuTraceErr(err);
21853+
21854+ switch (err) {
21855+ case -ENOENT:
21856+ case -ENOTDIR:
21857+ case -EEXIST:
21858+ case -EIO:
21859+ err = -EINVAL;
21860+ }
21861+ return err;
21862+}
21863+
21864+static int aufs_remount_fs(struct super_block *sb, int *flags, char *data)
21865+{
4a4d8108
AM
21866+ int err, do_dx;
21867+ unsigned int mntflags;
1facf9fc 21868+ struct au_opts opts;
21869+ struct dentry *root;
21870+ struct inode *inode;
21871+ struct au_sbinfo *sbinfo;
21872+
21873+ err = 0;
21874+ root = sb->s_root;
21875+ if (!data || !*data) {
e49829fe
JR
21876+ err = si_write_lock(sb, AuLock_FLUSH | AuLock_NOPLM);
21877+ if (!err) {
21878+ di_write_lock_child(root);
21879+ err = au_opts_verify(sb, *flags, /*pending*/0);
21880+ aufs_write_unlock(root);
21881+ }
1facf9fc 21882+ goto out;
21883+ }
21884+
21885+ err = -ENOMEM;
21886+ memset(&opts, 0, sizeof(opts));
21887+ opts.opt = (void *)__get_free_page(GFP_NOFS);
21888+ if (unlikely(!opts.opt))
21889+ goto out;
21890+ opts.max_opt = PAGE_SIZE / sizeof(*opts.opt);
21891+ opts.flags = AuOpts_REMOUNT;
21892+ opts.sb_flags = *flags;
21893+
21894+ /* parse it before aufs lock */
21895+ err = au_opts_parse(sb, data, &opts);
21896+ if (unlikely(err))
21897+ goto out_opts;
21898+
21899+ sbinfo = au_sbi(sb);
21900+ inode = root->d_inode;
21901+ mutex_lock(&inode->i_mutex);
e49829fe
JR
21902+ err = si_write_lock(sb, AuLock_FLUSH | AuLock_NOPLM);
21903+ if (unlikely(err))
21904+ goto out_mtx;
21905+ di_write_lock_child(root);
1facf9fc 21906+
21907+ /* au_opts_remount() may return an error */
21908+ err = au_opts_remount(sb, &opts);
21909+ au_opts_free(&opts);
21910+
027c5e7a
AM
21911+ if (au_ftest_opts(opts.flags, REFRESH))
21912+ au_remount_refresh(sb);
1facf9fc 21913+
4a4d8108
AM
21914+ if (au_ftest_opts(opts.flags, REFRESH_DYAOP)) {
21915+ mntflags = au_mntflags(sb);
21916+ do_dx = !!au_opt_test(mntflags, DIO);
21917+ au_dy_arefresh(do_dx);
21918+ }
21919+
1facf9fc 21920+ aufs_write_unlock(root);
953406b4 21921+
e49829fe
JR
21922+out_mtx:
21923+ mutex_unlock(&inode->i_mutex);
4f0767ce 21924+out_opts:
1facf9fc 21925+ free_page((unsigned long)opts.opt);
4f0767ce 21926+out:
1facf9fc 21927+ err = cvt_err(err);
21928+ AuTraceErr(err);
21929+ return err;
21930+}
21931+
4a4d8108 21932+static const struct super_operations aufs_sop = {
1facf9fc 21933+ .alloc_inode = aufs_alloc_inode,
21934+ .destroy_inode = aufs_destroy_inode,
b752ccd1 21935+ /* always deleting, no clearing */
1facf9fc 21936+ .drop_inode = generic_delete_inode,
21937+ .show_options = aufs_show_options,
21938+ .statfs = aufs_statfs,
21939+ .put_super = aufs_put_super,
21940+ .remount_fs = aufs_remount_fs
21941+};
21942+
21943+/* ---------------------------------------------------------------------- */
21944+
21945+static int alloc_root(struct super_block *sb)
21946+{
21947+ int err;
21948+ struct inode *inode;
21949+ struct dentry *root;
21950+
21951+ err = -ENOMEM;
21952+ inode = au_iget_locked(sb, AUFS_ROOT_INO);
21953+ err = PTR_ERR(inode);
21954+ if (IS_ERR(inode))
21955+ goto out;
21956+
21957+ inode->i_op = &aufs_dir_iop;
21958+ inode->i_fop = &aufs_dir_fop;
21959+ inode->i_mode = S_IFDIR;
21960+ inode->i_nlink = 2;
21961+ unlock_new_inode(inode);
21962+
21963+ root = d_alloc_root(inode);
21964+ if (unlikely(!root))
21965+ goto out_iput;
21966+ err = PTR_ERR(root);
21967+ if (IS_ERR(root))
21968+ goto out_iput;
21969+
4a4d8108 21970+ err = au_di_init(root);
1facf9fc 21971+ if (!err) {
21972+ sb->s_root = root;
21973+ return 0; /* success */
21974+ }
21975+ dput(root);
21976+ goto out; /* do not iput */
21977+
4f0767ce 21978+out_iput:
1facf9fc 21979+ iget_failed(inode);
4f0767ce 21980+out:
1facf9fc 21981+ return err;
21982+
21983+}
21984+
21985+static int aufs_fill_super(struct super_block *sb, void *raw_data,
21986+ int silent __maybe_unused)
21987+{
21988+ int err;
21989+ struct au_opts opts;
21990+ struct dentry *root;
21991+ struct inode *inode;
21992+ char *arg = raw_data;
21993+
21994+ if (unlikely(!arg || !*arg)) {
21995+ err = -EINVAL;
4a4d8108 21996+ pr_err("no arg\n");
1facf9fc 21997+ goto out;
21998+ }
21999+
22000+ err = -ENOMEM;
22001+ memset(&opts, 0, sizeof(opts));
22002+ opts.opt = (void *)__get_free_page(GFP_NOFS);
22003+ if (unlikely(!opts.opt))
22004+ goto out;
22005+ opts.max_opt = PAGE_SIZE / sizeof(*opts.opt);
22006+ opts.sb_flags = sb->s_flags;
22007+
22008+ err = au_si_alloc(sb);
22009+ if (unlikely(err))
22010+ goto out_opts;
22011+
22012+ /* all timestamps always follow the ones on the branch */
22013+ sb->s_flags |= MS_NOATIME | MS_NODIRATIME;
22014+ sb->s_op = &aufs_sop;
027c5e7a 22015+ sb->s_d_op = &aufs_dop;
1facf9fc 22016+ sb->s_magic = AUFS_SUPER_MAGIC;
22017+ sb->s_maxbytes = 0;
22018+ au_export_init(sb);
22019+
22020+ err = alloc_root(sb);
22021+ if (unlikely(err)) {
22022+ si_write_unlock(sb);
22023+ goto out_info;
22024+ }
22025+ root = sb->s_root;
22026+ inode = root->d_inode;
22027+
22028+ /*
22029+ * actually we can parse options regardless aufs lock here.
22030+ * but at remount time, parsing must be done before aufs lock.
22031+ * so we follow the same rule.
22032+ */
22033+ ii_write_lock_parent(inode);
22034+ aufs_write_unlock(root);
22035+ err = au_opts_parse(sb, arg, &opts);
22036+ if (unlikely(err))
22037+ goto out_root;
22038+
22039+ /* lock vfs_inode first, then aufs. */
22040+ mutex_lock(&inode->i_mutex);
1facf9fc 22041+ aufs_write_lock(root);
22042+ err = au_opts_mount(sb, &opts);
22043+ au_opts_free(&opts);
1facf9fc 22044+ aufs_write_unlock(root);
22045+ mutex_unlock(&inode->i_mutex);
4a4d8108
AM
22046+ if (!err)
22047+ goto out_opts; /* success */
1facf9fc 22048+
4f0767ce 22049+out_root:
1facf9fc 22050+ dput(root);
22051+ sb->s_root = NULL;
4f0767ce 22052+out_info:
2cbb1c4b 22053+ dbgaufs_si_fin(au_sbi(sb));
1facf9fc 22054+ kobject_put(&au_sbi(sb)->si_kobj);
22055+ sb->s_fs_info = NULL;
4f0767ce 22056+out_opts:
1facf9fc 22057+ free_page((unsigned long)opts.opt);
4f0767ce 22058+out:
1facf9fc 22059+ AuTraceErr(err);
22060+ err = cvt_err(err);
22061+ AuTraceErr(err);
22062+ return err;
22063+}
22064+
22065+/* ---------------------------------------------------------------------- */
22066+
027c5e7a
AM
22067+static struct dentry *aufs_mount(struct file_system_type *fs_type, int flags,
22068+ const char *dev_name __maybe_unused,
22069+ void *raw_data)
1facf9fc 22070+{
027c5e7a 22071+ struct dentry *root;
1facf9fc 22072+ struct super_block *sb;
22073+
22074+ /* all timestamps always follow the ones on the branch */
22075+ /* mnt->mnt_flags |= MNT_NOATIME | MNT_NODIRATIME; */
027c5e7a
AM
22076+ root = mount_nodev(fs_type, flags, raw_data, aufs_fill_super);
22077+ if (IS_ERR(root))
22078+ goto out;
22079+
22080+ sb = root->d_sb;
22081+ si_write_lock(sb, !AuLock_FLUSH);
22082+ sysaufs_brs_add(sb, 0);
22083+ si_write_unlock(sb);
22084+ au_sbilist_add(sb);
22085+
22086+out:
22087+ return root;
1facf9fc 22088+}
22089+
e49829fe
JR
22090+static void aufs_kill_sb(struct super_block *sb)
22091+{
22092+ struct au_sbinfo *sbinfo;
22093+
22094+ sbinfo = au_sbi(sb);
22095+ if (sbinfo) {
22096+ au_sbilist_del(sb);
22097+ aufs_write_lock(sb->s_root);
22098+ if (sbinfo->si_wbr_create_ops->fin)
22099+ sbinfo->si_wbr_create_ops->fin(sb);
22100+ if (au_opt_test(sbinfo->si_mntflags, UDBA_HNOTIFY)) {
22101+ au_opt_set_udba(sbinfo->si_mntflags, UDBA_NONE);
027c5e7a 22102+ au_remount_refresh(sb);
e49829fe
JR
22103+ }
22104+ if (au_opt_test(sbinfo->si_mntflags, PLINK))
22105+ au_plink_put(sb, /*verbose*/1);
22106+ au_xino_clr(sb);
22107+ aufs_write_unlock(sb->s_root);
e49829fe
JR
22108+ au_nwt_flush(&sbinfo->si_nowait);
22109+ }
22110+ generic_shutdown_super(sb);
22111+}
22112+
1facf9fc 22113+struct file_system_type aufs_fs_type = {
22114+ .name = AUFS_FSTYPE,
22115+ .fs_flags =
22116+ FS_RENAME_DOES_D_MOVE /* a race between rename and others */
22117+ | FS_REVAL_DOT, /* for NFS branch and udba */
027c5e7a 22118+ .mount = aufs_mount,
e49829fe 22119+ .kill_sb = aufs_kill_sb,
1facf9fc 22120+ /* no need to __module_get() and module_put(). */
22121+ .owner = THIS_MODULE,
22122+};
7f207e10
AM
22123diff -urN /usr/share/empty/fs/aufs/super.h linux/fs/aufs/super.h
22124--- /usr/share/empty/fs/aufs/super.h 1970-01-01 01:00:00.000000000 +0100
2cbb1c4b 22125+++ linux/fs/aufs/super.h 2011-07-11 11:34:24.077331673 +0200
027c5e7a 22126@@ -0,0 +1,527 @@
1facf9fc 22127+/*
027c5e7a 22128+ * Copyright (C) 2005-2011 Junjiro R. Okajima
1facf9fc 22129+ *
22130+ * This program, aufs is free software; you can redistribute it and/or modify
22131+ * it under the terms of the GNU General Public License as published by
22132+ * the Free Software Foundation; either version 2 of the License, or
22133+ * (at your option) any later version.
dece6358
AM
22134+ *
22135+ * This program is distributed in the hope that it will be useful,
22136+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
22137+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22138+ * GNU General Public License for more details.
22139+ *
22140+ * You should have received a copy of the GNU General Public License
22141+ * along with this program; if not, write to the Free Software
22142+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 22143+ */
22144+
22145+/*
22146+ * super_block operations
22147+ */
22148+
22149+#ifndef __AUFS_SUPER_H__
22150+#define __AUFS_SUPER_H__
22151+
22152+#ifdef __KERNEL__
22153+
22154+#include <linux/fs.h>
1facf9fc 22155+#include <linux/aufs_type.h>
22156+#include "rwsem.h"
22157+#include "spl.h"
22158+#include "wkq.h"
22159+
22160+typedef ssize_t (*au_readf_t)(struct file *, char __user *, size_t, loff_t *);
22161+typedef ssize_t (*au_writef_t)(struct file *, const char __user *, size_t,
22162+ loff_t *);
22163+
22164+/* policies to select one among multiple writable branches */
22165+struct au_wbr_copyup_operations {
22166+ int (*copyup)(struct dentry *dentry);
22167+};
22168+
22169+struct au_wbr_create_operations {
22170+ int (*create)(struct dentry *dentry, int isdir);
22171+ int (*init)(struct super_block *sb);
22172+ int (*fin)(struct super_block *sb);
22173+};
22174+
22175+struct au_wbr_mfs {
22176+ struct mutex mfs_lock; /* protect this structure */
22177+ unsigned long mfs_jiffy;
22178+ unsigned long mfs_expire;
22179+ aufs_bindex_t mfs_bindex;
22180+
22181+ unsigned long long mfsrr_bytes;
22182+ unsigned long long mfsrr_watermark;
22183+};
22184+
1facf9fc 22185+struct au_branch;
22186+struct au_sbinfo {
22187+ /* nowait tasks in the system-wide workqueue */
22188+ struct au_nowait_tasks si_nowait;
22189+
b752ccd1
AM
22190+ /*
22191+ * tried sb->s_umount, but failed due to the dependecy between i_mutex.
22192+ * rwsem for au_sbinfo is necessary.
22193+ */
dece6358 22194+ struct au_rwsem si_rwsem;
1facf9fc 22195+
b752ccd1
AM
22196+ /* prevent recursive locking in deleting inode */
22197+ struct {
22198+ unsigned long *bitmap;
22199+ spinlock_t tree_lock;
22200+ struct radix_tree_root tree;
22201+ } au_si_pid;
22202+
7f207e10
AM
22203+ /*
22204+ * dirty approach to protect sb->sb_inodes and ->s_files from remount.
22205+ */
22206+ atomic_long_t si_ninodes, si_nfiles;
22207+
1facf9fc 22208+ /* branch management */
22209+ unsigned int si_generation;
22210+
22211+ /* see above flags */
22212+ unsigned char au_si_status;
22213+
22214+ aufs_bindex_t si_bend;
7f207e10
AM
22215+
22216+ /* dirty trick to keep br_id plus */
22217+ unsigned int si_last_br_id :
22218+ sizeof(aufs_bindex_t) * BITS_PER_BYTE - 1;
1facf9fc 22219+ struct au_branch **si_branch;
22220+
22221+ /* policy to select a writable branch */
22222+ unsigned char si_wbr_copyup;
22223+ unsigned char si_wbr_create;
22224+ struct au_wbr_copyup_operations *si_wbr_copyup_ops;
22225+ struct au_wbr_create_operations *si_wbr_create_ops;
22226+
22227+ /* round robin */
22228+ atomic_t si_wbr_rr_next;
22229+
22230+ /* most free space */
22231+ struct au_wbr_mfs si_wbr_mfs;
22232+
22233+ /* mount flags */
22234+ /* include/asm-ia64/siginfo.h defines a macro named si_flags */
22235+ unsigned int si_mntflags;
22236+
22237+ /* external inode number (bitmap and translation table) */
22238+ au_readf_t si_xread;
22239+ au_writef_t si_xwrite;
22240+ struct file *si_xib;
22241+ struct mutex si_xib_mtx; /* protect xib members */
22242+ unsigned long *si_xib_buf;
22243+ unsigned long si_xib_last_pindex;
22244+ int si_xib_next_bit;
22245+ aufs_bindex_t si_xino_brid;
22246+ /* reserved for future use */
22247+ /* unsigned long long si_xib_limit; */ /* Max xib file size */
22248+
22249+#ifdef CONFIG_AUFS_EXPORT
22250+ /* i_generation */
22251+ struct file *si_xigen;
22252+ atomic_t si_xigen_next;
22253+#endif
22254+
22255+ /* vdir parameters */
e49829fe 22256+ unsigned long si_rdcache; /* max cache time in jiffies */
1facf9fc 22257+ unsigned int si_rdblk; /* deblk size */
22258+ unsigned int si_rdhash; /* hash size */
22259+
22260+ /*
22261+ * If the number of whiteouts are larger than si_dirwh, leave all of
22262+ * them after au_whtmp_ren to reduce the cost of rmdir(2).
22263+ * future fsck.aufs or kernel thread will remove them later.
22264+ * Otherwise, remove all whiteouts and the dir in rmdir(2).
22265+ */
22266+ unsigned int si_dirwh;
22267+
22268+ /*
22269+ * rename(2) a directory with all children.
22270+ */
22271+ /* reserved for future use */
22272+ /* int si_rendir; */
22273+
22274+ /* pseudo_link list */
22275+ struct au_splhead si_plink;
22276+ wait_queue_head_t si_plink_wq;
4a4d8108 22277+ spinlock_t si_plink_maint_lock;
e49829fe 22278+ pid_t si_plink_maint_pid;
1facf9fc 22279+
22280+ /*
22281+ * sysfs and lifetime management.
22282+ * this is not a small structure and it may be a waste of memory in case
22283+ * of sysfs is disabled, particulary when many aufs-es are mounted.
22284+ * but using sysfs is majority.
22285+ */
22286+ struct kobject si_kobj;
22287+#ifdef CONFIG_DEBUG_FS
22288+ struct dentry *si_dbgaufs, *si_dbgaufs_xib;
22289+#ifdef CONFIG_AUFS_EXPORT
22290+ struct dentry *si_dbgaufs_xigen;
22291+#endif
22292+#endif
22293+
e49829fe
JR
22294+#ifdef CONFIG_AUFS_SBILIST
22295+ struct list_head si_list;
22296+#endif
22297+
1facf9fc 22298+ /* dirty, necessary for unmounting, sysfs and sysrq */
22299+ struct super_block *si_sb;
22300+};
22301+
dece6358
AM
22302+/* sbinfo status flags */
22303+/*
22304+ * set true when refresh_dirs() failed at remount time.
22305+ * then try refreshing dirs at access time again.
22306+ * if it is false, refreshing dirs at access time is unnecesary
22307+ */
027c5e7a 22308+#define AuSi_FAILED_REFRESH_DIR 1
dece6358
AM
22309+static inline unsigned char au_do_ftest_si(struct au_sbinfo *sbi,
22310+ unsigned int flag)
22311+{
22312+ AuRwMustAnyLock(&sbi->si_rwsem);
22313+ return sbi->au_si_status & flag;
22314+}
22315+#define au_ftest_si(sbinfo, name) au_do_ftest_si(sbinfo, AuSi_##name)
22316+#define au_fset_si(sbinfo, name) do { \
22317+ AuRwMustWriteLock(&(sbinfo)->si_rwsem); \
22318+ (sbinfo)->au_si_status |= AuSi_##name; \
22319+} while (0)
22320+#define au_fclr_si(sbinfo, name) do { \
22321+ AuRwMustWriteLock(&(sbinfo)->si_rwsem); \
22322+ (sbinfo)->au_si_status &= ~AuSi_##name; \
22323+} while (0)
22324+
1facf9fc 22325+/* ---------------------------------------------------------------------- */
22326+
22327+/* policy to select one among writable branches */
4a4d8108
AM
22328+#define AuWbrCopyup(sbinfo, ...) \
22329+ ((sbinfo)->si_wbr_copyup_ops->copyup(__VA_ARGS__))
22330+#define AuWbrCreate(sbinfo, ...) \
22331+ ((sbinfo)->si_wbr_create_ops->create(__VA_ARGS__))
1facf9fc 22332+
22333+/* flags for si_read_lock()/aufs_read_lock()/di_read_lock() */
22334+#define AuLock_DW 1 /* write-lock dentry */
22335+#define AuLock_IR (1 << 1) /* read-lock inode */
22336+#define AuLock_IW (1 << 2) /* write-lock inode */
22337+#define AuLock_FLUSH (1 << 3) /* wait for 'nowait' tasks */
22338+#define AuLock_DIR (1 << 4) /* target is a dir */
e49829fe
JR
22339+#define AuLock_NOPLM (1 << 5) /* return err in plm mode */
22340+#define AuLock_NOPLMW (1 << 6) /* wait for plm mode ends */
027c5e7a 22341+#define AuLock_GEN (1 << 7) /* test digen/iigen */
1facf9fc 22342+#define au_ftest_lock(flags, name) ((flags) & AuLock_##name)
7f207e10
AM
22343+#define au_fset_lock(flags, name) \
22344+ do { (flags) |= AuLock_##name; } while (0)
22345+#define au_fclr_lock(flags, name) \
22346+ do { (flags) &= ~AuLock_##name; } while (0)
1facf9fc 22347+
22348+/* ---------------------------------------------------------------------- */
22349+
22350+/* super.c */
22351+extern struct file_system_type aufs_fs_type;
22352+struct inode *au_iget_locked(struct super_block *sb, ino_t ino);
7f207e10
AM
22353+typedef unsigned long long (*au_arraycb_t)(void *array, unsigned long long max,
22354+ void *arg);
22355+void au_array_free(void *array);
22356+void *au_array_alloc(unsigned long long *hint, au_arraycb_t cb, void *arg);
22357+struct inode **au_iarray_alloc(struct super_block *sb, unsigned long long *max);
22358+void au_iarray_free(struct inode **a, unsigned long long max);
1facf9fc 22359+
22360+/* sbinfo.c */
22361+void au_si_free(struct kobject *kobj);
22362+int au_si_alloc(struct super_block *sb);
22363+int au_sbr_realloc(struct au_sbinfo *sbinfo, int nbr);
22364+
22365+unsigned int au_sigen_inc(struct super_block *sb);
22366+aufs_bindex_t au_new_br_id(struct super_block *sb);
22367+
e49829fe
JR
22368+int si_read_lock(struct super_block *sb, int flags);
22369+int si_write_lock(struct super_block *sb, int flags);
22370+int aufs_read_lock(struct dentry *dentry, int flags);
1facf9fc 22371+void aufs_read_unlock(struct dentry *dentry, int flags);
22372+void aufs_write_lock(struct dentry *dentry);
22373+void aufs_write_unlock(struct dentry *dentry);
e49829fe 22374+int aufs_read_and_write_lock2(struct dentry *d1, struct dentry *d2, int flags);
1facf9fc 22375+void aufs_read_and_write_unlock2(struct dentry *d1, struct dentry *d2);
22376+
b752ccd1
AM
22377+int si_pid_test_slow(struct super_block *sb);
22378+void si_pid_set_slow(struct super_block *sb);
22379+void si_pid_clr_slow(struct super_block *sb);
22380+
1facf9fc 22381+/* wbr_policy.c */
22382+extern struct au_wbr_copyup_operations au_wbr_copyup_ops[];
22383+extern struct au_wbr_create_operations au_wbr_create_ops[];
22384+int au_cpdown_dirs(struct dentry *dentry, aufs_bindex_t bdst);
22385+
22386+/* ---------------------------------------------------------------------- */
22387+
22388+static inline struct au_sbinfo *au_sbi(struct super_block *sb)
22389+{
22390+ return sb->s_fs_info;
22391+}
22392+
22393+/* ---------------------------------------------------------------------- */
22394+
22395+#ifdef CONFIG_AUFS_EXPORT
22396+void au_export_init(struct super_block *sb);
22397+
b752ccd1 22398+static inline int au_test_nfsd(void)
1facf9fc 22399+{
b752ccd1
AM
22400+ struct task_struct *tsk = current;
22401+
22402+ return (tsk->flags & PF_KTHREAD)
22403+ && !strcmp(tsk->comm, "nfsd");
1facf9fc 22404+}
22405+
b752ccd1 22406+void au_xigen_inc(struct inode *inode);
1facf9fc 22407+int au_xigen_new(struct inode *inode);
22408+int au_xigen_set(struct super_block *sb, struct file *base);
22409+void au_xigen_clr(struct super_block *sb);
22410+
22411+static inline int au_busy_or_stale(void)
22412+{
b752ccd1 22413+ if (!au_test_nfsd())
1facf9fc 22414+ return -EBUSY;
22415+ return -ESTALE;
22416+}
22417+#else
4a4d8108 22418+AuStubVoid(au_export_init, struct super_block *sb)
b752ccd1
AM
22419+AuStubInt0(au_test_nfsd, void)
22420+AuStubVoid(au_xigen_inc, struct inode *inode)
4a4d8108
AM
22421+AuStubInt0(au_xigen_new, struct inode *inode)
22422+AuStubInt0(au_xigen_set, struct super_block *sb, struct file *base)
22423+AuStubVoid(au_xigen_clr, struct super_block *sb)
1facf9fc 22424+static inline int au_busy_or_stale(void)
22425+{
22426+ return -EBUSY;
22427+}
22428+#endif /* CONFIG_AUFS_EXPORT */
22429+
22430+/* ---------------------------------------------------------------------- */
22431+
e49829fe
JR
22432+#ifdef CONFIG_AUFS_SBILIST
22433+/* module.c */
22434+extern struct au_splhead au_sbilist;
22435+
22436+static inline void au_sbilist_init(void)
22437+{
22438+ au_spl_init(&au_sbilist);
22439+}
22440+
22441+static inline void au_sbilist_add(struct super_block *sb)
22442+{
22443+ au_spl_add(&au_sbi(sb)->si_list, &au_sbilist);
22444+}
22445+
22446+static inline void au_sbilist_del(struct super_block *sb)
22447+{
22448+ au_spl_del(&au_sbi(sb)->si_list, &au_sbilist);
22449+}
22450+#else
22451+AuStubVoid(au_sbilist_init, void)
22452+AuStubVoid(au_sbilist_add, struct super_block*)
22453+AuStubVoid(au_sbilist_del, struct super_block*)
22454+#endif
22455+
22456+/* ---------------------------------------------------------------------- */
22457+
1facf9fc 22458+static inline void dbgaufs_si_null(struct au_sbinfo *sbinfo)
22459+{
dece6358
AM
22460+ /*
22461+ * This function is a dynamic '__init' fucntion actually,
22462+ * so the tiny check for si_rwsem is unnecessary.
22463+ */
22464+ /* AuRwMustWriteLock(&sbinfo->si_rwsem); */
1facf9fc 22465+#ifdef CONFIG_DEBUG_FS
22466+ sbinfo->si_dbgaufs = NULL;
22467+ sbinfo->si_dbgaufs_xib = NULL;
22468+#ifdef CONFIG_AUFS_EXPORT
22469+ sbinfo->si_dbgaufs_xigen = NULL;
22470+#endif
22471+#endif
22472+}
22473+
22474+/* ---------------------------------------------------------------------- */
22475+
b752ccd1
AM
22476+static inline pid_t si_pid_bit(void)
22477+{
22478+ /* the origin of pid is 1, but the bitmap's is 0 */
22479+ return current->pid - 1;
22480+}
22481+
22482+static inline int si_pid_test(struct super_block *sb)
22483+{
22484+ pid_t bit = si_pid_bit();
22485+ if (bit < PID_MAX_DEFAULT)
22486+ return test_bit(bit, au_sbi(sb)->au_si_pid.bitmap);
22487+ else
22488+ return si_pid_test_slow(sb);
22489+}
22490+
22491+static inline void si_pid_set(struct super_block *sb)
22492+{
22493+ pid_t bit = si_pid_bit();
22494+ if (bit < PID_MAX_DEFAULT) {
22495+ AuDebugOn(test_bit(bit, au_sbi(sb)->au_si_pid.bitmap));
22496+ set_bit(bit, au_sbi(sb)->au_si_pid.bitmap);
22497+ /* smp_mb(); */
22498+ } else
22499+ si_pid_set_slow(sb);
22500+}
22501+
22502+static inline void si_pid_clr(struct super_block *sb)
22503+{
22504+ pid_t bit = si_pid_bit();
22505+ if (bit < PID_MAX_DEFAULT) {
22506+ AuDebugOn(!test_bit(bit, au_sbi(sb)->au_si_pid.bitmap));
22507+ clear_bit(bit, au_sbi(sb)->au_si_pid.bitmap);
22508+ /* smp_mb(); */
22509+ } else
22510+ si_pid_clr_slow(sb);
22511+}
22512+
22513+/* ---------------------------------------------------------------------- */
22514+
1facf9fc 22515+/* lock superblock. mainly for entry point functions */
22516+/*
b752ccd1
AM
22517+ * __si_read_lock, __si_write_lock,
22518+ * __si_read_unlock, __si_write_unlock, __si_downgrade_lock
1facf9fc 22519+ */
b752ccd1 22520+AuSimpleRwsemFuncs(__si, struct super_block *sb, &au_sbi(sb)->si_rwsem);
1facf9fc 22521+
dece6358
AM
22522+#define SiMustNoWaiters(sb) AuRwMustNoWaiters(&au_sbi(sb)->si_rwsem)
22523+#define SiMustAnyLock(sb) AuRwMustAnyLock(&au_sbi(sb)->si_rwsem)
22524+#define SiMustWriteLock(sb) AuRwMustWriteLock(&au_sbi(sb)->si_rwsem)
22525+
b752ccd1
AM
22526+static inline void si_noflush_read_lock(struct super_block *sb)
22527+{
22528+ __si_read_lock(sb);
22529+ si_pid_set(sb);
22530+}
22531+
22532+static inline int si_noflush_read_trylock(struct super_block *sb)
22533+{
22534+ int locked = __si_read_trylock(sb);
22535+ if (locked)
22536+ si_pid_set(sb);
22537+ return locked;
22538+}
22539+
22540+static inline void si_noflush_write_lock(struct super_block *sb)
22541+{
22542+ __si_write_lock(sb);
22543+ si_pid_set(sb);
22544+}
22545+
22546+static inline int si_noflush_write_trylock(struct super_block *sb)
22547+{
22548+ int locked = __si_write_trylock(sb);
22549+ if (locked)
22550+ si_pid_set(sb);
22551+ return locked;
22552+}
22553+
e49829fe 22554+#if 0 /* unused */
1facf9fc 22555+static inline int si_read_trylock(struct super_block *sb, int flags)
22556+{
22557+ if (au_ftest_lock(flags, FLUSH))
22558+ au_nwt_flush(&au_sbi(sb)->si_nowait);
22559+ return si_noflush_read_trylock(sb);
22560+}
e49829fe 22561+#endif
1facf9fc 22562+
b752ccd1
AM
22563+static inline void si_read_unlock(struct super_block *sb)
22564+{
22565+ si_pid_clr(sb);
22566+ __si_read_unlock(sb);
22567+}
22568+
b752ccd1 22569+#if 0 /* unused */
1facf9fc 22570+static inline int si_write_trylock(struct super_block *sb, int flags)
22571+{
22572+ if (au_ftest_lock(flags, FLUSH))
22573+ au_nwt_flush(&au_sbi(sb)->si_nowait);
22574+ return si_noflush_write_trylock(sb);
22575+}
b752ccd1
AM
22576+#endif
22577+
22578+static inline void si_write_unlock(struct super_block *sb)
22579+{
22580+ si_pid_clr(sb);
22581+ __si_write_unlock(sb);
22582+}
22583+
22584+#if 0 /* unused */
22585+static inline void si_downgrade_lock(struct super_block *sb)
22586+{
22587+ __si_downgrade_lock(sb);
22588+}
22589+#endif
1facf9fc 22590+
22591+/* ---------------------------------------------------------------------- */
22592+
22593+static inline aufs_bindex_t au_sbend(struct super_block *sb)
22594+{
dece6358 22595+ SiMustAnyLock(sb);
1facf9fc 22596+ return au_sbi(sb)->si_bend;
22597+}
22598+
22599+static inline unsigned int au_mntflags(struct super_block *sb)
22600+{
dece6358 22601+ SiMustAnyLock(sb);
1facf9fc 22602+ return au_sbi(sb)->si_mntflags;
22603+}
22604+
22605+static inline unsigned int au_sigen(struct super_block *sb)
22606+{
dece6358 22607+ SiMustAnyLock(sb);
1facf9fc 22608+ return au_sbi(sb)->si_generation;
22609+}
22610+
7f207e10
AM
22611+static inline void au_ninodes_inc(struct super_block *sb)
22612+{
22613+ atomic_long_inc(&au_sbi(sb)->si_ninodes);
22614+}
22615+
22616+static inline void au_ninodes_dec(struct super_block *sb)
22617+{
22618+ AuDebugOn(!atomic_long_read(&au_sbi(sb)->si_ninodes));
22619+ atomic_long_dec(&au_sbi(sb)->si_ninodes);
22620+}
22621+
22622+static inline void au_nfiles_inc(struct super_block *sb)
22623+{
22624+ atomic_long_inc(&au_sbi(sb)->si_nfiles);
22625+}
22626+
22627+static inline void au_nfiles_dec(struct super_block *sb)
22628+{
22629+ AuDebugOn(!atomic_long_read(&au_sbi(sb)->si_nfiles));
22630+ atomic_long_dec(&au_sbi(sb)->si_nfiles);
22631+}
22632+
1facf9fc 22633+static inline struct au_branch *au_sbr(struct super_block *sb,
22634+ aufs_bindex_t bindex)
22635+{
dece6358 22636+ SiMustAnyLock(sb);
1facf9fc 22637+ return au_sbi(sb)->si_branch[0 + bindex];
22638+}
22639+
22640+static inline void au_xino_brid_set(struct super_block *sb, aufs_bindex_t brid)
22641+{
dece6358 22642+ SiMustWriteLock(sb);
1facf9fc 22643+ au_sbi(sb)->si_xino_brid = brid;
22644+}
22645+
22646+static inline aufs_bindex_t au_xino_brid(struct super_block *sb)
22647+{
dece6358 22648+ SiMustAnyLock(sb);
1facf9fc 22649+ return au_sbi(sb)->si_xino_brid;
22650+}
22651+
22652+#endif /* __KERNEL__ */
22653+#endif /* __AUFS_SUPER_H__ */
7f207e10
AM
22654diff -urN /usr/share/empty/fs/aufs/sysaufs.c linux/fs/aufs/sysaufs.c
22655--- /usr/share/empty/fs/aufs/sysaufs.c 1970-01-01 01:00:00.000000000 +0100
2cbb1c4b 22656+++ linux/fs/aufs/sysaufs.c 2011-07-11 11:34:24.077331673 +0200
4a4d8108 22657@@ -0,0 +1,107 @@
1facf9fc 22658+/*
027c5e7a 22659+ * Copyright (C) 2005-2011 Junjiro R. Okajima
1facf9fc 22660+ *
22661+ * This program, aufs is free software; you can redistribute it and/or modify
22662+ * it under the terms of the GNU General Public License as published by
22663+ * the Free Software Foundation; either version 2 of the License, or
22664+ * (at your option) any later version.
dece6358
AM
22665+ *
22666+ * This program is distributed in the hope that it will be useful,
22667+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
22668+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22669+ * GNU General Public License for more details.
22670+ *
22671+ * You should have received a copy of the GNU General Public License
22672+ * along with this program; if not, write to the Free Software
22673+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 22674+ */
22675+
22676+/*
22677+ * sysfs interface and lifetime management
22678+ * they are necessary regardless sysfs is disabled.
22679+ */
22680+
22681+#include <linux/fs.h>
22682+#include <linux/random.h>
22683+#include <linux/sysfs.h>
22684+#include "aufs.h"
22685+
22686+unsigned long sysaufs_si_mask;
e49829fe 22687+struct kset *sysaufs_kset;
1facf9fc 22688+
22689+#define AuSiAttr(_name) { \
22690+ .attr = { .name = __stringify(_name), .mode = 0444 }, \
22691+ .show = sysaufs_si_##_name, \
22692+}
22693+
22694+static struct sysaufs_si_attr sysaufs_si_attr_xi_path = AuSiAttr(xi_path);
22695+struct attribute *sysaufs_si_attrs[] = {
22696+ &sysaufs_si_attr_xi_path.attr,
22697+ NULL,
22698+};
22699+
4a4d8108 22700+static const struct sysfs_ops au_sbi_ops = {
1facf9fc 22701+ .show = sysaufs_si_show
22702+};
22703+
22704+static struct kobj_type au_sbi_ktype = {
22705+ .release = au_si_free,
22706+ .sysfs_ops = &au_sbi_ops,
22707+ .default_attrs = sysaufs_si_attrs
22708+};
22709+
22710+/* ---------------------------------------------------------------------- */
22711+
22712+int sysaufs_si_init(struct au_sbinfo *sbinfo)
22713+{
22714+ int err;
22715+
e49829fe 22716+ sbinfo->si_kobj.kset = sysaufs_kset;
1facf9fc 22717+ /* cf. sysaufs_name() */
22718+ err = kobject_init_and_add
e49829fe 22719+ (&sbinfo->si_kobj, &au_sbi_ktype, /*&sysaufs_kset->kobj*/NULL,
1facf9fc 22720+ SysaufsSiNamePrefix "%lx", sysaufs_si_id(sbinfo));
22721+
22722+ dbgaufs_si_null(sbinfo);
22723+ if (!err) {
22724+ err = dbgaufs_si_init(sbinfo);
22725+ if (unlikely(err))
22726+ kobject_put(&sbinfo->si_kobj);
22727+ }
22728+ return err;
22729+}
22730+
22731+void sysaufs_fin(void)
22732+{
22733+ dbgaufs_fin();
e49829fe
JR
22734+ sysfs_remove_group(&sysaufs_kset->kobj, sysaufs_attr_group);
22735+ kset_unregister(sysaufs_kset);
1facf9fc 22736+}
22737+
22738+int __init sysaufs_init(void)
22739+{
22740+ int err;
22741+
22742+ do {
22743+ get_random_bytes(&sysaufs_si_mask, sizeof(sysaufs_si_mask));
22744+ } while (!sysaufs_si_mask);
22745+
4a4d8108 22746+ err = -EINVAL;
e49829fe
JR
22747+ sysaufs_kset = kset_create_and_add(AUFS_NAME, NULL, fs_kobj);
22748+ if (unlikely(!sysaufs_kset))
4a4d8108 22749+ goto out;
e49829fe
JR
22750+ err = PTR_ERR(sysaufs_kset);
22751+ if (IS_ERR(sysaufs_kset))
1facf9fc 22752+ goto out;
e49829fe 22753+ err = sysfs_create_group(&sysaufs_kset->kobj, sysaufs_attr_group);
1facf9fc 22754+ if (unlikely(err)) {
e49829fe 22755+ kset_unregister(sysaufs_kset);
1facf9fc 22756+ goto out;
22757+ }
22758+
22759+ err = dbgaufs_init();
22760+ if (unlikely(err))
22761+ sysaufs_fin();
4f0767ce 22762+out:
1facf9fc 22763+ return err;
22764+}
7f207e10
AM
22765diff -urN /usr/share/empty/fs/aufs/sysaufs.h linux/fs/aufs/sysaufs.h
22766--- /usr/share/empty/fs/aufs/sysaufs.h 1970-01-01 01:00:00.000000000 +0100
2cbb1c4b 22767+++ linux/fs/aufs/sysaufs.h 2011-07-11 11:34:24.077331673 +0200
4a4d8108 22768@@ -0,0 +1,105 @@
1facf9fc 22769+/*
027c5e7a 22770+ * Copyright (C) 2005-2011 Junjiro R. Okajima
1facf9fc 22771+ *
22772+ * This program, aufs is free software; you can redistribute it and/or modify
22773+ * it under the terms of the GNU General Public License as published by
22774+ * the Free Software Foundation; either version 2 of the License, or
22775+ * (at your option) any later version.
dece6358
AM
22776+ *
22777+ * This program is distributed in the hope that it will be useful,
22778+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
22779+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22780+ * GNU General Public License for more details.
22781+ *
22782+ * You should have received a copy of the GNU General Public License
22783+ * along with this program; if not, write to the Free Software
22784+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 22785+ */
22786+
22787+/*
22788+ * sysfs interface and mount lifetime management
22789+ */
22790+
22791+#ifndef __SYSAUFS_H__
22792+#define __SYSAUFS_H__
22793+
22794+#ifdef __KERNEL__
22795+
1facf9fc 22796+#include <linux/sysfs.h>
22797+#include <linux/aufs_type.h>
22798+#include "module.h"
22799+
dece6358
AM
22800+struct super_block;
22801+struct au_sbinfo;
22802+
1facf9fc 22803+struct sysaufs_si_attr {
22804+ struct attribute attr;
22805+ int (*show)(struct seq_file *seq, struct super_block *sb);
22806+};
22807+
22808+/* ---------------------------------------------------------------------- */
22809+
22810+/* sysaufs.c */
22811+extern unsigned long sysaufs_si_mask;
e49829fe 22812+extern struct kset *sysaufs_kset;
1facf9fc 22813+extern struct attribute *sysaufs_si_attrs[];
22814+int sysaufs_si_init(struct au_sbinfo *sbinfo);
22815+int __init sysaufs_init(void);
22816+void sysaufs_fin(void);
22817+
22818+/* ---------------------------------------------------------------------- */
22819+
22820+/* some people doesn't like to show a pointer in kernel */
22821+static inline unsigned long sysaufs_si_id(struct au_sbinfo *sbinfo)
22822+{
22823+ return sysaufs_si_mask ^ (unsigned long)sbinfo;
22824+}
22825+
22826+#define SysaufsSiNamePrefix "si_"
22827+#define SysaufsSiNameLen (sizeof(SysaufsSiNamePrefix) + 16)
22828+static inline void sysaufs_name(struct au_sbinfo *sbinfo, char *name)
22829+{
22830+ snprintf(name, SysaufsSiNameLen, SysaufsSiNamePrefix "%lx",
22831+ sysaufs_si_id(sbinfo));
22832+}
22833+
22834+struct au_branch;
22835+#ifdef CONFIG_SYSFS
22836+/* sysfs.c */
22837+extern struct attribute_group *sysaufs_attr_group;
22838+
22839+int sysaufs_si_xi_path(struct seq_file *seq, struct super_block *sb);
22840+ssize_t sysaufs_si_show(struct kobject *kobj, struct attribute *attr,
22841+ char *buf);
22842+
22843+void sysaufs_br_init(struct au_branch *br);
22844+void sysaufs_brs_add(struct super_block *sb, aufs_bindex_t bindex);
22845+void sysaufs_brs_del(struct super_block *sb, aufs_bindex_t bindex);
22846+
22847+#define sysaufs_brs_init() do {} while (0)
22848+
22849+#else
22850+#define sysaufs_attr_group NULL
22851+
4a4d8108 22852+AuStubInt0(sysaufs_si_xi_path, struct seq_file *seq, struct super_block *sb)
1facf9fc 22853+
22854+static inline
22855+ssize_t sysaufs_si_show(struct kobject *kobj, struct attribute *attr,
22856+ char *buf)
22857+{
22858+ return 0;
22859+}
22860+
4a4d8108
AM
22861+AuStubVoid(sysaufs_br_init, struct au_branch *br)
22862+AuStubVoid(sysaufs_brs_add, struct super_block *sb, aufs_bindex_t bindex)
22863+AuStubVoid(sysaufs_brs_del, struct super_block *sb, aufs_bindex_t bindex)
1facf9fc 22864+
22865+static inline void sysaufs_brs_init(void)
22866+{
22867+ sysaufs_brs = 0;
22868+}
22869+
22870+#endif /* CONFIG_SYSFS */
22871+
22872+#endif /* __KERNEL__ */
22873+#endif /* __SYSAUFS_H__ */
7f207e10
AM
22874diff -urN /usr/share/empty/fs/aufs/sysfs.c linux/fs/aufs/sysfs.c
22875--- /usr/share/empty/fs/aufs/sysfs.c 1970-01-01 01:00:00.000000000 +0100
2cbb1c4b 22876+++ linux/fs/aufs/sysfs.c 2011-07-11 11:34:24.077331673 +0200
953406b4 22877@@ -0,0 +1,250 @@
1facf9fc 22878+/*
027c5e7a 22879+ * Copyright (C) 2005-2011 Junjiro R. Okajima
1facf9fc 22880+ *
22881+ * This program, aufs is free software; you can redistribute it and/or modify
22882+ * it under the terms of the GNU General Public License as published by
22883+ * the Free Software Foundation; either version 2 of the License, or
22884+ * (at your option) any later version.
dece6358
AM
22885+ *
22886+ * This program is distributed in the hope that it will be useful,
22887+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
22888+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22889+ * GNU General Public License for more details.
22890+ *
22891+ * You should have received a copy of the GNU General Public License
22892+ * along with this program; if not, write to the Free Software
22893+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 22894+ */
22895+
22896+/*
22897+ * sysfs interface
22898+ */
22899+
22900+#include <linux/fs.h>
dece6358 22901+#include <linux/module.h>
1facf9fc 22902+#include <linux/seq_file.h>
22903+#include <linux/sysfs.h>
22904+#include "aufs.h"
22905+
4a4d8108
AM
22906+#ifdef CONFIG_AUFS_FS_MODULE
22907+/* this entry violates the "one line per file" policy of sysfs */
22908+static ssize_t config_show(struct kobject *kobj, struct kobj_attribute *attr,
22909+ char *buf)
22910+{
22911+ ssize_t err;
22912+ static char *conf =
22913+/* this file is generated at compiling */
22914+#include "conf.str"
22915+ ;
22916+
22917+ err = snprintf(buf, PAGE_SIZE, conf);
22918+ if (unlikely(err >= PAGE_SIZE))
22919+ err = -EFBIG;
22920+ return err;
22921+}
22922+
22923+static struct kobj_attribute au_config_attr = __ATTR_RO(config);
22924+#endif
22925+
1facf9fc 22926+static struct attribute *au_attr[] = {
4a4d8108
AM
22927+#ifdef CONFIG_AUFS_FS_MODULE
22928+ &au_config_attr.attr,
22929+#endif
1facf9fc 22930+ NULL, /* need to NULL terminate the list of attributes */
22931+};
22932+
22933+static struct attribute_group sysaufs_attr_group_body = {
22934+ .attrs = au_attr
22935+};
22936+
22937+struct attribute_group *sysaufs_attr_group = &sysaufs_attr_group_body;
22938+
22939+/* ---------------------------------------------------------------------- */
22940+
22941+int sysaufs_si_xi_path(struct seq_file *seq, struct super_block *sb)
22942+{
22943+ int err;
22944+
dece6358
AM
22945+ SiMustAnyLock(sb);
22946+
1facf9fc 22947+ err = 0;
22948+ if (au_opt_test(au_mntflags(sb), XINO)) {
22949+ err = au_xino_path(seq, au_sbi(sb)->si_xib);
22950+ seq_putc(seq, '\n');
22951+ }
22952+ return err;
22953+}
22954+
22955+/*
22956+ * the lifetime of branch is independent from the entry under sysfs.
22957+ * sysfs handles the lifetime of the entry, and never call ->show() after it is
22958+ * unlinked.
22959+ */
22960+static int sysaufs_si_br(struct seq_file *seq, struct super_block *sb,
22961+ aufs_bindex_t bindex)
22962+{
22963+ struct path path;
22964+ struct dentry *root;
22965+ struct au_branch *br;
22966+
22967+ AuDbg("b%d\n", bindex);
22968+
22969+ root = sb->s_root;
22970+ di_read_lock_parent(root, !AuLock_IR);
22971+ br = au_sbr(sb, bindex);
22972+ path.mnt = br->br_mnt;
22973+ path.dentry = au_h_dptr(root, bindex);
22974+ au_seq_path(seq, &path);
22975+ di_read_unlock(root, !AuLock_IR);
22976+ seq_printf(seq, "=%s\n", au_optstr_br_perm(br->br_perm));
22977+ return 0;
22978+}
22979+
22980+/* ---------------------------------------------------------------------- */
22981+
22982+static struct seq_file *au_seq(char *p, ssize_t len)
22983+{
22984+ struct seq_file *seq;
22985+
22986+ seq = kzalloc(sizeof(*seq), GFP_NOFS);
22987+ if (seq) {
22988+ /* mutex_init(&seq.lock); */
22989+ seq->buf = p;
22990+ seq->size = len;
22991+ return seq; /* success */
22992+ }
22993+
22994+ seq = ERR_PTR(-ENOMEM);
22995+ return seq;
22996+}
22997+
22998+#define SysaufsBr_PREFIX "br"
22999+
23000+/* todo: file size may exceed PAGE_SIZE */
23001+ssize_t sysaufs_si_show(struct kobject *kobj, struct attribute *attr,
1308ab2a 23002+ char *buf)
1facf9fc 23003+{
23004+ ssize_t err;
23005+ long l;
23006+ aufs_bindex_t bend;
23007+ struct au_sbinfo *sbinfo;
23008+ struct super_block *sb;
23009+ struct seq_file *seq;
23010+ char *name;
23011+ struct attribute **cattr;
23012+
23013+ sbinfo = container_of(kobj, struct au_sbinfo, si_kobj);
23014+ sb = sbinfo->si_sb;
1308ab2a 23015+
23016+ /*
23017+ * prevent a race condition between sysfs and aufs.
23018+ * for instance, sysfs_file_read() calls sysfs_get_active_two() which
23019+ * prohibits maintaining the sysfs entries.
23020+ * hew we acquire read lock after sysfs_get_active_two().
23021+ * on the other hand, the remount process may maintain the sysfs/aufs
23022+ * entries after acquiring write lock.
23023+ * it can cause a deadlock.
23024+ * simply we gave up processing read here.
23025+ */
23026+ err = -EBUSY;
23027+ if (unlikely(!si_noflush_read_trylock(sb)))
23028+ goto out;
1facf9fc 23029+
23030+ seq = au_seq(buf, PAGE_SIZE);
23031+ err = PTR_ERR(seq);
23032+ if (IS_ERR(seq))
1308ab2a 23033+ goto out_unlock;
1facf9fc 23034+
23035+ name = (void *)attr->name;
23036+ cattr = sysaufs_si_attrs;
23037+ while (*cattr) {
23038+ if (!strcmp(name, (*cattr)->name)) {
23039+ err = container_of(*cattr, struct sysaufs_si_attr, attr)
23040+ ->show(seq, sb);
23041+ goto out_seq;
23042+ }
23043+ cattr++;
23044+ }
23045+
23046+ bend = au_sbend(sb);
23047+ if (!strncmp(name, SysaufsBr_PREFIX, sizeof(SysaufsBr_PREFIX) - 1)) {
23048+ name += sizeof(SysaufsBr_PREFIX) - 1;
23049+ err = strict_strtol(name, 10, &l);
23050+ if (!err) {
23051+ if (l <= bend)
23052+ err = sysaufs_si_br(seq, sb, (aufs_bindex_t)l);
23053+ else
23054+ err = -ENOENT;
23055+ }
23056+ goto out_seq;
23057+ }
23058+ BUG();
23059+
4f0767ce 23060+out_seq:
1facf9fc 23061+ if (!err) {
23062+ err = seq->count;
23063+ /* sysfs limit */
23064+ if (unlikely(err == PAGE_SIZE))
23065+ err = -EFBIG;
23066+ }
23067+ kfree(seq);
4f0767ce 23068+out_unlock:
1facf9fc 23069+ si_read_unlock(sb);
4f0767ce 23070+out:
1facf9fc 23071+ return err;
23072+}
23073+
23074+/* ---------------------------------------------------------------------- */
23075+
23076+void sysaufs_br_init(struct au_branch *br)
23077+{
4a4d8108
AM
23078+ struct attribute *attr = &br->br_attr;
23079+
23080+ sysfs_attr_init(attr);
23081+ attr->name = br->br_name;
23082+ attr->mode = S_IRUGO;
1facf9fc 23083+}
23084+
23085+void sysaufs_brs_del(struct super_block *sb, aufs_bindex_t bindex)
23086+{
23087+ struct au_branch *br;
23088+ struct kobject *kobj;
23089+ aufs_bindex_t bend;
23090+
23091+ dbgaufs_brs_del(sb, bindex);
23092+
23093+ if (!sysaufs_brs)
23094+ return;
23095+
23096+ kobj = &au_sbi(sb)->si_kobj;
23097+ bend = au_sbend(sb);
23098+ for (; bindex <= bend; bindex++) {
23099+ br = au_sbr(sb, bindex);
23100+ sysfs_remove_file(kobj, &br->br_attr);
23101+ }
23102+}
23103+
23104+void sysaufs_brs_add(struct super_block *sb, aufs_bindex_t bindex)
23105+{
23106+ int err;
23107+ aufs_bindex_t bend;
23108+ struct kobject *kobj;
23109+ struct au_branch *br;
23110+
23111+ dbgaufs_brs_add(sb, bindex);
23112+
23113+ if (!sysaufs_brs)
23114+ return;
23115+
23116+ kobj = &au_sbi(sb)->si_kobj;
23117+ bend = au_sbend(sb);
23118+ for (; bindex <= bend; bindex++) {
23119+ br = au_sbr(sb, bindex);
23120+ snprintf(br->br_name, sizeof(br->br_name), SysaufsBr_PREFIX
23121+ "%d", bindex);
23122+ err = sysfs_create_file(kobj, &br->br_attr);
23123+ if (unlikely(err))
4a4d8108
AM
23124+ pr_warning("failed %s under sysfs(%d)\n",
23125+ br->br_name, err);
1facf9fc 23126+ }
23127+}
7f207e10
AM
23128diff -urN /usr/share/empty/fs/aufs/sysrq.c linux/fs/aufs/sysrq.c
23129--- /usr/share/empty/fs/aufs/sysrq.c 1970-01-01 01:00:00.000000000 +0100
2cbb1c4b
JR
23130+++ linux/fs/aufs/sysrq.c 2011-07-11 11:34:24.078331673 +0200
23131@@ -0,0 +1,151 @@
1facf9fc 23132+/*
027c5e7a 23133+ * Copyright (C) 2005-2011 Junjiro R. Okajima
1facf9fc 23134+ *
23135+ * This program, aufs is free software; you can redistribute it and/or modify
23136+ * it under the terms of the GNU General Public License as published by
23137+ * the Free Software Foundation; either version 2 of the License, or
23138+ * (at your option) any later version.
dece6358
AM
23139+ *
23140+ * This program is distributed in the hope that it will be useful,
23141+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
23142+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23143+ * GNU General Public License for more details.
23144+ *
23145+ * You should have received a copy of the GNU General Public License
23146+ * along with this program; if not, write to the Free Software
23147+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 23148+ */
23149+
23150+/*
23151+ * magic sysrq hanlder
23152+ */
23153+
23154+#include <linux/fs.h>
23155+#include <linux/module.h>
23156+#include <linux/moduleparam.h>
23157+/* #include <linux/sysrq.h> */
027c5e7a 23158+#include <linux/writeback.h>
1facf9fc 23159+#include "aufs.h"
23160+
23161+/* ---------------------------------------------------------------------- */
23162+
23163+static void sysrq_sb(struct super_block *sb)
23164+{
23165+ char *plevel;
23166+ struct au_sbinfo *sbinfo;
23167+ struct file *file;
23168+
23169+ plevel = au_plevel;
23170+ au_plevel = KERN_WARNING;
1facf9fc 23171+
23172+ sbinfo = au_sbi(sb);
4a4d8108
AM
23173+ /* since we define pr_fmt, call printk directly */
23174+ printk(KERN_WARNING "si=%lx\n", sysaufs_si_id(sbinfo));
23175+ printk(KERN_WARNING AUFS_NAME ": superblock\n");
1facf9fc 23176+ au_dpri_sb(sb);
027c5e7a
AM
23177+
23178+#if 0
4a4d8108 23179+ printk(KERN_WARNING AUFS_NAME ": root dentry\n");
1facf9fc 23180+ au_dpri_dentry(sb->s_root);
4a4d8108 23181+ printk(KERN_WARNING AUFS_NAME ": root inode\n");
1facf9fc 23182+ au_dpri_inode(sb->s_root->d_inode);
027c5e7a
AM
23183+#endif
23184+
1facf9fc 23185+#if 0
027c5e7a
AM
23186+ do {
23187+ int err, i, j, ndentry;
23188+ struct au_dcsub_pages dpages;
23189+ struct au_dpage *dpage;
23190+
23191+ err = au_dpages_init(&dpages, GFP_ATOMIC);
23192+ if (unlikely(err))
23193+ break;
23194+ err = au_dcsub_pages(&dpages, sb->s_root, NULL, NULL);
23195+ if (!err)
23196+ for (i = 0; i < dpages.ndpage; i++) {
23197+ dpage = dpages.dpages + i;
23198+ ndentry = dpage->ndentry;
23199+ for (j = 0; j < ndentry; j++)
23200+ au_dpri_dentry(dpage->dentries[j]);
23201+ }
23202+ au_dpages_free(&dpages);
23203+ } while (0);
23204+#endif
23205+
23206+#if 1
23207+ {
23208+ struct inode *i;
23209+ printk(KERN_WARNING AUFS_NAME ": isolated inode\n");
2cbb1c4b
JR
23210+ spin_lock(&inode_sb_list_lock);
23211+ list_for_each_entry(i, &sb->s_inodes, i_sb_list) {
23212+ spin_lock(&i->i_lock);
027c5e7a
AM
23213+ if (1 || list_empty(&i->i_dentry))
23214+ au_dpri_inode(i);
2cbb1c4b
JR
23215+ spin_unlock(&i->i_lock);
23216+ }
23217+ spin_unlock(&inode_sb_list_lock);
027c5e7a 23218+ }
1facf9fc 23219+#endif
4a4d8108 23220+ printk(KERN_WARNING AUFS_NAME ": files\n");
0c5527e5
AM
23221+ lg_global_lock(files_lglock);
23222+ do_file_list_for_each_entry(sb, file) {
4a4d8108
AM
23223+ umode_t mode;
23224+ mode = file->f_dentry->d_inode->i_mode;
23225+ if (!special_file(mode) || au_special_file(mode))
1facf9fc 23226+ au_dpri_file(file);
0c5527e5
AM
23227+ } while_file_list_for_each_entry;
23228+ lg_global_unlock(files_lglock);
e49829fe 23229+ printk(KERN_WARNING AUFS_NAME ": done\n");
1facf9fc 23230+
23231+ au_plevel = plevel;
1facf9fc 23232+}
23233+
23234+/* ---------------------------------------------------------------------- */
23235+
23236+/* module parameter */
23237+static char *aufs_sysrq_key = "a";
23238+module_param_named(sysrq, aufs_sysrq_key, charp, S_IRUGO);
23239+MODULE_PARM_DESC(sysrq, "MagicSysRq key for " AUFS_NAME);
23240+
0c5527e5 23241+static void au_sysrq(int key __maybe_unused)
1facf9fc 23242+{
1facf9fc 23243+ struct au_sbinfo *sbinfo;
23244+
027c5e7a 23245+ lockdep_off();
e49829fe
JR
23246+ spin_lock(&au_sbilist.spin);
23247+ list_for_each_entry(sbinfo, &au_sbilist.head, si_list)
1facf9fc 23248+ sysrq_sb(sbinfo->si_sb);
e49829fe 23249+ spin_unlock(&au_sbilist.spin);
027c5e7a 23250+ lockdep_on();
1facf9fc 23251+}
23252+
23253+static struct sysrq_key_op au_sysrq_op = {
23254+ .handler = au_sysrq,
23255+ .help_msg = "Aufs",
23256+ .action_msg = "Aufs",
23257+ .enable_mask = SYSRQ_ENABLE_DUMP
23258+};
23259+
23260+/* ---------------------------------------------------------------------- */
23261+
23262+int __init au_sysrq_init(void)
23263+{
23264+ int err;
23265+ char key;
23266+
23267+ err = -1;
23268+ key = *aufs_sysrq_key;
23269+ if ('a' <= key && key <= 'z')
23270+ err = register_sysrq_key(key, &au_sysrq_op);
23271+ if (unlikely(err))
4a4d8108 23272+ pr_err("err %d, sysrq=%c\n", err, key);
1facf9fc 23273+ return err;
23274+}
23275+
23276+void au_sysrq_fin(void)
23277+{
23278+ int err;
23279+ err = unregister_sysrq_key(*aufs_sysrq_key, &au_sysrq_op);
23280+ if (unlikely(err))
4a4d8108 23281+ pr_err("err %d (ignored)\n", err);
1facf9fc 23282+}
7f207e10
AM
23283diff -urN /usr/share/empty/fs/aufs/vdir.c linux/fs/aufs/vdir.c
23284--- /usr/share/empty/fs/aufs/vdir.c 1970-01-01 01:00:00.000000000 +0100
2cbb1c4b 23285+++ linux/fs/aufs/vdir.c 2011-07-11 11:34:24.078331673 +0200
7f207e10 23286@@ -0,0 +1,886 @@
1facf9fc 23287+/*
027c5e7a 23288+ * Copyright (C) 2005-2011 Junjiro R. Okajima
1facf9fc 23289+ *
23290+ * This program, aufs is free software; you can redistribute it and/or modify
23291+ * it under the terms of the GNU General Public License as published by
23292+ * the Free Software Foundation; either version 2 of the License, or
23293+ * (at your option) any later version.
dece6358
AM
23294+ *
23295+ * This program is distributed in the hope that it will be useful,
23296+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
23297+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23298+ * GNU General Public License for more details.
23299+ *
23300+ * You should have received a copy of the GNU General Public License
23301+ * along with this program; if not, write to the Free Software
23302+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 23303+ */
23304+
23305+/*
23306+ * virtual or vertical directory
23307+ */
23308+
dece6358 23309+#include <linux/hash.h>
1facf9fc 23310+#include "aufs.h"
23311+
dece6358 23312+static unsigned int calc_size(int nlen)
1facf9fc 23313+{
dece6358 23314+ return ALIGN(sizeof(struct au_vdir_de) + nlen, sizeof(ino_t));
1facf9fc 23315+}
23316+
23317+static int set_deblk_end(union au_vdir_deblk_p *p,
23318+ union au_vdir_deblk_p *deblk_end)
23319+{
23320+ if (calc_size(0) <= deblk_end->deblk - p->deblk) {
23321+ p->de->de_str.len = 0;
23322+ /* smp_mb(); */
23323+ return 0;
23324+ }
23325+ return -1; /* error */
23326+}
23327+
23328+/* returns true or false */
23329+static int is_deblk_end(union au_vdir_deblk_p *p,
23330+ union au_vdir_deblk_p *deblk_end)
23331+{
23332+ if (calc_size(0) <= deblk_end->deblk - p->deblk)
23333+ return !p->de->de_str.len;
23334+ return 1;
23335+}
23336+
23337+static unsigned char *last_deblk(struct au_vdir *vdir)
23338+{
23339+ return vdir->vd_deblk[vdir->vd_nblk - 1];
23340+}
23341+
23342+/* ---------------------------------------------------------------------- */
23343+
1308ab2a 23344+/* estimate the apropriate size for name hash table */
23345+unsigned int au_rdhash_est(loff_t sz)
23346+{
23347+ unsigned int n;
23348+
23349+ n = UINT_MAX;
23350+ sz >>= 10;
23351+ if (sz < n)
23352+ n = sz;
23353+ if (sz < AUFS_RDHASH_DEF)
23354+ n = AUFS_RDHASH_DEF;
4a4d8108 23355+ /* pr_info("n %u\n", n); */
1308ab2a 23356+ return n;
23357+}
23358+
1facf9fc 23359+/*
23360+ * the allocated memory has to be freed by
dece6358 23361+ * au_nhash_wh_free() or au_nhash_de_free().
1facf9fc 23362+ */
dece6358 23363+int au_nhash_alloc(struct au_nhash *nhash, unsigned int num_hash, gfp_t gfp)
1facf9fc 23364+{
1facf9fc 23365+ struct hlist_head *head;
dece6358 23366+ unsigned int u;
1facf9fc 23367+
dece6358
AM
23368+ head = kmalloc(sizeof(*nhash->nh_head) * num_hash, gfp);
23369+ if (head) {
23370+ nhash->nh_num = num_hash;
23371+ nhash->nh_head = head;
23372+ for (u = 0; u < num_hash; u++)
1facf9fc 23373+ INIT_HLIST_HEAD(head++);
dece6358 23374+ return 0; /* success */
1facf9fc 23375+ }
1facf9fc 23376+
dece6358 23377+ return -ENOMEM;
1facf9fc 23378+}
23379+
dece6358
AM
23380+static void nhash_count(struct hlist_head *head)
23381+{
23382+#if 0
23383+ unsigned long n;
23384+ struct hlist_node *pos;
23385+
23386+ n = 0;
23387+ hlist_for_each(pos, head)
23388+ n++;
4a4d8108 23389+ pr_info("%lu\n", n);
dece6358
AM
23390+#endif
23391+}
23392+
23393+static void au_nhash_wh_do_free(struct hlist_head *head)
1facf9fc 23394+{
1facf9fc 23395+ struct au_vdir_wh *tpos;
23396+ struct hlist_node *pos, *node;
23397+
dece6358
AM
23398+ hlist_for_each_entry_safe(tpos, pos, node, head, wh_hash) {
23399+ /* hlist_del(pos); */
23400+ kfree(tpos);
1facf9fc 23401+ }
23402+}
23403+
dece6358 23404+static void au_nhash_de_do_free(struct hlist_head *head)
1facf9fc 23405+{
dece6358
AM
23406+ struct au_vdir_dehstr *tpos;
23407+ struct hlist_node *pos, *node;
1facf9fc 23408+
dece6358
AM
23409+ hlist_for_each_entry_safe(tpos, pos, node, head, hash) {
23410+ /* hlist_del(pos); */
4a4d8108 23411+ au_cache_free_vdir_dehstr(tpos);
1facf9fc 23412+ }
1facf9fc 23413+}
23414+
dece6358
AM
23415+static void au_nhash_do_free(struct au_nhash *nhash,
23416+ void (*free)(struct hlist_head *head))
1facf9fc 23417+{
1308ab2a 23418+ unsigned int n;
1facf9fc 23419+ struct hlist_head *head;
1facf9fc 23420+
dece6358 23421+ n = nhash->nh_num;
1308ab2a 23422+ if (!n)
23423+ return;
23424+
dece6358 23425+ head = nhash->nh_head;
1308ab2a 23426+ while (n-- > 0) {
dece6358
AM
23427+ nhash_count(head);
23428+ free(head++);
1facf9fc 23429+ }
dece6358 23430+ kfree(nhash->nh_head);
1facf9fc 23431+}
23432+
dece6358 23433+void au_nhash_wh_free(struct au_nhash *whlist)
1facf9fc 23434+{
dece6358
AM
23435+ au_nhash_do_free(whlist, au_nhash_wh_do_free);
23436+}
1facf9fc 23437+
dece6358
AM
23438+static void au_nhash_de_free(struct au_nhash *delist)
23439+{
23440+ au_nhash_do_free(delist, au_nhash_de_do_free);
1facf9fc 23441+}
23442+
23443+/* ---------------------------------------------------------------------- */
23444+
23445+int au_nhash_test_longer_wh(struct au_nhash *whlist, aufs_bindex_t btgt,
23446+ int limit)
23447+{
23448+ int num;
23449+ unsigned int u, n;
23450+ struct hlist_head *head;
23451+ struct au_vdir_wh *tpos;
23452+ struct hlist_node *pos;
23453+
23454+ num = 0;
23455+ n = whlist->nh_num;
23456+ head = whlist->nh_head;
1308ab2a 23457+ for (u = 0; u < n; u++, head++)
1facf9fc 23458+ hlist_for_each_entry(tpos, pos, head, wh_hash)
23459+ if (tpos->wh_bindex == btgt && ++num > limit)
23460+ return 1;
1facf9fc 23461+ return 0;
23462+}
23463+
23464+static struct hlist_head *au_name_hash(struct au_nhash *nhash,
dece6358 23465+ unsigned char *name,
1facf9fc 23466+ unsigned int len)
23467+{
dece6358
AM
23468+ unsigned int v;
23469+ /* const unsigned int magic_bit = 12; */
23470+
1308ab2a 23471+ AuDebugOn(!nhash->nh_num || !nhash->nh_head);
23472+
dece6358
AM
23473+ v = 0;
23474+ while (len--)
23475+ v += *name++;
23476+ /* v = hash_long(v, magic_bit); */
23477+ v %= nhash->nh_num;
23478+ return nhash->nh_head + v;
23479+}
23480+
23481+static int au_nhash_test_name(struct au_vdir_destr *str, const char *name,
23482+ int nlen)
23483+{
23484+ return str->len == nlen && !memcmp(str->name, name, nlen);
1facf9fc 23485+}
23486+
23487+/* returns found or not */
dece6358 23488+int au_nhash_test_known_wh(struct au_nhash *whlist, char *name, int nlen)
1facf9fc 23489+{
23490+ struct hlist_head *head;
23491+ struct au_vdir_wh *tpos;
23492+ struct hlist_node *pos;
23493+ struct au_vdir_destr *str;
23494+
dece6358 23495+ head = au_name_hash(whlist, name, nlen);
1facf9fc 23496+ hlist_for_each_entry(tpos, pos, head, wh_hash) {
23497+ str = &tpos->wh_str;
23498+ AuDbg("%.*s\n", str->len, str->name);
dece6358
AM
23499+ if (au_nhash_test_name(str, name, nlen))
23500+ return 1;
23501+ }
23502+ return 0;
23503+}
23504+
23505+/* returns found(true) or not */
23506+static int test_known(struct au_nhash *delist, char *name, int nlen)
23507+{
23508+ struct hlist_head *head;
23509+ struct au_vdir_dehstr *tpos;
23510+ struct hlist_node *pos;
23511+ struct au_vdir_destr *str;
23512+
23513+ head = au_name_hash(delist, name, nlen);
23514+ hlist_for_each_entry(tpos, pos, head, hash) {
23515+ str = tpos->str;
23516+ AuDbg("%.*s\n", str->len, str->name);
23517+ if (au_nhash_test_name(str, name, nlen))
1facf9fc 23518+ return 1;
23519+ }
23520+ return 0;
23521+}
23522+
dece6358
AM
23523+static void au_shwh_init_wh(struct au_vdir_wh *wh, ino_t ino,
23524+ unsigned char d_type)
23525+{
23526+#ifdef CONFIG_AUFS_SHWH
23527+ wh->wh_ino = ino;
23528+ wh->wh_type = d_type;
23529+#endif
23530+}
23531+
23532+/* ---------------------------------------------------------------------- */
23533+
23534+int au_nhash_append_wh(struct au_nhash *whlist, char *name, int nlen, ino_t ino,
23535+ unsigned int d_type, aufs_bindex_t bindex,
23536+ unsigned char shwh)
1facf9fc 23537+{
23538+ int err;
23539+ struct au_vdir_destr *str;
23540+ struct au_vdir_wh *wh;
23541+
dece6358 23542+ AuDbg("%.*s\n", nlen, name);
1308ab2a 23543+ AuDebugOn(!whlist->nh_num || !whlist->nh_head);
23544+
1facf9fc 23545+ err = -ENOMEM;
dece6358 23546+ wh = kmalloc(sizeof(*wh) + nlen, GFP_NOFS);
1facf9fc 23547+ if (unlikely(!wh))
23548+ goto out;
23549+
23550+ err = 0;
23551+ wh->wh_bindex = bindex;
dece6358
AM
23552+ if (shwh)
23553+ au_shwh_init_wh(wh, ino, d_type);
1facf9fc 23554+ str = &wh->wh_str;
dece6358
AM
23555+ str->len = nlen;
23556+ memcpy(str->name, name, nlen);
23557+ hlist_add_head(&wh->wh_hash, au_name_hash(whlist, name, nlen));
1facf9fc 23558+ /* smp_mb(); */
23559+
4f0767ce 23560+out:
1facf9fc 23561+ return err;
23562+}
23563+
1facf9fc 23564+static int append_deblk(struct au_vdir *vdir)
23565+{
23566+ int err;
dece6358 23567+ unsigned long ul;
1facf9fc 23568+ const unsigned int deblk_sz = vdir->vd_deblk_sz;
23569+ union au_vdir_deblk_p p, deblk_end;
23570+ unsigned char **o;
23571+
23572+ err = -ENOMEM;
dece6358
AM
23573+ o = krealloc(vdir->vd_deblk, sizeof(*o) * (vdir->vd_nblk + 1),
23574+ GFP_NOFS);
1facf9fc 23575+ if (unlikely(!o))
23576+ goto out;
23577+
23578+ vdir->vd_deblk = o;
23579+ p.deblk = kmalloc(deblk_sz, GFP_NOFS);
23580+ if (p.deblk) {
23581+ ul = vdir->vd_nblk++;
23582+ vdir->vd_deblk[ul] = p.deblk;
23583+ vdir->vd_last.ul = ul;
23584+ vdir->vd_last.p.deblk = p.deblk;
23585+ deblk_end.deblk = p.deblk + deblk_sz;
23586+ err = set_deblk_end(&p, &deblk_end);
23587+ }
23588+
4f0767ce 23589+out:
1facf9fc 23590+ return err;
23591+}
23592+
dece6358
AM
23593+static int append_de(struct au_vdir *vdir, char *name, int nlen, ino_t ino,
23594+ unsigned int d_type, struct au_nhash *delist)
23595+{
23596+ int err;
23597+ unsigned int sz;
23598+ const unsigned int deblk_sz = vdir->vd_deblk_sz;
23599+ union au_vdir_deblk_p p, *room, deblk_end;
23600+ struct au_vdir_dehstr *dehstr;
23601+
23602+ p.deblk = last_deblk(vdir);
23603+ deblk_end.deblk = p.deblk + deblk_sz;
23604+ room = &vdir->vd_last.p;
23605+ AuDebugOn(room->deblk < p.deblk || deblk_end.deblk <= room->deblk
23606+ || !is_deblk_end(room, &deblk_end));
23607+
23608+ sz = calc_size(nlen);
23609+ if (unlikely(sz > deblk_end.deblk - room->deblk)) {
23610+ err = append_deblk(vdir);
23611+ if (unlikely(err))
23612+ goto out;
23613+
23614+ p.deblk = last_deblk(vdir);
23615+ deblk_end.deblk = p.deblk + deblk_sz;
23616+ /* smp_mb(); */
23617+ AuDebugOn(room->deblk != p.deblk);
23618+ }
23619+
23620+ err = -ENOMEM;
4a4d8108 23621+ dehstr = au_cache_alloc_vdir_dehstr();
dece6358
AM
23622+ if (unlikely(!dehstr))
23623+ goto out;
23624+
23625+ dehstr->str = &room->de->de_str;
23626+ hlist_add_head(&dehstr->hash, au_name_hash(delist, name, nlen));
23627+ room->de->de_ino = ino;
23628+ room->de->de_type = d_type;
23629+ room->de->de_str.len = nlen;
23630+ memcpy(room->de->de_str.name, name, nlen);
23631+
23632+ err = 0;
23633+ room->deblk += sz;
23634+ if (unlikely(set_deblk_end(room, &deblk_end)))
23635+ err = append_deblk(vdir);
23636+ /* smp_mb(); */
23637+
4f0767ce 23638+out:
dece6358
AM
23639+ return err;
23640+}
23641+
23642+/* ---------------------------------------------------------------------- */
23643+
23644+void au_vdir_free(struct au_vdir *vdir)
23645+{
23646+ unsigned char **deblk;
23647+
23648+ deblk = vdir->vd_deblk;
23649+ while (vdir->vd_nblk--)
23650+ kfree(*deblk++);
23651+ kfree(vdir->vd_deblk);
23652+ au_cache_free_vdir(vdir);
23653+}
23654+
1308ab2a 23655+static struct au_vdir *alloc_vdir(struct file *file)
1facf9fc 23656+{
23657+ struct au_vdir *vdir;
1308ab2a 23658+ struct super_block *sb;
1facf9fc 23659+ int err;
23660+
1308ab2a 23661+ sb = file->f_dentry->d_sb;
dece6358
AM
23662+ SiMustAnyLock(sb);
23663+
1facf9fc 23664+ err = -ENOMEM;
23665+ vdir = au_cache_alloc_vdir();
23666+ if (unlikely(!vdir))
23667+ goto out;
23668+
23669+ vdir->vd_deblk = kzalloc(sizeof(*vdir->vd_deblk), GFP_NOFS);
23670+ if (unlikely(!vdir->vd_deblk))
23671+ goto out_free;
23672+
23673+ vdir->vd_deblk_sz = au_sbi(sb)->si_rdblk;
1308ab2a 23674+ if (!vdir->vd_deblk_sz) {
23675+ /* estimate the apropriate size for deblk */
23676+ vdir->vd_deblk_sz = au_dir_size(file, /*dentry*/NULL);
4a4d8108 23677+ /* pr_info("vd_deblk_sz %u\n", vdir->vd_deblk_sz); */
1308ab2a 23678+ }
1facf9fc 23679+ vdir->vd_nblk = 0;
23680+ vdir->vd_version = 0;
23681+ vdir->vd_jiffy = 0;
23682+ err = append_deblk(vdir);
23683+ if (!err)
23684+ return vdir; /* success */
23685+
23686+ kfree(vdir->vd_deblk);
23687+
4f0767ce 23688+out_free:
1facf9fc 23689+ au_cache_free_vdir(vdir);
4f0767ce 23690+out:
1facf9fc 23691+ vdir = ERR_PTR(err);
23692+ return vdir;
23693+}
23694+
23695+static int reinit_vdir(struct au_vdir *vdir)
23696+{
23697+ int err;
23698+ union au_vdir_deblk_p p, deblk_end;
23699+
23700+ while (vdir->vd_nblk > 1) {
23701+ kfree(vdir->vd_deblk[vdir->vd_nblk - 1]);
23702+ /* vdir->vd_deblk[vdir->vd_nblk - 1] = NULL; */
23703+ vdir->vd_nblk--;
23704+ }
23705+ p.deblk = vdir->vd_deblk[0];
23706+ deblk_end.deblk = p.deblk + vdir->vd_deblk_sz;
23707+ err = set_deblk_end(&p, &deblk_end);
23708+ /* keep vd_dblk_sz */
23709+ vdir->vd_last.ul = 0;
23710+ vdir->vd_last.p.deblk = vdir->vd_deblk[0];
23711+ vdir->vd_version = 0;
23712+ vdir->vd_jiffy = 0;
23713+ /* smp_mb(); */
23714+ return err;
23715+}
23716+
23717+/* ---------------------------------------------------------------------- */
23718+
1facf9fc 23719+#define AuFillVdir_CALLED 1
23720+#define AuFillVdir_WHABLE (1 << 1)
dece6358 23721+#define AuFillVdir_SHWH (1 << 2)
1facf9fc 23722+#define au_ftest_fillvdir(flags, name) ((flags) & AuFillVdir_##name)
7f207e10
AM
23723+#define au_fset_fillvdir(flags, name) \
23724+ do { (flags) |= AuFillVdir_##name; } while (0)
23725+#define au_fclr_fillvdir(flags, name) \
23726+ do { (flags) &= ~AuFillVdir_##name; } while (0)
1facf9fc 23727+
dece6358
AM
23728+#ifndef CONFIG_AUFS_SHWH
23729+#undef AuFillVdir_SHWH
23730+#define AuFillVdir_SHWH 0
23731+#endif
23732+
1facf9fc 23733+struct fillvdir_arg {
23734+ struct file *file;
23735+ struct au_vdir *vdir;
dece6358
AM
23736+ struct au_nhash delist;
23737+ struct au_nhash whlist;
1facf9fc 23738+ aufs_bindex_t bindex;
23739+ unsigned int flags;
23740+ int err;
23741+};
23742+
dece6358 23743+static int fillvdir(void *__arg, const char *__name, int nlen,
1facf9fc 23744+ loff_t offset __maybe_unused, u64 h_ino,
23745+ unsigned int d_type)
23746+{
23747+ struct fillvdir_arg *arg = __arg;
23748+ char *name = (void *)__name;
23749+ struct super_block *sb;
1facf9fc 23750+ ino_t ino;
dece6358 23751+ const unsigned char shwh = !!au_ftest_fillvdir(arg->flags, SHWH);
1facf9fc 23752+
1facf9fc 23753+ arg->err = 0;
dece6358 23754+ sb = arg->file->f_dentry->d_sb;
1facf9fc 23755+ au_fset_fillvdir(arg->flags, CALLED);
23756+ /* smp_mb(); */
dece6358 23757+ if (nlen <= AUFS_WH_PFX_LEN
1facf9fc 23758+ || memcmp(name, AUFS_WH_PFX, AUFS_WH_PFX_LEN)) {
dece6358
AM
23759+ if (test_known(&arg->delist, name, nlen)
23760+ || au_nhash_test_known_wh(&arg->whlist, name, nlen))
23761+ goto out; /* already exists or whiteouted */
1facf9fc 23762+
23763+ sb = arg->file->f_dentry->d_sb;
dece6358 23764+ arg->err = au_ino(sb, arg->bindex, h_ino, d_type, &ino);
4a4d8108
AM
23765+ if (!arg->err) {
23766+ if (unlikely(nlen > AUFS_MAX_NAMELEN))
23767+ d_type = DT_UNKNOWN;
dece6358
AM
23768+ arg->err = append_de(arg->vdir, name, nlen, ino,
23769+ d_type, &arg->delist);
4a4d8108 23770+ }
1facf9fc 23771+ } else if (au_ftest_fillvdir(arg->flags, WHABLE)) {
23772+ name += AUFS_WH_PFX_LEN;
dece6358
AM
23773+ nlen -= AUFS_WH_PFX_LEN;
23774+ if (au_nhash_test_known_wh(&arg->whlist, name, nlen))
23775+ goto out; /* already whiteouted */
1facf9fc 23776+
dece6358
AM
23777+ if (shwh)
23778+ arg->err = au_wh_ino(sb, arg->bindex, h_ino, d_type,
23779+ &ino);
4a4d8108
AM
23780+ if (!arg->err) {
23781+ if (nlen <= AUFS_MAX_NAMELEN + AUFS_WH_PFX_LEN)
23782+ d_type = DT_UNKNOWN;
1facf9fc 23783+ arg->err = au_nhash_append_wh
dece6358
AM
23784+ (&arg->whlist, name, nlen, ino, d_type,
23785+ arg->bindex, shwh);
4a4d8108 23786+ }
1facf9fc 23787+ }
23788+
4f0767ce 23789+out:
1facf9fc 23790+ if (!arg->err)
23791+ arg->vdir->vd_jiffy = jiffies;
23792+ /* smp_mb(); */
23793+ AuTraceErr(arg->err);
23794+ return arg->err;
23795+}
23796+
dece6358
AM
23797+static int au_handle_shwh(struct super_block *sb, struct au_vdir *vdir,
23798+ struct au_nhash *whlist, struct au_nhash *delist)
23799+{
23800+#ifdef CONFIG_AUFS_SHWH
23801+ int err;
23802+ unsigned int nh, u;
23803+ struct hlist_head *head;
23804+ struct au_vdir_wh *tpos;
23805+ struct hlist_node *pos, *n;
23806+ char *p, *o;
23807+ struct au_vdir_destr *destr;
23808+
23809+ AuDebugOn(!au_opt_test(au_mntflags(sb), SHWH));
23810+
23811+ err = -ENOMEM;
4a4d8108 23812+ o = p = __getname_gfp(GFP_NOFS);
dece6358
AM
23813+ if (unlikely(!p))
23814+ goto out;
23815+
23816+ err = 0;
23817+ nh = whlist->nh_num;
23818+ memcpy(p, AUFS_WH_PFX, AUFS_WH_PFX_LEN);
23819+ p += AUFS_WH_PFX_LEN;
23820+ for (u = 0; u < nh; u++) {
23821+ head = whlist->nh_head + u;
23822+ hlist_for_each_entry_safe(tpos, pos, n, head, wh_hash) {
23823+ destr = &tpos->wh_str;
23824+ memcpy(p, destr->name, destr->len);
23825+ err = append_de(vdir, o, destr->len + AUFS_WH_PFX_LEN,
23826+ tpos->wh_ino, tpos->wh_type, delist);
23827+ if (unlikely(err))
23828+ break;
23829+ }
23830+ }
23831+
23832+ __putname(o);
23833+
4f0767ce 23834+out:
dece6358
AM
23835+ AuTraceErr(err);
23836+ return err;
23837+#else
23838+ return 0;
23839+#endif
23840+}
23841+
1facf9fc 23842+static int au_do_read_vdir(struct fillvdir_arg *arg)
23843+{
23844+ int err;
dece6358 23845+ unsigned int rdhash;
1facf9fc 23846+ loff_t offset;
dece6358
AM
23847+ aufs_bindex_t bend, bindex, bstart;
23848+ unsigned char shwh;
1facf9fc 23849+ struct file *hf, *file;
23850+ struct super_block *sb;
23851+
1facf9fc 23852+ file = arg->file;
23853+ sb = file->f_dentry->d_sb;
dece6358
AM
23854+ SiMustAnyLock(sb);
23855+
23856+ rdhash = au_sbi(sb)->si_rdhash;
1308ab2a 23857+ if (!rdhash)
23858+ rdhash = au_rdhash_est(au_dir_size(file, /*dentry*/NULL));
dece6358
AM
23859+ err = au_nhash_alloc(&arg->delist, rdhash, GFP_NOFS);
23860+ if (unlikely(err))
1facf9fc 23861+ goto out;
dece6358
AM
23862+ err = au_nhash_alloc(&arg->whlist, rdhash, GFP_NOFS);
23863+ if (unlikely(err))
1facf9fc 23864+ goto out_delist;
23865+
23866+ err = 0;
23867+ arg->flags = 0;
dece6358
AM
23868+ shwh = 0;
23869+ if (au_opt_test(au_mntflags(sb), SHWH)) {
23870+ shwh = 1;
23871+ au_fset_fillvdir(arg->flags, SHWH);
23872+ }
23873+ bstart = au_fbstart(file);
4a4d8108 23874+ bend = au_fbend_dir(file);
dece6358 23875+ for (bindex = bstart; !err && bindex <= bend; bindex++) {
4a4d8108 23876+ hf = au_hf_dir(file, bindex);
1facf9fc 23877+ if (!hf)
23878+ continue;
23879+
23880+ offset = vfsub_llseek(hf, 0, SEEK_SET);
23881+ err = offset;
23882+ if (unlikely(offset))
23883+ break;
23884+
23885+ arg->bindex = bindex;
23886+ au_fclr_fillvdir(arg->flags, WHABLE);
dece6358
AM
23887+ if (shwh
23888+ || (bindex != bend
23889+ && au_br_whable(au_sbr_perm(sb, bindex))))
1facf9fc 23890+ au_fset_fillvdir(arg->flags, WHABLE);
23891+ do {
23892+ arg->err = 0;
23893+ au_fclr_fillvdir(arg->flags, CALLED);
23894+ /* smp_mb(); */
23895+ err = vfsub_readdir(hf, fillvdir, arg);
23896+ if (err >= 0)
23897+ err = arg->err;
23898+ } while (!err && au_ftest_fillvdir(arg->flags, CALLED));
23899+ }
dece6358
AM
23900+
23901+ if (!err && shwh)
23902+ err = au_handle_shwh(sb, arg->vdir, &arg->whlist, &arg->delist);
23903+
23904+ au_nhash_wh_free(&arg->whlist);
1facf9fc 23905+
4f0767ce 23906+out_delist:
dece6358 23907+ au_nhash_de_free(&arg->delist);
4f0767ce 23908+out:
1facf9fc 23909+ return err;
23910+}
23911+
23912+static int read_vdir(struct file *file, int may_read)
23913+{
23914+ int err;
23915+ unsigned long expire;
23916+ unsigned char do_read;
23917+ struct fillvdir_arg arg;
23918+ struct inode *inode;
23919+ struct au_vdir *vdir, *allocated;
23920+
23921+ err = 0;
23922+ inode = file->f_dentry->d_inode;
23923+ IMustLock(inode);
dece6358
AM
23924+ SiMustAnyLock(inode->i_sb);
23925+
1facf9fc 23926+ allocated = NULL;
23927+ do_read = 0;
23928+ expire = au_sbi(inode->i_sb)->si_rdcache;
23929+ vdir = au_ivdir(inode);
23930+ if (!vdir) {
23931+ do_read = 1;
1308ab2a 23932+ vdir = alloc_vdir(file);
1facf9fc 23933+ err = PTR_ERR(vdir);
23934+ if (IS_ERR(vdir))
23935+ goto out;
23936+ err = 0;
23937+ allocated = vdir;
23938+ } else if (may_read
23939+ && (inode->i_version != vdir->vd_version
23940+ || time_after(jiffies, vdir->vd_jiffy + expire))) {
23941+ do_read = 1;
23942+ err = reinit_vdir(vdir);
23943+ if (unlikely(err))
23944+ goto out;
23945+ }
23946+
23947+ if (!do_read)
23948+ return 0; /* success */
23949+
23950+ arg.file = file;
23951+ arg.vdir = vdir;
23952+ err = au_do_read_vdir(&arg);
23953+ if (!err) {
23954+ /* file->f_pos = 0; */
23955+ vdir->vd_version = inode->i_version;
23956+ vdir->vd_last.ul = 0;
23957+ vdir->vd_last.p.deblk = vdir->vd_deblk[0];
23958+ if (allocated)
23959+ au_set_ivdir(inode, allocated);
23960+ } else if (allocated)
23961+ au_vdir_free(allocated);
23962+
4f0767ce 23963+out:
1facf9fc 23964+ return err;
23965+}
23966+
23967+static int copy_vdir(struct au_vdir *tgt, struct au_vdir *src)
23968+{
23969+ int err, rerr;
23970+ unsigned long ul, n;
23971+ const unsigned int deblk_sz = src->vd_deblk_sz;
23972+
23973+ AuDebugOn(tgt->vd_nblk != 1);
23974+
23975+ err = -ENOMEM;
23976+ if (tgt->vd_nblk < src->vd_nblk) {
23977+ unsigned char **p;
23978+
dece6358
AM
23979+ p = krealloc(tgt->vd_deblk, sizeof(*p) * src->vd_nblk,
23980+ GFP_NOFS);
1facf9fc 23981+ if (unlikely(!p))
23982+ goto out;
23983+ tgt->vd_deblk = p;
23984+ }
23985+
1308ab2a 23986+ if (tgt->vd_deblk_sz != deblk_sz) {
23987+ unsigned char *p;
23988+
23989+ tgt->vd_deblk_sz = deblk_sz;
23990+ p = krealloc(tgt->vd_deblk[0], deblk_sz, GFP_NOFS);
23991+ if (unlikely(!p))
23992+ goto out;
23993+ tgt->vd_deblk[0] = p;
23994+ }
1facf9fc 23995+ memcpy(tgt->vd_deblk[0], src->vd_deblk[0], deblk_sz);
1facf9fc 23996+ tgt->vd_version = src->vd_version;
23997+ tgt->vd_jiffy = src->vd_jiffy;
23998+
23999+ n = src->vd_nblk;
24000+ for (ul = 1; ul < n; ul++) {
dece6358
AM
24001+ tgt->vd_deblk[ul] = kmemdup(src->vd_deblk[ul], deblk_sz,
24002+ GFP_NOFS);
24003+ if (unlikely(!tgt->vd_deblk[ul]))
1facf9fc 24004+ goto out;
1308ab2a 24005+ tgt->vd_nblk++;
1facf9fc 24006+ }
1308ab2a 24007+ tgt->vd_nblk = n;
24008+ tgt->vd_last.ul = tgt->vd_last.ul;
24009+ tgt->vd_last.p.deblk = tgt->vd_deblk[tgt->vd_last.ul];
24010+ tgt->vd_last.p.deblk += src->vd_last.p.deblk
24011+ - src->vd_deblk[src->vd_last.ul];
1facf9fc 24012+ /* smp_mb(); */
24013+ return 0; /* success */
24014+
4f0767ce 24015+out:
1facf9fc 24016+ rerr = reinit_vdir(tgt);
24017+ BUG_ON(rerr);
24018+ return err;
24019+}
24020+
24021+int au_vdir_init(struct file *file)
24022+{
24023+ int err;
24024+ struct inode *inode;
24025+ struct au_vdir *vdir_cache, *allocated;
24026+
24027+ err = read_vdir(file, !file->f_pos);
24028+ if (unlikely(err))
24029+ goto out;
24030+
24031+ allocated = NULL;
24032+ vdir_cache = au_fvdir_cache(file);
24033+ if (!vdir_cache) {
1308ab2a 24034+ vdir_cache = alloc_vdir(file);
1facf9fc 24035+ err = PTR_ERR(vdir_cache);
24036+ if (IS_ERR(vdir_cache))
24037+ goto out;
24038+ allocated = vdir_cache;
24039+ } else if (!file->f_pos && vdir_cache->vd_version != file->f_version) {
24040+ err = reinit_vdir(vdir_cache);
24041+ if (unlikely(err))
24042+ goto out;
24043+ } else
24044+ return 0; /* success */
24045+
24046+ inode = file->f_dentry->d_inode;
24047+ err = copy_vdir(vdir_cache, au_ivdir(inode));
24048+ if (!err) {
24049+ file->f_version = inode->i_version;
24050+ if (allocated)
24051+ au_set_fvdir_cache(file, allocated);
24052+ } else if (allocated)
24053+ au_vdir_free(allocated);
24054+
4f0767ce 24055+out:
1facf9fc 24056+ return err;
24057+}
24058+
24059+static loff_t calc_offset(struct au_vdir *vdir)
24060+{
24061+ loff_t offset;
24062+ union au_vdir_deblk_p p;
24063+
24064+ p.deblk = vdir->vd_deblk[vdir->vd_last.ul];
24065+ offset = vdir->vd_last.p.deblk - p.deblk;
24066+ offset += vdir->vd_deblk_sz * vdir->vd_last.ul;
24067+ return offset;
24068+}
24069+
24070+/* returns true or false */
24071+static int seek_vdir(struct file *file)
24072+{
24073+ int valid;
24074+ unsigned int deblk_sz;
24075+ unsigned long ul, n;
24076+ loff_t offset;
24077+ union au_vdir_deblk_p p, deblk_end;
24078+ struct au_vdir *vdir_cache;
24079+
24080+ valid = 1;
24081+ vdir_cache = au_fvdir_cache(file);
24082+ offset = calc_offset(vdir_cache);
24083+ AuDbg("offset %lld\n", offset);
24084+ if (file->f_pos == offset)
24085+ goto out;
24086+
24087+ vdir_cache->vd_last.ul = 0;
24088+ vdir_cache->vd_last.p.deblk = vdir_cache->vd_deblk[0];
24089+ if (!file->f_pos)
24090+ goto out;
24091+
24092+ valid = 0;
24093+ deblk_sz = vdir_cache->vd_deblk_sz;
24094+ ul = div64_u64(file->f_pos, deblk_sz);
24095+ AuDbg("ul %lu\n", ul);
24096+ if (ul >= vdir_cache->vd_nblk)
24097+ goto out;
24098+
24099+ n = vdir_cache->vd_nblk;
24100+ for (; ul < n; ul++) {
24101+ p.deblk = vdir_cache->vd_deblk[ul];
24102+ deblk_end.deblk = p.deblk + deblk_sz;
24103+ offset = ul;
24104+ offset *= deblk_sz;
24105+ while (!is_deblk_end(&p, &deblk_end) && offset < file->f_pos) {
24106+ unsigned int l;
24107+
24108+ l = calc_size(p.de->de_str.len);
24109+ offset += l;
24110+ p.deblk += l;
24111+ }
24112+ if (!is_deblk_end(&p, &deblk_end)) {
24113+ valid = 1;
24114+ vdir_cache->vd_last.ul = ul;
24115+ vdir_cache->vd_last.p = p;
24116+ break;
24117+ }
24118+ }
24119+
4f0767ce 24120+out:
1facf9fc 24121+ /* smp_mb(); */
24122+ AuTraceErr(!valid);
24123+ return valid;
24124+}
24125+
24126+int au_vdir_fill_de(struct file *file, void *dirent, filldir_t filldir)
24127+{
24128+ int err;
24129+ unsigned int l, deblk_sz;
24130+ union au_vdir_deblk_p deblk_end;
24131+ struct au_vdir *vdir_cache;
24132+ struct au_vdir_de *de;
24133+
24134+ vdir_cache = au_fvdir_cache(file);
24135+ if (!seek_vdir(file))
24136+ return 0;
24137+
24138+ deblk_sz = vdir_cache->vd_deblk_sz;
24139+ while (1) {
24140+ deblk_end.deblk = vdir_cache->vd_deblk[vdir_cache->vd_last.ul];
24141+ deblk_end.deblk += deblk_sz;
24142+ while (!is_deblk_end(&vdir_cache->vd_last.p, &deblk_end)) {
24143+ de = vdir_cache->vd_last.p.de;
24144+ AuDbg("%.*s, off%lld, i%lu, dt%d\n",
24145+ de->de_str.len, de->de_str.name, file->f_pos,
24146+ (unsigned long)de->de_ino, de->de_type);
24147+ err = filldir(dirent, de->de_str.name, de->de_str.len,
24148+ file->f_pos, de->de_ino, de->de_type);
24149+ if (unlikely(err)) {
24150+ AuTraceErr(err);
24151+ /* todo: ignore the error caused by udba? */
24152+ /* return err; */
24153+ return 0;
24154+ }
24155+
24156+ l = calc_size(de->de_str.len);
24157+ vdir_cache->vd_last.p.deblk += l;
24158+ file->f_pos += l;
24159+ }
24160+ if (vdir_cache->vd_last.ul < vdir_cache->vd_nblk - 1) {
24161+ vdir_cache->vd_last.ul++;
24162+ vdir_cache->vd_last.p.deblk
24163+ = vdir_cache->vd_deblk[vdir_cache->vd_last.ul];
24164+ file->f_pos = deblk_sz * vdir_cache->vd_last.ul;
24165+ continue;
24166+ }
24167+ break;
24168+ }
24169+
24170+ /* smp_mb(); */
24171+ return 0;
24172+}
7f207e10
AM
24173diff -urN /usr/share/empty/fs/aufs/vfsub.c linux/fs/aufs/vfsub.c
24174--- /usr/share/empty/fs/aufs/vfsub.c 1970-01-01 01:00:00.000000000 +0100
2cbb1c4b
JR
24175+++ linux/fs/aufs/vfsub.c 2011-07-11 11:34:24.078331673 +0200
24176@@ -0,0 +1,818 @@
1facf9fc 24177+/*
027c5e7a 24178+ * Copyright (C) 2005-2011 Junjiro R. Okajima
1facf9fc 24179+ *
24180+ * This program, aufs is free software; you can redistribute it and/or modify
24181+ * it under the terms of the GNU General Public License as published by
24182+ * the Free Software Foundation; either version 2 of the License, or
24183+ * (at your option) any later version.
dece6358
AM
24184+ *
24185+ * This program is distributed in the hope that it will be useful,
24186+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
24187+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24188+ * GNU General Public License for more details.
24189+ *
24190+ * You should have received a copy of the GNU General Public License
24191+ * along with this program; if not, write to the Free Software
24192+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 24193+ */
24194+
24195+/*
24196+ * sub-routines for VFS
24197+ */
24198+
4a4d8108 24199+#include <linux/file.h>
1308ab2a 24200+#include <linux/ima.h>
dece6358
AM
24201+#include <linux/namei.h>
24202+#include <linux/security.h>
24203+#include <linux/splice.h>
1facf9fc 24204+#include <linux/uaccess.h>
24205+#include "aufs.h"
24206+
24207+int vfsub_update_h_iattr(struct path *h_path, int *did)
24208+{
24209+ int err;
24210+ struct kstat st;
24211+ struct super_block *h_sb;
24212+
24213+ /* for remote fs, leave work for its getattr or d_revalidate */
24214+ /* for bad i_attr fs, handle them in aufs_getattr() */
24215+ /* still some fs may acquire i_mutex. we need to skip them */
24216+ err = 0;
24217+ if (!did)
24218+ did = &err;
24219+ h_sb = h_path->dentry->d_sb;
24220+ *did = (!au_test_fs_remote(h_sb) && au_test_fs_refresh_iattr(h_sb));
24221+ if (*did)
24222+ err = vfs_getattr(h_path->mnt, h_path->dentry, &st);
24223+
24224+ return err;
24225+}
24226+
24227+/* ---------------------------------------------------------------------- */
24228+
4a4d8108 24229+struct file *vfsub_dentry_open(struct path *path, int flags)
1308ab2a 24230+{
24231+ struct file *file;
24232+
4a4d8108 24233+ path_get(path);
0c5527e5 24234+ file = dentry_open(path->dentry, path->mnt,
2cbb1c4b 24235+ flags /* | __FMODE_NONOTIFY */,
7f207e10 24236+ current_cred());
2cbb1c4b
JR
24237+ if (!IS_ERR_OR_NULL(file)
24238+ && (file->f_mode & (FMODE_READ | FMODE_WRITE)) == FMODE_READ)
24239+ i_readcount_inc(path->dentry->d_inode);
4a4d8108 24240+
1308ab2a 24241+ return file;
24242+}
24243+
1facf9fc 24244+struct file *vfsub_filp_open(const char *path, int oflags, int mode)
24245+{
24246+ struct file *file;
24247+
2cbb1c4b 24248+ lockdep_off();
7f207e10 24249+ file = filp_open(path,
2cbb1c4b 24250+ oflags /* | __FMODE_NONOTIFY */,
7f207e10 24251+ mode);
2cbb1c4b 24252+ lockdep_on();
1facf9fc 24253+ if (IS_ERR(file))
24254+ goto out;
24255+ vfsub_update_h_iattr(&file->f_path, /*did*/NULL); /*ignore*/
24256+
4f0767ce 24257+out:
1facf9fc 24258+ return file;
24259+}
24260+
24261+int vfsub_kern_path(const char *name, unsigned int flags, struct path *path)
24262+{
24263+ int err;
24264+
1facf9fc 24265+ err = kern_path(name, flags, path);
1facf9fc 24266+ if (!err && path->dentry->d_inode)
24267+ vfsub_update_h_iattr(path, /*did*/NULL); /*ignore*/
24268+ return err;
24269+}
24270+
24271+struct dentry *vfsub_lookup_one_len(const char *name, struct dentry *parent,
24272+ int len)
24273+{
24274+ struct path path = {
24275+ .mnt = NULL
24276+ };
24277+
1308ab2a 24278+ /* VFS checks it too, but by WARN_ON_ONCE() */
1facf9fc 24279+ IMustLock(parent->d_inode);
24280+
24281+ path.dentry = lookup_one_len(name, parent, len);
24282+ if (IS_ERR(path.dentry))
24283+ goto out;
24284+ if (path.dentry->d_inode)
24285+ vfsub_update_h_iattr(&path, /*did*/NULL); /*ignore*/
24286+
4f0767ce 24287+out:
4a4d8108 24288+ AuTraceErrPtr(path.dentry);
1facf9fc 24289+ return path.dentry;
24290+}
24291+
24292+struct dentry *vfsub_lookup_hash(struct nameidata *nd)
24293+{
24294+ struct path path = {
24295+ .mnt = nd->path.mnt
24296+ };
24297+
24298+ IMustLock(nd->path.dentry->d_inode);
24299+
24300+ path.dentry = lookup_hash(nd);
4a4d8108
AM
24301+ if (IS_ERR(path.dentry))
24302+ goto out;
24303+ if (path.dentry->d_inode)
1facf9fc 24304+ vfsub_update_h_iattr(&path, /*did*/NULL); /*ignore*/
24305+
4f0767ce 24306+out:
4a4d8108 24307+ AuTraceErrPtr(path.dentry);
1facf9fc 24308+ return path.dentry;
24309+}
24310+
2cbb1c4b
JR
24311+/*
24312+ * this is "VFS:__lookup_one_len()" which was removed and merged into
24313+ * VFS:lookup_one_len() by the commit.
24314+ * 6a96ba5 2011-03-14 kill __lookup_one_len()
24315+ * this function should always be equivalent to the corresponding part in
24316+ * VFS:lookup_one_len().
24317+ */
24318+int vfsub_name_hash(const char *name, struct qstr *this, int len)
24319+{
24320+ unsigned long hash;
24321+ unsigned int c;
24322+
24323+ this->name = name;
24324+ this->len = len;
24325+ if (!len)
24326+ return -EACCES;
24327+
24328+ hash = init_name_hash();
24329+ while (len--) {
24330+ c = *(const unsigned char *)name++;
24331+ if (c == '/' || c == '\0')
24332+ return -EACCES;
24333+ hash = partial_name_hash(c, hash);
24334+ }
24335+ this->hash = end_name_hash(hash);
24336+ return 0;
24337+}
24338+
1facf9fc 24339+/* ---------------------------------------------------------------------- */
24340+
24341+struct dentry *vfsub_lock_rename(struct dentry *d1, struct au_hinode *hdir1,
24342+ struct dentry *d2, struct au_hinode *hdir2)
24343+{
24344+ struct dentry *d;
24345+
2cbb1c4b 24346+ lockdep_off();
1facf9fc 24347+ d = lock_rename(d1, d2);
2cbb1c4b 24348+ lockdep_on();
4a4d8108 24349+ au_hn_suspend(hdir1);
1facf9fc 24350+ if (hdir1 != hdir2)
4a4d8108 24351+ au_hn_suspend(hdir2);
1facf9fc 24352+
24353+ return d;
24354+}
24355+
24356+void vfsub_unlock_rename(struct dentry *d1, struct au_hinode *hdir1,
24357+ struct dentry *d2, struct au_hinode *hdir2)
24358+{
4a4d8108 24359+ au_hn_resume(hdir1);
1facf9fc 24360+ if (hdir1 != hdir2)
4a4d8108 24361+ au_hn_resume(hdir2);
2cbb1c4b 24362+ lockdep_off();
1facf9fc 24363+ unlock_rename(d1, d2);
2cbb1c4b 24364+ lockdep_on();
1facf9fc 24365+}
24366+
24367+/* ---------------------------------------------------------------------- */
24368+
24369+int vfsub_create(struct inode *dir, struct path *path, int mode)
24370+{
24371+ int err;
24372+ struct dentry *d;
24373+
24374+ IMustLock(dir);
24375+
24376+ d = path->dentry;
24377+ path->dentry = d->d_parent;
b752ccd1 24378+ err = security_path_mknod(path, d, mode, 0);
1facf9fc 24379+ path->dentry = d;
24380+ if (unlikely(err))
24381+ goto out;
24382+
24383+ if (au_test_fs_null_nd(dir->i_sb))
24384+ err = vfs_create(dir, path->dentry, mode, NULL);
24385+ else {
24386+ struct nameidata h_nd;
24387+
24388+ memset(&h_nd, 0, sizeof(h_nd));
24389+ h_nd.flags = LOOKUP_CREATE;
24390+ h_nd.intent.open.flags = O_CREAT
24391+ | vfsub_fmode_to_uint(FMODE_READ);
24392+ h_nd.intent.open.create_mode = mode;
24393+ h_nd.path.dentry = path->dentry->d_parent;
24394+ h_nd.path.mnt = path->mnt;
24395+ path_get(&h_nd.path);
24396+ err = vfs_create(dir, path->dentry, mode, &h_nd);
24397+ path_put(&h_nd.path);
24398+ }
24399+
24400+ if (!err) {
24401+ struct path tmp = *path;
24402+ int did;
24403+
24404+ vfsub_update_h_iattr(&tmp, &did);
24405+ if (did) {
24406+ tmp.dentry = path->dentry->d_parent;
24407+ vfsub_update_h_iattr(&tmp, /*did*/NULL);
24408+ }
24409+ /*ignore*/
24410+ }
24411+
4f0767ce 24412+out:
1facf9fc 24413+ return err;
24414+}
24415+
24416+int vfsub_symlink(struct inode *dir, struct path *path, const char *symname)
24417+{
24418+ int err;
24419+ struct dentry *d;
24420+
24421+ IMustLock(dir);
24422+
24423+ d = path->dentry;
24424+ path->dentry = d->d_parent;
b752ccd1 24425+ err = security_path_symlink(path, d, symname);
1facf9fc 24426+ path->dentry = d;
24427+ if (unlikely(err))
24428+ goto out;
24429+
24430+ err = vfs_symlink(dir, path->dentry, symname);
24431+ if (!err) {
24432+ struct path tmp = *path;
24433+ int did;
24434+
24435+ vfsub_update_h_iattr(&tmp, &did);
24436+ if (did) {
24437+ tmp.dentry = path->dentry->d_parent;
24438+ vfsub_update_h_iattr(&tmp, /*did*/NULL);
24439+ }
24440+ /*ignore*/
24441+ }
24442+
4f0767ce 24443+out:
1facf9fc 24444+ return err;
24445+}
24446+
24447+int vfsub_mknod(struct inode *dir, struct path *path, int mode, dev_t dev)
24448+{
24449+ int err;
24450+ struct dentry *d;
24451+
24452+ IMustLock(dir);
24453+
24454+ d = path->dentry;
24455+ path->dentry = d->d_parent;
027c5e7a 24456+ err = security_path_mknod(path, d, mode, new_encode_dev(dev));
1facf9fc 24457+ path->dentry = d;
24458+ if (unlikely(err))
24459+ goto out;
24460+
24461+ err = vfs_mknod(dir, path->dentry, mode, dev);
24462+ if (!err) {
24463+ struct path tmp = *path;
24464+ int did;
24465+
24466+ vfsub_update_h_iattr(&tmp, &did);
24467+ if (did) {
24468+ tmp.dentry = path->dentry->d_parent;
24469+ vfsub_update_h_iattr(&tmp, /*did*/NULL);
24470+ }
24471+ /*ignore*/
24472+ }
24473+
4f0767ce 24474+out:
1facf9fc 24475+ return err;
24476+}
24477+
24478+static int au_test_nlink(struct inode *inode)
24479+{
24480+ const unsigned int link_max = UINT_MAX >> 1; /* rough margin */
24481+
24482+ if (!au_test_fs_no_limit_nlink(inode->i_sb)
24483+ || inode->i_nlink < link_max)
24484+ return 0;
24485+ return -EMLINK;
24486+}
24487+
24488+int vfsub_link(struct dentry *src_dentry, struct inode *dir, struct path *path)
24489+{
24490+ int err;
24491+ struct dentry *d;
24492+
24493+ IMustLock(dir);
24494+
24495+ err = au_test_nlink(src_dentry->d_inode);
24496+ if (unlikely(err))
24497+ return err;
24498+
24499+ d = path->dentry;
24500+ path->dentry = d->d_parent;
b752ccd1 24501+ err = security_path_link(src_dentry, path, d);
1facf9fc 24502+ path->dentry = d;
24503+ if (unlikely(err))
24504+ goto out;
24505+
2cbb1c4b 24506+ lockdep_off();
1facf9fc 24507+ err = vfs_link(src_dentry, dir, path->dentry);
2cbb1c4b 24508+ lockdep_on();
1facf9fc 24509+ if (!err) {
24510+ struct path tmp = *path;
24511+ int did;
24512+
24513+ /* fuse has different memory inode for the same inumber */
24514+ vfsub_update_h_iattr(&tmp, &did);
24515+ if (did) {
24516+ tmp.dentry = path->dentry->d_parent;
24517+ vfsub_update_h_iattr(&tmp, /*did*/NULL);
24518+ tmp.dentry = src_dentry;
24519+ vfsub_update_h_iattr(&tmp, /*did*/NULL);
24520+ }
24521+ /*ignore*/
24522+ }
24523+
4f0767ce 24524+out:
1facf9fc 24525+ return err;
24526+}
24527+
24528+int vfsub_rename(struct inode *src_dir, struct dentry *src_dentry,
24529+ struct inode *dir, struct path *path)
24530+{
24531+ int err;
24532+ struct path tmp = {
24533+ .mnt = path->mnt
24534+ };
24535+ struct dentry *d;
24536+
24537+ IMustLock(dir);
24538+ IMustLock(src_dir);
24539+
24540+ d = path->dentry;
24541+ path->dentry = d->d_parent;
24542+ tmp.dentry = src_dentry->d_parent;
b752ccd1 24543+ err = security_path_rename(&tmp, src_dentry, path, d);
1facf9fc 24544+ path->dentry = d;
24545+ if (unlikely(err))
24546+ goto out;
24547+
2cbb1c4b 24548+ lockdep_off();
1facf9fc 24549+ err = vfs_rename(src_dir, src_dentry, dir, path->dentry);
2cbb1c4b 24550+ lockdep_on();
1facf9fc 24551+ if (!err) {
24552+ int did;
24553+
24554+ tmp.dentry = d->d_parent;
24555+ vfsub_update_h_iattr(&tmp, &did);
24556+ if (did) {
24557+ tmp.dentry = src_dentry;
24558+ vfsub_update_h_iattr(&tmp, /*did*/NULL);
24559+ tmp.dentry = src_dentry->d_parent;
24560+ vfsub_update_h_iattr(&tmp, /*did*/NULL);
24561+ }
24562+ /*ignore*/
24563+ }
24564+
4f0767ce 24565+out:
1facf9fc 24566+ return err;
24567+}
24568+
24569+int vfsub_mkdir(struct inode *dir, struct path *path, int mode)
24570+{
24571+ int err;
24572+ struct dentry *d;
24573+
24574+ IMustLock(dir);
24575+
24576+ d = path->dentry;
24577+ path->dentry = d->d_parent;
b752ccd1 24578+ err = security_path_mkdir(path, d, mode);
1facf9fc 24579+ path->dentry = d;
24580+ if (unlikely(err))
24581+ goto out;
24582+
24583+ err = vfs_mkdir(dir, path->dentry, mode);
24584+ if (!err) {
24585+ struct path tmp = *path;
24586+ int did;
24587+
24588+ vfsub_update_h_iattr(&tmp, &did);
24589+ if (did) {
24590+ tmp.dentry = path->dentry->d_parent;
24591+ vfsub_update_h_iattr(&tmp, /*did*/NULL);
24592+ }
24593+ /*ignore*/
24594+ }
24595+
4f0767ce 24596+out:
1facf9fc 24597+ return err;
24598+}
24599+
24600+int vfsub_rmdir(struct inode *dir, struct path *path)
24601+{
24602+ int err;
24603+ struct dentry *d;
24604+
24605+ IMustLock(dir);
24606+
24607+ d = path->dentry;
24608+ path->dentry = d->d_parent;
b752ccd1 24609+ err = security_path_rmdir(path, d);
1facf9fc 24610+ path->dentry = d;
24611+ if (unlikely(err))
24612+ goto out;
24613+
2cbb1c4b 24614+ lockdep_off();
1facf9fc 24615+ err = vfs_rmdir(dir, path->dentry);
2cbb1c4b 24616+ lockdep_on();
1facf9fc 24617+ if (!err) {
24618+ struct path tmp = {
24619+ .dentry = path->dentry->d_parent,
24620+ .mnt = path->mnt
24621+ };
24622+
24623+ vfsub_update_h_iattr(&tmp, /*did*/NULL); /*ignore*/
24624+ }
24625+
4f0767ce 24626+out:
1facf9fc 24627+ return err;
24628+}
24629+
24630+/* ---------------------------------------------------------------------- */
24631+
24632+ssize_t vfsub_read_u(struct file *file, char __user *ubuf, size_t count,
24633+ loff_t *ppos)
24634+{
24635+ ssize_t err;
24636+
2cbb1c4b 24637+ lockdep_off();
1facf9fc 24638+ err = vfs_read(file, ubuf, count, ppos);
2cbb1c4b 24639+ lockdep_on();
1facf9fc 24640+ if (err >= 0)
24641+ vfsub_update_h_iattr(&file->f_path, /*did*/NULL); /*ignore*/
24642+ return err;
24643+}
24644+
24645+/* todo: kernel_read()? */
24646+ssize_t vfsub_read_k(struct file *file, void *kbuf, size_t count,
24647+ loff_t *ppos)
24648+{
24649+ ssize_t err;
24650+ mm_segment_t oldfs;
b752ccd1
AM
24651+ union {
24652+ void *k;
24653+ char __user *u;
24654+ } buf;
1facf9fc 24655+
b752ccd1 24656+ buf.k = kbuf;
1facf9fc 24657+ oldfs = get_fs();
24658+ set_fs(KERNEL_DS);
b752ccd1 24659+ err = vfsub_read_u(file, buf.u, count, ppos);
1facf9fc 24660+ set_fs(oldfs);
24661+ return err;
24662+}
24663+
24664+ssize_t vfsub_write_u(struct file *file, const char __user *ubuf, size_t count,
24665+ loff_t *ppos)
24666+{
24667+ ssize_t err;
24668+
2cbb1c4b 24669+ lockdep_off();
1facf9fc 24670+ err = vfs_write(file, ubuf, count, ppos);
2cbb1c4b 24671+ lockdep_on();
1facf9fc 24672+ if (err >= 0)
24673+ vfsub_update_h_iattr(&file->f_path, /*did*/NULL); /*ignore*/
24674+ return err;
24675+}
24676+
24677+ssize_t vfsub_write_k(struct file *file, void *kbuf, size_t count, loff_t *ppos)
24678+{
24679+ ssize_t err;
24680+ mm_segment_t oldfs;
b752ccd1
AM
24681+ union {
24682+ void *k;
24683+ const char __user *u;
24684+ } buf;
1facf9fc 24685+
b752ccd1 24686+ buf.k = kbuf;
1facf9fc 24687+ oldfs = get_fs();
24688+ set_fs(KERNEL_DS);
b752ccd1 24689+ err = vfsub_write_u(file, buf.u, count, ppos);
1facf9fc 24690+ set_fs(oldfs);
24691+ return err;
24692+}
24693+
4a4d8108
AM
24694+int vfsub_flush(struct file *file, fl_owner_t id)
24695+{
24696+ int err;
24697+
24698+ err = 0;
24699+ if (file->f_op && file->f_op->flush) {
2cbb1c4b
JR
24700+ if (!au_test_nfs(file->f_dentry->d_sb))
24701+ err = file->f_op->flush(file, id);
24702+ else {
24703+ lockdep_off();
24704+ err = file->f_op->flush(file, id);
24705+ lockdep_on();
24706+ }
4a4d8108
AM
24707+ if (!err)
24708+ vfsub_update_h_iattr(&file->f_path, /*did*/NULL);
24709+ /*ignore*/
24710+ }
24711+ return err;
24712+}
24713+
1facf9fc 24714+int vfsub_readdir(struct file *file, filldir_t filldir, void *arg)
24715+{
24716+ int err;
24717+
2cbb1c4b 24718+ lockdep_off();
1facf9fc 24719+ err = vfs_readdir(file, filldir, arg);
2cbb1c4b 24720+ lockdep_on();
1facf9fc 24721+ if (err >= 0)
24722+ vfsub_update_h_iattr(&file->f_path, /*did*/NULL); /*ignore*/
24723+ return err;
24724+}
24725+
24726+long vfsub_splice_to(struct file *in, loff_t *ppos,
24727+ struct pipe_inode_info *pipe, size_t len,
24728+ unsigned int flags)
24729+{
24730+ long err;
24731+
2cbb1c4b 24732+ lockdep_off();
0fc653ad 24733+ err = do_splice_to(in, ppos, pipe, len, flags);
2cbb1c4b 24734+ lockdep_on();
4a4d8108 24735+ file_accessed(in);
1facf9fc 24736+ if (err >= 0)
24737+ vfsub_update_h_iattr(&in->f_path, /*did*/NULL); /*ignore*/
24738+ return err;
24739+}
24740+
24741+long vfsub_splice_from(struct pipe_inode_info *pipe, struct file *out,
24742+ loff_t *ppos, size_t len, unsigned int flags)
24743+{
24744+ long err;
24745+
2cbb1c4b 24746+ lockdep_off();
0fc653ad 24747+ err = do_splice_from(pipe, out, ppos, len, flags);
2cbb1c4b 24748+ lockdep_on();
1facf9fc 24749+ if (err >= 0)
24750+ vfsub_update_h_iattr(&out->f_path, /*did*/NULL); /*ignore*/
24751+ return err;
24752+}
24753+
24754+/* cf. open.c:do_sys_truncate() and do_sys_ftruncate() */
24755+int vfsub_trunc(struct path *h_path, loff_t length, unsigned int attr,
24756+ struct file *h_file)
24757+{
24758+ int err;
24759+ struct inode *h_inode;
24760+
24761+ h_inode = h_path->dentry->d_inode;
24762+ if (!h_file) {
24763+ err = mnt_want_write(h_path->mnt);
24764+ if (err)
24765+ goto out;
24766+ err = inode_permission(h_inode, MAY_WRITE);
24767+ if (err)
24768+ goto out_mnt;
24769+ err = get_write_access(h_inode);
24770+ if (err)
24771+ goto out_mnt;
4a4d8108 24772+ err = break_lease(h_inode, O_WRONLY);
1facf9fc 24773+ if (err)
24774+ goto out_inode;
24775+ }
24776+
24777+ err = locks_verify_truncate(h_inode, h_file, length);
24778+ if (!err)
953406b4 24779+ err = security_path_truncate(h_path);
2cbb1c4b
JR
24780+ if (!err) {
24781+ lockdep_off();
1facf9fc 24782+ err = do_truncate(h_path->dentry, length, attr, h_file);
2cbb1c4b
JR
24783+ lockdep_on();
24784+ }
1facf9fc 24785+
4f0767ce 24786+out_inode:
1facf9fc 24787+ if (!h_file)
24788+ put_write_access(h_inode);
4f0767ce 24789+out_mnt:
1facf9fc 24790+ if (!h_file)
24791+ mnt_drop_write(h_path->mnt);
4f0767ce 24792+out:
1facf9fc 24793+ return err;
24794+}
24795+
24796+/* ---------------------------------------------------------------------- */
24797+
24798+struct au_vfsub_mkdir_args {
24799+ int *errp;
24800+ struct inode *dir;
24801+ struct path *path;
24802+ int mode;
24803+};
24804+
24805+static void au_call_vfsub_mkdir(void *args)
24806+{
24807+ struct au_vfsub_mkdir_args *a = args;
24808+ *a->errp = vfsub_mkdir(a->dir, a->path, a->mode);
24809+}
24810+
24811+int vfsub_sio_mkdir(struct inode *dir, struct path *path, int mode)
24812+{
24813+ int err, do_sio, wkq_err;
24814+
24815+ do_sio = au_test_h_perm_sio(dir, MAY_EXEC | MAY_WRITE);
24816+ if (!do_sio)
24817+ err = vfsub_mkdir(dir, path, mode);
24818+ else {
24819+ struct au_vfsub_mkdir_args args = {
24820+ .errp = &err,
24821+ .dir = dir,
24822+ .path = path,
24823+ .mode = mode
24824+ };
24825+ wkq_err = au_wkq_wait(au_call_vfsub_mkdir, &args);
24826+ if (unlikely(wkq_err))
24827+ err = wkq_err;
24828+ }
24829+
24830+ return err;
24831+}
24832+
24833+struct au_vfsub_rmdir_args {
24834+ int *errp;
24835+ struct inode *dir;
24836+ struct path *path;
24837+};
24838+
24839+static void au_call_vfsub_rmdir(void *args)
24840+{
24841+ struct au_vfsub_rmdir_args *a = args;
24842+ *a->errp = vfsub_rmdir(a->dir, a->path);
24843+}
24844+
24845+int vfsub_sio_rmdir(struct inode *dir, struct path *path)
24846+{
24847+ int err, do_sio, wkq_err;
24848+
24849+ do_sio = au_test_h_perm_sio(dir, MAY_EXEC | MAY_WRITE);
24850+ if (!do_sio)
24851+ err = vfsub_rmdir(dir, path);
24852+ else {
24853+ struct au_vfsub_rmdir_args args = {
24854+ .errp = &err,
24855+ .dir = dir,
24856+ .path = path
24857+ };
24858+ wkq_err = au_wkq_wait(au_call_vfsub_rmdir, &args);
24859+ if (unlikely(wkq_err))
24860+ err = wkq_err;
24861+ }
24862+
24863+ return err;
24864+}
24865+
24866+/* ---------------------------------------------------------------------- */
24867+
24868+struct notify_change_args {
24869+ int *errp;
24870+ struct path *path;
24871+ struct iattr *ia;
24872+};
24873+
24874+static void call_notify_change(void *args)
24875+{
24876+ struct notify_change_args *a = args;
24877+ struct inode *h_inode;
24878+
24879+ h_inode = a->path->dentry->d_inode;
24880+ IMustLock(h_inode);
24881+
24882+ *a->errp = -EPERM;
24883+ if (!IS_IMMUTABLE(h_inode) && !IS_APPEND(h_inode)) {
1facf9fc 24884+ *a->errp = notify_change(a->path->dentry, a->ia);
1facf9fc 24885+ if (!*a->errp)
24886+ vfsub_update_h_iattr(a->path, /*did*/NULL); /*ignore*/
24887+ }
24888+ AuTraceErr(*a->errp);
24889+}
24890+
24891+int vfsub_notify_change(struct path *path, struct iattr *ia)
24892+{
24893+ int err;
24894+ struct notify_change_args args = {
24895+ .errp = &err,
24896+ .path = path,
24897+ .ia = ia
24898+ };
24899+
24900+ call_notify_change(&args);
24901+
24902+ return err;
24903+}
24904+
24905+int vfsub_sio_notify_change(struct path *path, struct iattr *ia)
24906+{
24907+ int err, wkq_err;
24908+ struct notify_change_args args = {
24909+ .errp = &err,
24910+ .path = path,
24911+ .ia = ia
24912+ };
24913+
24914+ wkq_err = au_wkq_wait(call_notify_change, &args);
24915+ if (unlikely(wkq_err))
24916+ err = wkq_err;
24917+
24918+ return err;
24919+}
24920+
24921+/* ---------------------------------------------------------------------- */
24922+
24923+struct unlink_args {
24924+ int *errp;
24925+ struct inode *dir;
24926+ struct path *path;
24927+};
24928+
24929+static void call_unlink(void *args)
24930+{
24931+ struct unlink_args *a = args;
24932+ struct dentry *d = a->path->dentry;
24933+ struct inode *h_inode;
24934+ const int stop_sillyrename = (au_test_nfs(d->d_sb)
027c5e7a 24935+ && d->d_count == 1);
1facf9fc 24936+
24937+ IMustLock(a->dir);
24938+
24939+ a->path->dentry = d->d_parent;
24940+ *a->errp = security_path_unlink(a->path, d);
24941+ a->path->dentry = d;
24942+ if (unlikely(*a->errp))
24943+ return;
24944+
24945+ if (!stop_sillyrename)
24946+ dget(d);
24947+ h_inode = d->d_inode;
24948+ if (h_inode)
027c5e7a 24949+ ihold(h_inode);
1facf9fc 24950+
2cbb1c4b 24951+ lockdep_off();
1facf9fc 24952+ *a->errp = vfs_unlink(a->dir, d);
2cbb1c4b 24953+ lockdep_on();
1facf9fc 24954+ if (!*a->errp) {
24955+ struct path tmp = {
24956+ .dentry = d->d_parent,
24957+ .mnt = a->path->mnt
24958+ };
24959+ vfsub_update_h_iattr(&tmp, /*did*/NULL); /*ignore*/
24960+ }
24961+
24962+ if (!stop_sillyrename)
24963+ dput(d);
24964+ if (h_inode)
24965+ iput(h_inode);
24966+
24967+ AuTraceErr(*a->errp);
24968+}
24969+
24970+/*
24971+ * @dir: must be locked.
24972+ * @dentry: target dentry.
24973+ */
24974+int vfsub_unlink(struct inode *dir, struct path *path, int force)
24975+{
24976+ int err;
24977+ struct unlink_args args = {
24978+ .errp = &err,
24979+ .dir = dir,
24980+ .path = path
24981+ };
24982+
24983+ if (!force)
24984+ call_unlink(&args);
24985+ else {
24986+ int wkq_err;
24987+
24988+ wkq_err = au_wkq_wait(call_unlink, &args);
24989+ if (unlikely(wkq_err))
24990+ err = wkq_err;
24991+ }
24992+
24993+ return err;
24994+}
7f207e10
AM
24995diff -urN /usr/share/empty/fs/aufs/vfsub.h linux/fs/aufs/vfsub.h
24996--- /usr/share/empty/fs/aufs/vfsub.h 1970-01-01 01:00:00.000000000 +0100
2cbb1c4b
JR
24997+++ linux/fs/aufs/vfsub.h 2011-07-11 11:34:24.078331673 +0200
24998@@ -0,0 +1,231 @@
1facf9fc 24999+/*
027c5e7a 25000+ * Copyright (C) 2005-2011 Junjiro R. Okajima
1facf9fc 25001+ *
25002+ * This program, aufs is free software; you can redistribute it and/or modify
25003+ * it under the terms of the GNU General Public License as published by
25004+ * the Free Software Foundation; either version 2 of the License, or
25005+ * (at your option) any later version.
dece6358
AM
25006+ *
25007+ * This program is distributed in the hope that it will be useful,
25008+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
25009+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
25010+ * GNU General Public License for more details.
25011+ *
25012+ * You should have received a copy of the GNU General Public License
25013+ * along with this program; if not, write to the Free Software
25014+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 25015+ */
25016+
25017+/*
25018+ * sub-routines for VFS
25019+ */
25020+
25021+#ifndef __AUFS_VFSUB_H__
25022+#define __AUFS_VFSUB_H__
25023+
25024+#ifdef __KERNEL__
25025+
25026+#include <linux/fs.h>
0c5527e5 25027+#include <linux/lglock.h>
7f207e10 25028+#include "debug.h"
1facf9fc 25029+
7f207e10 25030+/* copied from linux/fs/internal.h */
2cbb1c4b 25031+/* todo: BAD approach!! */
0c5527e5 25032+DECLARE_BRLOCK(vfsmount_lock);
0c5527e5 25033+extern void file_sb_list_del(struct file *f);
2cbb1c4b 25034+extern spinlock_t inode_sb_list_lock;
0c5527e5 25035+
7f207e10
AM
25036+/* copied from linux/fs/file_table.c */
25037+DECLARE_LGLOCK(files_lglock);
0c5527e5
AM
25038+#ifdef CONFIG_SMP
25039+/*
25040+ * These macros iterate all files on all CPUs for a given superblock.
25041+ * files_lglock must be held globally.
25042+ */
25043+#define do_file_list_for_each_entry(__sb, __file) \
25044+{ \
25045+ int i; \
25046+ for_each_possible_cpu(i) { \
25047+ struct list_head *list; \
25048+ list = per_cpu_ptr((__sb)->s_files, i); \
25049+ list_for_each_entry((__file), list, f_u.fu_list)
25050+
25051+#define while_file_list_for_each_entry \
25052+ } \
25053+}
25054+
25055+#else
25056+
25057+#define do_file_list_for_each_entry(__sb, __file) \
25058+{ \
25059+ struct list_head *list; \
25060+ list = &(sb)->s_files; \
25061+ list_for_each_entry((__file), list, f_u.fu_list)
25062+
25063+#define while_file_list_for_each_entry \
25064+}
7f207e10
AM
25065+#endif
25066+
25067+/* ---------------------------------------------------------------------- */
1facf9fc 25068+
25069+/* lock subclass for lower inode */
25070+/* default MAX_LOCKDEP_SUBCLASSES(8) is not enough */
25071+/* reduce? gave up. */
25072+enum {
25073+ AuLsc_I_Begin = I_MUTEX_QUOTA, /* 4 */
25074+ AuLsc_I_PARENT, /* lower inode, parent first */
25075+ AuLsc_I_PARENT2, /* copyup dirs */
dece6358 25076+ AuLsc_I_PARENT3, /* copyup wh */
1facf9fc 25077+ AuLsc_I_CHILD,
25078+ AuLsc_I_CHILD2,
25079+ AuLsc_I_End
25080+};
25081+
25082+/* to debug easier, do not make them inlined functions */
25083+#define MtxMustLock(mtx) AuDebugOn(!mutex_is_locked(mtx))
25084+#define IMustLock(i) MtxMustLock(&(i)->i_mutex)
25085+
25086+/* ---------------------------------------------------------------------- */
25087+
7f207e10
AM
25088+static inline void vfsub_drop_nlink(struct inode *inode)
25089+{
25090+ AuDebugOn(!inode->i_nlink);
25091+ drop_nlink(inode);
25092+}
25093+
027c5e7a
AM
25094+static inline void vfsub_dead_dir(struct inode *inode)
25095+{
25096+ AuDebugOn(!S_ISDIR(inode->i_mode));
25097+ inode->i_flags |= S_DEAD;
25098+ clear_nlink(inode);
25099+}
25100+
7f207e10
AM
25101+/* ---------------------------------------------------------------------- */
25102+
25103+int vfsub_update_h_iattr(struct path *h_path, int *did);
25104+struct file *vfsub_dentry_open(struct path *path, int flags);
25105+struct file *vfsub_filp_open(const char *path, int oflags, int mode);
1facf9fc 25106+int vfsub_kern_path(const char *name, unsigned int flags, struct path *path);
25107+struct dentry *vfsub_lookup_one_len(const char *name, struct dentry *parent,
25108+ int len);
25109+struct dentry *vfsub_lookup_hash(struct nameidata *nd);
2cbb1c4b 25110+int vfsub_name_hash(const char *name, struct qstr *this, int len);
1facf9fc 25111+
25112+/* ---------------------------------------------------------------------- */
25113+
25114+struct au_hinode;
25115+struct dentry *vfsub_lock_rename(struct dentry *d1, struct au_hinode *hdir1,
25116+ struct dentry *d2, struct au_hinode *hdir2);
25117+void vfsub_unlock_rename(struct dentry *d1, struct au_hinode *hdir1,
25118+ struct dentry *d2, struct au_hinode *hdir2);
25119+
25120+int vfsub_create(struct inode *dir, struct path *path, int mode);
25121+int vfsub_symlink(struct inode *dir, struct path *path,
25122+ const char *symname);
25123+int vfsub_mknod(struct inode *dir, struct path *path, int mode, dev_t dev);
25124+int vfsub_link(struct dentry *src_dentry, struct inode *dir,
25125+ struct path *path);
25126+int vfsub_rename(struct inode *src_hdir, struct dentry *src_dentry,
25127+ struct inode *hdir, struct path *path);
25128+int vfsub_mkdir(struct inode *dir, struct path *path, int mode);
25129+int vfsub_rmdir(struct inode *dir, struct path *path);
25130+
25131+/* ---------------------------------------------------------------------- */
25132+
25133+ssize_t vfsub_read_u(struct file *file, char __user *ubuf, size_t count,
25134+ loff_t *ppos);
25135+ssize_t vfsub_read_k(struct file *file, void *kbuf, size_t count,
25136+ loff_t *ppos);
25137+ssize_t vfsub_write_u(struct file *file, const char __user *ubuf, size_t count,
25138+ loff_t *ppos);
25139+ssize_t vfsub_write_k(struct file *file, void *kbuf, size_t count,
25140+ loff_t *ppos);
4a4d8108 25141+int vfsub_flush(struct file *file, fl_owner_t id);
1facf9fc 25142+int vfsub_readdir(struct file *file, filldir_t filldir, void *arg);
25143+
4a4d8108
AM
25144+static inline unsigned int vfsub_file_flags(struct file *file)
25145+{
25146+ unsigned int flags;
25147+
25148+ spin_lock(&file->f_lock);
25149+ flags = file->f_flags;
25150+ spin_unlock(&file->f_lock);
25151+
25152+ return flags;
25153+}
1308ab2a 25154+
1facf9fc 25155+static inline void vfsub_file_accessed(struct file *h_file)
25156+{
25157+ file_accessed(h_file);
25158+ vfsub_update_h_iattr(&h_file->f_path, /*did*/NULL); /*ignore*/
25159+}
25160+
25161+static inline void vfsub_touch_atime(struct vfsmount *h_mnt,
25162+ struct dentry *h_dentry)
25163+{
25164+ struct path h_path = {
25165+ .dentry = h_dentry,
25166+ .mnt = h_mnt
25167+ };
25168+ touch_atime(h_mnt, h_dentry);
25169+ vfsub_update_h_iattr(&h_path, /*did*/NULL); /*ignore*/
25170+}
25171+
4a4d8108
AM
25172+long vfsub_splice_to(struct file *in, loff_t *ppos,
25173+ struct pipe_inode_info *pipe, size_t len,
25174+ unsigned int flags);
25175+long vfsub_splice_from(struct pipe_inode_info *pipe, struct file *out,
25176+ loff_t *ppos, size_t len, unsigned int flags);
25177+int vfsub_trunc(struct path *h_path, loff_t length, unsigned int attr,
25178+ struct file *h_file);
25179+
1facf9fc 25180+/* ---------------------------------------------------------------------- */
25181+
25182+static inline loff_t vfsub_llseek(struct file *file, loff_t offset, int origin)
25183+{
25184+ loff_t err;
25185+
2cbb1c4b 25186+ lockdep_off();
1facf9fc 25187+ err = vfs_llseek(file, offset, origin);
2cbb1c4b 25188+ lockdep_on();
1facf9fc 25189+ return err;
25190+}
25191+
25192+/* ---------------------------------------------------------------------- */
25193+
25194+/* dirty workaround for strict type of fmode_t */
25195+union vfsub_fmu {
25196+ fmode_t fm;
25197+ unsigned int ui;
25198+};
25199+
25200+static inline unsigned int vfsub_fmode_to_uint(fmode_t fm)
25201+{
25202+ union vfsub_fmu u = {
25203+ .fm = fm
25204+ };
25205+
25206+ BUILD_BUG_ON(sizeof(u.fm) != sizeof(u.ui));
25207+
25208+ return u.ui;
25209+}
25210+
25211+static inline fmode_t vfsub_uint_to_fmode(unsigned int ui)
25212+{
25213+ union vfsub_fmu u = {
25214+ .ui = ui
25215+ };
25216+
25217+ return u.fm;
25218+}
25219+
4a4d8108
AM
25220+/* ---------------------------------------------------------------------- */
25221+
25222+int vfsub_sio_mkdir(struct inode *dir, struct path *path, int mode);
25223+int vfsub_sio_rmdir(struct inode *dir, struct path *path);
25224+int vfsub_sio_notify_change(struct path *path, struct iattr *ia);
25225+int vfsub_notify_change(struct path *path, struct iattr *ia);
25226+int vfsub_unlink(struct inode *dir, struct path *path, int force);
25227+
1facf9fc 25228+#endif /* __KERNEL__ */
25229+#endif /* __AUFS_VFSUB_H__ */
7f207e10
AM
25230diff -urN /usr/share/empty/fs/aufs/wbr_policy.c linux/fs/aufs/wbr_policy.c
25231--- /usr/share/empty/fs/aufs/wbr_policy.c 1970-01-01 01:00:00.000000000 +0100
2cbb1c4b 25232+++ linux/fs/aufs/wbr_policy.c 2011-07-11 11:34:24.078331673 +0200
027c5e7a 25233@@ -0,0 +1,700 @@
1facf9fc 25234+/*
027c5e7a 25235+ * Copyright (C) 2005-2011 Junjiro R. Okajima
1facf9fc 25236+ *
25237+ * This program, aufs is free software; you can redistribute it and/or modify
25238+ * it under the terms of the GNU General Public License as published by
25239+ * the Free Software Foundation; either version 2 of the License, or
25240+ * (at your option) any later version.
dece6358
AM
25241+ *
25242+ * This program is distributed in the hope that it will be useful,
25243+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
25244+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
25245+ * GNU General Public License for more details.
25246+ *
25247+ * You should have received a copy of the GNU General Public License
25248+ * along with this program; if not, write to the Free Software
25249+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 25250+ */
25251+
25252+/*
25253+ * policies for selecting one among multiple writable branches
25254+ */
25255+
25256+#include <linux/statfs.h>
25257+#include "aufs.h"
25258+
25259+/* subset of cpup_attr() */
25260+static noinline_for_stack
25261+int au_cpdown_attr(struct path *h_path, struct dentry *h_src)
25262+{
25263+ int err, sbits;
25264+ struct iattr ia;
25265+ struct inode *h_isrc;
25266+
25267+ h_isrc = h_src->d_inode;
25268+ ia.ia_valid = ATTR_FORCE | ATTR_MODE | ATTR_UID | ATTR_GID;
25269+ ia.ia_mode = h_isrc->i_mode;
25270+ ia.ia_uid = h_isrc->i_uid;
25271+ ia.ia_gid = h_isrc->i_gid;
25272+ sbits = !!(ia.ia_mode & (S_ISUID | S_ISGID));
25273+ au_cpup_attr_flags(h_path->dentry->d_inode, h_isrc);
25274+ err = vfsub_sio_notify_change(h_path, &ia);
25275+
25276+ /* is this nfs only? */
25277+ if (!err && sbits && au_test_nfs(h_path->dentry->d_sb)) {
25278+ ia.ia_valid = ATTR_FORCE | ATTR_MODE;
25279+ ia.ia_mode = h_isrc->i_mode;
25280+ err = vfsub_sio_notify_change(h_path, &ia);
25281+ }
25282+
25283+ return err;
25284+}
25285+
25286+#define AuCpdown_PARENT_OPQ 1
25287+#define AuCpdown_WHED (1 << 1)
25288+#define AuCpdown_MADE_DIR (1 << 2)
25289+#define AuCpdown_DIROPQ (1 << 3)
25290+#define au_ftest_cpdown(flags, name) ((flags) & AuCpdown_##name)
7f207e10
AM
25291+#define au_fset_cpdown(flags, name) \
25292+ do { (flags) |= AuCpdown_##name; } while (0)
25293+#define au_fclr_cpdown(flags, name) \
25294+ do { (flags) &= ~AuCpdown_##name; } while (0)
1facf9fc 25295+
25296+struct au_cpdown_dir_args {
25297+ struct dentry *parent;
25298+ unsigned int flags;
25299+};
25300+
25301+static int au_cpdown_dir_opq(struct dentry *dentry, aufs_bindex_t bdst,
25302+ struct au_cpdown_dir_args *a)
25303+{
25304+ int err;
25305+ struct dentry *opq_dentry;
25306+
25307+ opq_dentry = au_diropq_create(dentry, bdst);
25308+ err = PTR_ERR(opq_dentry);
25309+ if (IS_ERR(opq_dentry))
25310+ goto out;
25311+ dput(opq_dentry);
25312+ au_fset_cpdown(a->flags, DIROPQ);
25313+
4f0767ce 25314+out:
1facf9fc 25315+ return err;
25316+}
25317+
25318+static int au_cpdown_dir_wh(struct dentry *dentry, struct dentry *h_parent,
25319+ struct inode *dir, aufs_bindex_t bdst)
25320+{
25321+ int err;
25322+ struct path h_path;
25323+ struct au_branch *br;
25324+
25325+ br = au_sbr(dentry->d_sb, bdst);
25326+ h_path.dentry = au_wh_lkup(h_parent, &dentry->d_name, br);
25327+ err = PTR_ERR(h_path.dentry);
25328+ if (IS_ERR(h_path.dentry))
25329+ goto out;
25330+
25331+ err = 0;
25332+ if (h_path.dentry->d_inode) {
25333+ h_path.mnt = br->br_mnt;
25334+ err = au_wh_unlink_dentry(au_h_iptr(dir, bdst), &h_path,
25335+ dentry);
25336+ }
25337+ dput(h_path.dentry);
25338+
4f0767ce 25339+out:
1facf9fc 25340+ return err;
25341+}
25342+
25343+static int au_cpdown_dir(struct dentry *dentry, aufs_bindex_t bdst,
25344+ struct dentry *h_parent, void *arg)
25345+{
25346+ int err, rerr;
4a4d8108 25347+ aufs_bindex_t bopq, bstart;
1facf9fc 25348+ struct path h_path;
25349+ struct dentry *parent;
25350+ struct inode *h_dir, *h_inode, *inode, *dir;
25351+ struct au_cpdown_dir_args *args = arg;
25352+
25353+ bstart = au_dbstart(dentry);
25354+ /* dentry is di-locked */
25355+ parent = dget_parent(dentry);
25356+ dir = parent->d_inode;
25357+ h_dir = h_parent->d_inode;
25358+ AuDebugOn(h_dir != au_h_iptr(dir, bdst));
25359+ IMustLock(h_dir);
25360+
25361+ err = au_lkup_neg(dentry, bdst);
25362+ if (unlikely(err < 0))
25363+ goto out;
25364+ h_path.dentry = au_h_dptr(dentry, bdst);
25365+ h_path.mnt = au_sbr_mnt(dentry->d_sb, bdst);
25366+ err = vfsub_sio_mkdir(au_h_iptr(dir, bdst), &h_path,
25367+ S_IRWXU | S_IRUGO | S_IXUGO);
25368+ if (unlikely(err))
25369+ goto out_put;
25370+ au_fset_cpdown(args->flags, MADE_DIR);
25371+
1facf9fc 25372+ bopq = au_dbdiropq(dentry);
25373+ au_fclr_cpdown(args->flags, WHED);
25374+ au_fclr_cpdown(args->flags, DIROPQ);
25375+ if (au_dbwh(dentry) == bdst)
25376+ au_fset_cpdown(args->flags, WHED);
25377+ if (!au_ftest_cpdown(args->flags, PARENT_OPQ) && bopq <= bdst)
25378+ au_fset_cpdown(args->flags, PARENT_OPQ);
1facf9fc 25379+ h_inode = h_path.dentry->d_inode;
25380+ mutex_lock_nested(&h_inode->i_mutex, AuLsc_I_CHILD);
25381+ if (au_ftest_cpdown(args->flags, WHED)) {
25382+ err = au_cpdown_dir_opq(dentry, bdst, args);
25383+ if (unlikely(err)) {
25384+ mutex_unlock(&h_inode->i_mutex);
25385+ goto out_dir;
25386+ }
25387+ }
25388+
25389+ err = au_cpdown_attr(&h_path, au_h_dptr(dentry, bstart));
25390+ mutex_unlock(&h_inode->i_mutex);
25391+ if (unlikely(err))
25392+ goto out_opq;
25393+
25394+ if (au_ftest_cpdown(args->flags, WHED)) {
25395+ err = au_cpdown_dir_wh(dentry, h_parent, dir, bdst);
25396+ if (unlikely(err))
25397+ goto out_opq;
25398+ }
25399+
25400+ inode = dentry->d_inode;
25401+ if (au_ibend(inode) < bdst)
25402+ au_set_ibend(inode, bdst);
25403+ au_set_h_iptr(inode, bdst, au_igrab(h_inode),
25404+ au_hi_flags(inode, /*isdir*/1));
25405+ goto out; /* success */
25406+
25407+ /* revert */
4f0767ce 25408+out_opq:
1facf9fc 25409+ if (au_ftest_cpdown(args->flags, DIROPQ)) {
25410+ mutex_lock_nested(&h_inode->i_mutex, AuLsc_I_CHILD);
25411+ rerr = au_diropq_remove(dentry, bdst);
25412+ mutex_unlock(&h_inode->i_mutex);
25413+ if (unlikely(rerr)) {
25414+ AuIOErr("failed removing diropq for %.*s b%d (%d)\n",
25415+ AuDLNPair(dentry), bdst, rerr);
25416+ err = -EIO;
25417+ goto out;
25418+ }
25419+ }
4f0767ce 25420+out_dir:
1facf9fc 25421+ if (au_ftest_cpdown(args->flags, MADE_DIR)) {
25422+ rerr = vfsub_sio_rmdir(au_h_iptr(dir, bdst), &h_path);
25423+ if (unlikely(rerr)) {
25424+ AuIOErr("failed removing %.*s b%d (%d)\n",
25425+ AuDLNPair(dentry), bdst, rerr);
25426+ err = -EIO;
25427+ }
25428+ }
4f0767ce 25429+out_put:
1facf9fc 25430+ au_set_h_dptr(dentry, bdst, NULL);
25431+ if (au_dbend(dentry) == bdst)
25432+ au_update_dbend(dentry);
4f0767ce 25433+out:
1facf9fc 25434+ dput(parent);
25435+ return err;
25436+}
25437+
25438+int au_cpdown_dirs(struct dentry *dentry, aufs_bindex_t bdst)
25439+{
25440+ int err;
25441+ struct au_cpdown_dir_args args = {
25442+ .parent = dget_parent(dentry),
25443+ .flags = 0
25444+ };
25445+
25446+ err = au_cp_dirs(dentry, bdst, au_cpdown_dir, &args);
25447+ dput(args.parent);
25448+
25449+ return err;
25450+}
25451+
25452+/* ---------------------------------------------------------------------- */
25453+
25454+/* policies for create */
25455+
4a4d8108
AM
25456+static int au_wbr_nonopq(struct dentry *dentry, aufs_bindex_t bindex)
25457+{
25458+ int err, i, j, ndentry;
25459+ aufs_bindex_t bopq;
25460+ struct au_dcsub_pages dpages;
25461+ struct au_dpage *dpage;
25462+ struct dentry **dentries, *parent, *d;
25463+
25464+ err = au_dpages_init(&dpages, GFP_NOFS);
25465+ if (unlikely(err))
25466+ goto out;
25467+ parent = dget_parent(dentry);
027c5e7a 25468+ err = au_dcsub_pages_rev_aufs(&dpages, parent, /*do_include*/0);
4a4d8108
AM
25469+ if (unlikely(err))
25470+ goto out_free;
25471+
25472+ err = bindex;
25473+ for (i = 0; i < dpages.ndpage; i++) {
25474+ dpage = dpages.dpages + i;
25475+ dentries = dpage->dentries;
25476+ ndentry = dpage->ndentry;
25477+ for (j = 0; j < ndentry; j++) {
25478+ d = dentries[j];
25479+ di_read_lock_parent2(d, !AuLock_IR);
25480+ bopq = au_dbdiropq(d);
25481+ di_read_unlock(d, !AuLock_IR);
25482+ if (bopq >= 0 && bopq < err)
25483+ err = bopq;
25484+ }
25485+ }
25486+
25487+out_free:
25488+ dput(parent);
25489+ au_dpages_free(&dpages);
25490+out:
25491+ return err;
25492+}
25493+
1facf9fc 25494+static int au_wbr_bu(struct super_block *sb, aufs_bindex_t bindex)
25495+{
25496+ for (; bindex >= 0; bindex--)
25497+ if (!au_br_rdonly(au_sbr(sb, bindex)))
25498+ return bindex;
25499+ return -EROFS;
25500+}
25501+
25502+/* top down parent */
25503+static int au_wbr_create_tdp(struct dentry *dentry, int isdir __maybe_unused)
25504+{
25505+ int err;
25506+ aufs_bindex_t bstart, bindex;
25507+ struct super_block *sb;
25508+ struct dentry *parent, *h_parent;
25509+
25510+ sb = dentry->d_sb;
25511+ bstart = au_dbstart(dentry);
25512+ err = bstart;
25513+ if (!au_br_rdonly(au_sbr(sb, bstart)))
25514+ goto out;
25515+
25516+ err = -EROFS;
25517+ parent = dget_parent(dentry);
25518+ for (bindex = au_dbstart(parent); bindex < bstart; bindex++) {
25519+ h_parent = au_h_dptr(parent, bindex);
25520+ if (!h_parent || !h_parent->d_inode)
25521+ continue;
25522+
25523+ if (!au_br_rdonly(au_sbr(sb, bindex))) {
25524+ err = bindex;
25525+ break;
25526+ }
25527+ }
25528+ dput(parent);
25529+
25530+ /* bottom up here */
4a4d8108 25531+ if (unlikely(err < 0)) {
1facf9fc 25532+ err = au_wbr_bu(sb, bstart - 1);
4a4d8108
AM
25533+ if (err >= 0)
25534+ err = au_wbr_nonopq(dentry, err);
25535+ }
1facf9fc 25536+
4f0767ce 25537+out:
1facf9fc 25538+ AuDbg("b%d\n", err);
25539+ return err;
25540+}
25541+
25542+/* ---------------------------------------------------------------------- */
25543+
25544+/* an exception for the policy other than tdp */
25545+static int au_wbr_create_exp(struct dentry *dentry)
25546+{
25547+ int err;
25548+ aufs_bindex_t bwh, bdiropq;
25549+ struct dentry *parent;
25550+
25551+ err = -1;
25552+ bwh = au_dbwh(dentry);
25553+ parent = dget_parent(dentry);
25554+ bdiropq = au_dbdiropq(parent);
25555+ if (bwh >= 0) {
25556+ if (bdiropq >= 0)
25557+ err = min(bdiropq, bwh);
25558+ else
25559+ err = bwh;
25560+ AuDbg("%d\n", err);
25561+ } else if (bdiropq >= 0) {
25562+ err = bdiropq;
25563+ AuDbg("%d\n", err);
25564+ }
25565+ dput(parent);
25566+
4a4d8108
AM
25567+ if (err >= 0)
25568+ err = au_wbr_nonopq(dentry, err);
25569+
1facf9fc 25570+ if (err >= 0 && au_br_rdonly(au_sbr(dentry->d_sb, err)))
25571+ err = -1;
25572+
25573+ AuDbg("%d\n", err);
25574+ return err;
25575+}
25576+
25577+/* ---------------------------------------------------------------------- */
25578+
25579+/* round robin */
25580+static int au_wbr_create_init_rr(struct super_block *sb)
25581+{
25582+ int err;
25583+
25584+ err = au_wbr_bu(sb, au_sbend(sb));
25585+ atomic_set(&au_sbi(sb)->si_wbr_rr_next, -err); /* less important */
dece6358 25586+ /* smp_mb(); */
1facf9fc 25587+
25588+ AuDbg("b%d\n", err);
25589+ return err;
25590+}
25591+
25592+static int au_wbr_create_rr(struct dentry *dentry, int isdir)
25593+{
25594+ int err, nbr;
25595+ unsigned int u;
25596+ aufs_bindex_t bindex, bend;
25597+ struct super_block *sb;
25598+ atomic_t *next;
25599+
25600+ err = au_wbr_create_exp(dentry);
25601+ if (err >= 0)
25602+ goto out;
25603+
25604+ sb = dentry->d_sb;
25605+ next = &au_sbi(sb)->si_wbr_rr_next;
25606+ bend = au_sbend(sb);
25607+ nbr = bend + 1;
25608+ for (bindex = 0; bindex <= bend; bindex++) {
25609+ if (!isdir) {
25610+ err = atomic_dec_return(next) + 1;
25611+ /* modulo for 0 is meaningless */
25612+ if (unlikely(!err))
25613+ err = atomic_dec_return(next) + 1;
25614+ } else
25615+ err = atomic_read(next);
25616+ AuDbg("%d\n", err);
25617+ u = err;
25618+ err = u % nbr;
25619+ AuDbg("%d\n", err);
25620+ if (!au_br_rdonly(au_sbr(sb, err)))
25621+ break;
25622+ err = -EROFS;
25623+ }
25624+
4a4d8108
AM
25625+ if (err >= 0)
25626+ err = au_wbr_nonopq(dentry, err);
25627+
4f0767ce 25628+out:
1facf9fc 25629+ AuDbg("%d\n", err);
25630+ return err;
25631+}
25632+
25633+/* ---------------------------------------------------------------------- */
25634+
25635+/* most free space */
25636+static void au_mfs(struct dentry *dentry)
25637+{
25638+ struct super_block *sb;
25639+ struct au_branch *br;
25640+ struct au_wbr_mfs *mfs;
25641+ aufs_bindex_t bindex, bend;
25642+ int err;
25643+ unsigned long long b, bavail;
7f207e10 25644+ struct path h_path;
1facf9fc 25645+ /* reduce the stack usage */
25646+ struct kstatfs *st;
25647+
25648+ st = kmalloc(sizeof(*st), GFP_NOFS);
25649+ if (unlikely(!st)) {
25650+ AuWarn1("failed updating mfs(%d), ignored\n", -ENOMEM);
25651+ return;
25652+ }
25653+
25654+ bavail = 0;
25655+ sb = dentry->d_sb;
25656+ mfs = &au_sbi(sb)->si_wbr_mfs;
dece6358 25657+ MtxMustLock(&mfs->mfs_lock);
1facf9fc 25658+ mfs->mfs_bindex = -EROFS;
25659+ mfs->mfsrr_bytes = 0;
25660+ bend = au_sbend(sb);
25661+ for (bindex = 0; bindex <= bend; bindex++) {
25662+ br = au_sbr(sb, bindex);
25663+ if (au_br_rdonly(br))
25664+ continue;
25665+
25666+ /* sb->s_root for NFS is unreliable */
7f207e10
AM
25667+ h_path.mnt = br->br_mnt;
25668+ h_path.dentry = h_path.mnt->mnt_root;
25669+ err = vfs_statfs(&h_path, st);
1facf9fc 25670+ if (unlikely(err)) {
25671+ AuWarn1("failed statfs, b%d, %d\n", bindex, err);
25672+ continue;
25673+ }
25674+
25675+ /* when the available size is equal, select the lower one */
25676+ BUILD_BUG_ON(sizeof(b) < sizeof(st->f_bavail)
25677+ || sizeof(b) < sizeof(st->f_bsize));
25678+ b = st->f_bavail * st->f_bsize;
25679+ br->br_wbr->wbr_bytes = b;
25680+ if (b >= bavail) {
25681+ bavail = b;
25682+ mfs->mfs_bindex = bindex;
25683+ mfs->mfs_jiffy = jiffies;
25684+ }
25685+ }
25686+
25687+ mfs->mfsrr_bytes = bavail;
25688+ AuDbg("b%d\n", mfs->mfs_bindex);
25689+ kfree(st);
25690+}
25691+
25692+static int au_wbr_create_mfs(struct dentry *dentry, int isdir __maybe_unused)
25693+{
25694+ int err;
25695+ struct super_block *sb;
25696+ struct au_wbr_mfs *mfs;
25697+
25698+ err = au_wbr_create_exp(dentry);
25699+ if (err >= 0)
25700+ goto out;
25701+
25702+ sb = dentry->d_sb;
25703+ mfs = &au_sbi(sb)->si_wbr_mfs;
25704+ mutex_lock(&mfs->mfs_lock);
25705+ if (time_after(jiffies, mfs->mfs_jiffy + mfs->mfs_expire)
25706+ || mfs->mfs_bindex < 0
25707+ || au_br_rdonly(au_sbr(sb, mfs->mfs_bindex)))
25708+ au_mfs(dentry);
25709+ mutex_unlock(&mfs->mfs_lock);
25710+ err = mfs->mfs_bindex;
25711+
4a4d8108
AM
25712+ if (err >= 0)
25713+ err = au_wbr_nonopq(dentry, err);
25714+
4f0767ce 25715+out:
1facf9fc 25716+ AuDbg("b%d\n", err);
25717+ return err;
25718+}
25719+
25720+static int au_wbr_create_init_mfs(struct super_block *sb)
25721+{
25722+ struct au_wbr_mfs *mfs;
25723+
25724+ mfs = &au_sbi(sb)->si_wbr_mfs;
25725+ mutex_init(&mfs->mfs_lock);
25726+ mfs->mfs_jiffy = 0;
25727+ mfs->mfs_bindex = -EROFS;
25728+
25729+ return 0;
25730+}
25731+
25732+static int au_wbr_create_fin_mfs(struct super_block *sb __maybe_unused)
25733+{
25734+ mutex_destroy(&au_sbi(sb)->si_wbr_mfs.mfs_lock);
25735+ return 0;
25736+}
25737+
25738+/* ---------------------------------------------------------------------- */
25739+
25740+/* most free space and then round robin */
25741+static int au_wbr_create_mfsrr(struct dentry *dentry, int isdir)
25742+{
25743+ int err;
25744+ struct au_wbr_mfs *mfs;
25745+
25746+ err = au_wbr_create_mfs(dentry, isdir);
25747+ if (err >= 0) {
25748+ mfs = &au_sbi(dentry->d_sb)->si_wbr_mfs;
dece6358 25749+ mutex_lock(&mfs->mfs_lock);
1facf9fc 25750+ if (mfs->mfsrr_bytes < mfs->mfsrr_watermark)
25751+ err = au_wbr_create_rr(dentry, isdir);
dece6358 25752+ mutex_unlock(&mfs->mfs_lock);
1facf9fc 25753+ }
25754+
25755+ AuDbg("b%d\n", err);
25756+ return err;
25757+}
25758+
25759+static int au_wbr_create_init_mfsrr(struct super_block *sb)
25760+{
25761+ int err;
25762+
25763+ au_wbr_create_init_mfs(sb); /* ignore */
25764+ err = au_wbr_create_init_rr(sb);
25765+
25766+ return err;
25767+}
25768+
25769+/* ---------------------------------------------------------------------- */
25770+
25771+/* top down parent and most free space */
25772+static int au_wbr_create_pmfs(struct dentry *dentry, int isdir)
25773+{
25774+ int err, e2;
25775+ unsigned long long b;
25776+ aufs_bindex_t bindex, bstart, bend;
25777+ struct super_block *sb;
25778+ struct dentry *parent, *h_parent;
25779+ struct au_branch *br;
25780+
25781+ err = au_wbr_create_tdp(dentry, isdir);
25782+ if (unlikely(err < 0))
25783+ goto out;
25784+ parent = dget_parent(dentry);
25785+ bstart = au_dbstart(parent);
25786+ bend = au_dbtaildir(parent);
25787+ if (bstart == bend)
25788+ goto out_parent; /* success */
25789+
25790+ e2 = au_wbr_create_mfs(dentry, isdir);
25791+ if (e2 < 0)
25792+ goto out_parent; /* success */
25793+
25794+ /* when the available size is equal, select upper one */
25795+ sb = dentry->d_sb;
25796+ br = au_sbr(sb, err);
25797+ b = br->br_wbr->wbr_bytes;
25798+ AuDbg("b%d, %llu\n", err, b);
25799+
25800+ for (bindex = bstart; bindex <= bend; bindex++) {
25801+ h_parent = au_h_dptr(parent, bindex);
25802+ if (!h_parent || !h_parent->d_inode)
25803+ continue;
25804+
25805+ br = au_sbr(sb, bindex);
25806+ if (!au_br_rdonly(br) && br->br_wbr->wbr_bytes > b) {
25807+ b = br->br_wbr->wbr_bytes;
25808+ err = bindex;
25809+ AuDbg("b%d, %llu\n", err, b);
25810+ }
25811+ }
25812+
4a4d8108
AM
25813+ if (err >= 0)
25814+ err = au_wbr_nonopq(dentry, err);
25815+
4f0767ce 25816+out_parent:
1facf9fc 25817+ dput(parent);
4f0767ce 25818+out:
1facf9fc 25819+ AuDbg("b%d\n", err);
25820+ return err;
25821+}
25822+
25823+/* ---------------------------------------------------------------------- */
25824+
25825+/* policies for copyup */
25826+
25827+/* top down parent */
25828+static int au_wbr_copyup_tdp(struct dentry *dentry)
25829+{
25830+ return au_wbr_create_tdp(dentry, /*isdir, anything is ok*/0);
25831+}
25832+
25833+/* bottom up parent */
25834+static int au_wbr_copyup_bup(struct dentry *dentry)
25835+{
25836+ int err;
25837+ aufs_bindex_t bindex, bstart;
25838+ struct dentry *parent, *h_parent;
25839+ struct super_block *sb;
25840+
25841+ err = -EROFS;
25842+ sb = dentry->d_sb;
25843+ parent = dget_parent(dentry);
25844+ bstart = au_dbstart(parent);
25845+ for (bindex = au_dbstart(dentry); bindex >= bstart; bindex--) {
25846+ h_parent = au_h_dptr(parent, bindex);
25847+ if (!h_parent || !h_parent->d_inode)
25848+ continue;
25849+
25850+ if (!au_br_rdonly(au_sbr(sb, bindex))) {
25851+ err = bindex;
25852+ break;
25853+ }
25854+ }
25855+ dput(parent);
25856+
25857+ /* bottom up here */
25858+ if (unlikely(err < 0))
25859+ err = au_wbr_bu(sb, bstart - 1);
25860+
25861+ AuDbg("b%d\n", err);
25862+ return err;
25863+}
25864+
25865+/* bottom up */
25866+static int au_wbr_copyup_bu(struct dentry *dentry)
25867+{
25868+ int err;
4a4d8108 25869+ aufs_bindex_t bstart;
1facf9fc 25870+
4a4d8108
AM
25871+ bstart = au_dbstart(dentry);
25872+ err = au_wbr_bu(dentry->d_sb, bstart);
25873+ AuDbg("b%d\n", err);
25874+ if (err > bstart)
25875+ err = au_wbr_nonopq(dentry, err);
1facf9fc 25876+
25877+ AuDbg("b%d\n", err);
25878+ return err;
25879+}
25880+
25881+/* ---------------------------------------------------------------------- */
25882+
25883+struct au_wbr_copyup_operations au_wbr_copyup_ops[] = {
25884+ [AuWbrCopyup_TDP] = {
25885+ .copyup = au_wbr_copyup_tdp
25886+ },
25887+ [AuWbrCopyup_BUP] = {
25888+ .copyup = au_wbr_copyup_bup
25889+ },
25890+ [AuWbrCopyup_BU] = {
25891+ .copyup = au_wbr_copyup_bu
25892+ }
25893+};
25894+
25895+struct au_wbr_create_operations au_wbr_create_ops[] = {
25896+ [AuWbrCreate_TDP] = {
25897+ .create = au_wbr_create_tdp
25898+ },
25899+ [AuWbrCreate_RR] = {
25900+ .create = au_wbr_create_rr,
25901+ .init = au_wbr_create_init_rr
25902+ },
25903+ [AuWbrCreate_MFS] = {
25904+ .create = au_wbr_create_mfs,
25905+ .init = au_wbr_create_init_mfs,
25906+ .fin = au_wbr_create_fin_mfs
25907+ },
25908+ [AuWbrCreate_MFSV] = {
25909+ .create = au_wbr_create_mfs,
25910+ .init = au_wbr_create_init_mfs,
25911+ .fin = au_wbr_create_fin_mfs
25912+ },
25913+ [AuWbrCreate_MFSRR] = {
25914+ .create = au_wbr_create_mfsrr,
25915+ .init = au_wbr_create_init_mfsrr,
25916+ .fin = au_wbr_create_fin_mfs
25917+ },
25918+ [AuWbrCreate_MFSRRV] = {
25919+ .create = au_wbr_create_mfsrr,
25920+ .init = au_wbr_create_init_mfsrr,
25921+ .fin = au_wbr_create_fin_mfs
25922+ },
25923+ [AuWbrCreate_PMFS] = {
25924+ .create = au_wbr_create_pmfs,
25925+ .init = au_wbr_create_init_mfs,
25926+ .fin = au_wbr_create_fin_mfs
25927+ },
25928+ [AuWbrCreate_PMFSV] = {
25929+ .create = au_wbr_create_pmfs,
25930+ .init = au_wbr_create_init_mfs,
25931+ .fin = au_wbr_create_fin_mfs
25932+ }
25933+};
7f207e10
AM
25934diff -urN /usr/share/empty/fs/aufs/whout.c linux/fs/aufs/whout.c
25935--- /usr/share/empty/fs/aufs/whout.c 1970-01-01 01:00:00.000000000 +0100
2cbb1c4b 25936+++ linux/fs/aufs/whout.c 2011-07-11 11:34:24.078331673 +0200
027c5e7a 25937@@ -0,0 +1,1062 @@
1facf9fc 25938+/*
027c5e7a 25939+ * Copyright (C) 2005-2011 Junjiro R. Okajima
1facf9fc 25940+ *
25941+ * This program, aufs is free software; you can redistribute it and/or modify
25942+ * it under the terms of the GNU General Public License as published by
25943+ * the Free Software Foundation; either version 2 of the License, or
25944+ * (at your option) any later version.
dece6358
AM
25945+ *
25946+ * This program is distributed in the hope that it will be useful,
25947+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
25948+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
25949+ * GNU General Public License for more details.
25950+ *
25951+ * You should have received a copy of the GNU General Public License
25952+ * along with this program; if not, write to the Free Software
25953+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 25954+ */
25955+
25956+/*
25957+ * whiteout for logical deletion and opaque directory
25958+ */
25959+
25960+#include <linux/fs.h>
25961+#include "aufs.h"
25962+
25963+#define WH_MASK S_IRUGO
25964+
25965+/*
25966+ * If a directory contains this file, then it is opaque. We start with the
25967+ * .wh. flag so that it is blocked by lookup.
25968+ */
25969+static struct qstr diropq_name = {
25970+ .name = AUFS_WH_DIROPQ,
25971+ .len = sizeof(AUFS_WH_DIROPQ) - 1
25972+};
25973+
25974+/*
25975+ * generate whiteout name, which is NOT terminated by NULL.
25976+ * @name: original d_name.name
25977+ * @len: original d_name.len
25978+ * @wh: whiteout qstr
25979+ * returns zero when succeeds, otherwise error.
25980+ * succeeded value as wh->name should be freed by kfree().
25981+ */
25982+int au_wh_name_alloc(struct qstr *wh, const struct qstr *name)
25983+{
25984+ char *p;
25985+
25986+ if (unlikely(name->len > PATH_MAX - AUFS_WH_PFX_LEN))
25987+ return -ENAMETOOLONG;
25988+
25989+ wh->len = name->len + AUFS_WH_PFX_LEN;
25990+ p = kmalloc(wh->len, GFP_NOFS);
25991+ wh->name = p;
25992+ if (p) {
25993+ memcpy(p, AUFS_WH_PFX, AUFS_WH_PFX_LEN);
25994+ memcpy(p + AUFS_WH_PFX_LEN, name->name, name->len);
25995+ /* smp_mb(); */
25996+ return 0;
25997+ }
25998+ return -ENOMEM;
25999+}
26000+
26001+/* ---------------------------------------------------------------------- */
26002+
26003+/*
26004+ * test if the @wh_name exists under @h_parent.
26005+ * @try_sio specifies the necessary of super-io.
26006+ */
26007+int au_wh_test(struct dentry *h_parent, struct qstr *wh_name,
26008+ struct au_branch *br, int try_sio)
26009+{
26010+ int err;
26011+ struct dentry *wh_dentry;
1facf9fc 26012+
1facf9fc 26013+ if (!try_sio)
26014+ wh_dentry = au_lkup_one(wh_name, h_parent, br, /*nd*/NULL);
26015+ else
26016+ wh_dentry = au_sio_lkup_one(wh_name, h_parent, br);
26017+ err = PTR_ERR(wh_dentry);
26018+ if (IS_ERR(wh_dentry))
26019+ goto out;
26020+
26021+ err = 0;
26022+ if (!wh_dentry->d_inode)
26023+ goto out_wh; /* success */
26024+
26025+ err = 1;
26026+ if (S_ISREG(wh_dentry->d_inode->i_mode))
26027+ goto out_wh; /* success */
26028+
26029+ err = -EIO;
26030+ AuIOErr("%.*s Invalid whiteout entry type 0%o.\n",
26031+ AuDLNPair(wh_dentry), wh_dentry->d_inode->i_mode);
26032+
4f0767ce 26033+out_wh:
1facf9fc 26034+ dput(wh_dentry);
4f0767ce 26035+out:
1facf9fc 26036+ return err;
26037+}
26038+
26039+/*
26040+ * test if the @h_dentry sets opaque or not.
26041+ */
26042+int au_diropq_test(struct dentry *h_dentry, struct au_branch *br)
26043+{
26044+ int err;
26045+ struct inode *h_dir;
26046+
26047+ h_dir = h_dentry->d_inode;
26048+ err = au_wh_test(h_dentry, &diropq_name, br,
26049+ au_test_h_perm_sio(h_dir, MAY_EXEC));
26050+ return err;
26051+}
26052+
26053+/*
26054+ * returns a negative dentry whose name is unique and temporary.
26055+ */
26056+struct dentry *au_whtmp_lkup(struct dentry *h_parent, struct au_branch *br,
26057+ struct qstr *prefix)
26058+{
1facf9fc 26059+ struct dentry *dentry;
26060+ int i;
027c5e7a 26061+ char defname[NAME_MAX - AUFS_MAX_NAMELEN + DNAME_INLINE_LEN + 1],
4a4d8108 26062+ *name, *p;
027c5e7a 26063+ /* strict atomic_t is unnecessary here */
1facf9fc 26064+ static unsigned short cnt;
26065+ struct qstr qs;
26066+
4a4d8108
AM
26067+ BUILD_BUG_ON(sizeof(cnt) * 2 > AUFS_WH_TMP_LEN);
26068+
1facf9fc 26069+ name = defname;
027c5e7a
AM
26070+ qs.len = sizeof(defname) - DNAME_INLINE_LEN + prefix->len - 1;
26071+ if (unlikely(prefix->len > DNAME_INLINE_LEN)) {
1facf9fc 26072+ dentry = ERR_PTR(-ENAMETOOLONG);
4a4d8108 26073+ if (unlikely(qs.len > NAME_MAX))
1facf9fc 26074+ goto out;
26075+ dentry = ERR_PTR(-ENOMEM);
26076+ name = kmalloc(qs.len + 1, GFP_NOFS);
26077+ if (unlikely(!name))
26078+ goto out;
26079+ }
26080+
26081+ /* doubly whiteout-ed */
26082+ memcpy(name, AUFS_WH_PFX AUFS_WH_PFX, AUFS_WH_PFX_LEN * 2);
26083+ p = name + AUFS_WH_PFX_LEN * 2;
26084+ memcpy(p, prefix->name, prefix->len);
26085+ p += prefix->len;
26086+ *p++ = '.';
4a4d8108 26087+ AuDebugOn(name + qs.len + 1 - p <= AUFS_WH_TMP_LEN);
1facf9fc 26088+
26089+ qs.name = name;
26090+ for (i = 0; i < 3; i++) {
b752ccd1 26091+ sprintf(p, "%.*x", AUFS_WH_TMP_LEN, cnt++);
1facf9fc 26092+ dentry = au_sio_lkup_one(&qs, h_parent, br);
26093+ if (IS_ERR(dentry) || !dentry->d_inode)
26094+ goto out_name;
26095+ dput(dentry);
26096+ }
4a4d8108 26097+ /* pr_warning("could not get random name\n"); */
1facf9fc 26098+ dentry = ERR_PTR(-EEXIST);
26099+ AuDbg("%.*s\n", AuLNPair(&qs));
26100+ BUG();
26101+
4f0767ce 26102+out_name:
1facf9fc 26103+ if (name != defname)
26104+ kfree(name);
4f0767ce 26105+out:
4a4d8108 26106+ AuTraceErrPtr(dentry);
1facf9fc 26107+ return dentry;
1facf9fc 26108+}
26109+
26110+/*
26111+ * rename the @h_dentry on @br to the whiteouted temporary name.
26112+ */
26113+int au_whtmp_ren(struct dentry *h_dentry, struct au_branch *br)
26114+{
26115+ int err;
26116+ struct path h_path = {
26117+ .mnt = br->br_mnt
26118+ };
26119+ struct inode *h_dir;
26120+ struct dentry *h_parent;
26121+
26122+ h_parent = h_dentry->d_parent; /* dir inode is locked */
26123+ h_dir = h_parent->d_inode;
26124+ IMustLock(h_dir);
26125+
26126+ h_path.dentry = au_whtmp_lkup(h_parent, br, &h_dentry->d_name);
26127+ err = PTR_ERR(h_path.dentry);
26128+ if (IS_ERR(h_path.dentry))
26129+ goto out;
26130+
26131+ /* under the same dir, no need to lock_rename() */
26132+ err = vfsub_rename(h_dir, h_dentry, h_dir, &h_path);
26133+ AuTraceErr(err);
26134+ dput(h_path.dentry);
26135+
4f0767ce 26136+out:
4a4d8108 26137+ AuTraceErr(err);
1facf9fc 26138+ return err;
26139+}
26140+
26141+/* ---------------------------------------------------------------------- */
26142+/*
26143+ * functions for removing a whiteout
26144+ */
26145+
26146+static int do_unlink_wh(struct inode *h_dir, struct path *h_path)
26147+{
26148+ int force;
26149+
26150+ /*
26151+ * forces superio when the dir has a sticky bit.
26152+ * this may be a violation of unix fs semantics.
26153+ */
26154+ force = (h_dir->i_mode & S_ISVTX)
26155+ && h_path->dentry->d_inode->i_uid != current_fsuid();
26156+ return vfsub_unlink(h_dir, h_path, force);
26157+}
26158+
26159+int au_wh_unlink_dentry(struct inode *h_dir, struct path *h_path,
26160+ struct dentry *dentry)
26161+{
26162+ int err;
26163+
26164+ err = do_unlink_wh(h_dir, h_path);
26165+ if (!err && dentry)
26166+ au_set_dbwh(dentry, -1);
26167+
26168+ return err;
26169+}
26170+
26171+static int unlink_wh_name(struct dentry *h_parent, struct qstr *wh,
26172+ struct au_branch *br)
26173+{
26174+ int err;
26175+ struct path h_path = {
26176+ .mnt = br->br_mnt
26177+ };
26178+
26179+ err = 0;
26180+ h_path.dentry = au_lkup_one(wh, h_parent, br, /*nd*/NULL);
26181+ if (IS_ERR(h_path.dentry))
26182+ err = PTR_ERR(h_path.dentry);
26183+ else {
26184+ if (h_path.dentry->d_inode
26185+ && S_ISREG(h_path.dentry->d_inode->i_mode))
26186+ err = do_unlink_wh(h_parent->d_inode, &h_path);
26187+ dput(h_path.dentry);
26188+ }
26189+
26190+ return err;
26191+}
26192+
26193+/* ---------------------------------------------------------------------- */
26194+/*
26195+ * initialize/clean whiteout for a branch
26196+ */
26197+
26198+static void au_wh_clean(struct inode *h_dir, struct path *whpath,
26199+ const int isdir)
26200+{
26201+ int err;
26202+
26203+ if (!whpath->dentry->d_inode)
26204+ return;
26205+
26206+ err = mnt_want_write(whpath->mnt);
26207+ if (!err) {
26208+ if (isdir)
26209+ err = vfsub_rmdir(h_dir, whpath);
26210+ else
26211+ err = vfsub_unlink(h_dir, whpath, /*force*/0);
26212+ mnt_drop_write(whpath->mnt);
26213+ }
26214+ if (unlikely(err))
4a4d8108
AM
26215+ pr_warning("failed removing %.*s (%d), ignored.\n",
26216+ AuDLNPair(whpath->dentry), err);
1facf9fc 26217+}
26218+
26219+static int test_linkable(struct dentry *h_root)
26220+{
26221+ struct inode *h_dir = h_root->d_inode;
26222+
26223+ if (h_dir->i_op->link)
26224+ return 0;
26225+
4a4d8108
AM
26226+ pr_err("%.*s (%s) doesn't support link(2), use noplink and rw+nolwh\n",
26227+ AuDLNPair(h_root), au_sbtype(h_root->d_sb));
1facf9fc 26228+ return -ENOSYS;
26229+}
26230+
26231+/* todo: should this mkdir be done in /sbin/mount.aufs helper? */
26232+static int au_whdir(struct inode *h_dir, struct path *path)
26233+{
26234+ int err;
26235+
26236+ err = -EEXIST;
26237+ if (!path->dentry->d_inode) {
26238+ int mode = S_IRWXU;
26239+
26240+ if (au_test_nfs(path->dentry->d_sb))
26241+ mode |= S_IXUGO;
26242+ err = mnt_want_write(path->mnt);
26243+ if (!err) {
26244+ err = vfsub_mkdir(h_dir, path, mode);
26245+ mnt_drop_write(path->mnt);
26246+ }
26247+ } else if (S_ISDIR(path->dentry->d_inode->i_mode))
26248+ err = 0;
26249+ else
4a4d8108 26250+ pr_err("unknown %.*s exists\n", AuDLNPair(path->dentry));
1facf9fc 26251+
26252+ return err;
26253+}
26254+
26255+struct au_wh_base {
26256+ const struct qstr *name;
26257+ struct dentry *dentry;
26258+};
26259+
26260+static void au_wh_init_ro(struct inode *h_dir, struct au_wh_base base[],
26261+ struct path *h_path)
26262+{
26263+ h_path->dentry = base[AuBrWh_BASE].dentry;
26264+ au_wh_clean(h_dir, h_path, /*isdir*/0);
26265+ h_path->dentry = base[AuBrWh_PLINK].dentry;
26266+ au_wh_clean(h_dir, h_path, /*isdir*/1);
26267+ h_path->dentry = base[AuBrWh_ORPH].dentry;
26268+ au_wh_clean(h_dir, h_path, /*isdir*/1);
26269+}
26270+
26271+/*
26272+ * returns tri-state,
26273+ * minus: error, caller should print the mesage
26274+ * zero: succuess
26275+ * plus: error, caller should NOT print the mesage
26276+ */
26277+static int au_wh_init_rw_nolink(struct dentry *h_root, struct au_wbr *wbr,
26278+ int do_plink, struct au_wh_base base[],
26279+ struct path *h_path)
26280+{
26281+ int err;
26282+ struct inode *h_dir;
26283+
26284+ h_dir = h_root->d_inode;
26285+ h_path->dentry = base[AuBrWh_BASE].dentry;
26286+ au_wh_clean(h_dir, h_path, /*isdir*/0);
26287+ h_path->dentry = base[AuBrWh_PLINK].dentry;
26288+ if (do_plink) {
26289+ err = test_linkable(h_root);
26290+ if (unlikely(err)) {
26291+ err = 1;
26292+ goto out;
26293+ }
26294+
26295+ err = au_whdir(h_dir, h_path);
26296+ if (unlikely(err))
26297+ goto out;
26298+ wbr->wbr_plink = dget(base[AuBrWh_PLINK].dentry);
26299+ } else
26300+ au_wh_clean(h_dir, h_path, /*isdir*/1);
26301+ h_path->dentry = base[AuBrWh_ORPH].dentry;
26302+ err = au_whdir(h_dir, h_path);
26303+ if (unlikely(err))
26304+ goto out;
26305+ wbr->wbr_orph = dget(base[AuBrWh_ORPH].dentry);
26306+
4f0767ce 26307+out:
1facf9fc 26308+ return err;
26309+}
26310+
26311+/*
26312+ * for the moment, aufs supports the branch filesystem which does not support
26313+ * link(2). testing on FAT which does not support i_op->setattr() fully either,
26314+ * copyup failed. finally, such filesystem will not be used as the writable
26315+ * branch.
26316+ *
26317+ * returns tri-state, see above.
26318+ */
26319+static int au_wh_init_rw(struct dentry *h_root, struct au_wbr *wbr,
26320+ int do_plink, struct au_wh_base base[],
26321+ struct path *h_path)
26322+{
26323+ int err;
26324+ struct inode *h_dir;
26325+
1308ab2a 26326+ WbrWhMustWriteLock(wbr);
26327+
1facf9fc 26328+ err = test_linkable(h_root);
26329+ if (unlikely(err)) {
26330+ err = 1;
26331+ goto out;
26332+ }
26333+
26334+ /*
26335+ * todo: should this create be done in /sbin/mount.aufs helper?
26336+ */
26337+ err = -EEXIST;
26338+ h_dir = h_root->d_inode;
26339+ if (!base[AuBrWh_BASE].dentry->d_inode) {
26340+ err = mnt_want_write(h_path->mnt);
26341+ if (!err) {
26342+ h_path->dentry = base[AuBrWh_BASE].dentry;
26343+ err = vfsub_create(h_dir, h_path, WH_MASK);
26344+ mnt_drop_write(h_path->mnt);
26345+ }
26346+ } else if (S_ISREG(base[AuBrWh_BASE].dentry->d_inode->i_mode))
26347+ err = 0;
26348+ else
4a4d8108
AM
26349+ pr_err("unknown %.*s/%.*s exists\n",
26350+ AuDLNPair(h_root), AuDLNPair(base[AuBrWh_BASE].dentry));
1facf9fc 26351+ if (unlikely(err))
26352+ goto out;
26353+
26354+ h_path->dentry = base[AuBrWh_PLINK].dentry;
26355+ if (do_plink) {
26356+ err = au_whdir(h_dir, h_path);
26357+ if (unlikely(err))
26358+ goto out;
26359+ wbr->wbr_plink = dget(base[AuBrWh_PLINK].dentry);
26360+ } else
26361+ au_wh_clean(h_dir, h_path, /*isdir*/1);
26362+ wbr->wbr_whbase = dget(base[AuBrWh_BASE].dentry);
26363+
26364+ h_path->dentry = base[AuBrWh_ORPH].dentry;
26365+ err = au_whdir(h_dir, h_path);
26366+ if (unlikely(err))
26367+ goto out;
26368+ wbr->wbr_orph = dget(base[AuBrWh_ORPH].dentry);
26369+
4f0767ce 26370+out:
1facf9fc 26371+ return err;
26372+}
26373+
26374+/*
26375+ * initialize the whiteout base file/dir for @br.
26376+ */
26377+int au_wh_init(struct dentry *h_root, struct au_branch *br,
26378+ struct super_block *sb)
26379+{
26380+ int err, i;
26381+ const unsigned char do_plink
26382+ = !!au_opt_test(au_mntflags(sb), PLINK);
26383+ struct path path = {
26384+ .mnt = br->br_mnt
26385+ };
26386+ struct inode *h_dir;
26387+ struct au_wbr *wbr = br->br_wbr;
26388+ static const struct qstr base_name[] = {
26389+ [AuBrWh_BASE] = {
26390+ .name = AUFS_BASE_NAME,
26391+ .len = sizeof(AUFS_BASE_NAME) - 1
26392+ },
26393+ [AuBrWh_PLINK] = {
26394+ .name = AUFS_PLINKDIR_NAME,
26395+ .len = sizeof(AUFS_PLINKDIR_NAME) - 1
26396+ },
26397+ [AuBrWh_ORPH] = {
26398+ .name = AUFS_ORPHDIR_NAME,
26399+ .len = sizeof(AUFS_ORPHDIR_NAME) - 1
26400+ }
26401+ };
26402+ struct au_wh_base base[] = {
26403+ [AuBrWh_BASE] = {
26404+ .name = base_name + AuBrWh_BASE,
26405+ .dentry = NULL
26406+ },
26407+ [AuBrWh_PLINK] = {
26408+ .name = base_name + AuBrWh_PLINK,
26409+ .dentry = NULL
26410+ },
26411+ [AuBrWh_ORPH] = {
26412+ .name = base_name + AuBrWh_ORPH,
26413+ .dentry = NULL
26414+ }
26415+ };
26416+
1308ab2a 26417+ if (wbr)
26418+ WbrWhMustWriteLock(wbr);
1facf9fc 26419+
1facf9fc 26420+ for (i = 0; i < AuBrWh_Last; i++) {
26421+ /* doubly whiteouted */
26422+ struct dentry *d;
26423+
26424+ d = au_wh_lkup(h_root, (void *)base[i].name, br);
26425+ err = PTR_ERR(d);
26426+ if (IS_ERR(d))
26427+ goto out;
26428+
26429+ base[i].dentry = d;
26430+ AuDebugOn(wbr
26431+ && wbr->wbr_wh[i]
26432+ && wbr->wbr_wh[i] != base[i].dentry);
26433+ }
26434+
26435+ if (wbr)
26436+ for (i = 0; i < AuBrWh_Last; i++) {
26437+ dput(wbr->wbr_wh[i]);
26438+ wbr->wbr_wh[i] = NULL;
26439+ }
26440+
26441+ err = 0;
1facf9fc 26442+ switch (br->br_perm) {
26443+ case AuBrPerm_RO:
26444+ case AuBrPerm_ROWH:
26445+ case AuBrPerm_RR:
26446+ case AuBrPerm_RRWH:
4a4d8108 26447+ h_dir = h_root->d_inode;
1facf9fc 26448+ au_wh_init_ro(h_dir, base, &path);
26449+ break;
26450+
26451+ case AuBrPerm_RWNoLinkWH:
26452+ err = au_wh_init_rw_nolink(h_root, wbr, do_plink, base, &path);
26453+ if (err > 0)
26454+ goto out;
26455+ else if (err)
26456+ goto out_err;
26457+ break;
26458+
26459+ case AuBrPerm_RW:
26460+ err = au_wh_init_rw(h_root, wbr, do_plink, base, &path);
26461+ if (err > 0)
26462+ goto out;
26463+ else if (err)
26464+ goto out_err;
26465+ break;
26466+
26467+ default:
26468+ BUG();
26469+ }
26470+ goto out; /* success */
26471+
4f0767ce 26472+out_err:
4a4d8108
AM
26473+ pr_err("an error(%d) on the writable branch %.*s(%s)\n",
26474+ err, AuDLNPair(h_root), au_sbtype(h_root->d_sb));
4f0767ce 26475+out:
1facf9fc 26476+ for (i = 0; i < AuBrWh_Last; i++)
26477+ dput(base[i].dentry);
26478+ return err;
26479+}
26480+
26481+/* ---------------------------------------------------------------------- */
26482+/*
26483+ * whiteouts are all hard-linked usually.
26484+ * when its link count reaches a ceiling, we create a new whiteout base
26485+ * asynchronously.
26486+ */
26487+
26488+struct reinit_br_wh {
26489+ struct super_block *sb;
26490+ struct au_branch *br;
26491+};
26492+
26493+static void reinit_br_wh(void *arg)
26494+{
26495+ int err;
26496+ aufs_bindex_t bindex;
26497+ struct path h_path;
26498+ struct reinit_br_wh *a = arg;
26499+ struct au_wbr *wbr;
26500+ struct inode *dir;
26501+ struct dentry *h_root;
26502+ struct au_hinode *hdir;
26503+
26504+ err = 0;
26505+ wbr = a->br->br_wbr;
26506+ /* big aufs lock */
26507+ si_noflush_write_lock(a->sb);
26508+ if (!au_br_writable(a->br->br_perm))
26509+ goto out;
26510+ bindex = au_br_index(a->sb, a->br->br_id);
26511+ if (unlikely(bindex < 0))
26512+ goto out;
26513+
1308ab2a 26514+ di_read_lock_parent(a->sb->s_root, AuLock_IR);
1facf9fc 26515+ dir = a->sb->s_root->d_inode;
1facf9fc 26516+ hdir = au_hi(dir, bindex);
26517+ h_root = au_h_dptr(a->sb->s_root, bindex);
26518+
4a4d8108 26519+ au_hn_imtx_lock_nested(hdir, AuLsc_I_PARENT);
1facf9fc 26520+ wbr_wh_write_lock(wbr);
26521+ err = au_h_verify(wbr->wbr_whbase, au_opt_udba(a->sb), hdir->hi_inode,
26522+ h_root, a->br);
26523+ if (!err) {
26524+ err = mnt_want_write(a->br->br_mnt);
26525+ if (!err) {
26526+ h_path.dentry = wbr->wbr_whbase;
26527+ h_path.mnt = a->br->br_mnt;
26528+ err = vfsub_unlink(hdir->hi_inode, &h_path, /*force*/0);
26529+ mnt_drop_write(a->br->br_mnt);
26530+ }
26531+ } else {
4a4d8108
AM
26532+ pr_warning("%.*s is moved, ignored\n",
26533+ AuDLNPair(wbr->wbr_whbase));
1facf9fc 26534+ err = 0;
26535+ }
26536+ dput(wbr->wbr_whbase);
26537+ wbr->wbr_whbase = NULL;
26538+ if (!err)
26539+ err = au_wh_init(h_root, a->br, a->sb);
26540+ wbr_wh_write_unlock(wbr);
4a4d8108 26541+ au_hn_imtx_unlock(hdir);
1308ab2a 26542+ di_read_unlock(a->sb->s_root, AuLock_IR);
1facf9fc 26543+
4f0767ce 26544+out:
1facf9fc 26545+ if (wbr)
26546+ atomic_dec(&wbr->wbr_wh_running);
26547+ atomic_dec(&a->br->br_count);
1facf9fc 26548+ si_write_unlock(a->sb);
027c5e7a 26549+ au_nwt_done(&au_sbi(a->sb)->si_nowait);
1facf9fc 26550+ kfree(arg);
26551+ if (unlikely(err))
26552+ AuIOErr("err %d\n", err);
26553+}
26554+
26555+static void kick_reinit_br_wh(struct super_block *sb, struct au_branch *br)
26556+{
26557+ int do_dec, wkq_err;
26558+ struct reinit_br_wh *arg;
26559+
26560+ do_dec = 1;
26561+ if (atomic_inc_return(&br->br_wbr->wbr_wh_running) != 1)
26562+ goto out;
26563+
26564+ /* ignore ENOMEM */
26565+ arg = kmalloc(sizeof(*arg), GFP_NOFS);
26566+ if (arg) {
26567+ /*
26568+ * dec(wh_running), kfree(arg) and dec(br_count)
26569+ * in reinit function
26570+ */
26571+ arg->sb = sb;
26572+ arg->br = br;
26573+ atomic_inc(&br->br_count);
26574+ wkq_err = au_wkq_nowait(reinit_br_wh, arg, sb);
26575+ if (unlikely(wkq_err)) {
26576+ atomic_dec(&br->br_wbr->wbr_wh_running);
26577+ atomic_dec(&br->br_count);
26578+ kfree(arg);
26579+ }
26580+ do_dec = 0;
26581+ }
26582+
4f0767ce 26583+out:
1facf9fc 26584+ if (do_dec)
26585+ atomic_dec(&br->br_wbr->wbr_wh_running);
26586+}
26587+
26588+/* ---------------------------------------------------------------------- */
26589+
26590+/*
26591+ * create the whiteout @wh.
26592+ */
26593+static int link_or_create_wh(struct super_block *sb, aufs_bindex_t bindex,
26594+ struct dentry *wh)
26595+{
26596+ int err;
26597+ struct path h_path = {
26598+ .dentry = wh
26599+ };
26600+ struct au_branch *br;
26601+ struct au_wbr *wbr;
26602+ struct dentry *h_parent;
26603+ struct inode *h_dir;
26604+
26605+ h_parent = wh->d_parent; /* dir inode is locked */
26606+ h_dir = h_parent->d_inode;
26607+ IMustLock(h_dir);
26608+
26609+ br = au_sbr(sb, bindex);
26610+ h_path.mnt = br->br_mnt;
26611+ wbr = br->br_wbr;
26612+ wbr_wh_read_lock(wbr);
26613+ if (wbr->wbr_whbase) {
26614+ err = vfsub_link(wbr->wbr_whbase, h_dir, &h_path);
26615+ if (!err || err != -EMLINK)
26616+ goto out;
26617+
26618+ /* link count full. re-initialize br_whbase. */
26619+ kick_reinit_br_wh(sb, br);
26620+ }
26621+
26622+ /* return this error in this context */
26623+ err = vfsub_create(h_dir, &h_path, WH_MASK);
26624+
4f0767ce 26625+out:
1facf9fc 26626+ wbr_wh_read_unlock(wbr);
26627+ return err;
26628+}
26629+
26630+/* ---------------------------------------------------------------------- */
26631+
26632+/*
26633+ * create or remove the diropq.
26634+ */
26635+static struct dentry *do_diropq(struct dentry *dentry, aufs_bindex_t bindex,
26636+ unsigned int flags)
26637+{
26638+ struct dentry *opq_dentry, *h_dentry;
26639+ struct super_block *sb;
26640+ struct au_branch *br;
26641+ int err;
26642+
26643+ sb = dentry->d_sb;
26644+ br = au_sbr(sb, bindex);
26645+ h_dentry = au_h_dptr(dentry, bindex);
26646+ opq_dentry = au_lkup_one(&diropq_name, h_dentry, br, /*nd*/NULL);
26647+ if (IS_ERR(opq_dentry))
26648+ goto out;
26649+
26650+ if (au_ftest_diropq(flags, CREATE)) {
26651+ err = link_or_create_wh(sb, bindex, opq_dentry);
26652+ if (!err) {
26653+ au_set_dbdiropq(dentry, bindex);
26654+ goto out; /* success */
26655+ }
26656+ } else {
26657+ struct path tmp = {
26658+ .dentry = opq_dentry,
26659+ .mnt = br->br_mnt
26660+ };
26661+ err = do_unlink_wh(au_h_iptr(dentry->d_inode, bindex), &tmp);
26662+ if (!err)
26663+ au_set_dbdiropq(dentry, -1);
26664+ }
26665+ dput(opq_dentry);
26666+ opq_dentry = ERR_PTR(err);
26667+
4f0767ce 26668+out:
1facf9fc 26669+ return opq_dentry;
26670+}
26671+
26672+struct do_diropq_args {
26673+ struct dentry **errp;
26674+ struct dentry *dentry;
26675+ aufs_bindex_t bindex;
26676+ unsigned int flags;
26677+};
26678+
26679+static void call_do_diropq(void *args)
26680+{
26681+ struct do_diropq_args *a = args;
26682+ *a->errp = do_diropq(a->dentry, a->bindex, a->flags);
26683+}
26684+
26685+struct dentry *au_diropq_sio(struct dentry *dentry, aufs_bindex_t bindex,
26686+ unsigned int flags)
26687+{
26688+ struct dentry *diropq, *h_dentry;
26689+
26690+ h_dentry = au_h_dptr(dentry, bindex);
26691+ if (!au_test_h_perm_sio(h_dentry->d_inode, MAY_EXEC | MAY_WRITE))
26692+ diropq = do_diropq(dentry, bindex, flags);
26693+ else {
26694+ int wkq_err;
26695+ struct do_diropq_args args = {
26696+ .errp = &diropq,
26697+ .dentry = dentry,
26698+ .bindex = bindex,
26699+ .flags = flags
26700+ };
26701+
26702+ wkq_err = au_wkq_wait(call_do_diropq, &args);
26703+ if (unlikely(wkq_err))
26704+ diropq = ERR_PTR(wkq_err);
26705+ }
26706+
26707+ return diropq;
26708+}
26709+
26710+/* ---------------------------------------------------------------------- */
26711+
26712+/*
26713+ * lookup whiteout dentry.
26714+ * @h_parent: lower parent dentry which must exist and be locked
26715+ * @base_name: name of dentry which will be whiteouted
26716+ * returns dentry for whiteout.
26717+ */
26718+struct dentry *au_wh_lkup(struct dentry *h_parent, struct qstr *base_name,
26719+ struct au_branch *br)
26720+{
26721+ int err;
26722+ struct qstr wh_name;
26723+ struct dentry *wh_dentry;
26724+
26725+ err = au_wh_name_alloc(&wh_name, base_name);
26726+ wh_dentry = ERR_PTR(err);
26727+ if (!err) {
26728+ wh_dentry = au_lkup_one(&wh_name, h_parent, br, /*nd*/NULL);
26729+ kfree(wh_name.name);
26730+ }
26731+ return wh_dentry;
26732+}
26733+
26734+/*
26735+ * link/create a whiteout for @dentry on @bindex.
26736+ */
26737+struct dentry *au_wh_create(struct dentry *dentry, aufs_bindex_t bindex,
26738+ struct dentry *h_parent)
26739+{
26740+ struct dentry *wh_dentry;
26741+ struct super_block *sb;
26742+ int err;
26743+
26744+ sb = dentry->d_sb;
26745+ wh_dentry = au_wh_lkup(h_parent, &dentry->d_name, au_sbr(sb, bindex));
26746+ if (!IS_ERR(wh_dentry) && !wh_dentry->d_inode) {
26747+ err = link_or_create_wh(sb, bindex, wh_dentry);
26748+ if (!err)
26749+ au_set_dbwh(dentry, bindex);
26750+ else {
26751+ dput(wh_dentry);
26752+ wh_dentry = ERR_PTR(err);
26753+ }
26754+ }
26755+
26756+ return wh_dentry;
26757+}
26758+
26759+/* ---------------------------------------------------------------------- */
26760+
26761+/* Delete all whiteouts in this directory on branch bindex. */
26762+static int del_wh_children(struct dentry *h_dentry, struct au_nhash *whlist,
26763+ aufs_bindex_t bindex, struct au_branch *br)
26764+{
26765+ int err;
26766+ unsigned long ul, n;
26767+ struct qstr wh_name;
26768+ char *p;
26769+ struct hlist_head *head;
26770+ struct au_vdir_wh *tpos;
26771+ struct hlist_node *pos;
26772+ struct au_vdir_destr *str;
26773+
26774+ err = -ENOMEM;
4a4d8108 26775+ p = __getname_gfp(GFP_NOFS);
1facf9fc 26776+ wh_name.name = p;
26777+ if (unlikely(!wh_name.name))
26778+ goto out;
26779+
26780+ err = 0;
26781+ memcpy(p, AUFS_WH_PFX, AUFS_WH_PFX_LEN);
26782+ p += AUFS_WH_PFX_LEN;
26783+ n = whlist->nh_num;
26784+ head = whlist->nh_head;
26785+ for (ul = 0; !err && ul < n; ul++, head++) {
26786+ hlist_for_each_entry(tpos, pos, head, wh_hash) {
26787+ if (tpos->wh_bindex != bindex)
26788+ continue;
26789+
26790+ str = &tpos->wh_str;
26791+ if (str->len + AUFS_WH_PFX_LEN <= PATH_MAX) {
26792+ memcpy(p, str->name, str->len);
26793+ wh_name.len = AUFS_WH_PFX_LEN + str->len;
26794+ err = unlink_wh_name(h_dentry, &wh_name, br);
26795+ if (!err)
26796+ continue;
26797+ break;
26798+ }
26799+ AuIOErr("whiteout name too long %.*s\n",
26800+ str->len, str->name);
26801+ err = -EIO;
26802+ break;
26803+ }
26804+ }
26805+ __putname(wh_name.name);
26806+
4f0767ce 26807+out:
1facf9fc 26808+ return err;
26809+}
26810+
26811+struct del_wh_children_args {
26812+ int *errp;
26813+ struct dentry *h_dentry;
1308ab2a 26814+ struct au_nhash *whlist;
1facf9fc 26815+ aufs_bindex_t bindex;
26816+ struct au_branch *br;
26817+};
26818+
26819+static void call_del_wh_children(void *args)
26820+{
26821+ struct del_wh_children_args *a = args;
1308ab2a 26822+ *a->errp = del_wh_children(a->h_dentry, a->whlist, a->bindex, a->br);
1facf9fc 26823+}
26824+
26825+/* ---------------------------------------------------------------------- */
26826+
26827+struct au_whtmp_rmdir *au_whtmp_rmdir_alloc(struct super_block *sb, gfp_t gfp)
26828+{
26829+ struct au_whtmp_rmdir *whtmp;
dece6358 26830+ int err;
1308ab2a 26831+ unsigned int rdhash;
dece6358
AM
26832+
26833+ SiMustAnyLock(sb);
1facf9fc 26834+
26835+ whtmp = kmalloc(sizeof(*whtmp), gfp);
dece6358
AM
26836+ if (unlikely(!whtmp)) {
26837+ whtmp = ERR_PTR(-ENOMEM);
1facf9fc 26838+ goto out;
dece6358 26839+ }
1facf9fc 26840+
26841+ whtmp->dir = NULL;
027c5e7a 26842+ whtmp->br = NULL;
1facf9fc 26843+ whtmp->wh_dentry = NULL;
1308ab2a 26844+ /* no estimation for dir size */
26845+ rdhash = au_sbi(sb)->si_rdhash;
26846+ if (!rdhash)
26847+ rdhash = AUFS_RDHASH_DEF;
26848+ err = au_nhash_alloc(&whtmp->whlist, rdhash, gfp);
26849+ if (unlikely(err)) {
26850+ kfree(whtmp);
26851+ whtmp = ERR_PTR(err);
26852+ }
dece6358 26853+
4f0767ce 26854+out:
dece6358 26855+ return whtmp;
1facf9fc 26856+}
26857+
26858+void au_whtmp_rmdir_free(struct au_whtmp_rmdir *whtmp)
26859+{
027c5e7a
AM
26860+ if (whtmp->br)
26861+ atomic_dec(&whtmp->br->br_count);
1facf9fc 26862+ dput(whtmp->wh_dentry);
26863+ iput(whtmp->dir);
dece6358 26864+ au_nhash_wh_free(&whtmp->whlist);
1facf9fc 26865+ kfree(whtmp);
26866+}
26867+
26868+/*
26869+ * rmdir the whiteouted temporary named dir @h_dentry.
26870+ * @whlist: whiteouted children.
26871+ */
26872+int au_whtmp_rmdir(struct inode *dir, aufs_bindex_t bindex,
26873+ struct dentry *wh_dentry, struct au_nhash *whlist)
26874+{
26875+ int err;
26876+ struct path h_tmp;
26877+ struct inode *wh_inode, *h_dir;
26878+ struct au_branch *br;
26879+
26880+ h_dir = wh_dentry->d_parent->d_inode; /* dir inode is locked */
26881+ IMustLock(h_dir);
26882+
26883+ br = au_sbr(dir->i_sb, bindex);
26884+ wh_inode = wh_dentry->d_inode;
26885+ mutex_lock_nested(&wh_inode->i_mutex, AuLsc_I_CHILD);
26886+
26887+ /*
26888+ * someone else might change some whiteouts while we were sleeping.
26889+ * it means this whlist may have an obsoleted entry.
26890+ */
26891+ if (!au_test_h_perm_sio(wh_inode, MAY_EXEC | MAY_WRITE))
26892+ err = del_wh_children(wh_dentry, whlist, bindex, br);
26893+ else {
26894+ int wkq_err;
26895+ struct del_wh_children_args args = {
26896+ .errp = &err,
26897+ .h_dentry = wh_dentry,
1308ab2a 26898+ .whlist = whlist,
1facf9fc 26899+ .bindex = bindex,
26900+ .br = br
26901+ };
26902+
26903+ wkq_err = au_wkq_wait(call_del_wh_children, &args);
26904+ if (unlikely(wkq_err))
26905+ err = wkq_err;
26906+ }
26907+ mutex_unlock(&wh_inode->i_mutex);
26908+
26909+ if (!err) {
26910+ h_tmp.dentry = wh_dentry;
26911+ h_tmp.mnt = br->br_mnt;
26912+ err = vfsub_rmdir(h_dir, &h_tmp);
1facf9fc 26913+ }
26914+
26915+ if (!err) {
26916+ if (au_ibstart(dir) == bindex) {
7f207e10 26917+ /* todo: dir->i_mutex is necessary */
1facf9fc 26918+ au_cpup_attr_timesizes(dir);
7f207e10 26919+ vfsub_drop_nlink(dir);
1facf9fc 26920+ }
26921+ return 0; /* success */
26922+ }
26923+
4a4d8108
AM
26924+ pr_warning("failed removing %.*s(%d), ignored\n",
26925+ AuDLNPair(wh_dentry), err);
1facf9fc 26926+ return err;
26927+}
26928+
26929+static void call_rmdir_whtmp(void *args)
26930+{
26931+ int err;
e49829fe 26932+ aufs_bindex_t bindex;
1facf9fc 26933+ struct au_whtmp_rmdir *a = args;
26934+ struct super_block *sb;
26935+ struct dentry *h_parent;
26936+ struct inode *h_dir;
1facf9fc 26937+ struct au_hinode *hdir;
26938+
26939+ /* rmdir by nfsd may cause deadlock with this i_mutex */
26940+ /* mutex_lock(&a->dir->i_mutex); */
e49829fe 26941+ err = -EROFS;
1facf9fc 26942+ sb = a->dir->i_sb;
e49829fe
JR
26943+ si_read_lock(sb, !AuLock_FLUSH);
26944+ if (!au_br_writable(a->br->br_perm))
26945+ goto out;
26946+ bindex = au_br_index(sb, a->br->br_id);
26947+ if (unlikely(bindex < 0))
1facf9fc 26948+ goto out;
26949+
26950+ err = -EIO;
1facf9fc 26951+ ii_write_lock_parent(a->dir);
26952+ h_parent = dget_parent(a->wh_dentry);
26953+ h_dir = h_parent->d_inode;
e49829fe 26954+ hdir = au_hi(a->dir, bindex);
4a4d8108 26955+ au_hn_imtx_lock_nested(hdir, AuLsc_I_PARENT);
e49829fe
JR
26956+ err = au_h_verify(a->wh_dentry, au_opt_udba(sb), h_dir, h_parent,
26957+ a->br);
1facf9fc 26958+ if (!err) {
e49829fe 26959+ err = mnt_want_write(a->br->br_mnt);
1facf9fc 26960+ if (!err) {
e49829fe 26961+ err = au_whtmp_rmdir(a->dir, bindex, a->wh_dentry,
dece6358 26962+ &a->whlist);
e49829fe 26963+ mnt_drop_write(a->br->br_mnt);
1facf9fc 26964+ }
26965+ }
4a4d8108 26966+ au_hn_imtx_unlock(hdir);
1facf9fc 26967+ dput(h_parent);
26968+ ii_write_unlock(a->dir);
26969+
4f0767ce 26970+out:
1facf9fc 26971+ /* mutex_unlock(&a->dir->i_mutex); */
1facf9fc 26972+ au_whtmp_rmdir_free(a);
027c5e7a
AM
26973+ si_read_unlock(sb);
26974+ au_nwt_done(&au_sbi(sb)->si_nowait);
1facf9fc 26975+ if (unlikely(err))
26976+ AuIOErr("err %d\n", err);
26977+}
26978+
26979+void au_whtmp_kick_rmdir(struct inode *dir, aufs_bindex_t bindex,
26980+ struct dentry *wh_dentry, struct au_whtmp_rmdir *args)
26981+{
26982+ int wkq_err;
e49829fe 26983+ struct super_block *sb;
1facf9fc 26984+
26985+ IMustLock(dir);
26986+
26987+ /* all post-process will be done in do_rmdir_whtmp(). */
e49829fe 26988+ sb = dir->i_sb;
1facf9fc 26989+ args->dir = au_igrab(dir);
e49829fe
JR
26990+ args->br = au_sbr(sb, bindex);
26991+ atomic_inc(&args->br->br_count);
1facf9fc 26992+ args->wh_dentry = dget(wh_dentry);
e49829fe 26993+ wkq_err = au_wkq_nowait(call_rmdir_whtmp, args, sb);
1facf9fc 26994+ if (unlikely(wkq_err)) {
4a4d8108
AM
26995+ pr_warning("rmdir error %.*s (%d), ignored\n",
26996+ AuDLNPair(wh_dentry), wkq_err);
1facf9fc 26997+ au_whtmp_rmdir_free(args);
26998+ }
26999+}
7f207e10
AM
27000diff -urN /usr/share/empty/fs/aufs/whout.h linux/fs/aufs/whout.h
27001--- /usr/share/empty/fs/aufs/whout.h 1970-01-01 01:00:00.000000000 +0100
2cbb1c4b 27002+++ linux/fs/aufs/whout.h 2011-07-11 11:34:24.078331673 +0200
7f207e10 27003@@ -0,0 +1,89 @@
1facf9fc 27004+/*
027c5e7a 27005+ * Copyright (C) 2005-2011 Junjiro R. Okajima
1facf9fc 27006+ *
27007+ * This program, aufs is free software; you can redistribute it and/or modify
27008+ * it under the terms of the GNU General Public License as published by
27009+ * the Free Software Foundation; either version 2 of the License, or
27010+ * (at your option) any later version.
dece6358
AM
27011+ *
27012+ * This program is distributed in the hope that it will be useful,
27013+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
27014+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
27015+ * GNU General Public License for more details.
27016+ *
27017+ * You should have received a copy of the GNU General Public License
27018+ * along with this program; if not, write to the Free Software
27019+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 27020+ */
27021+
27022+/*
27023+ * whiteout for logical deletion and opaque directory
27024+ */
27025+
27026+#ifndef __AUFS_WHOUT_H__
27027+#define __AUFS_WHOUT_H__
27028+
27029+#ifdef __KERNEL__
27030+
1facf9fc 27031+#include <linux/aufs_type.h>
27032+#include "dir.h"
27033+
27034+/* whout.c */
27035+int au_wh_name_alloc(struct qstr *wh, const struct qstr *name);
27036+struct au_branch;
27037+int au_wh_test(struct dentry *h_parent, struct qstr *wh_name,
27038+ struct au_branch *br, int try_sio);
27039+int au_diropq_test(struct dentry *h_dentry, struct au_branch *br);
27040+struct dentry *au_whtmp_lkup(struct dentry *h_parent, struct au_branch *br,
27041+ struct qstr *prefix);
27042+int au_whtmp_ren(struct dentry *h_dentry, struct au_branch *br);
27043+int au_wh_unlink_dentry(struct inode *h_dir, struct path *h_path,
27044+ struct dentry *dentry);
27045+int au_wh_init(struct dentry *h_parent, struct au_branch *br,
27046+ struct super_block *sb);
27047+
27048+/* diropq flags */
27049+#define AuDiropq_CREATE 1
27050+#define au_ftest_diropq(flags, name) ((flags) & AuDiropq_##name)
7f207e10
AM
27051+#define au_fset_diropq(flags, name) \
27052+ do { (flags) |= AuDiropq_##name; } while (0)
27053+#define au_fclr_diropq(flags, name) \
27054+ do { (flags) &= ~AuDiropq_##name; } while (0)
1facf9fc 27055+
27056+struct dentry *au_diropq_sio(struct dentry *dentry, aufs_bindex_t bindex,
27057+ unsigned int flags);
27058+struct dentry *au_wh_lkup(struct dentry *h_parent, struct qstr *base_name,
27059+ struct au_branch *br);
27060+struct dentry *au_wh_create(struct dentry *dentry, aufs_bindex_t bindex,
27061+ struct dentry *h_parent);
27062+
27063+/* real rmdir for the whiteout-ed dir */
27064+struct au_whtmp_rmdir {
27065+ struct inode *dir;
e49829fe 27066+ struct au_branch *br;
1facf9fc 27067+ struct dentry *wh_dentry;
dece6358 27068+ struct au_nhash whlist;
1facf9fc 27069+};
27070+
27071+struct au_whtmp_rmdir *au_whtmp_rmdir_alloc(struct super_block *sb, gfp_t gfp);
27072+void au_whtmp_rmdir_free(struct au_whtmp_rmdir *whtmp);
27073+int au_whtmp_rmdir(struct inode *dir, aufs_bindex_t bindex,
27074+ struct dentry *wh_dentry, struct au_nhash *whlist);
27075+void au_whtmp_kick_rmdir(struct inode *dir, aufs_bindex_t bindex,
27076+ struct dentry *wh_dentry, struct au_whtmp_rmdir *args);
27077+
27078+/* ---------------------------------------------------------------------- */
27079+
27080+static inline struct dentry *au_diropq_create(struct dentry *dentry,
27081+ aufs_bindex_t bindex)
27082+{
27083+ return au_diropq_sio(dentry, bindex, AuDiropq_CREATE);
27084+}
27085+
27086+static inline int au_diropq_remove(struct dentry *dentry, aufs_bindex_t bindex)
27087+{
27088+ return PTR_ERR(au_diropq_sio(dentry, bindex, !AuDiropq_CREATE));
27089+}
27090+
27091+#endif /* __KERNEL__ */
27092+#endif /* __AUFS_WHOUT_H__ */
7f207e10
AM
27093diff -urN /usr/share/empty/fs/aufs/wkq.c linux/fs/aufs/wkq.c
27094--- /usr/share/empty/fs/aufs/wkq.c 1970-01-01 01:00:00.000000000 +0100
2cbb1c4b 27095+++ linux/fs/aufs/wkq.c 2011-07-11 11:34:24.079331673 +0200
027c5e7a 27096@@ -0,0 +1,236 @@
1facf9fc 27097+/*
027c5e7a 27098+ * Copyright (C) 2005-2011 Junjiro R. Okajima
1facf9fc 27099+ *
27100+ * This program, aufs is free software; you can redistribute it and/or modify
27101+ * it under the terms of the GNU General Public License as published by
27102+ * the Free Software Foundation; either version 2 of the License, or
27103+ * (at your option) any later version.
dece6358
AM
27104+ *
27105+ * This program is distributed in the hope that it will be useful,
27106+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
27107+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
27108+ * GNU General Public License for more details.
27109+ *
27110+ * You should have received a copy of the GNU General Public License
27111+ * along with this program; if not, write to the Free Software
27112+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 27113+ */
27114+
27115+/*
27116+ * workqueue for asynchronous/super-io operations
27117+ * todo: try new dredential scheme
27118+ */
27119+
dece6358 27120+#include <linux/module.h>
1facf9fc 27121+#include "aufs.h"
27122+
b752ccd1
AM
27123+/* internal workqueue named AUFS_WKQ_NAME and AUFS_WKQ_PRE_NAME */
27124+enum {
27125+ AuWkq_INORMAL,
27126+ AuWkq_IPRE
27127+};
27128+
27129+static struct {
27130+ char *name;
27131+ struct workqueue_struct *wkq;
27132+} au_wkq[] = {
27133+ [AuWkq_INORMAL] = {
27134+ .name = AUFS_WKQ_NAME
27135+ },
27136+ [AuWkq_IPRE] = {
27137+ .name = AUFS_WKQ_PRE_NAME
27138+ }
27139+};
1facf9fc 27140+
27141+struct au_wkinfo {
27142+ struct work_struct wk;
7f207e10 27143+ struct kobject *kobj;
1facf9fc 27144+
27145+ unsigned int flags; /* see wkq.h */
27146+
27147+ au_wkq_func_t func;
27148+ void *args;
27149+
1facf9fc 27150+ struct completion *comp;
27151+};
27152+
27153+/* ---------------------------------------------------------------------- */
27154+
1facf9fc 27155+static void wkq_func(struct work_struct *wk)
27156+{
27157+ struct au_wkinfo *wkinfo = container_of(wk, struct au_wkinfo, wk);
27158+
7f207e10
AM
27159+ AuDebugOn(current_fsuid());
27160+ AuDebugOn(rlimit(RLIMIT_FSIZE) != RLIM_INFINITY);
27161+
1facf9fc 27162+ wkinfo->func(wkinfo->args);
1facf9fc 27163+ if (au_ftest_wkq(wkinfo->flags, WAIT))
27164+ complete(wkinfo->comp);
27165+ else {
7f207e10 27166+ kobject_put(wkinfo->kobj);
1facf9fc 27167+ module_put(THIS_MODULE);
27168+ kfree(wkinfo);
27169+ }
27170+}
27171+
27172+/*
27173+ * Since struct completion is large, try allocating it dynamically.
27174+ */
27175+#if defined(CONFIG_4KSTACKS) || defined(AuTest4KSTACKS)
27176+#define AuWkqCompDeclare(name) struct completion *comp = NULL
27177+
27178+static int au_wkq_comp_alloc(struct au_wkinfo *wkinfo, struct completion **comp)
27179+{
27180+ *comp = kmalloc(sizeof(**comp), GFP_NOFS);
27181+ if (*comp) {
27182+ init_completion(*comp);
27183+ wkinfo->comp = *comp;
27184+ return 0;
27185+ }
27186+ return -ENOMEM;
27187+}
27188+
27189+static void au_wkq_comp_free(struct completion *comp)
27190+{
27191+ kfree(comp);
27192+}
27193+
27194+#else
27195+
27196+/* no braces */
27197+#define AuWkqCompDeclare(name) \
27198+ DECLARE_COMPLETION_ONSTACK(_ ## name); \
27199+ struct completion *comp = &_ ## name
27200+
27201+static int au_wkq_comp_alloc(struct au_wkinfo *wkinfo, struct completion **comp)
27202+{
27203+ wkinfo->comp = *comp;
27204+ return 0;
27205+}
27206+
27207+static void au_wkq_comp_free(struct completion *comp __maybe_unused)
27208+{
27209+ /* empty */
27210+}
27211+#endif /* 4KSTACKS */
27212+
b752ccd1 27213+static void au_wkq_run(struct au_wkinfo *wkinfo, unsigned int flags)
1facf9fc 27214+{
b752ccd1
AM
27215+ struct workqueue_struct *wkq;
27216+
1facf9fc 27217+ au_dbg_verify_kthread();
b752ccd1 27218+ if (flags & AuWkq_WAIT) {
a1f66529 27219+ INIT_WORK_ONSTACK(&wkinfo->wk, wkq_func);
b752ccd1
AM
27220+ wkq = au_wkq[AuWkq_INORMAL].wkq;
27221+ if (flags & AuWkq_PRE)
27222+ wkq = au_wkq[AuWkq_IPRE].wkq;
27223+ queue_work(wkq, &wkinfo->wk);
4a4d8108
AM
27224+ } else {
27225+ INIT_WORK(&wkinfo->wk, wkq_func);
27226+ schedule_work(&wkinfo->wk);
27227+ }
1facf9fc 27228+}
27229+
7f207e10
AM
27230+/*
27231+ * Be careful. It is easy to make deadlock happen.
27232+ * processA: lock, wkq and wait
27233+ * processB: wkq and wait, lock in wkq
27234+ * --> deadlock
27235+ */
b752ccd1 27236+int au_wkq_do_wait(unsigned int flags, au_wkq_func_t func, void *args)
1facf9fc 27237+{
27238+ int err;
27239+ AuWkqCompDeclare(comp);
27240+ struct au_wkinfo wkinfo = {
b752ccd1 27241+ .flags = flags,
1facf9fc 27242+ .func = func,
27243+ .args = args
27244+ };
27245+
27246+ err = au_wkq_comp_alloc(&wkinfo, &comp);
27247+ if (!err) {
b752ccd1 27248+ au_wkq_run(&wkinfo, flags);
1facf9fc 27249+ /* no timeout, no interrupt */
27250+ wait_for_completion(wkinfo.comp);
27251+ au_wkq_comp_free(comp);
4a4d8108 27252+ destroy_work_on_stack(&wkinfo.wk);
1facf9fc 27253+ }
27254+
27255+ return err;
27256+
27257+}
27258+
027c5e7a
AM
27259+/*
27260+ * Note: dget/dput() in func for aufs dentries are not supported. It will be a
27261+ * problem in a concurrent umounting.
27262+ */
1facf9fc 27263+int au_wkq_nowait(au_wkq_func_t func, void *args, struct super_block *sb)
27264+{
27265+ int err;
27266+ struct au_wkinfo *wkinfo;
27267+
27268+ atomic_inc(&au_sbi(sb)->si_nowait.nw_len);
27269+
27270+ /*
27271+ * wkq_func() must free this wkinfo.
27272+ * it highly depends upon the implementation of workqueue.
27273+ */
27274+ err = 0;
27275+ wkinfo = kmalloc(sizeof(*wkinfo), GFP_NOFS);
27276+ if (wkinfo) {
7f207e10 27277+ wkinfo->kobj = &au_sbi(sb)->si_kobj;
1facf9fc 27278+ wkinfo->flags = !AuWkq_WAIT;
27279+ wkinfo->func = func;
27280+ wkinfo->args = args;
27281+ wkinfo->comp = NULL;
7f207e10 27282+ kobject_get(wkinfo->kobj);
1facf9fc 27283+ __module_get(THIS_MODULE);
27284+
4a4d8108 27285+ au_wkq_run(wkinfo, !AuWkq_WAIT);
1facf9fc 27286+ } else {
27287+ err = -ENOMEM;
e49829fe 27288+ au_nwt_done(&au_sbi(sb)->si_nowait);
1facf9fc 27289+ }
27290+
27291+ return err;
27292+}
27293+
27294+/* ---------------------------------------------------------------------- */
27295+
27296+void au_nwt_init(struct au_nowait_tasks *nwt)
27297+{
27298+ atomic_set(&nwt->nw_len, 0);
4a4d8108 27299+ /* smp_mb(); */ /* atomic_set */
1facf9fc 27300+ init_waitqueue_head(&nwt->nw_wq);
27301+}
27302+
27303+void au_wkq_fin(void)
27304+{
b752ccd1
AM
27305+ int i;
27306+
27307+ for (i = 0; i < ARRAY_SIZE(au_wkq); i++)
27308+ if (au_wkq[i].wkq)
27309+ destroy_workqueue(au_wkq[i].wkq);
1facf9fc 27310+}
27311+
27312+int __init au_wkq_init(void)
27313+{
b752ccd1
AM
27314+ int err, i;
27315+
27316+ err = 0;
27317+ for (i = 0; !err && i < ARRAY_SIZE(au_wkq); i++) {
7f207e10
AM
27318+ BUILD_BUG_ON(!WQ_RESCUER);
27319+ au_wkq[i].wkq = alloc_workqueue(au_wkq[i].name, !WQ_RESCUER,
27320+ WQ_DFL_ACTIVE);
b752ccd1
AM
27321+ if (IS_ERR(au_wkq[i].wkq))
27322+ err = PTR_ERR(au_wkq[i].wkq);
27323+ else if (!au_wkq[i].wkq)
27324+ err = -ENOMEM;
27325+ if (unlikely(err))
27326+ au_wkq[i].wkq = NULL;
27327+ }
7f207e10 27328+ if (unlikely(err))
b752ccd1
AM
27329+ au_wkq_fin();
27330+
27331+ return err;
1facf9fc 27332+}
7f207e10
AM
27333diff -urN /usr/share/empty/fs/aufs/wkq.h linux/fs/aufs/wkq.h
27334--- /usr/share/empty/fs/aufs/wkq.h 1970-01-01 01:00:00.000000000 +0100
2cbb1c4b 27335+++ linux/fs/aufs/wkq.h 2011-07-11 11:34:24.079331673 +0200
7f207e10 27336@@ -0,0 +1,90 @@
1facf9fc 27337+/*
027c5e7a 27338+ * Copyright (C) 2005-2011 Junjiro R. Okajima
1facf9fc 27339+ *
27340+ * This program, aufs is free software; you can redistribute it and/or modify
27341+ * it under the terms of the GNU General Public License as published by
27342+ * the Free Software Foundation; either version 2 of the License, or
27343+ * (at your option) any later version.
dece6358
AM
27344+ *
27345+ * This program is distributed in the hope that it will be useful,
27346+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
27347+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
27348+ * GNU General Public License for more details.
27349+ *
27350+ * You should have received a copy of the GNU General Public License
27351+ * along with this program; if not, write to the Free Software
27352+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 27353+ */
27354+
27355+/*
27356+ * workqueue for asynchronous/super-io operations
27357+ * todo: try new credentials management scheme
27358+ */
27359+
27360+#ifndef __AUFS_WKQ_H__
27361+#define __AUFS_WKQ_H__
27362+
27363+#ifdef __KERNEL__
27364+
1facf9fc 27365+#include <linux/sched.h>
dece6358 27366+#include <linux/wait.h>
1facf9fc 27367+#include <linux/aufs_type.h>
27368+
dece6358
AM
27369+struct super_block;
27370+
1facf9fc 27371+/* ---------------------------------------------------------------------- */
27372+
27373+/*
27374+ * in the next operation, wait for the 'nowait' tasks in system-wide workqueue
27375+ */
27376+struct au_nowait_tasks {
27377+ atomic_t nw_len;
27378+ wait_queue_head_t nw_wq;
27379+};
27380+
27381+/* ---------------------------------------------------------------------- */
27382+
27383+typedef void (*au_wkq_func_t)(void *args);
27384+
27385+/* wkq flags */
27386+#define AuWkq_WAIT 1
b752ccd1 27387+#define AuWkq_PRE (1 << 1)
1facf9fc 27388+#define au_ftest_wkq(flags, name) ((flags) & AuWkq_##name)
7f207e10
AM
27389+#define au_fset_wkq(flags, name) \
27390+ do { (flags) |= AuWkq_##name; } while (0)
27391+#define au_fclr_wkq(flags, name) \
27392+ do { (flags) &= ~AuWkq_##name; } while (0)
1facf9fc 27393+
27394+/* wkq.c */
b752ccd1 27395+int au_wkq_do_wait(unsigned int flags, au_wkq_func_t func, void *args);
1facf9fc 27396+int au_wkq_nowait(au_wkq_func_t func, void *args, struct super_block *sb);
27397+void au_nwt_init(struct au_nowait_tasks *nwt);
27398+int __init au_wkq_init(void);
27399+void au_wkq_fin(void);
27400+
27401+/* ---------------------------------------------------------------------- */
27402+
b752ccd1
AM
27403+static inline int au_wkq_wait_pre(au_wkq_func_t func, void *args)
27404+{
27405+ return au_wkq_do_wait(AuWkq_WAIT | AuWkq_PRE, func, args);
27406+}
27407+
27408+static inline int au_wkq_wait(au_wkq_func_t func, void *args)
1facf9fc 27409+{
b752ccd1 27410+ return au_wkq_do_wait(AuWkq_WAIT, func, args);
1facf9fc 27411+}
27412+
27413+static inline void au_nwt_done(struct au_nowait_tasks *nwt)
27414+{
e49829fe 27415+ if (atomic_dec_and_test(&nwt->nw_len))
1facf9fc 27416+ wake_up_all(&nwt->nw_wq);
27417+}
27418+
27419+static inline int au_nwt_flush(struct au_nowait_tasks *nwt)
27420+{
27421+ wait_event(nwt->nw_wq, !atomic_read(&nwt->nw_len));
27422+ return 0;
27423+}
27424+
27425+#endif /* __KERNEL__ */
27426+#endif /* __AUFS_WKQ_H__ */
7f207e10
AM
27427diff -urN /usr/share/empty/fs/aufs/xino.c linux/fs/aufs/xino.c
27428--- /usr/share/empty/fs/aufs/xino.c 1970-01-01 01:00:00.000000000 +0100
2cbb1c4b 27429+++ linux/fs/aufs/xino.c 2011-07-11 11:34:24.079331673 +0200
7f207e10 27430@@ -0,0 +1,1265 @@
1facf9fc 27431+/*
027c5e7a 27432+ * Copyright (C) 2005-2011 Junjiro R. Okajima
1facf9fc 27433+ *
27434+ * This program, aufs is free software; you can redistribute it and/or modify
27435+ * it under the terms of the GNU General Public License as published by
27436+ * the Free Software Foundation; either version 2 of the License, or
27437+ * (at your option) any later version.
dece6358
AM
27438+ *
27439+ * This program is distributed in the hope that it will be useful,
27440+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
27441+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
27442+ * GNU General Public License for more details.
27443+ *
27444+ * You should have received a copy of the GNU General Public License
27445+ * along with this program; if not, write to the Free Software
27446+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 27447+ */
27448+
27449+/*
27450+ * external inode number translation table and bitmap
27451+ */
27452+
dece6358 27453+#include <linux/file.h>
1facf9fc 27454+#include <linux/seq_file.h>
27455+#include <linux/uaccess.h>
27456+#include "aufs.h"
27457+
b752ccd1 27458+ssize_t xino_fread(au_readf_t func, struct file *file, void *kbuf, size_t size,
1facf9fc 27459+ loff_t *pos)
27460+{
27461+ ssize_t err;
27462+ mm_segment_t oldfs;
b752ccd1
AM
27463+ union {
27464+ void *k;
27465+ char __user *u;
27466+ } buf;
1facf9fc 27467+
b752ccd1 27468+ buf.k = kbuf;
1facf9fc 27469+ oldfs = get_fs();
27470+ set_fs(KERNEL_DS);
27471+ do {
27472+ /* todo: signal_pending? */
b752ccd1 27473+ err = func(file, buf.u, size, pos);
1facf9fc 27474+ } while (err == -EAGAIN || err == -EINTR);
27475+ set_fs(oldfs);
27476+
27477+#if 0 /* reserved for future use */
27478+ if (err > 0)
27479+ fsnotify_access(file->f_dentry);
27480+#endif
27481+
27482+ return err;
27483+}
27484+
27485+/* ---------------------------------------------------------------------- */
27486+
b752ccd1 27487+static ssize_t do_xino_fwrite(au_writef_t func, struct file *file, void *kbuf,
1facf9fc 27488+ size_t size, loff_t *pos)
27489+{
27490+ ssize_t err;
27491+ mm_segment_t oldfs;
b752ccd1
AM
27492+ union {
27493+ void *k;
27494+ const char __user *u;
27495+ } buf;
1facf9fc 27496+
b752ccd1 27497+ buf.k = kbuf;
1facf9fc 27498+ oldfs = get_fs();
27499+ set_fs(KERNEL_DS);
1facf9fc 27500+ do {
27501+ /* todo: signal_pending? */
b752ccd1 27502+ err = func(file, buf.u, size, pos);
1facf9fc 27503+ } while (err == -EAGAIN || err == -EINTR);
1facf9fc 27504+ set_fs(oldfs);
27505+
27506+#if 0 /* reserved for future use */
27507+ if (err > 0)
27508+ fsnotify_modify(file->f_dentry);
27509+#endif
27510+
27511+ return err;
27512+}
27513+
27514+struct do_xino_fwrite_args {
27515+ ssize_t *errp;
27516+ au_writef_t func;
27517+ struct file *file;
27518+ void *buf;
27519+ size_t size;
27520+ loff_t *pos;
27521+};
27522+
27523+static void call_do_xino_fwrite(void *args)
27524+{
27525+ struct do_xino_fwrite_args *a = args;
27526+ *a->errp = do_xino_fwrite(a->func, a->file, a->buf, a->size, a->pos);
27527+}
27528+
27529+ssize_t xino_fwrite(au_writef_t func, struct file *file, void *buf, size_t size,
27530+ loff_t *pos)
27531+{
27532+ ssize_t err;
27533+
27534+ /* todo: signal block and no wkq? */
b752ccd1
AM
27535+ if (rlimit(RLIMIT_FSIZE) == RLIM_INFINITY) {
27536+ lockdep_off();
27537+ err = do_xino_fwrite(func, file, buf, size, pos);
27538+ lockdep_on();
27539+ } else {
27540+ /*
27541+ * it breaks RLIMIT_FSIZE and normal user's limit,
27542+ * users should care about quota and real 'filesystem full.'
27543+ */
1facf9fc 27544+ int wkq_err;
27545+ struct do_xino_fwrite_args args = {
27546+ .errp = &err,
27547+ .func = func,
27548+ .file = file,
27549+ .buf = buf,
27550+ .size = size,
27551+ .pos = pos
27552+ };
27553+
27554+ wkq_err = au_wkq_wait(call_do_xino_fwrite, &args);
27555+ if (unlikely(wkq_err))
27556+ err = wkq_err;
b752ccd1 27557+ }
1facf9fc 27558+
27559+ return err;
27560+}
27561+
27562+/* ---------------------------------------------------------------------- */
27563+
27564+/*
27565+ * create a new xinofile at the same place/path as @base_file.
27566+ */
27567+struct file *au_xino_create2(struct file *base_file, struct file *copy_src)
27568+{
27569+ struct file *file;
4a4d8108 27570+ struct dentry *base, *parent;
1facf9fc 27571+ struct inode *dir;
27572+ struct qstr *name;
1308ab2a 27573+ struct path path;
4a4d8108 27574+ int err;
1facf9fc 27575+
27576+ base = base_file->f_dentry;
27577+ parent = base->d_parent; /* dir inode is locked */
27578+ dir = parent->d_inode;
27579+ IMustLock(dir);
27580+
27581+ file = ERR_PTR(-EINVAL);
27582+ name = &base->d_name;
4a4d8108
AM
27583+ path.dentry = vfsub_lookup_one_len(name->name, parent, name->len);
27584+ if (IS_ERR(path.dentry)) {
27585+ file = (void *)path.dentry;
27586+ pr_err("%.*s lookup err %ld\n",
27587+ AuLNPair(name), PTR_ERR(path.dentry));
1facf9fc 27588+ goto out;
27589+ }
27590+
27591+ /* no need to mnt_want_write() since we call dentry_open() later */
4a4d8108 27592+ err = vfs_create(dir, path.dentry, S_IRUGO | S_IWUGO, NULL);
1facf9fc 27593+ if (unlikely(err)) {
27594+ file = ERR_PTR(err);
4a4d8108 27595+ pr_err("%.*s create err %d\n", AuLNPair(name), err);
1facf9fc 27596+ goto out_dput;
27597+ }
27598+
1308ab2a 27599+ path.mnt = base_file->f_vfsmnt;
4a4d8108 27600+ file = vfsub_dentry_open(&path,
7f207e10 27601+ O_RDWR | O_CREAT | O_EXCL | O_LARGEFILE
2cbb1c4b 27602+ /* | __FMODE_NONOTIFY */);
1facf9fc 27603+ if (IS_ERR(file)) {
4a4d8108 27604+ pr_err("%.*s open err %ld\n", AuLNPair(name), PTR_ERR(file));
1facf9fc 27605+ goto out_dput;
27606+ }
27607+
27608+ err = vfsub_unlink(dir, &file->f_path, /*force*/0);
27609+ if (unlikely(err)) {
4a4d8108 27610+ pr_err("%.*s unlink err %d\n", AuLNPair(name), err);
1facf9fc 27611+ goto out_fput;
27612+ }
27613+
27614+ if (copy_src) {
27615+ /* no one can touch copy_src xino */
27616+ err = au_copy_file(file, copy_src,
27617+ i_size_read(copy_src->f_dentry->d_inode));
27618+ if (unlikely(err)) {
4a4d8108 27619+ pr_err("%.*s copy err %d\n", AuLNPair(name), err);
1facf9fc 27620+ goto out_fput;
27621+ }
27622+ }
27623+ goto out_dput; /* success */
27624+
4f0767ce 27625+out_fput:
1facf9fc 27626+ fput(file);
27627+ file = ERR_PTR(err);
4f0767ce 27628+out_dput:
4a4d8108 27629+ dput(path.dentry);
4f0767ce 27630+out:
1facf9fc 27631+ return file;
27632+}
27633+
27634+struct au_xino_lock_dir {
27635+ struct au_hinode *hdir;
27636+ struct dentry *parent;
27637+ struct mutex *mtx;
27638+};
27639+
27640+static void au_xino_lock_dir(struct super_block *sb, struct file *xino,
27641+ struct au_xino_lock_dir *ldir)
27642+{
27643+ aufs_bindex_t brid, bindex;
27644+
27645+ ldir->hdir = NULL;
27646+ bindex = -1;
27647+ brid = au_xino_brid(sb);
27648+ if (brid >= 0)
27649+ bindex = au_br_index(sb, brid);
27650+ if (bindex >= 0) {
27651+ ldir->hdir = au_hi(sb->s_root->d_inode, bindex);
4a4d8108 27652+ au_hn_imtx_lock_nested(ldir->hdir, AuLsc_I_PARENT);
1facf9fc 27653+ } else {
27654+ ldir->parent = dget_parent(xino->f_dentry);
27655+ ldir->mtx = &ldir->parent->d_inode->i_mutex;
27656+ mutex_lock_nested(ldir->mtx, AuLsc_I_PARENT);
27657+ }
27658+}
27659+
27660+static void au_xino_unlock_dir(struct au_xino_lock_dir *ldir)
27661+{
27662+ if (ldir->hdir)
4a4d8108 27663+ au_hn_imtx_unlock(ldir->hdir);
1facf9fc 27664+ else {
27665+ mutex_unlock(ldir->mtx);
27666+ dput(ldir->parent);
27667+ }
27668+}
27669+
27670+/* ---------------------------------------------------------------------- */
27671+
27672+/* trucate xino files asynchronously */
27673+
27674+int au_xino_trunc(struct super_block *sb, aufs_bindex_t bindex)
27675+{
27676+ int err;
27677+ aufs_bindex_t bi, bend;
27678+ struct au_branch *br;
27679+ struct file *new_xino, *file;
27680+ struct super_block *h_sb;
27681+ struct au_xino_lock_dir ldir;
27682+
27683+ err = -EINVAL;
27684+ bend = au_sbend(sb);
27685+ if (unlikely(bindex < 0 || bend < bindex))
27686+ goto out;
27687+ br = au_sbr(sb, bindex);
27688+ file = br->br_xino.xi_file;
27689+ if (!file)
27690+ goto out;
27691+
27692+ au_xino_lock_dir(sb, file, &ldir);
27693+ /* mnt_want_write() is unnecessary here */
27694+ new_xino = au_xino_create2(file, file);
27695+ au_xino_unlock_dir(&ldir);
27696+ err = PTR_ERR(new_xino);
27697+ if (IS_ERR(new_xino))
27698+ goto out;
27699+ err = 0;
27700+ fput(file);
27701+ br->br_xino.xi_file = new_xino;
27702+
27703+ h_sb = br->br_mnt->mnt_sb;
27704+ for (bi = 0; bi <= bend; bi++) {
27705+ if (unlikely(bi == bindex))
27706+ continue;
27707+ br = au_sbr(sb, bi);
27708+ if (br->br_mnt->mnt_sb != h_sb)
27709+ continue;
27710+
27711+ fput(br->br_xino.xi_file);
27712+ br->br_xino.xi_file = new_xino;
27713+ get_file(new_xino);
27714+ }
27715+
4f0767ce 27716+out:
1facf9fc 27717+ return err;
27718+}
27719+
27720+struct xino_do_trunc_args {
27721+ struct super_block *sb;
27722+ struct au_branch *br;
27723+};
27724+
27725+static void xino_do_trunc(void *_args)
27726+{
27727+ struct xino_do_trunc_args *args = _args;
27728+ struct super_block *sb;
27729+ struct au_branch *br;
27730+ struct inode *dir;
27731+ int err;
27732+ aufs_bindex_t bindex;
27733+
27734+ err = 0;
27735+ sb = args->sb;
27736+ dir = sb->s_root->d_inode;
27737+ br = args->br;
27738+
27739+ si_noflush_write_lock(sb);
27740+ ii_read_lock_parent(dir);
27741+ bindex = au_br_index(sb, br->br_id);
27742+ err = au_xino_trunc(sb, bindex);
dece6358
AM
27743+ if (!err
27744+ && br->br_xino.xi_file->f_dentry->d_inode->i_blocks
1facf9fc 27745+ >= br->br_xino_upper)
27746+ br->br_xino_upper += AUFS_XINO_TRUNC_STEP;
27747+
1facf9fc 27748+ ii_read_unlock(dir);
27749+ if (unlikely(err))
4a4d8108 27750+ pr_warning("err b%d, (%d)\n", bindex, err);
1facf9fc 27751+ atomic_dec(&br->br_xino_running);
27752+ atomic_dec(&br->br_count);
1facf9fc 27753+ si_write_unlock(sb);
027c5e7a 27754+ au_nwt_done(&au_sbi(sb)->si_nowait);
1facf9fc 27755+ kfree(args);
27756+}
27757+
27758+static void xino_try_trunc(struct super_block *sb, struct au_branch *br)
27759+{
27760+ struct xino_do_trunc_args *args;
27761+ int wkq_err;
27762+
27763+ if (br->br_xino.xi_file->f_dentry->d_inode->i_blocks
27764+ < br->br_xino_upper)
27765+ return;
27766+
27767+ if (atomic_inc_return(&br->br_xino_running) > 1)
27768+ goto out;
27769+
27770+ /* lock and kfree() will be called in trunc_xino() */
27771+ args = kmalloc(sizeof(*args), GFP_NOFS);
27772+ if (unlikely(!args)) {
27773+ AuErr1("no memory\n");
27774+ goto out_args;
27775+ }
27776+
e49829fe 27777+ atomic_inc(&br->br_count);
1facf9fc 27778+ args->sb = sb;
27779+ args->br = br;
27780+ wkq_err = au_wkq_nowait(xino_do_trunc, args, sb);
27781+ if (!wkq_err)
27782+ return; /* success */
27783+
4a4d8108 27784+ pr_err("wkq %d\n", wkq_err);
e49829fe 27785+ atomic_dec(&br->br_count);
1facf9fc 27786+
4f0767ce 27787+out_args:
1facf9fc 27788+ kfree(args);
4f0767ce 27789+out:
e49829fe 27790+ atomic_dec(&br->br_xino_running);
1facf9fc 27791+}
27792+
27793+/* ---------------------------------------------------------------------- */
27794+
27795+static int au_xino_do_write(au_writef_t write, struct file *file,
27796+ ino_t h_ino, ino_t ino)
27797+{
27798+ loff_t pos;
27799+ ssize_t sz;
27800+
27801+ pos = h_ino;
27802+ if (unlikely(au_loff_max / sizeof(ino) - 1 < pos)) {
27803+ AuIOErr1("too large hi%lu\n", (unsigned long)h_ino);
27804+ return -EFBIG;
27805+ }
27806+ pos *= sizeof(ino);
27807+ sz = xino_fwrite(write, file, &ino, sizeof(ino), &pos);
27808+ if (sz == sizeof(ino))
27809+ return 0; /* success */
27810+
27811+ AuIOErr("write failed (%zd)\n", sz);
27812+ return -EIO;
27813+}
27814+
27815+/*
27816+ * write @ino to the xinofile for the specified branch{@sb, @bindex}
27817+ * at the position of @h_ino.
27818+ * even if @ino is zero, it is written to the xinofile and means no entry.
27819+ * if the size of the xino file on a specific filesystem exceeds the watermark,
27820+ * try truncating it.
27821+ */
27822+int au_xino_write(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino,
27823+ ino_t ino)
27824+{
27825+ int err;
27826+ unsigned int mnt_flags;
27827+ struct au_branch *br;
27828+
27829+ BUILD_BUG_ON(sizeof(long long) != sizeof(au_loff_max)
27830+ || ((loff_t)-1) > 0);
dece6358 27831+ SiMustAnyLock(sb);
1facf9fc 27832+
27833+ mnt_flags = au_mntflags(sb);
27834+ if (!au_opt_test(mnt_flags, XINO))
27835+ return 0;
27836+
27837+ br = au_sbr(sb, bindex);
27838+ err = au_xino_do_write(au_sbi(sb)->si_xwrite, br->br_xino.xi_file,
27839+ h_ino, ino);
27840+ if (!err) {
27841+ if (au_opt_test(mnt_flags, TRUNC_XINO)
27842+ && au_test_fs_trunc_xino(br->br_mnt->mnt_sb))
27843+ xino_try_trunc(sb, br);
27844+ return 0; /* success */
27845+ }
27846+
27847+ AuIOErr("write failed (%d)\n", err);
27848+ return -EIO;
27849+}
27850+
27851+/* ---------------------------------------------------------------------- */
27852+
27853+/* aufs inode number bitmap */
27854+
27855+static const int page_bits = (int)PAGE_SIZE * BITS_PER_BYTE;
27856+static ino_t xib_calc_ino(unsigned long pindex, int bit)
27857+{
27858+ ino_t ino;
27859+
27860+ AuDebugOn(bit < 0 || page_bits <= bit);
27861+ ino = AUFS_FIRST_INO + pindex * page_bits + bit;
27862+ return ino;
27863+}
27864+
27865+static void xib_calc_bit(ino_t ino, unsigned long *pindex, int *bit)
27866+{
27867+ AuDebugOn(ino < AUFS_FIRST_INO);
27868+ ino -= AUFS_FIRST_INO;
27869+ *pindex = ino / page_bits;
27870+ *bit = ino % page_bits;
27871+}
27872+
27873+static int xib_pindex(struct super_block *sb, unsigned long pindex)
27874+{
27875+ int err;
27876+ loff_t pos;
27877+ ssize_t sz;
27878+ struct au_sbinfo *sbinfo;
27879+ struct file *xib;
27880+ unsigned long *p;
27881+
27882+ sbinfo = au_sbi(sb);
27883+ MtxMustLock(&sbinfo->si_xib_mtx);
27884+ AuDebugOn(pindex > ULONG_MAX / PAGE_SIZE
27885+ || !au_opt_test(sbinfo->si_mntflags, XINO));
27886+
27887+ if (pindex == sbinfo->si_xib_last_pindex)
27888+ return 0;
27889+
27890+ xib = sbinfo->si_xib;
27891+ p = sbinfo->si_xib_buf;
27892+ pos = sbinfo->si_xib_last_pindex;
27893+ pos *= PAGE_SIZE;
27894+ sz = xino_fwrite(sbinfo->si_xwrite, xib, p, PAGE_SIZE, &pos);
27895+ if (unlikely(sz != PAGE_SIZE))
27896+ goto out;
27897+
27898+ pos = pindex;
27899+ pos *= PAGE_SIZE;
27900+ if (i_size_read(xib->f_dentry->d_inode) >= pos + PAGE_SIZE)
27901+ sz = xino_fread(sbinfo->si_xread, xib, p, PAGE_SIZE, &pos);
27902+ else {
27903+ memset(p, 0, PAGE_SIZE);
27904+ sz = xino_fwrite(sbinfo->si_xwrite, xib, p, PAGE_SIZE, &pos);
27905+ }
27906+ if (sz == PAGE_SIZE) {
27907+ sbinfo->si_xib_last_pindex = pindex;
27908+ return 0; /* success */
27909+ }
27910+
4f0767ce 27911+out:
b752ccd1
AM
27912+ AuIOErr1("write failed (%zd)\n", sz);
27913+ err = sz;
27914+ if (sz >= 0)
27915+ err = -EIO;
27916+ return err;
27917+}
27918+
27919+/* ---------------------------------------------------------------------- */
27920+
27921+static void au_xib_clear_bit(struct inode *inode)
27922+{
27923+ int err, bit;
27924+ unsigned long pindex;
27925+ struct super_block *sb;
27926+ struct au_sbinfo *sbinfo;
27927+
27928+ AuDebugOn(inode->i_nlink);
27929+
27930+ sb = inode->i_sb;
27931+ xib_calc_bit(inode->i_ino, &pindex, &bit);
27932+ AuDebugOn(page_bits <= bit);
27933+ sbinfo = au_sbi(sb);
27934+ mutex_lock(&sbinfo->si_xib_mtx);
27935+ err = xib_pindex(sb, pindex);
27936+ if (!err) {
27937+ clear_bit(bit, sbinfo->si_xib_buf);
27938+ sbinfo->si_xib_next_bit = bit;
27939+ }
27940+ mutex_unlock(&sbinfo->si_xib_mtx);
27941+}
27942+
27943+/* for s_op->delete_inode() */
27944+void au_xino_delete_inode(struct inode *inode, const int unlinked)
27945+{
27946+ int err;
27947+ unsigned int mnt_flags;
27948+ aufs_bindex_t bindex, bend, bi;
27949+ unsigned char try_trunc;
27950+ struct au_iinfo *iinfo;
27951+ struct super_block *sb;
27952+ struct au_hinode *hi;
27953+ struct inode *h_inode;
27954+ struct au_branch *br;
27955+ au_writef_t xwrite;
27956+
27957+ sb = inode->i_sb;
27958+ mnt_flags = au_mntflags(sb);
27959+ if (!au_opt_test(mnt_flags, XINO)
27960+ || inode->i_ino == AUFS_ROOT_INO)
27961+ return;
27962+
27963+ if (unlinked) {
27964+ au_xigen_inc(inode);
27965+ au_xib_clear_bit(inode);
27966+ }
27967+
27968+ iinfo = au_ii(inode);
27969+ if (!iinfo)
27970+ return;
1facf9fc 27971+
b752ccd1
AM
27972+ bindex = iinfo->ii_bstart;
27973+ if (bindex < 0)
27974+ return;
1facf9fc 27975+
b752ccd1
AM
27976+ xwrite = au_sbi(sb)->si_xwrite;
27977+ try_trunc = !!au_opt_test(mnt_flags, TRUNC_XINO);
27978+ hi = iinfo->ii_hinode + bindex;
27979+ bend = iinfo->ii_bend;
27980+ for (; bindex <= bend; bindex++, hi++) {
27981+ h_inode = hi->hi_inode;
27982+ if (!h_inode
27983+ || (!unlinked && h_inode->i_nlink))
27984+ continue;
1facf9fc 27985+
b752ccd1
AM
27986+ /* inode may not be revalidated */
27987+ bi = au_br_index(sb, hi->hi_id);
27988+ if (bi < 0)
27989+ continue;
1facf9fc 27990+
b752ccd1
AM
27991+ br = au_sbr(sb, bi);
27992+ err = au_xino_do_write(xwrite, br->br_xino.xi_file,
27993+ h_inode->i_ino, /*ino*/0);
27994+ if (!err && try_trunc
27995+ && au_test_fs_trunc_xino(br->br_mnt->mnt_sb))
27996+ xino_try_trunc(sb, br);
1facf9fc 27997+ }
1facf9fc 27998+}
27999+
28000+/* get an unused inode number from bitmap */
28001+ino_t au_xino_new_ino(struct super_block *sb)
28002+{
28003+ ino_t ino;
28004+ unsigned long *p, pindex, ul, pend;
28005+ struct au_sbinfo *sbinfo;
28006+ struct file *file;
28007+ int free_bit, err;
28008+
28009+ if (!au_opt_test(au_mntflags(sb), XINO))
28010+ return iunique(sb, AUFS_FIRST_INO);
28011+
28012+ sbinfo = au_sbi(sb);
28013+ mutex_lock(&sbinfo->si_xib_mtx);
28014+ p = sbinfo->si_xib_buf;
28015+ free_bit = sbinfo->si_xib_next_bit;
28016+ if (free_bit < page_bits && !test_bit(free_bit, p))
28017+ goto out; /* success */
28018+ free_bit = find_first_zero_bit(p, page_bits);
28019+ if (free_bit < page_bits)
28020+ goto out; /* success */
28021+
28022+ pindex = sbinfo->si_xib_last_pindex;
28023+ for (ul = pindex - 1; ul < ULONG_MAX; ul--) {
28024+ err = xib_pindex(sb, ul);
28025+ if (unlikely(err))
28026+ goto out_err;
28027+ free_bit = find_first_zero_bit(p, page_bits);
28028+ if (free_bit < page_bits)
28029+ goto out; /* success */
28030+ }
28031+
28032+ file = sbinfo->si_xib;
28033+ pend = i_size_read(file->f_dentry->d_inode) / PAGE_SIZE;
28034+ for (ul = pindex + 1; ul <= pend; ul++) {
28035+ err = xib_pindex(sb, ul);
28036+ if (unlikely(err))
28037+ goto out_err;
28038+ free_bit = find_first_zero_bit(p, page_bits);
28039+ if (free_bit < page_bits)
28040+ goto out; /* success */
28041+ }
28042+ BUG();
28043+
4f0767ce 28044+out:
1facf9fc 28045+ set_bit(free_bit, p);
7f207e10 28046+ sbinfo->si_xib_next_bit = free_bit + 1;
1facf9fc 28047+ pindex = sbinfo->si_xib_last_pindex;
28048+ mutex_unlock(&sbinfo->si_xib_mtx);
28049+ ino = xib_calc_ino(pindex, free_bit);
28050+ AuDbg("i%lu\n", (unsigned long)ino);
28051+ return ino;
4f0767ce 28052+out_err:
1facf9fc 28053+ mutex_unlock(&sbinfo->si_xib_mtx);
28054+ AuDbg("i0\n");
28055+ return 0;
28056+}
28057+
28058+/*
28059+ * read @ino from xinofile for the specified branch{@sb, @bindex}
28060+ * at the position of @h_ino.
28061+ * if @ino does not exist and @do_new is true, get new one.
28062+ */
28063+int au_xino_read(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino,
28064+ ino_t *ino)
28065+{
28066+ int err;
28067+ ssize_t sz;
28068+ loff_t pos;
28069+ struct file *file;
28070+ struct au_sbinfo *sbinfo;
28071+
28072+ *ino = 0;
28073+ if (!au_opt_test(au_mntflags(sb), XINO))
28074+ return 0; /* no xino */
28075+
28076+ err = 0;
28077+ sbinfo = au_sbi(sb);
28078+ pos = h_ino;
28079+ if (unlikely(au_loff_max / sizeof(*ino) - 1 < pos)) {
28080+ AuIOErr1("too large hi%lu\n", (unsigned long)h_ino);
28081+ return -EFBIG;
28082+ }
28083+ pos *= sizeof(*ino);
28084+
28085+ file = au_sbr(sb, bindex)->br_xino.xi_file;
28086+ if (i_size_read(file->f_dentry->d_inode) < pos + sizeof(*ino))
28087+ return 0; /* no ino */
28088+
28089+ sz = xino_fread(sbinfo->si_xread, file, ino, sizeof(*ino), &pos);
28090+ if (sz == sizeof(*ino))
28091+ return 0; /* success */
28092+
28093+ err = sz;
28094+ if (unlikely(sz >= 0)) {
28095+ err = -EIO;
28096+ AuIOErr("xino read error (%zd)\n", sz);
28097+ }
28098+
28099+ return err;
28100+}
28101+
28102+/* ---------------------------------------------------------------------- */
28103+
28104+/* create and set a new xino file */
28105+
28106+struct file *au_xino_create(struct super_block *sb, char *fname, int silent)
28107+{
28108+ struct file *file;
28109+ struct dentry *h_parent, *d;
28110+ struct inode *h_dir;
28111+ int err;
28112+
28113+ /*
28114+ * at mount-time, and the xino file is the default path,
4a4d8108 28115+ * hnotify is disabled so we have no notify events to ignore.
1facf9fc 28116+ * when a user specified the xino, we cannot get au_hdir to be ignored.
28117+ */
7f207e10 28118+ file = vfsub_filp_open(fname, O_RDWR | O_CREAT | O_EXCL | O_LARGEFILE
2cbb1c4b 28119+ /* | __FMODE_NONOTIFY */,
1facf9fc 28120+ S_IRUGO | S_IWUGO);
28121+ if (IS_ERR(file)) {
28122+ if (!silent)
4a4d8108 28123+ pr_err("open %s(%ld)\n", fname, PTR_ERR(file));
1facf9fc 28124+ return file;
28125+ }
28126+
28127+ /* keep file count */
28128+ h_parent = dget_parent(file->f_dentry);
28129+ h_dir = h_parent->d_inode;
28130+ mutex_lock_nested(&h_dir->i_mutex, AuLsc_I_PARENT);
28131+ /* mnt_want_write() is unnecessary here */
28132+ err = vfsub_unlink(h_dir, &file->f_path, /*force*/0);
28133+ mutex_unlock(&h_dir->i_mutex);
28134+ dput(h_parent);
28135+ if (unlikely(err)) {
28136+ if (!silent)
4a4d8108 28137+ pr_err("unlink %s(%d)\n", fname, err);
1facf9fc 28138+ goto out;
28139+ }
28140+
28141+ err = -EINVAL;
28142+ d = file->f_dentry;
28143+ if (unlikely(sb == d->d_sb)) {
28144+ if (!silent)
4a4d8108 28145+ pr_err("%s must be outside\n", fname);
1facf9fc 28146+ goto out;
28147+ }
28148+ if (unlikely(au_test_fs_bad_xino(d->d_sb))) {
28149+ if (!silent)
4a4d8108
AM
28150+ pr_err("xino doesn't support %s(%s)\n",
28151+ fname, au_sbtype(d->d_sb));
1facf9fc 28152+ goto out;
28153+ }
28154+ return file; /* success */
28155+
4f0767ce 28156+out:
1facf9fc 28157+ fput(file);
28158+ file = ERR_PTR(err);
28159+ return file;
28160+}
28161+
28162+/*
28163+ * find another branch who is on the same filesystem of the specified
28164+ * branch{@btgt}. search until @bend.
28165+ */
28166+static int is_sb_shared(struct super_block *sb, aufs_bindex_t btgt,
28167+ aufs_bindex_t bend)
28168+{
28169+ aufs_bindex_t bindex;
28170+ struct super_block *tgt_sb = au_sbr_sb(sb, btgt);
28171+
28172+ for (bindex = 0; bindex < btgt; bindex++)
28173+ if (unlikely(tgt_sb == au_sbr_sb(sb, bindex)))
28174+ return bindex;
28175+ for (bindex++; bindex <= bend; bindex++)
28176+ if (unlikely(tgt_sb == au_sbr_sb(sb, bindex)))
28177+ return bindex;
28178+ return -1;
28179+}
28180+
28181+/* ---------------------------------------------------------------------- */
28182+
28183+/*
28184+ * initialize the xinofile for the specified branch @br
28185+ * at the place/path where @base_file indicates.
28186+ * test whether another branch is on the same filesystem or not,
28187+ * if @do_test is true.
28188+ */
28189+int au_xino_br(struct super_block *sb, struct au_branch *br, ino_t h_ino,
28190+ struct file *base_file, int do_test)
28191+{
28192+ int err;
28193+ ino_t ino;
28194+ aufs_bindex_t bend, bindex;
28195+ struct au_branch *shared_br, *b;
28196+ struct file *file;
28197+ struct super_block *tgt_sb;
28198+
28199+ shared_br = NULL;
28200+ bend = au_sbend(sb);
28201+ if (do_test) {
28202+ tgt_sb = br->br_mnt->mnt_sb;
28203+ for (bindex = 0; bindex <= bend; bindex++) {
28204+ b = au_sbr(sb, bindex);
28205+ if (tgt_sb == b->br_mnt->mnt_sb) {
28206+ shared_br = b;
28207+ break;
28208+ }
28209+ }
28210+ }
28211+
28212+ if (!shared_br || !shared_br->br_xino.xi_file) {
28213+ struct au_xino_lock_dir ldir;
28214+
28215+ au_xino_lock_dir(sb, base_file, &ldir);
28216+ /* mnt_want_write() is unnecessary here */
28217+ file = au_xino_create2(base_file, NULL);
28218+ au_xino_unlock_dir(&ldir);
28219+ err = PTR_ERR(file);
28220+ if (IS_ERR(file))
28221+ goto out;
28222+ br->br_xino.xi_file = file;
28223+ } else {
28224+ br->br_xino.xi_file = shared_br->br_xino.xi_file;
28225+ get_file(br->br_xino.xi_file);
28226+ }
28227+
28228+ ino = AUFS_ROOT_INO;
28229+ err = au_xino_do_write(au_sbi(sb)->si_xwrite, br->br_xino.xi_file,
28230+ h_ino, ino);
b752ccd1
AM
28231+ if (unlikely(err)) {
28232+ fput(br->br_xino.xi_file);
28233+ br->br_xino.xi_file = NULL;
28234+ }
1facf9fc 28235+
4f0767ce 28236+out:
1facf9fc 28237+ return err;
28238+}
28239+
28240+/* ---------------------------------------------------------------------- */
28241+
28242+/* trucate a xino bitmap file */
28243+
28244+/* todo: slow */
28245+static int do_xib_restore(struct super_block *sb, struct file *file, void *page)
28246+{
28247+ int err, bit;
28248+ ssize_t sz;
28249+ unsigned long pindex;
28250+ loff_t pos, pend;
28251+ struct au_sbinfo *sbinfo;
28252+ au_readf_t func;
28253+ ino_t *ino;
28254+ unsigned long *p;
28255+
28256+ err = 0;
28257+ sbinfo = au_sbi(sb);
dece6358 28258+ MtxMustLock(&sbinfo->si_xib_mtx);
1facf9fc 28259+ p = sbinfo->si_xib_buf;
28260+ func = sbinfo->si_xread;
28261+ pend = i_size_read(file->f_dentry->d_inode);
28262+ pos = 0;
28263+ while (pos < pend) {
28264+ sz = xino_fread(func, file, page, PAGE_SIZE, &pos);
28265+ err = sz;
28266+ if (unlikely(sz <= 0))
28267+ goto out;
28268+
28269+ err = 0;
28270+ for (ino = page; sz > 0; ino++, sz -= sizeof(ino)) {
28271+ if (unlikely(*ino < AUFS_FIRST_INO))
28272+ continue;
28273+
28274+ xib_calc_bit(*ino, &pindex, &bit);
28275+ AuDebugOn(page_bits <= bit);
28276+ err = xib_pindex(sb, pindex);
28277+ if (!err)
28278+ set_bit(bit, p);
28279+ else
28280+ goto out;
28281+ }
28282+ }
28283+
4f0767ce 28284+out:
1facf9fc 28285+ return err;
28286+}
28287+
28288+static int xib_restore(struct super_block *sb)
28289+{
28290+ int err;
28291+ aufs_bindex_t bindex, bend;
28292+ void *page;
28293+
28294+ err = -ENOMEM;
28295+ page = (void *)__get_free_page(GFP_NOFS);
28296+ if (unlikely(!page))
28297+ goto out;
28298+
28299+ err = 0;
28300+ bend = au_sbend(sb);
28301+ for (bindex = 0; !err && bindex <= bend; bindex++)
28302+ if (!bindex || is_sb_shared(sb, bindex, bindex - 1) < 0)
28303+ err = do_xib_restore
28304+ (sb, au_sbr(sb, bindex)->br_xino.xi_file, page);
28305+ else
28306+ AuDbg("b%d\n", bindex);
28307+ free_page((unsigned long)page);
28308+
4f0767ce 28309+out:
1facf9fc 28310+ return err;
28311+}
28312+
28313+int au_xib_trunc(struct super_block *sb)
28314+{
28315+ int err;
28316+ ssize_t sz;
28317+ loff_t pos;
28318+ struct au_xino_lock_dir ldir;
28319+ struct au_sbinfo *sbinfo;
28320+ unsigned long *p;
28321+ struct file *file;
28322+
dece6358
AM
28323+ SiMustWriteLock(sb);
28324+
1facf9fc 28325+ err = 0;
28326+ sbinfo = au_sbi(sb);
28327+ if (!au_opt_test(sbinfo->si_mntflags, XINO))
28328+ goto out;
28329+
28330+ file = sbinfo->si_xib;
28331+ if (i_size_read(file->f_dentry->d_inode) <= PAGE_SIZE)
28332+ goto out;
28333+
28334+ au_xino_lock_dir(sb, file, &ldir);
28335+ /* mnt_want_write() is unnecessary here */
28336+ file = au_xino_create2(sbinfo->si_xib, NULL);
28337+ au_xino_unlock_dir(&ldir);
28338+ err = PTR_ERR(file);
28339+ if (IS_ERR(file))
28340+ goto out;
28341+ fput(sbinfo->si_xib);
28342+ sbinfo->si_xib = file;
28343+
28344+ p = sbinfo->si_xib_buf;
28345+ memset(p, 0, PAGE_SIZE);
28346+ pos = 0;
28347+ sz = xino_fwrite(sbinfo->si_xwrite, sbinfo->si_xib, p, PAGE_SIZE, &pos);
28348+ if (unlikely(sz != PAGE_SIZE)) {
28349+ err = sz;
28350+ AuIOErr("err %d\n", err);
28351+ if (sz >= 0)
28352+ err = -EIO;
28353+ goto out;
28354+ }
28355+
28356+ mutex_lock(&sbinfo->si_xib_mtx);
28357+ /* mnt_want_write() is unnecessary here */
28358+ err = xib_restore(sb);
28359+ mutex_unlock(&sbinfo->si_xib_mtx);
28360+
28361+out:
28362+ return err;
28363+}
28364+
28365+/* ---------------------------------------------------------------------- */
28366+
28367+/*
28368+ * xino mount option handlers
28369+ */
28370+static au_readf_t find_readf(struct file *h_file)
28371+{
28372+ const struct file_operations *fop = h_file->f_op;
28373+
28374+ if (fop) {
28375+ if (fop->read)
28376+ return fop->read;
28377+ if (fop->aio_read)
28378+ return do_sync_read;
28379+ }
28380+ return ERR_PTR(-ENOSYS);
28381+}
28382+
28383+static au_writef_t find_writef(struct file *h_file)
28384+{
28385+ const struct file_operations *fop = h_file->f_op;
28386+
28387+ if (fop) {
28388+ if (fop->write)
28389+ return fop->write;
28390+ if (fop->aio_write)
28391+ return do_sync_write;
28392+ }
28393+ return ERR_PTR(-ENOSYS);
28394+}
28395+
28396+/* xino bitmap */
28397+static void xino_clear_xib(struct super_block *sb)
28398+{
28399+ struct au_sbinfo *sbinfo;
28400+
dece6358
AM
28401+ SiMustWriteLock(sb);
28402+
1facf9fc 28403+ sbinfo = au_sbi(sb);
28404+ sbinfo->si_xread = NULL;
28405+ sbinfo->si_xwrite = NULL;
28406+ if (sbinfo->si_xib)
28407+ fput(sbinfo->si_xib);
28408+ sbinfo->si_xib = NULL;
28409+ free_page((unsigned long)sbinfo->si_xib_buf);
28410+ sbinfo->si_xib_buf = NULL;
28411+}
28412+
28413+static int au_xino_set_xib(struct super_block *sb, struct file *base)
28414+{
28415+ int err;
28416+ loff_t pos;
28417+ struct au_sbinfo *sbinfo;
28418+ struct file *file;
28419+
dece6358
AM
28420+ SiMustWriteLock(sb);
28421+
1facf9fc 28422+ sbinfo = au_sbi(sb);
28423+ file = au_xino_create2(base, sbinfo->si_xib);
28424+ err = PTR_ERR(file);
28425+ if (IS_ERR(file))
28426+ goto out;
28427+ if (sbinfo->si_xib)
28428+ fput(sbinfo->si_xib);
28429+ sbinfo->si_xib = file;
28430+ sbinfo->si_xread = find_readf(file);
28431+ sbinfo->si_xwrite = find_writef(file);
28432+
28433+ err = -ENOMEM;
28434+ if (!sbinfo->si_xib_buf)
28435+ sbinfo->si_xib_buf = (void *)get_zeroed_page(GFP_NOFS);
28436+ if (unlikely(!sbinfo->si_xib_buf))
28437+ goto out_unset;
28438+
28439+ sbinfo->si_xib_last_pindex = 0;
28440+ sbinfo->si_xib_next_bit = 0;
28441+ if (i_size_read(file->f_dentry->d_inode) < PAGE_SIZE) {
28442+ pos = 0;
28443+ err = xino_fwrite(sbinfo->si_xwrite, file, sbinfo->si_xib_buf,
28444+ PAGE_SIZE, &pos);
28445+ if (unlikely(err != PAGE_SIZE))
28446+ goto out_free;
28447+ }
28448+ err = 0;
28449+ goto out; /* success */
28450+
4f0767ce 28451+out_free:
1facf9fc 28452+ free_page((unsigned long)sbinfo->si_xib_buf);
b752ccd1
AM
28453+ sbinfo->si_xib_buf = NULL;
28454+ if (err >= 0)
28455+ err = -EIO;
4f0767ce 28456+out_unset:
b752ccd1
AM
28457+ fput(sbinfo->si_xib);
28458+ sbinfo->si_xib = NULL;
28459+ sbinfo->si_xread = NULL;
28460+ sbinfo->si_xwrite = NULL;
4f0767ce 28461+out:
b752ccd1 28462+ return err;
1facf9fc 28463+}
28464+
b752ccd1
AM
28465+/* xino for each branch */
28466+static void xino_clear_br(struct super_block *sb)
28467+{
28468+ aufs_bindex_t bindex, bend;
28469+ struct au_branch *br;
1facf9fc 28470+
b752ccd1
AM
28471+ bend = au_sbend(sb);
28472+ for (bindex = 0; bindex <= bend; bindex++) {
28473+ br = au_sbr(sb, bindex);
28474+ if (!br || !br->br_xino.xi_file)
28475+ continue;
28476+
28477+ fput(br->br_xino.xi_file);
28478+ br->br_xino.xi_file = NULL;
28479+ }
28480+}
28481+
28482+static int au_xino_set_br(struct super_block *sb, struct file *base)
1facf9fc 28483+{
28484+ int err;
b752ccd1
AM
28485+ ino_t ino;
28486+ aufs_bindex_t bindex, bend, bshared;
28487+ struct {
28488+ struct file *old, *new;
28489+ } *fpair, *p;
28490+ struct au_branch *br;
28491+ struct inode *inode;
28492+ au_writef_t writef;
1facf9fc 28493+
b752ccd1
AM
28494+ SiMustWriteLock(sb);
28495+
28496+ err = -ENOMEM;
28497+ bend = au_sbend(sb);
28498+ fpair = kcalloc(bend + 1, sizeof(*fpair), GFP_NOFS);
28499+ if (unlikely(!fpair))
1facf9fc 28500+ goto out;
28501+
b752ccd1
AM
28502+ inode = sb->s_root->d_inode;
28503+ ino = AUFS_ROOT_INO;
28504+ writef = au_sbi(sb)->si_xwrite;
28505+ for (bindex = 0, p = fpair; bindex <= bend; bindex++, p++) {
28506+ br = au_sbr(sb, bindex);
28507+ bshared = is_sb_shared(sb, bindex, bindex - 1);
28508+ if (bshared >= 0) {
28509+ /* shared xino */
28510+ *p = fpair[bshared];
28511+ get_file(p->new);
28512+ }
28513+
28514+ if (!p->new) {
28515+ /* new xino */
28516+ p->old = br->br_xino.xi_file;
28517+ p->new = au_xino_create2(base, br->br_xino.xi_file);
28518+ err = PTR_ERR(p->new);
28519+ if (IS_ERR(p->new)) {
28520+ p->new = NULL;
28521+ goto out_pair;
28522+ }
28523+ }
28524+
28525+ err = au_xino_do_write(writef, p->new,
28526+ au_h_iptr(inode, bindex)->i_ino, ino);
28527+ if (unlikely(err))
28528+ goto out_pair;
28529+ }
28530+
28531+ for (bindex = 0, p = fpair; bindex <= bend; bindex++, p++) {
28532+ br = au_sbr(sb, bindex);
28533+ if (br->br_xino.xi_file)
28534+ fput(br->br_xino.xi_file);
28535+ get_file(p->new);
28536+ br->br_xino.xi_file = p->new;
28537+ }
1facf9fc 28538+
4f0767ce 28539+out_pair:
b752ccd1
AM
28540+ for (bindex = 0, p = fpair; bindex <= bend; bindex++, p++)
28541+ if (p->new)
28542+ fput(p->new);
28543+ else
28544+ break;
28545+ kfree(fpair);
4f0767ce 28546+out:
1facf9fc 28547+ return err;
28548+}
b752ccd1
AM
28549+
28550+void au_xino_clr(struct super_block *sb)
28551+{
28552+ struct au_sbinfo *sbinfo;
28553+
28554+ au_xigen_clr(sb);
28555+ xino_clear_xib(sb);
28556+ xino_clear_br(sb);
28557+ sbinfo = au_sbi(sb);
28558+ /* lvalue, do not call au_mntflags() */
28559+ au_opt_clr(sbinfo->si_mntflags, XINO);
28560+}
28561+
28562+int au_xino_set(struct super_block *sb, struct au_opt_xino *xino, int remount)
28563+{
28564+ int err, skip;
28565+ struct dentry *parent, *cur_parent;
28566+ struct qstr *dname, *cur_name;
28567+ struct file *cur_xino;
28568+ struct inode *dir;
28569+ struct au_sbinfo *sbinfo;
28570+
28571+ SiMustWriteLock(sb);
28572+
28573+ err = 0;
28574+ sbinfo = au_sbi(sb);
28575+ parent = dget_parent(xino->file->f_dentry);
28576+ if (remount) {
28577+ skip = 0;
28578+ dname = &xino->file->f_dentry->d_name;
28579+ cur_xino = sbinfo->si_xib;
28580+ if (cur_xino) {
28581+ cur_parent = dget_parent(cur_xino->f_dentry);
28582+ cur_name = &cur_xino->f_dentry->d_name;
28583+ skip = (cur_parent == parent
28584+ && dname->len == cur_name->len
28585+ && !memcmp(dname->name, cur_name->name,
28586+ dname->len));
28587+ dput(cur_parent);
28588+ }
28589+ if (skip)
28590+ goto out;
28591+ }
28592+
28593+ au_opt_set(sbinfo->si_mntflags, XINO);
28594+ dir = parent->d_inode;
28595+ mutex_lock_nested(&dir->i_mutex, AuLsc_I_PARENT);
28596+ /* mnt_want_write() is unnecessary here */
28597+ err = au_xino_set_xib(sb, xino->file);
28598+ if (!err)
28599+ err = au_xigen_set(sb, xino->file);
28600+ if (!err)
28601+ err = au_xino_set_br(sb, xino->file);
28602+ mutex_unlock(&dir->i_mutex);
28603+ if (!err)
28604+ goto out; /* success */
28605+
28606+ /* reset all */
28607+ AuIOErr("failed creating xino(%d).\n", err);
28608+
4f0767ce 28609+out:
b752ccd1
AM
28610+ dput(parent);
28611+ return err;
28612+}
28613+
28614+/* ---------------------------------------------------------------------- */
28615+
28616+/*
28617+ * create a xinofile at the default place/path.
28618+ */
28619+struct file *au_xino_def(struct super_block *sb)
28620+{
28621+ struct file *file;
28622+ char *page, *p;
28623+ struct au_branch *br;
28624+ struct super_block *h_sb;
28625+ struct path path;
28626+ aufs_bindex_t bend, bindex, bwr;
28627+
28628+ br = NULL;
28629+ bend = au_sbend(sb);
28630+ bwr = -1;
28631+ for (bindex = 0; bindex <= bend; bindex++) {
28632+ br = au_sbr(sb, bindex);
28633+ if (au_br_writable(br->br_perm)
28634+ && !au_test_fs_bad_xino(br->br_mnt->mnt_sb)) {
28635+ bwr = bindex;
28636+ break;
28637+ }
28638+ }
28639+
7f207e10
AM
28640+ if (bwr >= 0) {
28641+ file = ERR_PTR(-ENOMEM);
28642+ page = __getname_gfp(GFP_NOFS);
28643+ if (unlikely(!page))
28644+ goto out;
28645+ path.mnt = br->br_mnt;
28646+ path.dentry = au_h_dptr(sb->s_root, bwr);
28647+ p = d_path(&path, page, PATH_MAX - sizeof(AUFS_XINO_FNAME));
28648+ file = (void *)p;
28649+ if (!IS_ERR(p)) {
28650+ strcat(p, "/" AUFS_XINO_FNAME);
28651+ AuDbg("%s\n", p);
28652+ file = au_xino_create(sb, p, /*silent*/0);
28653+ if (!IS_ERR(file))
28654+ au_xino_brid_set(sb, br->br_id);
28655+ }
28656+ __putname(page);
28657+ } else {
28658+ file = au_xino_create(sb, AUFS_XINO_DEFPATH, /*silent*/0);
28659+ if (IS_ERR(file))
28660+ goto out;
28661+ h_sb = file->f_dentry->d_sb;
28662+ if (unlikely(au_test_fs_bad_xino(h_sb))) {
28663+ pr_err("xino doesn't support %s(%s)\n",
28664+ AUFS_XINO_DEFPATH, au_sbtype(h_sb));
28665+ fput(file);
28666+ file = ERR_PTR(-EINVAL);
28667+ }
28668+ if (!IS_ERR(file))
28669+ au_xino_brid_set(sb, -1);
28670+ }
0c5527e5 28671+
7f207e10
AM
28672+out:
28673+ return file;
28674+}
28675+
28676+/* ---------------------------------------------------------------------- */
28677+
28678+int au_xino_path(struct seq_file *seq, struct file *file)
28679+{
28680+ int err;
28681+
28682+ err = au_seq_path(seq, &file->f_path);
28683+ if (unlikely(err < 0))
28684+ goto out;
28685+
28686+ err = 0;
28687+#define Deleted "\\040(deleted)"
28688+ seq->count -= sizeof(Deleted) - 1;
28689+ AuDebugOn(memcmp(seq->buf + seq->count, Deleted,
28690+ sizeof(Deleted) - 1));
28691+#undef Deleted
28692+
28693+out:
28694+ return err;
28695+}
28696diff -urN /usr/share/empty/include/linux/aufs_type.h linux/include/linux/aufs_type.h
28697--- /usr/share/empty/include/linux/aufs_type.h 1970-01-01 01:00:00.000000000 +0100
2cbb1c4b 28698+++ linux/include/linux/aufs_type.h 2011-07-11 11:34:24.079331673 +0200
027c5e7a 28699@@ -0,0 +1,206 @@
7f207e10 28700+/*
027c5e7a 28701+ * Copyright (C) 2005-2011 Junjiro R. Okajima
7f207e10
AM
28702+ *
28703+ * This program, aufs is free software; you can redistribute it and/or modify
28704+ * it under the terms of the GNU General Public License as published by
28705+ * the Free Software Foundation; either version 2 of the License, or
28706+ * (at your option) any later version.
28707+ *
28708+ * This program is distributed in the hope that it will be useful,
28709+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
28710+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
28711+ * GNU General Public License for more details.
28712+ *
28713+ * You should have received a copy of the GNU General Public License
28714+ * along with this program; if not, write to the Free Software
28715+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
28716+ */
28717+
28718+#ifndef __AUFS_TYPE_H__
28719+#define __AUFS_TYPE_H__
28720+
28721+#include <linux/ioctl.h>
28722+#include <linux/kernel.h>
28723+#include <linux/limits.h>
28724+#include <linux/types.h>
28725+
2cbb1c4b 28726+#define AUFS_VERSION "2.1-standalone.tree-3.0-rcN-20110711"
7f207e10
AM
28727+
28728+/* todo? move this to linux-2.6.19/include/magic.h */
28729+#define AUFS_SUPER_MAGIC ('a' << 24 | 'u' << 16 | 'f' << 8 | 's')
28730+
28731+/* ---------------------------------------------------------------------- */
28732+
28733+#ifdef CONFIG_AUFS_BRANCH_MAX_127
28734+typedef __s8 aufs_bindex_t;
28735+#define AUFS_BRANCH_MAX 127
28736+#else
28737+typedef __s16 aufs_bindex_t;
28738+#ifdef CONFIG_AUFS_BRANCH_MAX_511
28739+#define AUFS_BRANCH_MAX 511
28740+#elif defined(CONFIG_AUFS_BRANCH_MAX_1023)
28741+#define AUFS_BRANCH_MAX 1023
28742+#elif defined(CONFIG_AUFS_BRANCH_MAX_32767)
28743+#define AUFS_BRANCH_MAX 32767
28744+#endif
28745+#endif
28746+
28747+#ifdef __KERNEL__
28748+#ifndef AUFS_BRANCH_MAX
28749+#error unknown CONFIG_AUFS_BRANCH_MAX value
28750+#endif
28751+#endif /* __KERNEL__ */
28752+
28753+/* ---------------------------------------------------------------------- */
28754+
28755+#define AUFS_NAME "aufs"
28756+#define AUFS_FSTYPE AUFS_NAME
28757+
28758+#define AUFS_ROOT_INO 2
28759+#define AUFS_FIRST_INO 11
28760+
28761+#define AUFS_WH_PFX ".wh."
28762+#define AUFS_WH_PFX_LEN ((int)sizeof(AUFS_WH_PFX) - 1)
28763+#define AUFS_WH_TMP_LEN 4
28764+/* a limit for rmdir/rename a dir */
28765+#define AUFS_MAX_NAMELEN (NAME_MAX \
28766+ - AUFS_WH_PFX_LEN * 2 /* doubly whiteouted */\
28767+ - 1 /* dot */\
28768+ - AUFS_WH_TMP_LEN) /* hex */
28769+#define AUFS_XINO_FNAME "." AUFS_NAME ".xino"
28770+#define AUFS_XINO_DEFPATH "/tmp/" AUFS_XINO_FNAME
28771+#define AUFS_XINO_TRUNC_INIT 64 /* blocks */
28772+#define AUFS_XINO_TRUNC_STEP 4 /* blocks */
28773+#define AUFS_DIRWH_DEF 3
28774+#define AUFS_RDCACHE_DEF 10 /* seconds */
027c5e7a 28775+#define AUFS_RDCACHE_MAX 3600 /* seconds */
7f207e10
AM
28776+#define AUFS_RDBLK_DEF 512 /* bytes */
28777+#define AUFS_RDHASH_DEF 32
28778+#define AUFS_WKQ_NAME AUFS_NAME "d"
28779+#define AUFS_WKQ_PRE_NAME AUFS_WKQ_NAME "_pre"
027c5e7a
AM
28780+#define AUFS_MFS_DEF_SEC 30 /* seconds */
28781+#define AUFS_MFS_MAX_SEC 3600 /* seconds */
7f207e10
AM
28782+#define AUFS_PLINK_WARN 100 /* number of plinks */
28783+
28784+/* pseudo-link maintenace under /proc */
28785+#define AUFS_PLINK_MAINT_NAME "plink_maint"
28786+#define AUFS_PLINK_MAINT_DIR "fs/" AUFS_NAME
28787+#define AUFS_PLINK_MAINT_PATH AUFS_PLINK_MAINT_DIR "/" AUFS_PLINK_MAINT_NAME
28788+
28789+#define AUFS_DIROPQ_NAME AUFS_WH_PFX ".opq" /* whiteouted doubly */
28790+#define AUFS_WH_DIROPQ AUFS_WH_PFX AUFS_DIROPQ_NAME
28791+
28792+#define AUFS_BASE_NAME AUFS_WH_PFX AUFS_NAME
28793+#define AUFS_PLINKDIR_NAME AUFS_WH_PFX "plnk"
28794+#define AUFS_ORPHDIR_NAME AUFS_WH_PFX "orph"
28795+
28796+/* doubly whiteouted */
28797+#define AUFS_WH_BASE AUFS_WH_PFX AUFS_BASE_NAME
28798+#define AUFS_WH_PLINKDIR AUFS_WH_PFX AUFS_PLINKDIR_NAME
28799+#define AUFS_WH_ORPHDIR AUFS_WH_PFX AUFS_ORPHDIR_NAME
28800+
28801+/* branch permission */
28802+#define AUFS_BRPERM_RW "rw"
28803+#define AUFS_BRPERM_RO "ro"
28804+#define AUFS_BRPERM_RR "rr"
28805+#define AUFS_BRPERM_WH "wh"
28806+#define AUFS_BRPERM_NLWH "nolwh"
28807+#define AUFS_BRPERM_ROWH AUFS_BRPERM_RO "+" AUFS_BRPERM_WH
28808+#define AUFS_BRPERM_RRWH AUFS_BRPERM_RR "+" AUFS_BRPERM_WH
28809+#define AUFS_BRPERM_RWNLWH AUFS_BRPERM_RW "+" AUFS_BRPERM_NLWH
28810+
28811+/* ---------------------------------------------------------------------- */
28812+
28813+/* ioctl */
28814+enum {
28815+ /* readdir in userspace */
28816+ AuCtl_RDU,
28817+ AuCtl_RDU_INO,
28818+
28819+ /* pathconf wrapper */
027c5e7a
AM
28820+ AuCtl_WBR_FD,
28821+
28822+ /* busy inode */
28823+ AuCtl_IBUSY
7f207e10
AM
28824+};
28825+
28826+/* borrowed from linux/include/linux/kernel.h */
28827+#ifndef ALIGN
28828+#define ALIGN(x, a) __ALIGN_MASK(x, (typeof(x))(a)-1)
28829+#define __ALIGN_MASK(x, mask) (((x)+(mask))&~(mask))
28830+#endif
28831+
28832+/* borrowed from linux/include/linux/compiler-gcc3.h */
28833+#ifndef __aligned
28834+#define __aligned(x) __attribute__((aligned(x)))
28835+#define __packed __attribute__((packed))
28836+#endif
28837+
28838+struct au_rdu_cookie {
28839+ __u64 h_pos;
28840+ __s16 bindex;
28841+ __u8 flags;
28842+ __u8 pad;
28843+ __u32 generation;
28844+} __aligned(8);
28845+
28846+struct au_rdu_ent {
28847+ __u64 ino;
28848+ __s16 bindex;
28849+ __u8 type;
28850+ __u8 nlen;
28851+ __u8 wh;
28852+ char name[0];
28853+} __aligned(8);
28854+
28855+static inline int au_rdu_len(int nlen)
28856+{
28857+ /* include the terminating NULL */
28858+ return ALIGN(sizeof(struct au_rdu_ent) + nlen + 1,
28859+ sizeof(__u64));
28860+}
28861+
28862+union au_rdu_ent_ul {
28863+ struct au_rdu_ent __user *e;
28864+ __u64 ul;
28865+};
28866+
28867+enum {
28868+ AufsCtlRduV_SZ,
28869+ AufsCtlRduV_End
28870+};
28871+
28872+struct aufs_rdu {
28873+ /* input */
28874+ union {
28875+ __u64 sz; /* AuCtl_RDU */
28876+ __u64 nent; /* AuCtl_RDU_INO */
28877+ };
28878+ union au_rdu_ent_ul ent;
28879+ __u16 verify[AufsCtlRduV_End];
28880+
28881+ /* input/output */
28882+ __u32 blk;
28883+
28884+ /* output */
28885+ union au_rdu_ent_ul tail;
28886+ /* number of entries which were added in a single call */
28887+ __u64 rent;
28888+ __u8 full;
28889+ __u8 shwh;
28890+
28891+ struct au_rdu_cookie cookie;
28892+} __aligned(8);
28893+
027c5e7a
AM
28894+struct aufs_ibusy {
28895+ __u64 ino, h_ino;
28896+ __s16 bindex;
28897+} __aligned(8);
28898+
7f207e10
AM
28899+#define AuCtlType 'A'
28900+#define AUFS_CTL_RDU _IOWR(AuCtlType, AuCtl_RDU, struct aufs_rdu)
28901+#define AUFS_CTL_RDU_INO _IOWR(AuCtlType, AuCtl_RDU_INO, struct aufs_rdu)
28902+#define AUFS_CTL_WBR_FD _IO(AuCtlType, AuCtl_WBR_FD)
027c5e7a 28903+#define AUFS_CTL_IBUSY _IOWR(AuCtlType, AuCtl_IBUSY, struct aufs_ibusy)
7f207e10
AM
28904+
28905+#endif /* __AUFS_TYPE_H__ */
2cbb1c4b
JR
28906diff -urN a/include/linux/Kbuild b/include/linux/Kbuild
28907--- a/include/linux/Kbuild 1970-01-01 01:00:00.000000000 +0100
28908+++ b/include/linux/Kbuild 2011-07-11 11:34:21.297331675 +0200
28909@@ -401,3 +401,4 @@
28910 header-y += x25.h
28911 header-y += xattr.h
28912 header-y += xfrm.h
28913+header-y += aufs_type.h
This page took 5.116147 seconds and 4 git commands to generate.