]> git.pld-linux.org Git - packages/kernel.git/blame - kernel-aufs2.patch
- typo
[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
87a755f4 262@@ -978,4 +978,5 @@
94337f0d 263 }
7f207e10
AM
264 return ret;
265 }
266+EXPORT_SYMBOL(cap_file_mmap);
87a755f4 267
7f207e10 268diff --git a/security/device_cgroup.c b/security/device_cgroup.c
2cbb1c4b 269index 1be6826..215278c 100644
7f207e10
AM
270--- a/security/device_cgroup.c
271+++ b/security/device_cgroup.c
2cbb1c4b 272@@ -508,6 +508,7 @@ found:
7f207e10
AM
273
274 return -EPERM;
275 }
2cbb1c4b 276+EXPORT_SYMBOL(__devcgroup_inode_permission);
7f207e10
AM
277
278 int devcgroup_inode_mknod(int mode, dev_t dev)
279 {
280diff --git a/security/security.c b/security/security.c
2cbb1c4b 281index 4ba6d4c..9f64bb8 100644
7f207e10
AM
282--- a/security/security.c
283+++ b/security/security.c
2cbb1c4b 284@@ -373,6 +373,7 @@ int security_path_rmdir(struct path *dir, struct dentry *dentry)
7f207e10
AM
285 return 0;
286 return security_ops->path_rmdir(dir, dentry);
287 }
288+EXPORT_SYMBOL(security_path_rmdir);
289
290 int security_path_unlink(struct path *dir, struct dentry *dentry)
291 {
2cbb1c4b 292@@ -389,6 +390,7 @@ int security_path_symlink(struct path *dir, struct dentry *dentry,
7f207e10
AM
293 return 0;
294 return security_ops->path_symlink(dir, dentry, old_name);
295 }
296+EXPORT_SYMBOL(security_path_symlink);
297
298 int security_path_link(struct dentry *old_dentry, struct path *new_dir,
299 struct dentry *new_dentry)
2cbb1c4b 300@@ -397,6 +399,7 @@ int security_path_link(struct dentry *old_dentry, struct path *new_dir,
7f207e10
AM
301 return 0;
302 return security_ops->path_link(old_dentry, new_dir, new_dentry);
303 }
304+EXPORT_SYMBOL(security_path_link);
305
306 int security_path_rename(struct path *old_dir, struct dentry *old_dentry,
307 struct path *new_dir, struct dentry *new_dentry)
2cbb1c4b 308@@ -415,6 +418,7 @@ int security_path_truncate(struct path *path)
7f207e10
AM
309 return 0;
310 return security_ops->path_truncate(path);
311 }
312+EXPORT_SYMBOL(security_path_truncate);
313
314 int security_path_chmod(struct dentry *dentry, struct vfsmount *mnt,
315 mode_t mode)
2cbb1c4b 316@@ -423,6 +427,7 @@ int security_path_chmod(struct dentry *dentry, struct vfsmount *mnt,
7f207e10
AM
317 return 0;
318 return security_ops->path_chmod(dentry, mnt, mode);
319 }
320+EXPORT_SYMBOL(security_path_chmod);
321
322 int security_path_chown(struct path *path, uid_t uid, gid_t gid)
323 {
2cbb1c4b 324@@ -430,6 +435,7 @@ int security_path_chown(struct path *path, uid_t uid, gid_t gid)
7f207e10
AM
325 return 0;
326 return security_ops->path_chown(path, uid, gid);
327 }
328+EXPORT_SYMBOL(security_path_chown);
329
330 int security_path_chroot(struct path *path)
331 {
2cbb1c4b 332@@ -506,6 +512,7 @@ int security_inode_readlink(struct dentry *dentry)
7f207e10
AM
333 return 0;
334 return security_ops->inode_readlink(dentry);
335 }
336+EXPORT_SYMBOL(security_inode_readlink);
337
338 int security_inode_follow_link(struct dentry *dentry, struct nameidata *nd)
339 {
2cbb1c4b 340@@ -520,6 +527,7 @@ int security_inode_permission(struct inode *inode, int mask)
7f207e10 341 return 0;
2cbb1c4b 342 return security_ops->inode_permission(inode, mask, 0);
7f207e10
AM
343 }
344+EXPORT_SYMBOL(security_inode_permission);
345
027c5e7a 346 int security_inode_exec_permission(struct inode *inode, unsigned int flags)
7f207e10 347 {
2cbb1c4b 348@@ -626,6 +634,7 @@ int security_file_permission(struct file *file, int mask)
7f207e10
AM
349
350 return fsnotify_perm(file, mask);
351 }
352+EXPORT_SYMBOL(security_file_permission);
353
354 int security_file_alloc(struct file *file)
355 {
2cbb1c4b 356@@ -653,6 +662,7 @@ int security_file_mmap(struct file *file, unsigned long reqprot,
7f207e10
AM
357 return ret;
358 return ima_file_mmap(file, prot);
359 }
360+EXPORT_SYMBOL(security_file_mmap);
361
362 int security_file_mprotect(struct vm_area_struct *vma, unsigned long reqprot,
363 unsigned long prot)
364diff -urN /usr/share/empty/Documentation/ABI/testing/debugfs-aufs linux/Documentation/ABI/testing/debugfs-aufs
365--- /usr/share/empty/Documentation/ABI/testing/debugfs-aufs 1970-01-01 01:00:00.000000000 +0100
87a755f4 366+++ linux/Documentation/ABI/testing/debugfs-aufs 2011-03-17 10:46:59.000000000 +0100
7f207e10
AM
367@@ -0,0 +1,37 @@
368+What: /debug/aufs/si_<id>/
369+Date: March 2009
370+Contact: J. R. Okajima <hooanon05@yahoo.co.jp>
371+Description:
372+ Under /debug/aufs, a directory named si_<id> is created
373+ per aufs mount, where <id> is a unique id generated
374+ internally.
1facf9fc 375+
7f207e10
AM
376+What: /debug/aufs/si_<id>/xib
377+Date: March 2009
378+Contact: J. R. Okajima <hooanon05@yahoo.co.jp>
379+Description:
380+ It shows the consumed blocks by xib (External Inode Number
381+ Bitmap), its block size and file size.
382+ When the aufs mount option 'noxino' is specified, it
383+ will be empty. About XINO files, see the aufs manual.
384+
385+What: /debug/aufs/si_<id>/xino0, xino1 ... xinoN
386+Date: March 2009
387+Contact: J. R. Okajima <hooanon05@yahoo.co.jp>
388+Description:
389+ It shows the consumed blocks by xino (External Inode Number
390+ Translation Table), its link count, block size and file
391+ size.
392+ When the aufs mount option 'noxino' is specified, it
393+ will be empty. About XINO files, see the aufs manual.
394+
395+What: /debug/aufs/si_<id>/xigen
396+Date: March 2009
397+Contact: J. R. Okajima <hooanon05@yahoo.co.jp>
398+Description:
399+ It shows the consumed blocks by xigen (External Inode
400+ Generation Table), its block size and file size.
401+ If CONFIG_AUFS_EXPORT is disabled, this entry will not
402+ be created.
403+ When the aufs mount option 'noxino' is specified, it
404+ will be empty. About XINO files, see the aufs manual.
405diff -urN /usr/share/empty/Documentation/ABI/testing/sysfs-aufs linux/Documentation/ABI/testing/sysfs-aufs
406--- /usr/share/empty/Documentation/ABI/testing/sysfs-aufs 1970-01-01 01:00:00.000000000 +0100
87a755f4 407+++ linux/Documentation/ABI/testing/sysfs-aufs 2011-03-17 10:46:59.000000000 +0100
7f207e10
AM
408@@ -0,0 +1,24 @@
409+What: /sys/fs/aufs/si_<id>/
410+Date: March 2009
411+Contact: J. R. Okajima <hooanon05@yahoo.co.jp>
412+Description:
413+ Under /sys/fs/aufs, a directory named si_<id> is created
414+ per aufs mount, where <id> is a unique id generated
415+ internally.
416+
417+What: /sys/fs/aufs/si_<id>/br0, br1 ... brN
418+Date: March 2009
419+Contact: J. R. Okajima <hooanon05@yahoo.co.jp>
420+Description:
421+ It shows the abolute path of a member directory (which
422+ is called branch) in aufs, and its permission.
423+
424+What: /sys/fs/aufs/si_<id>/xi_path
425+Date: March 2009
426+Contact: J. R. Okajima <hooanon05@yahoo.co.jp>
427+Description:
428+ It shows the abolute path of XINO (External Inode Number
429+ Bitmap, Translation Table and Generation Table) file
430+ even if it is the default path.
431+ When the aufs mount option 'noxino' is specified, it
432+ will be empty. About XINO files, see the aufs manual.
433diff -urN /usr/share/empty/fs/aufs/aufs.h linux/fs/aufs/aufs.h
434--- /usr/share/empty/fs/aufs/aufs.h 1970-01-01 01:00:00.000000000 +0100
87a755f4 435+++ linux/fs/aufs/aufs.h 2011-07-22 08:26:47.854303107 +0200
2cbb1c4b 436@@ -0,0 +1,60 @@
7f207e10 437+/*
027c5e7a 438+ * Copyright (C) 2005-2011 Junjiro R. Okajima
7f207e10
AM
439+ *
440+ * This program, aufs is free software; you can redistribute it and/or modify
441+ * it under the terms of the GNU General Public License as published by
442+ * the Free Software Foundation; either version 2 of the License, or
443+ * (at your option) any later version.
444+ *
445+ * This program is distributed in the hope that it will be useful,
446+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
447+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
448+ * GNU General Public License for more details.
449+ *
450+ * You should have received a copy of the GNU General Public License
451+ * along with this program; if not, write to the Free Software
452+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
453+ */
454+
455+/*
456+ * all header files
457+ */
458+
459+#ifndef __AUFS_H__
460+#define __AUFS_H__
461+
462+#ifdef __KERNEL__
463+
464+#define AuStub(type, name, body, ...) \
465+ static inline type name(__VA_ARGS__) { body; }
466+
467+#define AuStubVoid(name, ...) \
468+ AuStub(void, name, , __VA_ARGS__)
469+#define AuStubInt0(name, ...) \
470+ AuStub(int, name, return 0, __VA_ARGS__)
471+
472+#include "debug.h"
473+
474+#include "branch.h"
475+#include "cpup.h"
476+#include "dcsub.h"
477+#include "dbgaufs.h"
478+#include "dentry.h"
479+#include "dir.h"
480+#include "dynop.h"
481+#include "file.h"
482+#include "fstype.h"
483+#include "inode.h"
484+#include "loop.h"
485+#include "module.h"
7f207e10
AM
486+#include "opts.h"
487+#include "rwsem.h"
488+#include "spl.h"
489+#include "super.h"
490+#include "sysaufs.h"
491+#include "vfsub.h"
492+#include "whout.h"
493+#include "wkq.h"
494+
495+#endif /* __KERNEL__ */
496+#endif /* __AUFS_H__ */
497diff -urN /usr/share/empty/fs/aufs/branch.c linux/fs/aufs/branch.c
498--- /usr/share/empty/fs/aufs/branch.c 1970-01-01 01:00:00.000000000 +0100
87a755f4 499+++ linux/fs/aufs/branch.c 2011-03-17 10:46:59.000000000 +0100
027c5e7a 500@@ -0,0 +1,1160 @@
7f207e10 501+/*
027c5e7a 502+ * Copyright (C) 2005-2011 Junjiro R. Okajima
7f207e10
AM
503+ *
504+ * This program, aufs is free software; you can redistribute it and/or modify
505+ * it under the terms of the GNU General Public License as published by
506+ * the Free Software Foundation; either version 2 of the License, or
507+ * (at your option) any later version.
508+ *
509+ * This program is distributed in the hope that it will be useful,
510+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
511+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
512+ * GNU General Public License for more details.
513+ *
514+ * You should have received a copy of the GNU General Public License
515+ * along with this program; if not, write to the Free Software
516+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
517+ */
518+
519+/*
520+ * branch management
521+ */
522+
027c5e7a 523+#include <linux/compat.h>
7f207e10
AM
524+#include <linux/file.h>
525+#include <linux/statfs.h>
526+#include "aufs.h"
527+
528+/*
529+ * free a single branch
1facf9fc 530+ */
531+static void au_br_do_free(struct au_branch *br)
532+{
533+ int i;
534+ struct au_wbr *wbr;
4a4d8108 535+ struct au_dykey **key;
1facf9fc 536+
027c5e7a
AM
537+ au_hnotify_fin_br(br);
538+
1facf9fc 539+ if (br->br_xino.xi_file)
540+ fput(br->br_xino.xi_file);
541+ mutex_destroy(&br->br_xino.xi_nondir_mtx);
542+
543+ AuDebugOn(atomic_read(&br->br_count));
544+
545+ wbr = br->br_wbr;
546+ if (wbr) {
547+ for (i = 0; i < AuBrWh_Last; i++)
548+ dput(wbr->wbr_wh[i]);
549+ AuDebugOn(atomic_read(&wbr->wbr_wh_running));
dece6358 550+ AuRwDestroy(&wbr->wbr_wh_rwsem);
1facf9fc 551+ }
552+
4a4d8108
AM
553+ key = br->br_dykey;
554+ for (i = 0; i < AuBrDynOp; i++, key++)
555+ if (*key)
556+ au_dy_put(*key);
557+ else
558+ break;
559+
1facf9fc 560+ mntput(br->br_mnt);
1facf9fc 561+ kfree(wbr);
562+ kfree(br);
563+}
564+
565+/*
566+ * frees all branches
567+ */
568+void au_br_free(struct au_sbinfo *sbinfo)
569+{
570+ aufs_bindex_t bmax;
571+ struct au_branch **br;
572+
dece6358
AM
573+ AuRwMustWriteLock(&sbinfo->si_rwsem);
574+
1facf9fc 575+ bmax = sbinfo->si_bend + 1;
576+ br = sbinfo->si_branch;
577+ while (bmax--)
578+ au_br_do_free(*br++);
579+}
580+
581+/*
582+ * find the index of a branch which is specified by @br_id.
583+ */
584+int au_br_index(struct super_block *sb, aufs_bindex_t br_id)
585+{
586+ aufs_bindex_t bindex, bend;
587+
588+ bend = au_sbend(sb);
589+ for (bindex = 0; bindex <= bend; bindex++)
590+ if (au_sbr_id(sb, bindex) == br_id)
591+ return bindex;
592+ return -1;
593+}
594+
595+/* ---------------------------------------------------------------------- */
596+
597+/*
598+ * add a branch
599+ */
600+
b752ccd1
AM
601+static int test_overlap(struct super_block *sb, struct dentry *h_adding,
602+ struct dentry *h_root)
1facf9fc 603+{
b752ccd1
AM
604+ if (unlikely(h_adding == h_root
605+ || au_test_loopback_overlap(sb, h_adding)))
1facf9fc 606+ return 1;
b752ccd1
AM
607+ if (h_adding->d_sb != h_root->d_sb)
608+ return 0;
609+ return au_test_subdir(h_adding, h_root)
610+ || au_test_subdir(h_root, h_adding);
1facf9fc 611+}
612+
613+/*
614+ * returns a newly allocated branch. @new_nbranch is a number of branches
615+ * after adding a branch.
616+ */
617+static struct au_branch *au_br_alloc(struct super_block *sb, int new_nbranch,
618+ int perm)
619+{
620+ struct au_branch *add_branch;
621+ struct dentry *root;
4a4d8108 622+ int err;
1facf9fc 623+
4a4d8108 624+ err = -ENOMEM;
1facf9fc 625+ root = sb->s_root;
626+ add_branch = kmalloc(sizeof(*add_branch), GFP_NOFS);
627+ if (unlikely(!add_branch))
628+ goto out;
629+
027c5e7a
AM
630+ err = au_hnotify_init_br(add_branch, perm);
631+ if (unlikely(err))
632+ goto out_br;
633+
1facf9fc 634+ add_branch->br_wbr = NULL;
635+ if (au_br_writable(perm)) {
636+ /* may be freed separately at changing the branch permission */
637+ add_branch->br_wbr = kmalloc(sizeof(*add_branch->br_wbr),
638+ GFP_NOFS);
639+ if (unlikely(!add_branch->br_wbr))
027c5e7a 640+ goto out_hnotify;
1facf9fc 641+ }
642+
4a4d8108
AM
643+ err = au_sbr_realloc(au_sbi(sb), new_nbranch);
644+ if (!err)
645+ err = au_di_realloc(au_di(root), new_nbranch);
646+ if (!err)
647+ err = au_ii_realloc(au_ii(root->d_inode), new_nbranch);
648+ if (!err)
649+ return add_branch; /* success */
1facf9fc 650+
1facf9fc 651+ kfree(add_branch->br_wbr);
4a4d8108 652+
027c5e7a
AM
653+out_hnotify:
654+ au_hnotify_fin_br(add_branch);
4f0767ce 655+out_br:
1facf9fc 656+ kfree(add_branch);
4f0767ce 657+out:
4a4d8108 658+ return ERR_PTR(err);
1facf9fc 659+}
660+
661+/*
662+ * test if the branch permission is legal or not.
663+ */
664+static int test_br(struct inode *inode, int brperm, char *path)
665+{
666+ int err;
667+
4a4d8108
AM
668+ err = (au_br_writable(brperm) && IS_RDONLY(inode));
669+ if (!err)
670+ goto out;
1facf9fc 671+
4a4d8108
AM
672+ err = -EINVAL;
673+ pr_err("write permission for readonly mount or inode, %s\n", path);
674+
4f0767ce 675+out:
1facf9fc 676+ return err;
677+}
678+
679+/*
680+ * returns:
681+ * 0: success, the caller will add it
682+ * plus: success, it is already unified, the caller should ignore it
683+ * minus: error
684+ */
685+static int test_add(struct super_block *sb, struct au_opt_add *add, int remount)
686+{
687+ int err;
688+ aufs_bindex_t bend, bindex;
689+ struct dentry *root;
690+ struct inode *inode, *h_inode;
691+
692+ root = sb->s_root;
693+ bend = au_sbend(sb);
694+ if (unlikely(bend >= 0
695+ && au_find_dbindex(root, add->path.dentry) >= 0)) {
696+ err = 1;
697+ if (!remount) {
698+ err = -EINVAL;
4a4d8108 699+ pr_err("%s duplicated\n", add->pathname);
1facf9fc 700+ }
701+ goto out;
702+ }
703+
704+ err = -ENOSPC; /* -E2BIG; */
705+ if (unlikely(AUFS_BRANCH_MAX <= add->bindex
706+ || AUFS_BRANCH_MAX - 1 <= bend)) {
4a4d8108 707+ pr_err("number of branches exceeded %s\n", add->pathname);
1facf9fc 708+ goto out;
709+ }
710+
711+ err = -EDOM;
712+ if (unlikely(add->bindex < 0 || bend + 1 < add->bindex)) {
4a4d8108 713+ pr_err("bad index %d\n", add->bindex);
1facf9fc 714+ goto out;
715+ }
716+
717+ inode = add->path.dentry->d_inode;
718+ err = -ENOENT;
719+ if (unlikely(!inode->i_nlink)) {
4a4d8108 720+ pr_err("no existence %s\n", add->pathname);
1facf9fc 721+ goto out;
722+ }
723+
724+ err = -EINVAL;
725+ if (unlikely(inode->i_sb == sb)) {
4a4d8108 726+ pr_err("%s must be outside\n", add->pathname);
1facf9fc 727+ goto out;
728+ }
729+
730+ if (unlikely(au_test_fs_unsuppoted(inode->i_sb))) {
4a4d8108
AM
731+ pr_err("unsupported filesystem, %s (%s)\n",
732+ add->pathname, au_sbtype(inode->i_sb));
1facf9fc 733+ goto out;
734+ }
735+
736+ err = test_br(add->path.dentry->d_inode, add->perm, add->pathname);
737+ if (unlikely(err))
738+ goto out;
739+
740+ if (bend < 0)
741+ return 0; /* success */
742+
743+ err = -EINVAL;
744+ for (bindex = 0; bindex <= bend; bindex++)
745+ if (unlikely(test_overlap(sb, add->path.dentry,
746+ au_h_dptr(root, bindex)))) {
4a4d8108 747+ pr_err("%s is overlapped\n", add->pathname);
1facf9fc 748+ goto out;
749+ }
750+
751+ err = 0;
752+ if (au_opt_test(au_mntflags(sb), WARN_PERM)) {
753+ h_inode = au_h_dptr(root, 0)->d_inode;
754+ if ((h_inode->i_mode & S_IALLUGO) != (inode->i_mode & S_IALLUGO)
755+ || h_inode->i_uid != inode->i_uid
756+ || h_inode->i_gid != inode->i_gid)
4a4d8108
AM
757+ pr_warning("uid/gid/perm %s %u/%u/0%o, %u/%u/0%o\n",
758+ add->pathname,
759+ inode->i_uid, inode->i_gid,
760+ (inode->i_mode & S_IALLUGO),
761+ h_inode->i_uid, h_inode->i_gid,
762+ (h_inode->i_mode & S_IALLUGO));
1facf9fc 763+ }
764+
4f0767ce 765+out:
1facf9fc 766+ return err;
767+}
768+
769+/*
770+ * initialize or clean the whiteouts for an adding branch
771+ */
772+static int au_br_init_wh(struct super_block *sb, struct au_branch *br,
773+ int new_perm, struct dentry *h_root)
774+{
775+ int err, old_perm;
776+ aufs_bindex_t bindex;
777+ struct mutex *h_mtx;
778+ struct au_wbr *wbr;
779+ struct au_hinode *hdir;
780+
781+ wbr = br->br_wbr;
782+ old_perm = br->br_perm;
783+ br->br_perm = new_perm;
784+ hdir = NULL;
785+ h_mtx = NULL;
786+ bindex = au_br_index(sb, br->br_id);
787+ if (0 <= bindex) {
788+ hdir = au_hi(sb->s_root->d_inode, bindex);
4a4d8108 789+ au_hn_imtx_lock_nested(hdir, AuLsc_I_PARENT);
1facf9fc 790+ } else {
791+ h_mtx = &h_root->d_inode->i_mutex;
792+ mutex_lock_nested(h_mtx, AuLsc_I_PARENT);
793+ }
794+ if (!wbr)
795+ err = au_wh_init(h_root, br, sb);
796+ else {
797+ wbr_wh_write_lock(wbr);
798+ err = au_wh_init(h_root, br, sb);
799+ wbr_wh_write_unlock(wbr);
800+ }
801+ if (hdir)
4a4d8108 802+ au_hn_imtx_unlock(hdir);
1facf9fc 803+ else
804+ mutex_unlock(h_mtx);
805+ br->br_perm = old_perm;
806+
807+ if (!err && wbr && !au_br_writable(new_perm)) {
808+ kfree(wbr);
809+ br->br_wbr = NULL;
810+ }
811+
812+ return err;
813+}
814+
815+static int au_wbr_init(struct au_branch *br, struct super_block *sb,
816+ int perm, struct path *path)
817+{
818+ int err;
4a4d8108 819+ struct kstatfs kst;
1facf9fc 820+ struct au_wbr *wbr;
4a4d8108 821+ struct dentry *h_dentry;
1facf9fc 822+
823+ wbr = br->br_wbr;
dece6358 824+ au_rw_init(&wbr->wbr_wh_rwsem);
1facf9fc 825+ memset(wbr->wbr_wh, 0, sizeof(wbr->wbr_wh));
826+ atomic_set(&wbr->wbr_wh_running, 0);
827+ wbr->wbr_bytes = 0;
828+
4a4d8108
AM
829+ /*
830+ * a limit for rmdir/rename a dir
831+ * cf. AUFS_MAX_NAMELEN in include/linux/aufs_type.h
832+ */
7f207e10 833+ err = vfs_statfs(path, &kst);
4a4d8108
AM
834+ if (unlikely(err))
835+ goto out;
836+ err = -EINVAL;
7f207e10 837+ h_dentry = path->dentry;
4a4d8108
AM
838+ if (kst.f_namelen >= NAME_MAX)
839+ err = au_br_init_wh(sb, br, perm, h_dentry);
840+ else
841+ pr_err("%.*s(%s), unsupported namelen %ld\n",
842+ AuDLNPair(h_dentry), au_sbtype(h_dentry->d_sb),
843+ kst.f_namelen);
1facf9fc 844+
4f0767ce 845+out:
1facf9fc 846+ return err;
847+}
848+
849+/* intialize a new branch */
850+static int au_br_init(struct au_branch *br, struct super_block *sb,
851+ struct au_opt_add *add)
852+{
853+ int err;
854+
855+ err = 0;
856+ memset(&br->br_xino, 0, sizeof(br->br_xino));
857+ mutex_init(&br->br_xino.xi_nondir_mtx);
858+ br->br_perm = add->perm;
859+ br->br_mnt = add->path.mnt; /* set first, mntget() later */
4a4d8108
AM
860+ spin_lock_init(&br->br_dykey_lock);
861+ memset(br->br_dykey, 0, sizeof(br->br_dykey));
1facf9fc 862+ atomic_set(&br->br_count, 0);
863+ br->br_xino_upper = AUFS_XINO_TRUNC_INIT;
864+ atomic_set(&br->br_xino_running, 0);
865+ br->br_id = au_new_br_id(sb);
7f207e10 866+ AuDebugOn(br->br_id < 0);
1facf9fc 867+
868+ if (au_br_writable(add->perm)) {
869+ err = au_wbr_init(br, sb, add->perm, &add->path);
870+ if (unlikely(err))
b752ccd1 871+ goto out_err;
1facf9fc 872+ }
873+
874+ if (au_opt_test(au_mntflags(sb), XINO)) {
875+ err = au_xino_br(sb, br, add->path.dentry->d_inode->i_ino,
876+ au_sbr(sb, 0)->br_xino.xi_file, /*do_test*/1);
877+ if (unlikely(err)) {
878+ AuDebugOn(br->br_xino.xi_file);
b752ccd1 879+ goto out_err;
1facf9fc 880+ }
881+ }
882+
883+ sysaufs_br_init(br);
884+ mntget(add->path.mnt);
b752ccd1 885+ goto out; /* success */
1facf9fc 886+
4f0767ce 887+out_err:
b752ccd1 888+ br->br_mnt = NULL;
4f0767ce 889+out:
1facf9fc 890+ return err;
891+}
892+
893+static void au_br_do_add_brp(struct au_sbinfo *sbinfo, aufs_bindex_t bindex,
894+ struct au_branch *br, aufs_bindex_t bend,
895+ aufs_bindex_t amount)
896+{
897+ struct au_branch **brp;
898+
dece6358
AM
899+ AuRwMustWriteLock(&sbinfo->si_rwsem);
900+
1facf9fc 901+ brp = sbinfo->si_branch + bindex;
902+ memmove(brp + 1, brp, sizeof(*brp) * amount);
903+ *brp = br;
904+ sbinfo->si_bend++;
905+ if (unlikely(bend < 0))
906+ sbinfo->si_bend = 0;
907+}
908+
909+static void au_br_do_add_hdp(struct au_dinfo *dinfo, aufs_bindex_t bindex,
910+ aufs_bindex_t bend, aufs_bindex_t amount)
911+{
912+ struct au_hdentry *hdp;
913+
1308ab2a 914+ AuRwMustWriteLock(&dinfo->di_rwsem);
915+
1facf9fc 916+ hdp = dinfo->di_hdentry + bindex;
917+ memmove(hdp + 1, hdp, sizeof(*hdp) * amount);
918+ au_h_dentry_init(hdp);
919+ dinfo->di_bend++;
920+ if (unlikely(bend < 0))
921+ dinfo->di_bstart = 0;
922+}
923+
924+static void au_br_do_add_hip(struct au_iinfo *iinfo, aufs_bindex_t bindex,
925+ aufs_bindex_t bend, aufs_bindex_t amount)
926+{
927+ struct au_hinode *hip;
928+
1308ab2a 929+ AuRwMustWriteLock(&iinfo->ii_rwsem);
930+
1facf9fc 931+ hip = iinfo->ii_hinode + bindex;
932+ memmove(hip + 1, hip, sizeof(*hip) * amount);
933+ hip->hi_inode = NULL;
4a4d8108 934+ au_hn_init(hip);
1facf9fc 935+ iinfo->ii_bend++;
936+ if (unlikely(bend < 0))
937+ iinfo->ii_bstart = 0;
938+}
939+
940+static void au_br_do_add(struct super_block *sb, struct dentry *h_dentry,
941+ struct au_branch *br, aufs_bindex_t bindex)
942+{
943+ struct dentry *root;
944+ struct inode *root_inode;
945+ aufs_bindex_t bend, amount;
946+
947+ root = sb->s_root;
948+ root_inode = root->d_inode;
1facf9fc 949+ bend = au_sbend(sb);
950+ amount = bend + 1 - bindex;
951+ au_br_do_add_brp(au_sbi(sb), bindex, br, bend, amount);
952+ au_br_do_add_hdp(au_di(root), bindex, bend, amount);
953+ au_br_do_add_hip(au_ii(root_inode), bindex, bend, amount);
954+ au_set_h_dptr(root, bindex, dget(h_dentry));
955+ au_set_h_iptr(root_inode, bindex, au_igrab(h_dentry->d_inode),
956+ /*flags*/0);
957+}
958+
959+int au_br_add(struct super_block *sb, struct au_opt_add *add, int remount)
960+{
961+ int err;
1facf9fc 962+ aufs_bindex_t bend, add_bindex;
963+ struct dentry *root, *h_dentry;
964+ struct inode *root_inode;
965+ struct au_branch *add_branch;
966+
967+ root = sb->s_root;
968+ root_inode = root->d_inode;
969+ IMustLock(root_inode);
970+ err = test_add(sb, add, remount);
971+ if (unlikely(err < 0))
972+ goto out;
973+ if (err) {
974+ err = 0;
975+ goto out; /* success */
976+ }
977+
978+ bend = au_sbend(sb);
979+ add_branch = au_br_alloc(sb, bend + 2, add->perm);
980+ err = PTR_ERR(add_branch);
981+ if (IS_ERR(add_branch))
982+ goto out;
983+
984+ err = au_br_init(add_branch, sb, add);
985+ if (unlikely(err)) {
986+ au_br_do_free(add_branch);
987+ goto out;
988+ }
989+
990+ add_bindex = add->bindex;
991+ h_dentry = add->path.dentry;
992+ if (!remount)
993+ au_br_do_add(sb, h_dentry, add_branch, add_bindex);
994+ else {
995+ sysaufs_brs_del(sb, add_bindex);
996+ au_br_do_add(sb, h_dentry, add_branch, add_bindex);
997+ sysaufs_brs_add(sb, add_bindex);
998+ }
999+
1308ab2a 1000+ if (!add_bindex) {
1facf9fc 1001+ au_cpup_attr_all(root_inode, /*force*/1);
1308ab2a 1002+ sb->s_maxbytes = h_dentry->d_sb->s_maxbytes;
1003+ } else
1facf9fc 1004+ au_add_nlink(root_inode, h_dentry->d_inode);
1facf9fc 1005+
1006+ /*
4a4d8108 1007+ * this test/set prevents aufs from handling unnecesary notify events
027c5e7a 1008+ * of xino files, in case of re-adding a writable branch which was
1facf9fc 1009+ * once detached from aufs.
1010+ */
1011+ if (au_xino_brid(sb) < 0
1012+ && au_br_writable(add_branch->br_perm)
1013+ && !au_test_fs_bad_xino(h_dentry->d_sb)
1014+ && add_branch->br_xino.xi_file
1015+ && add_branch->br_xino.xi_file->f_dentry->d_parent == h_dentry)
1016+ au_xino_brid_set(sb, add_branch->br_id);
1017+
4f0767ce 1018+out:
1facf9fc 1019+ return err;
1020+}
1021+
1022+/* ---------------------------------------------------------------------- */
1023+
1024+/*
1025+ * delete a branch
1026+ */
1027+
1028+/* to show the line number, do not make it inlined function */
4a4d8108 1029+#define AuVerbose(do_info, fmt, ...) do { \
1facf9fc 1030+ if (do_info) \
4a4d8108 1031+ pr_info(fmt, ##__VA_ARGS__); \
1facf9fc 1032+} while (0)
1033+
027c5e7a
AM
1034+static int au_test_ibusy(struct inode *inode, aufs_bindex_t bstart,
1035+ aufs_bindex_t bend)
1036+{
1037+ return (inode && !S_ISDIR(inode->i_mode)) || bstart == bend;
1038+}
1039+
1040+static int au_test_dbusy(struct dentry *dentry, aufs_bindex_t bstart,
1041+ aufs_bindex_t bend)
1042+{
1043+ return au_test_ibusy(dentry->d_inode, bstart, bend);
1044+}
1045+
1facf9fc 1046+/*
1047+ * test if the branch is deletable or not.
1048+ */
1049+static int test_dentry_busy(struct dentry *root, aufs_bindex_t bindex,
b752ccd1 1050+ unsigned int sigen, const unsigned int verbose)
1facf9fc 1051+{
1052+ int err, i, j, ndentry;
1053+ aufs_bindex_t bstart, bend;
1facf9fc 1054+ struct au_dcsub_pages dpages;
1055+ struct au_dpage *dpage;
1056+ struct dentry *d;
1facf9fc 1057+
1058+ err = au_dpages_init(&dpages, GFP_NOFS);
1059+ if (unlikely(err))
1060+ goto out;
1061+ err = au_dcsub_pages(&dpages, root, NULL, NULL);
1062+ if (unlikely(err))
1063+ goto out_dpages;
1064+
1facf9fc 1065+ for (i = 0; !err && i < dpages.ndpage; i++) {
1066+ dpage = dpages.dpages + i;
1067+ ndentry = dpage->ndentry;
1068+ for (j = 0; !err && j < ndentry; j++) {
1069+ d = dpage->dentries[j];
027c5e7a
AM
1070+ AuDebugOn(!d->d_count);
1071+ if (!au_digen_test(d, sigen)) {
1facf9fc 1072+ di_read_lock_child(d, AuLock_IR);
027c5e7a
AM
1073+ if (unlikely(au_dbrange_test(d))) {
1074+ di_read_unlock(d, AuLock_IR);
1075+ continue;
1076+ }
1077+ } else {
1facf9fc 1078+ di_write_lock_child(d);
027c5e7a
AM
1079+ if (unlikely(au_dbrange_test(d))) {
1080+ di_write_unlock(d);
1081+ continue;
1082+ }
1facf9fc 1083+ err = au_reval_dpath(d, sigen);
1084+ if (!err)
1085+ di_downgrade_lock(d, AuLock_IR);
1086+ else {
1087+ di_write_unlock(d);
1088+ break;
1089+ }
1090+ }
1091+
027c5e7a 1092+ /* AuDbgDentry(d); */
1facf9fc 1093+ bstart = au_dbstart(d);
1094+ bend = au_dbend(d);
1095+ if (bstart <= bindex
1096+ && bindex <= bend
1097+ && au_h_dptr(d, bindex)
027c5e7a 1098+ && au_test_dbusy(d, bstart, bend)) {
1facf9fc 1099+ err = -EBUSY;
1100+ AuVerbose(verbose, "busy %.*s\n", AuDLNPair(d));
027c5e7a 1101+ AuDbgDentry(d);
1facf9fc 1102+ }
1103+ di_read_unlock(d, AuLock_IR);
1104+ }
1105+ }
1106+
4f0767ce 1107+out_dpages:
1facf9fc 1108+ au_dpages_free(&dpages);
4f0767ce 1109+out:
1facf9fc 1110+ return err;
1111+}
1112+
1113+static int test_inode_busy(struct super_block *sb, aufs_bindex_t bindex,
b752ccd1 1114+ unsigned int sigen, const unsigned int verbose)
1facf9fc 1115+{
1116+ int err;
7f207e10
AM
1117+ unsigned long long max, ull;
1118+ struct inode *i, **array;
1facf9fc 1119+ aufs_bindex_t bstart, bend;
1facf9fc 1120+
7f207e10
AM
1121+ array = au_iarray_alloc(sb, &max);
1122+ err = PTR_ERR(array);
1123+ if (IS_ERR(array))
1124+ goto out;
1125+
1facf9fc 1126+ err = 0;
7f207e10
AM
1127+ AuDbg("b%d\n", bindex);
1128+ for (ull = 0; !err && ull < max; ull++) {
1129+ i = array[ull];
1130+ if (i->i_ino == AUFS_ROOT_INO)
1facf9fc 1131+ continue;
1132+
7f207e10 1133+ /* AuDbgInode(i); */
1facf9fc 1134+ if (au_iigen(i) == sigen)
1135+ ii_read_lock_child(i);
1136+ else {
1137+ ii_write_lock_child(i);
027c5e7a
AM
1138+ err = au_refresh_hinode_self(i);
1139+ au_iigen_dec(i);
1facf9fc 1140+ if (!err)
1141+ ii_downgrade_lock(i);
1142+ else {
1143+ ii_write_unlock(i);
1144+ break;
1145+ }
1146+ }
1147+
1148+ bstart = au_ibstart(i);
1149+ bend = au_ibend(i);
1150+ if (bstart <= bindex
1151+ && bindex <= bend
1152+ && au_h_iptr(i, bindex)
027c5e7a 1153+ && au_test_ibusy(i, bstart, bend)) {
1facf9fc 1154+ err = -EBUSY;
1155+ AuVerbose(verbose, "busy i%lu\n", i->i_ino);
7f207e10 1156+ AuDbgInode(i);
1facf9fc 1157+ }
1158+ ii_read_unlock(i);
1159+ }
7f207e10 1160+ au_iarray_free(array, max);
1facf9fc 1161+
7f207e10 1162+out:
1facf9fc 1163+ return err;
1164+}
1165+
b752ccd1
AM
1166+static int test_children_busy(struct dentry *root, aufs_bindex_t bindex,
1167+ const unsigned int verbose)
1facf9fc 1168+{
1169+ int err;
1170+ unsigned int sigen;
1171+
1172+ sigen = au_sigen(root->d_sb);
1173+ DiMustNoWaiters(root);
1174+ IiMustNoWaiters(root->d_inode);
1175+ di_write_unlock(root);
b752ccd1 1176+ err = test_dentry_busy(root, bindex, sigen, verbose);
1facf9fc 1177+ if (!err)
b752ccd1 1178+ err = test_inode_busy(root->d_sb, bindex, sigen, verbose);
1facf9fc 1179+ di_write_lock_child(root); /* aufs_write_lock() calls ..._child() */
1180+
1181+ return err;
1182+}
1183+
1184+static void au_br_do_del_brp(struct au_sbinfo *sbinfo,
1185+ const aufs_bindex_t bindex,
1186+ const aufs_bindex_t bend)
1187+{
1188+ struct au_branch **brp, **p;
1189+
dece6358
AM
1190+ AuRwMustWriteLock(&sbinfo->si_rwsem);
1191+
1facf9fc 1192+ brp = sbinfo->si_branch + bindex;
1193+ if (bindex < bend)
1194+ memmove(brp, brp + 1, sizeof(*brp) * (bend - bindex));
1195+ sbinfo->si_branch[0 + bend] = NULL;
1196+ sbinfo->si_bend--;
1197+
1198+ p = krealloc(sbinfo->si_branch, sizeof(*p) * bend, GFP_NOFS);
1199+ if (p)
1200+ sbinfo->si_branch = p;
4a4d8108 1201+ /* harmless error */
1facf9fc 1202+}
1203+
1204+static void au_br_do_del_hdp(struct au_dinfo *dinfo, const aufs_bindex_t bindex,
1205+ const aufs_bindex_t bend)
1206+{
1207+ struct au_hdentry *hdp, *p;
1208+
1308ab2a 1209+ AuRwMustWriteLock(&dinfo->di_rwsem);
1210+
4a4d8108 1211+ hdp = dinfo->di_hdentry;
1facf9fc 1212+ if (bindex < bend)
4a4d8108
AM
1213+ memmove(hdp + bindex, hdp + bindex + 1,
1214+ sizeof(*hdp) * (bend - bindex));
1215+ hdp[0 + bend].hd_dentry = NULL;
1facf9fc 1216+ dinfo->di_bend--;
1217+
4a4d8108 1218+ p = krealloc(hdp, sizeof(*p) * bend, GFP_NOFS);
1facf9fc 1219+ if (p)
1220+ dinfo->di_hdentry = p;
4a4d8108 1221+ /* harmless error */
1facf9fc 1222+}
1223+
1224+static void au_br_do_del_hip(struct au_iinfo *iinfo, const aufs_bindex_t bindex,
1225+ const aufs_bindex_t bend)
1226+{
1227+ struct au_hinode *hip, *p;
1228+
1308ab2a 1229+ AuRwMustWriteLock(&iinfo->ii_rwsem);
1230+
1facf9fc 1231+ hip = iinfo->ii_hinode + bindex;
1232+ if (bindex < bend)
1233+ memmove(hip, hip + 1, sizeof(*hip) * (bend - bindex));
1234+ iinfo->ii_hinode[0 + bend].hi_inode = NULL;
4a4d8108 1235+ au_hn_init(iinfo->ii_hinode + bend);
1facf9fc 1236+ iinfo->ii_bend--;
1237+
1238+ p = krealloc(iinfo->ii_hinode, sizeof(*p) * bend, GFP_NOFS);
1239+ if (p)
1240+ iinfo->ii_hinode = p;
4a4d8108 1241+ /* harmless error */
1facf9fc 1242+}
1243+
1244+static void au_br_do_del(struct super_block *sb, aufs_bindex_t bindex,
1245+ struct au_branch *br)
1246+{
1247+ aufs_bindex_t bend;
1248+ struct au_sbinfo *sbinfo;
1249+ struct dentry *root;
1250+ struct inode *inode;
1251+
dece6358
AM
1252+ SiMustWriteLock(sb);
1253+
1facf9fc 1254+ root = sb->s_root;
1255+ inode = root->d_inode;
1facf9fc 1256+ sbinfo = au_sbi(sb);
1257+ bend = sbinfo->si_bend;
1258+
1259+ dput(au_h_dptr(root, bindex));
1260+ au_hiput(au_hi(inode, bindex));
1261+ au_br_do_free(br);
1262+
1263+ au_br_do_del_brp(sbinfo, bindex, bend);
1264+ au_br_do_del_hdp(au_di(root), bindex, bend);
1265+ au_br_do_del_hip(au_ii(inode), bindex, bend);
1266+}
1267+
1268+int au_br_del(struct super_block *sb, struct au_opt_del *del, int remount)
1269+{
1270+ int err, rerr, i;
1271+ unsigned int mnt_flags;
1272+ aufs_bindex_t bindex, bend, br_id;
1273+ unsigned char do_wh, verbose;
1274+ struct au_branch *br;
1275+ struct au_wbr *wbr;
1276+
1277+ err = 0;
1278+ bindex = au_find_dbindex(sb->s_root, del->h_path.dentry);
1279+ if (bindex < 0) {
1280+ if (remount)
1281+ goto out; /* success */
1282+ err = -ENOENT;
4a4d8108 1283+ pr_err("%s no such branch\n", del->pathname);
1facf9fc 1284+ goto out;
1285+ }
1286+ AuDbg("bindex b%d\n", bindex);
1287+
1288+ err = -EBUSY;
1289+ mnt_flags = au_mntflags(sb);
1290+ verbose = !!au_opt_test(mnt_flags, VERBOSE);
1291+ bend = au_sbend(sb);
1292+ if (unlikely(!bend)) {
1293+ AuVerbose(verbose, "no more branches left\n");
1294+ goto out;
1295+ }
1296+ br = au_sbr(sb, bindex);
1297+ i = atomic_read(&br->br_count);
1298+ if (unlikely(i)) {
1299+ AuVerbose(verbose, "%d file(s) opened\n", i);
e49829fe 1300+ goto out;
1facf9fc 1301+ }
1302+
1303+ wbr = br->br_wbr;
1304+ do_wh = wbr && (wbr->wbr_whbase || wbr->wbr_plink || wbr->wbr_orph);
1305+ if (do_wh) {
1308ab2a 1306+ /* instead of WbrWhMustWriteLock(wbr) */
1307+ SiMustWriteLock(sb);
1facf9fc 1308+ for (i = 0; i < AuBrWh_Last; i++) {
1309+ dput(wbr->wbr_wh[i]);
1310+ wbr->wbr_wh[i] = NULL;
1311+ }
1312+ }
1313+
b752ccd1 1314+ err = test_children_busy(sb->s_root, bindex, verbose);
1facf9fc 1315+ if (unlikely(err)) {
1316+ if (do_wh)
1317+ goto out_wh;
1318+ goto out;
1319+ }
1320+
1321+ err = 0;
1322+ br_id = br->br_id;
1323+ if (!remount)
1324+ au_br_do_del(sb, bindex, br);
1325+ else {
1326+ sysaufs_brs_del(sb, bindex);
1327+ au_br_do_del(sb, bindex, br);
1328+ sysaufs_brs_add(sb, bindex);
1329+ }
1330+
1308ab2a 1331+ if (!bindex) {
1facf9fc 1332+ au_cpup_attr_all(sb->s_root->d_inode, /*force*/1);
1308ab2a 1333+ sb->s_maxbytes = au_sbr_sb(sb, 0)->s_maxbytes;
1334+ } else
1facf9fc 1335+ au_sub_nlink(sb->s_root->d_inode, del->h_path.dentry->d_inode);
1336+ if (au_opt_test(mnt_flags, PLINK))
1337+ au_plink_half_refresh(sb, br_id);
1338+
b752ccd1 1339+ if (au_xino_brid(sb) == br_id)
1facf9fc 1340+ au_xino_brid_set(sb, -1);
1341+ goto out; /* success */
1342+
4f0767ce 1343+out_wh:
1facf9fc 1344+ /* revert */
1345+ rerr = au_br_init_wh(sb, br, br->br_perm, del->h_path.dentry);
1346+ if (rerr)
4a4d8108
AM
1347+ pr_warning("failed re-creating base whiteout, %s. (%d)\n",
1348+ del->pathname, rerr);
4f0767ce 1349+out:
1facf9fc 1350+ return err;
1351+}
1352+
1353+/* ---------------------------------------------------------------------- */
1354+
027c5e7a
AM
1355+static int au_ibusy(struct super_block *sb, struct aufs_ibusy __user *arg)
1356+{
1357+ int err;
1358+ aufs_bindex_t bstart, bend;
1359+ struct aufs_ibusy ibusy;
1360+ struct inode *inode, *h_inode;
1361+
1362+ err = -EPERM;
1363+ if (unlikely(!capable(CAP_SYS_ADMIN)))
1364+ goto out;
1365+
1366+ err = copy_from_user(&ibusy, arg, sizeof(ibusy));
1367+ if (!err)
1368+ err = !access_ok(VERIFY_WRITE, &arg->h_ino, sizeof(arg->h_ino));
1369+ if (unlikely(err)) {
1370+ err = -EFAULT;
1371+ AuTraceErr(err);
1372+ goto out;
1373+ }
1374+
1375+ err = -EINVAL;
1376+ si_read_lock(sb, AuLock_FLUSH);
1377+ if (unlikely(ibusy.bindex < 0 || ibusy.bindex > au_sbend(sb)))
1378+ goto out_unlock;
1379+
1380+ err = 0;
1381+ ibusy.h_ino = 0; /* invalid */
1382+ inode = ilookup(sb, ibusy.ino);
1383+ if (!inode
1384+ || inode->i_ino == AUFS_ROOT_INO
1385+ || is_bad_inode(inode))
1386+ goto out_unlock;
1387+
1388+ ii_read_lock_child(inode);
1389+ bstart = au_ibstart(inode);
1390+ bend = au_ibend(inode);
1391+ if (bstart <= ibusy.bindex && ibusy.bindex <= bend) {
1392+ h_inode = au_h_iptr(inode, ibusy.bindex);
1393+ if (h_inode && au_test_ibusy(inode, bstart, bend))
1394+ ibusy.h_ino = h_inode->i_ino;
1395+ }
1396+ ii_read_unlock(inode);
1397+ iput(inode);
1398+
1399+out_unlock:
1400+ si_read_unlock(sb);
1401+ if (!err) {
1402+ err = __put_user(ibusy.h_ino, &arg->h_ino);
1403+ if (unlikely(err)) {
1404+ err = -EFAULT;
1405+ AuTraceErr(err);
1406+ }
1407+ }
1408+out:
1409+ return err;
1410+}
1411+
1412+long au_ibusy_ioctl(struct file *file, unsigned long arg)
1413+{
1414+ return au_ibusy(file->f_dentry->d_sb, (void __user *)arg);
1415+}
1416+
1417+#ifdef CONFIG_COMPAT
1418+long au_ibusy_compat_ioctl(struct file *file, unsigned long arg)
1419+{
1420+ return au_ibusy(file->f_dentry->d_sb, compat_ptr(arg));
1421+}
1422+#endif
1423+
1424+/* ---------------------------------------------------------------------- */
1425+
1facf9fc 1426+/*
1427+ * change a branch permission
1428+ */
1429+
dece6358
AM
1430+static void au_warn_ima(void)
1431+{
1432+#ifdef CONFIG_IMA
1308ab2a 1433+ /* since it doesn't support mark_files_ro() */
027c5e7a 1434+ AuWarn1("RW -> RO makes IMA to produce wrong message\n");
dece6358
AM
1435+#endif
1436+}
1437+
1facf9fc 1438+static int do_need_sigen_inc(int a, int b)
1439+{
1440+ return au_br_whable(a) && !au_br_whable(b);
1441+}
1442+
1443+static int need_sigen_inc(int old, int new)
1444+{
1445+ return do_need_sigen_inc(old, new)
1446+ || do_need_sigen_inc(new, old);
1447+}
1448+
7f207e10
AM
1449+static unsigned long long au_farray_cb(void *a,
1450+ unsigned long long max __maybe_unused,
1451+ void *arg)
1452+{
1453+ unsigned long long n;
1454+ struct file **p, *f;
1455+ struct super_block *sb = arg;
1456+
1457+ n = 0;
1458+ p = a;
1459+ lg_global_lock(files_lglock);
1460+ do_file_list_for_each_entry(sb, f) {
1461+ if (au_fi(f)
027c5e7a 1462+ && file_count(f)
7f207e10
AM
1463+ && !special_file(f->f_dentry->d_inode->i_mode)) {
1464+ get_file(f);
1465+ *p++ = f;
1466+ n++;
1467+ AuDebugOn(n > max);
1468+ }
1469+ } while_file_list_for_each_entry;
1470+ lg_global_unlock(files_lglock);
1471+
1472+ return n;
1473+}
1474+
1475+static struct file **au_farray_alloc(struct super_block *sb,
1476+ unsigned long long *max)
1477+{
1478+ *max = atomic_long_read(&au_sbi(sb)->si_nfiles);
1479+ return au_array_alloc(max, au_farray_cb, sb);
1480+}
1481+
1482+static void au_farray_free(struct file **a, unsigned long long max)
1483+{
1484+ unsigned long long ull;
1485+
1486+ for (ull = 0; ull < max; ull++)
1487+ if (a[ull])
1488+ fput(a[ull]);
1489+ au_array_free(a);
1490+}
1491+
1facf9fc 1492+static int au_br_mod_files_ro(struct super_block *sb, aufs_bindex_t bindex)
1493+{
7f207e10 1494+ int err, do_warn;
027c5e7a 1495+ unsigned int mnt_flags;
7f207e10 1496+ unsigned long long ull, max;
e49829fe 1497+ aufs_bindex_t br_id;
027c5e7a 1498+ unsigned char verbose;
7f207e10 1499+ struct file *file, *hf, **array;
e49829fe
JR
1500+ struct inode *inode;
1501+ struct au_hfile *hfile;
1facf9fc 1502+
027c5e7a
AM
1503+ mnt_flags = au_mntflags(sb);
1504+ verbose = !!au_opt_test(mnt_flags, VERBOSE);
1505+
7f207e10
AM
1506+ array = au_farray_alloc(sb, &max);
1507+ err = PTR_ERR(array);
1508+ if (IS_ERR(array))
1facf9fc 1509+ goto out;
1510+
7f207e10 1511+ do_warn = 0;
e49829fe 1512+ br_id = au_sbr_id(sb, bindex);
7f207e10
AM
1513+ for (ull = 0; ull < max; ull++) {
1514+ file = array[ull];
1facf9fc 1515+
7f207e10 1516+ /* AuDbg("%.*s\n", AuDLNPair(file->f_dentry)); */
1facf9fc 1517+ fi_read_lock(file);
1518+ if (unlikely(au_test_mmapped(file))) {
1519+ err = -EBUSY;
027c5e7a
AM
1520+ AuVerbose(verbose, "mmapped %.*s\n",
1521+ AuDLNPair(file->f_dentry));
7f207e10 1522+ AuDbgFile(file);
1facf9fc 1523+ FiMustNoWaiters(file);
1524+ fi_read_unlock(file);
7f207e10 1525+ goto out_array;
1facf9fc 1526+ }
1527+
027c5e7a 1528+ inode = file->f_dentry->d_inode;
e49829fe
JR
1529+ hfile = &au_fi(file)->fi_htop;
1530+ hf = hfile->hf_file;
1531+ if (!S_ISREG(inode->i_mode)
1facf9fc 1532+ || !(file->f_mode & FMODE_WRITE)
e49829fe 1533+ || hfile->hf_br->br_id != br_id
7f207e10
AM
1534+ || !(hf->f_mode & FMODE_WRITE))
1535+ array[ull] = NULL;
1536+ else {
1537+ do_warn = 1;
1538+ get_file(file);
1facf9fc 1539+ }
1540+
1facf9fc 1541+ FiMustNoWaiters(file);
1542+ fi_read_unlock(file);
7f207e10
AM
1543+ fput(file);
1544+ }
1facf9fc 1545+
1546+ err = 0;
7f207e10 1547+ if (do_warn)
dece6358 1548+ au_warn_ima();
7f207e10
AM
1549+
1550+ for (ull = 0; ull < max; ull++) {
1551+ file = array[ull];
1552+ if (!file)
1553+ continue;
1554+
1facf9fc 1555+ /* todo: already flushed? */
1556+ /* cf. fs/super.c:mark_files_ro() */
7f207e10
AM
1557+ /* fi_read_lock(file); */
1558+ hfile = &au_fi(file)->fi_htop;
1559+ hf = hfile->hf_file;
1560+ /* fi_read_unlock(file); */
027c5e7a 1561+ spin_lock(&hf->f_lock);
1facf9fc 1562+ hf->f_mode &= ~FMODE_WRITE;
027c5e7a 1563+ spin_unlock(&hf->f_lock);
1facf9fc 1564+ if (!file_check_writeable(hf)) {
1565+ file_release_write(hf);
1566+ mnt_drop_write(hf->f_vfsmnt);
1567+ }
1568+ }
1569+
7f207e10
AM
1570+out_array:
1571+ au_farray_free(array, max);
4f0767ce 1572+out:
7f207e10 1573+ AuTraceErr(err);
1facf9fc 1574+ return err;
1575+}
1576+
1577+int au_br_mod(struct super_block *sb, struct au_opt_mod *mod, int remount,
7f207e10 1578+ int *do_refresh)
1facf9fc 1579+{
1580+ int err, rerr;
1581+ aufs_bindex_t bindex;
1308ab2a 1582+ struct path path;
1facf9fc 1583+ struct dentry *root;
1584+ struct au_branch *br;
1585+
1586+ root = sb->s_root;
1facf9fc 1587+ bindex = au_find_dbindex(root, mod->h_root);
1588+ if (bindex < 0) {
1589+ if (remount)
1590+ return 0; /* success */
1591+ err = -ENOENT;
4a4d8108 1592+ pr_err("%s no such branch\n", mod->path);
1facf9fc 1593+ goto out;
1594+ }
1595+ AuDbg("bindex b%d\n", bindex);
1596+
1597+ err = test_br(mod->h_root->d_inode, mod->perm, mod->path);
1598+ if (unlikely(err))
1599+ goto out;
1600+
1601+ br = au_sbr(sb, bindex);
1602+ if (br->br_perm == mod->perm)
1603+ return 0; /* success */
1604+
1605+ if (au_br_writable(br->br_perm)) {
1606+ /* remove whiteout base */
1607+ err = au_br_init_wh(sb, br, mod->perm, mod->h_root);
1608+ if (unlikely(err))
1609+ goto out;
1610+
1611+ if (!au_br_writable(mod->perm)) {
1612+ /* rw --> ro, file might be mmapped */
1613+ DiMustNoWaiters(root);
1614+ IiMustNoWaiters(root->d_inode);
1615+ di_write_unlock(root);
1616+ err = au_br_mod_files_ro(sb, bindex);
1617+ /* aufs_write_lock() calls ..._child() */
1618+ di_write_lock_child(root);
1619+
1620+ if (unlikely(err)) {
1621+ rerr = -ENOMEM;
1622+ br->br_wbr = kmalloc(sizeof(*br->br_wbr),
1623+ GFP_NOFS);
1308ab2a 1624+ if (br->br_wbr) {
1625+ path.mnt = br->br_mnt;
1626+ path.dentry = mod->h_root;
1627+ rerr = au_wbr_init(br, sb, br->br_perm,
1628+ &path);
1629+ }
1facf9fc 1630+ if (unlikely(rerr)) {
1631+ AuIOErr("nested error %d (%d)\n",
1632+ rerr, err);
1633+ br->br_perm = mod->perm;
1634+ }
1635+ }
1636+ }
1637+ } else if (au_br_writable(mod->perm)) {
1638+ /* ro --> rw */
1639+ err = -ENOMEM;
1640+ br->br_wbr = kmalloc(sizeof(*br->br_wbr), GFP_NOFS);
1641+ if (br->br_wbr) {
1308ab2a 1642+ path.mnt = br->br_mnt;
1643+ path.dentry = mod->h_root;
1facf9fc 1644+ err = au_wbr_init(br, sb, mod->perm, &path);
1645+ if (unlikely(err)) {
1646+ kfree(br->br_wbr);
1647+ br->br_wbr = NULL;
1648+ }
1649+ }
1650+ }
1651+
1652+ if (!err) {
7f207e10 1653+ *do_refresh |= need_sigen_inc(br->br_perm, mod->perm);
1facf9fc 1654+ br->br_perm = mod->perm;
1655+ }
1656+
4f0767ce 1657+out:
7f207e10 1658+ AuTraceErr(err);
1facf9fc 1659+ return err;
1660+}
7f207e10
AM
1661diff -urN /usr/share/empty/fs/aufs/branch.h linux/fs/aufs/branch.h
1662--- /usr/share/empty/fs/aufs/branch.h 1970-01-01 01:00:00.000000000 +0100
87a755f4 1663+++ linux/fs/aufs/branch.h 2011-03-17 10:46:59.000000000 +0100
027c5e7a 1664@@ -0,0 +1,233 @@
1facf9fc 1665+/*
027c5e7a 1666+ * Copyright (C) 2005-2011 Junjiro R. Okajima
1facf9fc 1667+ *
1668+ * This program, aufs is free software; you can redistribute it and/or modify
1669+ * it under the terms of the GNU General Public License as published by
1670+ * the Free Software Foundation; either version 2 of the License, or
1671+ * (at your option) any later version.
dece6358
AM
1672+ *
1673+ * This program is distributed in the hope that it will be useful,
1674+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1675+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1676+ * GNU General Public License for more details.
1677+ *
1678+ * You should have received a copy of the GNU General Public License
1679+ * along with this program; if not, write to the Free Software
1680+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 1681+ */
1682+
1683+/*
1684+ * branch filesystems and xino for them
1685+ */
1686+
1687+#ifndef __AUFS_BRANCH_H__
1688+#define __AUFS_BRANCH_H__
1689+
1690+#ifdef __KERNEL__
1691+
1692+#include <linux/fs.h>
1693+#include <linux/mount.h>
1facf9fc 1694+#include <linux/aufs_type.h>
4a4d8108 1695+#include "dynop.h"
1facf9fc 1696+#include "rwsem.h"
1697+#include "super.h"
1698+
1699+/* ---------------------------------------------------------------------- */
1700+
1701+/* a xino file */
1702+struct au_xino_file {
1703+ struct file *xi_file;
1704+ struct mutex xi_nondir_mtx;
1705+
1706+ /* todo: make xino files an array to support huge inode number */
1707+
1708+#ifdef CONFIG_DEBUG_FS
1709+ struct dentry *xi_dbgaufs;
1710+#endif
1711+};
1712+
1713+/* members for writable branch only */
1714+enum {AuBrWh_BASE, AuBrWh_PLINK, AuBrWh_ORPH, AuBrWh_Last};
1715+struct au_wbr {
dece6358 1716+ struct au_rwsem wbr_wh_rwsem;
1facf9fc 1717+ struct dentry *wbr_wh[AuBrWh_Last];
4a4d8108 1718+ atomic_t wbr_wh_running;
1facf9fc 1719+#define wbr_whbase wbr_wh[AuBrWh_BASE] /* whiteout base */
1720+#define wbr_plink wbr_wh[AuBrWh_PLINK] /* pseudo-link dir */
1721+#define wbr_orph wbr_wh[AuBrWh_ORPH] /* dir for orphans */
1722+
1723+ /* mfs mode */
1724+ unsigned long long wbr_bytes;
1725+};
1726+
4a4d8108
AM
1727+/* ext2 has 3 types of operations at least, ext3 has 4 */
1728+#define AuBrDynOp (AuDyLast * 4)
1729+
1facf9fc 1730+/* protected by superblock rwsem */
1731+struct au_branch {
1732+ struct au_xino_file br_xino;
1733+
1734+ aufs_bindex_t br_id;
1735+
1736+ int br_perm;
1737+ struct vfsmount *br_mnt;
4a4d8108
AM
1738+ spinlock_t br_dykey_lock;
1739+ struct au_dykey *br_dykey[AuBrDynOp];
1facf9fc 1740+ atomic_t br_count;
1741+
1742+ struct au_wbr *br_wbr;
1743+
1744+ /* xino truncation */
1745+ blkcnt_t br_xino_upper; /* watermark in blocks */
1746+ atomic_t br_xino_running;
1747+
027c5e7a
AM
1748+#ifdef CONFIG_AUFS_HFSNOTIFY
1749+ struct fsnotify_group *br_hfsn_group;
1750+ struct fsnotify_ops br_hfsn_ops;
1751+#endif
1752+
1facf9fc 1753+#ifdef CONFIG_SYSFS
1754+ /* an entry under sysfs per mount-point */
1755+ char br_name[8];
1756+ struct attribute br_attr;
1757+#endif
1758+};
1759+
1760+/* ---------------------------------------------------------------------- */
1761+
1762+/* branch permission and attribute */
1763+enum {
1764+ AuBrPerm_RW, /* writable, linkable wh */
1765+ AuBrPerm_RO, /* readonly, no wh */
1766+ AuBrPerm_RR, /* natively readonly, no wh */
1767+
1768+ AuBrPerm_RWNoLinkWH, /* un-linkable whiteouts */
1769+
1770+ AuBrPerm_ROWH, /* whiteout-able */
1771+ AuBrPerm_RRWH, /* whiteout-able */
1772+
1773+ AuBrPerm_Last
1774+};
1775+
1776+static inline int au_br_writable(int brperm)
1777+{
1778+ return brperm == AuBrPerm_RW || brperm == AuBrPerm_RWNoLinkWH;
1779+}
1780+
1781+static inline int au_br_whable(int brperm)
1782+{
1783+ return brperm == AuBrPerm_RW
1784+ || brperm == AuBrPerm_ROWH
1785+ || brperm == AuBrPerm_RRWH;
1786+}
1787+
1788+static inline int au_br_rdonly(struct au_branch *br)
1789+{
1790+ return ((br->br_mnt->mnt_sb->s_flags & MS_RDONLY)
1791+ || !au_br_writable(br->br_perm))
1792+ ? -EROFS : 0;
1793+}
1794+
4a4d8108 1795+static inline int au_br_hnotifyable(int brperm __maybe_unused)
1facf9fc 1796+{
4a4d8108 1797+#ifdef CONFIG_AUFS_HNOTIFY
1facf9fc 1798+ return brperm != AuBrPerm_RR && brperm != AuBrPerm_RRWH;
1799+#else
1800+ return 0;
1801+#endif
1802+}
1803+
1804+/* ---------------------------------------------------------------------- */
1805+
1806+/* branch.c */
1807+struct au_sbinfo;
1808+void au_br_free(struct au_sbinfo *sinfo);
1809+int au_br_index(struct super_block *sb, aufs_bindex_t br_id);
1810+struct au_opt_add;
1811+int au_br_add(struct super_block *sb, struct au_opt_add *add, int remount);
1812+struct au_opt_del;
1813+int au_br_del(struct super_block *sb, struct au_opt_del *del, int remount);
027c5e7a
AM
1814+long au_ibusy_ioctl(struct file *file, unsigned long arg);
1815+#ifdef CONFIG_COMPAT
1816+long au_ibusy_compat_ioctl(struct file *file, unsigned long arg);
1817+#endif
1facf9fc 1818+struct au_opt_mod;
1819+int au_br_mod(struct super_block *sb, struct au_opt_mod *mod, int remount,
7f207e10 1820+ int *do_refresh);
1facf9fc 1821+
1822+/* xino.c */
1823+static const loff_t au_loff_max = LLONG_MAX;
1824+
1825+int au_xib_trunc(struct super_block *sb);
1826+ssize_t xino_fread(au_readf_t func, struct file *file, void *buf, size_t size,
1827+ loff_t *pos);
1828+ssize_t xino_fwrite(au_writef_t func, struct file *file, void *buf, size_t size,
1829+ loff_t *pos);
1830+struct file *au_xino_create2(struct file *base_file, struct file *copy_src);
1831+struct file *au_xino_create(struct super_block *sb, char *fname, int silent);
1832+ino_t au_xino_new_ino(struct super_block *sb);
b752ccd1 1833+void au_xino_delete_inode(struct inode *inode, const int unlinked);
1facf9fc 1834+int au_xino_write(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino,
1835+ ino_t ino);
1836+int au_xino_read(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino,
1837+ ino_t *ino);
1838+int au_xino_br(struct super_block *sb, struct au_branch *br, ino_t hino,
1839+ struct file *base_file, int do_test);
1840+int au_xino_trunc(struct super_block *sb, aufs_bindex_t bindex);
1841+
1842+struct au_opt_xino;
1843+int au_xino_set(struct super_block *sb, struct au_opt_xino *xino, int remount);
1844+void au_xino_clr(struct super_block *sb);
1845+struct file *au_xino_def(struct super_block *sb);
1846+int au_xino_path(struct seq_file *seq, struct file *file);
1847+
1848+/* ---------------------------------------------------------------------- */
1849+
1850+/* Superblock to branch */
1851+static inline
1852+aufs_bindex_t au_sbr_id(struct super_block *sb, aufs_bindex_t bindex)
1853+{
1854+ return au_sbr(sb, bindex)->br_id;
1855+}
1856+
1857+static inline
1858+struct vfsmount *au_sbr_mnt(struct super_block *sb, aufs_bindex_t bindex)
1859+{
1860+ return au_sbr(sb, bindex)->br_mnt;
1861+}
1862+
1863+static inline
1864+struct super_block *au_sbr_sb(struct super_block *sb, aufs_bindex_t bindex)
1865+{
1866+ return au_sbr_mnt(sb, bindex)->mnt_sb;
1867+}
1868+
1869+static inline void au_sbr_put(struct super_block *sb, aufs_bindex_t bindex)
1870+{
e49829fe 1871+ atomic_dec(&au_sbr(sb, bindex)->br_count);
1facf9fc 1872+}
1873+
1874+static inline int au_sbr_perm(struct super_block *sb, aufs_bindex_t bindex)
1875+{
1876+ return au_sbr(sb, bindex)->br_perm;
1877+}
1878+
1879+static inline int au_sbr_whable(struct super_block *sb, aufs_bindex_t bindex)
1880+{
1881+ return au_br_whable(au_sbr_perm(sb, bindex));
1882+}
1883+
1884+/* ---------------------------------------------------------------------- */
1885+
1886+/*
1887+ * wbr_wh_read_lock, wbr_wh_write_lock
1888+ * wbr_wh_read_unlock, wbr_wh_write_unlock, wbr_wh_downgrade_lock
1889+ */
1890+AuSimpleRwsemFuncs(wbr_wh, struct au_wbr *wbr, &wbr->wbr_wh_rwsem);
1891+
dece6358
AM
1892+#define WbrWhMustNoWaiters(wbr) AuRwMustNoWaiters(&wbr->wbr_wh_rwsem)
1893+#define WbrWhMustAnyLock(wbr) AuRwMustAnyLock(&wbr->wbr_wh_rwsem)
1894+#define WbrWhMustWriteLock(wbr) AuRwMustWriteLock(&wbr->wbr_wh_rwsem)
1895+
1facf9fc 1896+#endif /* __KERNEL__ */
1897+#endif /* __AUFS_BRANCH_H__ */
7f207e10
AM
1898diff -urN /usr/share/empty/fs/aufs/conf.mk linux/fs/aufs/conf.mk
1899--- /usr/share/empty/fs/aufs/conf.mk 1970-01-01 01:00:00.000000000 +0100
87a755f4 1900+++ linux/fs/aufs/conf.mk 2011-07-22 08:26:47.854303107 +0200
2cbb1c4b 1901@@ -0,0 +1,38 @@
4a4d8108
AM
1902+
1903+AuConfStr = CONFIG_AUFS_FS=${CONFIG_AUFS_FS}
1904+
1905+define AuConf
1906+ifdef ${1}
1907+AuConfStr += ${1}=${${1}}
1908+endif
1909+endef
1910+
b752ccd1 1911+AuConfAll = BRANCH_MAX_127 BRANCH_MAX_511 BRANCH_MAX_1023 BRANCH_MAX_32767 \
e49829fe 1912+ SBILIST \
7f207e10 1913+ HNOTIFY HFSNOTIFY \
4a4d8108
AM
1914+ EXPORT INO_T_64 \
1915+ RDU \
2cbb1c4b 1916+ PROC_MAP \
4a4d8108
AM
1917+ SP_IATTR \
1918+ SHWH \
1919+ BR_RAMFS \
1920+ BR_FUSE POLL \
1921+ BR_HFSPLUS \
1922+ BDEV_LOOP \
b752ccd1
AM
1923+ DEBUG MAGIC_SYSRQ
1924+$(foreach i, ${AuConfAll}, \
4a4d8108
AM
1925+ $(eval $(call AuConf,CONFIG_AUFS_${i})))
1926+
1927+AuConfName = ${obj}/conf.str
1928+${AuConfName}.tmp: FORCE
1929+ @echo ${AuConfStr} | tr ' ' '\n' | sed -e 's/^/"/' -e 's/$$/\\n"/' > $@
1930+${AuConfName}: ${AuConfName}.tmp
1931+ @diff -q $< $@ > /dev/null 2>&1 || { \
1932+ echo ' GEN ' $@; \
1933+ cp -p $< $@; \
1934+ }
1935+FORCE:
1936+clean-files += ${AuConfName} ${AuConfName}.tmp
1937+${obj}/sysfs.o: ${AuConfName}
b752ccd1
AM
1938+
1939+-include ${srctree}/${src}/conf_priv.mk
7f207e10
AM
1940diff -urN /usr/share/empty/fs/aufs/cpup.c linux/fs/aufs/cpup.c
1941--- /usr/share/empty/fs/aufs/cpup.c 1970-01-01 01:00:00.000000000 +0100
87a755f4 1942+++ linux/fs/aufs/cpup.c 2011-03-17 10:46:59.000000000 +0100
027c5e7a 1943@@ -0,0 +1,1063 @@
1facf9fc 1944+/*
027c5e7a 1945+ * Copyright (C) 2005-2011 Junjiro R. Okajima
1facf9fc 1946+ *
1947+ * This program, aufs is free software; you can redistribute it and/or modify
1948+ * it under the terms of the GNU General Public License as published by
1949+ * the Free Software Foundation; either version 2 of the License, or
1950+ * (at your option) any later version.
dece6358
AM
1951+ *
1952+ * This program is distributed in the hope that it will be useful,
1953+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1954+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1955+ * GNU General Public License for more details.
1956+ *
1957+ * You should have received a copy of the GNU General Public License
1958+ * along with this program; if not, write to the Free Software
1959+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 1960+ */
1961+
1962+/*
1963+ * copy-up functions, see wbr_policy.c for copy-down
1964+ */
1965+
dece6358 1966+#include <linux/file.h>
1facf9fc 1967+#include <linux/fs_stack.h>
dece6358 1968+#include <linux/mm.h>
1facf9fc 1969+#include <linux/uaccess.h>
1970+#include "aufs.h"
1971+
1972+void au_cpup_attr_flags(struct inode *dst, struct inode *src)
1973+{
1974+ const unsigned int mask = S_DEAD | S_SWAPFILE | S_PRIVATE
1975+ | S_NOATIME | S_NOCMTIME;
1976+
1977+ dst->i_flags |= src->i_flags & ~mask;
1978+ if (au_test_fs_notime(dst->i_sb))
1979+ dst->i_flags |= S_NOATIME | S_NOCMTIME;
1980+}
1981+
1982+void au_cpup_attr_timesizes(struct inode *inode)
1983+{
1984+ struct inode *h_inode;
1985+
1986+ h_inode = au_h_iptr(inode, au_ibstart(inode));
1987+ fsstack_copy_attr_times(inode, h_inode);
4a4d8108 1988+ fsstack_copy_inode_size(inode, h_inode);
1facf9fc 1989+}
1990+
1991+void au_cpup_attr_nlink(struct inode *inode, int force)
1992+{
1993+ struct inode *h_inode;
1994+ struct super_block *sb;
1995+ aufs_bindex_t bindex, bend;
1996+
1997+ sb = inode->i_sb;
1998+ bindex = au_ibstart(inode);
1999+ h_inode = au_h_iptr(inode, bindex);
2000+ if (!force
2001+ && !S_ISDIR(h_inode->i_mode)
2002+ && au_opt_test(au_mntflags(sb), PLINK)
2003+ && au_plink_test(inode))
2004+ return;
2005+
2006+ inode->i_nlink = h_inode->i_nlink;
2007+
2008+ /*
2009+ * fewer nlink makes find(1) noisy, but larger nlink doesn't.
2010+ * it may includes whplink directory.
2011+ */
2012+ if (S_ISDIR(h_inode->i_mode)) {
2013+ bend = au_ibend(inode);
2014+ for (bindex++; bindex <= bend; bindex++) {
2015+ h_inode = au_h_iptr(inode, bindex);
2016+ if (h_inode)
2017+ au_add_nlink(inode, h_inode);
2018+ }
2019+ }
2020+}
2021+
2022+void au_cpup_attr_changeable(struct inode *inode)
2023+{
2024+ struct inode *h_inode;
2025+
2026+ h_inode = au_h_iptr(inode, au_ibstart(inode));
2027+ inode->i_mode = h_inode->i_mode;
2028+ inode->i_uid = h_inode->i_uid;
2029+ inode->i_gid = h_inode->i_gid;
2030+ au_cpup_attr_timesizes(inode);
2031+ au_cpup_attr_flags(inode, h_inode);
2032+}
2033+
2034+void au_cpup_igen(struct inode *inode, struct inode *h_inode)
2035+{
2036+ struct au_iinfo *iinfo = au_ii(inode);
2037+
1308ab2a 2038+ IiMustWriteLock(inode);
2039+
1facf9fc 2040+ iinfo->ii_higen = h_inode->i_generation;
2041+ iinfo->ii_hsb1 = h_inode->i_sb;
2042+}
2043+
2044+void au_cpup_attr_all(struct inode *inode, int force)
2045+{
2046+ struct inode *h_inode;
2047+
2048+ h_inode = au_h_iptr(inode, au_ibstart(inode));
2049+ au_cpup_attr_changeable(inode);
2050+ if (inode->i_nlink > 0)
2051+ au_cpup_attr_nlink(inode, force);
2052+ inode->i_rdev = h_inode->i_rdev;
2053+ inode->i_blkbits = h_inode->i_blkbits;
2054+ au_cpup_igen(inode, h_inode);
2055+}
2056+
2057+/* ---------------------------------------------------------------------- */
2058+
2059+/* Note: dt_dentry and dt_h_dentry are not dget/dput-ed */
2060+
2061+/* keep the timestamps of the parent dir when cpup */
2062+void au_dtime_store(struct au_dtime *dt, struct dentry *dentry,
2063+ struct path *h_path)
2064+{
2065+ struct inode *h_inode;
2066+
2067+ dt->dt_dentry = dentry;
2068+ dt->dt_h_path = *h_path;
2069+ h_inode = h_path->dentry->d_inode;
2070+ dt->dt_atime = h_inode->i_atime;
2071+ dt->dt_mtime = h_inode->i_mtime;
2072+ /* smp_mb(); */
2073+}
2074+
2075+void au_dtime_revert(struct au_dtime *dt)
2076+{
2077+ struct iattr attr;
2078+ int err;
2079+
2080+ attr.ia_atime = dt->dt_atime;
2081+ attr.ia_mtime = dt->dt_mtime;
2082+ attr.ia_valid = ATTR_FORCE | ATTR_MTIME | ATTR_MTIME_SET
2083+ | ATTR_ATIME | ATTR_ATIME_SET;
2084+
2085+ err = vfsub_notify_change(&dt->dt_h_path, &attr);
2086+ if (unlikely(err))
4a4d8108 2087+ pr_warning("restoring timestamps failed(%d). ignored\n", err);
1facf9fc 2088+}
2089+
2090+/* ---------------------------------------------------------------------- */
2091+
2092+static noinline_for_stack
2093+int cpup_iattr(struct dentry *dst, aufs_bindex_t bindex, struct dentry *h_src)
2094+{
2095+ int err, sbits;
2096+ struct iattr ia;
2097+ struct path h_path;
1308ab2a 2098+ struct inode *h_isrc, *h_idst;
1facf9fc 2099+
2100+ h_path.dentry = au_h_dptr(dst, bindex);
1308ab2a 2101+ h_idst = h_path.dentry->d_inode;
1facf9fc 2102+ h_path.mnt = au_sbr_mnt(dst->d_sb, bindex);
2103+ h_isrc = h_src->d_inode;
1308ab2a 2104+ ia.ia_valid = ATTR_FORCE | ATTR_UID | ATTR_GID
1facf9fc 2105+ | ATTR_ATIME | ATTR_MTIME
2106+ | ATTR_ATIME_SET | ATTR_MTIME_SET;
1facf9fc 2107+ ia.ia_uid = h_isrc->i_uid;
2108+ ia.ia_gid = h_isrc->i_gid;
2109+ ia.ia_atime = h_isrc->i_atime;
2110+ ia.ia_mtime = h_isrc->i_mtime;
1308ab2a 2111+ if (h_idst->i_mode != h_isrc->i_mode
2112+ && !S_ISLNK(h_idst->i_mode)) {
2113+ ia.ia_valid |= ATTR_MODE;
2114+ ia.ia_mode = h_isrc->i_mode;
2115+ }
2116+ sbits = !!(h_isrc->i_mode & (S_ISUID | S_ISGID));
2117+ au_cpup_attr_flags(h_idst, h_isrc);
1facf9fc 2118+ err = vfsub_notify_change(&h_path, &ia);
2119+
2120+ /* is this nfs only? */
2121+ if (!err && sbits && au_test_nfs(h_path.dentry->d_sb)) {
2122+ ia.ia_valid = ATTR_FORCE | ATTR_MODE;
2123+ ia.ia_mode = h_isrc->i_mode;
2124+ err = vfsub_notify_change(&h_path, &ia);
2125+ }
2126+
2127+ return err;
2128+}
2129+
2130+/* ---------------------------------------------------------------------- */
2131+
2132+static int au_do_copy_file(struct file *dst, struct file *src, loff_t len,
2133+ char *buf, unsigned long blksize)
2134+{
2135+ int err;
2136+ size_t sz, rbytes, wbytes;
2137+ unsigned char all_zero;
2138+ char *p, *zp;
2139+ struct mutex *h_mtx;
2140+ /* reduce stack usage */
2141+ struct iattr *ia;
2142+
2143+ zp = page_address(ZERO_PAGE(0));
2144+ if (unlikely(!zp))
2145+ return -ENOMEM; /* possible? */
2146+
2147+ err = 0;
2148+ all_zero = 0;
2149+ while (len) {
2150+ AuDbg("len %lld\n", len);
2151+ sz = blksize;
2152+ if (len < blksize)
2153+ sz = len;
2154+
2155+ rbytes = 0;
2156+ /* todo: signal_pending? */
2157+ while (!rbytes || err == -EAGAIN || err == -EINTR) {
2158+ rbytes = vfsub_read_k(src, buf, sz, &src->f_pos);
2159+ err = rbytes;
2160+ }
2161+ if (unlikely(err < 0))
2162+ break;
2163+
2164+ all_zero = 0;
2165+ if (len >= rbytes && rbytes == blksize)
2166+ all_zero = !memcmp(buf, zp, rbytes);
2167+ if (!all_zero) {
2168+ wbytes = rbytes;
2169+ p = buf;
2170+ while (wbytes) {
2171+ size_t b;
2172+
2173+ b = vfsub_write_k(dst, p, wbytes, &dst->f_pos);
2174+ err = b;
2175+ /* todo: signal_pending? */
2176+ if (unlikely(err == -EAGAIN || err == -EINTR))
2177+ continue;
2178+ if (unlikely(err < 0))
2179+ break;
2180+ wbytes -= b;
2181+ p += b;
2182+ }
2183+ } else {
2184+ loff_t res;
2185+
2186+ AuLabel(hole);
2187+ res = vfsub_llseek(dst, rbytes, SEEK_CUR);
2188+ err = res;
2189+ if (unlikely(res < 0))
2190+ break;
2191+ }
2192+ len -= rbytes;
2193+ err = 0;
2194+ }
2195+
2196+ /* the last block may be a hole */
2197+ if (!err && all_zero) {
2198+ AuLabel(last hole);
2199+
2200+ err = 1;
2201+ if (au_test_nfs(dst->f_dentry->d_sb)) {
2202+ /* nfs requires this step to make last hole */
2203+ /* is this only nfs? */
2204+ do {
2205+ /* todo: signal_pending? */
2206+ err = vfsub_write_k(dst, "\0", 1, &dst->f_pos);
2207+ } while (err == -EAGAIN || err == -EINTR);
2208+ if (err == 1)
2209+ dst->f_pos--;
2210+ }
2211+
2212+ if (err == 1) {
2213+ ia = (void *)buf;
2214+ ia->ia_size = dst->f_pos;
2215+ ia->ia_valid = ATTR_SIZE | ATTR_FILE;
2216+ ia->ia_file = dst;
2217+ h_mtx = &dst->f_dentry->d_inode->i_mutex;
2218+ mutex_lock_nested(h_mtx, AuLsc_I_CHILD2);
2219+ err = vfsub_notify_change(&dst->f_path, ia);
2220+ mutex_unlock(h_mtx);
2221+ }
2222+ }
2223+
2224+ return err;
2225+}
2226+
2227+int au_copy_file(struct file *dst, struct file *src, loff_t len)
2228+{
2229+ int err;
2230+ unsigned long blksize;
2231+ unsigned char do_kfree;
2232+ char *buf;
2233+
2234+ err = -ENOMEM;
2235+ blksize = dst->f_dentry->d_sb->s_blocksize;
2236+ if (!blksize || PAGE_SIZE < blksize)
2237+ blksize = PAGE_SIZE;
2238+ AuDbg("blksize %lu\n", blksize);
2239+ do_kfree = (blksize != PAGE_SIZE && blksize >= sizeof(struct iattr *));
2240+ if (do_kfree)
2241+ buf = kmalloc(blksize, GFP_NOFS);
2242+ else
2243+ buf = (void *)__get_free_page(GFP_NOFS);
2244+ if (unlikely(!buf))
2245+ goto out;
2246+
2247+ if (len > (1 << 22))
2248+ AuDbg("copying a large file %lld\n", (long long)len);
2249+
2250+ src->f_pos = 0;
2251+ dst->f_pos = 0;
2252+ err = au_do_copy_file(dst, src, len, buf, blksize);
2253+ if (do_kfree)
2254+ kfree(buf);
2255+ else
2256+ free_page((unsigned long)buf);
2257+
4f0767ce 2258+out:
1facf9fc 2259+ return err;
2260+}
2261+
2262+/*
2263+ * to support a sparse file which is opened with O_APPEND,
2264+ * we need to close the file.
2265+ */
2266+static int au_cp_regular(struct dentry *dentry, aufs_bindex_t bdst,
4a4d8108 2267+ aufs_bindex_t bsrc, loff_t len)
1facf9fc 2268+{
2269+ int err, i;
2270+ enum { SRC, DST };
2271+ struct {
2272+ aufs_bindex_t bindex;
2273+ unsigned int flags;
2274+ struct dentry *dentry;
2275+ struct file *file;
2276+ void *label, *label_file;
2277+ } *f, file[] = {
2278+ {
2279+ .bindex = bsrc,
2280+ .flags = O_RDONLY | O_NOATIME | O_LARGEFILE,
2281+ .file = NULL,
2282+ .label = &&out,
2283+ .label_file = &&out_src
2284+ },
2285+ {
2286+ .bindex = bdst,
2287+ .flags = O_WRONLY | O_NOATIME | O_LARGEFILE,
2288+ .file = NULL,
2289+ .label = &&out_src,
2290+ .label_file = &&out_dst
2291+ }
2292+ };
2293+ struct super_block *sb;
2294+
2295+ /* bsrc branch can be ro/rw. */
2296+ sb = dentry->d_sb;
2297+ f = file;
2298+ for (i = 0; i < 2; i++, f++) {
2299+ f->dentry = au_h_dptr(dentry, f->bindex);
2300+ f->file = au_h_open(dentry, f->bindex, f->flags, /*file*/NULL);
2301+ err = PTR_ERR(f->file);
2302+ if (IS_ERR(f->file))
2303+ goto *f->label;
2304+ err = -EINVAL;
2305+ if (unlikely(!f->file->f_op))
2306+ goto *f->label_file;
2307+ }
2308+
2309+ /* try stopping to update while we copyup */
2310+ IMustLock(file[SRC].dentry->d_inode);
2311+ err = au_copy_file(file[DST].file, file[SRC].file, len);
2312+
4f0767ce 2313+out_dst:
1facf9fc 2314+ fput(file[DST].file);
2315+ au_sbr_put(sb, file[DST].bindex);
4f0767ce 2316+out_src:
1facf9fc 2317+ fput(file[SRC].file);
2318+ au_sbr_put(sb, file[SRC].bindex);
4f0767ce 2319+out:
1facf9fc 2320+ return err;
2321+}
2322+
2323+static int au_do_cpup_regular(struct dentry *dentry, aufs_bindex_t bdst,
2324+ aufs_bindex_t bsrc, loff_t len,
2325+ struct inode *h_dir, struct path *h_path)
2326+{
2327+ int err, rerr;
2328+ loff_t l;
2329+
2330+ err = 0;
2331+ l = i_size_read(au_h_iptr(dentry->d_inode, bsrc));
2332+ if (len == -1 || l < len)
2333+ len = l;
2334+ if (len)
2335+ err = au_cp_regular(dentry, bdst, bsrc, len);
2336+ if (!err)
2337+ goto out; /* success */
2338+
2339+ rerr = vfsub_unlink(h_dir, h_path, /*force*/0);
2340+ if (rerr) {
2341+ AuIOErr("failed unlinking cpup-ed %.*s(%d, %d)\n",
2342+ AuDLNPair(h_path->dentry), err, rerr);
2343+ err = -EIO;
2344+ }
2345+
4f0767ce 2346+out:
1facf9fc 2347+ return err;
2348+}
2349+
2350+static int au_do_cpup_symlink(struct path *h_path, struct dentry *h_src,
2351+ struct inode *h_dir)
2352+{
2353+ int err, symlen;
2354+ mm_segment_t old_fs;
b752ccd1
AM
2355+ union {
2356+ char *k;
2357+ char __user *u;
2358+ } sym;
1facf9fc 2359+
2360+ err = -ENOSYS;
2361+ if (unlikely(!h_src->d_inode->i_op->readlink))
2362+ goto out;
2363+
2364+ err = -ENOMEM;
b752ccd1
AM
2365+ sym.k = __getname_gfp(GFP_NOFS);
2366+ if (unlikely(!sym.k))
1facf9fc 2367+ goto out;
2368+
2369+ old_fs = get_fs();
2370+ set_fs(KERNEL_DS);
b752ccd1 2371+ symlen = h_src->d_inode->i_op->readlink(h_src, sym.u, PATH_MAX);
1facf9fc 2372+ err = symlen;
2373+ set_fs(old_fs);
2374+
2375+ if (symlen > 0) {
b752ccd1
AM
2376+ sym.k[symlen] = 0;
2377+ err = vfsub_symlink(h_dir, h_path, sym.k);
1facf9fc 2378+ }
b752ccd1 2379+ __putname(sym.k);
1facf9fc 2380+
4f0767ce 2381+out:
1facf9fc 2382+ return err;
2383+}
2384+
2385+/* return with the lower dst inode is locked */
2386+static noinline_for_stack
2387+int cpup_entry(struct dentry *dentry, aufs_bindex_t bdst,
2388+ aufs_bindex_t bsrc, loff_t len, unsigned int flags,
2389+ struct dentry *dst_parent)
2390+{
2391+ int err;
2392+ umode_t mode;
2393+ unsigned int mnt_flags;
2394+ unsigned char isdir;
2395+ const unsigned char do_dt = !!au_ftest_cpup(flags, DTIME);
2396+ struct au_dtime dt;
2397+ struct path h_path;
2398+ struct dentry *h_src, *h_dst, *h_parent;
2399+ struct inode *h_inode, *h_dir;
2400+ struct super_block *sb;
2401+
2402+ /* bsrc branch can be ro/rw. */
2403+ h_src = au_h_dptr(dentry, bsrc);
2404+ h_inode = h_src->d_inode;
2405+ AuDebugOn(h_inode != au_h_iptr(dentry->d_inode, bsrc));
2406+
2407+ /* try stopping to be referenced while we are creating */
2408+ h_dst = au_h_dptr(dentry, bdst);
2409+ h_parent = h_dst->d_parent; /* dir inode is locked */
2410+ h_dir = h_parent->d_inode;
2411+ IMustLock(h_dir);
2412+ AuDebugOn(h_parent != h_dst->d_parent);
2413+
2414+ sb = dentry->d_sb;
2415+ h_path.mnt = au_sbr_mnt(sb, bdst);
2416+ if (do_dt) {
2417+ h_path.dentry = h_parent;
2418+ au_dtime_store(&dt, dst_parent, &h_path);
2419+ }
2420+ h_path.dentry = h_dst;
2421+
2422+ isdir = 0;
2423+ mode = h_inode->i_mode;
2424+ switch (mode & S_IFMT) {
2425+ case S_IFREG:
2426+ /* try stopping to update while we are referencing */
2427+ IMustLock(h_inode);
2428+ err = vfsub_create(h_dir, &h_path, mode | S_IWUSR);
2429+ if (!err)
2430+ err = au_do_cpup_regular
2431+ (dentry, bdst, bsrc, len,
2432+ au_h_iptr(dst_parent->d_inode, bdst), &h_path);
2433+ break;
2434+ case S_IFDIR:
2435+ isdir = 1;
2436+ err = vfsub_mkdir(h_dir, &h_path, mode);
2437+ if (!err) {
2438+ /*
2439+ * strange behaviour from the users view,
2440+ * particularry setattr case
2441+ */
2442+ if (au_ibstart(dst_parent->d_inode) == bdst)
2443+ au_cpup_attr_nlink(dst_parent->d_inode,
2444+ /*force*/1);
2445+ au_cpup_attr_nlink(dentry->d_inode, /*force*/1);
2446+ }
2447+ break;
2448+ case S_IFLNK:
2449+ err = au_do_cpup_symlink(&h_path, h_src, h_dir);
2450+ break;
2451+ case S_IFCHR:
2452+ case S_IFBLK:
2453+ AuDebugOn(!capable(CAP_MKNOD));
2454+ /*FALLTHROUGH*/
2455+ case S_IFIFO:
2456+ case S_IFSOCK:
2457+ err = vfsub_mknod(h_dir, &h_path, mode, h_inode->i_rdev);
2458+ break;
2459+ default:
2460+ AuIOErr("Unknown inode type 0%o\n", mode);
2461+ err = -EIO;
2462+ }
2463+
2464+ mnt_flags = au_mntflags(sb);
2465+ if (!au_opt_test(mnt_flags, UDBA_NONE)
2466+ && !isdir
2467+ && au_opt_test(mnt_flags, XINO)
2468+ && h_inode->i_nlink == 1
2469+ /* todo: unnecessary? */
2470+ /* && dentry->d_inode->i_nlink == 1 */
2471+ && bdst < bsrc
2472+ && !au_ftest_cpup(flags, KEEPLINO))
1308ab2a 2473+ au_xino_write(sb, bsrc, h_inode->i_ino, /*ino*/0);
1facf9fc 2474+ /* ignore this error */
2475+
2476+ if (do_dt)
2477+ au_dtime_revert(&dt);
2478+ return err;
2479+}
2480+
2481+/*
2482+ * copyup the @dentry from @bsrc to @bdst.
2483+ * the caller must set the both of lower dentries.
2484+ * @len is for truncating when it is -1 copyup the entire file.
2485+ * in link/rename cases, @dst_parent may be different from the real one.
2486+ */
2487+static int au_cpup_single(struct dentry *dentry, aufs_bindex_t bdst,
2488+ aufs_bindex_t bsrc, loff_t len, unsigned int flags,
2489+ struct dentry *dst_parent)
2490+{
2491+ int err, rerr;
2492+ aufs_bindex_t old_ibstart;
2493+ unsigned char isdir, plink;
2494+ struct au_dtime dt;
2495+ struct path h_path;
2496+ struct dentry *h_src, *h_dst, *h_parent;
2497+ struct inode *dst_inode, *h_dir, *inode;
2498+ struct super_block *sb;
2499+
2500+ AuDebugOn(bsrc <= bdst);
2501+
2502+ sb = dentry->d_sb;
2503+ h_path.mnt = au_sbr_mnt(sb, bdst);
2504+ h_dst = au_h_dptr(dentry, bdst);
2505+ h_parent = h_dst->d_parent; /* dir inode is locked */
2506+ h_dir = h_parent->d_inode;
2507+ IMustLock(h_dir);
2508+
2509+ h_src = au_h_dptr(dentry, bsrc);
2510+ inode = dentry->d_inode;
2511+
2512+ if (!dst_parent)
2513+ dst_parent = dget_parent(dentry);
2514+ else
2515+ dget(dst_parent);
2516+
2517+ plink = !!au_opt_test(au_mntflags(sb), PLINK);
2518+ dst_inode = au_h_iptr(inode, bdst);
2519+ if (dst_inode) {
2520+ if (unlikely(!plink)) {
2521+ err = -EIO;
027c5e7a
AM
2522+ AuIOErr("hi%lu(i%lu) exists on b%d "
2523+ "but plink is disabled\n",
2524+ dst_inode->i_ino, inode->i_ino, bdst);
1facf9fc 2525+ goto out;
2526+ }
2527+
2528+ if (dst_inode->i_nlink) {
2529+ const int do_dt = au_ftest_cpup(flags, DTIME);
2530+
2531+ h_src = au_plink_lkup(inode, bdst);
2532+ err = PTR_ERR(h_src);
2533+ if (IS_ERR(h_src))
2534+ goto out;
2535+ if (unlikely(!h_src->d_inode)) {
2536+ err = -EIO;
2537+ AuIOErr("i%lu exists on a upper branch "
027c5e7a
AM
2538+ "but not pseudo-linked\n",
2539+ inode->i_ino);
1facf9fc 2540+ dput(h_src);
2541+ goto out;
2542+ }
2543+
2544+ if (do_dt) {
2545+ h_path.dentry = h_parent;
2546+ au_dtime_store(&dt, dst_parent, &h_path);
2547+ }
2548+ h_path.dentry = h_dst;
2549+ err = vfsub_link(h_src, h_dir, &h_path);
2550+ if (do_dt)
2551+ au_dtime_revert(&dt);
2552+ dput(h_src);
2553+ goto out;
2554+ } else
2555+ /* todo: cpup_wh_file? */
2556+ /* udba work */
4a4d8108 2557+ au_update_ibrange(inode, /*do_put_zero*/1);
1facf9fc 2558+ }
2559+
2560+ old_ibstart = au_ibstart(inode);
2561+ err = cpup_entry(dentry, bdst, bsrc, len, flags, dst_parent);
2562+ if (unlikely(err))
2563+ goto out;
2564+ dst_inode = h_dst->d_inode;
2565+ mutex_lock_nested(&dst_inode->i_mutex, AuLsc_I_CHILD2);
2566+
2567+ err = cpup_iattr(dentry, bdst, h_src);
2568+ isdir = S_ISDIR(dst_inode->i_mode);
2569+ if (!err) {
4a4d8108
AM
2570+ if (bdst < old_ibstart) {
2571+ if (S_ISREG(inode->i_mode)) {
2572+ err = au_dy_iaop(inode, bdst, dst_inode);
2573+ if (unlikely(err))
2574+ goto out_rev;
2575+ }
1facf9fc 2576+ au_set_ibstart(inode, bdst);
4a4d8108 2577+ }
1facf9fc 2578+ au_set_h_iptr(inode, bdst, au_igrab(dst_inode),
2579+ au_hi_flags(inode, isdir));
2580+ mutex_unlock(&dst_inode->i_mutex);
2581+ if (!isdir
2582+ && h_src->d_inode->i_nlink > 1
2583+ && plink)
2584+ au_plink_append(inode, bdst, h_dst);
2585+ goto out; /* success */
2586+ }
2587+
2588+ /* revert */
4a4d8108 2589+out_rev:
1facf9fc 2590+ h_path.dentry = h_parent;
2591+ mutex_unlock(&dst_inode->i_mutex);
2592+ au_dtime_store(&dt, dst_parent, &h_path);
2593+ h_path.dentry = h_dst;
2594+ if (!isdir)
2595+ rerr = vfsub_unlink(h_dir, &h_path, /*force*/0);
2596+ else
2597+ rerr = vfsub_rmdir(h_dir, &h_path);
2598+ au_dtime_revert(&dt);
2599+ if (rerr) {
2600+ AuIOErr("failed removing broken entry(%d, %d)\n", err, rerr);
2601+ err = -EIO;
2602+ }
2603+
4f0767ce 2604+out:
1facf9fc 2605+ dput(dst_parent);
2606+ return err;
2607+}
2608+
2609+struct au_cpup_single_args {
2610+ int *errp;
2611+ struct dentry *dentry;
2612+ aufs_bindex_t bdst, bsrc;
2613+ loff_t len;
2614+ unsigned int flags;
2615+ struct dentry *dst_parent;
2616+};
2617+
2618+static void au_call_cpup_single(void *args)
2619+{
2620+ struct au_cpup_single_args *a = args;
2621+ *a->errp = au_cpup_single(a->dentry, a->bdst, a->bsrc, a->len,
2622+ a->flags, a->dst_parent);
2623+}
2624+
2625+int au_sio_cpup_single(struct dentry *dentry, aufs_bindex_t bdst,
2626+ aufs_bindex_t bsrc, loff_t len, unsigned int flags,
2627+ struct dentry *dst_parent)
2628+{
2629+ int err, wkq_err;
2630+ umode_t mode;
2631+ struct dentry *h_dentry;
2632+
2633+ h_dentry = au_h_dptr(dentry, bsrc);
2634+ mode = h_dentry->d_inode->i_mode & S_IFMT;
2635+ if ((mode != S_IFCHR && mode != S_IFBLK)
2636+ || capable(CAP_MKNOD))
2637+ err = au_cpup_single(dentry, bdst, bsrc, len, flags,
2638+ dst_parent);
2639+ else {
2640+ struct au_cpup_single_args args = {
2641+ .errp = &err,
2642+ .dentry = dentry,
2643+ .bdst = bdst,
2644+ .bsrc = bsrc,
2645+ .len = len,
2646+ .flags = flags,
2647+ .dst_parent = dst_parent
2648+ };
2649+ wkq_err = au_wkq_wait(au_call_cpup_single, &args);
2650+ if (unlikely(wkq_err))
2651+ err = wkq_err;
2652+ }
2653+
2654+ return err;
2655+}
2656+
2657+/*
2658+ * copyup the @dentry from the first active lower branch to @bdst,
2659+ * using au_cpup_single().
2660+ */
2661+static int au_cpup_simple(struct dentry *dentry, aufs_bindex_t bdst, loff_t len,
2662+ unsigned int flags)
2663+{
2664+ int err;
2665+ aufs_bindex_t bsrc, bend;
2666+
2667+ bend = au_dbend(dentry);
2668+ for (bsrc = bdst + 1; bsrc <= bend; bsrc++)
2669+ if (au_h_dptr(dentry, bsrc))
2670+ break;
2671+
2672+ err = au_lkup_neg(dentry, bdst);
2673+ if (!err) {
2674+ err = au_cpup_single(dentry, bdst, bsrc, len, flags, NULL);
2675+ if (!err)
2676+ return 0; /* success */
2677+
2678+ /* revert */
2679+ au_set_h_dptr(dentry, bdst, NULL);
2680+ au_set_dbstart(dentry, bsrc);
2681+ }
2682+
2683+ return err;
2684+}
2685+
2686+struct au_cpup_simple_args {
2687+ int *errp;
2688+ struct dentry *dentry;
2689+ aufs_bindex_t bdst;
2690+ loff_t len;
2691+ unsigned int flags;
2692+};
2693+
2694+static void au_call_cpup_simple(void *args)
2695+{
2696+ struct au_cpup_simple_args *a = args;
2697+ *a->errp = au_cpup_simple(a->dentry, a->bdst, a->len, a->flags);
2698+}
2699+
2700+int au_sio_cpup_simple(struct dentry *dentry, aufs_bindex_t bdst, loff_t len,
2701+ unsigned int flags)
2702+{
2703+ int err, wkq_err;
2704+ unsigned char do_sio;
2705+ struct dentry *parent;
2706+ struct inode *h_dir;
2707+
2708+ parent = dget_parent(dentry);
2709+ h_dir = au_h_iptr(parent->d_inode, bdst);
2710+ do_sio = !!au_test_h_perm_sio(h_dir, MAY_EXEC | MAY_WRITE);
2711+ if (!do_sio) {
2712+ /*
2713+ * testing CAP_MKNOD is for generic fs,
2714+ * but CAP_FSETID is for xfs only, currently.
2715+ */
2716+ umode_t mode = dentry->d_inode->i_mode;
2717+ do_sio = (((mode & (S_IFCHR | S_IFBLK))
2718+ && !capable(CAP_MKNOD))
2719+ || ((mode & (S_ISUID | S_ISGID))
2720+ && !capable(CAP_FSETID)));
2721+ }
2722+ if (!do_sio)
2723+ err = au_cpup_simple(dentry, bdst, len, flags);
2724+ else {
2725+ struct au_cpup_simple_args args = {
2726+ .errp = &err,
2727+ .dentry = dentry,
2728+ .bdst = bdst,
2729+ .len = len,
2730+ .flags = flags
2731+ };
2732+ wkq_err = au_wkq_wait(au_call_cpup_simple, &args);
2733+ if (unlikely(wkq_err))
2734+ err = wkq_err;
2735+ }
2736+
2737+ dput(parent);
2738+ return err;
2739+}
2740+
2741+/* ---------------------------------------------------------------------- */
2742+
2743+/*
2744+ * copyup the deleted file for writing.
2745+ */
2746+static int au_do_cpup_wh(struct dentry *dentry, aufs_bindex_t bdst,
2747+ struct dentry *wh_dentry, struct file *file,
2748+ loff_t len)
2749+{
2750+ int err;
2751+ aufs_bindex_t bstart;
2752+ struct au_dinfo *dinfo;
2753+ struct dentry *h_d_dst, *h_d_start;
4a4d8108 2754+ struct au_hdentry *hdp;
1facf9fc 2755+
2756+ dinfo = au_di(dentry);
1308ab2a 2757+ AuRwMustWriteLock(&dinfo->di_rwsem);
2758+
1facf9fc 2759+ bstart = dinfo->di_bstart;
4a4d8108
AM
2760+ hdp = dinfo->di_hdentry;
2761+ h_d_dst = hdp[0 + bdst].hd_dentry;
1facf9fc 2762+ dinfo->di_bstart = bdst;
4a4d8108 2763+ hdp[0 + bdst].hd_dentry = wh_dentry;
027c5e7a
AM
2764+ if (file) {
2765+ h_d_start = hdp[0 + bstart].hd_dentry;
4a4d8108 2766+ hdp[0 + bstart].hd_dentry = au_hf_top(file)->f_dentry;
027c5e7a 2767+ }
1facf9fc 2768+ err = au_cpup_single(dentry, bdst, bstart, len, !AuCpup_DTIME,
2769+ /*h_parent*/NULL);
027c5e7a
AM
2770+ if (file) {
2771+ if (!err)
2772+ err = au_reopen_nondir(file);
4a4d8108 2773+ hdp[0 + bstart].hd_dentry = h_d_start;
1facf9fc 2774+ }
4a4d8108 2775+ hdp[0 + bdst].hd_dentry = h_d_dst;
1facf9fc 2776+ dinfo->di_bstart = bstart;
2777+
2778+ return err;
2779+}
2780+
2781+static int au_cpup_wh(struct dentry *dentry, aufs_bindex_t bdst, loff_t len,
2782+ struct file *file)
2783+{
2784+ int err;
2785+ struct au_dtime dt;
2786+ struct dentry *parent, *h_parent, *wh_dentry;
2787+ struct au_branch *br;
2788+ struct path h_path;
2789+
2790+ br = au_sbr(dentry->d_sb, bdst);
2791+ parent = dget_parent(dentry);
2792+ h_parent = au_h_dptr(parent, bdst);
2793+ wh_dentry = au_whtmp_lkup(h_parent, br, &dentry->d_name);
2794+ err = PTR_ERR(wh_dentry);
2795+ if (IS_ERR(wh_dentry))
2796+ goto out;
2797+
2798+ h_path.dentry = h_parent;
2799+ h_path.mnt = br->br_mnt;
2800+ au_dtime_store(&dt, parent, &h_path);
2801+ err = au_do_cpup_wh(dentry, bdst, wh_dentry, file, len);
2802+ if (unlikely(err))
2803+ goto out_wh;
2804+
2805+ dget(wh_dentry);
2806+ h_path.dentry = wh_dentry;
4a4d8108
AM
2807+ if (!S_ISDIR(wh_dentry->d_inode->i_mode))
2808+ err = vfsub_unlink(h_parent->d_inode, &h_path, /*force*/0);
2809+ else
2810+ err = vfsub_rmdir(h_parent->d_inode, &h_path);
1facf9fc 2811+ if (unlikely(err)) {
2812+ AuIOErr("failed remove copied-up tmp file %.*s(%d)\n",
2813+ AuDLNPair(wh_dentry), err);
2814+ err = -EIO;
2815+ }
2816+ au_dtime_revert(&dt);
2817+ au_set_hi_wh(dentry->d_inode, bdst, wh_dentry);
2818+
4f0767ce 2819+out_wh:
1facf9fc 2820+ dput(wh_dentry);
4f0767ce 2821+out:
1facf9fc 2822+ dput(parent);
2823+ return err;
2824+}
2825+
2826+struct au_cpup_wh_args {
2827+ int *errp;
2828+ struct dentry *dentry;
2829+ aufs_bindex_t bdst;
2830+ loff_t len;
2831+ struct file *file;
2832+};
2833+
2834+static void au_call_cpup_wh(void *args)
2835+{
2836+ struct au_cpup_wh_args *a = args;
2837+ *a->errp = au_cpup_wh(a->dentry, a->bdst, a->len, a->file);
2838+}
2839+
2840+int au_sio_cpup_wh(struct dentry *dentry, aufs_bindex_t bdst, loff_t len,
2841+ struct file *file)
2842+{
2843+ int err, wkq_err;
2844+ struct dentry *parent, *h_orph, *h_parent, *h_dentry;
2845+ struct inode *dir, *h_dir, *h_tmpdir, *h_inode;
2846+ struct au_wbr *wbr;
2847+
2848+ parent = dget_parent(dentry);
2849+ dir = parent->d_inode;
2850+ h_orph = NULL;
2851+ h_parent = NULL;
2852+ h_dir = au_igrab(au_h_iptr(dir, bdst));
2853+ h_tmpdir = h_dir;
2854+ if (!h_dir->i_nlink) {
2855+ wbr = au_sbr(dentry->d_sb, bdst)->br_wbr;
2856+ h_orph = wbr->wbr_orph;
2857+
2858+ h_parent = dget(au_h_dptr(parent, bdst));
1facf9fc 2859+ au_set_h_dptr(parent, bdst, dget(h_orph));
2860+ h_tmpdir = h_orph->d_inode;
1facf9fc 2861+ au_set_h_iptr(dir, bdst, au_igrab(h_tmpdir), /*flags*/0);
2862+
2863+ /* this temporary unlock is safe */
2864+ if (file)
4a4d8108 2865+ h_dentry = au_hf_top(file)->f_dentry;
1facf9fc 2866+ else
2867+ h_dentry = au_h_dptr(dentry, au_dbstart(dentry));
2868+ h_inode = h_dentry->d_inode;
2869+ IMustLock(h_inode);
2870+ mutex_unlock(&h_inode->i_mutex);
dece6358 2871+ mutex_lock_nested(&h_tmpdir->i_mutex, AuLsc_I_PARENT3);
1facf9fc 2872+ mutex_lock_nested(&h_inode->i_mutex, AuLsc_I_CHILD);
4a4d8108 2873+ /* todo: au_h_open_pre()? */
1facf9fc 2874+ }
2875+
2876+ if (!au_test_h_perm_sio(h_tmpdir, MAY_EXEC | MAY_WRITE))
2877+ err = au_cpup_wh(dentry, bdst, len, file);
2878+ else {
2879+ struct au_cpup_wh_args args = {
2880+ .errp = &err,
2881+ .dentry = dentry,
2882+ .bdst = bdst,
2883+ .len = len,
2884+ .file = file
2885+ };
2886+ wkq_err = au_wkq_wait(au_call_cpup_wh, &args);
2887+ if (unlikely(wkq_err))
2888+ err = wkq_err;
2889+ }
2890+
2891+ if (h_orph) {
2892+ mutex_unlock(&h_tmpdir->i_mutex);
4a4d8108 2893+ /* todo: au_h_open_post()? */
1facf9fc 2894+ au_set_h_iptr(dir, bdst, au_igrab(h_dir), /*flags*/0);
1facf9fc 2895+ au_set_h_dptr(parent, bdst, h_parent);
2896+ }
2897+ iput(h_dir);
2898+ dput(parent);
2899+
2900+ return err;
2901+}
2902+
2903+/* ---------------------------------------------------------------------- */
2904+
2905+/*
2906+ * generic routine for both of copy-up and copy-down.
2907+ */
2908+/* cf. revalidate function in file.c */
2909+int au_cp_dirs(struct dentry *dentry, aufs_bindex_t bdst,
2910+ int (*cp)(struct dentry *dentry, aufs_bindex_t bdst,
2911+ struct dentry *h_parent, void *arg),
2912+ void *arg)
2913+{
2914+ int err;
2915+ struct au_pin pin;
2916+ struct dentry *d, *parent, *h_parent, *real_parent;
2917+
2918+ err = 0;
2919+ parent = dget_parent(dentry);
2920+ if (IS_ROOT(parent))
2921+ goto out;
2922+
2923+ au_pin_init(&pin, dentry, bdst, AuLsc_DI_PARENT2, AuLsc_I_PARENT2,
2924+ au_opt_udba(dentry->d_sb), AuPin_MNT_WRITE);
2925+
2926+ /* do not use au_dpage */
2927+ real_parent = parent;
2928+ while (1) {
2929+ dput(parent);
2930+ parent = dget_parent(dentry);
2931+ h_parent = au_h_dptr(parent, bdst);
2932+ if (h_parent)
2933+ goto out; /* success */
2934+
2935+ /* find top dir which is necessary to cpup */
2936+ do {
2937+ d = parent;
2938+ dput(parent);
2939+ parent = dget_parent(d);
2940+ di_read_lock_parent3(parent, !AuLock_IR);
2941+ h_parent = au_h_dptr(parent, bdst);
2942+ di_read_unlock(parent, !AuLock_IR);
2943+ } while (!h_parent);
2944+
2945+ if (d != real_parent)
2946+ di_write_lock_child3(d);
2947+
2948+ /* somebody else might create while we were sleeping */
2949+ if (!au_h_dptr(d, bdst) || !au_h_dptr(d, bdst)->d_inode) {
2950+ if (au_h_dptr(d, bdst))
2951+ au_update_dbstart(d);
2952+
2953+ au_pin_set_dentry(&pin, d);
2954+ err = au_do_pin(&pin);
2955+ if (!err) {
2956+ err = cp(d, bdst, h_parent, arg);
2957+ au_unpin(&pin);
2958+ }
2959+ }
2960+
2961+ if (d != real_parent)
2962+ di_write_unlock(d);
2963+ if (unlikely(err))
2964+ break;
2965+ }
2966+
4f0767ce 2967+out:
1facf9fc 2968+ dput(parent);
2969+ return err;
2970+}
2971+
2972+static int au_cpup_dir(struct dentry *dentry, aufs_bindex_t bdst,
2973+ struct dentry *h_parent __maybe_unused ,
2974+ void *arg __maybe_unused)
2975+{
2976+ return au_sio_cpup_simple(dentry, bdst, -1, AuCpup_DTIME);
2977+}
2978+
2979+int au_cpup_dirs(struct dentry *dentry, aufs_bindex_t bdst)
2980+{
2981+ return au_cp_dirs(dentry, bdst, au_cpup_dir, NULL);
2982+}
2983+
2984+int au_test_and_cpup_dirs(struct dentry *dentry, aufs_bindex_t bdst)
2985+{
2986+ int err;
2987+ struct dentry *parent;
2988+ struct inode *dir;
2989+
2990+ parent = dget_parent(dentry);
2991+ dir = parent->d_inode;
2992+ err = 0;
2993+ if (au_h_iptr(dir, bdst))
2994+ goto out;
2995+
2996+ di_read_unlock(parent, AuLock_IR);
2997+ di_write_lock_parent(parent);
2998+ /* someone else might change our inode while we were sleeping */
2999+ if (!au_h_iptr(dir, bdst))
3000+ err = au_cpup_dirs(dentry, bdst);
3001+ di_downgrade_lock(parent, AuLock_IR);
3002+
4f0767ce 3003+out:
1facf9fc 3004+ dput(parent);
3005+ return err;
3006+}
7f207e10
AM
3007diff -urN /usr/share/empty/fs/aufs/cpup.h linux/fs/aufs/cpup.h
3008--- /usr/share/empty/fs/aufs/cpup.h 1970-01-01 01:00:00.000000000 +0100
87a755f4 3009+++ linux/fs/aufs/cpup.h 2011-03-17 10:46:59.000000000 +0100
7f207e10 3010@@ -0,0 +1,83 @@
1facf9fc 3011+/*
027c5e7a 3012+ * Copyright (C) 2005-2011 Junjiro R. Okajima
1facf9fc 3013+ *
3014+ * This program, aufs is free software; you can redistribute it and/or modify
3015+ * it under the terms of the GNU General Public License as published by
3016+ * the Free Software Foundation; either version 2 of the License, or
3017+ * (at your option) any later version.
dece6358
AM
3018+ *
3019+ * This program is distributed in the hope that it will be useful,
3020+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
3021+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
3022+ * GNU General Public License for more details.
3023+ *
3024+ * You should have received a copy of the GNU General Public License
3025+ * along with this program; if not, write to the Free Software
3026+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 3027+ */
3028+
3029+/*
3030+ * copy-up/down functions
3031+ */
3032+
3033+#ifndef __AUFS_CPUP_H__
3034+#define __AUFS_CPUP_H__
3035+
3036+#ifdef __KERNEL__
3037+
dece6358
AM
3038+#include <linux/path.h>
3039+#include <linux/time.h>
1facf9fc 3040+#include <linux/aufs_type.h>
3041+
dece6358
AM
3042+struct inode;
3043+struct file;
3044+
1facf9fc 3045+void au_cpup_attr_flags(struct inode *dst, struct inode *src);
3046+void au_cpup_attr_timesizes(struct inode *inode);
3047+void au_cpup_attr_nlink(struct inode *inode, int force);
3048+void au_cpup_attr_changeable(struct inode *inode);
3049+void au_cpup_igen(struct inode *inode, struct inode *h_inode);
3050+void au_cpup_attr_all(struct inode *inode, int force);
3051+
3052+/* ---------------------------------------------------------------------- */
3053+
3054+/* cpup flags */
3055+#define AuCpup_DTIME 1 /* do dtime_store/revert */
3056+#define AuCpup_KEEPLINO (1 << 1) /* do not clear the lower xino,
3057+ for link(2) */
3058+#define au_ftest_cpup(flags, name) ((flags) & AuCpup_##name)
7f207e10
AM
3059+#define au_fset_cpup(flags, name) \
3060+ do { (flags) |= AuCpup_##name; } while (0)
3061+#define au_fclr_cpup(flags, name) \
3062+ do { (flags) &= ~AuCpup_##name; } while (0)
1facf9fc 3063+
3064+int au_copy_file(struct file *dst, struct file *src, loff_t len);
3065+int au_sio_cpup_single(struct dentry *dentry, aufs_bindex_t bdst,
3066+ aufs_bindex_t bsrc, loff_t len, unsigned int flags,
3067+ struct dentry *dst_parent);
3068+int au_sio_cpup_simple(struct dentry *dentry, aufs_bindex_t bdst, loff_t len,
3069+ unsigned int flags);
3070+int au_sio_cpup_wh(struct dentry *dentry, aufs_bindex_t bdst, loff_t len,
3071+ struct file *file);
3072+
3073+int au_cp_dirs(struct dentry *dentry, aufs_bindex_t bdst,
3074+ int (*cp)(struct dentry *dentry, aufs_bindex_t bdst,
3075+ struct dentry *h_parent, void *arg),
3076+ void *arg);
3077+int au_cpup_dirs(struct dentry *dentry, aufs_bindex_t bdst);
3078+int au_test_and_cpup_dirs(struct dentry *dentry, aufs_bindex_t bdst);
3079+
3080+/* ---------------------------------------------------------------------- */
3081+
3082+/* keep timestamps when copyup */
3083+struct au_dtime {
3084+ struct dentry *dt_dentry;
3085+ struct path dt_h_path;
3086+ struct timespec dt_atime, dt_mtime;
3087+};
3088+void au_dtime_store(struct au_dtime *dt, struct dentry *dentry,
3089+ struct path *h_path);
3090+void au_dtime_revert(struct au_dtime *dt);
3091+
3092+#endif /* __KERNEL__ */
3093+#endif /* __AUFS_CPUP_H__ */
7f207e10
AM
3094diff -urN /usr/share/empty/fs/aufs/dbgaufs.c linux/fs/aufs/dbgaufs.c
3095--- /usr/share/empty/fs/aufs/dbgaufs.c 1970-01-01 01:00:00.000000000 +0100
87a755f4 3096+++ linux/fs/aufs/dbgaufs.c 2011-03-17 10:46:59.000000000 +0100
4a4d8108 3097@@ -0,0 +1,334 @@
1facf9fc 3098+/*
027c5e7a 3099+ * Copyright (C) 2005-2011 Junjiro R. Okajima
1facf9fc 3100+ *
3101+ * This program, aufs is free software; you can redistribute it and/or modify
3102+ * it under the terms of the GNU General Public License as published by
3103+ * the Free Software Foundation; either version 2 of the License, or
3104+ * (at your option) any later version.
dece6358
AM
3105+ *
3106+ * This program is distributed in the hope that it will be useful,
3107+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
3108+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
3109+ * GNU General Public License for more details.
3110+ *
3111+ * You should have received a copy of the GNU General Public License
3112+ * along with this program; if not, write to the Free Software
3113+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 3114+ */
3115+
3116+/*
3117+ * debugfs interface
3118+ */
3119+
3120+#include <linux/debugfs.h>
3121+#include "aufs.h"
3122+
3123+#ifndef CONFIG_SYSFS
3124+#error DEBUG_FS depends upon SYSFS
3125+#endif
3126+
3127+static struct dentry *dbgaufs;
3128+static const mode_t dbgaufs_mode = S_IRUSR | S_IRGRP | S_IROTH;
3129+
3130+/* 20 is max digits length of ulong 64 */
3131+struct dbgaufs_arg {
3132+ int n;
3133+ char a[20 * 4];
3134+};
3135+
3136+/*
3137+ * common function for all XINO files
3138+ */
3139+static int dbgaufs_xi_release(struct inode *inode __maybe_unused,
3140+ struct file *file)
3141+{
3142+ kfree(file->private_data);
3143+ return 0;
3144+}
3145+
3146+static int dbgaufs_xi_open(struct file *xf, struct file *file, int do_fcnt)
3147+{
3148+ int err;
3149+ struct kstat st;
3150+ struct dbgaufs_arg *p;
3151+
3152+ err = -ENOMEM;
3153+ p = kmalloc(sizeof(*p), GFP_NOFS);
3154+ if (unlikely(!p))
3155+ goto out;
3156+
3157+ err = 0;
3158+ p->n = 0;
3159+ file->private_data = p;
3160+ if (!xf)
3161+ goto out;
3162+
3163+ err = vfs_getattr(xf->f_vfsmnt, xf->f_dentry, &st);
3164+ if (!err) {
3165+ if (do_fcnt)
3166+ p->n = snprintf
3167+ (p->a, sizeof(p->a), "%ld, %llux%lu %lld\n",
3168+ (long)file_count(xf), st.blocks, st.blksize,
3169+ (long long)st.size);
3170+ else
3171+ p->n = snprintf(p->a, sizeof(p->a), "%llux%lu %lld\n",
3172+ st.blocks, st.blksize,
3173+ (long long)st.size);
3174+ AuDebugOn(p->n >= sizeof(p->a));
3175+ } else {
3176+ p->n = snprintf(p->a, sizeof(p->a), "err %d\n", err);
3177+ err = 0;
3178+ }
3179+
4f0767ce 3180+out:
1facf9fc 3181+ return err;
3182+
3183+}
3184+
3185+static ssize_t dbgaufs_xi_read(struct file *file, char __user *buf,
3186+ size_t count, loff_t *ppos)
3187+{
3188+ struct dbgaufs_arg *p;
3189+
3190+ p = file->private_data;
3191+ return simple_read_from_buffer(buf, count, ppos, p->a, p->n);
3192+}
3193+
3194+/* ---------------------------------------------------------------------- */
3195+
3196+static int dbgaufs_xib_open(struct inode *inode, struct file *file)
3197+{
3198+ int err;
3199+ struct au_sbinfo *sbinfo;
3200+ struct super_block *sb;
3201+
3202+ sbinfo = inode->i_private;
3203+ sb = sbinfo->si_sb;
3204+ si_noflush_read_lock(sb);
3205+ err = dbgaufs_xi_open(sbinfo->si_xib, file, /*do_fcnt*/0);
3206+ si_read_unlock(sb);
3207+ return err;
3208+}
3209+
3210+static const struct file_operations dbgaufs_xib_fop = {
4a4d8108 3211+ .owner = THIS_MODULE,
1facf9fc 3212+ .open = dbgaufs_xib_open,
3213+ .release = dbgaufs_xi_release,
3214+ .read = dbgaufs_xi_read
3215+};
3216+
3217+/* ---------------------------------------------------------------------- */
3218+
3219+#define DbgaufsXi_PREFIX "xi"
3220+
3221+static int dbgaufs_xino_open(struct inode *inode, struct file *file)
3222+{
3223+ int err;
3224+ long l;
3225+ struct au_sbinfo *sbinfo;
3226+ struct super_block *sb;
3227+ struct file *xf;
3228+ struct qstr *name;
3229+
3230+ err = -ENOENT;
3231+ xf = NULL;
3232+ name = &file->f_dentry->d_name;
3233+ if (unlikely(name->len < sizeof(DbgaufsXi_PREFIX)
3234+ || memcmp(name->name, DbgaufsXi_PREFIX,
3235+ sizeof(DbgaufsXi_PREFIX) - 1)))
3236+ goto out;
3237+ err = strict_strtol(name->name + sizeof(DbgaufsXi_PREFIX) - 1, 10, &l);
3238+ if (unlikely(err))
3239+ goto out;
3240+
3241+ sbinfo = inode->i_private;
3242+ sb = sbinfo->si_sb;
3243+ si_noflush_read_lock(sb);
3244+ if (l <= au_sbend(sb)) {
3245+ xf = au_sbr(sb, (aufs_bindex_t)l)->br_xino.xi_file;
3246+ err = dbgaufs_xi_open(xf, file, /*do_fcnt*/1);
3247+ } else
3248+ err = -ENOENT;
3249+ si_read_unlock(sb);
3250+
4f0767ce 3251+out:
1facf9fc 3252+ return err;
3253+}
3254+
3255+static const struct file_operations dbgaufs_xino_fop = {
4a4d8108 3256+ .owner = THIS_MODULE,
1facf9fc 3257+ .open = dbgaufs_xino_open,
3258+ .release = dbgaufs_xi_release,
3259+ .read = dbgaufs_xi_read
3260+};
3261+
3262+void dbgaufs_brs_del(struct super_block *sb, aufs_bindex_t bindex)
3263+{
3264+ aufs_bindex_t bend;
3265+ struct au_branch *br;
3266+ struct au_xino_file *xi;
3267+
3268+ if (!au_sbi(sb)->si_dbgaufs)
3269+ return;
3270+
3271+ bend = au_sbend(sb);
3272+ for (; bindex <= bend; bindex++) {
3273+ br = au_sbr(sb, bindex);
3274+ xi = &br->br_xino;
3275+ if (xi->xi_dbgaufs) {
3276+ debugfs_remove(xi->xi_dbgaufs);
3277+ xi->xi_dbgaufs = NULL;
3278+ }
3279+ }
3280+}
3281+
3282+void dbgaufs_brs_add(struct super_block *sb, aufs_bindex_t bindex)
3283+{
3284+ struct au_sbinfo *sbinfo;
3285+ struct dentry *parent;
3286+ struct au_branch *br;
3287+ struct au_xino_file *xi;
3288+ aufs_bindex_t bend;
3289+ char name[sizeof(DbgaufsXi_PREFIX) + 5]; /* "xi" bindex NULL */
3290+
3291+ sbinfo = au_sbi(sb);
3292+ parent = sbinfo->si_dbgaufs;
3293+ if (!parent)
3294+ return;
3295+
3296+ bend = au_sbend(sb);
3297+ for (; bindex <= bend; bindex++) {
3298+ snprintf(name, sizeof(name), DbgaufsXi_PREFIX "%d", bindex);
3299+ br = au_sbr(sb, bindex);
3300+ xi = &br->br_xino;
3301+ AuDebugOn(xi->xi_dbgaufs);
3302+ xi->xi_dbgaufs = debugfs_create_file(name, dbgaufs_mode, parent,
3303+ sbinfo, &dbgaufs_xino_fop);
3304+ /* ignore an error */
3305+ if (unlikely(!xi->xi_dbgaufs))
3306+ AuWarn1("failed %s under debugfs\n", name);
3307+ }
3308+}
3309+
3310+/* ---------------------------------------------------------------------- */
3311+
3312+#ifdef CONFIG_AUFS_EXPORT
3313+static int dbgaufs_xigen_open(struct inode *inode, struct file *file)
3314+{
3315+ int err;
3316+ struct au_sbinfo *sbinfo;
3317+ struct super_block *sb;
3318+
3319+ sbinfo = inode->i_private;
3320+ sb = sbinfo->si_sb;
3321+ si_noflush_read_lock(sb);
3322+ err = dbgaufs_xi_open(sbinfo->si_xigen, file, /*do_fcnt*/0);
3323+ si_read_unlock(sb);
3324+ return err;
3325+}
3326+
3327+static const struct file_operations dbgaufs_xigen_fop = {
4a4d8108 3328+ .owner = THIS_MODULE,
1facf9fc 3329+ .open = dbgaufs_xigen_open,
3330+ .release = dbgaufs_xi_release,
3331+ .read = dbgaufs_xi_read
3332+};
3333+
3334+static int dbgaufs_xigen_init(struct au_sbinfo *sbinfo)
3335+{
3336+ int err;
3337+
dece6358
AM
3338+ /*
3339+ * This function is a dynamic '__init' fucntion actually,
3340+ * so the tiny check for si_rwsem is unnecessary.
3341+ */
3342+ /* AuRwMustWriteLock(&sbinfo->si_rwsem); */
3343+
1facf9fc 3344+ err = -EIO;
3345+ sbinfo->si_dbgaufs_xigen = debugfs_create_file
3346+ ("xigen", dbgaufs_mode, sbinfo->si_dbgaufs, sbinfo,
3347+ &dbgaufs_xigen_fop);
3348+ if (sbinfo->si_dbgaufs_xigen)
3349+ err = 0;
3350+
3351+ return err;
3352+}
3353+#else
3354+static int dbgaufs_xigen_init(struct au_sbinfo *sbinfo)
3355+{
3356+ return 0;
3357+}
3358+#endif /* CONFIG_AUFS_EXPORT */
3359+
3360+/* ---------------------------------------------------------------------- */
3361+
3362+void dbgaufs_si_fin(struct au_sbinfo *sbinfo)
3363+{
dece6358
AM
3364+ /*
3365+ * This function is a dynamic '__init' fucntion actually,
3366+ * so the tiny check for si_rwsem is unnecessary.
3367+ */
3368+ /* AuRwMustWriteLock(&sbinfo->si_rwsem); */
3369+
1facf9fc 3370+ debugfs_remove_recursive(sbinfo->si_dbgaufs);
3371+ sbinfo->si_dbgaufs = NULL;
3372+ kobject_put(&sbinfo->si_kobj);
3373+}
3374+
3375+int dbgaufs_si_init(struct au_sbinfo *sbinfo)
3376+{
3377+ int err;
3378+ char name[SysaufsSiNameLen];
3379+
dece6358
AM
3380+ /*
3381+ * This function is a dynamic '__init' fucntion actually,
3382+ * so the tiny check for si_rwsem is unnecessary.
3383+ */
3384+ /* AuRwMustWriteLock(&sbinfo->si_rwsem); */
3385+
1facf9fc 3386+ err = -ENOENT;
3387+ if (!dbgaufs) {
3388+ AuErr1("/debug/aufs is uninitialized\n");
3389+ goto out;
3390+ }
3391+
3392+ err = -EIO;
3393+ sysaufs_name(sbinfo, name);
3394+ sbinfo->si_dbgaufs = debugfs_create_dir(name, dbgaufs);
3395+ if (unlikely(!sbinfo->si_dbgaufs))
3396+ goto out;
3397+ kobject_get(&sbinfo->si_kobj);
3398+
3399+ sbinfo->si_dbgaufs_xib = debugfs_create_file
3400+ ("xib", dbgaufs_mode, sbinfo->si_dbgaufs, sbinfo,
3401+ &dbgaufs_xib_fop);
3402+ if (unlikely(!sbinfo->si_dbgaufs_xib))
3403+ goto out_dir;
3404+
3405+ err = dbgaufs_xigen_init(sbinfo);
3406+ if (!err)
3407+ goto out; /* success */
3408+
4f0767ce 3409+out_dir:
1facf9fc 3410+ dbgaufs_si_fin(sbinfo);
4f0767ce 3411+out:
1facf9fc 3412+ return err;
3413+}
3414+
3415+/* ---------------------------------------------------------------------- */
3416+
3417+void dbgaufs_fin(void)
3418+{
3419+ debugfs_remove(dbgaufs);
3420+}
3421+
3422+int __init dbgaufs_init(void)
3423+{
3424+ int err;
3425+
3426+ err = -EIO;
3427+ dbgaufs = debugfs_create_dir(AUFS_NAME, NULL);
3428+ if (dbgaufs)
3429+ err = 0;
3430+ return err;
3431+}
7f207e10
AM
3432diff -urN /usr/share/empty/fs/aufs/dbgaufs.h linux/fs/aufs/dbgaufs.h
3433--- /usr/share/empty/fs/aufs/dbgaufs.h 1970-01-01 01:00:00.000000000 +0100
87a755f4 3434+++ linux/fs/aufs/dbgaufs.h 2011-03-17 10:46:59.000000000 +0100
4a4d8108 3435@@ -0,0 +1,52 @@
1facf9fc 3436+/*
027c5e7a 3437+ * Copyright (C) 2005-2011 Junjiro R. Okajima
1facf9fc 3438+ *
3439+ * This program, aufs is free software; you can redistribute it and/or modify
3440+ * it under the terms of the GNU General Public License as published by
3441+ * the Free Software Foundation; either version 2 of the License, or
3442+ * (at your option) any later version.
dece6358
AM
3443+ *
3444+ * This program is distributed in the hope that it will be useful,
3445+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
3446+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
3447+ * GNU General Public License for more details.
3448+ *
3449+ * You should have received a copy of the GNU General Public License
3450+ * along with this program; if not, write to the Free Software
3451+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 3452+ */
3453+
3454+/*
3455+ * debugfs interface
3456+ */
3457+
3458+#ifndef __DBGAUFS_H__
3459+#define __DBGAUFS_H__
3460+
3461+#ifdef __KERNEL__
3462+
dece6358 3463+#include <linux/init.h>
1facf9fc 3464+#include <linux/aufs_type.h>
3465+
dece6358 3466+struct super_block;
1facf9fc 3467+struct au_sbinfo;
dece6358 3468+
1facf9fc 3469+#ifdef CONFIG_DEBUG_FS
3470+/* dbgaufs.c */
3471+void dbgaufs_brs_del(struct super_block *sb, aufs_bindex_t bindex);
3472+void dbgaufs_brs_add(struct super_block *sb, aufs_bindex_t bindex);
3473+void dbgaufs_si_fin(struct au_sbinfo *sbinfo);
3474+int dbgaufs_si_init(struct au_sbinfo *sbinfo);
3475+void dbgaufs_fin(void);
3476+int __init dbgaufs_init(void);
1facf9fc 3477+#else
4a4d8108
AM
3478+AuStubVoid(dbgaufs_brs_del, struct super_block *sb, aufs_bindex_t bindex)
3479+AuStubVoid(dbgaufs_brs_add, struct super_block *sb, aufs_bindex_t bindex)
3480+AuStubVoid(dbgaufs_si_fin, struct au_sbinfo *sbinfo)
3481+AuStubInt0(dbgaufs_si_init, struct au_sbinfo *sbinfo)
3482+AuStubVoid(dbgaufs_fin, void)
3483+AuStubInt0(__init dbgaufs_init, void)
1facf9fc 3484+#endif /* CONFIG_DEBUG_FS */
3485+
3486+#endif /* __KERNEL__ */
3487+#endif /* __DBGAUFS_H__ */
7f207e10
AM
3488diff -urN /usr/share/empty/fs/aufs/dcsub.c linux/fs/aufs/dcsub.c
3489--- /usr/share/empty/fs/aufs/dcsub.c 1970-01-01 01:00:00.000000000 +0100
87a755f4 3490+++ linux/fs/aufs/dcsub.c 2011-03-17 10:46:59.000000000 +0100
027c5e7a 3491@@ -0,0 +1,243 @@
1facf9fc 3492+/*
027c5e7a 3493+ * Copyright (C) 2005-2011 Junjiro R. Okajima
1facf9fc 3494+ *
3495+ * This program, aufs is free software; you can redistribute it and/or modify
3496+ * it under the terms of the GNU General Public License as published by
3497+ * the Free Software Foundation; either version 2 of the License, or
3498+ * (at your option) any later version.
dece6358
AM
3499+ *
3500+ * This program is distributed in the hope that it will be useful,
3501+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
3502+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
3503+ * GNU General Public License for more details.
3504+ *
3505+ * You should have received a copy of the GNU General Public License
3506+ * along with this program; if not, write to the Free Software
3507+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 3508+ */
3509+
3510+/*
3511+ * sub-routines for dentry cache
3512+ */
3513+
3514+#include "aufs.h"
3515+
3516+static void au_dpage_free(struct au_dpage *dpage)
3517+{
3518+ int i;
3519+ struct dentry **p;
3520+
3521+ p = dpage->dentries;
3522+ for (i = 0; i < dpage->ndentry; i++)
3523+ dput(*p++);
3524+ free_page((unsigned long)dpage->dentries);
3525+}
3526+
3527+int au_dpages_init(struct au_dcsub_pages *dpages, gfp_t gfp)
3528+{
3529+ int err;
3530+ void *p;
3531+
3532+ err = -ENOMEM;
3533+ dpages->dpages = kmalloc(sizeof(*dpages->dpages), gfp);
3534+ if (unlikely(!dpages->dpages))
3535+ goto out;
3536+
3537+ p = (void *)__get_free_page(gfp);
3538+ if (unlikely(!p))
3539+ goto out_dpages;
3540+
3541+ dpages->dpages[0].ndentry = 0;
3542+ dpages->dpages[0].dentries = p;
3543+ dpages->ndpage = 1;
3544+ return 0; /* success */
3545+
4f0767ce 3546+out_dpages:
1facf9fc 3547+ kfree(dpages->dpages);
4f0767ce 3548+out:
1facf9fc 3549+ return err;
3550+}
3551+
3552+void au_dpages_free(struct au_dcsub_pages *dpages)
3553+{
3554+ int i;
3555+ struct au_dpage *p;
3556+
3557+ p = dpages->dpages;
3558+ for (i = 0; i < dpages->ndpage; i++)
3559+ au_dpage_free(p++);
3560+ kfree(dpages->dpages);
3561+}
3562+
3563+static int au_dpages_append(struct au_dcsub_pages *dpages,
3564+ struct dentry *dentry, gfp_t gfp)
3565+{
3566+ int err, sz;
3567+ struct au_dpage *dpage;
3568+ void *p;
3569+
3570+ dpage = dpages->dpages + dpages->ndpage - 1;
3571+ sz = PAGE_SIZE / sizeof(dentry);
3572+ if (unlikely(dpage->ndentry >= sz)) {
3573+ AuLabel(new dpage);
3574+ err = -ENOMEM;
3575+ sz = dpages->ndpage * sizeof(*dpages->dpages);
3576+ p = au_kzrealloc(dpages->dpages, sz,
3577+ sz + sizeof(*dpages->dpages), gfp);
3578+ if (unlikely(!p))
3579+ goto out;
3580+
3581+ dpages->dpages = p;
3582+ dpage = dpages->dpages + dpages->ndpage;
3583+ p = (void *)__get_free_page(gfp);
3584+ if (unlikely(!p))
3585+ goto out;
3586+
3587+ dpage->ndentry = 0;
3588+ dpage->dentries = p;
3589+ dpages->ndpage++;
3590+ }
3591+
027c5e7a
AM
3592+ AuDebugOn(!dentry->d_count);
3593+ dpage->dentries[dpage->ndentry++] = dget_dlock(dentry);
1facf9fc 3594+ return 0; /* success */
3595+
4f0767ce 3596+out:
1facf9fc 3597+ return err;
3598+}
3599+
3600+int au_dcsub_pages(struct au_dcsub_pages *dpages, struct dentry *root,
3601+ au_dpages_test test, void *arg)
3602+{
3603+ int err;
027c5e7a 3604+ struct dentry *this_parent;
1facf9fc 3605+ struct list_head *next;
3606+ struct super_block *sb = root->d_sb;
3607+
3608+ err = 0;
027c5e7a
AM
3609+ write_seqlock(&rename_lock);
3610+ this_parent = root;
3611+ spin_lock(&this_parent->d_lock);
4f0767ce 3612+repeat:
1facf9fc 3613+ next = this_parent->d_subdirs.next;
4f0767ce 3614+resume:
1facf9fc 3615+ if (this_parent->d_sb == sb
3616+ && !IS_ROOT(this_parent)
027c5e7a
AM
3617+ && au_di(this_parent)
3618+ && this_parent->d_count
1facf9fc 3619+ && (!test || test(this_parent, arg))) {
3620+ err = au_dpages_append(dpages, this_parent, GFP_ATOMIC);
3621+ if (unlikely(err))
3622+ goto out;
3623+ }
3624+
3625+ while (next != &this_parent->d_subdirs) {
3626+ struct list_head *tmp = next;
3627+ struct dentry *dentry = list_entry(tmp, struct dentry,
3628+ d_u.d_child);
027c5e7a 3629+
1facf9fc 3630+ next = tmp->next;
027c5e7a
AM
3631+ spin_lock_nested(&dentry->d_lock, DENTRY_D_LOCK_NESTED);
3632+ if (dentry->d_count) {
3633+ if (!list_empty(&dentry->d_subdirs)) {
3634+ spin_unlock(&this_parent->d_lock);
3635+ spin_release(&dentry->d_lock.dep_map, 1,
3636+ _RET_IP_);
3637+ this_parent = dentry;
3638+ spin_acquire(&this_parent->d_lock.dep_map, 0, 1,
3639+ _RET_IP_);
3640+ goto repeat;
3641+ }
3642+ if (dentry->d_sb == sb
3643+ && au_di(dentry)
3644+ && (!test || test(dentry, arg)))
3645+ err = au_dpages_append(dpages, dentry,
3646+ GFP_ATOMIC);
1facf9fc 3647+ }
027c5e7a
AM
3648+ spin_unlock(&dentry->d_lock);
3649+ if (unlikely(err))
3650+ goto out;
1facf9fc 3651+ }
3652+
3653+ if (this_parent != root) {
027c5e7a
AM
3654+ struct dentry *tmp;
3655+ struct dentry *child;
3656+
3657+ tmp = this_parent->d_parent;
3658+ rcu_read_lock();
3659+ spin_unlock(&this_parent->d_lock);
3660+ child = this_parent;
3661+ this_parent = tmp;
3662+ spin_lock(&this_parent->d_lock);
3663+ rcu_read_unlock();
3664+ next = child->d_u.d_child.next;
1facf9fc 3665+ goto resume;
3666+ }
027c5e7a 3667+
4f0767ce 3668+out:
027c5e7a
AM
3669+ spin_unlock(&this_parent->d_lock);
3670+ write_sequnlock(&rename_lock);
1facf9fc 3671+ return err;
3672+}
3673+
3674+int au_dcsub_pages_rev(struct au_dcsub_pages *dpages, struct dentry *dentry,
3675+ int do_include, au_dpages_test test, void *arg)
3676+{
3677+ int err;
3678+
3679+ err = 0;
027c5e7a
AM
3680+ write_seqlock(&rename_lock);
3681+ spin_lock(&dentry->d_lock);
3682+ if (do_include
3683+ && dentry->d_count
3684+ && (!test || test(dentry, arg)))
1facf9fc 3685+ err = au_dpages_append(dpages, dentry, GFP_ATOMIC);
027c5e7a
AM
3686+ spin_unlock(&dentry->d_lock);
3687+ if (unlikely(err))
3688+ goto out;
3689+
3690+ /*
3691+ * vfsmount_lock is unnecessary since this is a traverse in a single
3692+ * mount
3693+ */
1facf9fc 3694+ while (!IS_ROOT(dentry)) {
027c5e7a
AM
3695+ dentry = dentry->d_parent; /* rename_lock is locked */
3696+ spin_lock(&dentry->d_lock);
3697+ if (dentry->d_count
3698+ && (!test || test(dentry, arg)))
1facf9fc 3699+ err = au_dpages_append(dpages, dentry, GFP_ATOMIC);
027c5e7a
AM
3700+ spin_unlock(&dentry->d_lock);
3701+ if (unlikely(err))
3702+ break;
1facf9fc 3703+ }
3704+
4f0767ce 3705+out:
027c5e7a 3706+ write_sequnlock(&rename_lock);
1facf9fc 3707+ return err;
3708+}
3709+
027c5e7a
AM
3710+static inline int au_dcsub_dpages_aufs(struct dentry *dentry, void *arg)
3711+{
3712+ return au_di(dentry) && dentry->d_sb == arg;
3713+}
3714+
3715+int au_dcsub_pages_rev_aufs(struct au_dcsub_pages *dpages,
3716+ struct dentry *dentry, int do_include)
3717+{
3718+ return au_dcsub_pages_rev(dpages, dentry, do_include,
3719+ au_dcsub_dpages_aufs, dentry->d_sb);
3720+}
3721+
4a4d8108 3722+int au_test_subdir(struct dentry *d1, struct dentry *d2)
1facf9fc 3723+{
4a4d8108
AM
3724+ struct path path[2] = {
3725+ {
3726+ .dentry = d1
3727+ },
3728+ {
3729+ .dentry = d2
3730+ }
3731+ };
1facf9fc 3732+
4a4d8108 3733+ return path_is_under(path + 0, path + 1);
1facf9fc 3734+}
7f207e10
AM
3735diff -urN /usr/share/empty/fs/aufs/dcsub.h linux/fs/aufs/dcsub.h
3736--- /usr/share/empty/fs/aufs/dcsub.h 1970-01-01 01:00:00.000000000 +0100
87a755f4 3737+++ linux/fs/aufs/dcsub.h 2011-03-17 10:46:59.000000000 +0100
027c5e7a 3738@@ -0,0 +1,95 @@
1facf9fc 3739+/*
027c5e7a 3740+ * Copyright (C) 2005-2011 Junjiro R. Okajima
1facf9fc 3741+ *
3742+ * This program, aufs is free software; you can redistribute it and/or modify
3743+ * it under the terms of the GNU General Public License as published by
3744+ * the Free Software Foundation; either version 2 of the License, or
3745+ * (at your option) any later version.
dece6358
AM
3746+ *
3747+ * This program is distributed in the hope that it will be useful,
3748+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
3749+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
3750+ * GNU General Public License for more details.
3751+ *
3752+ * You should have received a copy of the GNU General Public License
3753+ * along with this program; if not, write to the Free Software
3754+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 3755+ */
3756+
3757+/*
3758+ * sub-routines for dentry cache
3759+ */
3760+
3761+#ifndef __AUFS_DCSUB_H__
3762+#define __AUFS_DCSUB_H__
3763+
3764+#ifdef __KERNEL__
3765+
7f207e10 3766+#include <linux/dcache.h>
027c5e7a 3767+#include <linux/fs.h>
dece6358
AM
3768+#include <linux/types.h>
3769+
3770+struct dentry;
1facf9fc 3771+
3772+struct au_dpage {
3773+ int ndentry;
3774+ struct dentry **dentries;
3775+};
3776+
3777+struct au_dcsub_pages {
3778+ int ndpage;
3779+ struct au_dpage *dpages;
3780+};
3781+
3782+/* ---------------------------------------------------------------------- */
3783+
7f207e10 3784+/* dcsub.c */
1facf9fc 3785+int au_dpages_init(struct au_dcsub_pages *dpages, gfp_t gfp);
3786+void au_dpages_free(struct au_dcsub_pages *dpages);
3787+typedef int (*au_dpages_test)(struct dentry *dentry, void *arg);
3788+int au_dcsub_pages(struct au_dcsub_pages *dpages, struct dentry *root,
3789+ au_dpages_test test, void *arg);
3790+int au_dcsub_pages_rev(struct au_dcsub_pages *dpages, struct dentry *dentry,
3791+ int do_include, au_dpages_test test, void *arg);
027c5e7a
AM
3792+int au_dcsub_pages_rev_aufs(struct au_dcsub_pages *dpages,
3793+ struct dentry *dentry, int do_include);
4a4d8108 3794+int au_test_subdir(struct dentry *d1, struct dentry *d2);
1facf9fc 3795+
7f207e10
AM
3796+/* ---------------------------------------------------------------------- */
3797+
027c5e7a
AM
3798+static inline int au_d_hashed_positive(struct dentry *d)
3799+{
3800+ int err;
3801+ struct inode *inode = d->d_inode;
3802+ err = 0;
3803+ if (unlikely(d_unhashed(d) || !inode || !inode->i_nlink))
3804+ err = -ENOENT;
3805+ return err;
3806+}
3807+
3808+static inline int au_d_alive(struct dentry *d)
3809+{
3810+ int err;
3811+ struct inode *inode;
3812+ err = 0;
3813+ if (!IS_ROOT(d))
3814+ err = au_d_hashed_positive(d);
3815+ else {
3816+ inode = d->d_inode;
3817+ if (unlikely(d_unlinked(d) || !inode || !inode->i_nlink))
3818+ err = -ENOENT;
3819+ }
3820+ return err;
3821+}
3822+
3823+static inline int au_alive_dir(struct dentry *d)
7f207e10 3824+{
027c5e7a
AM
3825+ int err;
3826+ err = au_d_alive(d);
3827+ if (unlikely(err || IS_DEADDIR(d->d_inode)))
3828+ err = -ENOENT;
3829+ return err;
7f207e10
AM
3830+}
3831+
1facf9fc 3832+#endif /* __KERNEL__ */
3833+#endif /* __AUFS_DCSUB_H__ */
7f207e10
AM
3834diff -urN /usr/share/empty/fs/aufs/debug.c linux/fs/aufs/debug.c
3835--- /usr/share/empty/fs/aufs/debug.c 1970-01-01 01:00:00.000000000 +0100
87a755f4 3836+++ linux/fs/aufs/debug.c 2011-07-22 08:26:47.854303107 +0200
2cbb1c4b 3837@@ -0,0 +1,479 @@
1facf9fc 3838+/*
027c5e7a 3839+ * Copyright (C) 2005-2011 Junjiro R. Okajima
1facf9fc 3840+ *
3841+ * This program, aufs is free software; you can redistribute it and/or modify
3842+ * it under the terms of the GNU General Public License as published by
3843+ * the Free Software Foundation; either version 2 of the License, or
3844+ * (at your option) any later version.
dece6358
AM
3845+ *
3846+ * This program is distributed in the hope that it will be useful,
3847+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
3848+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
3849+ * GNU General Public License for more details.
3850+ *
3851+ * You should have received a copy of the GNU General Public License
3852+ * along with this program; if not, write to the Free Software
3853+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 3854+ */
3855+
3856+/*
3857+ * debug print functions
3858+ */
3859+
dece6358 3860+#include <linux/module.h>
7f207e10 3861+#include <linux/vt_kern.h>
1facf9fc 3862+#include "aufs.h"
3863+
3864+int aufs_debug;
3865+MODULE_PARM_DESC(debug, "debug print");
3866+module_param_named(debug, aufs_debug, int, S_IRUGO | S_IWUSR | S_IWGRP);
3867+
3868+char *au_plevel = KERN_DEBUG;
e49829fe
JR
3869+#define dpri(fmt, ...) do { \
3870+ if ((au_plevel \
3871+ && strcmp(au_plevel, KERN_DEBUG)) \
3872+ || au_debug_test()) \
3873+ printk("%s" fmt, au_plevel, ##__VA_ARGS__); \
1facf9fc 3874+} while (0)
3875+
3876+/* ---------------------------------------------------------------------- */
3877+
3878+void au_dpri_whlist(struct au_nhash *whlist)
3879+{
3880+ unsigned long ul, n;
3881+ struct hlist_head *head;
3882+ struct au_vdir_wh *tpos;
3883+ struct hlist_node *pos;
3884+
3885+ n = whlist->nh_num;
3886+ head = whlist->nh_head;
3887+ for (ul = 0; ul < n; ul++) {
3888+ hlist_for_each_entry(tpos, pos, head, wh_hash)
3889+ dpri("b%d, %.*s, %d\n",
3890+ tpos->wh_bindex,
3891+ tpos->wh_str.len, tpos->wh_str.name,
3892+ tpos->wh_str.len);
3893+ head++;
3894+ }
3895+}
3896+
3897+void au_dpri_vdir(struct au_vdir *vdir)
3898+{
3899+ unsigned long ul;
3900+ union au_vdir_deblk_p p;
3901+ unsigned char *o;
3902+
3903+ if (!vdir || IS_ERR(vdir)) {
3904+ dpri("err %ld\n", PTR_ERR(vdir));
3905+ return;
3906+ }
3907+
3908+ dpri("deblk %u, nblk %lu, deblk %p, last{%lu, %p}, ver %lu\n",
3909+ vdir->vd_deblk_sz, vdir->vd_nblk, vdir->vd_deblk,
3910+ vdir->vd_last.ul, vdir->vd_last.p.deblk, vdir->vd_version);
3911+ for (ul = 0; ul < vdir->vd_nblk; ul++) {
3912+ p.deblk = vdir->vd_deblk[ul];
3913+ o = p.deblk;
3914+ dpri("[%lu]: %p\n", ul, o);
3915+ }
3916+}
3917+
3918+static int do_pri_inode(aufs_bindex_t bindex, struct inode *inode,
3919+ struct dentry *wh)
3920+{
3921+ char *n = NULL;
3922+ int l = 0;
3923+
3924+ if (!inode || IS_ERR(inode)) {
3925+ dpri("i%d: err %ld\n", bindex, PTR_ERR(inode));
3926+ return -1;
3927+ }
3928+
3929+ /* the type of i_blocks depends upon CONFIG_LSF */
3930+ BUILD_BUG_ON(sizeof(inode->i_blocks) != sizeof(unsigned long)
3931+ && sizeof(inode->i_blocks) != sizeof(u64));
3932+ if (wh) {
3933+ n = (void *)wh->d_name.name;
3934+ l = wh->d_name.len;
3935+ }
3936+
3937+ dpri("i%d: i%lu, %s, cnt %d, nl %u, 0%o, sz %llu, blk %llu,"
b752ccd1 3938+ " ct %lld, np %lu, st 0x%lx, f 0x%x, v %llu, g %x%s%.*s\n",
1facf9fc 3939+ bindex,
3940+ inode->i_ino, inode->i_sb ? au_sbtype(inode->i_sb) : "??",
3941+ atomic_read(&inode->i_count), inode->i_nlink, inode->i_mode,
3942+ i_size_read(inode), (unsigned long long)inode->i_blocks,
3943+ (long long)timespec_to_ns(&inode->i_ctime) & 0x0ffff,
3944+ inode->i_mapping ? inode->i_mapping->nrpages : 0,
b752ccd1
AM
3945+ inode->i_state, inode->i_flags, inode->i_version,
3946+ inode->i_generation,
1facf9fc 3947+ l ? ", wh " : "", l, n);
3948+ return 0;
3949+}
3950+
3951+void au_dpri_inode(struct inode *inode)
3952+{
3953+ struct au_iinfo *iinfo;
3954+ aufs_bindex_t bindex;
3955+ int err;
3956+
3957+ err = do_pri_inode(-1, inode, NULL);
3958+ if (err || !au_test_aufs(inode->i_sb))
3959+ return;
3960+
3961+ iinfo = au_ii(inode);
3962+ if (!iinfo)
3963+ return;
3964+ dpri("i-1: bstart %d, bend %d, gen %d\n",
3965+ iinfo->ii_bstart, iinfo->ii_bend, au_iigen(inode));
3966+ if (iinfo->ii_bstart < 0)
3967+ return;
3968+ for (bindex = iinfo->ii_bstart; bindex <= iinfo->ii_bend; bindex++)
3969+ do_pri_inode(bindex, iinfo->ii_hinode[0 + bindex].hi_inode,
3970+ iinfo->ii_hinode[0 + bindex].hi_whdentry);
3971+}
3972+
2cbb1c4b
JR
3973+void au_dpri_dalias(struct inode *inode)
3974+{
3975+ struct dentry *d;
3976+
3977+ spin_lock(&inode->i_lock);
3978+ list_for_each_entry(d, &inode->i_dentry, d_alias)
3979+ au_dpri_dentry(d);
3980+ spin_unlock(&inode->i_lock);
3981+}
3982+
1facf9fc 3983+static int do_pri_dentry(aufs_bindex_t bindex, struct dentry *dentry)
3984+{
3985+ struct dentry *wh = NULL;
3986+
3987+ if (!dentry || IS_ERR(dentry)) {
3988+ dpri("d%d: err %ld\n", bindex, PTR_ERR(dentry));
3989+ return -1;
3990+ }
3991+ /* do not call dget_parent() here */
027c5e7a 3992+ /* note: access d_xxx without d_lock */
1facf9fc 3993+ dpri("d%d: %.*s?/%.*s, %s, cnt %d, flags 0x%x\n",
3994+ bindex,
3995+ AuDLNPair(dentry->d_parent), AuDLNPair(dentry),
3996+ dentry->d_sb ? au_sbtype(dentry->d_sb) : "??",
027c5e7a 3997+ dentry->d_count, dentry->d_flags);
1facf9fc 3998+ if (bindex >= 0 && dentry->d_inode && au_test_aufs(dentry->d_sb)) {
3999+ struct au_iinfo *iinfo = au_ii(dentry->d_inode);
4000+ if (iinfo)
4001+ wh = iinfo->ii_hinode[0 + bindex].hi_whdentry;
4002+ }
4003+ do_pri_inode(bindex, dentry->d_inode, wh);
4004+ return 0;
4005+}
4006+
4007+void au_dpri_dentry(struct dentry *dentry)
4008+{
4009+ struct au_dinfo *dinfo;
4010+ aufs_bindex_t bindex;
4011+ int err;
4a4d8108 4012+ struct au_hdentry *hdp;
1facf9fc 4013+
4014+ err = do_pri_dentry(-1, dentry);
4015+ if (err || !au_test_aufs(dentry->d_sb))
4016+ return;
4017+
4018+ dinfo = au_di(dentry);
4019+ if (!dinfo)
4020+ return;
4021+ dpri("d-1: bstart %d, bend %d, bwh %d, bdiropq %d, gen %d\n",
4022+ dinfo->di_bstart, dinfo->di_bend,
4023+ dinfo->di_bwh, dinfo->di_bdiropq, au_digen(dentry));
4024+ if (dinfo->di_bstart < 0)
4025+ return;
4a4d8108 4026+ hdp = dinfo->di_hdentry;
1facf9fc 4027+ for (bindex = dinfo->di_bstart; bindex <= dinfo->di_bend; bindex++)
4a4d8108 4028+ do_pri_dentry(bindex, hdp[0 + bindex].hd_dentry);
1facf9fc 4029+}
4030+
4031+static int do_pri_file(aufs_bindex_t bindex, struct file *file)
4032+{
4033+ char a[32];
4034+
4035+ if (!file || IS_ERR(file)) {
4036+ dpri("f%d: err %ld\n", bindex, PTR_ERR(file));
4037+ return -1;
4038+ }
4039+ a[0] = 0;
4040+ if (bindex < 0
4041+ && file->f_dentry
4042+ && au_test_aufs(file->f_dentry->d_sb)
4043+ && au_fi(file))
e49829fe 4044+ snprintf(a, sizeof(a), ", gen %d, mmapped %d",
2cbb1c4b 4045+ au_figen(file), atomic_read(&au_fi(file)->fi_mmapped));
b752ccd1 4046+ dpri("f%d: mode 0x%x, flags 0%o, cnt %ld, v %llu, pos %llu%s\n",
1facf9fc 4047+ bindex, file->f_mode, file->f_flags, (long)file_count(file),
b752ccd1 4048+ file->f_version, file->f_pos, a);
1facf9fc 4049+ if (file->f_dentry)
4050+ do_pri_dentry(bindex, file->f_dentry);
4051+ return 0;
4052+}
4053+
4054+void au_dpri_file(struct file *file)
4055+{
4056+ struct au_finfo *finfo;
4a4d8108
AM
4057+ struct au_fidir *fidir;
4058+ struct au_hfile *hfile;
1facf9fc 4059+ aufs_bindex_t bindex;
4060+ int err;
4061+
4062+ err = do_pri_file(-1, file);
4063+ if (err || !file->f_dentry || !au_test_aufs(file->f_dentry->d_sb))
4064+ return;
4065+
4066+ finfo = au_fi(file);
4067+ if (!finfo)
4068+ return;
4a4d8108 4069+ if (finfo->fi_btop < 0)
1facf9fc 4070+ return;
4a4d8108
AM
4071+ fidir = finfo->fi_hdir;
4072+ if (!fidir)
4073+ do_pri_file(finfo->fi_btop, finfo->fi_htop.hf_file);
4074+ else
e49829fe
JR
4075+ for (bindex = finfo->fi_btop;
4076+ bindex >= 0 && bindex <= fidir->fd_bbot;
4a4d8108
AM
4077+ bindex++) {
4078+ hfile = fidir->fd_hfile + bindex;
4079+ do_pri_file(bindex, hfile ? hfile->hf_file : NULL);
4080+ }
1facf9fc 4081+}
4082+
4083+static int do_pri_br(aufs_bindex_t bindex, struct au_branch *br)
4084+{
4085+ struct vfsmount *mnt;
4086+ struct super_block *sb;
4087+
4088+ if (!br || IS_ERR(br))
4089+ goto out;
4090+ mnt = br->br_mnt;
4091+ if (!mnt || IS_ERR(mnt))
4092+ goto out;
4093+ sb = mnt->mnt_sb;
4094+ if (!sb || IS_ERR(sb))
4095+ goto out;
4096+
4097+ dpri("s%d: {perm 0x%x, cnt %d, wbr %p}, "
b752ccd1 4098+ "%s, dev 0x%02x%02x, flags 0x%lx, cnt %d, active %d, "
1facf9fc 4099+ "xino %d\n",
4100+ bindex, br->br_perm, atomic_read(&br->br_count), br->br_wbr,
4101+ au_sbtype(sb), MAJOR(sb->s_dev), MINOR(sb->s_dev),
b752ccd1 4102+ sb->s_flags, sb->s_count,
1facf9fc 4103+ atomic_read(&sb->s_active), !!br->br_xino.xi_file);
4104+ return 0;
4105+
4f0767ce 4106+out:
1facf9fc 4107+ dpri("s%d: err %ld\n", bindex, PTR_ERR(br));
4108+ return -1;
4109+}
4110+
4111+void au_dpri_sb(struct super_block *sb)
4112+{
4113+ struct au_sbinfo *sbinfo;
4114+ aufs_bindex_t bindex;
4115+ int err;
4116+ /* to reuduce stack size */
4117+ struct {
4118+ struct vfsmount mnt;
4119+ struct au_branch fake;
4120+ } *a;
4121+
4122+ /* this function can be called from magic sysrq */
4123+ a = kzalloc(sizeof(*a), GFP_ATOMIC);
4124+ if (unlikely(!a)) {
4125+ dpri("no memory\n");
4126+ return;
4127+ }
4128+
4129+ a->mnt.mnt_sb = sb;
4130+ a->fake.br_perm = 0;
4131+ a->fake.br_mnt = &a->mnt;
4132+ a->fake.br_xino.xi_file = NULL;
4133+ atomic_set(&a->fake.br_count, 0);
4134+ smp_mb(); /* atomic_set */
4135+ err = do_pri_br(-1, &a->fake);
4136+ kfree(a);
4137+ dpri("dev 0x%x\n", sb->s_dev);
4138+ if (err || !au_test_aufs(sb))
4139+ return;
4140+
4141+ sbinfo = au_sbi(sb);
4142+ if (!sbinfo)
4143+ return;
4144+ dpri("nw %d, gen %u, kobj %d\n",
4145+ atomic_read(&sbinfo->si_nowait.nw_len), sbinfo->si_generation,
4146+ atomic_read(&sbinfo->si_kobj.kref.refcount));
4147+ for (bindex = 0; bindex <= sbinfo->si_bend; bindex++)
4148+ do_pri_br(bindex, sbinfo->si_branch[0 + bindex]);
4149+}
4150+
4151+/* ---------------------------------------------------------------------- */
4152+
4153+void au_dbg_sleep_jiffy(int jiffy)
4154+{
4155+ while (jiffy)
4156+ jiffy = schedule_timeout_uninterruptible(jiffy);
4157+}
4158+
4159+void au_dbg_iattr(struct iattr *ia)
4160+{
4161+#define AuBit(name) if (ia->ia_valid & ATTR_ ## name) \
4162+ dpri(#name "\n")
4163+ AuBit(MODE);
4164+ AuBit(UID);
4165+ AuBit(GID);
4166+ AuBit(SIZE);
4167+ AuBit(ATIME);
4168+ AuBit(MTIME);
4169+ AuBit(CTIME);
4170+ AuBit(ATIME_SET);
4171+ AuBit(MTIME_SET);
4172+ AuBit(FORCE);
4173+ AuBit(ATTR_FLAG);
4174+ AuBit(KILL_SUID);
4175+ AuBit(KILL_SGID);
4176+ AuBit(FILE);
4177+ AuBit(KILL_PRIV);
4178+ AuBit(OPEN);
4179+ AuBit(TIMES_SET);
4180+#undef AuBit
4181+ dpri("ia_file %p\n", ia->ia_file);
4182+}
4183+
4184+/* ---------------------------------------------------------------------- */
4185+
027c5e7a
AM
4186+void __au_dbg_verify_dinode(struct dentry *dentry, const char *func, int line)
4187+{
4188+ struct inode *h_inode, *inode = dentry->d_inode;
4189+ struct dentry *h_dentry;
4190+ aufs_bindex_t bindex, bend, bi;
4191+
4192+ if (!inode /* || au_di(dentry)->di_lsc == AuLsc_DI_TMP */)
4193+ return;
4194+
4195+ bend = au_dbend(dentry);
4196+ bi = au_ibend(inode);
4197+ if (bi < bend)
4198+ bend = bi;
4199+ bindex = au_dbstart(dentry);
4200+ bi = au_ibstart(inode);
4201+ if (bi > bindex)
4202+ bindex = bi;
4203+
4204+ for (; bindex <= bend; bindex++) {
4205+ h_dentry = au_h_dptr(dentry, bindex);
4206+ if (!h_dentry)
4207+ continue;
4208+ h_inode = au_h_iptr(inode, bindex);
4209+ if (unlikely(h_inode != h_dentry->d_inode)) {
4210+ int old = au_debug_test();
4211+ if (!old)
4212+ au_debug(1);
4213+ AuDbg("b%d, %s:%d\n", bindex, func, line);
4214+ AuDbgDentry(dentry);
4215+ AuDbgInode(inode);
4216+ if (!old)
4217+ au_debug(0);
4218+ BUG();
4219+ }
4220+ }
4221+}
4222+
1facf9fc 4223+void au_dbg_verify_dir_parent(struct dentry *dentry, unsigned int sigen)
4224+{
4225+ struct dentry *parent;
4226+
4227+ parent = dget_parent(dentry);
027c5e7a
AM
4228+ AuDebugOn(!S_ISDIR(dentry->d_inode->i_mode));
4229+ AuDebugOn(IS_ROOT(dentry));
4230+ AuDebugOn(au_digen_test(parent, sigen));
1facf9fc 4231+ dput(parent);
4232+}
4233+
4234+void au_dbg_verify_nondir_parent(struct dentry *dentry, unsigned int sigen)
4235+{
4236+ struct dentry *parent;
027c5e7a 4237+ struct inode *inode;
1facf9fc 4238+
4239+ parent = dget_parent(dentry);
027c5e7a
AM
4240+ inode = dentry->d_inode;
4241+ AuDebugOn(inode && S_ISDIR(dentry->d_inode->i_mode));
4242+ AuDebugOn(au_digen_test(parent, sigen));
1facf9fc 4243+ dput(parent);
4244+}
4245+
4246+void au_dbg_verify_gen(struct dentry *parent, unsigned int sigen)
4247+{
4248+ int err, i, j;
4249+ struct au_dcsub_pages dpages;
4250+ struct au_dpage *dpage;
4251+ struct dentry **dentries;
4252+
4253+ err = au_dpages_init(&dpages, GFP_NOFS);
4254+ AuDebugOn(err);
027c5e7a 4255+ err = au_dcsub_pages_rev_aufs(&dpages, parent, /*do_include*/1);
1facf9fc 4256+ AuDebugOn(err);
4257+ for (i = dpages.ndpage - 1; !err && i >= 0; i--) {
4258+ dpage = dpages.dpages + i;
4259+ dentries = dpage->dentries;
4260+ for (j = dpage->ndentry - 1; !err && j >= 0; j--)
027c5e7a 4261+ AuDebugOn(au_digen_test(dentries[j], sigen));
1facf9fc 4262+ }
4263+ au_dpages_free(&dpages);
4264+}
4265+
1facf9fc 4266+void au_dbg_verify_kthread(void)
4267+{
7f207e10 4268+ if (current->flags & PF_WQ_WORKER) {
1facf9fc 4269+ au_dbg_blocked();
7f207e10 4270+ WARN_ON(1);
1facf9fc 4271+ }
4272+}
4273+
4274+/* ---------------------------------------------------------------------- */
4275+
4276+void au_debug_sbinfo_init(struct au_sbinfo *sbinfo __maybe_unused)
4277+{
4278+#ifdef AuForceNoPlink
4279+ au_opt_clr(sbinfo->si_mntflags, PLINK);
4280+#endif
4281+#ifdef AuForceNoXino
4282+ au_opt_clr(sbinfo->si_mntflags, XINO);
4283+#endif
4284+#ifdef AuForceNoRefrof
4285+ au_opt_clr(sbinfo->si_mntflags, REFROF);
4286+#endif
4a4d8108
AM
4287+#ifdef AuForceHnotify
4288+ au_opt_set_udba(sbinfo->si_mntflags, UDBA_HNOTIFY);
1facf9fc 4289+#endif
1308ab2a 4290+#ifdef AuForceRd0
4291+ sbinfo->si_rdblk = 0;
4292+ sbinfo->si_rdhash = 0;
4293+#endif
1facf9fc 4294+}
4295+
4296+int __init au_debug_init(void)
4297+{
4298+ aufs_bindex_t bindex;
4299+ struct au_vdir_destr destr;
4300+
4301+ bindex = -1;
4302+ AuDebugOn(bindex >= 0);
4303+
4304+ destr.len = -1;
4305+ AuDebugOn(destr.len < NAME_MAX);
4306+
4307+#ifdef CONFIG_4KSTACKS
4a4d8108 4308+ pr_warning("CONFIG_4KSTACKS is defined.\n");
1facf9fc 4309+#endif
4310+
4311+#ifdef AuForceNoBrs
4312+ sysaufs_brs = 0;
4313+#endif
4314+
4315+ return 0;
4316+}
7f207e10
AM
4317diff -urN /usr/share/empty/fs/aufs/debug.h linux/fs/aufs/debug.h
4318--- /usr/share/empty/fs/aufs/debug.h 1970-01-01 01:00:00.000000000 +0100
87a755f4 4319+++ linux/fs/aufs/debug.h 2011-07-22 08:26:47.854303107 +0200
2cbb1c4b 4320@@ -0,0 +1,252 @@
1facf9fc 4321+/*
027c5e7a 4322+ * Copyright (C) 2005-2011 Junjiro R. Okajima
1facf9fc 4323+ *
4324+ * This program, aufs is free software; you can redistribute it and/or modify
4325+ * it under the terms of the GNU General Public License as published by
4326+ * the Free Software Foundation; either version 2 of the License, or
4327+ * (at your option) any later version.
dece6358
AM
4328+ *
4329+ * This program is distributed in the hope that it will be useful,
4330+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
4331+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
4332+ * GNU General Public License for more details.
4333+ *
4334+ * You should have received a copy of the GNU General Public License
4335+ * along with this program; if not, write to the Free Software
4336+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 4337+ */
4338+
4339+/*
4340+ * debug print functions
4341+ */
4342+
4343+#ifndef __AUFS_DEBUG_H__
4344+#define __AUFS_DEBUG_H__
4345+
4346+#ifdef __KERNEL__
4347+
1308ab2a 4348+#include <asm/system.h>
dece6358 4349+#include <linux/bug.h>
7f207e10 4350+/* #include <linux/err.h> */
1308ab2a 4351+#include <linux/init.h>
4a4d8108
AM
4352+#include <linux/module.h>
4353+#include <linux/kallsyms.h>
7f207e10 4354+/* #include <linux/kernel.h> */
1facf9fc 4355+#include <linux/delay.h>
7f207e10 4356+/* #include <linux/kd.h> */
1facf9fc 4357+#include <linux/sysrq.h>
4358+#include <linux/aufs_type.h>
4359+
4a4d8108
AM
4360+#include <asm/system.h>
4361+
1facf9fc 4362+#ifdef CONFIG_AUFS_DEBUG
4363+#define AuDebugOn(a) BUG_ON(a)
4364+
4365+/* module parameter */
4366+extern int aufs_debug;
4367+static inline void au_debug(int n)
4368+{
4369+ aufs_debug = n;
4370+ smp_mb();
4371+}
4372+
4373+static inline int au_debug_test(void)
4374+{
4375+ return aufs_debug;
4376+}
4377+#else
4378+#define AuDebugOn(a) do {} while (0)
4a4d8108
AM
4379+AuStubVoid(au_debug, int n)
4380+AuStubInt0(au_debug_test, void)
1facf9fc 4381+#endif /* CONFIG_AUFS_DEBUG */
4382+
4383+/* ---------------------------------------------------------------------- */
4384+
4385+/* debug print */
4386+
4a4d8108 4387+#define AuDbg(fmt, ...) do { \
1facf9fc 4388+ if (au_debug_test()) \
4a4d8108 4389+ pr_debug("DEBUG: " fmt, ##__VA_ARGS__); \
1facf9fc 4390+} while (0)
4a4d8108
AM
4391+#define AuLabel(l) AuDbg(#l "\n")
4392+#define AuIOErr(fmt, ...) pr_err("I/O Error, " fmt, ##__VA_ARGS__)
4393+#define AuWarn1(fmt, ...) do { \
1facf9fc 4394+ static unsigned char _c; \
4395+ if (!_c++) \
4a4d8108 4396+ pr_warning(fmt, ##__VA_ARGS__); \
1facf9fc 4397+} while (0)
4398+
4a4d8108 4399+#define AuErr1(fmt, ...) do { \
1facf9fc 4400+ static unsigned char _c; \
4401+ if (!_c++) \
4a4d8108 4402+ pr_err(fmt, ##__VA_ARGS__); \
1facf9fc 4403+} while (0)
4404+
4a4d8108 4405+#define AuIOErr1(fmt, ...) do { \
1facf9fc 4406+ static unsigned char _c; \
4407+ if (!_c++) \
4a4d8108 4408+ AuIOErr(fmt, ##__VA_ARGS__); \
1facf9fc 4409+} while (0)
4410+
4411+#define AuUnsupportMsg "This operation is not supported." \
4412+ " Please report this application to aufs-users ML."
4a4d8108
AM
4413+#define AuUnsupport(fmt, ...) do { \
4414+ pr_err(AuUnsupportMsg "\n" fmt, ##__VA_ARGS__); \
1facf9fc 4415+ dump_stack(); \
4416+} while (0)
4417+
4418+#define AuTraceErr(e) do { \
4419+ if (unlikely((e) < 0)) \
4420+ AuDbg("err %d\n", (int)(e)); \
4421+} while (0)
4422+
4423+#define AuTraceErrPtr(p) do { \
4424+ if (IS_ERR(p)) \
4425+ AuDbg("err %ld\n", PTR_ERR(p)); \
4426+} while (0)
4427+
4428+/* dirty macros for debug print, use with "%.*s" and caution */
4429+#define AuLNPair(qstr) (qstr)->len, (qstr)->name
4430+#define AuDLNPair(d) AuLNPair(&(d)->d_name)
4431+
4432+/* ---------------------------------------------------------------------- */
4433+
4434+struct au_sbinfo;
4435+struct au_finfo;
dece6358 4436+struct dentry;
1facf9fc 4437+#ifdef CONFIG_AUFS_DEBUG
4438+extern char *au_plevel;
4439+struct au_nhash;
4440+void au_dpri_whlist(struct au_nhash *whlist);
4441+struct au_vdir;
4442+void au_dpri_vdir(struct au_vdir *vdir);
dece6358 4443+struct inode;
1facf9fc 4444+void au_dpri_inode(struct inode *inode);
2cbb1c4b 4445+void au_dpri_dalias(struct inode *inode);
1facf9fc 4446+void au_dpri_dentry(struct dentry *dentry);
dece6358 4447+struct file;
1facf9fc 4448+void au_dpri_file(struct file *filp);
dece6358 4449+struct super_block;
1facf9fc 4450+void au_dpri_sb(struct super_block *sb);
4451+
4452+void au_dbg_sleep_jiffy(int jiffy);
dece6358 4453+struct iattr;
1facf9fc 4454+void au_dbg_iattr(struct iattr *ia);
4455+
027c5e7a
AM
4456+#define au_dbg_verify_dinode(d) __au_dbg_verify_dinode(d, __func__, __LINE__)
4457+void __au_dbg_verify_dinode(struct dentry *dentry, const char *func, int line);
1facf9fc 4458+void au_dbg_verify_dir_parent(struct dentry *dentry, unsigned int sigen);
4459+void au_dbg_verify_nondir_parent(struct dentry *dentry, unsigned int sigen);
4460+void au_dbg_verify_gen(struct dentry *parent, unsigned int sigen);
1facf9fc 4461+void au_dbg_verify_kthread(void);
4462+
4463+int __init au_debug_init(void);
4464+void au_debug_sbinfo_init(struct au_sbinfo *sbinfo);
4465+#define AuDbgWhlist(w) do { \
4466+ AuDbg(#w "\n"); \
4467+ au_dpri_whlist(w); \
4468+} while (0)
4469+
4470+#define AuDbgVdir(v) do { \
4471+ AuDbg(#v "\n"); \
4472+ au_dpri_vdir(v); \
4473+} while (0)
4474+
4475+#define AuDbgInode(i) do { \
4476+ AuDbg(#i "\n"); \
4477+ au_dpri_inode(i); \
4478+} while (0)
4479+
2cbb1c4b
JR
4480+#define AuDbgDAlias(i) do { \
4481+ AuDbg(#i "\n"); \
4482+ au_dpri_dalias(i); \
4483+} while (0)
4484+
1facf9fc 4485+#define AuDbgDentry(d) do { \
4486+ AuDbg(#d "\n"); \
4487+ au_dpri_dentry(d); \
4488+} while (0)
4489+
4490+#define AuDbgFile(f) do { \
4491+ AuDbg(#f "\n"); \
4492+ au_dpri_file(f); \
4493+} while (0)
4494+
4495+#define AuDbgSb(sb) do { \
4496+ AuDbg(#sb "\n"); \
4497+ au_dpri_sb(sb); \
4498+} while (0)
4499+
4500+#define AuDbgSleep(sec) do { \
4501+ AuDbg("sleep %d sec\n", sec); \
4502+ ssleep(sec); \
4503+} while (0)
4504+
4505+#define AuDbgSleepJiffy(jiffy) do { \
4506+ AuDbg("sleep %d jiffies\n", jiffy); \
4507+ au_dbg_sleep_jiffy(jiffy); \
4508+} while (0)
4509+
4510+#define AuDbgIAttr(ia) do { \
4511+ AuDbg("ia_valid 0x%x\n", (ia)->ia_valid); \
4512+ au_dbg_iattr(ia); \
4513+} while (0)
4a4d8108
AM
4514+
4515+#define AuDbgSym(addr) do { \
4516+ char sym[KSYM_SYMBOL_LEN]; \
4517+ sprint_symbol(sym, (unsigned long)addr); \
4518+ AuDbg("%s\n", sym); \
4519+} while (0)
4520+
4521+#define AuInfoSym(addr) do { \
4522+ char sym[KSYM_SYMBOL_LEN]; \
4523+ sprint_symbol(sym, (unsigned long)addr); \
4524+ AuInfo("%s\n", sym); \
4525+} while (0)
1facf9fc 4526+#else
027c5e7a 4527+AuStubVoid(au_dbg_verify_dinode, struct dentry *dentry)
4a4d8108
AM
4528+AuStubVoid(au_dbg_verify_dir_parent, struct dentry *dentry, unsigned int sigen)
4529+AuStubVoid(au_dbg_verify_nondir_parent, struct dentry *dentry,
4530+ unsigned int sigen)
4531+AuStubVoid(au_dbg_verify_gen, struct dentry *parent, unsigned int sigen)
4532+AuStubVoid(au_dbg_verify_kthread, void)
4533+AuStubInt0(__init au_debug_init, void)
4534+AuStubVoid(au_debug_sbinfo_init, struct au_sbinfo *sbinfo)
1facf9fc 4535+
1facf9fc 4536+#define AuDbgWhlist(w) do {} while (0)
4537+#define AuDbgVdir(v) do {} while (0)
4538+#define AuDbgInode(i) do {} while (0)
2cbb1c4b 4539+#define AuDbgDAlias(i) do {} while (0)
1facf9fc 4540+#define AuDbgDentry(d) do {} while (0)
4541+#define AuDbgFile(f) do {} while (0)
4542+#define AuDbgSb(sb) do {} while (0)
4543+#define AuDbgSleep(sec) do {} while (0)
4544+#define AuDbgSleepJiffy(jiffy) do {} while (0)
4545+#define AuDbgIAttr(ia) do {} while (0)
4a4d8108
AM
4546+#define AuDbgSym(addr) do {} while (0)
4547+#define AuInfoSym(addr) do {} while (0)
1facf9fc 4548+#endif /* CONFIG_AUFS_DEBUG */
4549+
4550+/* ---------------------------------------------------------------------- */
4551+
4552+#ifdef CONFIG_AUFS_MAGIC_SYSRQ
4553+int __init au_sysrq_init(void);
4554+void au_sysrq_fin(void);
4555+
4556+#ifdef CONFIG_HW_CONSOLE
4557+#define au_dbg_blocked() do { \
4558+ WARN_ON(1); \
0c5527e5 4559+ handle_sysrq('w'); \
1facf9fc 4560+} while (0)
4561+#else
4a4d8108 4562+AuStubVoid(au_dbg_blocked, void)
1facf9fc 4563+#endif
4564+
4565+#else
4a4d8108
AM
4566+AuStubInt0(__init au_sysrq_init, void)
4567+AuStubVoid(au_sysrq_fin, void)
4568+AuStubVoid(au_dbg_blocked, void)
1facf9fc 4569+#endif /* CONFIG_AUFS_MAGIC_SYSRQ */
4570+
4571+#endif /* __KERNEL__ */
4572+#endif /* __AUFS_DEBUG_H__ */
7f207e10
AM
4573diff -urN /usr/share/empty/fs/aufs/dentry.c linux/fs/aufs/dentry.c
4574--- /usr/share/empty/fs/aufs/dentry.c 1970-01-01 01:00:00.000000000 +0100
87a755f4 4575+++ linux/fs/aufs/dentry.c 2011-07-22 08:26:47.854303107 +0200
027c5e7a 4576@@ -0,0 +1,1140 @@
1facf9fc 4577+/*
027c5e7a 4578+ * Copyright (C) 2005-2011 Junjiro R. Okajima
1facf9fc 4579+ *
4580+ * This program, aufs is free software; you can redistribute it and/or modify
4581+ * it under the terms of the GNU General Public License as published by
4582+ * the Free Software Foundation; either version 2 of the License, or
4583+ * (at your option) any later version.
dece6358
AM
4584+ *
4585+ * This program is distributed in the hope that it will be useful,
4586+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
4587+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
4588+ * GNU General Public License for more details.
4589+ *
4590+ * You should have received a copy of the GNU General Public License
4591+ * along with this program; if not, write to the Free Software
4592+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 4593+ */
4594+
4595+/*
4596+ * lookup and dentry operations
4597+ */
4598+
dece6358 4599+#include <linux/namei.h>
1facf9fc 4600+#include "aufs.h"
4601+
4602+static void au_h_nd(struct nameidata *h_nd, struct nameidata *nd)
4603+{
4604+ if (nd) {
4605+ *h_nd = *nd;
4606+
4607+ /*
4608+ * gave up supporting LOOKUP_CREATE/OPEN for lower fs,
4609+ * due to whiteout and branch permission.
4610+ */
4611+ h_nd->flags &= ~(/*LOOKUP_PARENT |*/ LOOKUP_OPEN | LOOKUP_CREATE
b752ccd1 4612+ | LOOKUP_FOLLOW | LOOKUP_EXCL);
1facf9fc 4613+ /* unnecessary? */
4614+ h_nd->intent.open.file = NULL;
4615+ } else
4616+ memset(h_nd, 0, sizeof(*h_nd));
4617+}
4618+
4619+struct au_lkup_one_args {
4620+ struct dentry **errp;
4621+ struct qstr *name;
4622+ struct dentry *h_parent;
4623+ struct au_branch *br;
4624+ struct nameidata *nd;
4625+};
4626+
4627+struct dentry *au_lkup_one(struct qstr *name, struct dentry *h_parent,
4628+ struct au_branch *br, struct nameidata *nd)
4629+{
4630+ struct dentry *h_dentry;
4631+ int err;
4632+ struct nameidata h_nd;
4633+
4634+ if (au_test_fs_null_nd(h_parent->d_sb))
4635+ return vfsub_lookup_one_len(name->name, h_parent, name->len);
4636+
4637+ au_h_nd(&h_nd, nd);
4638+ h_nd.path.dentry = h_parent;
4639+ h_nd.path.mnt = br->br_mnt;
4640+
2cbb1c4b 4641+ err = vfsub_name_hash(name->name, &h_nd.last, name->len);
1facf9fc 4642+ h_dentry = ERR_PTR(err);
4643+ if (!err) {
4644+ path_get(&h_nd.path);
4645+ h_dentry = vfsub_lookup_hash(&h_nd);
4646+ path_put(&h_nd.path);
4647+ }
4648+
4a4d8108 4649+ AuTraceErrPtr(h_dentry);
1facf9fc 4650+ return h_dentry;
4651+}
4652+
4653+static void au_call_lkup_one(void *args)
4654+{
4655+ struct au_lkup_one_args *a = args;
4656+ *a->errp = au_lkup_one(a->name, a->h_parent, a->br, a->nd);
4657+}
4658+
4659+#define AuLkup_ALLOW_NEG 1
4660+#define au_ftest_lkup(flags, name) ((flags) & AuLkup_##name)
7f207e10
AM
4661+#define au_fset_lkup(flags, name) \
4662+ do { (flags) |= AuLkup_##name; } while (0)
4663+#define au_fclr_lkup(flags, name) \
4664+ do { (flags) &= ~AuLkup_##name; } while (0)
1facf9fc 4665+
4666+struct au_do_lookup_args {
4667+ unsigned int flags;
4668+ mode_t type;
4669+ struct nameidata *nd;
4670+};
4671+
4672+/*
4673+ * returns positive/negative dentry, NULL or an error.
4674+ * NULL means whiteout-ed or not-found.
4675+ */
4676+static struct dentry*
4677+au_do_lookup(struct dentry *h_parent, struct dentry *dentry,
4678+ aufs_bindex_t bindex, struct qstr *wh_name,
4679+ struct au_do_lookup_args *args)
4680+{
4681+ struct dentry *h_dentry;
4682+ struct inode *h_inode, *inode;
1facf9fc 4683+ struct au_branch *br;
4684+ int wh_found, opq;
4685+ unsigned char wh_able;
4686+ const unsigned char allow_neg = !!au_ftest_lkup(args->flags, ALLOW_NEG);
4687+
1facf9fc 4688+ wh_found = 0;
4689+ br = au_sbr(dentry->d_sb, bindex);
4690+ wh_able = !!au_br_whable(br->br_perm);
4691+ if (wh_able)
4692+ wh_found = au_wh_test(h_parent, wh_name, br, /*try_sio*/0);
4693+ h_dentry = ERR_PTR(wh_found);
4694+ if (!wh_found)
4695+ goto real_lookup;
4696+ if (unlikely(wh_found < 0))
4697+ goto out;
4698+
4699+ /* We found a whiteout */
4700+ /* au_set_dbend(dentry, bindex); */
4701+ au_set_dbwh(dentry, bindex);
4702+ if (!allow_neg)
4703+ return NULL; /* success */
4704+
4f0767ce 4705+real_lookup:
4a4d8108 4706+ h_dentry = au_lkup_one(&dentry->d_name, h_parent, br, args->nd);
1facf9fc 4707+ if (IS_ERR(h_dentry))
4708+ goto out;
4709+
4710+ h_inode = h_dentry->d_inode;
4711+ if (!h_inode) {
4712+ if (!allow_neg)
4713+ goto out_neg;
4714+ } else if (wh_found
4715+ || (args->type && args->type != (h_inode->i_mode & S_IFMT)))
4716+ goto out_neg;
4717+
4718+ if (au_dbend(dentry) <= bindex)
4719+ au_set_dbend(dentry, bindex);
4720+ if (au_dbstart(dentry) < 0 || bindex < au_dbstart(dentry))
4721+ au_set_dbstart(dentry, bindex);
4722+ au_set_h_dptr(dentry, bindex, h_dentry);
4723+
4724+ inode = dentry->d_inode;
4725+ if (!h_inode || !S_ISDIR(h_inode->i_mode) || !wh_able
4726+ || (inode && !S_ISDIR(inode->i_mode)))
4727+ goto out; /* success */
4728+
4729+ mutex_lock_nested(&h_inode->i_mutex, AuLsc_I_CHILD);
4730+ opq = au_diropq_test(h_dentry, br);
4731+ mutex_unlock(&h_inode->i_mutex);
4732+ if (opq > 0)
4733+ au_set_dbdiropq(dentry, bindex);
4734+ else if (unlikely(opq < 0)) {
4735+ au_set_h_dptr(dentry, bindex, NULL);
4736+ h_dentry = ERR_PTR(opq);
4737+ }
4738+ goto out;
4739+
4f0767ce 4740+out_neg:
1facf9fc 4741+ dput(h_dentry);
4742+ h_dentry = NULL;
4f0767ce 4743+out:
1facf9fc 4744+ return h_dentry;
4745+}
4746+
dece6358
AM
4747+static int au_test_shwh(struct super_block *sb, const struct qstr *name)
4748+{
4749+ if (unlikely(!au_opt_test(au_mntflags(sb), SHWH)
4750+ && !strncmp(name->name, AUFS_WH_PFX, AUFS_WH_PFX_LEN)))
4751+ return -EPERM;
4752+ return 0;
4753+}
4754+
1facf9fc 4755+/*
4756+ * returns the number of lower positive dentries,
4757+ * otherwise an error.
4758+ * can be called at unlinking with @type is zero.
4759+ */
4760+int au_lkup_dentry(struct dentry *dentry, aufs_bindex_t bstart, mode_t type,
4761+ struct nameidata *nd)
4762+{
4763+ int npositive, err;
4764+ aufs_bindex_t bindex, btail, bdiropq;
4765+ unsigned char isdir;
4766+ struct qstr whname;
4767+ struct au_do_lookup_args args = {
4768+ .flags = 0,
4769+ .type = type,
4770+ .nd = nd
4771+ };
4772+ const struct qstr *name = &dentry->d_name;
4773+ struct dentry *parent;
4774+ struct inode *inode;
4775+
dece6358
AM
4776+ err = au_test_shwh(dentry->d_sb, name);
4777+ if (unlikely(err))
1facf9fc 4778+ goto out;
4779+
4780+ err = au_wh_name_alloc(&whname, name);
4781+ if (unlikely(err))
4782+ goto out;
4783+
4784+ inode = dentry->d_inode;
4785+ isdir = !!(inode && S_ISDIR(inode->i_mode));
4786+ if (!type)
4787+ au_fset_lkup(args.flags, ALLOW_NEG);
4788+
4789+ npositive = 0;
4a4d8108 4790+ parent = dget_parent(dentry);
1facf9fc 4791+ btail = au_dbtaildir(parent);
4792+ for (bindex = bstart; bindex <= btail; bindex++) {
4793+ struct dentry *h_parent, *h_dentry;
4794+ struct inode *h_inode, *h_dir;
4795+
4796+ h_dentry = au_h_dptr(dentry, bindex);
4797+ if (h_dentry) {
4798+ if (h_dentry->d_inode)
4799+ npositive++;
4800+ if (type != S_IFDIR)
4801+ break;
4802+ continue;
4803+ }
4804+ h_parent = au_h_dptr(parent, bindex);
4805+ if (!h_parent)
4806+ continue;
4807+ h_dir = h_parent->d_inode;
4808+ if (!h_dir || !S_ISDIR(h_dir->i_mode))
4809+ continue;
4810+
4811+ mutex_lock_nested(&h_dir->i_mutex, AuLsc_I_PARENT);
4812+ h_dentry = au_do_lookup(h_parent, dentry, bindex, &whname,
4813+ &args);
4814+ mutex_unlock(&h_dir->i_mutex);
4815+ err = PTR_ERR(h_dentry);
4816+ if (IS_ERR(h_dentry))
4a4d8108 4817+ goto out_parent;
1facf9fc 4818+ au_fclr_lkup(args.flags, ALLOW_NEG);
4819+
4820+ if (au_dbwh(dentry) >= 0)
4821+ break;
4822+ if (!h_dentry)
4823+ continue;
4824+ h_inode = h_dentry->d_inode;
4825+ if (!h_inode)
4826+ continue;
4827+ npositive++;
4828+ if (!args.type)
4829+ args.type = h_inode->i_mode & S_IFMT;
4830+ if (args.type != S_IFDIR)
4831+ break;
4832+ else if (isdir) {
4833+ /* the type of lower may be different */
4834+ bdiropq = au_dbdiropq(dentry);
4835+ if (bdiropq >= 0 && bdiropq <= bindex)
4836+ break;
4837+ }
4838+ }
4839+
4840+ if (npositive) {
4841+ AuLabel(positive);
4842+ au_update_dbstart(dentry);
4843+ }
4844+ err = npositive;
4845+ if (unlikely(!au_opt_test(au_mntflags(dentry->d_sb), UDBA_NONE)
027c5e7a 4846+ && au_dbstart(dentry) < 0)) {
1facf9fc 4847+ err = -EIO;
027c5e7a
AM
4848+ AuIOErr("both of real entry and whiteout found, %.*s, err %d\n",
4849+ AuDLNPair(dentry), err);
4850+ }
1facf9fc 4851+
4f0767ce 4852+out_parent:
4a4d8108 4853+ dput(parent);
1facf9fc 4854+ kfree(whname.name);
4f0767ce 4855+out:
1facf9fc 4856+ return err;
4857+}
4858+
4859+struct dentry *au_sio_lkup_one(struct qstr *name, struct dentry *parent,
4860+ struct au_branch *br)
4861+{
4862+ struct dentry *dentry;
4863+ int wkq_err;
4864+
4865+ if (!au_test_h_perm_sio(parent->d_inode, MAY_EXEC))
4866+ dentry = au_lkup_one(name, parent, br, /*nd*/NULL);
4867+ else {
4868+ struct au_lkup_one_args args = {
4869+ .errp = &dentry,
4870+ .name = name,
4871+ .h_parent = parent,
4872+ .br = br,
4873+ .nd = NULL
4874+ };
4875+
4876+ wkq_err = au_wkq_wait(au_call_lkup_one, &args);
4877+ if (unlikely(wkq_err))
4878+ dentry = ERR_PTR(wkq_err);
4879+ }
4880+
4881+ return dentry;
4882+}
4883+
4884+/*
4885+ * lookup @dentry on @bindex which should be negative.
4886+ */
4887+int au_lkup_neg(struct dentry *dentry, aufs_bindex_t bindex)
4888+{
4889+ int err;
4890+ struct dentry *parent, *h_parent, *h_dentry;
1facf9fc 4891+
1facf9fc 4892+ parent = dget_parent(dentry);
4893+ h_parent = au_h_dptr(parent, bindex);
4a4d8108 4894+ h_dentry = au_sio_lkup_one(&dentry->d_name, h_parent,
1facf9fc 4895+ au_sbr(dentry->d_sb, bindex));
4896+ err = PTR_ERR(h_dentry);
4897+ if (IS_ERR(h_dentry))
4898+ goto out;
4899+ if (unlikely(h_dentry->d_inode)) {
4900+ err = -EIO;
027c5e7a
AM
4901+ AuIOErr("%.*s should be negative on b%d.\n",
4902+ AuDLNPair(h_dentry), bindex);
1facf9fc 4903+ dput(h_dentry);
4904+ goto out;
4905+ }
4906+
4a4d8108 4907+ err = 0;
1facf9fc 4908+ if (bindex < au_dbstart(dentry))
4909+ au_set_dbstart(dentry, bindex);
4910+ if (au_dbend(dentry) < bindex)
4911+ au_set_dbend(dentry, bindex);
4912+ au_set_h_dptr(dentry, bindex, h_dentry);
1facf9fc 4913+
4f0767ce 4914+out:
1facf9fc 4915+ dput(parent);
4916+ return err;
4917+}
4918+
4919+/* ---------------------------------------------------------------------- */
4920+
4921+/* subset of struct inode */
4922+struct au_iattr {
4923+ unsigned long i_ino;
4924+ /* unsigned int i_nlink; */
4925+ uid_t i_uid;
4926+ gid_t i_gid;
4927+ u64 i_version;
4928+/*
4929+ loff_t i_size;
4930+ blkcnt_t i_blocks;
4931+*/
4932+ umode_t i_mode;
4933+};
4934+
4935+static void au_iattr_save(struct au_iattr *ia, struct inode *h_inode)
4936+{
4937+ ia->i_ino = h_inode->i_ino;
4938+ /* ia->i_nlink = h_inode->i_nlink; */
4939+ ia->i_uid = h_inode->i_uid;
4940+ ia->i_gid = h_inode->i_gid;
4941+ ia->i_version = h_inode->i_version;
4942+/*
4943+ ia->i_size = h_inode->i_size;
4944+ ia->i_blocks = h_inode->i_blocks;
4945+*/
4946+ ia->i_mode = (h_inode->i_mode & S_IFMT);
4947+}
4948+
4949+static int au_iattr_test(struct au_iattr *ia, struct inode *h_inode)
4950+{
4951+ return ia->i_ino != h_inode->i_ino
4952+ /* || ia->i_nlink != h_inode->i_nlink */
4953+ || ia->i_uid != h_inode->i_uid
4954+ || ia->i_gid != h_inode->i_gid
4955+ || ia->i_version != h_inode->i_version
4956+/*
4957+ || ia->i_size != h_inode->i_size
4958+ || ia->i_blocks != h_inode->i_blocks
4959+*/
4960+ || ia->i_mode != (h_inode->i_mode & S_IFMT);
4961+}
4962+
4963+static int au_h_verify_dentry(struct dentry *h_dentry, struct dentry *h_parent,
4964+ struct au_branch *br)
4965+{
4966+ int err;
4967+ struct au_iattr ia;
4968+ struct inode *h_inode;
4969+ struct dentry *h_d;
4970+ struct super_block *h_sb;
4971+
4972+ err = 0;
4973+ memset(&ia, -1, sizeof(ia));
4974+ h_sb = h_dentry->d_sb;
4975+ h_inode = h_dentry->d_inode;
4976+ if (h_inode)
4977+ au_iattr_save(&ia, h_inode);
4978+ else if (au_test_nfs(h_sb) || au_test_fuse(h_sb))
4979+ /* nfs d_revalidate may return 0 for negative dentry */
4980+ /* fuse d_revalidate always return 0 for negative dentry */
4981+ goto out;
4982+
4983+ /* main purpose is namei.c:cached_lookup() and d_revalidate */
4984+ h_d = au_lkup_one(&h_dentry->d_name, h_parent, br, /*nd*/NULL);
4985+ err = PTR_ERR(h_d);
4986+ if (IS_ERR(h_d))
4987+ goto out;
4988+
4989+ err = 0;
4990+ if (unlikely(h_d != h_dentry
4991+ || h_d->d_inode != h_inode
4992+ || (h_inode && au_iattr_test(&ia, h_inode))))
4993+ err = au_busy_or_stale();
4994+ dput(h_d);
4995+
4f0767ce 4996+out:
1facf9fc 4997+ AuTraceErr(err);
4998+ return err;
4999+}
5000+
5001+int au_h_verify(struct dentry *h_dentry, unsigned int udba, struct inode *h_dir,
5002+ struct dentry *h_parent, struct au_branch *br)
5003+{
5004+ int err;
5005+
5006+ err = 0;
027c5e7a
AM
5007+ if (udba == AuOpt_UDBA_REVAL
5008+ && !au_test_fs_remote(h_dentry->d_sb)) {
1facf9fc 5009+ IMustLock(h_dir);
5010+ err = (h_dentry->d_parent->d_inode != h_dir);
027c5e7a 5011+ } else if (udba != AuOpt_UDBA_NONE)
1facf9fc 5012+ err = au_h_verify_dentry(h_dentry, h_parent, br);
5013+
5014+ return err;
5015+}
5016+
5017+/* ---------------------------------------------------------------------- */
5018+
027c5e7a 5019+static int au_do_refresh_hdentry(struct dentry *dentry, struct dentry *parent)
1facf9fc 5020+{
027c5e7a 5021+ int err;
1facf9fc 5022+ aufs_bindex_t new_bindex, bindex, bend, bwh, bdiropq;
027c5e7a
AM
5023+ struct au_hdentry tmp, *p, *q;
5024+ struct au_dinfo *dinfo;
5025+ struct super_block *sb;
1facf9fc 5026+
027c5e7a 5027+ DiMustWriteLock(dentry);
1308ab2a 5028+
027c5e7a
AM
5029+ sb = dentry->d_sb;
5030+ dinfo = au_di(dentry);
1facf9fc 5031+ bend = dinfo->di_bend;
5032+ bwh = dinfo->di_bwh;
5033+ bdiropq = dinfo->di_bdiropq;
027c5e7a 5034+ p = dinfo->di_hdentry + dinfo->di_bstart;
1facf9fc 5035+ for (bindex = dinfo->di_bstart; bindex <= bend; bindex++, p++) {
027c5e7a 5036+ if (!p->hd_dentry)
1facf9fc 5037+ continue;
5038+
027c5e7a
AM
5039+ new_bindex = au_br_index(sb, p->hd_id);
5040+ if (new_bindex == bindex)
1facf9fc 5041+ continue;
1facf9fc 5042+
1facf9fc 5043+ if (dinfo->di_bwh == bindex)
5044+ bwh = new_bindex;
5045+ if (dinfo->di_bdiropq == bindex)
5046+ bdiropq = new_bindex;
5047+ if (new_bindex < 0) {
5048+ au_hdput(p);
5049+ p->hd_dentry = NULL;
5050+ continue;
5051+ }
5052+
5053+ /* swap two lower dentries, and loop again */
5054+ q = dinfo->di_hdentry + new_bindex;
5055+ tmp = *q;
5056+ *q = *p;
5057+ *p = tmp;
5058+ if (tmp.hd_dentry) {
5059+ bindex--;
5060+ p--;
5061+ }
5062+ }
5063+
1facf9fc 5064+ dinfo->di_bwh = -1;
5065+ if (bwh >= 0 && bwh <= au_sbend(sb) && au_sbr_whable(sb, bwh))
5066+ dinfo->di_bwh = bwh;
5067+
5068+ dinfo->di_bdiropq = -1;
5069+ if (bdiropq >= 0
5070+ && bdiropq <= au_sbend(sb)
5071+ && au_sbr_whable(sb, bdiropq))
5072+ dinfo->di_bdiropq = bdiropq;
5073+
027c5e7a
AM
5074+ err = -EIO;
5075+ dinfo->di_bstart = -1;
5076+ dinfo->di_bend = -1;
1facf9fc 5077+ bend = au_dbend(parent);
5078+ p = dinfo->di_hdentry;
5079+ for (bindex = 0; bindex <= bend; bindex++, p++)
5080+ if (p->hd_dentry) {
5081+ dinfo->di_bstart = bindex;
5082+ break;
5083+ }
5084+
027c5e7a
AM
5085+ if (dinfo->di_bstart >= 0) {
5086+ p = dinfo->di_hdentry + bend;
5087+ for (bindex = bend; bindex >= 0; bindex--, p--)
5088+ if (p->hd_dentry) {
5089+ dinfo->di_bend = bindex;
5090+ err = 0;
5091+ break;
5092+ }
5093+ }
5094+
5095+ return err;
1facf9fc 5096+}
5097+
027c5e7a 5098+static void au_do_hide(struct dentry *dentry)
1facf9fc 5099+{
027c5e7a 5100+ struct inode *inode;
1facf9fc 5101+
027c5e7a
AM
5102+ inode = dentry->d_inode;
5103+ if (inode) {
5104+ if (!S_ISDIR(inode->i_mode)) {
5105+ if (inode->i_nlink && !d_unhashed(dentry))
5106+ drop_nlink(inode);
5107+ } else {
5108+ clear_nlink(inode);
5109+ /* stop next lookup */
5110+ inode->i_flags |= S_DEAD;
5111+ }
5112+ smp_mb(); /* necessary? */
5113+ }
5114+ d_drop(dentry);
5115+}
1308ab2a 5116+
027c5e7a
AM
5117+static int au_hide_children(struct dentry *parent)
5118+{
5119+ int err, i, j, ndentry;
5120+ struct au_dcsub_pages dpages;
5121+ struct au_dpage *dpage;
5122+ struct dentry *dentry;
1facf9fc 5123+
027c5e7a 5124+ err = au_dpages_init(&dpages, GFP_NOFS);
1facf9fc 5125+ if (unlikely(err))
5126+ goto out;
027c5e7a
AM
5127+ err = au_dcsub_pages(&dpages, parent, NULL, NULL);
5128+ if (unlikely(err))
5129+ goto out_dpages;
1facf9fc 5130+
027c5e7a
AM
5131+ /* in reverse order */
5132+ for (i = dpages.ndpage - 1; i >= 0; i--) {
5133+ dpage = dpages.dpages + i;
5134+ ndentry = dpage->ndentry;
5135+ for (j = ndentry - 1; j >= 0; j--) {
5136+ dentry = dpage->dentries[j];
5137+ if (dentry != parent)
5138+ au_do_hide(dentry);
5139+ }
5140+ }
1facf9fc 5141+
027c5e7a
AM
5142+out_dpages:
5143+ au_dpages_free(&dpages);
4f0767ce 5144+out:
027c5e7a 5145+ return err;
1facf9fc 5146+}
5147+
027c5e7a 5148+static void au_hide(struct dentry *dentry)
1facf9fc 5149+{
027c5e7a
AM
5150+ int err;
5151+ struct inode *inode;
1facf9fc 5152+
027c5e7a
AM
5153+ AuDbgDentry(dentry);
5154+ inode = dentry->d_inode;
5155+ if (inode && S_ISDIR(inode->i_mode)) {
5156+ /* shrink_dcache_parent(dentry); */
5157+ err = au_hide_children(dentry);
5158+ if (unlikely(err))
5159+ AuIOErr("%.*s, failed hiding children, ignored %d\n",
5160+ AuDLNPair(dentry), err);
5161+ }
5162+ au_do_hide(dentry);
5163+}
1facf9fc 5164+
027c5e7a
AM
5165+/*
5166+ * By adding a dirty branch, a cached dentry may be affected in various ways.
5167+ *
5168+ * a dirty branch is added
5169+ * - on the top of layers
5170+ * - in the middle of layers
5171+ * - to the bottom of layers
5172+ *
5173+ * on the added branch there exists
5174+ * - a whiteout
5175+ * - a diropq
5176+ * - a same named entry
5177+ * + exist
5178+ * * negative --> positive
5179+ * * positive --> positive
5180+ * - type is unchanged
5181+ * - type is changed
5182+ * + doesn't exist
5183+ * * negative --> negative
5184+ * * positive --> negative (rejected by au_br_del() for non-dir case)
5185+ * - none
5186+ */
5187+static int au_refresh_by_dinfo(struct dentry *dentry, struct au_dinfo *dinfo,
5188+ struct au_dinfo *tmp)
5189+{
5190+ int err;
5191+ aufs_bindex_t bindex, bend;
5192+ struct {
5193+ struct dentry *dentry;
5194+ struct inode *inode;
5195+ mode_t mode;
5196+ } orig_h, tmp_h;
5197+ struct au_hdentry *hd;
5198+ struct inode *inode, *h_inode;
5199+ struct dentry *h_dentry;
5200+
5201+ err = 0;
5202+ AuDebugOn(dinfo->di_bstart < 0);
5203+ orig_h.dentry = dinfo->di_hdentry[dinfo->di_bstart].hd_dentry;
5204+ orig_h.inode = orig_h.dentry->d_inode;
5205+ orig_h.mode = 0;
5206+ if (orig_h.inode)
5207+ orig_h.mode = orig_h.inode->i_mode & S_IFMT;
5208+ memset(&tmp_h, 0, sizeof(tmp_h));
5209+ if (tmp->di_bstart >= 0) {
5210+ tmp_h.dentry = tmp->di_hdentry[tmp->di_bstart].hd_dentry;
5211+ tmp_h.inode = tmp_h.dentry->d_inode;
5212+ if (tmp_h.inode)
5213+ tmp_h.mode = tmp_h.inode->i_mode & S_IFMT;
5214+ }
5215+
5216+ inode = dentry->d_inode;
5217+ if (!orig_h.inode) {
5218+ AuDbg("nagative originally\n");
5219+ if (inode) {
5220+ au_hide(dentry);
5221+ goto out;
5222+ }
5223+ AuDebugOn(inode);
5224+ AuDebugOn(dinfo->di_bstart != dinfo->di_bend);
5225+ AuDebugOn(dinfo->di_bdiropq != -1);
5226+
5227+ if (!tmp_h.inode) {
5228+ AuDbg("negative --> negative\n");
5229+ /* should have only one negative lower */
5230+ if (tmp->di_bstart >= 0
5231+ && tmp->di_bstart < dinfo->di_bstart) {
5232+ AuDebugOn(tmp->di_bstart != tmp->di_bend);
5233+ AuDebugOn(dinfo->di_bstart != dinfo->di_bend);
5234+ au_set_h_dptr(dentry, dinfo->di_bstart, NULL);
5235+ au_di_cp(dinfo, tmp);
5236+ hd = tmp->di_hdentry + tmp->di_bstart;
5237+ au_set_h_dptr(dentry, tmp->di_bstart,
5238+ dget(hd->hd_dentry));
5239+ }
5240+ au_dbg_verify_dinode(dentry);
5241+ } else {
5242+ AuDbg("negative --> positive\n");
5243+ /*
5244+ * similar to the behaviour of creating with bypassing
5245+ * aufs.
5246+ * unhash it in order to force an error in the
5247+ * succeeding create operation.
5248+ * we should not set S_DEAD here.
5249+ */
5250+ d_drop(dentry);
5251+ /* au_di_swap(tmp, dinfo); */
5252+ au_dbg_verify_dinode(dentry);
5253+ }
5254+ } else {
5255+ AuDbg("positive originally\n");
5256+ /* inode may be NULL */
5257+ AuDebugOn(inode && (inode->i_mode & S_IFMT) != orig_h.mode);
5258+ if (!tmp_h.inode) {
5259+ AuDbg("positive --> negative\n");
5260+ /* or bypassing aufs */
5261+ au_hide(dentry);
5262+ if (tmp->di_bwh >= 0 && tmp->di_bwh <= dinfo->di_bstart)
5263+ dinfo->di_bwh = tmp->di_bwh;
5264+ if (inode)
5265+ err = au_refresh_hinode_self(inode);
5266+ au_dbg_verify_dinode(dentry);
5267+ } else if (orig_h.mode == tmp_h.mode) {
5268+ AuDbg("positive --> positive, same type\n");
5269+ if (!S_ISDIR(orig_h.mode)
5270+ && dinfo->di_bstart > tmp->di_bstart) {
5271+ /*
5272+ * similar to the behaviour of removing and
5273+ * creating.
5274+ */
5275+ au_hide(dentry);
5276+ if (inode)
5277+ err = au_refresh_hinode_self(inode);
5278+ au_dbg_verify_dinode(dentry);
5279+ } else {
5280+ /* fill empty slots */
5281+ if (dinfo->di_bstart > tmp->di_bstart)
5282+ dinfo->di_bstart = tmp->di_bstart;
5283+ if (dinfo->di_bend < tmp->di_bend)
5284+ dinfo->di_bend = tmp->di_bend;
5285+ dinfo->di_bwh = tmp->di_bwh;
5286+ dinfo->di_bdiropq = tmp->di_bdiropq;
5287+ hd = tmp->di_hdentry;
5288+ bend = dinfo->di_bend;
5289+ for (bindex = tmp->di_bstart; bindex <= bend;
5290+ bindex++) {
5291+ if (au_h_dptr(dentry, bindex))
5292+ continue;
5293+ h_dentry = hd[bindex].hd_dentry;
5294+ if (!h_dentry)
5295+ continue;
5296+ h_inode = h_dentry->d_inode;
5297+ AuDebugOn(!h_inode);
5298+ AuDebugOn(orig_h.mode
5299+ != (h_inode->i_mode
5300+ & S_IFMT));
5301+ au_set_h_dptr(dentry, bindex,
5302+ dget(h_dentry));
5303+ }
5304+ err = au_refresh_hinode(inode, dentry);
5305+ au_dbg_verify_dinode(dentry);
5306+ }
5307+ } else {
5308+ AuDbg("positive --> positive, different type\n");
5309+ /* similar to the behaviour of removing and creating */
5310+ au_hide(dentry);
5311+ if (inode)
5312+ err = au_refresh_hinode_self(inode);
5313+ au_dbg_verify_dinode(dentry);
5314+ }
5315+ }
5316+
5317+out:
5318+ return err;
5319+}
5320+
5321+int au_refresh_dentry(struct dentry *dentry, struct dentry *parent)
5322+{
5323+ int err, ebrange;
5324+ unsigned int sigen;
5325+ struct au_dinfo *dinfo, *tmp;
5326+ struct super_block *sb;
5327+ struct inode *inode;
5328+
5329+ DiMustWriteLock(dentry);
5330+ AuDebugOn(IS_ROOT(dentry));
5331+ AuDebugOn(!parent->d_inode);
5332+
5333+ sb = dentry->d_sb;
5334+ inode = dentry->d_inode;
5335+ sigen = au_sigen(sb);
5336+ err = au_digen_test(parent, sigen);
5337+ if (unlikely(err))
5338+ goto out;
5339+
5340+ dinfo = au_di(dentry);
5341+ err = au_di_realloc(dinfo, au_sbend(sb) + 1);
5342+ if (unlikely(err))
5343+ goto out;
5344+ ebrange = au_dbrange_test(dentry);
5345+ if (!ebrange)
5346+ ebrange = au_do_refresh_hdentry(dentry, parent);
5347+
5348+ if (d_unhashed(dentry) || ebrange) {
5349+ AuDebugOn(au_dbstart(dentry) < 0 && au_dbend(dentry) >= 0);
5350+ if (inode)
5351+ err = au_refresh_hinode_self(inode);
5352+ au_dbg_verify_dinode(dentry);
5353+ if (!err)
5354+ goto out_dgen; /* success */
5355+ goto out;
5356+ }
5357+
5358+ /* temporary dinfo */
5359+ AuDbgDentry(dentry);
5360+ err = -ENOMEM;
5361+ tmp = au_di_alloc(sb, AuLsc_DI_TMP);
5362+ if (unlikely(!tmp))
5363+ goto out;
5364+ au_di_swap(tmp, dinfo);
5365+ /* returns the number of positive dentries */
5366+ /*
5367+ * if current working dir is removed, it returns an error.
5368+ * but the dentry is legal.
5369+ */
5370+ err = au_lkup_dentry(dentry, /*bstart*/0, /*type*/0, /*nd*/NULL);
5371+ AuDbgDentry(dentry);
5372+ au_di_swap(tmp, dinfo);
5373+ if (err == -ENOENT)
5374+ err = 0;
5375+ if (err >= 0) {
5376+ /* compare/refresh by dinfo */
5377+ AuDbgDentry(dentry);
5378+ err = au_refresh_by_dinfo(dentry, dinfo, tmp);
5379+ au_dbg_verify_dinode(dentry);
5380+ AuTraceErr(err);
5381+ }
5382+ au_rw_write_unlock(&tmp->di_rwsem);
5383+ au_di_free(tmp);
5384+ if (unlikely(err))
5385+ goto out;
5386+
5387+out_dgen:
5388+ au_update_digen(dentry);
5389+out:
5390+ if (unlikely(err && !(dentry->d_flags & DCACHE_NFSFS_RENAMED))) {
5391+ AuIOErr("failed refreshing %.*s, %d\n",
5392+ AuDLNPair(dentry), err);
5393+ AuDbgDentry(dentry);
5394+ }
5395+ AuTraceErr(err);
5396+ return err;
5397+}
5398+
5399+static noinline_for_stack
5400+int au_do_h_d_reval(struct dentry *h_dentry, struct nameidata *nd,
5401+ struct dentry *dentry, aufs_bindex_t bindex)
5402+{
5403+ int err, valid;
5404+ int (*reval)(struct dentry *, struct nameidata *);
5405+
5406+ err = 0;
5407+ if (!(h_dentry->d_flags & DCACHE_OP_REVALIDATE))
5408+ goto out;
5409+ reval = h_dentry->d_op->d_revalidate;
5410+
5411+ AuDbg("b%d\n", bindex);
5412+ if (au_test_fs_null_nd(h_dentry->d_sb))
5413+ /* it may return tri-state */
5414+ valid = reval(h_dentry, NULL);
5415+ else {
5416+ struct nameidata h_nd;
5417+ int locked;
1facf9fc 5418+ struct dentry *parent;
5419+
5420+ au_h_nd(&h_nd, nd);
5421+ parent = nd->path.dentry;
5422+ locked = (nd && nd->path.dentry != dentry);
5423+ if (locked)
5424+ di_read_lock_parent(parent, AuLock_IR);
5425+ BUG_ON(bindex > au_dbend(parent));
5426+ h_nd.path.dentry = au_h_dptr(parent, bindex);
5427+ BUG_ON(!h_nd.path.dentry);
5428+ h_nd.path.mnt = au_sbr(parent->d_sb, bindex)->br_mnt;
5429+ path_get(&h_nd.path);
5430+ valid = reval(h_dentry, &h_nd);
5431+ path_put(&h_nd.path);
5432+ if (locked)
5433+ di_read_unlock(parent, AuLock_IR);
5434+ }
5435+
5436+ if (unlikely(valid < 0))
5437+ err = valid;
5438+ else if (!valid)
5439+ err = -EINVAL;
5440+
4f0767ce 5441+out:
1facf9fc 5442+ AuTraceErr(err);
5443+ return err;
5444+}
5445+
5446+/* todo: remove this */
5447+static int h_d_revalidate(struct dentry *dentry, struct inode *inode,
5448+ struct nameidata *nd, int do_udba)
5449+{
5450+ int err;
5451+ umode_t mode, h_mode;
5452+ aufs_bindex_t bindex, btail, bstart, ibs, ibe;
5453+ unsigned char plus, unhashed, is_root, h_plus;
4a4d8108 5454+ struct inode *h_inode, *h_cached_inode;
1facf9fc 5455+ struct dentry *h_dentry;
5456+ struct qstr *name, *h_name;
5457+
5458+ err = 0;
5459+ plus = 0;
5460+ mode = 0;
1facf9fc 5461+ ibs = -1;
5462+ ibe = -1;
5463+ unhashed = !!d_unhashed(dentry);
5464+ is_root = !!IS_ROOT(dentry);
5465+ name = &dentry->d_name;
5466+
5467+ /*
7f207e10
AM
5468+ * Theoretically, REVAL test should be unnecessary in case of
5469+ * {FS,I}NOTIFY.
5470+ * But {fs,i}notify doesn't fire some necessary events,
1facf9fc 5471+ * IN_ATTRIB for atime/nlink/pageio
5472+ * IN_DELETE for NFS dentry
5473+ * Let's do REVAL test too.
5474+ */
5475+ if (do_udba && inode) {
5476+ mode = (inode->i_mode & S_IFMT);
5477+ plus = (inode->i_nlink > 0);
1facf9fc 5478+ ibs = au_ibstart(inode);
5479+ ibe = au_ibend(inode);
5480+ }
5481+
5482+ bstart = au_dbstart(dentry);
5483+ btail = bstart;
5484+ if (inode && S_ISDIR(inode->i_mode))
5485+ btail = au_dbtaildir(dentry);
5486+ for (bindex = bstart; bindex <= btail; bindex++) {
5487+ h_dentry = au_h_dptr(dentry, bindex);
5488+ if (!h_dentry)
5489+ continue;
5490+
5491+ AuDbg("b%d, %.*s\n", bindex, AuDLNPair(h_dentry));
027c5e7a 5492+ spin_lock(&h_dentry->d_lock);
1facf9fc 5493+ h_name = &h_dentry->d_name;
5494+ if (unlikely(do_udba
5495+ && !is_root
5496+ && (unhashed != !!d_unhashed(h_dentry)
5497+ || name->len != h_name->len
5498+ || memcmp(name->name, h_name->name, name->len))
5499+ )) {
5500+ AuDbg("unhash 0x%x 0x%x, %.*s %.*s\n",
5501+ unhashed, d_unhashed(h_dentry),
5502+ AuDLNPair(dentry), AuDLNPair(h_dentry));
027c5e7a 5503+ spin_unlock(&h_dentry->d_lock);
1facf9fc 5504+ goto err;
5505+ }
027c5e7a 5506+ spin_unlock(&h_dentry->d_lock);
1facf9fc 5507+
5508+ err = au_do_h_d_reval(h_dentry, nd, dentry, bindex);
5509+ if (unlikely(err))
5510+ /* do not goto err, to keep the errno */
5511+ break;
5512+
5513+ /* todo: plink too? */
5514+ if (!do_udba)
5515+ continue;
5516+
5517+ /* UDBA tests */
5518+ h_inode = h_dentry->d_inode;
5519+ if (unlikely(!!inode != !!h_inode))
5520+ goto err;
5521+
5522+ h_plus = plus;
5523+ h_mode = mode;
5524+ h_cached_inode = h_inode;
5525+ if (h_inode) {
5526+ h_mode = (h_inode->i_mode & S_IFMT);
5527+ h_plus = (h_inode->i_nlink > 0);
5528+ }
5529+ if (inode && ibs <= bindex && bindex <= ibe)
5530+ h_cached_inode = au_h_iptr(inode, bindex);
5531+
5532+ if (unlikely(plus != h_plus
5533+ || mode != h_mode
5534+ || h_cached_inode != h_inode))
5535+ goto err;
5536+ continue;
5537+
5538+ err:
5539+ err = -EINVAL;
5540+ break;
5541+ }
5542+
5543+ return err;
5544+}
5545+
027c5e7a 5546+/* todo: consolidate with do_refresh() and au_reval_for_attr() */
1facf9fc 5547+static int simple_reval_dpath(struct dentry *dentry, unsigned int sigen)
5548+{
5549+ int err;
5550+ struct dentry *parent;
1facf9fc 5551+
027c5e7a 5552+ if (!au_digen_test(dentry, sigen))
1facf9fc 5553+ return 0;
5554+
5555+ parent = dget_parent(dentry);
5556+ di_read_lock_parent(parent, AuLock_IR);
027c5e7a 5557+ AuDebugOn(au_digen_test(parent, sigen));
1facf9fc 5558+ au_dbg_verify_gen(parent, sigen);
027c5e7a 5559+ err = au_refresh_dentry(dentry, parent);
1facf9fc 5560+ di_read_unlock(parent, AuLock_IR);
5561+ dput(parent);
027c5e7a 5562+ AuTraceErr(err);
1facf9fc 5563+ return err;
5564+}
5565+
5566+int au_reval_dpath(struct dentry *dentry, unsigned int sigen)
5567+{
5568+ int err;
5569+ struct dentry *d, *parent;
5570+ struct inode *inode;
5571+
027c5e7a 5572+ if (!au_ftest_si(au_sbi(dentry->d_sb), FAILED_REFRESH_DIR))
1facf9fc 5573+ return simple_reval_dpath(dentry, sigen);
5574+
5575+ /* slow loop, keep it simple and stupid */
5576+ /* cf: au_cpup_dirs() */
5577+ err = 0;
5578+ parent = NULL;
027c5e7a 5579+ while (au_digen_test(dentry, sigen)) {
1facf9fc 5580+ d = dentry;
5581+ while (1) {
5582+ dput(parent);
5583+ parent = dget_parent(d);
027c5e7a 5584+ if (!au_digen_test(parent, sigen))
1facf9fc 5585+ break;
5586+ d = parent;
5587+ }
5588+
5589+ inode = d->d_inode;
5590+ if (d != dentry)
027c5e7a 5591+ di_write_lock_child2(d);
1facf9fc 5592+
5593+ /* someone might update our dentry while we were sleeping */
027c5e7a
AM
5594+ if (au_digen_test(d, sigen)) {
5595+ /*
5596+ * todo: consolidate with simple_reval_dpath(),
5597+ * do_refresh() and au_reval_for_attr().
5598+ */
1facf9fc 5599+ di_read_lock_parent(parent, AuLock_IR);
027c5e7a 5600+ err = au_refresh_dentry(d, parent);
1facf9fc 5601+ di_read_unlock(parent, AuLock_IR);
5602+ }
5603+
5604+ if (d != dentry)
5605+ di_write_unlock(d);
5606+ dput(parent);
5607+ if (unlikely(err))
5608+ break;
5609+ }
5610+
5611+ return err;
5612+}
5613+
5614+/*
5615+ * if valid returns 1, otherwise 0.
5616+ */
5617+static int aufs_d_revalidate(struct dentry *dentry, struct nameidata *nd)
5618+{
5619+ int valid, err;
5620+ unsigned int sigen;
5621+ unsigned char do_udba;
5622+ struct super_block *sb;
5623+ struct inode *inode;
5624+
027c5e7a
AM
5625+ /* todo: support rcu-walk? */
5626+ if (nd && (nd->flags & LOOKUP_RCU))
5627+ return -ECHILD;
5628+
5629+ valid = 0;
5630+ if (unlikely(!au_di(dentry)))
5631+ goto out;
5632+
5633+ inode = dentry->d_inode;
5634+ if (inode && is_bad_inode(inode))
5635+ goto out;
5636+
e49829fe 5637+ valid = 1;
1facf9fc 5638+ sb = dentry->d_sb;
e49829fe
JR
5639+ /*
5640+ * todo: very ugly
5641+ * i_mutex of parent dir may be held,
5642+ * but we should not return 'invalid' due to busy.
5643+ */
5644+ err = aufs_read_lock(dentry, AuLock_FLUSH | AuLock_DW | AuLock_NOPLM);
5645+ if (unlikely(err)) {
5646+ valid = err;
027c5e7a 5647+ AuTraceErr(err);
e49829fe
JR
5648+ goto out;
5649+ }
027c5e7a
AM
5650+ if (unlikely(au_dbrange_test(dentry))) {
5651+ err = -EINVAL;
5652+ AuTraceErr(err);
5653+ goto out_dgrade;
1facf9fc 5654+ }
027c5e7a
AM
5655+
5656+ sigen = au_sigen(sb);
5657+ if (au_digen_test(dentry, sigen)) {
1facf9fc 5658+ AuDebugOn(IS_ROOT(dentry));
027c5e7a
AM
5659+ err = au_reval_dpath(dentry, sigen);
5660+ if (unlikely(err)) {
5661+ AuTraceErr(err);
1facf9fc 5662+ goto out_dgrade;
027c5e7a 5663+ }
1facf9fc 5664+ }
5665+ di_downgrade_lock(dentry, AuLock_IR);
5666+
1facf9fc 5667+ err = -EINVAL;
027c5e7a
AM
5668+ if (inode && (IS_DEADDIR(inode) || !inode->i_nlink))
5669+ goto out_inval;
5670+
1facf9fc 5671+ do_udba = !au_opt_test(au_mntflags(sb), UDBA_NONE);
5672+ if (do_udba && inode) {
5673+ aufs_bindex_t bstart = au_ibstart(inode);
027c5e7a 5674+ struct inode *h_inode;
1facf9fc 5675+
027c5e7a
AM
5676+ if (bstart >= 0) {
5677+ h_inode = au_h_iptr(inode, bstart);
5678+ if (h_inode && au_test_higen(inode, h_inode))
5679+ goto out_inval;
5680+ }
1facf9fc 5681+ }
5682+
5683+ err = h_d_revalidate(dentry, inode, nd, do_udba);
027c5e7a 5684+ if (unlikely(!err && do_udba && au_dbstart(dentry) < 0)) {
1facf9fc 5685+ err = -EIO;
027c5e7a
AM
5686+ AuDbg("both of real entry and whiteout found, %.*s, err %d\n",
5687+ AuDLNPair(dentry), err);
5688+ }
e49829fe 5689+ goto out_inval;
1facf9fc 5690+
4f0767ce 5691+out_dgrade:
1facf9fc 5692+ di_downgrade_lock(dentry, AuLock_IR);
e49829fe 5693+out_inval:
1facf9fc 5694+ aufs_read_unlock(dentry, AuLock_IR);
5695+ AuTraceErr(err);
5696+ valid = !err;
e49829fe 5697+out:
027c5e7a 5698+ if (!valid) {
e49829fe 5699+ AuDbg("%.*s invalid, %d\n", AuDLNPair(dentry), valid);
027c5e7a
AM
5700+ d_drop(dentry);
5701+ }
1facf9fc 5702+ return valid;
5703+}
5704+
5705+static void aufs_d_release(struct dentry *dentry)
5706+{
027c5e7a 5707+ if (au_di(dentry)) {
4a4d8108
AM
5708+ au_di_fin(dentry);
5709+ au_hn_di_reinit(dentry);
1facf9fc 5710+ }
1facf9fc 5711+}
5712+
4a4d8108 5713+const struct dentry_operations aufs_dop = {
1facf9fc 5714+ .d_revalidate = aufs_d_revalidate,
5715+ .d_release = aufs_d_release
5716+};
7f207e10
AM
5717diff -urN /usr/share/empty/fs/aufs/dentry.h linux/fs/aufs/dentry.h
5718--- /usr/share/empty/fs/aufs/dentry.h 1970-01-01 01:00:00.000000000 +0100
87a755f4 5719+++ linux/fs/aufs/dentry.h 2011-07-22 08:26:47.854303107 +0200
2cbb1c4b 5720@@ -0,0 +1,238 @@
1facf9fc 5721+/*
027c5e7a 5722+ * Copyright (C) 2005-2011 Junjiro R. Okajima
1facf9fc 5723+ *
5724+ * This program, aufs is free software; you can redistribute it and/or modify
5725+ * it under the terms of the GNU General Public License as published by
5726+ * the Free Software Foundation; either version 2 of the License, or
5727+ * (at your option) any later version.
dece6358
AM
5728+ *
5729+ * This program is distributed in the hope that it will be useful,
5730+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
5731+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
5732+ * GNU General Public License for more details.
5733+ *
5734+ * You should have received a copy of the GNU General Public License
5735+ * along with this program; if not, write to the Free Software
5736+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 5737+ */
5738+
5739+/*
5740+ * lookup and dentry operations
5741+ */
5742+
5743+#ifndef __AUFS_DENTRY_H__
5744+#define __AUFS_DENTRY_H__
5745+
5746+#ifdef __KERNEL__
5747+
dece6358 5748+#include <linux/dcache.h>
1facf9fc 5749+#include <linux/aufs_type.h>
5750+#include "rwsem.h"
5751+
1facf9fc 5752+struct au_hdentry {
5753+ struct dentry *hd_dentry;
027c5e7a 5754+ aufs_bindex_t hd_id;
1facf9fc 5755+};
5756+
5757+struct au_dinfo {
5758+ atomic_t di_generation;
5759+
dece6358 5760+ struct au_rwsem di_rwsem;
1facf9fc 5761+ aufs_bindex_t di_bstart, di_bend, di_bwh, di_bdiropq;
5762+ struct au_hdentry *di_hdentry;
4a4d8108 5763+} ____cacheline_aligned_in_smp;
1facf9fc 5764+
5765+/* ---------------------------------------------------------------------- */
5766+
5767+/* dentry.c */
4a4d8108 5768+extern const struct dentry_operations aufs_dop;
1facf9fc 5769+struct au_branch;
5770+struct dentry *au_lkup_one(struct qstr *name, struct dentry *h_parent,
5771+ struct au_branch *br, struct nameidata *nd);
5772+struct dentry *au_sio_lkup_one(struct qstr *name, struct dentry *parent,
5773+ struct au_branch *br);
5774+int au_h_verify(struct dentry *h_dentry, unsigned int udba, struct inode *h_dir,
5775+ struct dentry *h_parent, struct au_branch *br);
5776+
5777+int au_lkup_dentry(struct dentry *dentry, aufs_bindex_t bstart, mode_t type,
5778+ struct nameidata *nd);
5779+int au_lkup_neg(struct dentry *dentry, aufs_bindex_t bindex);
027c5e7a 5780+int au_refresh_dentry(struct dentry *dentry, struct dentry *parent);
1facf9fc 5781+int au_reval_dpath(struct dentry *dentry, unsigned int sigen);
5782+
5783+/* dinfo.c */
4a4d8108 5784+void au_di_init_once(void *_di);
027c5e7a
AM
5785+struct au_dinfo *au_di_alloc(struct super_block *sb, unsigned int lsc);
5786+void au_di_free(struct au_dinfo *dinfo);
5787+void au_di_swap(struct au_dinfo *a, struct au_dinfo *b);
5788+void au_di_cp(struct au_dinfo *dst, struct au_dinfo *src);
4a4d8108
AM
5789+int au_di_init(struct dentry *dentry);
5790+void au_di_fin(struct dentry *dentry);
1facf9fc 5791+int au_di_realloc(struct au_dinfo *dinfo, int nbr);
5792+
5793+void di_read_lock(struct dentry *d, int flags, unsigned int lsc);
5794+void di_read_unlock(struct dentry *d, int flags);
5795+void di_downgrade_lock(struct dentry *d, int flags);
5796+void di_write_lock(struct dentry *d, unsigned int lsc);
5797+void di_write_unlock(struct dentry *d);
5798+void di_write_lock2_child(struct dentry *d1, struct dentry *d2, int isdir);
5799+void di_write_lock2_parent(struct dentry *d1, struct dentry *d2, int isdir);
5800+void di_write_unlock2(struct dentry *d1, struct dentry *d2);
5801+
5802+struct dentry *au_h_dptr(struct dentry *dentry, aufs_bindex_t bindex);
2cbb1c4b 5803+struct dentry *au_h_d_alias(struct dentry *dentry, aufs_bindex_t bindex);
1facf9fc 5804+aufs_bindex_t au_dbtail(struct dentry *dentry);
5805+aufs_bindex_t au_dbtaildir(struct dentry *dentry);
5806+
5807+void au_set_h_dptr(struct dentry *dentry, aufs_bindex_t bindex,
5808+ struct dentry *h_dentry);
027c5e7a
AM
5809+int au_digen_test(struct dentry *dentry, unsigned int sigen);
5810+int au_dbrange_test(struct dentry *dentry);
1facf9fc 5811+void au_update_digen(struct dentry *dentry);
5812+void au_update_dbrange(struct dentry *dentry, int do_put_zero);
5813+void au_update_dbstart(struct dentry *dentry);
5814+void au_update_dbend(struct dentry *dentry);
5815+int au_find_dbindex(struct dentry *dentry, struct dentry *h_dentry);
5816+
5817+/* ---------------------------------------------------------------------- */
5818+
5819+static inline struct au_dinfo *au_di(struct dentry *dentry)
5820+{
5821+ return dentry->d_fsdata;
5822+}
5823+
5824+/* ---------------------------------------------------------------------- */
5825+
5826+/* lock subclass for dinfo */
5827+enum {
5828+ AuLsc_DI_CHILD, /* child first */
4a4d8108 5829+ AuLsc_DI_CHILD2, /* rename(2), link(2), and cpup at hnotify */
1facf9fc 5830+ AuLsc_DI_CHILD3, /* copyup dirs */
5831+ AuLsc_DI_PARENT,
5832+ AuLsc_DI_PARENT2,
027c5e7a
AM
5833+ AuLsc_DI_PARENT3,
5834+ AuLsc_DI_TMP /* temp for replacing dinfo */
1facf9fc 5835+};
5836+
5837+/*
5838+ * di_read_lock_child, di_write_lock_child,
5839+ * di_read_lock_child2, di_write_lock_child2,
5840+ * di_read_lock_child3, di_write_lock_child3,
5841+ * di_read_lock_parent, di_write_lock_parent,
5842+ * di_read_lock_parent2, di_write_lock_parent2,
5843+ * di_read_lock_parent3, di_write_lock_parent3,
5844+ */
5845+#define AuReadLockFunc(name, lsc) \
5846+static inline void di_read_lock_##name(struct dentry *d, int flags) \
5847+{ di_read_lock(d, flags, AuLsc_DI_##lsc); }
5848+
5849+#define AuWriteLockFunc(name, lsc) \
5850+static inline void di_write_lock_##name(struct dentry *d) \
5851+{ di_write_lock(d, AuLsc_DI_##lsc); }
5852+
5853+#define AuRWLockFuncs(name, lsc) \
5854+ AuReadLockFunc(name, lsc) \
5855+ AuWriteLockFunc(name, lsc)
5856+
5857+AuRWLockFuncs(child, CHILD);
5858+AuRWLockFuncs(child2, CHILD2);
5859+AuRWLockFuncs(child3, CHILD3);
5860+AuRWLockFuncs(parent, PARENT);
5861+AuRWLockFuncs(parent2, PARENT2);
5862+AuRWLockFuncs(parent3, PARENT3);
5863+
5864+#undef AuReadLockFunc
5865+#undef AuWriteLockFunc
5866+#undef AuRWLockFuncs
5867+
5868+#define DiMustNoWaiters(d) AuRwMustNoWaiters(&au_di(d)->di_rwsem)
dece6358
AM
5869+#define DiMustAnyLock(d) AuRwMustAnyLock(&au_di(d)->di_rwsem)
5870+#define DiMustWriteLock(d) AuRwMustWriteLock(&au_di(d)->di_rwsem)
1facf9fc 5871+
5872+/* ---------------------------------------------------------------------- */
5873+
5874+/* todo: memory barrier? */
5875+static inline unsigned int au_digen(struct dentry *d)
5876+{
5877+ return atomic_read(&au_di(d)->di_generation);
5878+}
5879+
5880+static inline void au_h_dentry_init(struct au_hdentry *hdentry)
5881+{
5882+ hdentry->hd_dentry = NULL;
5883+}
5884+
5885+static inline void au_hdput(struct au_hdentry *hd)
5886+{
4a4d8108
AM
5887+ if (hd)
5888+ dput(hd->hd_dentry);
1facf9fc 5889+}
5890+
5891+static inline aufs_bindex_t au_dbstart(struct dentry *dentry)
5892+{
1308ab2a 5893+ DiMustAnyLock(dentry);
1facf9fc 5894+ return au_di(dentry)->di_bstart;
5895+}
5896+
5897+static inline aufs_bindex_t au_dbend(struct dentry *dentry)
5898+{
1308ab2a 5899+ DiMustAnyLock(dentry);
1facf9fc 5900+ return au_di(dentry)->di_bend;
5901+}
5902+
5903+static inline aufs_bindex_t au_dbwh(struct dentry *dentry)
5904+{
1308ab2a 5905+ DiMustAnyLock(dentry);
1facf9fc 5906+ return au_di(dentry)->di_bwh;
5907+}
5908+
5909+static inline aufs_bindex_t au_dbdiropq(struct dentry *dentry)
5910+{
1308ab2a 5911+ DiMustAnyLock(dentry);
1facf9fc 5912+ return au_di(dentry)->di_bdiropq;
5913+}
5914+
5915+/* todo: hard/soft set? */
5916+static inline void au_set_dbstart(struct dentry *dentry, aufs_bindex_t bindex)
5917+{
1308ab2a 5918+ DiMustWriteLock(dentry);
1facf9fc 5919+ au_di(dentry)->di_bstart = bindex;
5920+}
5921+
5922+static inline void au_set_dbend(struct dentry *dentry, aufs_bindex_t bindex)
5923+{
1308ab2a 5924+ DiMustWriteLock(dentry);
1facf9fc 5925+ au_di(dentry)->di_bend = bindex;
5926+}
5927+
5928+static inline void au_set_dbwh(struct dentry *dentry, aufs_bindex_t bindex)
5929+{
1308ab2a 5930+ DiMustWriteLock(dentry);
1facf9fc 5931+ /* dbwh can be outside of bstart - bend range */
5932+ au_di(dentry)->di_bwh = bindex;
5933+}
5934+
5935+static inline void au_set_dbdiropq(struct dentry *dentry, aufs_bindex_t bindex)
5936+{
1308ab2a 5937+ DiMustWriteLock(dentry);
1facf9fc 5938+ au_di(dentry)->di_bdiropq = bindex;
5939+}
5940+
5941+/* ---------------------------------------------------------------------- */
5942+
4a4d8108 5943+#ifdef CONFIG_AUFS_HNOTIFY
1facf9fc 5944+static inline void au_digen_dec(struct dentry *d)
5945+{
e49829fe 5946+ atomic_dec(&au_di(d)->di_generation);
1facf9fc 5947+}
5948+
4a4d8108 5949+static inline void au_hn_di_reinit(struct dentry *dentry)
1facf9fc 5950+{
5951+ dentry->d_fsdata = NULL;
5952+}
5953+#else
4a4d8108
AM
5954+AuStubVoid(au_hn_di_reinit, struct dentry *dentry __maybe_unused)
5955+#endif /* CONFIG_AUFS_HNOTIFY */
1facf9fc 5956+
5957+#endif /* __KERNEL__ */
5958+#endif /* __AUFS_DENTRY_H__ */
7f207e10
AM
5959diff -urN /usr/share/empty/fs/aufs/dinfo.c linux/fs/aufs/dinfo.c
5960--- /usr/share/empty/fs/aufs/dinfo.c 1970-01-01 01:00:00.000000000 +0100
87a755f4 5961+++ linux/fs/aufs/dinfo.c 2011-07-22 08:26:47.854303107 +0200
2cbb1c4b 5962@@ -0,0 +1,543 @@
1facf9fc 5963+/*
027c5e7a 5964+ * Copyright (C) 2005-2011 Junjiro R. Okajima
1facf9fc 5965+ *
5966+ * This program, aufs is free software; you can redistribute it and/or modify
5967+ * it under the terms of the GNU General Public License as published by
5968+ * the Free Software Foundation; either version 2 of the License, or
5969+ * (at your option) any later version.
dece6358
AM
5970+ *
5971+ * This program is distributed in the hope that it will be useful,
5972+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
5973+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
5974+ * GNU General Public License for more details.
5975+ *
5976+ * You should have received a copy of the GNU General Public License
5977+ * along with this program; if not, write to the Free Software
5978+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 5979+ */
5980+
5981+/*
5982+ * dentry private data
5983+ */
5984+
5985+#include "aufs.h"
5986+
e49829fe 5987+void au_di_init_once(void *_dinfo)
4a4d8108 5988+{
e49829fe
JR
5989+ struct au_dinfo *dinfo = _dinfo;
5990+ static struct lock_class_key aufs_di;
4a4d8108 5991+
e49829fe
JR
5992+ au_rw_init(&dinfo->di_rwsem);
5993+ au_rw_class(&dinfo->di_rwsem, &aufs_di);
4a4d8108
AM
5994+}
5995+
027c5e7a 5996+struct au_dinfo *au_di_alloc(struct super_block *sb, unsigned int lsc)
1facf9fc 5997+{
5998+ struct au_dinfo *dinfo;
027c5e7a 5999+ int nbr, i;
1facf9fc 6000+
6001+ dinfo = au_cache_alloc_dinfo();
6002+ if (unlikely(!dinfo))
6003+ goto out;
6004+
1facf9fc 6005+ nbr = au_sbend(sb) + 1;
6006+ if (nbr <= 0)
6007+ nbr = 1;
6008+ dinfo->di_hdentry = kcalloc(nbr, sizeof(*dinfo->di_hdentry), GFP_NOFS);
027c5e7a
AM
6009+ if (dinfo->di_hdentry) {
6010+ au_rw_write_lock_nested(&dinfo->di_rwsem, lsc);
6011+ dinfo->di_bstart = -1;
6012+ dinfo->di_bend = -1;
6013+ dinfo->di_bwh = -1;
6014+ dinfo->di_bdiropq = -1;
6015+ for (i = 0; i < nbr; i++)
6016+ dinfo->di_hdentry[i].hd_id = -1;
6017+ goto out;
6018+ }
1facf9fc 6019+
1facf9fc 6020+ au_cache_free_dinfo(dinfo);
027c5e7a
AM
6021+ dinfo = NULL;
6022+
4f0767ce 6023+out:
027c5e7a 6024+ return dinfo;
1facf9fc 6025+}
6026+
027c5e7a 6027+void au_di_free(struct au_dinfo *dinfo)
4a4d8108 6028+{
4a4d8108
AM
6029+ struct au_hdentry *p;
6030+ aufs_bindex_t bend, bindex;
6031+
6032+ /* dentry may not be revalidated */
027c5e7a 6033+ bindex = dinfo->di_bstart;
4a4d8108 6034+ if (bindex >= 0) {
027c5e7a
AM
6035+ bend = dinfo->di_bend;
6036+ p = dinfo->di_hdentry + bindex;
4a4d8108
AM
6037+ while (bindex++ <= bend)
6038+ au_hdput(p++);
6039+ }
027c5e7a
AM
6040+ kfree(dinfo->di_hdentry);
6041+ au_cache_free_dinfo(dinfo);
6042+}
6043+
6044+void au_di_swap(struct au_dinfo *a, struct au_dinfo *b)
6045+{
6046+ struct au_hdentry *p;
6047+ aufs_bindex_t bi;
6048+
6049+ AuRwMustWriteLock(&a->di_rwsem);
6050+ AuRwMustWriteLock(&b->di_rwsem);
6051+
6052+#define DiSwap(v, name) \
6053+ do { \
6054+ v = a->di_##name; \
6055+ a->di_##name = b->di_##name; \
6056+ b->di_##name = v; \
6057+ } while (0)
6058+
6059+ DiSwap(p, hdentry);
6060+ DiSwap(bi, bstart);
6061+ DiSwap(bi, bend);
6062+ DiSwap(bi, bwh);
6063+ DiSwap(bi, bdiropq);
6064+ /* smp_mb(); */
6065+
6066+#undef DiSwap
6067+}
6068+
6069+void au_di_cp(struct au_dinfo *dst, struct au_dinfo *src)
6070+{
6071+ AuRwMustWriteLock(&dst->di_rwsem);
6072+ AuRwMustWriteLock(&src->di_rwsem);
6073+
6074+ dst->di_bstart = src->di_bstart;
6075+ dst->di_bend = src->di_bend;
6076+ dst->di_bwh = src->di_bwh;
6077+ dst->di_bdiropq = src->di_bdiropq;
6078+ /* smp_mb(); */
6079+}
6080+
6081+int au_di_init(struct dentry *dentry)
6082+{
6083+ int err;
6084+ struct super_block *sb;
6085+ struct au_dinfo *dinfo;
6086+
6087+ err = 0;
6088+ sb = dentry->d_sb;
6089+ dinfo = au_di_alloc(sb, AuLsc_DI_CHILD);
6090+ if (dinfo) {
6091+ atomic_set(&dinfo->di_generation, au_sigen(sb));
6092+ /* smp_mb(); */ /* atomic_set */
6093+ dentry->d_fsdata = dinfo;
6094+ } else
6095+ err = -ENOMEM;
6096+
6097+ return err;
6098+}
6099+
6100+void au_di_fin(struct dentry *dentry)
6101+{
6102+ struct au_dinfo *dinfo;
6103+
6104+ dinfo = au_di(dentry);
6105+ AuRwDestroy(&dinfo->di_rwsem);
6106+ au_di_free(dinfo);
4a4d8108
AM
6107+}
6108+
1facf9fc 6109+int au_di_realloc(struct au_dinfo *dinfo, int nbr)
6110+{
6111+ int err, sz;
6112+ struct au_hdentry *hdp;
6113+
1308ab2a 6114+ AuRwMustWriteLock(&dinfo->di_rwsem);
6115+
1facf9fc 6116+ err = -ENOMEM;
6117+ sz = sizeof(*hdp) * (dinfo->di_bend + 1);
6118+ if (!sz)
6119+ sz = sizeof(*hdp);
6120+ hdp = au_kzrealloc(dinfo->di_hdentry, sz, sizeof(*hdp) * nbr, GFP_NOFS);
6121+ if (hdp) {
6122+ dinfo->di_hdentry = hdp;
6123+ err = 0;
6124+ }
6125+
6126+ return err;
6127+}
6128+
6129+/* ---------------------------------------------------------------------- */
6130+
6131+static void do_ii_write_lock(struct inode *inode, unsigned int lsc)
6132+{
6133+ switch (lsc) {
6134+ case AuLsc_DI_CHILD:
6135+ ii_write_lock_child(inode);
6136+ break;
6137+ case AuLsc_DI_CHILD2:
6138+ ii_write_lock_child2(inode);
6139+ break;
6140+ case AuLsc_DI_CHILD3:
6141+ ii_write_lock_child3(inode);
6142+ break;
6143+ case AuLsc_DI_PARENT:
6144+ ii_write_lock_parent(inode);
6145+ break;
6146+ case AuLsc_DI_PARENT2:
6147+ ii_write_lock_parent2(inode);
6148+ break;
6149+ case AuLsc_DI_PARENT3:
6150+ ii_write_lock_parent3(inode);
6151+ break;
6152+ default:
6153+ BUG();
6154+ }
6155+}
6156+
6157+static void do_ii_read_lock(struct inode *inode, unsigned int lsc)
6158+{
6159+ switch (lsc) {
6160+ case AuLsc_DI_CHILD:
6161+ ii_read_lock_child(inode);
6162+ break;
6163+ case AuLsc_DI_CHILD2:
6164+ ii_read_lock_child2(inode);
6165+ break;
6166+ case AuLsc_DI_CHILD3:
6167+ ii_read_lock_child3(inode);
6168+ break;
6169+ case AuLsc_DI_PARENT:
6170+ ii_read_lock_parent(inode);
6171+ break;
6172+ case AuLsc_DI_PARENT2:
6173+ ii_read_lock_parent2(inode);
6174+ break;
6175+ case AuLsc_DI_PARENT3:
6176+ ii_read_lock_parent3(inode);
6177+ break;
6178+ default:
6179+ BUG();
6180+ }
6181+}
6182+
6183+void di_read_lock(struct dentry *d, int flags, unsigned int lsc)
6184+{
dece6358 6185+ au_rw_read_lock_nested(&au_di(d)->di_rwsem, lsc);
1facf9fc 6186+ if (d->d_inode) {
6187+ if (au_ftest_lock(flags, IW))
6188+ do_ii_write_lock(d->d_inode, lsc);
6189+ else if (au_ftest_lock(flags, IR))
6190+ do_ii_read_lock(d->d_inode, lsc);
6191+ }
6192+}
6193+
6194+void di_read_unlock(struct dentry *d, int flags)
6195+{
6196+ if (d->d_inode) {
027c5e7a
AM
6197+ if (au_ftest_lock(flags, IW)) {
6198+ au_dbg_verify_dinode(d);
1facf9fc 6199+ ii_write_unlock(d->d_inode);
027c5e7a
AM
6200+ } else if (au_ftest_lock(flags, IR)) {
6201+ au_dbg_verify_dinode(d);
1facf9fc 6202+ ii_read_unlock(d->d_inode);
027c5e7a 6203+ }
1facf9fc 6204+ }
dece6358 6205+ au_rw_read_unlock(&au_di(d)->di_rwsem);
1facf9fc 6206+}
6207+
6208+void di_downgrade_lock(struct dentry *d, int flags)
6209+{
1facf9fc 6210+ if (d->d_inode && au_ftest_lock(flags, IR))
6211+ ii_downgrade_lock(d->d_inode);
dece6358 6212+ au_rw_dgrade_lock(&au_di(d)->di_rwsem);
1facf9fc 6213+}
6214+
6215+void di_write_lock(struct dentry *d, unsigned int lsc)
6216+{
dece6358 6217+ au_rw_write_lock_nested(&au_di(d)->di_rwsem, lsc);
1facf9fc 6218+ if (d->d_inode)
6219+ do_ii_write_lock(d->d_inode, lsc);
6220+}
6221+
6222+void di_write_unlock(struct dentry *d)
6223+{
027c5e7a 6224+ au_dbg_verify_dinode(d);
1facf9fc 6225+ if (d->d_inode)
6226+ ii_write_unlock(d->d_inode);
dece6358 6227+ au_rw_write_unlock(&au_di(d)->di_rwsem);
1facf9fc 6228+}
6229+
6230+void di_write_lock2_child(struct dentry *d1, struct dentry *d2, int isdir)
6231+{
6232+ AuDebugOn(d1 == d2
6233+ || d1->d_inode == d2->d_inode
6234+ || d1->d_sb != d2->d_sb);
6235+
6236+ if (isdir && au_test_subdir(d1, d2)) {
6237+ di_write_lock_child(d1);
6238+ di_write_lock_child2(d2);
6239+ } else {
6240+ /* there should be no races */
6241+ di_write_lock_child(d2);
6242+ di_write_lock_child2(d1);
6243+ }
6244+}
6245+
6246+void di_write_lock2_parent(struct dentry *d1, struct dentry *d2, int isdir)
6247+{
6248+ AuDebugOn(d1 == d2
6249+ || d1->d_inode == d2->d_inode
6250+ || d1->d_sb != d2->d_sb);
6251+
6252+ if (isdir && au_test_subdir(d1, d2)) {
6253+ di_write_lock_parent(d1);
6254+ di_write_lock_parent2(d2);
6255+ } else {
6256+ /* there should be no races */
6257+ di_write_lock_parent(d2);
6258+ di_write_lock_parent2(d1);
6259+ }
6260+}
6261+
6262+void di_write_unlock2(struct dentry *d1, struct dentry *d2)
6263+{
6264+ di_write_unlock(d1);
6265+ if (d1->d_inode == d2->d_inode)
dece6358 6266+ au_rw_write_unlock(&au_di(d2)->di_rwsem);
1facf9fc 6267+ else
6268+ di_write_unlock(d2);
6269+}
6270+
6271+/* ---------------------------------------------------------------------- */
6272+
6273+struct dentry *au_h_dptr(struct dentry *dentry, aufs_bindex_t bindex)
6274+{
6275+ struct dentry *d;
6276+
1308ab2a 6277+ DiMustAnyLock(dentry);
6278+
1facf9fc 6279+ if (au_dbstart(dentry) < 0 || bindex < au_dbstart(dentry))
6280+ return NULL;
6281+ AuDebugOn(bindex < 0);
6282+ d = au_di(dentry)->di_hdentry[0 + bindex].hd_dentry;
027c5e7a 6283+ AuDebugOn(d && d->d_count <= 0);
1facf9fc 6284+ return d;
6285+}
6286+
2cbb1c4b
JR
6287+/*
6288+ * extended version of au_h_dptr().
6289+ * returns a hashed and positive h_dentry in bindex, NULL, or error.
6290+ */
6291+struct dentry *au_h_d_alias(struct dentry *dentry, aufs_bindex_t bindex)
6292+{
6293+ struct dentry *h_dentry;
6294+ struct inode *inode, *h_inode;
6295+
6296+ inode = dentry->d_inode;
6297+ AuDebugOn(!inode);
6298+
6299+ h_dentry = NULL;
6300+ if (au_dbstart(dentry) <= bindex
6301+ && bindex <= au_dbend(dentry))
6302+ h_dentry = au_h_dptr(dentry, bindex);
6303+ if (h_dentry && !au_d_hashed_positive(h_dentry)) {
6304+ dget(h_dentry);
6305+ goto out; /* success */
6306+ }
6307+
6308+ AuDebugOn(bindex < au_ibstart(inode));
6309+ AuDebugOn(au_ibend(inode) < bindex);
6310+ h_inode = au_h_iptr(inode, bindex);
6311+ h_dentry = d_find_alias(h_inode);
6312+ if (h_dentry) {
6313+ if (!IS_ERR(h_dentry)) {
6314+ if (!au_d_hashed_positive(h_dentry))
6315+ goto out; /* success */
6316+ dput(h_dentry);
6317+ } else
6318+ goto out;
6319+ }
6320+
6321+ if (au_opt_test(au_mntflags(dentry->d_sb), PLINK)) {
6322+ h_dentry = au_plink_lkup(inode, bindex);
6323+ AuDebugOn(!h_dentry);
6324+ if (!IS_ERR(h_dentry)) {
6325+ if (!au_d_hashed_positive(h_dentry))
6326+ goto out; /* success */
6327+ dput(h_dentry);
6328+ h_dentry = NULL;
6329+ }
6330+ }
6331+
6332+out:
6333+ AuDbgDentry(h_dentry);
6334+ return h_dentry;
6335+}
6336+
1facf9fc 6337+aufs_bindex_t au_dbtail(struct dentry *dentry)
6338+{
6339+ aufs_bindex_t bend, bwh;
6340+
6341+ bend = au_dbend(dentry);
6342+ if (0 <= bend) {
6343+ bwh = au_dbwh(dentry);
6344+ if (!bwh)
6345+ return bwh;
6346+ if (0 < bwh && bwh < bend)
6347+ return bwh - 1;
6348+ }
6349+ return bend;
6350+}
6351+
6352+aufs_bindex_t au_dbtaildir(struct dentry *dentry)
6353+{
6354+ aufs_bindex_t bend, bopq;
6355+
6356+ bend = au_dbtail(dentry);
6357+ if (0 <= bend) {
6358+ bopq = au_dbdiropq(dentry);
6359+ if (0 <= bopq && bopq < bend)
6360+ bend = bopq;
6361+ }
6362+ return bend;
6363+}
6364+
6365+/* ---------------------------------------------------------------------- */
6366+
6367+void au_set_h_dptr(struct dentry *dentry, aufs_bindex_t bindex,
6368+ struct dentry *h_dentry)
6369+{
6370+ struct au_hdentry *hd = au_di(dentry)->di_hdentry + bindex;
027c5e7a 6371+ struct au_branch *br;
1facf9fc 6372+
1308ab2a 6373+ DiMustWriteLock(dentry);
6374+
4a4d8108 6375+ au_hdput(hd);
1facf9fc 6376+ hd->hd_dentry = h_dentry;
027c5e7a
AM
6377+ if (h_dentry) {
6378+ br = au_sbr(dentry->d_sb, bindex);
6379+ hd->hd_id = br->br_id;
6380+ }
6381+}
6382+
6383+int au_dbrange_test(struct dentry *dentry)
6384+{
6385+ int err;
6386+ aufs_bindex_t bstart, bend;
6387+
6388+ err = 0;
6389+ bstart = au_dbstart(dentry);
6390+ bend = au_dbend(dentry);
6391+ if (bstart >= 0)
6392+ AuDebugOn(bend < 0 && bstart > bend);
6393+ else {
6394+ err = -EIO;
6395+ AuDebugOn(bend >= 0);
6396+ }
6397+
6398+ return err;
6399+}
6400+
6401+int au_digen_test(struct dentry *dentry, unsigned int sigen)
6402+{
6403+ int err;
6404+
6405+ err = 0;
6406+ if (unlikely(au_digen(dentry) != sigen
6407+ || au_iigen_test(dentry->d_inode, sigen)))
6408+ err = -EIO;
6409+
6410+ return err;
1facf9fc 6411+}
6412+
6413+void au_update_digen(struct dentry *dentry)
6414+{
6415+ atomic_set(&au_di(dentry)->di_generation, au_sigen(dentry->d_sb));
6416+ /* smp_mb(); */ /* atomic_set */
6417+}
6418+
6419+void au_update_dbrange(struct dentry *dentry, int do_put_zero)
6420+{
6421+ struct au_dinfo *dinfo;
6422+ struct dentry *h_d;
4a4d8108 6423+ struct au_hdentry *hdp;
1facf9fc 6424+
1308ab2a 6425+ DiMustWriteLock(dentry);
6426+
1facf9fc 6427+ dinfo = au_di(dentry);
6428+ if (!dinfo || dinfo->di_bstart < 0)
6429+ return;
6430+
4a4d8108 6431+ hdp = dinfo->di_hdentry;
1facf9fc 6432+ if (do_put_zero) {
6433+ aufs_bindex_t bindex, bend;
6434+
6435+ bend = dinfo->di_bend;
6436+ for (bindex = dinfo->di_bstart; bindex <= bend; bindex++) {
4a4d8108 6437+ h_d = hdp[0 + bindex].hd_dentry;
1facf9fc 6438+ if (h_d && !h_d->d_inode)
6439+ au_set_h_dptr(dentry, bindex, NULL);
6440+ }
6441+ }
6442+
6443+ dinfo->di_bstart = -1;
6444+ while (++dinfo->di_bstart <= dinfo->di_bend)
4a4d8108 6445+ if (hdp[0 + dinfo->di_bstart].hd_dentry)
1facf9fc 6446+ break;
6447+ if (dinfo->di_bstart > dinfo->di_bend) {
6448+ dinfo->di_bstart = -1;
6449+ dinfo->di_bend = -1;
6450+ return;
6451+ }
6452+
6453+ dinfo->di_bend++;
6454+ while (0 <= --dinfo->di_bend)
4a4d8108 6455+ if (hdp[0 + dinfo->di_bend].hd_dentry)
1facf9fc 6456+ break;
6457+ AuDebugOn(dinfo->di_bstart > dinfo->di_bend || dinfo->di_bend < 0);
6458+}
6459+
6460+void au_update_dbstart(struct dentry *dentry)
6461+{
6462+ aufs_bindex_t bindex, bend;
6463+ struct dentry *h_dentry;
6464+
6465+ bend = au_dbend(dentry);
6466+ for (bindex = au_dbstart(dentry); bindex <= bend; bindex++) {
6467+ h_dentry = au_h_dptr(dentry, bindex);
6468+ if (!h_dentry)
6469+ continue;
6470+ if (h_dentry->d_inode) {
6471+ au_set_dbstart(dentry, bindex);
6472+ return;
6473+ }
6474+ au_set_h_dptr(dentry, bindex, NULL);
6475+ }
6476+}
6477+
6478+void au_update_dbend(struct dentry *dentry)
6479+{
6480+ aufs_bindex_t bindex, bstart;
6481+ struct dentry *h_dentry;
6482+
6483+ bstart = au_dbstart(dentry);
7f207e10 6484+ for (bindex = au_dbend(dentry); bindex >= bstart; bindex--) {
1facf9fc 6485+ h_dentry = au_h_dptr(dentry, bindex);
6486+ if (!h_dentry)
6487+ continue;
6488+ if (h_dentry->d_inode) {
6489+ au_set_dbend(dentry, bindex);
6490+ return;
6491+ }
6492+ au_set_h_dptr(dentry, bindex, NULL);
6493+ }
6494+}
6495+
6496+int au_find_dbindex(struct dentry *dentry, struct dentry *h_dentry)
6497+{
6498+ aufs_bindex_t bindex, bend;
6499+
6500+ bend = au_dbend(dentry);
6501+ for (bindex = au_dbstart(dentry); bindex <= bend; bindex++)
6502+ if (au_h_dptr(dentry, bindex) == h_dentry)
6503+ return bindex;
6504+ return -1;
6505+}
7f207e10
AM
6506diff -urN /usr/share/empty/fs/aufs/dir.c linux/fs/aufs/dir.c
6507--- /usr/share/empty/fs/aufs/dir.c 1970-01-01 01:00:00.000000000 +0100
87a755f4 6508+++ linux/fs/aufs/dir.c 2011-03-17 10:46:59.000000000 +0100
027c5e7a 6509@@ -0,0 +1,647 @@
1facf9fc 6510+/*
027c5e7a 6511+ * Copyright (C) 2005-2011 Junjiro R. Okajima
1facf9fc 6512+ *
6513+ * This program, aufs is free software; you can redistribute it and/or modify
6514+ * it under the terms of the GNU General Public License as published by
6515+ * the Free Software Foundation; either version 2 of the License, or
6516+ * (at your option) any later version.
dece6358
AM
6517+ *
6518+ * This program is distributed in the hope that it will be useful,
6519+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
6520+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
6521+ * GNU General Public License for more details.
6522+ *
6523+ * You should have received a copy of the GNU General Public License
6524+ * along with this program; if not, write to the Free Software
6525+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 6526+ */
6527+
6528+/*
6529+ * directory operations
6530+ */
6531+
dece6358 6532+#include <linux/file.h>
1facf9fc 6533+#include <linux/fs_stack.h>
6534+#include "aufs.h"
6535+
6536+void au_add_nlink(struct inode *dir, struct inode *h_dir)
6537+{
6538+ AuDebugOn(!S_ISDIR(dir->i_mode) || !S_ISDIR(h_dir->i_mode));
6539+
6540+ dir->i_nlink += h_dir->i_nlink - 2;
6541+ if (h_dir->i_nlink < 2)
6542+ dir->i_nlink += 2;
6543+}
6544+
6545+void au_sub_nlink(struct inode *dir, struct inode *h_dir)
6546+{
6547+ AuDebugOn(!S_ISDIR(dir->i_mode) || !S_ISDIR(h_dir->i_mode));
6548+
6549+ dir->i_nlink -= h_dir->i_nlink - 2;
6550+ if (h_dir->i_nlink < 2)
6551+ dir->i_nlink -= 2;
6552+}
6553+
1308ab2a 6554+loff_t au_dir_size(struct file *file, struct dentry *dentry)
6555+{
6556+ loff_t sz;
6557+ aufs_bindex_t bindex, bend;
6558+ struct file *h_file;
6559+ struct dentry *h_dentry;
6560+
6561+ sz = 0;
6562+ if (file) {
6563+ AuDebugOn(!file->f_dentry);
6564+ AuDebugOn(!file->f_dentry->d_inode);
6565+ AuDebugOn(!S_ISDIR(file->f_dentry->d_inode->i_mode));
6566+
4a4d8108 6567+ bend = au_fbend_dir(file);
1308ab2a 6568+ for (bindex = au_fbstart(file);
6569+ bindex <= bend && sz < KMALLOC_MAX_SIZE;
6570+ bindex++) {
4a4d8108 6571+ h_file = au_hf_dir(file, bindex);
1308ab2a 6572+ if (h_file
6573+ && h_file->f_dentry
6574+ && h_file->f_dentry->d_inode)
6575+ sz += i_size_read(h_file->f_dentry->d_inode);
6576+ }
6577+ } else {
6578+ AuDebugOn(!dentry);
6579+ AuDebugOn(!dentry->d_inode);
6580+ AuDebugOn(!S_ISDIR(dentry->d_inode->i_mode));
6581+
6582+ bend = au_dbtaildir(dentry);
6583+ for (bindex = au_dbstart(dentry);
6584+ bindex <= bend && sz < KMALLOC_MAX_SIZE;
6585+ bindex++) {
6586+ h_dentry = au_h_dptr(dentry, bindex);
6587+ if (h_dentry && h_dentry->d_inode)
6588+ sz += i_size_read(h_dentry->d_inode);
6589+ }
6590+ }
6591+ if (sz < KMALLOC_MAX_SIZE)
6592+ sz = roundup_pow_of_two(sz);
6593+ if (sz > KMALLOC_MAX_SIZE)
6594+ sz = KMALLOC_MAX_SIZE;
6595+ else if (sz < NAME_MAX) {
6596+ BUILD_BUG_ON(AUFS_RDBLK_DEF < NAME_MAX);
6597+ sz = AUFS_RDBLK_DEF;
6598+ }
6599+ return sz;
6600+}
6601+
1facf9fc 6602+/* ---------------------------------------------------------------------- */
6603+
6604+static int reopen_dir(struct file *file)
6605+{
6606+ int err;
6607+ unsigned int flags;
6608+ aufs_bindex_t bindex, btail, bstart;
6609+ struct dentry *dentry, *h_dentry;
6610+ struct file *h_file;
6611+
6612+ /* open all lower dirs */
6613+ dentry = file->f_dentry;
6614+ bstart = au_dbstart(dentry);
6615+ for (bindex = au_fbstart(file); bindex < bstart; bindex++)
6616+ au_set_h_fptr(file, bindex, NULL);
6617+ au_set_fbstart(file, bstart);
6618+
6619+ btail = au_dbtaildir(dentry);
4a4d8108 6620+ for (bindex = au_fbend_dir(file); btail < bindex; bindex--)
1facf9fc 6621+ au_set_h_fptr(file, bindex, NULL);
4a4d8108 6622+ au_set_fbend_dir(file, btail);
1facf9fc 6623+
4a4d8108 6624+ flags = vfsub_file_flags(file);
1facf9fc 6625+ for (bindex = bstart; bindex <= btail; bindex++) {
6626+ h_dentry = au_h_dptr(dentry, bindex);
6627+ if (!h_dentry)
6628+ continue;
4a4d8108 6629+ h_file = au_hf_dir(file, bindex);
1facf9fc 6630+ if (h_file)
6631+ continue;
6632+
6633+ h_file = au_h_open(dentry, bindex, flags, file);
6634+ err = PTR_ERR(h_file);
6635+ if (IS_ERR(h_file))
6636+ goto out; /* close all? */
6637+ au_set_h_fptr(file, bindex, h_file);
6638+ }
6639+ au_update_figen(file);
6640+ /* todo: necessary? */
6641+ /* file->f_ra = h_file->f_ra; */
6642+ err = 0;
6643+
4f0767ce 6644+out:
1facf9fc 6645+ return err;
6646+}
6647+
6648+static int do_open_dir(struct file *file, int flags)
6649+{
6650+ int err;
6651+ aufs_bindex_t bindex, btail;
6652+ struct dentry *dentry, *h_dentry;
6653+ struct file *h_file;
6654+
1308ab2a 6655+ FiMustWriteLock(file);
6656+
1facf9fc 6657+ dentry = file->f_dentry;
027c5e7a
AM
6658+ err = au_alive_dir(dentry);
6659+ if (unlikely(err))
6660+ goto out;
6661+
1facf9fc 6662+ file->f_version = dentry->d_inode->i_version;
6663+ bindex = au_dbstart(dentry);
6664+ au_set_fbstart(file, bindex);
6665+ btail = au_dbtaildir(dentry);
4a4d8108 6666+ au_set_fbend_dir(file, btail);
1facf9fc 6667+ for (; !err && bindex <= btail; bindex++) {
6668+ h_dentry = au_h_dptr(dentry, bindex);
6669+ if (!h_dentry)
6670+ continue;
6671+
6672+ h_file = au_h_open(dentry, bindex, flags, file);
6673+ if (IS_ERR(h_file)) {
6674+ err = PTR_ERR(h_file);
6675+ break;
6676+ }
6677+ au_set_h_fptr(file, bindex, h_file);
6678+ }
6679+ au_update_figen(file);
6680+ /* todo: necessary? */
6681+ /* file->f_ra = h_file->f_ra; */
6682+ if (!err)
6683+ return 0; /* success */
6684+
6685+ /* close all */
6686+ for (bindex = au_fbstart(file); bindex <= btail; bindex++)
6687+ au_set_h_fptr(file, bindex, NULL);
6688+ au_set_fbstart(file, -1);
4a4d8108
AM
6689+ au_set_fbend_dir(file, -1);
6690+
027c5e7a 6691+out:
1facf9fc 6692+ return err;
6693+}
6694+
6695+static int aufs_open_dir(struct inode *inode __maybe_unused,
6696+ struct file *file)
6697+{
4a4d8108
AM
6698+ int err;
6699+ struct super_block *sb;
6700+ struct au_fidir *fidir;
6701+
6702+ err = -ENOMEM;
6703+ sb = file->f_dentry->d_sb;
6704+ si_read_lock(sb, AuLock_FLUSH);
e49829fe 6705+ fidir = au_fidir_alloc(sb);
4a4d8108
AM
6706+ if (fidir) {
6707+ err = au_do_open(file, do_open_dir, fidir);
6708+ if (unlikely(err))
6709+ kfree(fidir);
6710+ }
6711+ si_read_unlock(sb);
6712+ return err;
1facf9fc 6713+}
6714+
6715+static int aufs_release_dir(struct inode *inode __maybe_unused,
6716+ struct file *file)
6717+{
6718+ struct au_vdir *vdir_cache;
4a4d8108
AM
6719+ struct au_finfo *finfo;
6720+ struct au_fidir *fidir;
6721+ aufs_bindex_t bindex, bend;
1facf9fc 6722+
4a4d8108
AM
6723+ finfo = au_fi(file);
6724+ fidir = finfo->fi_hdir;
6725+ if (fidir) {
0c5527e5
AM
6726+ /* remove me from sb->s_files */
6727+ file_sb_list_del(file);
6728+
4a4d8108
AM
6729+ vdir_cache = fidir->fd_vdir_cache; /* lock-free */
6730+ if (vdir_cache)
6731+ au_vdir_free(vdir_cache);
6732+
6733+ bindex = finfo->fi_btop;
6734+ if (bindex >= 0) {
6735+ /*
6736+ * calls fput() instead of filp_close(),
6737+ * since no dnotify or lock for the lower file.
6738+ */
6739+ bend = fidir->fd_bbot;
6740+ for (; bindex <= bend; bindex++)
6741+ au_set_h_fptr(file, bindex, NULL);
6742+ }
6743+ kfree(fidir);
6744+ finfo->fi_hdir = NULL;
1facf9fc 6745+ }
1facf9fc 6746+ au_finfo_fin(file);
1facf9fc 6747+ return 0;
6748+}
6749+
6750+/* ---------------------------------------------------------------------- */
6751+
4a4d8108
AM
6752+static int au_do_flush_dir(struct file *file, fl_owner_t id)
6753+{
6754+ int err;
6755+ aufs_bindex_t bindex, bend;
6756+ struct file *h_file;
6757+
6758+ err = 0;
6759+ bend = au_fbend_dir(file);
6760+ for (bindex = au_fbstart(file); !err && bindex <= bend; bindex++) {
6761+ h_file = au_hf_dir(file, bindex);
6762+ if (h_file)
6763+ err = vfsub_flush(h_file, id);
6764+ }
6765+ return err;
6766+}
6767+
6768+static int aufs_flush_dir(struct file *file, fl_owner_t id)
6769+{
6770+ return au_do_flush(file, id, au_do_flush_dir);
6771+}
6772+
6773+/* ---------------------------------------------------------------------- */
6774+
1facf9fc 6775+static int au_do_fsync_dir_no_file(struct dentry *dentry, int datasync)
6776+{
6777+ int err;
6778+ aufs_bindex_t bend, bindex;
6779+ struct inode *inode;
6780+ struct super_block *sb;
6781+
6782+ err = 0;
6783+ sb = dentry->d_sb;
6784+ inode = dentry->d_inode;
6785+ IMustLock(inode);
6786+ bend = au_dbend(dentry);
6787+ for (bindex = au_dbstart(dentry); !err && bindex <= bend; bindex++) {
6788+ struct path h_path;
6789+ struct inode *h_inode;
6790+
6791+ if (au_test_ro(sb, bindex, inode))
6792+ continue;
6793+ h_path.dentry = au_h_dptr(dentry, bindex);
6794+ if (!h_path.dentry)
6795+ continue;
6796+ h_inode = h_path.dentry->d_inode;
6797+ if (!h_inode)
6798+ continue;
6799+
6800+ /* no mnt_want_write() */
6801+ /* cf. fs/nsfd/vfs.c and fs/nfsd/nfs4recover.c */
6802+ /* todo: inotiry fired? */
6803+ h_path.mnt = au_sbr_mnt(sb, bindex);
6804+ mutex_lock(&h_inode->i_mutex);
6805+ err = filemap_fdatawrite(h_inode->i_mapping);
6806+ AuDebugOn(!h_inode->i_fop);
6807+ if (!err && h_inode->i_fop->fsync)
b752ccd1 6808+ err = h_inode->i_fop->fsync(NULL, datasync);
1facf9fc 6809+ if (!err)
6810+ err = filemap_fdatawrite(h_inode->i_mapping);
6811+ if (!err)
6812+ vfsub_update_h_iattr(&h_path, /*did*/NULL); /*ignore*/
6813+ mutex_unlock(&h_inode->i_mutex);
6814+ }
6815+
6816+ return err;
6817+}
6818+
6819+static int au_do_fsync_dir(struct file *file, int datasync)
6820+{
6821+ int err;
6822+ aufs_bindex_t bend, bindex;
6823+ struct file *h_file;
6824+ struct super_block *sb;
6825+ struct inode *inode;
6826+ struct mutex *h_mtx;
6827+
6828+ err = au_reval_and_lock_fdi(file, reopen_dir, /*wlock*/1);
6829+ if (unlikely(err))
6830+ goto out;
6831+
6832+ sb = file->f_dentry->d_sb;
6833+ inode = file->f_dentry->d_inode;
4a4d8108 6834+ bend = au_fbend_dir(file);
1facf9fc 6835+ for (bindex = au_fbstart(file); !err && bindex <= bend; bindex++) {
4a4d8108 6836+ h_file = au_hf_dir(file, bindex);
1facf9fc 6837+ if (!h_file || au_test_ro(sb, bindex, inode))
6838+ continue;
6839+
b752ccd1 6840+ err = vfs_fsync(h_file, datasync);
1facf9fc 6841+ if (!err) {
6842+ h_mtx = &h_file->f_dentry->d_inode->i_mutex;
6843+ mutex_lock(h_mtx);
6844+ vfsub_update_h_iattr(&h_file->f_path, /*did*/NULL);
6845+ /*ignore*/
6846+ mutex_unlock(h_mtx);
6847+ }
6848+ }
6849+
4f0767ce 6850+out:
1facf9fc 6851+ return err;
6852+}
6853+
6854+/*
6855+ * @file may be NULL
6856+ */
b752ccd1 6857+static int aufs_fsync_dir(struct file *file, int datasync)
1facf9fc 6858+{
6859+ int err;
b752ccd1 6860+ struct dentry *dentry;
1facf9fc 6861+ struct super_block *sb;
6862+
b752ccd1 6863+ dentry = file->f_dentry;
1facf9fc 6864+ IMustLock(dentry->d_inode);
6865+
6866+ err = 0;
6867+ sb = dentry->d_sb;
6868+ si_noflush_read_lock(sb);
6869+ if (file)
6870+ err = au_do_fsync_dir(file, datasync);
6871+ else {
6872+ di_write_lock_child(dentry);
6873+ err = au_do_fsync_dir_no_file(dentry, datasync);
6874+ }
6875+ au_cpup_attr_timesizes(dentry->d_inode);
6876+ di_write_unlock(dentry);
6877+ if (file)
6878+ fi_write_unlock(file);
6879+
6880+ si_read_unlock(sb);
6881+ return err;
6882+}
6883+
6884+/* ---------------------------------------------------------------------- */
6885+
6886+static int aufs_readdir(struct file *file, void *dirent, filldir_t filldir)
6887+{
6888+ int err;
6889+ struct dentry *dentry;
6890+ struct inode *inode;
6891+ struct super_block *sb;
6892+
6893+ dentry = file->f_dentry;
6894+ inode = dentry->d_inode;
6895+ IMustLock(inode);
6896+
6897+ sb = dentry->d_sb;
6898+ si_read_lock(sb, AuLock_FLUSH);
6899+ err = au_reval_and_lock_fdi(file, reopen_dir, /*wlock*/1);
6900+ if (unlikely(err))
6901+ goto out;
027c5e7a
AM
6902+ err = au_alive_dir(dentry);
6903+ if (!err)
6904+ err = au_vdir_init(file);
1facf9fc 6905+ di_downgrade_lock(dentry, AuLock_IR);
6906+ if (unlikely(err))
6907+ goto out_unlock;
6908+
b752ccd1 6909+ if (!au_test_nfsd()) {
1facf9fc 6910+ err = au_vdir_fill_de(file, dirent, filldir);
6911+ fsstack_copy_attr_atime(inode,
6912+ au_h_iptr(inode, au_ibstart(inode)));
6913+ } else {
6914+ /*
6915+ * nfsd filldir may call lookup_one_len(), vfs_getattr(),
6916+ * encode_fh() and others.
6917+ */
6918+ struct inode *h_inode = au_h_iptr(inode, au_ibstart(inode));
6919+
6920+ di_read_unlock(dentry, AuLock_IR);
6921+ si_read_unlock(sb);
1facf9fc 6922+ err = au_vdir_fill_de(file, dirent, filldir);
1facf9fc 6923+ fsstack_copy_attr_atime(inode, h_inode);
6924+ fi_write_unlock(file);
6925+
6926+ AuTraceErr(err);
6927+ return err;
6928+ }
6929+
4f0767ce 6930+out_unlock:
1facf9fc 6931+ di_read_unlock(dentry, AuLock_IR);
6932+ fi_write_unlock(file);
4f0767ce 6933+out:
1facf9fc 6934+ si_read_unlock(sb);
6935+ return err;
6936+}
6937+
6938+/* ---------------------------------------------------------------------- */
6939+
6940+#define AuTestEmpty_WHONLY 1
dece6358
AM
6941+#define AuTestEmpty_CALLED (1 << 1)
6942+#define AuTestEmpty_SHWH (1 << 2)
1facf9fc 6943+#define au_ftest_testempty(flags, name) ((flags) & AuTestEmpty_##name)
7f207e10
AM
6944+#define au_fset_testempty(flags, name) \
6945+ do { (flags) |= AuTestEmpty_##name; } while (0)
6946+#define au_fclr_testempty(flags, name) \
6947+ do { (flags) &= ~AuTestEmpty_##name; } while (0)
1facf9fc 6948+
dece6358
AM
6949+#ifndef CONFIG_AUFS_SHWH
6950+#undef AuTestEmpty_SHWH
6951+#define AuTestEmpty_SHWH 0
6952+#endif
6953+
1facf9fc 6954+struct test_empty_arg {
1308ab2a 6955+ struct au_nhash *whlist;
1facf9fc 6956+ unsigned int flags;
6957+ int err;
6958+ aufs_bindex_t bindex;
6959+};
6960+
6961+static int test_empty_cb(void *__arg, const char *__name, int namelen,
dece6358
AM
6962+ loff_t offset __maybe_unused, u64 ino,
6963+ unsigned int d_type)
1facf9fc 6964+{
6965+ struct test_empty_arg *arg = __arg;
6966+ char *name = (void *)__name;
6967+
6968+ arg->err = 0;
6969+ au_fset_testempty(arg->flags, CALLED);
6970+ /* smp_mb(); */
6971+ if (name[0] == '.'
6972+ && (namelen == 1 || (name[1] == '.' && namelen == 2)))
6973+ goto out; /* success */
6974+
6975+ if (namelen <= AUFS_WH_PFX_LEN
6976+ || memcmp(name, AUFS_WH_PFX, AUFS_WH_PFX_LEN)) {
6977+ if (au_ftest_testempty(arg->flags, WHONLY)
1308ab2a 6978+ && !au_nhash_test_known_wh(arg->whlist, name, namelen))
1facf9fc 6979+ arg->err = -ENOTEMPTY;
6980+ goto out;
6981+ }
6982+
6983+ name += AUFS_WH_PFX_LEN;
6984+ namelen -= AUFS_WH_PFX_LEN;
1308ab2a 6985+ if (!au_nhash_test_known_wh(arg->whlist, name, namelen))
1facf9fc 6986+ arg->err = au_nhash_append_wh
1308ab2a 6987+ (arg->whlist, name, namelen, ino, d_type, arg->bindex,
dece6358 6988+ au_ftest_testempty(arg->flags, SHWH));
1facf9fc 6989+
4f0767ce 6990+out:
1facf9fc 6991+ /* smp_mb(); */
6992+ AuTraceErr(arg->err);
6993+ return arg->err;
6994+}
6995+
6996+static int do_test_empty(struct dentry *dentry, struct test_empty_arg *arg)
6997+{
6998+ int err;
6999+ struct file *h_file;
7000+
7001+ h_file = au_h_open(dentry, arg->bindex,
7002+ O_RDONLY | O_NONBLOCK | O_DIRECTORY | O_LARGEFILE,
7003+ /*file*/NULL);
7004+ err = PTR_ERR(h_file);
7005+ if (IS_ERR(h_file))
7006+ goto out;
7007+
7008+ err = 0;
7009+ if (!au_opt_test(au_mntflags(dentry->d_sb), UDBA_NONE)
7010+ && !h_file->f_dentry->d_inode->i_nlink)
7011+ goto out_put;
7012+
7013+ do {
7014+ arg->err = 0;
7015+ au_fclr_testempty(arg->flags, CALLED);
7016+ /* smp_mb(); */
7017+ err = vfsub_readdir(h_file, test_empty_cb, arg);
7018+ if (err >= 0)
7019+ err = arg->err;
7020+ } while (!err && au_ftest_testempty(arg->flags, CALLED));
7021+
4f0767ce 7022+out_put:
1facf9fc 7023+ fput(h_file);
7024+ au_sbr_put(dentry->d_sb, arg->bindex);
4f0767ce 7025+out:
1facf9fc 7026+ return err;
7027+}
7028+
7029+struct do_test_empty_args {
7030+ int *errp;
7031+ struct dentry *dentry;
7032+ struct test_empty_arg *arg;
7033+};
7034+
7035+static void call_do_test_empty(void *args)
7036+{
7037+ struct do_test_empty_args *a = args;
7038+ *a->errp = do_test_empty(a->dentry, a->arg);
7039+}
7040+
7041+static int sio_test_empty(struct dentry *dentry, struct test_empty_arg *arg)
7042+{
7043+ int err, wkq_err;
7044+ struct dentry *h_dentry;
7045+ struct inode *h_inode;
7046+
7047+ h_dentry = au_h_dptr(dentry, arg->bindex);
7048+ h_inode = h_dentry->d_inode;
7049+ mutex_lock_nested(&h_inode->i_mutex, AuLsc_I_CHILD);
7050+ err = au_test_h_perm_sio(h_inode, MAY_EXEC | MAY_READ);
7051+ mutex_unlock(&h_inode->i_mutex);
7052+ if (!err)
7053+ err = do_test_empty(dentry, arg);
7054+ else {
7055+ struct do_test_empty_args args = {
7056+ .errp = &err,
7057+ .dentry = dentry,
7058+ .arg = arg
7059+ };
7060+ unsigned int flags = arg->flags;
7061+
7062+ wkq_err = au_wkq_wait(call_do_test_empty, &args);
7063+ if (unlikely(wkq_err))
7064+ err = wkq_err;
7065+ arg->flags = flags;
7066+ }
7067+
7068+ return err;
7069+}
7070+
7071+int au_test_empty_lower(struct dentry *dentry)
7072+{
7073+ int err;
1308ab2a 7074+ unsigned int rdhash;
1facf9fc 7075+ aufs_bindex_t bindex, bstart, btail;
1308ab2a 7076+ struct au_nhash whlist;
1facf9fc 7077+ struct test_empty_arg arg;
1facf9fc 7078+
dece6358
AM
7079+ SiMustAnyLock(dentry->d_sb);
7080+
1308ab2a 7081+ rdhash = au_sbi(dentry->d_sb)->si_rdhash;
7082+ if (!rdhash)
7083+ rdhash = au_rdhash_est(au_dir_size(/*file*/NULL, dentry));
7084+ err = au_nhash_alloc(&whlist, rdhash, GFP_NOFS);
dece6358 7085+ if (unlikely(err))
1facf9fc 7086+ goto out;
7087+
1facf9fc 7088+ arg.flags = 0;
1308ab2a 7089+ arg.whlist = &whlist;
7090+ bstart = au_dbstart(dentry);
dece6358
AM
7091+ if (au_opt_test(au_mntflags(dentry->d_sb), SHWH))
7092+ au_fset_testempty(arg.flags, SHWH);
1facf9fc 7093+ arg.bindex = bstart;
7094+ err = do_test_empty(dentry, &arg);
7095+ if (unlikely(err))
7096+ goto out_whlist;
7097+
7098+ au_fset_testempty(arg.flags, WHONLY);
7099+ btail = au_dbtaildir(dentry);
7100+ for (bindex = bstart + 1; !err && bindex <= btail; bindex++) {
7101+ struct dentry *h_dentry;
7102+
7103+ h_dentry = au_h_dptr(dentry, bindex);
7104+ if (h_dentry && h_dentry->d_inode) {
7105+ arg.bindex = bindex;
7106+ err = do_test_empty(dentry, &arg);
7107+ }
7108+ }
7109+
4f0767ce 7110+out_whlist:
1308ab2a 7111+ au_nhash_wh_free(&whlist);
4f0767ce 7112+out:
1facf9fc 7113+ return err;
7114+}
7115+
7116+int au_test_empty(struct dentry *dentry, struct au_nhash *whlist)
7117+{
7118+ int err;
7119+ struct test_empty_arg arg;
7120+ aufs_bindex_t bindex, btail;
7121+
7122+ err = 0;
1308ab2a 7123+ arg.whlist = whlist;
1facf9fc 7124+ arg.flags = AuTestEmpty_WHONLY;
dece6358
AM
7125+ if (au_opt_test(au_mntflags(dentry->d_sb), SHWH))
7126+ au_fset_testempty(arg.flags, SHWH);
1facf9fc 7127+ btail = au_dbtaildir(dentry);
7128+ for (bindex = au_dbstart(dentry); !err && bindex <= btail; bindex++) {
7129+ struct dentry *h_dentry;
7130+
7131+ h_dentry = au_h_dptr(dentry, bindex);
7132+ if (h_dentry && h_dentry->d_inode) {
7133+ arg.bindex = bindex;
7134+ err = sio_test_empty(dentry, &arg);
7135+ }
7136+ }
7137+
7138+ return err;
7139+}
7140+
7141+/* ---------------------------------------------------------------------- */
7142+
7143+const struct file_operations aufs_dir_fop = {
4a4d8108 7144+ .owner = THIS_MODULE,
027c5e7a 7145+ .llseek = default_llseek,
1facf9fc 7146+ .read = generic_read_dir,
7147+ .readdir = aufs_readdir,
7148+ .unlocked_ioctl = aufs_ioctl_dir,
b752ccd1
AM
7149+#ifdef CONFIG_COMPAT
7150+ .compat_ioctl = aufs_compat_ioctl_dir,
7151+#endif
1facf9fc 7152+ .open = aufs_open_dir,
7153+ .release = aufs_release_dir,
4a4d8108 7154+ .flush = aufs_flush_dir,
1facf9fc 7155+ .fsync = aufs_fsync_dir
7156+};
7f207e10
AM
7157diff -urN /usr/share/empty/fs/aufs/dir.h linux/fs/aufs/dir.h
7158--- /usr/share/empty/fs/aufs/dir.h 1970-01-01 01:00:00.000000000 +0100
87a755f4 7159+++ linux/fs/aufs/dir.h 2011-03-17 10:46:59.000000000 +0100
b752ccd1 7160@@ -0,0 +1,138 @@
1facf9fc 7161+/*
027c5e7a 7162+ * Copyright (C) 2005-2011 Junjiro R. Okajima
1facf9fc 7163+ *
7164+ * This program, aufs is free software; you can redistribute it and/or modify
7165+ * it under the terms of the GNU General Public License as published by
7166+ * the Free Software Foundation; either version 2 of the License, or
7167+ * (at your option) any later version.
dece6358
AM
7168+ *
7169+ * This program is distributed in the hope that it will be useful,
7170+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
7171+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
7172+ * GNU General Public License for more details.
7173+ *
7174+ * You should have received a copy of the GNU General Public License
7175+ * along with this program; if not, write to the Free Software
7176+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 7177+ */
7178+
7179+/*
7180+ * directory operations
7181+ */
7182+
7183+#ifndef __AUFS_DIR_H__
7184+#define __AUFS_DIR_H__
7185+
7186+#ifdef __KERNEL__
7187+
7188+#include <linux/fs.h>
7189+#include <linux/aufs_type.h>
7190+
7191+/* ---------------------------------------------------------------------- */
7192+
7193+/* need to be faster and smaller */
7194+
7195+struct au_nhash {
dece6358
AM
7196+ unsigned int nh_num;
7197+ struct hlist_head *nh_head;
1facf9fc 7198+};
7199+
7200+struct au_vdir_destr {
7201+ unsigned char len;
7202+ unsigned char name[0];
7203+} __packed;
7204+
7205+struct au_vdir_dehstr {
7206+ struct hlist_node hash;
7207+ struct au_vdir_destr *str;
4a4d8108 7208+} ____cacheline_aligned_in_smp;
1facf9fc 7209+
7210+struct au_vdir_de {
7211+ ino_t de_ino;
7212+ unsigned char de_type;
7213+ /* caution: packed */
7214+ struct au_vdir_destr de_str;
7215+} __packed;
7216+
7217+struct au_vdir_wh {
7218+ struct hlist_node wh_hash;
dece6358
AM
7219+#ifdef CONFIG_AUFS_SHWH
7220+ ino_t wh_ino;
1facf9fc 7221+ aufs_bindex_t wh_bindex;
dece6358
AM
7222+ unsigned char wh_type;
7223+#else
7224+ aufs_bindex_t wh_bindex;
7225+#endif
7226+ /* caution: packed */
1facf9fc 7227+ struct au_vdir_destr wh_str;
7228+} __packed;
7229+
7230+union au_vdir_deblk_p {
7231+ unsigned char *deblk;
7232+ struct au_vdir_de *de;
7233+};
7234+
7235+struct au_vdir {
7236+ unsigned char **vd_deblk;
7237+ unsigned long vd_nblk;
1facf9fc 7238+ struct {
7239+ unsigned long ul;
7240+ union au_vdir_deblk_p p;
7241+ } vd_last;
7242+
7243+ unsigned long vd_version;
dece6358 7244+ unsigned int vd_deblk_sz;
1facf9fc 7245+ unsigned long vd_jiffy;
4a4d8108 7246+} ____cacheline_aligned_in_smp;
1facf9fc 7247+
7248+/* ---------------------------------------------------------------------- */
7249+
7250+/* dir.c */
7251+extern const struct file_operations aufs_dir_fop;
7252+void au_add_nlink(struct inode *dir, struct inode *h_dir);
7253+void au_sub_nlink(struct inode *dir, struct inode *h_dir);
1308ab2a 7254+loff_t au_dir_size(struct file *file, struct dentry *dentry);
1facf9fc 7255+int au_test_empty_lower(struct dentry *dentry);
7256+int au_test_empty(struct dentry *dentry, struct au_nhash *whlist);
7257+
7258+/* vdir.c */
1308ab2a 7259+unsigned int au_rdhash_est(loff_t sz);
dece6358
AM
7260+int au_nhash_alloc(struct au_nhash *nhash, unsigned int num_hash, gfp_t gfp);
7261+void au_nhash_wh_free(struct au_nhash *whlist);
1facf9fc 7262+int au_nhash_test_longer_wh(struct au_nhash *whlist, aufs_bindex_t btgt,
7263+ int limit);
dece6358
AM
7264+int au_nhash_test_known_wh(struct au_nhash *whlist, char *name, int nlen);
7265+int au_nhash_append_wh(struct au_nhash *whlist, char *name, int nlen, ino_t ino,
7266+ unsigned int d_type, aufs_bindex_t bindex,
7267+ unsigned char shwh);
1facf9fc 7268+void au_vdir_free(struct au_vdir *vdir);
7269+int au_vdir_init(struct file *file);
7270+int au_vdir_fill_de(struct file *file, void *dirent, filldir_t filldir);
7271+
7272+/* ioctl.c */
7273+long aufs_ioctl_dir(struct file *file, unsigned int cmd, unsigned long arg);
7274+
1308ab2a 7275+#ifdef CONFIG_AUFS_RDU
7276+/* rdu.c */
7277+long au_rdu_ioctl(struct file *file, unsigned int cmd, unsigned long arg);
b752ccd1
AM
7278+#ifdef CONFIG_COMPAT
7279+long au_rdu_compat_ioctl(struct file *file, unsigned int cmd,
7280+ unsigned long arg);
7281+#endif
1308ab2a 7282+#else
7283+static inline long au_rdu_ioctl(struct file *file, unsigned int cmd,
7284+ unsigned long arg)
7285+{
7286+ return -EINVAL;
7287+}
b752ccd1
AM
7288+#ifdef CONFIG_COMPAT
7289+static inline long au_rdu_compat_ioctl(struct file *file, unsigned int cmd,
7290+ unsigned long arg)
7291+{
7292+ return -EINVAL;
7293+}
7294+#endif
1308ab2a 7295+#endif
7296+
1facf9fc 7297+#endif /* __KERNEL__ */
7298+#endif /* __AUFS_DIR_H__ */
7f207e10
AM
7299diff -urN /usr/share/empty/fs/aufs/dynop.c linux/fs/aufs/dynop.c
7300--- /usr/share/empty/fs/aufs/dynop.c 1970-01-01 01:00:00.000000000 +0100
87a755f4 7301+++ linux/fs/aufs/dynop.c 2011-07-22 08:26:47.854303107 +0200
2cbb1c4b 7302@@ -0,0 +1,377 @@
1facf9fc 7303+/*
027c5e7a 7304+ * Copyright (C) 2010-2011 Junjiro R. Okajima
1facf9fc 7305+ *
7306+ * This program, aufs is free software; you can redistribute it and/or modify
7307+ * it under the terms of the GNU General Public License as published by
7308+ * the Free Software Foundation; either version 2 of the License, or
7309+ * (at your option) any later version.
dece6358
AM
7310+ *
7311+ * This program is distributed in the hope that it will be useful,
7312+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
7313+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
7314+ * GNU General Public License for more details.
7315+ *
7316+ * You should have received a copy of the GNU General Public License
7317+ * along with this program; if not, write to the Free Software
7318+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 7319+ */
7320+
7321+/*
4a4d8108 7322+ * dynamically customizable operations for regular files
1facf9fc 7323+ */
7324+
1facf9fc 7325+#include "aufs.h"
7326+
4a4d8108 7327+#define DyPrSym(key) AuDbgSym(key->dk_op.dy_hop)
1facf9fc 7328+
4a4d8108
AM
7329+/*
7330+ * How large will these lists be?
7331+ * Usually just a few elements, 20-30 at most for each, I guess.
7332+ */
7333+static struct au_splhead dynop[AuDyLast];
7334+
7335+static struct au_dykey *dy_gfind_get(struct au_splhead *spl, const void *h_op)
1facf9fc 7336+{
4a4d8108
AM
7337+ struct au_dykey *key, *tmp;
7338+ struct list_head *head;
1facf9fc 7339+
4a4d8108
AM
7340+ key = NULL;
7341+ head = &spl->head;
7342+ rcu_read_lock();
7343+ list_for_each_entry_rcu(tmp, head, dk_list)
7344+ if (tmp->dk_op.dy_hop == h_op) {
7345+ key = tmp;
7346+ kref_get(&key->dk_kref);
7347+ break;
7348+ }
7349+ rcu_read_unlock();
7350+
7351+ return key;
1facf9fc 7352+}
7353+
4a4d8108 7354+static struct au_dykey *dy_bradd(struct au_branch *br, struct au_dykey *key)
1facf9fc 7355+{
4a4d8108
AM
7356+ struct au_dykey **k, *found;
7357+ const void *h_op = key->dk_op.dy_hop;
7358+ int i;
1facf9fc 7359+
4a4d8108
AM
7360+ found = NULL;
7361+ k = br->br_dykey;
7362+ for (i = 0; i < AuBrDynOp; i++)
7363+ if (k[i]) {
7364+ if (k[i]->dk_op.dy_hop == h_op) {
7365+ found = k[i];
7366+ break;
7367+ }
7368+ } else
7369+ break;
7370+ if (!found) {
7371+ spin_lock(&br->br_dykey_lock);
7372+ for (; i < AuBrDynOp; i++)
7373+ if (k[i]) {
7374+ if (k[i]->dk_op.dy_hop == h_op) {
7375+ found = k[i];
7376+ break;
7377+ }
7378+ } else {
7379+ k[i] = key;
7380+ break;
7381+ }
7382+ spin_unlock(&br->br_dykey_lock);
7383+ BUG_ON(i == AuBrDynOp); /* expand the array */
7384+ }
7385+
7386+ return found;
1facf9fc 7387+}
7388+
4a4d8108
AM
7389+/* kref_get() if @key is already added */
7390+static struct au_dykey *dy_gadd(struct au_splhead *spl, struct au_dykey *key)
7391+{
7392+ struct au_dykey *tmp, *found;
7393+ struct list_head *head;
7394+ const void *h_op = key->dk_op.dy_hop;
1facf9fc 7395+
4a4d8108
AM
7396+ found = NULL;
7397+ head = &spl->head;
7398+ spin_lock(&spl->spin);
7399+ list_for_each_entry(tmp, head, dk_list)
7400+ if (tmp->dk_op.dy_hop == h_op) {
7401+ kref_get(&tmp->dk_kref);
7402+ found = tmp;
7403+ break;
7404+ }
7405+ if (!found)
7406+ list_add_rcu(&key->dk_list, head);
7407+ spin_unlock(&spl->spin);
1facf9fc 7408+
4a4d8108
AM
7409+ if (!found)
7410+ DyPrSym(key);
7411+ return found;
7412+}
7413+
7414+static void dy_free_rcu(struct rcu_head *rcu)
1facf9fc 7415+{
4a4d8108
AM
7416+ struct au_dykey *key;
7417+
7418+ key = container_of(rcu, struct au_dykey, dk_rcu);
7419+ DyPrSym(key);
7420+ kfree(key);
1facf9fc 7421+}
7422+
4a4d8108
AM
7423+static void dy_free(struct kref *kref)
7424+{
7425+ struct au_dykey *key;
7426+ struct au_splhead *spl;
1facf9fc 7427+
4a4d8108
AM
7428+ key = container_of(kref, struct au_dykey, dk_kref);
7429+ spl = dynop + key->dk_op.dy_type;
7430+ au_spl_del_rcu(&key->dk_list, spl);
7431+ call_rcu(&key->dk_rcu, dy_free_rcu);
7432+}
7433+
7434+void au_dy_put(struct au_dykey *key)
1facf9fc 7435+{
4a4d8108
AM
7436+ kref_put(&key->dk_kref, dy_free);
7437+}
1facf9fc 7438+
4a4d8108
AM
7439+/* ---------------------------------------------------------------------- */
7440+
7441+#define DyDbgSize(cnt, op) AuDebugOn(cnt != sizeof(op)/sizeof(void *))
7442+
7443+#ifdef CONFIG_AUFS_DEBUG
7444+#define DyDbgDeclare(cnt) unsigned int cnt = 0
4f0767ce 7445+#define DyDbgInc(cnt) do { cnt++; } while (0)
4a4d8108
AM
7446+#else
7447+#define DyDbgDeclare(cnt) do {} while (0)
7448+#define DyDbgInc(cnt) do {} while (0)
7449+#endif
7450+
7451+#define DySet(func, dst, src, h_op, h_sb) do { \
7452+ DyDbgInc(cnt); \
7453+ if (h_op->func) { \
7454+ if (src.func) \
7455+ dst.func = src.func; \
7456+ else \
7457+ AuDbg("%s %s\n", au_sbtype(h_sb), #func); \
7458+ } \
7459+} while (0)
7460+
7461+#define DySetForce(func, dst, src) do { \
7462+ AuDebugOn(!src.func); \
7463+ DyDbgInc(cnt); \
7464+ dst.func = src.func; \
7465+} while (0)
7466+
7467+#define DySetAop(func) \
7468+ DySet(func, dyaop->da_op, aufs_aop, h_aop, h_sb)
7469+#define DySetAopForce(func) \
7470+ DySetForce(func, dyaop->da_op, aufs_aop)
7471+
7472+static void dy_aop(struct au_dykey *key, const void *h_op,
7473+ struct super_block *h_sb __maybe_unused)
7474+{
7475+ struct au_dyaop *dyaop = (void *)key;
7476+ const struct address_space_operations *h_aop = h_op;
7477+ DyDbgDeclare(cnt);
7478+
7479+ AuDbg("%s\n", au_sbtype(h_sb));
7480+
7481+ DySetAop(writepage);
7482+ DySetAopForce(readpage); /* force */
4a4d8108
AM
7483+ DySetAop(writepages);
7484+ DySetAop(set_page_dirty);
7485+ DySetAop(readpages);
7486+ DySetAop(write_begin);
7487+ DySetAop(write_end);
7488+ DySetAop(bmap);
7489+ DySetAop(invalidatepage);
7490+ DySetAop(releasepage);
027c5e7a 7491+ DySetAop(freepage);
4a4d8108
AM
7492+ /* these two will be changed according to an aufs mount option */
7493+ DySetAop(direct_IO);
7494+ DySetAop(get_xip_mem);
7495+ DySetAop(migratepage);
7496+ DySetAop(launder_page);
7497+ DySetAop(is_partially_uptodate);
7498+ DySetAop(error_remove_page);
7499+
7500+ DyDbgSize(cnt, *h_aop);
7501+ dyaop->da_get_xip_mem = h_aop->get_xip_mem;
7502+}
7503+
4a4d8108
AM
7504+/* ---------------------------------------------------------------------- */
7505+
7506+static void dy_bug(struct kref *kref)
7507+{
7508+ BUG();
7509+}
7510+
7511+static struct au_dykey *dy_get(struct au_dynop *op, struct au_branch *br)
7512+{
7513+ struct au_dykey *key, *old;
7514+ struct au_splhead *spl;
b752ccd1 7515+ struct op {
4a4d8108 7516+ unsigned int sz;
b752ccd1
AM
7517+ void (*set)(struct au_dykey *key, const void *h_op,
7518+ struct super_block *h_sb __maybe_unused);
7519+ };
7520+ static const struct op a[] = {
4a4d8108
AM
7521+ [AuDy_AOP] = {
7522+ .sz = sizeof(struct au_dyaop),
b752ccd1 7523+ .set = dy_aop
4a4d8108 7524+ }
b752ccd1
AM
7525+ };
7526+ const struct op *p;
4a4d8108
AM
7527+
7528+ spl = dynop + op->dy_type;
7529+ key = dy_gfind_get(spl, op->dy_hop);
7530+ if (key)
7531+ goto out_add; /* success */
7532+
7533+ p = a + op->dy_type;
7534+ key = kzalloc(p->sz, GFP_NOFS);
7535+ if (unlikely(!key)) {
7536+ key = ERR_PTR(-ENOMEM);
7537+ goto out;
7538+ }
7539+
7540+ key->dk_op.dy_hop = op->dy_hop;
7541+ kref_init(&key->dk_kref);
b752ccd1 7542+ p->set(key, op->dy_hop, br->br_mnt->mnt_sb);
4a4d8108
AM
7543+ old = dy_gadd(spl, key);
7544+ if (old) {
7545+ kfree(key);
7546+ key = old;
7547+ }
7548+
7549+out_add:
7550+ old = dy_bradd(br, key);
7551+ if (old)
7552+ /* its ref-count should never be zero here */
7553+ kref_put(&key->dk_kref, dy_bug);
7554+out:
7555+ return key;
7556+}
7557+
7558+/* ---------------------------------------------------------------------- */
7559+/*
7560+ * Aufs prohibits O_DIRECT by defaut even if the branch supports it.
7561+ * This behaviour is neccessary to return an error from open(O_DIRECT) instead
7562+ * of the succeeding I/O. The dio mount option enables O_DIRECT and makes
7563+ * open(O_DIRECT) always succeed, but the succeeding I/O may return an error.
7564+ * See the aufs manual in detail.
7565+ *
7566+ * To keep this behaviour, aufs has to set NULL to ->get_xip_mem too, and the
7567+ * performance of fadvise() and madvise() may be affected.
7568+ */
7569+static void dy_adx(struct au_dyaop *dyaop, int do_dx)
7570+{
7571+ if (!do_dx) {
7572+ dyaop->da_op.direct_IO = NULL;
7573+ dyaop->da_op.get_xip_mem = NULL;
7574+ } else {
7575+ dyaop->da_op.direct_IO = aufs_aop.direct_IO;
7576+ dyaop->da_op.get_xip_mem = aufs_aop.get_xip_mem;
7577+ if (!dyaop->da_get_xip_mem)
7578+ dyaop->da_op.get_xip_mem = NULL;
7579+ }
7580+}
7581+
7582+static struct au_dyaop *dy_aget(struct au_branch *br,
7583+ const struct address_space_operations *h_aop,
7584+ int do_dx)
7585+{
7586+ struct au_dyaop *dyaop;
7587+ struct au_dynop op;
7588+
7589+ op.dy_type = AuDy_AOP;
7590+ op.dy_haop = h_aop;
7591+ dyaop = (void *)dy_get(&op, br);
7592+ if (IS_ERR(dyaop))
7593+ goto out;
7594+ dy_adx(dyaop, do_dx);
7595+
7596+out:
7597+ return dyaop;
7598+}
7599+
7600+int au_dy_iaop(struct inode *inode, aufs_bindex_t bindex,
7601+ struct inode *h_inode)
7602+{
7603+ int err, do_dx;
7604+ struct super_block *sb;
7605+ struct au_branch *br;
7606+ struct au_dyaop *dyaop;
7607+
7608+ AuDebugOn(!S_ISREG(h_inode->i_mode));
7609+ IiMustWriteLock(inode);
7610+
7611+ sb = inode->i_sb;
7612+ br = au_sbr(sb, bindex);
7613+ do_dx = !!au_opt_test(au_mntflags(sb), DIO);
7614+ dyaop = dy_aget(br, h_inode->i_mapping->a_ops, do_dx);
7615+ err = PTR_ERR(dyaop);
7616+ if (IS_ERR(dyaop))
7617+ /* unnecessary to call dy_fput() */
7618+ goto out;
7619+
7620+ err = 0;
7621+ inode->i_mapping->a_ops = &dyaop->da_op;
7622+
7623+out:
7624+ return err;
7625+}
7626+
b752ccd1
AM
7627+/*
7628+ * Is it safe to replace a_ops during the inode/file is in operation?
7629+ * Yes, I hope so.
7630+ */
7631+int au_dy_irefresh(struct inode *inode)
7632+{
7633+ int err;
7634+ aufs_bindex_t bstart;
7635+ struct inode *h_inode;
7636+
7637+ err = 0;
7638+ if (S_ISREG(inode->i_mode)) {
7639+ bstart = au_ibstart(inode);
7640+ h_inode = au_h_iptr(inode, bstart);
7641+ err = au_dy_iaop(inode, bstart, h_inode);
7642+ }
7643+ return err;
7644+}
7645+
4a4d8108
AM
7646+void au_dy_arefresh(int do_dx)
7647+{
7648+ struct au_splhead *spl;
7649+ struct list_head *head;
7650+ struct au_dykey *key;
7651+
7652+ spl = dynop + AuDy_AOP;
7653+ head = &spl->head;
7654+ spin_lock(&spl->spin);
7655+ list_for_each_entry(key, head, dk_list)
7656+ dy_adx((void *)key, do_dx);
7657+ spin_unlock(&spl->spin);
7658+}
7659+
4a4d8108
AM
7660+/* ---------------------------------------------------------------------- */
7661+
7662+void __init au_dy_init(void)
7663+{
7664+ int i;
7665+
7666+ /* make sure that 'struct au_dykey *' can be any type */
7667+ BUILD_BUG_ON(offsetof(struct au_dyaop, da_key));
4a4d8108
AM
7668+
7669+ for (i = 0; i < AuDyLast; i++)
7670+ au_spl_init(dynop + i);
7671+}
7672+
7673+void au_dy_fin(void)
7674+{
7675+ int i;
7676+
7677+ for (i = 0; i < AuDyLast; i++)
7678+ WARN_ON(!list_empty(&dynop[i].head));
7679+}
7f207e10
AM
7680diff -urN /usr/share/empty/fs/aufs/dynop.h linux/fs/aufs/dynop.h
7681--- /usr/share/empty/fs/aufs/dynop.h 1970-01-01 01:00:00.000000000 +0100
87a755f4 7682+++ linux/fs/aufs/dynop.h 2011-07-22 08:26:47.854303107 +0200
2cbb1c4b 7683@@ -0,0 +1,80 @@
4a4d8108 7684+/*
027c5e7a 7685+ * Copyright (C) 2010-2011 Junjiro R. Okajima
4a4d8108
AM
7686+ *
7687+ * This program, aufs is free software; you can redistribute it and/or modify
7688+ * it under the terms of the GNU General Public License as published by
7689+ * the Free Software Foundation; either version 2 of the License, or
7690+ * (at your option) any later version.
7691+ *
7692+ * This program is distributed in the hope that it will be useful,
7693+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
7694+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
7695+ * GNU General Public License for more details.
7696+ *
7697+ * You should have received a copy of the GNU General Public License
7698+ * along with this program; if not, write to the Free Software
7699+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
7700+ */
7701+
7702+/*
7703+ * dynamically customizable operations (for regular files only)
7704+ */
7705+
7706+#ifndef __AUFS_DYNOP_H__
7707+#define __AUFS_DYNOP_H__
7708+
7709+#ifdef __KERNEL__
7710+
7711+#include <linux/fs.h>
7712+#include <linux/mm.h>
7713+#include <linux/rcupdate.h>
7714+#include <linux/aufs_type.h>
7715+#include "inode.h"
7716+
2cbb1c4b 7717+enum {AuDy_AOP, AuDyLast};
4a4d8108
AM
7718+
7719+struct au_dynop {
7720+ int dy_type;
7721+ union {
7722+ const void *dy_hop;
7723+ const struct address_space_operations *dy_haop;
4a4d8108
AM
7724+ };
7725+};
7726+
7727+struct au_dykey {
7728+ union {
7729+ struct list_head dk_list;
7730+ struct rcu_head dk_rcu;
7731+ };
7732+ struct au_dynop dk_op;
7733+
7734+ /*
7735+ * during I am in the branch local array, kref is gotten. when the
7736+ * branch is removed, kref is put.
7737+ */
7738+ struct kref dk_kref;
7739+};
7740+
7741+/* stop unioning since their sizes are very different from each other */
7742+struct au_dyaop {
7743+ struct au_dykey da_key;
7744+ struct address_space_operations da_op; /* not const */
7745+ int (*da_get_xip_mem)(struct address_space *, pgoff_t, int,
7746+ void **, unsigned long *);
7747+};
7748+
4a4d8108
AM
7749+/* ---------------------------------------------------------------------- */
7750+
7751+/* dynop.c */
7752+struct au_branch;
7753+void au_dy_put(struct au_dykey *key);
7754+int au_dy_iaop(struct inode *inode, aufs_bindex_t bindex,
7755+ struct inode *h_inode);
b752ccd1 7756+int au_dy_irefresh(struct inode *inode);
4a4d8108 7757+void au_dy_arefresh(int do_dio);
4a4d8108
AM
7758+
7759+void __init au_dy_init(void);
7760+void au_dy_fin(void);
7761+
4a4d8108
AM
7762+#endif /* __KERNEL__ */
7763+#endif /* __AUFS_DYNOP_H__ */
7f207e10
AM
7764diff -urN /usr/share/empty/fs/aufs/export.c linux/fs/aufs/export.c
7765--- /usr/share/empty/fs/aufs/export.c 1970-01-01 01:00:00.000000000 +0100
87a755f4 7766+++ linux/fs/aufs/export.c 2011-07-22 08:26:47.854303107 +0200
2cbb1c4b 7767@@ -0,0 +1,805 @@
4a4d8108 7768+/*
027c5e7a 7769+ * Copyright (C) 2005-2011 Junjiro R. Okajima
4a4d8108
AM
7770+ *
7771+ * This program, aufs is free software; you can redistribute it and/or modify
7772+ * it under the terms of the GNU General Public License as published by
7773+ * the Free Software Foundation; either version 2 of the License, or
7774+ * (at your option) any later version.
7775+ *
7776+ * This program is distributed in the hope that it will be useful,
7777+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
7778+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
7779+ * GNU General Public License for more details.
7780+ *
7781+ * You should have received a copy of the GNU General Public License
7782+ * along with this program; if not, write to the Free Software
7783+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
7784+ */
7785+
7786+/*
7787+ * export via nfs
7788+ */
7789+
7790+#include <linux/exportfs.h>
7791+#include <linux/file.h>
7792+#include <linux/mnt_namespace.h>
7793+#include <linux/namei.h>
7794+#include <linux/nsproxy.h>
7795+#include <linux/random.h>
7796+#include <linux/writeback.h>
7797+#include "aufs.h"
7798+
7799+union conv {
7800+#ifdef CONFIG_AUFS_INO_T_64
7801+ __u32 a[2];
7802+#else
7803+ __u32 a[1];
7804+#endif
7805+ ino_t ino;
7806+};
7807+
7808+static ino_t decode_ino(__u32 *a)
7809+{
7810+ union conv u;
7811+
7812+ BUILD_BUG_ON(sizeof(u.ino) != sizeof(u.a));
7813+ u.a[0] = a[0];
7814+#ifdef CONFIG_AUFS_INO_T_64
7815+ u.a[1] = a[1];
7816+#endif
7817+ return u.ino;
7818+}
7819+
7820+static void encode_ino(__u32 *a, ino_t ino)
7821+{
7822+ union conv u;
7823+
7824+ u.ino = ino;
7825+ a[0] = u.a[0];
7826+#ifdef CONFIG_AUFS_INO_T_64
7827+ a[1] = u.a[1];
7828+#endif
7829+}
7830+
7831+/* NFS file handle */
7832+enum {
7833+ Fh_br_id,
7834+ Fh_sigen,
7835+#ifdef CONFIG_AUFS_INO_T_64
7836+ /* support 64bit inode number */
7837+ Fh_ino1,
7838+ Fh_ino2,
7839+ Fh_dir_ino1,
7840+ Fh_dir_ino2,
7841+#else
7842+ Fh_ino1,
7843+ Fh_dir_ino1,
7844+#endif
7845+ Fh_igen,
7846+ Fh_h_type,
7847+ Fh_tail,
7848+
7849+ Fh_ino = Fh_ino1,
7850+ Fh_dir_ino = Fh_dir_ino1
7851+};
7852+
7853+static int au_test_anon(struct dentry *dentry)
7854+{
027c5e7a 7855+ /* note: read d_flags without d_lock */
4a4d8108
AM
7856+ return !!(dentry->d_flags & DCACHE_DISCONNECTED);
7857+}
7858+
7859+/* ---------------------------------------------------------------------- */
7860+/* inode generation external table */
7861+
b752ccd1 7862+void au_xigen_inc(struct inode *inode)
4a4d8108 7863+{
4a4d8108
AM
7864+ loff_t pos;
7865+ ssize_t sz;
7866+ __u32 igen;
7867+ struct super_block *sb;
7868+ struct au_sbinfo *sbinfo;
7869+
4a4d8108 7870+ sb = inode->i_sb;
b752ccd1 7871+ AuDebugOn(!au_opt_test(au_mntflags(sb), XINO));
1facf9fc 7872+
b752ccd1 7873+ sbinfo = au_sbi(sb);
1facf9fc 7874+ pos = inode->i_ino;
7875+ pos *= sizeof(igen);
7876+ igen = inode->i_generation + 1;
1facf9fc 7877+ sz = xino_fwrite(sbinfo->si_xwrite, sbinfo->si_xigen, &igen,
7878+ sizeof(igen), &pos);
7879+ if (sz == sizeof(igen))
b752ccd1 7880+ return; /* success */
1facf9fc 7881+
b752ccd1 7882+ if (unlikely(sz >= 0))
1facf9fc 7883+ AuIOErr("xigen error (%zd)\n", sz);
1facf9fc 7884+}
7885+
7886+int au_xigen_new(struct inode *inode)
7887+{
7888+ int err;
7889+ loff_t pos;
7890+ ssize_t sz;
7891+ struct super_block *sb;
7892+ struct au_sbinfo *sbinfo;
7893+ struct file *file;
7894+
7895+ err = 0;
7896+ /* todo: dirty, at mount time */
7897+ if (inode->i_ino == AUFS_ROOT_INO)
7898+ goto out;
7899+ sb = inode->i_sb;
dece6358 7900+ SiMustAnyLock(sb);
1facf9fc 7901+ if (unlikely(!au_opt_test(au_mntflags(sb), XINO)))
7902+ goto out;
7903+
7904+ err = -EFBIG;
7905+ pos = inode->i_ino;
7906+ if (unlikely(au_loff_max / sizeof(inode->i_generation) - 1 < pos)) {
7907+ AuIOErr1("too large i%lld\n", pos);
7908+ goto out;
7909+ }
7910+ pos *= sizeof(inode->i_generation);
7911+
7912+ err = 0;
7913+ sbinfo = au_sbi(sb);
7914+ file = sbinfo->si_xigen;
7915+ BUG_ON(!file);
7916+
7917+ if (i_size_read(file->f_dentry->d_inode)
7918+ < pos + sizeof(inode->i_generation)) {
7919+ inode->i_generation = atomic_inc_return(&sbinfo->si_xigen_next);
7920+ sz = xino_fwrite(sbinfo->si_xwrite, file, &inode->i_generation,
7921+ sizeof(inode->i_generation), &pos);
7922+ } else
7923+ sz = xino_fread(sbinfo->si_xread, file, &inode->i_generation,
7924+ sizeof(inode->i_generation), &pos);
7925+ if (sz == sizeof(inode->i_generation))
7926+ goto out; /* success */
7927+
7928+ err = sz;
7929+ if (unlikely(sz >= 0)) {
7930+ err = -EIO;
7931+ AuIOErr("xigen error (%zd)\n", sz);
7932+ }
7933+
4f0767ce 7934+out:
1facf9fc 7935+ return err;
7936+}
7937+
7938+int au_xigen_set(struct super_block *sb, struct file *base)
7939+{
7940+ int err;
7941+ struct au_sbinfo *sbinfo;
7942+ struct file *file;
7943+
dece6358
AM
7944+ SiMustWriteLock(sb);
7945+
1facf9fc 7946+ sbinfo = au_sbi(sb);
7947+ file = au_xino_create2(base, sbinfo->si_xigen);
7948+ err = PTR_ERR(file);
7949+ if (IS_ERR(file))
7950+ goto out;
7951+ err = 0;
7952+ if (sbinfo->si_xigen)
7953+ fput(sbinfo->si_xigen);
7954+ sbinfo->si_xigen = file;
7955+
4f0767ce 7956+out:
1facf9fc 7957+ return err;
7958+}
7959+
7960+void au_xigen_clr(struct super_block *sb)
7961+{
7962+ struct au_sbinfo *sbinfo;
7963+
dece6358
AM
7964+ SiMustWriteLock(sb);
7965+
1facf9fc 7966+ sbinfo = au_sbi(sb);
7967+ if (sbinfo->si_xigen) {
7968+ fput(sbinfo->si_xigen);
7969+ sbinfo->si_xigen = NULL;
7970+ }
7971+}
7972+
7973+/* ---------------------------------------------------------------------- */
7974+
7975+static struct dentry *decode_by_ino(struct super_block *sb, ino_t ino,
7976+ ino_t dir_ino)
7977+{
7978+ struct dentry *dentry, *d;
7979+ struct inode *inode;
7980+ unsigned int sigen;
7981+
7982+ dentry = NULL;
7983+ inode = ilookup(sb, ino);
7984+ if (!inode)
7985+ goto out;
7986+
7987+ dentry = ERR_PTR(-ESTALE);
7988+ sigen = au_sigen(sb);
7989+ if (unlikely(is_bad_inode(inode)
7990+ || IS_DEADDIR(inode)
7991+ || sigen != au_iigen(inode)))
7992+ goto out_iput;
7993+
7994+ dentry = NULL;
7995+ if (!dir_ino || S_ISDIR(inode->i_mode))
7996+ dentry = d_find_alias(inode);
7997+ else {
027c5e7a
AM
7998+ spin_lock(&inode->i_lock);
7999+ list_for_each_entry(d, &inode->i_dentry, d_alias) {
8000+ spin_lock(&d->d_lock);
1facf9fc 8001+ if (!au_test_anon(d)
8002+ && d->d_parent->d_inode->i_ino == dir_ino) {
027c5e7a
AM
8003+ dentry = dget_dlock(d);
8004+ spin_unlock(&d->d_lock);
1facf9fc 8005+ break;
8006+ }
027c5e7a
AM
8007+ spin_unlock(&d->d_lock);
8008+ }
8009+ spin_unlock(&inode->i_lock);
1facf9fc 8010+ }
027c5e7a 8011+ if (unlikely(dentry && au_digen_test(dentry, sigen))) {
2cbb1c4b 8012+ /* need to refresh */
1facf9fc 8013+ dput(dentry);
2cbb1c4b 8014+ dentry = NULL;
1facf9fc 8015+ }
8016+
4f0767ce 8017+out_iput:
1facf9fc 8018+ iput(inode);
4f0767ce 8019+out:
2cbb1c4b 8020+ AuTraceErrPtr(dentry);
1facf9fc 8021+ return dentry;
8022+}
8023+
8024+/* ---------------------------------------------------------------------- */
8025+
8026+/* todo: dirty? */
8027+/* if exportfs_decode_fh() passed vfsmount*, we could be happy */
4a4d8108
AM
8028+
8029+struct au_compare_mnt_args {
8030+ /* input */
8031+ struct super_block *sb;
8032+
8033+ /* output */
8034+ struct vfsmount *mnt;
8035+};
8036+
8037+static int au_compare_mnt(struct vfsmount *mnt, void *arg)
8038+{
8039+ struct au_compare_mnt_args *a = arg;
8040+
8041+ if (mnt->mnt_sb != a->sb)
8042+ return 0;
8043+ a->mnt = mntget(mnt);
8044+ return 1;
8045+}
8046+
1facf9fc 8047+static struct vfsmount *au_mnt_get(struct super_block *sb)
8048+{
4a4d8108
AM
8049+ int err;
8050+ struct au_compare_mnt_args args = {
8051+ .sb = sb
8052+ };
1facf9fc 8053+ struct mnt_namespace *ns;
1facf9fc 8054+
0c5527e5 8055+ br_read_lock(vfsmount_lock);
1facf9fc 8056+ /* no get/put ?? */
8057+ AuDebugOn(!current->nsproxy);
8058+ ns = current->nsproxy->mnt_ns;
8059+ AuDebugOn(!ns);
4a4d8108 8060+ err = iterate_mounts(au_compare_mnt, &args, ns->root);
0c5527e5 8061+ br_read_unlock(vfsmount_lock);
4a4d8108
AM
8062+ AuDebugOn(!err);
8063+ AuDebugOn(!args.mnt);
8064+ return args.mnt;
1facf9fc 8065+}
8066+
8067+struct au_nfsd_si_lock {
4a4d8108 8068+ unsigned int sigen;
027c5e7a 8069+ aufs_bindex_t bindex, br_id;
1facf9fc 8070+ unsigned char force_lock;
8071+};
8072+
027c5e7a
AM
8073+static int si_nfsd_read_lock(struct super_block *sb,
8074+ struct au_nfsd_si_lock *nsi_lock)
1facf9fc 8075+{
027c5e7a 8076+ int err;
1facf9fc 8077+ aufs_bindex_t bindex;
8078+
8079+ si_read_lock(sb, AuLock_FLUSH);
8080+
8081+ /* branch id may be wrapped around */
027c5e7a 8082+ err = 0;
1facf9fc 8083+ bindex = au_br_index(sb, nsi_lock->br_id);
8084+ if (bindex >= 0 && nsi_lock->sigen + AUFS_BRANCH_MAX > au_sigen(sb))
8085+ goto out; /* success */
8086+
027c5e7a
AM
8087+ err = -ESTALE;
8088+ bindex = -1;
1facf9fc 8089+ if (!nsi_lock->force_lock)
8090+ si_read_unlock(sb);
1facf9fc 8091+
4f0767ce 8092+out:
027c5e7a
AM
8093+ nsi_lock->bindex = bindex;
8094+ return err;
1facf9fc 8095+}
8096+
8097+struct find_name_by_ino {
8098+ int called, found;
8099+ ino_t ino;
8100+ char *name;
8101+ int namelen;
8102+};
8103+
8104+static int
8105+find_name_by_ino(void *arg, const char *name, int namelen, loff_t offset,
8106+ u64 ino, unsigned int d_type)
8107+{
8108+ struct find_name_by_ino *a = arg;
8109+
8110+ a->called++;
8111+ if (a->ino != ino)
8112+ return 0;
8113+
8114+ memcpy(a->name, name, namelen);
8115+ a->namelen = namelen;
8116+ a->found = 1;
8117+ return 1;
8118+}
8119+
8120+static struct dentry *au_lkup_by_ino(struct path *path, ino_t ino,
8121+ struct au_nfsd_si_lock *nsi_lock)
8122+{
8123+ struct dentry *dentry, *parent;
8124+ struct file *file;
8125+ struct inode *dir;
8126+ struct find_name_by_ino arg;
8127+ int err;
8128+
8129+ parent = path->dentry;
8130+ if (nsi_lock)
8131+ si_read_unlock(parent->d_sb);
4a4d8108 8132+ file = vfsub_dentry_open(path, au_dir_roflags);
1facf9fc 8133+ dentry = (void *)file;
8134+ if (IS_ERR(file))
8135+ goto out;
8136+
8137+ dentry = ERR_PTR(-ENOMEM);
4a4d8108 8138+ arg.name = __getname_gfp(GFP_NOFS);
1facf9fc 8139+ if (unlikely(!arg.name))
8140+ goto out_file;
8141+ arg.ino = ino;
8142+ arg.found = 0;
8143+ do {
8144+ arg.called = 0;
8145+ /* smp_mb(); */
8146+ err = vfsub_readdir(file, find_name_by_ino, &arg);
8147+ } while (!err && !arg.found && arg.called);
8148+ dentry = ERR_PTR(err);
8149+ if (unlikely(err))
8150+ goto out_name;
8151+ dentry = ERR_PTR(-ENOENT);
8152+ if (!arg.found)
8153+ goto out_name;
8154+
8155+ /* do not call au_lkup_one() */
8156+ dir = parent->d_inode;
8157+ mutex_lock(&dir->i_mutex);
8158+ dentry = vfsub_lookup_one_len(arg.name, parent, arg.namelen);
8159+ mutex_unlock(&dir->i_mutex);
8160+ AuTraceErrPtr(dentry);
8161+ if (IS_ERR(dentry))
8162+ goto out_name;
8163+ AuDebugOn(au_test_anon(dentry));
8164+ if (unlikely(!dentry->d_inode)) {
8165+ dput(dentry);
8166+ dentry = ERR_PTR(-ENOENT);
8167+ }
8168+
4f0767ce 8169+out_name:
1facf9fc 8170+ __putname(arg.name);
4f0767ce 8171+out_file:
1facf9fc 8172+ fput(file);
4f0767ce 8173+out:
1facf9fc 8174+ if (unlikely(nsi_lock
8175+ && si_nfsd_read_lock(parent->d_sb, nsi_lock) < 0))
8176+ if (!IS_ERR(dentry)) {
8177+ dput(dentry);
8178+ dentry = ERR_PTR(-ESTALE);
8179+ }
8180+ AuTraceErrPtr(dentry);
8181+ return dentry;
8182+}
8183+
8184+static struct dentry *decode_by_dir_ino(struct super_block *sb, ino_t ino,
8185+ ino_t dir_ino,
8186+ struct au_nfsd_si_lock *nsi_lock)
8187+{
8188+ struct dentry *dentry;
8189+ struct path path;
8190+
8191+ if (dir_ino != AUFS_ROOT_INO) {
8192+ path.dentry = decode_by_ino(sb, dir_ino, 0);
8193+ dentry = path.dentry;
8194+ if (!path.dentry || IS_ERR(path.dentry))
8195+ goto out;
8196+ AuDebugOn(au_test_anon(path.dentry));
8197+ } else
8198+ path.dentry = dget(sb->s_root);
8199+
8200+ path.mnt = au_mnt_get(sb);
8201+ dentry = au_lkup_by_ino(&path, ino, nsi_lock);
8202+ path_put(&path);
8203+
4f0767ce 8204+out:
1facf9fc 8205+ AuTraceErrPtr(dentry);
8206+ return dentry;
8207+}
8208+
8209+/* ---------------------------------------------------------------------- */
8210+
8211+static int h_acceptable(void *expv, struct dentry *dentry)
8212+{
8213+ return 1;
8214+}
8215+
8216+static char *au_build_path(struct dentry *h_parent, struct path *h_rootpath,
8217+ char *buf, int len, struct super_block *sb)
8218+{
8219+ char *p;
8220+ int n;
8221+ struct path path;
8222+
8223+ p = d_path(h_rootpath, buf, len);
8224+ if (IS_ERR(p))
8225+ goto out;
8226+ n = strlen(p);
8227+
8228+ path.mnt = h_rootpath->mnt;
8229+ path.dentry = h_parent;
8230+ p = d_path(&path, buf, len);
8231+ if (IS_ERR(p))
8232+ goto out;
8233+ if (n != 1)
8234+ p += n;
8235+
8236+ path.mnt = au_mnt_get(sb);
8237+ path.dentry = sb->s_root;
8238+ p = d_path(&path, buf, len - strlen(p));
8239+ mntput(path.mnt);
8240+ if (IS_ERR(p))
8241+ goto out;
8242+ if (n != 1)
8243+ p[strlen(p)] = '/';
8244+
4f0767ce 8245+out:
1facf9fc 8246+ AuTraceErrPtr(p);
8247+ return p;
8248+}
8249+
8250+static
027c5e7a
AM
8251+struct dentry *decode_by_path(struct super_block *sb, ino_t ino, __u32 *fh,
8252+ int fh_len, struct au_nfsd_si_lock *nsi_lock)
1facf9fc 8253+{
8254+ struct dentry *dentry, *h_parent, *root;
8255+ struct super_block *h_sb;
8256+ char *pathname, *p;
8257+ struct vfsmount *h_mnt;
8258+ struct au_branch *br;
8259+ int err;
8260+ struct path path;
8261+
027c5e7a 8262+ br = au_sbr(sb, nsi_lock->bindex);
1facf9fc 8263+ h_mnt = br->br_mnt;
8264+ h_sb = h_mnt->mnt_sb;
8265+ /* todo: call lower fh_to_dentry()? fh_to_parent()? */
8266+ h_parent = exportfs_decode_fh(h_mnt, (void *)(fh + Fh_tail),
8267+ fh_len - Fh_tail, fh[Fh_h_type],
8268+ h_acceptable, /*context*/NULL);
8269+ dentry = h_parent;
8270+ if (unlikely(!h_parent || IS_ERR(h_parent))) {
8271+ AuWarn1("%s decode_fh failed, %ld\n",
8272+ au_sbtype(h_sb), PTR_ERR(h_parent));
8273+ goto out;
8274+ }
8275+ dentry = NULL;
8276+ if (unlikely(au_test_anon(h_parent))) {
8277+ AuWarn1("%s decode_fh returned a disconnected dentry\n",
8278+ au_sbtype(h_sb));
8279+ goto out_h_parent;
8280+ }
8281+
8282+ dentry = ERR_PTR(-ENOMEM);
8283+ pathname = (void *)__get_free_page(GFP_NOFS);
8284+ if (unlikely(!pathname))
8285+ goto out_h_parent;
8286+
8287+ root = sb->s_root;
8288+ path.mnt = h_mnt;
8289+ di_read_lock_parent(root, !AuLock_IR);
027c5e7a 8290+ path.dentry = au_h_dptr(root, nsi_lock->bindex);
1facf9fc 8291+ di_read_unlock(root, !AuLock_IR);
8292+ p = au_build_path(h_parent, &path, pathname, PAGE_SIZE, sb);
8293+ dentry = (void *)p;
8294+ if (IS_ERR(p))
8295+ goto out_pathname;
8296+
8297+ si_read_unlock(sb);
8298+ err = vfsub_kern_path(p, LOOKUP_FOLLOW | LOOKUP_DIRECTORY, &path);
8299+ dentry = ERR_PTR(err);
8300+ if (unlikely(err))
8301+ goto out_relock;
8302+
8303+ dentry = ERR_PTR(-ENOENT);
8304+ AuDebugOn(au_test_anon(path.dentry));
8305+ if (unlikely(!path.dentry->d_inode))
8306+ goto out_path;
8307+
8308+ if (ino != path.dentry->d_inode->i_ino)
8309+ dentry = au_lkup_by_ino(&path, ino, /*nsi_lock*/NULL);
8310+ else
8311+ dentry = dget(path.dentry);
8312+
4f0767ce 8313+out_path:
1facf9fc 8314+ path_put(&path);
4f0767ce 8315+out_relock:
1facf9fc 8316+ if (unlikely(si_nfsd_read_lock(sb, nsi_lock) < 0))
8317+ if (!IS_ERR(dentry)) {
8318+ dput(dentry);
8319+ dentry = ERR_PTR(-ESTALE);
8320+ }
4f0767ce 8321+out_pathname:
1facf9fc 8322+ free_page((unsigned long)pathname);
4f0767ce 8323+out_h_parent:
1facf9fc 8324+ dput(h_parent);
4f0767ce 8325+out:
1facf9fc 8326+ AuTraceErrPtr(dentry);
8327+ return dentry;
8328+}
8329+
8330+/* ---------------------------------------------------------------------- */
8331+
8332+static struct dentry *
8333+aufs_fh_to_dentry(struct super_block *sb, struct fid *fid, int fh_len,
8334+ int fh_type)
8335+{
8336+ struct dentry *dentry;
8337+ __u32 *fh = fid->raw;
027c5e7a 8338+ struct au_branch *br;
1facf9fc 8339+ ino_t ino, dir_ino;
1facf9fc 8340+ struct au_nfsd_si_lock nsi_lock = {
1facf9fc 8341+ .force_lock = 0
8342+ };
8343+
1facf9fc 8344+ dentry = ERR_PTR(-ESTALE);
4a4d8108
AM
8345+ /* it should never happen, but the file handle is unreliable */
8346+ if (unlikely(fh_len < Fh_tail))
8347+ goto out;
8348+ nsi_lock.sigen = fh[Fh_sigen];
8349+ nsi_lock.br_id = fh[Fh_br_id];
8350+
1facf9fc 8351+ /* branch id may be wrapped around */
027c5e7a
AM
8352+ br = NULL;
8353+ if (unlikely(si_nfsd_read_lock(sb, &nsi_lock)))
1facf9fc 8354+ goto out;
8355+ nsi_lock.force_lock = 1;
8356+
8357+ /* is this inode still cached? */
8358+ ino = decode_ino(fh + Fh_ino);
4a4d8108
AM
8359+ /* it should never happen */
8360+ if (unlikely(ino == AUFS_ROOT_INO))
8361+ goto out;
8362+
1facf9fc 8363+ dir_ino = decode_ino(fh + Fh_dir_ino);
8364+ dentry = decode_by_ino(sb, ino, dir_ino);
8365+ if (IS_ERR(dentry))
8366+ goto out_unlock;
8367+ if (dentry)
8368+ goto accept;
8369+
8370+ /* is the parent dir cached? */
027c5e7a
AM
8371+ br = au_sbr(sb, nsi_lock.bindex);
8372+ atomic_inc(&br->br_count);
1facf9fc 8373+ dentry = decode_by_dir_ino(sb, ino, dir_ino, &nsi_lock);
8374+ if (IS_ERR(dentry))
8375+ goto out_unlock;
8376+ if (dentry)
8377+ goto accept;
8378+
8379+ /* lookup path */
027c5e7a 8380+ dentry = decode_by_path(sb, ino, fh, fh_len, &nsi_lock);
1facf9fc 8381+ if (IS_ERR(dentry))
8382+ goto out_unlock;
8383+ if (unlikely(!dentry))
8384+ /* todo?: make it ESTALE */
8385+ goto out_unlock;
8386+
4f0767ce 8387+accept:
027c5e7a
AM
8388+ if (!au_digen_test(dentry, au_sigen(sb))
8389+ && dentry->d_inode->i_generation == fh[Fh_igen])
1facf9fc 8390+ goto out_unlock; /* success */
8391+
8392+ dput(dentry);
8393+ dentry = ERR_PTR(-ESTALE);
4f0767ce 8394+out_unlock:
027c5e7a
AM
8395+ if (br)
8396+ atomic_dec(&br->br_count);
1facf9fc 8397+ si_read_unlock(sb);
4f0767ce 8398+out:
1facf9fc 8399+ AuTraceErrPtr(dentry);
8400+ return dentry;
8401+}
8402+
8403+#if 0 /* reserved for future use */
8404+/* support subtreecheck option */
8405+static struct dentry *aufs_fh_to_parent(struct super_block *sb, struct fid *fid,
8406+ int fh_len, int fh_type)
8407+{
8408+ struct dentry *parent;
8409+ __u32 *fh = fid->raw;
8410+ ino_t dir_ino;
8411+
8412+ dir_ino = decode_ino(fh + Fh_dir_ino);
8413+ parent = decode_by_ino(sb, dir_ino, 0);
8414+ if (IS_ERR(parent))
8415+ goto out;
8416+ if (!parent)
8417+ parent = decode_by_path(sb, au_br_index(sb, fh[Fh_br_id]),
8418+ dir_ino, fh, fh_len);
8419+
4f0767ce 8420+out:
1facf9fc 8421+ AuTraceErrPtr(parent);
8422+ return parent;
8423+}
8424+#endif
8425+
8426+/* ---------------------------------------------------------------------- */
8427+
8428+static int aufs_encode_fh(struct dentry *dentry, __u32 *fh, int *max_len,
8429+ int connectable)
8430+{
8431+ int err;
8432+ aufs_bindex_t bindex, bend;
8433+ struct super_block *sb, *h_sb;
8434+ struct inode *inode;
8435+ struct dentry *parent, *h_parent;
8436+ struct au_branch *br;
8437+
8438+ AuDebugOn(au_test_anon(dentry));
8439+
8440+ parent = NULL;
8441+ err = -ENOSPC;
8442+ if (unlikely(*max_len <= Fh_tail)) {
8443+ AuWarn1("NFSv2 client (max_len %d)?\n", *max_len);
8444+ goto out;
8445+ }
8446+
8447+ err = FILEID_ROOT;
8448+ if (IS_ROOT(dentry)) {
8449+ AuDebugOn(dentry->d_inode->i_ino != AUFS_ROOT_INO);
8450+ goto out;
8451+ }
8452+
1facf9fc 8453+ h_parent = NULL;
027c5e7a
AM
8454+ err = aufs_read_lock(dentry, AuLock_FLUSH | AuLock_IR | AuLock_GEN);
8455+ if (unlikely(err))
8456+ goto out;
8457+
1facf9fc 8458+ inode = dentry->d_inode;
8459+ AuDebugOn(!inode);
027c5e7a 8460+ sb = dentry->d_sb;
1facf9fc 8461+#ifdef CONFIG_AUFS_DEBUG
8462+ if (unlikely(!au_opt_test(au_mntflags(sb), XINO)))
8463+ AuWarn1("NFS-exporting requires xino\n");
8464+#endif
027c5e7a
AM
8465+ err = -EIO;
8466+ parent = dget_parent(dentry);
8467+ di_read_lock_parent(parent, !AuLock_IR);
1facf9fc 8468+ bend = au_dbtaildir(parent);
8469+ for (bindex = au_dbstart(parent); bindex <= bend; bindex++) {
8470+ h_parent = au_h_dptr(parent, bindex);
8471+ if (h_parent) {
8472+ dget(h_parent);
8473+ break;
8474+ }
8475+ }
8476+ if (unlikely(!h_parent))
8477+ goto out_unlock;
8478+
8479+ err = -EPERM;
8480+ br = au_sbr(sb, bindex);
8481+ h_sb = br->br_mnt->mnt_sb;
8482+ if (unlikely(!h_sb->s_export_op)) {
8483+ AuErr1("%s branch is not exportable\n", au_sbtype(h_sb));
8484+ goto out_dput;
8485+ }
8486+
8487+ fh[Fh_br_id] = br->br_id;
8488+ fh[Fh_sigen] = au_sigen(sb);
8489+ encode_ino(fh + Fh_ino, inode->i_ino);
8490+ encode_ino(fh + Fh_dir_ino, parent->d_inode->i_ino);
8491+ fh[Fh_igen] = inode->i_generation;
8492+
8493+ *max_len -= Fh_tail;
8494+ fh[Fh_h_type] = exportfs_encode_fh(h_parent, (void *)(fh + Fh_tail),
8495+ max_len,
8496+ /*connectable or subtreecheck*/0);
8497+ err = fh[Fh_h_type];
8498+ *max_len += Fh_tail;
8499+ /* todo: macros? */
8500+ if (err != 255)
8501+ err = 99;
8502+ else
8503+ AuWarn1("%s encode_fh failed\n", au_sbtype(h_sb));
8504+
4f0767ce 8505+out_dput:
1facf9fc 8506+ dput(h_parent);
4f0767ce 8507+out_unlock:
1facf9fc 8508+ di_read_unlock(parent, !AuLock_IR);
8509+ dput(parent);
8510+ aufs_read_unlock(dentry, AuLock_IR);
4f0767ce 8511+out:
1facf9fc 8512+ if (unlikely(err < 0))
8513+ err = 255;
8514+ return err;
8515+}
8516+
8517+/* ---------------------------------------------------------------------- */
8518+
4a4d8108
AM
8519+static int aufs_commit_metadata(struct inode *inode)
8520+{
8521+ int err;
8522+ aufs_bindex_t bindex;
8523+ struct super_block *sb;
8524+ struct inode *h_inode;
8525+ int (*f)(struct inode *inode);
8526+
8527+ sb = inode->i_sb;
e49829fe 8528+ si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLMW);
4a4d8108
AM
8529+ ii_write_lock_child(inode);
8530+ bindex = au_ibstart(inode);
8531+ AuDebugOn(bindex < 0);
8532+ h_inode = au_h_iptr(inode, bindex);
8533+
8534+ f = h_inode->i_sb->s_export_op->commit_metadata;
8535+ if (f)
8536+ err = f(h_inode);
8537+ else {
8538+ struct writeback_control wbc = {
8539+ .sync_mode = WB_SYNC_ALL,
8540+ .nr_to_write = 0 /* metadata only */
8541+ };
8542+
8543+ err = sync_inode(h_inode, &wbc);
8544+ }
8545+
8546+ au_cpup_attr_timesizes(inode);
8547+ ii_write_unlock(inode);
8548+ si_read_unlock(sb);
8549+ return err;
8550+}
8551+
8552+/* ---------------------------------------------------------------------- */
8553+
1facf9fc 8554+static struct export_operations aufs_export_op = {
4a4d8108 8555+ .fh_to_dentry = aufs_fh_to_dentry,
1facf9fc 8556+ /* .fh_to_parent = aufs_fh_to_parent, */
4a4d8108
AM
8557+ .encode_fh = aufs_encode_fh,
8558+ .commit_metadata = aufs_commit_metadata
1facf9fc 8559+};
8560+
8561+void au_export_init(struct super_block *sb)
8562+{
8563+ struct au_sbinfo *sbinfo;
8564+ __u32 u;
8565+
8566+ sb->s_export_op = &aufs_export_op;
8567+ sbinfo = au_sbi(sb);
8568+ sbinfo->si_xigen = NULL;
8569+ get_random_bytes(&u, sizeof(u));
8570+ BUILD_BUG_ON(sizeof(u) != sizeof(int));
8571+ atomic_set(&sbinfo->si_xigen_next, u);
8572+}
7f207e10
AM
8573diff -urN /usr/share/empty/fs/aufs/file.c linux/fs/aufs/file.c
8574--- /usr/share/empty/fs/aufs/file.c 1970-01-01 01:00:00.000000000 +0100
87a755f4 8575+++ linux/fs/aufs/file.c 2011-07-22 08:26:47.857636522 +0200
2cbb1c4b 8576@@ -0,0 +1,676 @@
1facf9fc 8577+/*
027c5e7a 8578+ * Copyright (C) 2005-2011 Junjiro R. Okajima
1facf9fc 8579+ *
8580+ * This program, aufs is free software; you can redistribute it and/or modify
8581+ * it under the terms of the GNU General Public License as published by
8582+ * the Free Software Foundation; either version 2 of the License, or
8583+ * (at your option) any later version.
dece6358
AM
8584+ *
8585+ * This program is distributed in the hope that it will be useful,
8586+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
8587+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
8588+ * GNU General Public License for more details.
8589+ *
8590+ * You should have received a copy of the GNU General Public License
8591+ * along with this program; if not, write to the Free Software
8592+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 8593+ */
8594+
8595+/*
4a4d8108 8596+ * handling file/dir, and address_space operation
1facf9fc 8597+ */
8598+
dece6358 8599+#include <linux/file.h>
4a4d8108
AM
8600+#include <linux/fsnotify.h>
8601+#include <linux/namei.h>
8602+#include <linux/pagemap.h>
1facf9fc 8603+#include "aufs.h"
8604+
4a4d8108
AM
8605+/* drop flags for writing */
8606+unsigned int au_file_roflags(unsigned int flags)
8607+{
8608+ flags &= ~(O_WRONLY | O_RDWR | O_APPEND | O_CREAT | O_TRUNC);
8609+ flags |= O_RDONLY | O_NOATIME;
8610+ return flags;
8611+}
8612+
8613+/* common functions to regular file and dir */
8614+struct file *au_h_open(struct dentry *dentry, aufs_bindex_t bindex, int flags,
8615+ struct file *file)
1facf9fc 8616+{
1308ab2a 8617+ struct file *h_file;
4a4d8108
AM
8618+ struct dentry *h_dentry;
8619+ struct inode *h_inode;
8620+ struct super_block *sb;
8621+ struct au_branch *br;
8622+ struct path h_path;
8623+ int err, exec_flag;
1facf9fc 8624+
4a4d8108
AM
8625+ /* a race condition can happen between open and unlink/rmdir */
8626+ h_file = ERR_PTR(-ENOENT);
8627+ h_dentry = au_h_dptr(dentry, bindex);
b752ccd1 8628+ if (au_test_nfsd() && !h_dentry)
4a4d8108
AM
8629+ goto out;
8630+ h_inode = h_dentry->d_inode;
b752ccd1 8631+ if (au_test_nfsd() && !h_inode)
4a4d8108 8632+ goto out;
027c5e7a
AM
8633+ spin_lock(&h_dentry->d_lock);
8634+ err = (!d_unhashed(dentry) && d_unlinked(h_dentry))
8635+ || !h_inode
8636+ /* || !dentry->d_inode->i_nlink */
8637+ ;
8638+ spin_unlock(&h_dentry->d_lock);
8639+ if (unlikely(err))
4a4d8108 8640+ goto out;
1facf9fc 8641+
4a4d8108
AM
8642+ sb = dentry->d_sb;
8643+ br = au_sbr(sb, bindex);
8644+ h_file = ERR_PTR(-EACCES);
2cbb1c4b 8645+ exec_flag = flags & __FMODE_EXEC;
4a4d8108 8646+ if (exec_flag && (br->br_mnt->mnt_flags & MNT_NOEXEC))
027c5e7a 8647+ goto out;
1facf9fc 8648+
4a4d8108
AM
8649+ /* drop flags for writing */
8650+ if (au_test_ro(sb, bindex, dentry->d_inode))
8651+ flags = au_file_roflags(flags);
8652+ flags &= ~O_CREAT;
8653+ atomic_inc(&br->br_count);
8654+ h_path.dentry = h_dentry;
8655+ h_path.mnt = br->br_mnt;
8656+ if (!au_special_file(h_inode->i_mode))
8657+ h_file = vfsub_dentry_open(&h_path, flags);
8658+ else {
8659+ /* this block depends upon the configuration */
8660+ di_read_unlock(dentry, AuLock_IR);
8661+ fi_write_unlock(file);
8662+ si_read_unlock(sb);
8663+ h_file = vfsub_dentry_open(&h_path, flags);
8664+ si_noflush_read_lock(sb);
8665+ fi_write_lock(file);
8666+ di_read_lock_child(dentry, AuLock_IR);
dece6358 8667+ }
4a4d8108
AM
8668+ if (IS_ERR(h_file))
8669+ goto out_br;
dece6358 8670+
4a4d8108
AM
8671+ if (exec_flag) {
8672+ err = deny_write_access(h_file);
8673+ if (unlikely(err)) {
8674+ fput(h_file);
8675+ h_file = ERR_PTR(err);
8676+ goto out_br;
8677+ }
8678+ }
953406b4 8679+ fsnotify_open(h_file);
4a4d8108 8680+ goto out; /* success */
1facf9fc 8681+
4f0767ce 8682+out_br:
4a4d8108 8683+ atomic_dec(&br->br_count);
4f0767ce 8684+out:
4a4d8108
AM
8685+ return h_file;
8686+}
1308ab2a 8687+
4a4d8108
AM
8688+int au_do_open(struct file *file, int (*open)(struct file *file, int flags),
8689+ struct au_fidir *fidir)
1facf9fc 8690+{
dece6358 8691+ int err;
1facf9fc 8692+ struct dentry *dentry;
1308ab2a 8693+
4a4d8108
AM
8694+ err = au_finfo_init(file, fidir);
8695+ if (unlikely(err))
8696+ goto out;
1facf9fc 8697+
8698+ dentry = file->f_dentry;
4a4d8108
AM
8699+ di_read_lock_child(dentry, AuLock_IR);
8700+ err = open(file, vfsub_file_flags(file));
8701+ di_read_unlock(dentry, AuLock_IR);
1facf9fc 8702+
4a4d8108
AM
8703+ fi_write_unlock(file);
8704+ if (unlikely(err)) {
8705+ au_fi(file)->fi_hdir = NULL;
8706+ au_finfo_fin(file);
1308ab2a 8707+ }
4a4d8108 8708+
4f0767ce 8709+out:
1308ab2a 8710+ return err;
8711+}
dece6358 8712+
4a4d8108 8713+int au_reopen_nondir(struct file *file)
1308ab2a 8714+{
4a4d8108
AM
8715+ int err;
8716+ aufs_bindex_t bstart;
8717+ struct dentry *dentry;
8718+ struct file *h_file, *h_file_tmp;
1308ab2a 8719+
4a4d8108
AM
8720+ dentry = file->f_dentry;
8721+ AuDebugOn(au_special_file(dentry->d_inode->i_mode));
8722+ bstart = au_dbstart(dentry);
8723+ h_file_tmp = NULL;
8724+ if (au_fbstart(file) == bstart) {
8725+ h_file = au_hf_top(file);
8726+ if (file->f_mode == h_file->f_mode)
8727+ return 0; /* success */
8728+ h_file_tmp = h_file;
8729+ get_file(h_file_tmp);
8730+ au_set_h_fptr(file, bstart, NULL);
8731+ }
8732+ AuDebugOn(au_fi(file)->fi_hdir);
8733+ AuDebugOn(au_fbstart(file) < bstart);
1308ab2a 8734+
4a4d8108
AM
8735+ h_file = au_h_open(dentry, bstart, vfsub_file_flags(file) & ~O_TRUNC,
8736+ file);
8737+ err = PTR_ERR(h_file);
8738+ if (IS_ERR(h_file))
8739+ goto out; /* todo: close all? */
8740+
8741+ err = 0;
8742+ au_set_fbstart(file, bstart);
8743+ au_set_h_fptr(file, bstart, h_file);
8744+ au_update_figen(file);
8745+ /* todo: necessary? */
8746+ /* file->f_ra = h_file->f_ra; */
8747+
4f0767ce 8748+out:
4a4d8108
AM
8749+ if (h_file_tmp)
8750+ fput(h_file_tmp);
8751+ return err;
1facf9fc 8752+}
8753+
1308ab2a 8754+/* ---------------------------------------------------------------------- */
8755+
4a4d8108
AM
8756+static int au_reopen_wh(struct file *file, aufs_bindex_t btgt,
8757+ struct dentry *hi_wh)
1facf9fc 8758+{
4a4d8108
AM
8759+ int err;
8760+ aufs_bindex_t bstart;
8761+ struct au_dinfo *dinfo;
8762+ struct dentry *h_dentry;
8763+ struct au_hdentry *hdp;
1facf9fc 8764+
4a4d8108
AM
8765+ dinfo = au_di(file->f_dentry);
8766+ AuRwMustWriteLock(&dinfo->di_rwsem);
dece6358 8767+
4a4d8108
AM
8768+ bstart = dinfo->di_bstart;
8769+ dinfo->di_bstart = btgt;
8770+ hdp = dinfo->di_hdentry;
8771+ h_dentry = hdp[0 + btgt].hd_dentry;
8772+ hdp[0 + btgt].hd_dentry = hi_wh;
8773+ err = au_reopen_nondir(file);
8774+ hdp[0 + btgt].hd_dentry = h_dentry;
8775+ dinfo->di_bstart = bstart;
1facf9fc 8776+
1facf9fc 8777+ return err;
8778+}
8779+
4a4d8108
AM
8780+static int au_ready_to_write_wh(struct file *file, loff_t len,
8781+ aufs_bindex_t bcpup)
1facf9fc 8782+{
4a4d8108 8783+ int err;
027c5e7a
AM
8784+ struct inode *inode, *h_inode;
8785+ struct dentry *dentry, *h_dentry, *hi_wh;
1facf9fc 8786+
dece6358 8787+ dentry = file->f_dentry;
4a4d8108 8788+ au_update_dbstart(dentry);
dece6358 8789+ inode = dentry->d_inode;
027c5e7a
AM
8790+ h_inode = NULL;
8791+ if (au_dbstart(dentry) <= bcpup && au_dbend(dentry) >= bcpup) {
8792+ h_dentry = au_h_dptr(dentry, bcpup);
8793+ if (h_dentry)
8794+ h_inode = h_dentry->d_inode;
8795+ }
4a4d8108 8796+ hi_wh = au_hi_wh(inode, bcpup);
027c5e7a 8797+ if (!hi_wh && !h_inode)
4a4d8108
AM
8798+ err = au_sio_cpup_wh(dentry, bcpup, len, file);
8799+ else
8800+ /* already copied-up after unlink */
8801+ err = au_reopen_wh(file, bcpup, hi_wh);
1facf9fc 8802+
4a4d8108
AM
8803+ if (!err
8804+ && inode->i_nlink > 1
8805+ && au_opt_test(au_mntflags(dentry->d_sb), PLINK))
8806+ au_plink_append(inode, bcpup, au_h_dptr(dentry, bcpup));
1308ab2a 8807+
dece6358 8808+ return err;
1facf9fc 8809+}
8810+
4a4d8108
AM
8811+/*
8812+ * prepare the @file for writing.
8813+ */
8814+int au_ready_to_write(struct file *file, loff_t len, struct au_pin *pin)
1facf9fc 8815+{
4a4d8108 8816+ int err;
027c5e7a 8817+ aufs_bindex_t bstart, bcpup, dbstart;
4a4d8108
AM
8818+ struct dentry *dentry, *parent, *h_dentry;
8819+ struct inode *h_inode, *inode;
1facf9fc 8820+ struct super_block *sb;
4a4d8108 8821+ struct file *h_file;
1facf9fc 8822+
8823+ dentry = file->f_dentry;
1facf9fc 8824+ sb = dentry->d_sb;
4a4d8108
AM
8825+ inode = dentry->d_inode;
8826+ AuDebugOn(au_special_file(inode->i_mode));
8827+ bstart = au_fbstart(file);
8828+ err = au_test_ro(sb, bstart, inode);
8829+ if (!err && (au_hf_top(file)->f_mode & FMODE_WRITE)) {
8830+ err = au_pin(pin, dentry, bstart, AuOpt_UDBA_NONE, /*flags*/0);
1facf9fc 8831+ goto out;
4a4d8108 8832+ }
1facf9fc 8833+
027c5e7a 8834+ /* need to cpup or reopen */
4a4d8108
AM
8835+ parent = dget_parent(dentry);
8836+ di_write_lock_parent(parent);
8837+ err = AuWbrCopyup(au_sbi(sb), dentry);
8838+ bcpup = err;
8839+ if (unlikely(err < 0))
8840+ goto out_dgrade;
8841+ err = 0;
8842+
027c5e7a 8843+ if (!d_unhashed(dentry) && !au_h_dptr(parent, bcpup)) {
4a4d8108 8844+ err = au_cpup_dirs(dentry, bcpup);
1facf9fc 8845+ if (unlikely(err))
4a4d8108
AM
8846+ goto out_dgrade;
8847+ }
8848+
8849+ err = au_pin(pin, dentry, bcpup, AuOpt_UDBA_NONE,
8850+ AuPin_DI_LOCKED | AuPin_MNT_WRITE);
8851+ if (unlikely(err))
8852+ goto out_dgrade;
8853+
8854+ h_dentry = au_hf_top(file)->f_dentry;
8855+ h_inode = h_dentry->d_inode;
027c5e7a
AM
8856+ dbstart = au_dbstart(dentry);
8857+ if (dbstart <= bcpup) {
8858+ h_dentry = au_h_dptr(dentry, bcpup);
8859+ AuDebugOn(!h_dentry);
8860+ h_inode = h_dentry->d_inode;
8861+ AuDebugOn(!h_inode);
8862+ bstart = bcpup;
8863+ }
8864+
8865+ if (dbstart <= bcpup /* just reopen */
8866+ || !d_unhashed(dentry) /* copyup and reopen */
8867+ ) {
8868+ mutex_lock_nested(&h_inode->i_mutex, AuLsc_I_CHILD);
8869+ h_file = au_h_open_pre(dentry, bstart);
8870+ if (IS_ERR(h_file)) {
8871+ err = PTR_ERR(h_file);
8872+ h_file = NULL;
8873+ } else {
8874+ di_downgrade_lock(parent, AuLock_IR);
8875+ if (dbstart > bcpup)
8876+ err = au_sio_cpup_simple(dentry, bcpup, len,
8877+ AuCpup_DTIME);
8878+ if (!err)
8879+ err = au_reopen_nondir(file);
8880+ }
8881+ mutex_unlock(&h_inode->i_mutex);
8882+ au_h_open_post(dentry, bstart, h_file);
8883+ } else { /* copyup as wh and reopen */
8884+ /*
8885+ * since writable hfsplus branch is not supported,
8886+ * h_open_pre/post() are unnecessary.
8887+ */
8888+ mutex_lock_nested(&h_inode->i_mutex, AuLsc_I_CHILD);
4a4d8108
AM
8889+ err = au_ready_to_write_wh(file, len, bcpup);
8890+ di_downgrade_lock(parent, AuLock_IR);
027c5e7a 8891+ mutex_unlock(&h_inode->i_mutex);
4a4d8108 8892+ }
4a4d8108
AM
8893+
8894+ if (!err) {
8895+ au_pin_set_parent_lflag(pin, /*lflag*/0);
8896+ goto out_dput; /* success */
8897+ }
8898+ au_unpin(pin);
8899+ goto out_unlock;
1facf9fc 8900+
4f0767ce 8901+out_dgrade:
4a4d8108 8902+ di_downgrade_lock(parent, AuLock_IR);
4f0767ce 8903+out_unlock:
4a4d8108 8904+ di_read_unlock(parent, AuLock_IR);
4f0767ce 8905+out_dput:
4a4d8108 8906+ dput(parent);
4f0767ce 8907+out:
1facf9fc 8908+ return err;
8909+}
8910+
4a4d8108
AM
8911+/* ---------------------------------------------------------------------- */
8912+
8913+int au_do_flush(struct file *file, fl_owner_t id,
8914+ int (*flush)(struct file *file, fl_owner_t id))
1facf9fc 8915+{
4a4d8108 8916+ int err;
1308ab2a 8917+ struct dentry *dentry;
1facf9fc 8918+ struct super_block *sb;
4a4d8108 8919+ struct inode *inode;
1facf9fc 8920+
1facf9fc 8921+ dentry = file->f_dentry;
8922+ sb = dentry->d_sb;
dece6358 8923+ inode = dentry->d_inode;
4a4d8108
AM
8924+ si_noflush_read_lock(sb);
8925+ fi_read_lock(file);
b752ccd1 8926+ ii_read_lock_child(inode);
1facf9fc 8927+
4a4d8108
AM
8928+ err = flush(file, id);
8929+ au_cpup_attr_timesizes(inode);
1facf9fc 8930+
b752ccd1 8931+ ii_read_unlock(inode);
4a4d8108 8932+ fi_read_unlock(file);
1308ab2a 8933+ si_read_unlock(sb);
dece6358 8934+ return err;
1facf9fc 8935+}
8936+
4a4d8108
AM
8937+/* ---------------------------------------------------------------------- */
8938+
8939+static int au_file_refresh_by_inode(struct file *file, int *need_reopen)
1facf9fc 8940+{
4a4d8108
AM
8941+ int err;
8942+ aufs_bindex_t bstart;
8943+ struct au_pin pin;
8944+ struct au_finfo *finfo;
8945+ struct dentry *dentry, *parent, *hi_wh;
8946+ struct inode *inode;
1facf9fc 8947+ struct super_block *sb;
8948+
4a4d8108
AM
8949+ FiMustWriteLock(file);
8950+
8951+ err = 0;
8952+ finfo = au_fi(file);
1308ab2a 8953+ dentry = file->f_dentry;
8954+ sb = dentry->d_sb;
4a4d8108
AM
8955+ inode = dentry->d_inode;
8956+ bstart = au_ibstart(inode);
027c5e7a 8957+ if (bstart == finfo->fi_btop || IS_ROOT(dentry))
1308ab2a 8958+ goto out;
dece6358 8959+
4a4d8108
AM
8960+ parent = dget_parent(dentry);
8961+ if (au_test_ro(sb, bstart, inode)) {
8962+ di_read_lock_parent(parent, !AuLock_IR);
8963+ err = AuWbrCopyup(au_sbi(sb), dentry);
8964+ bstart = err;
8965+ di_read_unlock(parent, !AuLock_IR);
8966+ if (unlikely(err < 0))
8967+ goto out_parent;
8968+ err = 0;
1facf9fc 8969+ }
1facf9fc 8970+
4a4d8108
AM
8971+ di_read_lock_parent(parent, AuLock_IR);
8972+ hi_wh = au_hi_wh(inode, bstart);
7f207e10
AM
8973+ if (!S_ISDIR(inode->i_mode)
8974+ && au_opt_test(au_mntflags(sb), PLINK)
4a4d8108
AM
8975+ && au_plink_test(inode)
8976+ && !d_unhashed(dentry)) {
8977+ err = au_test_and_cpup_dirs(dentry, bstart);
8978+ if (unlikely(err))
8979+ goto out_unlock;
8980+
8981+ /* always superio. */
8982+ err = au_pin(&pin, dentry, bstart, AuOpt_UDBA_NONE,
8983+ AuPin_DI_LOCKED | AuPin_MNT_WRITE);
8984+ if (!err)
8985+ err = au_sio_cpup_simple(dentry, bstart, -1,
8986+ AuCpup_DTIME);
8987+ au_unpin(&pin);
8988+ } else if (hi_wh) {
8989+ /* already copied-up after unlink */
8990+ err = au_reopen_wh(file, bstart, hi_wh);
8991+ *need_reopen = 0;
8992+ }
1facf9fc 8993+
4f0767ce 8994+out_unlock:
4a4d8108 8995+ di_read_unlock(parent, AuLock_IR);
4f0767ce 8996+out_parent:
4a4d8108 8997+ dput(parent);
4f0767ce 8998+out:
1308ab2a 8999+ return err;
dece6358 9000+}
1facf9fc 9001+
4a4d8108 9002+static void au_do_refresh_dir(struct file *file)
dece6358 9003+{
4a4d8108
AM
9004+ aufs_bindex_t bindex, bend, new_bindex, brid;
9005+ struct au_hfile *p, tmp, *q;
9006+ struct au_finfo *finfo;
1308ab2a 9007+ struct super_block *sb;
4a4d8108 9008+ struct au_fidir *fidir;
1facf9fc 9009+
4a4d8108 9010+ FiMustWriteLock(file);
1facf9fc 9011+
4a4d8108
AM
9012+ sb = file->f_dentry->d_sb;
9013+ finfo = au_fi(file);
9014+ fidir = finfo->fi_hdir;
9015+ AuDebugOn(!fidir);
9016+ p = fidir->fd_hfile + finfo->fi_btop;
9017+ brid = p->hf_br->br_id;
9018+ bend = fidir->fd_bbot;
9019+ for (bindex = finfo->fi_btop; bindex <= bend; bindex++, p++) {
9020+ if (!p->hf_file)
9021+ continue;
1308ab2a 9022+
4a4d8108
AM
9023+ new_bindex = au_br_index(sb, p->hf_br->br_id);
9024+ if (new_bindex == bindex)
9025+ continue;
9026+ if (new_bindex < 0) {
9027+ au_set_h_fptr(file, bindex, NULL);
9028+ continue;
9029+ }
1308ab2a 9030+
4a4d8108
AM
9031+ /* swap two lower inode, and loop again */
9032+ q = fidir->fd_hfile + new_bindex;
9033+ tmp = *q;
9034+ *q = *p;
9035+ *p = tmp;
9036+ if (tmp.hf_file) {
9037+ bindex--;
9038+ p--;
9039+ }
9040+ }
1308ab2a 9041+
4a4d8108 9042+ p = fidir->fd_hfile;
027c5e7a 9043+ if (!au_test_mmapped(file) && !d_unlinked(file->f_dentry)) {
4a4d8108
AM
9044+ bend = au_sbend(sb);
9045+ for (finfo->fi_btop = 0; finfo->fi_btop <= bend;
9046+ finfo->fi_btop++, p++)
9047+ if (p->hf_file) {
9048+ if (p->hf_file->f_dentry
9049+ && p->hf_file->f_dentry->d_inode)
9050+ break;
9051+ else
9052+ au_hfput(p, file);
9053+ }
9054+ } else {
9055+ bend = au_br_index(sb, brid);
9056+ for (finfo->fi_btop = 0; finfo->fi_btop < bend;
9057+ finfo->fi_btop++, p++)
9058+ if (p->hf_file)
9059+ au_hfput(p, file);
9060+ bend = au_sbend(sb);
9061+ }
1308ab2a 9062+
4a4d8108
AM
9063+ p = fidir->fd_hfile + bend;
9064+ for (fidir->fd_bbot = bend; fidir->fd_bbot >= finfo->fi_btop;
9065+ fidir->fd_bbot--, p--)
9066+ if (p->hf_file) {
9067+ if (p->hf_file->f_dentry
9068+ && p->hf_file->f_dentry->d_inode)
9069+ break;
9070+ else
9071+ au_hfput(p, file);
9072+ }
9073+ AuDebugOn(fidir->fd_bbot < finfo->fi_btop);
1308ab2a 9074+}
9075+
4a4d8108
AM
9076+/*
9077+ * after branch manipulating, refresh the file.
9078+ */
9079+static int refresh_file(struct file *file, int (*reopen)(struct file *file))
1facf9fc 9080+{
4a4d8108
AM
9081+ int err, need_reopen;
9082+ aufs_bindex_t bend, bindex;
9083+ struct dentry *dentry;
1308ab2a 9084+ struct au_finfo *finfo;
4a4d8108 9085+ struct au_hfile *hfile;
1facf9fc 9086+
4a4d8108 9087+ dentry = file->f_dentry;
1308ab2a 9088+ finfo = au_fi(file);
4a4d8108
AM
9089+ if (!finfo->fi_hdir) {
9090+ hfile = &finfo->fi_htop;
9091+ AuDebugOn(!hfile->hf_file);
9092+ bindex = au_br_index(dentry->d_sb, hfile->hf_br->br_id);
9093+ AuDebugOn(bindex < 0);
9094+ if (bindex != finfo->fi_btop)
9095+ au_set_fbstart(file, bindex);
9096+ } else {
9097+ err = au_fidir_realloc(finfo, au_sbend(dentry->d_sb) + 1);
9098+ if (unlikely(err))
9099+ goto out;
9100+ au_do_refresh_dir(file);
9101+ }
1facf9fc 9102+
4a4d8108
AM
9103+ err = 0;
9104+ need_reopen = 1;
9105+ if (!au_test_mmapped(file))
9106+ err = au_file_refresh_by_inode(file, &need_reopen);
027c5e7a 9107+ if (!err && need_reopen && !d_unlinked(dentry))
4a4d8108
AM
9108+ err = reopen(file);
9109+ if (!err) {
9110+ au_update_figen(file);
9111+ goto out; /* success */
9112+ }
9113+
9114+ /* error, close all lower files */
9115+ if (finfo->fi_hdir) {
9116+ bend = au_fbend_dir(file);
9117+ for (bindex = au_fbstart(file); bindex <= bend; bindex++)
9118+ au_set_h_fptr(file, bindex, NULL);
9119+ }
1facf9fc 9120+
4f0767ce 9121+out:
1facf9fc 9122+ return err;
9123+}
9124+
4a4d8108
AM
9125+/* common function to regular file and dir */
9126+int au_reval_and_lock_fdi(struct file *file, int (*reopen)(struct file *file),
9127+ int wlock)
dece6358 9128+{
1308ab2a 9129+ int err;
4a4d8108
AM
9130+ unsigned int sigen, figen;
9131+ aufs_bindex_t bstart;
9132+ unsigned char pseudo_link;
9133+ struct dentry *dentry;
9134+ struct inode *inode;
1facf9fc 9135+
4a4d8108
AM
9136+ err = 0;
9137+ dentry = file->f_dentry;
9138+ inode = dentry->d_inode;
9139+ AuDebugOn(au_special_file(inode->i_mode));
9140+ sigen = au_sigen(dentry->d_sb);
9141+ fi_write_lock(file);
9142+ figen = au_figen(file);
9143+ di_write_lock_child(dentry);
9144+ bstart = au_dbstart(dentry);
9145+ pseudo_link = (bstart != au_ibstart(inode));
9146+ if (sigen == figen && !pseudo_link && au_fbstart(file) == bstart) {
9147+ if (!wlock) {
9148+ di_downgrade_lock(dentry, AuLock_IR);
9149+ fi_downgrade_lock(file);
9150+ }
9151+ goto out; /* success */
9152+ }
dece6358 9153+
4a4d8108 9154+ AuDbg("sigen %d, figen %d\n", sigen, figen);
027c5e7a 9155+ if (au_digen_test(dentry, sigen)) {
4a4d8108 9156+ err = au_reval_dpath(dentry, sigen);
027c5e7a 9157+ AuDebugOn(!err && au_digen_test(dentry, sigen));
4a4d8108 9158+ }
dece6358 9159+
027c5e7a
AM
9160+ if (!err)
9161+ err = refresh_file(file, reopen);
4a4d8108
AM
9162+ if (!err) {
9163+ if (!wlock) {
9164+ di_downgrade_lock(dentry, AuLock_IR);
9165+ fi_downgrade_lock(file);
9166+ }
9167+ } else {
9168+ di_write_unlock(dentry);
9169+ fi_write_unlock(file);
9170+ }
1facf9fc 9171+
4f0767ce 9172+out:
1308ab2a 9173+ return err;
9174+}
1facf9fc 9175+
4a4d8108
AM
9176+/* ---------------------------------------------------------------------- */
9177+
9178+/* cf. aufs_nopage() */
9179+/* for madvise(2) */
9180+static int aufs_readpage(struct file *file __maybe_unused, struct page *page)
1308ab2a 9181+{
4a4d8108
AM
9182+ unlock_page(page);
9183+ return 0;
9184+}
1facf9fc 9185+
4a4d8108
AM
9186+/* it will never be called, but necessary to support O_DIRECT */
9187+static ssize_t aufs_direct_IO(int rw, struct kiocb *iocb,
9188+ const struct iovec *iov, loff_t offset,
9189+ unsigned long nr_segs)
9190+{ BUG(); return 0; }
1facf9fc 9191+
4a4d8108
AM
9192+/*
9193+ * it will never be called, but madvise and fadvise behaves differently
9194+ * when get_xip_mem is defined
9195+ */
9196+static int aufs_get_xip_mem(struct address_space *mapping, pgoff_t pgoff,
9197+ int create, void **kmem, unsigned long *pfn)
9198+{ BUG(); return 0; }
1facf9fc 9199+
4a4d8108
AM
9200+/* they will never be called. */
9201+#ifdef CONFIG_AUFS_DEBUG
9202+static int aufs_write_begin(struct file *file, struct address_space *mapping,
9203+ loff_t pos, unsigned len, unsigned flags,
9204+ struct page **pagep, void **fsdata)
9205+{ AuUnsupport(); return 0; }
9206+static int aufs_write_end(struct file *file, struct address_space *mapping,
9207+ loff_t pos, unsigned len, unsigned copied,
9208+ struct page *page, void *fsdata)
9209+{ AuUnsupport(); return 0; }
9210+static int aufs_writepage(struct page *page, struct writeback_control *wbc)
9211+{ AuUnsupport(); return 0; }
1308ab2a 9212+
4a4d8108
AM
9213+static int aufs_set_page_dirty(struct page *page)
9214+{ AuUnsupport(); return 0; }
9215+static void aufs_invalidatepage(struct page *page, unsigned long offset)
9216+{ AuUnsupport(); }
9217+static int aufs_releasepage(struct page *page, gfp_t gfp)
9218+{ AuUnsupport(); return 0; }
9219+static int aufs_migratepage(struct address_space *mapping, struct page *newpage,
9220+ struct page *page)
9221+{ AuUnsupport(); return 0; }
9222+static int aufs_launder_page(struct page *page)
9223+{ AuUnsupport(); return 0; }
9224+static int aufs_is_partially_uptodate(struct page *page,
9225+ read_descriptor_t *desc,
9226+ unsigned long from)
9227+{ AuUnsupport(); return 0; }
9228+static int aufs_error_remove_page(struct address_space *mapping,
9229+ struct page *page)
9230+{ AuUnsupport(); return 0; }
9231+#endif /* CONFIG_AUFS_DEBUG */
9232+
9233+const struct address_space_operations aufs_aop = {
9234+ .readpage = aufs_readpage,
9235+ .direct_IO = aufs_direct_IO,
9236+ .get_xip_mem = aufs_get_xip_mem,
9237+#ifdef CONFIG_AUFS_DEBUG
9238+ .writepage = aufs_writepage,
4a4d8108
AM
9239+ /* no writepages, because of writepage */
9240+ .set_page_dirty = aufs_set_page_dirty,
9241+ /* no readpages, because of readpage */
9242+ .write_begin = aufs_write_begin,
9243+ .write_end = aufs_write_end,
9244+ /* no bmap, no block device */
9245+ .invalidatepage = aufs_invalidatepage,
9246+ .releasepage = aufs_releasepage,
9247+ .migratepage = aufs_migratepage,
9248+ .launder_page = aufs_launder_page,
9249+ .is_partially_uptodate = aufs_is_partially_uptodate,
9250+ .error_remove_page = aufs_error_remove_page
9251+#endif /* CONFIG_AUFS_DEBUG */
dece6358 9252+};
7f207e10
AM
9253diff -urN /usr/share/empty/fs/aufs/file.h linux/fs/aufs/file.h
9254--- /usr/share/empty/fs/aufs/file.h 1970-01-01 01:00:00.000000000 +0100
87a755f4 9255+++ linux/fs/aufs/file.h 2011-07-22 08:26:47.857636522 +0200
2cbb1c4b 9256@@ -0,0 +1,293 @@
4a4d8108 9257+/*
027c5e7a 9258+ * Copyright (C) 2005-2011 Junjiro R. Okajima
4a4d8108
AM
9259+ *
9260+ * This program, aufs is free software; you can redistribute it and/or modify
9261+ * it under the terms of the GNU General Public License as published by
9262+ * the Free Software Foundation; either version 2 of the License, or
9263+ * (at your option) any later version.
9264+ *
9265+ * This program is distributed in the hope that it will be useful,
9266+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
9267+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
9268+ * GNU General Public License for more details.
9269+ *
9270+ * You should have received a copy of the GNU General Public License
9271+ * along with this program; if not, write to the Free Software
9272+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
9273+ */
1facf9fc 9274+
4a4d8108
AM
9275+/*
9276+ * file operations
9277+ */
1facf9fc 9278+
4a4d8108
AM
9279+#ifndef __AUFS_FILE_H__
9280+#define __AUFS_FILE_H__
1facf9fc 9281+
4a4d8108 9282+#ifdef __KERNEL__
1facf9fc 9283+
2cbb1c4b 9284+#include <linux/file.h>
4a4d8108
AM
9285+#include <linux/fs.h>
9286+#include <linux/poll.h>
9287+#include <linux/aufs_type.h>
9288+#include "rwsem.h"
1facf9fc 9289+
4a4d8108
AM
9290+struct au_branch;
9291+struct au_hfile {
9292+ struct file *hf_file;
9293+ struct au_branch *hf_br;
9294+};
1facf9fc 9295+
4a4d8108
AM
9296+struct au_vdir;
9297+struct au_fidir {
9298+ aufs_bindex_t fd_bbot;
9299+ aufs_bindex_t fd_nent;
9300+ struct au_vdir *fd_vdir_cache;
9301+ struct au_hfile fd_hfile[];
9302+};
1facf9fc 9303+
4a4d8108 9304+static inline int au_fidir_sz(int nent)
dece6358 9305+{
4f0767ce
JR
9306+ AuDebugOn(nent < 0);
9307+ return sizeof(struct au_fidir) + sizeof(struct au_hfile) * nent;
4a4d8108 9308+}
1facf9fc 9309+
4a4d8108
AM
9310+struct au_finfo {
9311+ atomic_t fi_generation;
dece6358 9312+
4a4d8108
AM
9313+ struct au_rwsem fi_rwsem;
9314+ aufs_bindex_t fi_btop;
9315+
9316+ /* do not union them */
9317+ struct { /* for non-dir */
9318+ struct au_hfile fi_htop;
2cbb1c4b 9319+ atomic_t fi_mmapped;
4a4d8108
AM
9320+ };
9321+ struct au_fidir *fi_hdir; /* for dir only */
9322+} ____cacheline_aligned_in_smp;
1facf9fc 9323+
4a4d8108 9324+/* ---------------------------------------------------------------------- */
1facf9fc 9325+
4a4d8108
AM
9326+/* file.c */
9327+extern const struct address_space_operations aufs_aop;
9328+unsigned int au_file_roflags(unsigned int flags);
9329+struct file *au_h_open(struct dentry *dentry, aufs_bindex_t bindex, int flags,
9330+ struct file *file);
9331+int au_do_open(struct file *file, int (*open)(struct file *file, int flags),
9332+ struct au_fidir *fidir);
9333+int au_reopen_nondir(struct file *file);
9334+struct au_pin;
9335+int au_ready_to_write(struct file *file, loff_t len, struct au_pin *pin);
9336+int au_reval_and_lock_fdi(struct file *file, int (*reopen)(struct file *file),
9337+ int wlock);
9338+int au_do_flush(struct file *file, fl_owner_t id,
9339+ int (*flush)(struct file *file, fl_owner_t id));
1facf9fc 9340+
4a4d8108
AM
9341+/* poll.c */
9342+#ifdef CONFIG_AUFS_POLL
9343+unsigned int aufs_poll(struct file *file, poll_table *wait);
9344+#endif
1facf9fc 9345+
4a4d8108
AM
9346+#ifdef CONFIG_AUFS_BR_HFSPLUS
9347+/* hfsplus.c */
9348+struct file *au_h_open_pre(struct dentry *dentry, aufs_bindex_t bindex);
9349+void au_h_open_post(struct dentry *dentry, aufs_bindex_t bindex,
9350+ struct file *h_file);
9351+#else
9352+static inline
9353+struct file *au_h_open_pre(struct dentry *dentry, aufs_bindex_t bindex)
dece6358 9354+{
4a4d8108
AM
9355+ return NULL;
9356+}
1facf9fc 9357+
4a4d8108
AM
9358+AuStubVoid(au_h_open_post, struct dentry *dentry, aufs_bindex_t bindex,
9359+ struct file *h_file);
9360+#endif
1facf9fc 9361+
4a4d8108
AM
9362+/* f_op.c */
9363+extern const struct file_operations aufs_file_fop;
4a4d8108
AM
9364+int au_do_open_nondir(struct file *file, int flags);
9365+int aufs_release_nondir(struct inode *inode __maybe_unused, struct file *file);
9366+
9367+#ifdef CONFIG_AUFS_SP_IATTR
9368+/* f_op_sp.c */
9369+int au_special_file(umode_t mode);
9370+void au_init_special_fop(struct inode *inode, umode_t mode, dev_t rdev);
9371+#else
9372+AuStubInt0(au_special_file, umode_t mode)
9373+static inline void au_init_special_fop(struct inode *inode, umode_t mode,
9374+ dev_t rdev)
9375+{
9376+ init_special_inode(inode, mode, rdev);
9377+}
9378+#endif
1facf9fc 9379+
4a4d8108
AM
9380+/* finfo.c */
9381+void au_hfput(struct au_hfile *hf, struct file *file);
9382+void au_set_h_fptr(struct file *file, aufs_bindex_t bindex,
9383+ struct file *h_file);
1facf9fc 9384+
4a4d8108 9385+void au_update_figen(struct file *file);
4a4d8108
AM
9386+struct au_fidir *au_fidir_alloc(struct super_block *sb);
9387+int au_fidir_realloc(struct au_finfo *finfo, int nbr);
1facf9fc 9388+
4a4d8108
AM
9389+void au_fi_init_once(void *_fi);
9390+void au_finfo_fin(struct file *file);
9391+int au_finfo_init(struct file *file, struct au_fidir *fidir);
1facf9fc 9392+
4a4d8108
AM
9393+/* ioctl.c */
9394+long aufs_ioctl_nondir(struct file *file, unsigned int cmd, unsigned long arg);
b752ccd1
AM
9395+#ifdef CONFIG_COMPAT
9396+long aufs_compat_ioctl_dir(struct file *file, unsigned int cmd,
9397+ unsigned long arg);
9398+#endif
1facf9fc 9399+
4a4d8108 9400+/* ---------------------------------------------------------------------- */
1facf9fc 9401+
4a4d8108
AM
9402+static inline struct au_finfo *au_fi(struct file *file)
9403+{
9404+ return file->private_data;
9405+}
1facf9fc 9406+
4a4d8108 9407+/* ---------------------------------------------------------------------- */
1facf9fc 9408+
4a4d8108
AM
9409+/*
9410+ * fi_read_lock, fi_write_lock,
9411+ * fi_read_unlock, fi_write_unlock, fi_downgrade_lock
9412+ */
9413+AuSimpleRwsemFuncs(fi, struct file *f, &au_fi(f)->fi_rwsem);
1308ab2a 9414+
4a4d8108
AM
9415+#define FiMustNoWaiters(f) AuRwMustNoWaiters(&au_fi(f)->fi_rwsem)
9416+#define FiMustAnyLock(f) AuRwMustAnyLock(&au_fi(f)->fi_rwsem)
9417+#define FiMustWriteLock(f) AuRwMustWriteLock(&au_fi(f)->fi_rwsem)
1facf9fc 9418+
1308ab2a 9419+/* ---------------------------------------------------------------------- */
9420+
4a4d8108
AM
9421+/* todo: hard/soft set? */
9422+static inline aufs_bindex_t au_fbstart(struct file *file)
dece6358 9423+{
4a4d8108
AM
9424+ FiMustAnyLock(file);
9425+ return au_fi(file)->fi_btop;
9426+}
dece6358 9427+
4a4d8108
AM
9428+static inline aufs_bindex_t au_fbend_dir(struct file *file)
9429+{
9430+ FiMustAnyLock(file);
9431+ AuDebugOn(!au_fi(file)->fi_hdir);
9432+ return au_fi(file)->fi_hdir->fd_bbot;
9433+}
1facf9fc 9434+
4a4d8108
AM
9435+static inline struct au_vdir *au_fvdir_cache(struct file *file)
9436+{
9437+ FiMustAnyLock(file);
9438+ AuDebugOn(!au_fi(file)->fi_hdir);
9439+ return au_fi(file)->fi_hdir->fd_vdir_cache;
9440+}
1facf9fc 9441+
4a4d8108
AM
9442+static inline void au_set_fbstart(struct file *file, aufs_bindex_t bindex)
9443+{
9444+ FiMustWriteLock(file);
9445+ au_fi(file)->fi_btop = bindex;
9446+}
1facf9fc 9447+
4a4d8108
AM
9448+static inline void au_set_fbend_dir(struct file *file, aufs_bindex_t bindex)
9449+{
9450+ FiMustWriteLock(file);
9451+ AuDebugOn(!au_fi(file)->fi_hdir);
9452+ au_fi(file)->fi_hdir->fd_bbot = bindex;
9453+}
1308ab2a 9454+
4a4d8108
AM
9455+static inline void au_set_fvdir_cache(struct file *file,
9456+ struct au_vdir *vdir_cache)
9457+{
9458+ FiMustWriteLock(file);
9459+ AuDebugOn(!au_fi(file)->fi_hdir);
9460+ au_fi(file)->fi_hdir->fd_vdir_cache = vdir_cache;
9461+}
dece6358 9462+
4a4d8108
AM
9463+static inline struct file *au_hf_top(struct file *file)
9464+{
9465+ FiMustAnyLock(file);
9466+ AuDebugOn(au_fi(file)->fi_hdir);
9467+ return au_fi(file)->fi_htop.hf_file;
9468+}
1facf9fc 9469+
4a4d8108
AM
9470+static inline struct file *au_hf_dir(struct file *file, aufs_bindex_t bindex)
9471+{
9472+ FiMustAnyLock(file);
9473+ AuDebugOn(!au_fi(file)->fi_hdir);
9474+ return au_fi(file)->fi_hdir->fd_hfile[0 + bindex].hf_file;
dece6358
AM
9475+}
9476+
4a4d8108
AM
9477+/* todo: memory barrier? */
9478+static inline unsigned int au_figen(struct file *f)
dece6358 9479+{
4a4d8108
AM
9480+ return atomic_read(&au_fi(f)->fi_generation);
9481+}
dece6358 9482+
2cbb1c4b
JR
9483+static inline void au_set_mmapped(struct file *f)
9484+{
9485+ if (atomic_inc_return(&au_fi(f)->fi_mmapped))
9486+ return;
9487+ pr_warning("fi_mmapped wrapped around\n");
9488+ while (!atomic_inc_return(&au_fi(f)->fi_mmapped))
9489+ ;
9490+}
9491+
9492+static inline void au_unset_mmapped(struct file *f)
9493+{
9494+ atomic_dec(&au_fi(f)->fi_mmapped);
9495+}
9496+
4a4d8108
AM
9497+static inline int au_test_mmapped(struct file *f)
9498+{
2cbb1c4b
JR
9499+ return atomic_read(&au_fi(f)->fi_mmapped);
9500+}
9501+
9502+/* customize vma->vm_file */
9503+
9504+static inline void au_do_vm_file_reset(struct vm_area_struct *vma,
9505+ struct file *file)
9506+{
9507+ fput(vma->vm_file);
9508+ get_file(file);
9509+ vma->vm_file = file;
9510+}
9511+
9512+#ifdef CONFIG_MMU
9513+#define AuDbgVmRegion(file, vma) do {} while (0)
9514+
9515+static inline void au_vm_file_reset(struct vm_area_struct *vma,
9516+ struct file *file)
9517+{
9518+ au_do_vm_file_reset(vma, file);
9519+}
9520+#else
9521+#define AuDbgVmRegion(file, vma) \
9522+ AuDebugOn((vma)->vm_region && (vma)->vm_region->vm_file != (file))
9523+
9524+static inline void au_vm_file_reset(struct vm_area_struct *vma,
9525+ struct file *file)
9526+{
9527+ au_do_vm_file_reset(vma, file);
9528+ fput(vma->vm_region->vm_file);
9529+ get_file(file);
9530+ vma->vm_region->vm_file = file;
9531+}
9532+#endif /* CONFIG_MMU */
9533+
9534+/* handle vma->vm_prfile */
9535+static inline void au_vm_prfile_set(struct vm_area_struct *vma,
9536+ struct file *file)
9537+{
9538+#ifdef CONFIG_AUFS_PROC_MAP
9539+ get_file(file);
9540+ vma->vm_prfile = file;
9541+#ifndef CONFIG_MMU
9542+ get_file(file);
9543+ vma->vm_region->vm_prfile = file;
9544+#endif
9545+#endif
4a4d8108 9546+}
1308ab2a 9547+
4a4d8108
AM
9548+#endif /* __KERNEL__ */
9549+#endif /* __AUFS_FILE_H__ */
7f207e10
AM
9550diff -urN /usr/share/empty/fs/aufs/finfo.c linux/fs/aufs/finfo.c
9551--- /usr/share/empty/fs/aufs/finfo.c 1970-01-01 01:00:00.000000000 +0100
87a755f4 9552+++ linux/fs/aufs/finfo.c 2011-07-22 08:26:47.857636522 +0200
2cbb1c4b 9553@@ -0,0 +1,153 @@
4a4d8108 9554+/*
027c5e7a 9555+ * Copyright (C) 2005-2011 Junjiro R. Okajima
4a4d8108
AM
9556+ *
9557+ * This program, aufs is free software; you can redistribute it and/or modify
9558+ * it under the terms of the GNU General Public License as published by
9559+ * the Free Software Foundation; either version 2 of the License, or
9560+ * (at your option) any later version.
9561+ *
9562+ * This program is distributed in the hope that it will be useful,
9563+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
9564+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
9565+ * GNU General Public License for more details.
9566+ *
9567+ * You should have received a copy of the GNU General Public License
9568+ * along with this program; if not, write to the Free Software
9569+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
9570+ */
1308ab2a 9571+
4a4d8108
AM
9572+/*
9573+ * file private data
9574+ */
1facf9fc 9575+
4a4d8108
AM
9576+#include <linux/file.h>
9577+#include "aufs.h"
1facf9fc 9578+
4a4d8108
AM
9579+void au_hfput(struct au_hfile *hf, struct file *file)
9580+{
9581+ /* todo: direct access f_flags */
2cbb1c4b 9582+ if (vfsub_file_flags(file) & __FMODE_EXEC)
4a4d8108
AM
9583+ allow_write_access(hf->hf_file);
9584+ fput(hf->hf_file);
9585+ hf->hf_file = NULL;
e49829fe 9586+ atomic_dec(&hf->hf_br->br_count);
4a4d8108
AM
9587+ hf->hf_br = NULL;
9588+}
1facf9fc 9589+
4a4d8108
AM
9590+void au_set_h_fptr(struct file *file, aufs_bindex_t bindex, struct file *val)
9591+{
9592+ struct au_finfo *finfo = au_fi(file);
9593+ struct au_hfile *hf;
9594+ struct au_fidir *fidir;
9595+
9596+ fidir = finfo->fi_hdir;
9597+ if (!fidir) {
9598+ AuDebugOn(finfo->fi_btop != bindex);
9599+ hf = &finfo->fi_htop;
9600+ } else
9601+ hf = fidir->fd_hfile + bindex;
9602+
9603+ if (hf && hf->hf_file)
9604+ au_hfput(hf, file);
9605+ if (val) {
9606+ FiMustWriteLock(file);
9607+ hf->hf_file = val;
9608+ hf->hf_br = au_sbr(file->f_dentry->d_sb, bindex);
1308ab2a 9609+ }
4a4d8108 9610+}
1facf9fc 9611+
4a4d8108
AM
9612+void au_update_figen(struct file *file)
9613+{
9614+ atomic_set(&au_fi(file)->fi_generation, au_digen(file->f_dentry));
9615+ /* smp_mb(); */ /* atomic_set */
1facf9fc 9616+}
9617+
4a4d8108
AM
9618+/* ---------------------------------------------------------------------- */
9619+
4a4d8108
AM
9620+struct au_fidir *au_fidir_alloc(struct super_block *sb)
9621+{
9622+ struct au_fidir *fidir;
9623+ int nbr;
9624+
9625+ nbr = au_sbend(sb) + 1;
9626+ if (nbr < 2)
9627+ nbr = 2; /* initial allocate for 2 branches */
9628+ fidir = kzalloc(au_fidir_sz(nbr), GFP_NOFS);
9629+ if (fidir) {
9630+ fidir->fd_bbot = -1;
9631+ fidir->fd_nent = nbr;
9632+ fidir->fd_vdir_cache = NULL;
9633+ }
9634+
9635+ return fidir;
9636+}
9637+
9638+int au_fidir_realloc(struct au_finfo *finfo, int nbr)
9639+{
9640+ int err;
9641+ struct au_fidir *fidir, *p;
9642+
9643+ AuRwMustWriteLock(&finfo->fi_rwsem);
9644+ fidir = finfo->fi_hdir;
9645+ AuDebugOn(!fidir);
9646+
9647+ err = -ENOMEM;
9648+ p = au_kzrealloc(fidir, au_fidir_sz(fidir->fd_nent), au_fidir_sz(nbr),
9649+ GFP_NOFS);
9650+ if (p) {
9651+ p->fd_nent = nbr;
9652+ finfo->fi_hdir = p;
9653+ err = 0;
9654+ }
1facf9fc 9655+
dece6358 9656+ return err;
1facf9fc 9657+}
1308ab2a 9658+
9659+/* ---------------------------------------------------------------------- */
9660+
4a4d8108 9661+void au_finfo_fin(struct file *file)
1308ab2a 9662+{
4a4d8108
AM
9663+ struct au_finfo *finfo;
9664+
7f207e10
AM
9665+ au_nfiles_dec(file->f_dentry->d_sb);
9666+
4a4d8108
AM
9667+ finfo = au_fi(file);
9668+ AuDebugOn(finfo->fi_hdir);
9669+ AuRwDestroy(&finfo->fi_rwsem);
9670+ au_cache_free_finfo(finfo);
1308ab2a 9671+}
1308ab2a 9672+
e49829fe 9673+void au_fi_init_once(void *_finfo)
4a4d8108 9674+{
e49829fe 9675+ struct au_finfo *finfo = _finfo;
2cbb1c4b 9676+ static struct lock_class_key aufs_fi;
1308ab2a 9677+
e49829fe
JR
9678+ au_rw_init(&finfo->fi_rwsem);
9679+ au_rw_class(&finfo->fi_rwsem, &aufs_fi);
4a4d8108 9680+}
1308ab2a 9681+
4a4d8108
AM
9682+int au_finfo_init(struct file *file, struct au_fidir *fidir)
9683+{
9684+ int err;
9685+ struct au_finfo *finfo;
9686+ struct dentry *dentry;
9687+
9688+ err = -ENOMEM;
9689+ dentry = file->f_dentry;
9690+ finfo = au_cache_alloc_finfo();
9691+ if (unlikely(!finfo))
9692+ goto out;
9693+
9694+ err = 0;
7f207e10 9695+ au_nfiles_inc(dentry->d_sb);
4a4d8108
AM
9696+ au_rw_write_lock(&finfo->fi_rwsem);
9697+ finfo->fi_btop = -1;
9698+ finfo->fi_hdir = fidir;
9699+ atomic_set(&finfo->fi_generation, au_digen(dentry));
9700+ /* smp_mb(); */ /* atomic_set */
9701+
9702+ file->private_data = finfo;
9703+
9704+out:
9705+ return err;
9706+}
7f207e10
AM
9707diff -urN /usr/share/empty/fs/aufs/f_op.c linux/fs/aufs/f_op.c
9708--- /usr/share/empty/fs/aufs/f_op.c 1970-01-01 01:00:00.000000000 +0100
87a755f4
AM
9709+++ linux/fs/aufs/f_op.c 2011-07-22 08:26:47.857636522 +0200
9710@@ -0,0 +1,731 @@
dece6358 9711+/*
027c5e7a 9712+ * Copyright (C) 2005-2011 Junjiro R. Okajima
dece6358
AM
9713+ *
9714+ * This program, aufs is free software; you can redistribute it and/or modify
9715+ * it under the terms of the GNU General Public License as published by
9716+ * the Free Software Foundation; either version 2 of the License, or
9717+ * (at your option) any later version.
9718+ *
9719+ * This program is distributed in the hope that it will be useful,
9720+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
9721+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
9722+ * GNU General Public License for more details.
9723+ *
9724+ * You should have received a copy of the GNU General Public License
9725+ * along with this program; if not, write to the Free Software
9726+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
9727+ */
1facf9fc 9728+
9729+/*
4a4d8108 9730+ * file and vm operations
1facf9fc 9731+ */
dece6358
AM
9732+
9733+#include <linux/file.h>
4a4d8108
AM
9734+#include <linux/fs_stack.h>
9735+#include <linux/mman.h>
9736+#include <linux/mm.h>
9737+#include <linux/security.h>
dece6358
AM
9738+#include "aufs.h"
9739+
4a4d8108 9740+int au_do_open_nondir(struct file *file, int flags)
1facf9fc 9741+{
4a4d8108
AM
9742+ int err;
9743+ aufs_bindex_t bindex;
9744+ struct file *h_file;
9745+ struct dentry *dentry;
9746+ struct au_finfo *finfo;
9747+
9748+ FiMustWriteLock(file);
9749+
4a4d8108 9750+ dentry = file->f_dentry;
027c5e7a
AM
9751+ err = au_d_alive(dentry);
9752+ if (unlikely(err))
9753+ goto out;
9754+
4a4d8108
AM
9755+ finfo = au_fi(file);
9756+ memset(&finfo->fi_htop, 0, sizeof(finfo->fi_htop));
2cbb1c4b 9757+ atomic_set(&finfo->fi_mmapped, 0);
4a4d8108
AM
9758+ bindex = au_dbstart(dentry);
9759+ h_file = au_h_open(dentry, bindex, flags, file);
9760+ if (IS_ERR(h_file))
9761+ err = PTR_ERR(h_file);
9762+ else {
9763+ au_set_fbstart(file, bindex);
9764+ au_set_h_fptr(file, bindex, h_file);
9765+ au_update_figen(file);
9766+ /* todo: necessary? */
9767+ /* file->f_ra = h_file->f_ra; */
9768+ }
027c5e7a
AM
9769+
9770+out:
4a4d8108 9771+ return err;
1facf9fc 9772+}
9773+
4a4d8108
AM
9774+static int aufs_open_nondir(struct inode *inode __maybe_unused,
9775+ struct file *file)
1facf9fc 9776+{
4a4d8108 9777+ int err;
1308ab2a 9778+ struct super_block *sb;
1facf9fc 9779+
2cbb1c4b 9780+ AuDbg("%.*s, f_flags 0x%x, f_mode 0x%x\n",
4a4d8108
AM
9781+ AuDLNPair(file->f_dentry), vfsub_file_flags(file),
9782+ file->f_mode);
1facf9fc 9783+
4a4d8108
AM
9784+ sb = file->f_dentry->d_sb;
9785+ si_read_lock(sb, AuLock_FLUSH);
9786+ err = au_do_open(file, au_do_open_nondir, /*fidir*/NULL);
9787+ si_read_unlock(sb);
9788+ return err;
9789+}
1facf9fc 9790+
4a4d8108
AM
9791+int aufs_release_nondir(struct inode *inode __maybe_unused, struct file *file)
9792+{
9793+ struct au_finfo *finfo;
9794+ aufs_bindex_t bindex;
1facf9fc 9795+
4a4d8108
AM
9796+ finfo = au_fi(file);
9797+ bindex = finfo->fi_btop;
0c5527e5
AM
9798+ if (bindex >= 0) {
9799+ /* remove me from sb->s_files */
9800+ file_sb_list_del(file);
4a4d8108 9801+ au_set_h_fptr(file, bindex, NULL);
0c5527e5 9802+ }
7f207e10 9803+
4a4d8108
AM
9804+ au_finfo_fin(file);
9805+ return 0;
1facf9fc 9806+}
9807+
4a4d8108
AM
9808+/* ---------------------------------------------------------------------- */
9809+
9810+static int au_do_flush_nondir(struct file *file, fl_owner_t id)
dece6358 9811+{
1308ab2a 9812+ int err;
4a4d8108
AM
9813+ struct file *h_file;
9814+
9815+ err = 0;
9816+ h_file = au_hf_top(file);
9817+ if (h_file)
9818+ err = vfsub_flush(h_file, id);
9819+ return err;
9820+}
9821+
9822+static int aufs_flush_nondir(struct file *file, fl_owner_t id)
9823+{
9824+ return au_do_flush(file, id, au_do_flush_nondir);
9825+}
9826+
9827+/* ---------------------------------------------------------------------- */
9828+
9829+static ssize_t aufs_read(struct file *file, char __user *buf, size_t count,
9830+ loff_t *ppos)
9831+{
9832+ ssize_t err;
dece6358 9833+ struct dentry *dentry;
4a4d8108 9834+ struct file *h_file;
dece6358 9835+ struct super_block *sb;
1facf9fc 9836+
dece6358
AM
9837+ dentry = file->f_dentry;
9838+ sb = dentry->d_sb;
e49829fe 9839+ si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLMW);
4a4d8108 9840+ err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/0);
dece6358
AM
9841+ if (unlikely(err))
9842+ goto out;
1facf9fc 9843+
4a4d8108
AM
9844+ h_file = au_hf_top(file);
9845+ err = vfsub_read_u(h_file, buf, count, ppos);
9846+ /* todo: necessary? */
9847+ /* file->f_ra = h_file->f_ra; */
9848+ fsstack_copy_attr_atime(dentry->d_inode, h_file->f_dentry->d_inode);
1308ab2a 9849+
4a4d8108
AM
9850+ di_read_unlock(dentry, AuLock_IR);
9851+ fi_read_unlock(file);
4f0767ce 9852+out:
dece6358
AM
9853+ si_read_unlock(sb);
9854+ return err;
9855+}
1facf9fc 9856+
e49829fe
JR
9857+/*
9858+ * todo: very ugly
9859+ * it locks both of i_mutex and si_rwsem for read in safe.
9860+ * if the plink maintenance mode continues forever (that is the problem),
9861+ * may loop forever.
9862+ */
9863+static void au_mtx_and_read_lock(struct inode *inode)
9864+{
9865+ int err;
9866+ struct super_block *sb = inode->i_sb;
9867+
9868+ while (1) {
9869+ mutex_lock(&inode->i_mutex);
9870+ err = si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLM);
9871+ if (!err)
9872+ break;
9873+ mutex_unlock(&inode->i_mutex);
9874+ si_read_lock(sb, AuLock_NOPLMW);
9875+ si_read_unlock(sb);
9876+ }
9877+}
9878+
4a4d8108
AM
9879+static ssize_t aufs_write(struct file *file, const char __user *ubuf,
9880+ size_t count, loff_t *ppos)
dece6358 9881+{
4a4d8108
AM
9882+ ssize_t err;
9883+ struct au_pin pin;
dece6358 9884+ struct dentry *dentry;
4a4d8108 9885+ struct inode *inode;
4a4d8108
AM
9886+ struct file *h_file;
9887+ char __user *buf = (char __user *)ubuf;
1facf9fc 9888+
dece6358 9889+ dentry = file->f_dentry;
4a4d8108 9890+ inode = dentry->d_inode;
e49829fe 9891+ au_mtx_and_read_lock(inode);
1facf9fc 9892+
4a4d8108
AM
9893+ err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/1);
9894+ if (unlikely(err))
9895+ goto out;
1facf9fc 9896+
4a4d8108
AM
9897+ err = au_ready_to_write(file, -1, &pin);
9898+ di_downgrade_lock(dentry, AuLock_IR);
9899+ if (unlikely(err))
9900+ goto out_unlock;
1facf9fc 9901+
4a4d8108
AM
9902+ h_file = au_hf_top(file);
9903+ au_unpin(&pin);
9904+ err = vfsub_write_u(h_file, buf, count, ppos);
9905+ au_cpup_attr_timesizes(inode);
9906+ inode->i_mode = h_file->f_dentry->d_inode->i_mode;
1facf9fc 9907+
4f0767ce 9908+out_unlock:
4a4d8108
AM
9909+ di_read_unlock(dentry, AuLock_IR);
9910+ fi_write_unlock(file);
4f0767ce 9911+out:
e49829fe 9912+ si_read_unlock(inode->i_sb);
4a4d8108 9913+ mutex_unlock(&inode->i_mutex);
dece6358
AM
9914+ return err;
9915+}
1facf9fc 9916+
4a4d8108
AM
9917+static ssize_t au_do_aio(struct file *h_file, int rw, struct kiocb *kio,
9918+ const struct iovec *iov, unsigned long nv, loff_t pos)
dece6358 9919+{
4a4d8108
AM
9920+ ssize_t err;
9921+ struct file *file;
9922+ ssize_t (*func)(struct kiocb *, const struct iovec *, unsigned long,
9923+ loff_t);
1facf9fc 9924+
4a4d8108
AM
9925+ err = security_file_permission(h_file, rw);
9926+ if (unlikely(err))
9927+ goto out;
1facf9fc 9928+
4a4d8108
AM
9929+ err = -ENOSYS;
9930+ func = NULL;
9931+ if (rw == MAY_READ)
9932+ func = h_file->f_op->aio_read;
9933+ else if (rw == MAY_WRITE)
9934+ func = h_file->f_op->aio_write;
9935+ if (func) {
9936+ file = kio->ki_filp;
9937+ kio->ki_filp = h_file;
2cbb1c4b 9938+ lockdep_off();
4a4d8108 9939+ err = func(kio, iov, nv, pos);
2cbb1c4b 9940+ lockdep_on();
4a4d8108
AM
9941+ kio->ki_filp = file;
9942+ } else
9943+ /* currently there is no such fs */
9944+ WARN_ON_ONCE(1);
1facf9fc 9945+
4f0767ce 9946+out:
dece6358
AM
9947+ return err;
9948+}
1facf9fc 9949+
4a4d8108
AM
9950+static ssize_t aufs_aio_read(struct kiocb *kio, const struct iovec *iov,
9951+ unsigned long nv, loff_t pos)
1facf9fc 9952+{
4a4d8108
AM
9953+ ssize_t err;
9954+ struct file *file, *h_file;
9955+ struct dentry *dentry;
dece6358 9956+ struct super_block *sb;
1facf9fc 9957+
4a4d8108 9958+ file = kio->ki_filp;
dece6358 9959+ dentry = file->f_dentry;
1308ab2a 9960+ sb = dentry->d_sb;
e49829fe 9961+ si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLMW);
4a4d8108
AM
9962+ err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/0);
9963+ if (unlikely(err))
9964+ goto out;
9965+
9966+ h_file = au_hf_top(file);
9967+ err = au_do_aio(h_file, MAY_READ, kio, iov, nv, pos);
9968+ /* todo: necessary? */
9969+ /* file->f_ra = h_file->f_ra; */
9970+ fsstack_copy_attr_atime(dentry->d_inode, h_file->f_dentry->d_inode);
9971+ di_read_unlock(dentry, AuLock_IR);
9972+ fi_read_unlock(file);
1facf9fc 9973+
4f0767ce 9974+out:
4a4d8108 9975+ si_read_unlock(sb);
1308ab2a 9976+ return err;
9977+}
1facf9fc 9978+
4a4d8108
AM
9979+static ssize_t aufs_aio_write(struct kiocb *kio, const struct iovec *iov,
9980+ unsigned long nv, loff_t pos)
1308ab2a 9981+{
4a4d8108
AM
9982+ ssize_t err;
9983+ struct au_pin pin;
9984+ struct dentry *dentry;
9985+ struct inode *inode;
4a4d8108 9986+ struct file *file, *h_file;
1308ab2a 9987+
4a4d8108 9988+ file = kio->ki_filp;
1308ab2a 9989+ dentry = file->f_dentry;
1308ab2a 9990+ inode = dentry->d_inode;
e49829fe
JR
9991+ au_mtx_and_read_lock(inode);
9992+
4a4d8108
AM
9993+ err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/1);
9994+ if (unlikely(err))
1308ab2a 9995+ goto out;
1facf9fc 9996+
4a4d8108
AM
9997+ err = au_ready_to_write(file, -1, &pin);
9998+ di_downgrade_lock(dentry, AuLock_IR);
dece6358 9999+ if (unlikely(err))
4a4d8108 10000+ goto out_unlock;
1facf9fc 10001+
4a4d8108
AM
10002+ au_unpin(&pin);
10003+ h_file = au_hf_top(file);
10004+ err = au_do_aio(h_file, MAY_WRITE, kio, iov, nv, pos);
10005+ au_cpup_attr_timesizes(inode);
10006+ inode->i_mode = h_file->f_dentry->d_inode->i_mode;
1facf9fc 10007+
4f0767ce 10008+out_unlock:
4a4d8108
AM
10009+ di_read_unlock(dentry, AuLock_IR);
10010+ fi_write_unlock(file);
4f0767ce 10011+out:
e49829fe 10012+ si_read_unlock(inode->i_sb);
4a4d8108 10013+ mutex_unlock(&inode->i_mutex);
dece6358 10014+ return err;
1facf9fc 10015+}
10016+
4a4d8108
AM
10017+static ssize_t aufs_splice_read(struct file *file, loff_t *ppos,
10018+ struct pipe_inode_info *pipe, size_t len,
10019+ unsigned int flags)
1facf9fc 10020+{
4a4d8108
AM
10021+ ssize_t err;
10022+ struct file *h_file;
10023+ struct dentry *dentry;
dece6358 10024+ struct super_block *sb;
1facf9fc 10025+
dece6358 10026+ dentry = file->f_dentry;
dece6358 10027+ sb = dentry->d_sb;
e49829fe 10028+ si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLMW);
4a4d8108
AM
10029+ err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/0);
10030+ if (unlikely(err))
dece6358 10031+ goto out;
1facf9fc 10032+
4a4d8108
AM
10033+ err = -EINVAL;
10034+ h_file = au_hf_top(file);
10035+ if (au_test_loopback_kthread()) {
87a755f4
AM
10036+ au_warn_loopback(h_file->f_dentry->d_sb);
10037+ if (file->f_mapping != h_file->f_mapping) {
10038+ file->f_mapping = h_file->f_mapping;
10039+ smp_mb(); /* unnecessary? */
10040+ }
1308ab2a 10041+ }
4a4d8108
AM
10042+ err = vfsub_splice_to(h_file, ppos, pipe, len, flags);
10043+ /* todo: necessasry? */
10044+ /* file->f_ra = h_file->f_ra; */
10045+ fsstack_copy_attr_atime(dentry->d_inode, h_file->f_dentry->d_inode);
1facf9fc 10046+
4a4d8108
AM
10047+ di_read_unlock(dentry, AuLock_IR);
10048+ fi_read_unlock(file);
1facf9fc 10049+
4f0767ce 10050+out:
4a4d8108 10051+ si_read_unlock(sb);
dece6358 10052+ return err;
1facf9fc 10053+}
10054+
4a4d8108
AM
10055+static ssize_t
10056+aufs_splice_write(struct pipe_inode_info *pipe, struct file *file, loff_t *ppos,
10057+ size_t len, unsigned int flags)
1facf9fc 10058+{
4a4d8108
AM
10059+ ssize_t err;
10060+ struct au_pin pin;
10061+ struct dentry *dentry;
10062+ struct inode *inode;
4a4d8108 10063+ struct file *h_file;
1facf9fc 10064+
4a4d8108
AM
10065+ dentry = file->f_dentry;
10066+ inode = dentry->d_inode;
e49829fe 10067+ au_mtx_and_read_lock(inode);
4a4d8108
AM
10068+ err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/1);
10069+ if (unlikely(err))
10070+ goto out;
1facf9fc 10071+
4a4d8108
AM
10072+ err = au_ready_to_write(file, -1, &pin);
10073+ di_downgrade_lock(dentry, AuLock_IR);
10074+ if (unlikely(err))
10075+ goto out_unlock;
1facf9fc 10076+
4a4d8108
AM
10077+ h_file = au_hf_top(file);
10078+ au_unpin(&pin);
10079+ err = vfsub_splice_from(pipe, h_file, ppos, len, flags);
10080+ au_cpup_attr_timesizes(inode);
10081+ inode->i_mode = h_file->f_dentry->d_inode->i_mode;
1facf9fc 10082+
4f0767ce 10083+out_unlock:
4a4d8108
AM
10084+ di_read_unlock(dentry, AuLock_IR);
10085+ fi_write_unlock(file);
4f0767ce 10086+out:
e49829fe 10087+ si_read_unlock(inode->i_sb);
4a4d8108
AM
10088+ mutex_unlock(&inode->i_mutex);
10089+ return err;
10090+}
1facf9fc 10091+
4a4d8108
AM
10092+/* ---------------------------------------------------------------------- */
10093+
4a4d8108
AM
10094+/* cf. linux/include/linux/mman.h: calc_vm_prot_bits() */
10095+#define AuConv_VM_PROT(f, b) _calc_vm_trans(f, VM_##b, PROT_##b)
1308ab2a 10096+
4a4d8108 10097+static unsigned long au_arch_prot_conv(unsigned long flags)
dece6358 10098+{
4a4d8108
AM
10099+ /* currently ppc64 only */
10100+#ifdef CONFIG_PPC64
10101+ /* cf. linux/arch/powerpc/include/asm/mman.h */
10102+ AuDebugOn(arch_calc_vm_prot_bits(-1) != VM_SAO);
10103+ return AuConv_VM_PROT(flags, SAO);
10104+#else
10105+ AuDebugOn(arch_calc_vm_prot_bits(-1));
10106+ return 0;
10107+#endif
dece6358
AM
10108+}
10109+
4a4d8108 10110+static unsigned long au_prot_conv(unsigned long flags)
dece6358 10111+{
4a4d8108
AM
10112+ return AuConv_VM_PROT(flags, READ)
10113+ | AuConv_VM_PROT(flags, WRITE)
10114+ | AuConv_VM_PROT(flags, EXEC)
10115+ | au_arch_prot_conv(flags);
dece6358
AM
10116+}
10117+
4a4d8108
AM
10118+/* cf. linux/include/linux/mman.h: calc_vm_flag_bits() */
10119+#define AuConv_VM_MAP(f, b) _calc_vm_trans(f, VM_##b, MAP_##b)
dece6358 10120+
4a4d8108 10121+static unsigned long au_flag_conv(unsigned long flags)
dece6358 10122+{
4a4d8108
AM
10123+ return AuConv_VM_MAP(flags, GROWSDOWN)
10124+ | AuConv_VM_MAP(flags, DENYWRITE)
10125+ | AuConv_VM_MAP(flags, EXECUTABLE)
10126+ | AuConv_VM_MAP(flags, LOCKED);
dece6358 10127+}
1308ab2a 10128+/*
4a4d8108
AM
10129+ * This is another ugly approach to keep the lock order, particularly
10130+ * mm->mmap_sem and aufs rwsem. The previous approach was reverted and you can
10131+ * find it in git-log, if you want.
1308ab2a 10132+ *
4a4d8108
AM
10133+ * native readdir: i_mutex, copy_to_user, mmap_sem
10134+ * aufs readdir: i_mutex, rwsem, nested-i_mutex, copy_to_user, mmap_sem
1308ab2a 10135+ *
4a4d8108
AM
10136+ * Before aufs_mmap() mmap_sem is acquired already, but aufs_mmap() has to
10137+ * acquire aufs rwsem. It introduces a circular locking dependency.
10138+ * To address this problem, aufs_mmap() delegates the part which requires aufs
10139+ * rwsem to its internal workqueue.
1308ab2a 10140+ */
10141+
4a4d8108
AM
10142+struct au_mmap_pre_args {
10143+ /* input */
10144+ struct file *file;
10145+ struct vm_area_struct *vma;
1308ab2a 10146+
4a4d8108
AM
10147+ /* output */
10148+ int *errp;
10149+ struct file *h_file;
10150+ struct au_branch *br;
4a4d8108 10151+};
dece6358 10152+
4a4d8108 10153+static int au_mmap_pre(struct file *file, struct vm_area_struct *vma,
2cbb1c4b 10154+ struct file **h_file, struct au_branch **br)
dece6358 10155+{
4a4d8108
AM
10156+ int err;
10157+ aufs_bindex_t bstart;
10158+ const unsigned char wlock
10159+ = !!(file->f_mode & FMODE_WRITE) && (vma->vm_flags & VM_SHARED);
10160+ struct dentry *dentry;
10161+ struct super_block *sb;
1308ab2a 10162+
4a4d8108
AM
10163+ dentry = file->f_dentry;
10164+ sb = dentry->d_sb;
e49829fe 10165+ si_read_lock(sb, AuLock_NOPLMW);
4a4d8108
AM
10166+ err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/1);
10167+ if (unlikely(err))
10168+ goto out;
10169+
4a4d8108
AM
10170+ if (wlock) {
10171+ struct au_pin pin;
10172+
10173+ err = au_ready_to_write(file, -1, &pin);
10174+ di_write_unlock(dentry);
10175+ if (unlikely(err))
10176+ goto out_unlock;
10177+ au_unpin(&pin);
10178+ } else
10179+ di_write_unlock(dentry);
10180+ bstart = au_fbstart(file);
10181+ *br = au_sbr(sb, bstart);
10182+ *h_file = au_hf_top(file);
10183+ get_file(*h_file);
2cbb1c4b 10184+ au_set_mmapped(file);
4a4d8108
AM
10185+
10186+out_unlock:
10187+ fi_write_unlock(file);
10188+out:
10189+ si_read_unlock(sb);
10190+ return err;
dece6358
AM
10191+}
10192+
4a4d8108 10193+static void au_call_mmap_pre(void *args)
dece6358 10194+{
4a4d8108 10195+ struct au_mmap_pre_args *a = args;
2cbb1c4b 10196+ *a->errp = au_mmap_pre(a->file, a->vma, &a->h_file, &a->br);
dece6358
AM
10197+}
10198+
4a4d8108 10199+static int aufs_mmap(struct file *file, struct vm_area_struct *vma)
dece6358 10200+{
4a4d8108 10201+ int err, wkq_err;
2cbb1c4b 10202+ unsigned long prot;
4a4d8108
AM
10203+ struct au_mmap_pre_args args = {
10204+ .file = file,
10205+ .vma = vma,
10206+ .errp = &err
10207+ };
10208+
2cbb1c4b 10209+ AuDbgVmRegion(file, vma);
b752ccd1 10210+ wkq_err = au_wkq_wait_pre(au_call_mmap_pre, &args);
4a4d8108
AM
10211+ if (unlikely(wkq_err))
10212+ err = wkq_err;
10213+ if (unlikely(err))
10214+ goto out;
1308ab2a 10215+
2cbb1c4b
JR
10216+ au_vm_file_reset(vma, args.h_file);
10217+ prot = au_prot_conv(vma->vm_flags);
10218+ err = security_file_mmap(args.h_file, /*reqprot*/prot, prot,
10219+ au_flag_conv(vma->vm_flags), vma->vm_start, 0);
4a4d8108 10220+ if (unlikely(err))
2cbb1c4b 10221+ goto out_reset;
4a4d8108 10222+
2cbb1c4b
JR
10223+ err = args.h_file->f_op->mmap(args.h_file, vma);
10224+ if (unlikely(err))
10225+ goto out_reset;
4a4d8108 10226+
2cbb1c4b 10227+ au_vm_prfile_set(vma, file);
4a4d8108
AM
10228+ vfsub_file_accessed(args.h_file);
10229+ /* update without lock, I don't think it a problem */
2cbb1c4b
JR
10230+ fsstack_copy_attr_atime(file->f_dentry->d_inode,
10231+ args.h_file->f_dentry->d_inode);
10232+ goto out_fput; /* success */
4a4d8108 10233+
2cbb1c4b
JR
10234+out_reset:
10235+ au_unset_mmapped(file);
10236+ au_vm_file_reset(vma, file);
10237+out_fput:
4a4d8108 10238+ fput(args.h_file);
4f0767ce 10239+out:
4a4d8108
AM
10240+ return err;
10241+}
10242+
10243+/* ---------------------------------------------------------------------- */
10244+
b752ccd1 10245+static int aufs_fsync_nondir(struct file *file, int datasync)
4a4d8108
AM
10246+{
10247+ int err;
10248+ struct au_pin pin;
b752ccd1 10249+ struct dentry *dentry;
4a4d8108
AM
10250+ struct inode *inode;
10251+ struct file *h_file;
10252+ struct super_block *sb;
10253+
b752ccd1 10254+ dentry = file->f_dentry;
4a4d8108
AM
10255+ inode = dentry->d_inode;
10256+ IMustLock(file->f_mapping->host);
10257+ if (inode != file->f_mapping->host) {
10258+ mutex_unlock(&file->f_mapping->host->i_mutex);
10259+ mutex_lock(&inode->i_mutex);
10260+ }
10261+ IMustLock(inode);
10262+
10263+ sb = dentry->d_sb;
e49829fe
JR
10264+ err = si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLM);
10265+ if (unlikely(err))
10266+ goto out;
4a4d8108
AM
10267+
10268+ err = 0; /* -EBADF; */ /* posix? */
10269+ if (unlikely(!(file->f_mode & FMODE_WRITE)))
e49829fe 10270+ goto out_si;
4a4d8108
AM
10271+ err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/1);
10272+ if (unlikely(err))
e49829fe 10273+ goto out_si;
4a4d8108
AM
10274+
10275+ err = au_ready_to_write(file, -1, &pin);
10276+ di_downgrade_lock(dentry, AuLock_IR);
10277+ if (unlikely(err))
10278+ goto out_unlock;
10279+ au_unpin(&pin);
10280+
10281+ err = -EINVAL;
10282+ h_file = au_hf_top(file);
10283+ if (h_file->f_op && h_file->f_op->fsync) {
4a4d8108
AM
10284+ struct mutex *h_mtx;
10285+
10286+ /*
10287+ * no filemap_fdatawrite() since aufs file has no its own
10288+ * mapping, but dir.
10289+ */
b752ccd1 10290+ h_mtx = &h_file->f_dentry->d_inode->i_mutex;
4a4d8108 10291+ mutex_lock_nested(h_mtx, AuLsc_I_CHILD);
b752ccd1 10292+ err = h_file->f_op->fsync(h_file, datasync);
4a4d8108
AM
10293+ if (!err)
10294+ vfsub_update_h_iattr(&h_file->f_path, /*did*/NULL);
10295+ /*ignore*/
10296+ au_cpup_attr_timesizes(inode);
10297+ mutex_unlock(h_mtx);
10298+ }
10299+
4f0767ce 10300+out_unlock:
4a4d8108 10301+ di_read_unlock(dentry, AuLock_IR);
1308ab2a 10302+ fi_write_unlock(file);
e49829fe 10303+out_si:
953406b4 10304+ si_read_unlock(sb);
e49829fe 10305+out:
4a4d8108
AM
10306+ if (inode != file->f_mapping->host) {
10307+ mutex_unlock(&inode->i_mutex);
10308+ mutex_lock(&file->f_mapping->host->i_mutex);
10309+ }
10310+ return err;
dece6358
AM
10311+}
10312+
4a4d8108
AM
10313+/* no one supports this operation, currently */
10314+#if 0
10315+static int aufs_aio_fsync_nondir(struct kiocb *kio, int datasync)
dece6358 10316+{
4a4d8108
AM
10317+ int err;
10318+ struct au_pin pin;
1308ab2a 10319+ struct dentry *dentry;
4a4d8108
AM
10320+ struct inode *inode;
10321+ struct file *file, *h_file;
1308ab2a 10322+
4a4d8108 10323+ file = kio->ki_filp;
1308ab2a 10324+ dentry = file->f_dentry;
4a4d8108 10325+ inode = dentry->d_inode;
e49829fe 10326+ au_mtx_and_read_lock(inode);
4a4d8108
AM
10327+
10328+ err = 0; /* -EBADF; */ /* posix? */
10329+ if (unlikely(!(file->f_mode & FMODE_WRITE)))
10330+ goto out;
10331+ err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/1);
10332+ if (unlikely(err))
1308ab2a 10333+ goto out;
10334+
4a4d8108
AM
10335+ err = au_ready_to_write(file, -1, &pin);
10336+ di_downgrade_lock(dentry, AuLock_IR);
10337+ if (unlikely(err))
10338+ goto out_unlock;
10339+ au_unpin(&pin);
1308ab2a 10340+
4a4d8108
AM
10341+ err = -ENOSYS;
10342+ h_file = au_hf_top(file);
10343+ if (h_file->f_op && h_file->f_op->aio_fsync) {
10344+ struct dentry *h_d;
10345+ struct mutex *h_mtx;
1308ab2a 10346+
4a4d8108
AM
10347+ h_d = h_file->f_dentry;
10348+ h_mtx = &h_d->d_inode->i_mutex;
10349+ if (!is_sync_kiocb(kio)) {
10350+ get_file(h_file);
10351+ fput(file);
10352+ }
10353+ kio->ki_filp = h_file;
10354+ err = h_file->f_op->aio_fsync(kio, datasync);
10355+ mutex_lock_nested(h_mtx, AuLsc_I_CHILD);
10356+ if (!err)
10357+ vfsub_update_h_iattr(&h_file->f_path, /*did*/NULL);
10358+ /*ignore*/
10359+ au_cpup_attr_timesizes(inode);
10360+ mutex_unlock(h_mtx);
10361+ }
1308ab2a 10362+
4f0767ce 10363+out_unlock:
4a4d8108
AM
10364+ di_read_unlock(dentry, AuLock_IR);
10365+ fi_write_unlock(file);
4f0767ce 10366+out:
e49829fe 10367+ si_read_unlock(inode->sb);
4a4d8108
AM
10368+ mutex_unlock(&inode->i_mutex);
10369+ return err;
dece6358 10370+}
4a4d8108 10371+#endif
dece6358 10372+
4a4d8108 10373+static int aufs_fasync(int fd, struct file *file, int flag)
dece6358 10374+{
4a4d8108
AM
10375+ int err;
10376+ struct file *h_file;
10377+ struct dentry *dentry;
10378+ struct super_block *sb;
1308ab2a 10379+
4a4d8108
AM
10380+ dentry = file->f_dentry;
10381+ sb = dentry->d_sb;
e49829fe 10382+ si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLMW);
4a4d8108
AM
10383+ err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/0);
10384+ if (unlikely(err))
10385+ goto out;
10386+
10387+ h_file = au_hf_top(file);
10388+ if (h_file->f_op && h_file->f_op->fasync)
10389+ err = h_file->f_op->fasync(fd, h_file, flag);
10390+
10391+ di_read_unlock(dentry, AuLock_IR);
10392+ fi_read_unlock(file);
1308ab2a 10393+
4f0767ce 10394+out:
4a4d8108 10395+ si_read_unlock(sb);
1308ab2a 10396+ return err;
dece6358 10397+}
4a4d8108
AM
10398+
10399+/* ---------------------------------------------------------------------- */
10400+
10401+/* no one supports this operation, currently */
10402+#if 0
10403+static ssize_t aufs_sendpage(struct file *file, struct page *page, int offset,
10404+ size_t len, loff_t *pos , int more)
10405+{
10406+}
10407+#endif
10408+
10409+/* ---------------------------------------------------------------------- */
10410+
10411+const struct file_operations aufs_file_fop = {
10412+ .owner = THIS_MODULE,
2cbb1c4b 10413+
027c5e7a 10414+ .llseek = default_llseek,
4a4d8108
AM
10415+
10416+ .read = aufs_read,
10417+ .write = aufs_write,
10418+ .aio_read = aufs_aio_read,
10419+ .aio_write = aufs_aio_write,
10420+#ifdef CONFIG_AUFS_POLL
10421+ .poll = aufs_poll,
10422+#endif
10423+ .unlocked_ioctl = aufs_ioctl_nondir,
b752ccd1
AM
10424+#ifdef CONFIG_COMPAT
10425+ .compat_ioctl = aufs_ioctl_nondir, /* same */
10426+#endif
4a4d8108
AM
10427+ .mmap = aufs_mmap,
10428+ .open = aufs_open_nondir,
10429+ .flush = aufs_flush_nondir,
10430+ .release = aufs_release_nondir,
10431+ .fsync = aufs_fsync_nondir,
10432+ /* .aio_fsync = aufs_aio_fsync_nondir, */
10433+ .fasync = aufs_fasync,
10434+ /* .sendpage = aufs_sendpage, */
10435+ .splice_write = aufs_splice_write,
10436+ .splice_read = aufs_splice_read,
10437+#if 0
10438+ .aio_splice_write = aufs_aio_splice_write,
10439+ .aio_splice_read = aufs_aio_splice_read
10440+#endif
10441+};
7f207e10
AM
10442diff -urN /usr/share/empty/fs/aufs/f_op_sp.c linux/fs/aufs/f_op_sp.c
10443--- /usr/share/empty/fs/aufs/f_op_sp.c 1970-01-01 01:00:00.000000000 +0100
87a755f4 10444+++ linux/fs/aufs/f_op_sp.c 2011-03-17 10:46:59.000000000 +0100
e49829fe 10445@@ -0,0 +1,299 @@
1308ab2a 10446+/*
027c5e7a 10447+ * Copyright (C) 2005-2011 Junjiro R. Okajima
1308ab2a 10448+ *
10449+ * This program, aufs is free software; you can redistribute it and/or modify
10450+ * it under the terms of the GNU General Public License as published by
10451+ * the Free Software Foundation; either version 2 of the License, or
10452+ * (at your option) any later version.
10453+ *
10454+ * This program is distributed in the hope that it will be useful,
10455+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
10456+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10457+ * GNU General Public License for more details.
10458+ *
10459+ * You should have received a copy of the GNU General Public License
10460+ * along with this program; if not, write to the Free Software
10461+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
10462+ */
dece6358 10463+
1308ab2a 10464+/*
4a4d8108
AM
10465+ * file operations for special files.
10466+ * while they exist in aufs virtually,
10467+ * their file I/O is handled out of aufs.
1308ab2a 10468+ */
10469+
4a4d8108
AM
10470+#include <linux/fs_stack.h>
10471+#include "aufs.h"
1308ab2a 10472+
4a4d8108
AM
10473+static ssize_t aufs_aio_read_sp(struct kiocb *kio, const struct iovec *iov,
10474+ unsigned long nv, loff_t pos)
dece6358 10475+{
4a4d8108
AM
10476+ ssize_t err;
10477+ aufs_bindex_t bstart;
10478+ unsigned char wbr;
10479+ struct file *file, *h_file;
10480+ struct super_block *sb;
1308ab2a 10481+
4a4d8108
AM
10482+ file = kio->ki_filp;
10483+ sb = file->f_dentry->d_sb;
10484+ si_read_lock(sb, AuLock_FLUSH);
10485+ fi_read_lock(file);
10486+ bstart = au_fbstart(file);
10487+ h_file = au_hf_top(file);
10488+ fi_read_unlock(file);
10489+ wbr = !!au_br_writable(au_sbr(sb, bstart)->br_perm);
10490+ si_read_unlock(sb);
10491+
10492+ /* do not change the file in kio */
10493+ AuDebugOn(!h_file->f_op || !h_file->f_op->aio_read);
10494+ err = h_file->f_op->aio_read(kio, iov, nv, pos);
10495+ if (err > 0 && wbr)
10496+ file_accessed(h_file);
10497+
10498+ return err;
10499+}
10500+
10501+static ssize_t aufs_aio_write_sp(struct kiocb *kio, const struct iovec *iov,
10502+ unsigned long nv, loff_t pos)
10503+{
10504+ ssize_t err;
10505+ aufs_bindex_t bstart;
10506+ unsigned char wbr;
10507+ struct super_block *sb;
10508+ struct file *file, *h_file;
10509+
10510+ file = kio->ki_filp;
10511+ sb = file->f_dentry->d_sb;
10512+ si_read_lock(sb, AuLock_FLUSH);
10513+ fi_read_lock(file);
10514+ bstart = au_fbstart(file);
10515+ h_file = au_hf_top(file);
10516+ fi_read_unlock(file);
10517+ wbr = !!au_br_writable(au_sbr(sb, bstart)->br_perm);
10518+ si_read_unlock(sb);
10519+
10520+ /* do not change the file in kio */
10521+ AuDebugOn(!h_file->f_op || !h_file->f_op->aio_write);
10522+ err = h_file->f_op->aio_write(kio, iov, nv, pos);
10523+ if (err > 0 && wbr)
10524+ file_update_time(h_file);
10525+
10526+ return err;
10527+}
10528+
10529+/* ---------------------------------------------------------------------- */
10530+
10531+static int aufs_release_sp(struct inode *inode, struct file *file)
10532+{
10533+ int err;
10534+ struct file *h_file;
10535+
10536+ fi_read_lock(file);
10537+ h_file = au_hf_top(file);
10538+ fi_read_unlock(file);
10539+ /* close this fifo in aufs */
10540+ err = h_file->f_op->release(inode, file); /* ignore */
10541+ aufs_release_nondir(inode, file); /* ignore */
10542+ return err;
10543+}
10544+
10545+/* ---------------------------------------------------------------------- */
10546+
10547+/* currently, support only FIFO */
4f0767ce
JR
10548+enum {
10549+ AuSp_FIFO, AuSp_FIFO_R, AuSp_FIFO_W, AuSp_FIFO_RW,
10550+ /* AuSp_SOCK, AuSp_CHR, AuSp_BLK, */
10551+ AuSp_Last
10552+};
4a4d8108
AM
10553+static int aufs_open_sp(struct inode *inode, struct file *file);
10554+static struct au_sp_fop {
10555+ int done;
10556+ struct file_operations fop; /* not 'const' */
10557+ spinlock_t spin;
10558+} au_sp_fop[AuSp_Last] = {
10559+ [AuSp_FIFO] = {
10560+ .fop = {
10561+ .owner = THIS_MODULE,
10562+ .open = aufs_open_sp
10563+ }
10564+ }
10565+};
10566+
10567+static void au_init_fop_sp(struct file *file)
10568+{
10569+ struct au_sp_fop *p;
10570+ int i;
10571+ struct file *h_file;
10572+
10573+ p = au_sp_fop;
10574+ if (unlikely(!p->done)) {
10575+ /* initialize first time only */
10576+ static DEFINE_SPINLOCK(spin);
10577+
10578+ spin_lock(&spin);
10579+ if (!p->done) {
10580+ BUILD_BUG_ON(sizeof(au_sp_fop)/sizeof(*au_sp_fop)
10581+ != AuSp_Last);
10582+ for (i = 0; i < AuSp_Last; i++)
10583+ spin_lock_init(&p[i].spin);
10584+ p->done = 1;
10585+ }
10586+ spin_unlock(&spin);
10587+ }
10588+
10589+ switch (file->f_mode & (FMODE_READ | FMODE_WRITE)) {
10590+ case FMODE_READ:
10591+ i = AuSp_FIFO_R;
10592+ break;
10593+ case FMODE_WRITE:
10594+ i = AuSp_FIFO_W;
10595+ break;
10596+ case FMODE_READ | FMODE_WRITE:
10597+ i = AuSp_FIFO_RW;
10598+ break;
10599+ default:
10600+ BUG();
10601+ }
10602+
10603+ p += i;
10604+ if (unlikely(!p->done)) {
10605+ /* initialize first time only */
10606+ h_file = au_hf_top(file);
10607+ spin_lock(&p->spin);
10608+ if (!p->done) {
10609+ p->fop = *h_file->f_op;
10610+ p->fop.owner = THIS_MODULE;
10611+ if (p->fop.aio_read)
10612+ p->fop.aio_read = aufs_aio_read_sp;
10613+ if (p->fop.aio_write)
10614+ p->fop.aio_write = aufs_aio_write_sp;
10615+ p->fop.release = aufs_release_sp;
10616+ p->done = 1;
10617+ }
10618+ spin_unlock(&p->spin);
10619+ }
10620+ file->f_op = &p->fop;
10621+}
10622+
10623+static int au_cpup_sp(struct dentry *dentry)
10624+{
10625+ int err;
10626+ aufs_bindex_t bcpup;
10627+ struct au_pin pin;
10628+ struct au_wr_dir_args wr_dir_args = {
10629+ .force_btgt = -1,
10630+ .flags = 0
10631+ };
10632+
10633+ AuDbg("%.*s\n", AuDLNPair(dentry));
10634+
10635+ di_read_unlock(dentry, AuLock_IR);
10636+ di_write_lock_child(dentry);
10637+ err = au_wr_dir(dentry, /*src_dentry*/NULL, &wr_dir_args);
10638+ if (unlikely(err < 0))
10639+ goto out;
10640+ bcpup = err;
10641+ err = 0;
10642+ if (bcpup == au_dbstart(dentry))
10643+ goto out; /* success */
10644+
10645+ err = au_pin(&pin, dentry, bcpup, au_opt_udba(dentry->d_sb),
10646+ AuPin_MNT_WRITE);
10647+ if (!err) {
10648+ err = au_sio_cpup_simple(dentry, bcpup, -1, AuCpup_DTIME);
10649+ au_unpin(&pin);
10650+ }
10651+
4f0767ce 10652+out:
4a4d8108
AM
10653+ di_downgrade_lock(dentry, AuLock_IR);
10654+ return err;
10655+}
10656+
10657+static int au_do_open_sp(struct file *file, int flags)
10658+{
10659+ int err;
10660+ struct dentry *dentry;
10661+ struct super_block *sb;
10662+ struct file *h_file;
10663+ struct inode *h_inode;
10664+
10665+ dentry = file->f_dentry;
10666+ AuDbg("%.*s\n", AuDLNPair(dentry));
10667+
10668+ /*
10669+ * try copying-up.
10670+ * operate on the ro branch is not an error.
10671+ */
10672+ au_cpup_sp(dentry); /* ignore */
10673+
10674+ /* prepare h_file */
10675+ err = au_do_open_nondir(file, vfsub_file_flags(file));
10676+ if (unlikely(err))
10677+ goto out;
10678+
10679+ sb = dentry->d_sb;
10680+ h_file = au_hf_top(file);
10681+ h_inode = h_file->f_dentry->d_inode;
10682+ di_read_unlock(dentry, AuLock_IR);
10683+ fi_write_unlock(file);
10684+ si_read_unlock(sb);
10685+ /* open this fifo in aufs */
10686+ err = h_inode->i_fop->open(file->f_dentry->d_inode, file);
10687+ si_noflush_read_lock(sb);
10688+ fi_write_lock(file);
10689+ di_read_lock_child(dentry, AuLock_IR);
10690+ if (!err)
10691+ au_init_fop_sp(file);
4a4d8108 10692+
4f0767ce 10693+out:
4a4d8108
AM
10694+ return err;
10695+}
10696+
10697+static int aufs_open_sp(struct inode *inode, struct file *file)
10698+{
10699+ int err;
10700+ struct super_block *sb;
10701+
10702+ sb = file->f_dentry->d_sb;
10703+ si_read_lock(sb, AuLock_FLUSH);
10704+ err = au_do_open(file, au_do_open_sp, /*fidir*/NULL);
10705+ si_read_unlock(sb);
10706+ return err;
10707+}
10708+
10709+/* ---------------------------------------------------------------------- */
10710+
10711+void au_init_special_fop(struct inode *inode, umode_t mode, dev_t rdev)
10712+{
10713+ init_special_inode(inode, mode, rdev);
10714+
10715+ switch (mode & S_IFMT) {
10716+ case S_IFIFO:
10717+ inode->i_fop = &au_sp_fop[AuSp_FIFO].fop;
10718+ /*FALLTHROUGH*/
10719+ case S_IFCHR:
10720+ case S_IFBLK:
10721+ case S_IFSOCK:
10722+ break;
10723+ default:
10724+ AuDebugOn(1);
10725+ }
10726+}
10727+
10728+int au_special_file(umode_t mode)
10729+{
10730+ int ret;
10731+
10732+ ret = 0;
10733+ switch (mode & S_IFMT) {
10734+ case S_IFIFO:
10735+#if 0
10736+ case S_IFCHR:
10737+ case S_IFBLK:
10738+ case S_IFSOCK:
10739+#endif
10740+ ret = 1;
10741+ }
10742+
10743+ return ret;
10744+}
7f207e10
AM
10745diff -urN /usr/share/empty/fs/aufs/fstype.h linux/fs/aufs/fstype.h
10746--- /usr/share/empty/fs/aufs/fstype.h 1970-01-01 01:00:00.000000000 +0100
87a755f4 10747+++ linux/fs/aufs/fstype.h 2011-03-17 10:46:59.000000000 +0100
4a4d8108
AM
10748@@ -0,0 +1,497 @@
10749+/*
027c5e7a 10750+ * Copyright (C) 2005-2011 Junjiro R. Okajima
4a4d8108
AM
10751+ *
10752+ * This program, aufs is free software; you can redistribute it and/or modify
10753+ * it under the terms of the GNU General Public License as published by
10754+ * the Free Software Foundation; either version 2 of the License, or
10755+ * (at your option) any later version.
10756+ *
10757+ * This program is distributed in the hope that it will be useful,
10758+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
10759+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10760+ * GNU General Public License for more details.
10761+ *
10762+ * You should have received a copy of the GNU General Public License
10763+ * along with this program; if not, write to the Free Software
10764+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
10765+ */
10766+
10767+/*
10768+ * judging filesystem type
10769+ */
10770+
10771+#ifndef __AUFS_FSTYPE_H__
10772+#define __AUFS_FSTYPE_H__
10773+
10774+#ifdef __KERNEL__
10775+
10776+#include <linux/fs.h>
10777+#include <linux/magic.h>
10778+#include <linux/romfs_fs.h>
10779+#include <linux/aufs_type.h>
10780+
10781+static inline int au_test_aufs(struct super_block *sb)
10782+{
10783+ return sb->s_magic == AUFS_SUPER_MAGIC;
10784+}
10785+
10786+static inline const char *au_sbtype(struct super_block *sb)
10787+{
10788+ return sb->s_type->name;
10789+}
1308ab2a 10790+
10791+static inline int au_test_iso9660(struct super_block *sb __maybe_unused)
10792+{
10793+#if defined(CONFIG_ROMFS_FS) || defined(CONFIG_ROMFS_FS_MODULE)
10794+ return sb->s_magic == ROMFS_MAGIC;
dece6358
AM
10795+#else
10796+ return 0;
10797+#endif
10798+}
10799+
1308ab2a 10800+static inline int au_test_romfs(struct super_block *sb __maybe_unused)
dece6358 10801+{
1308ab2a 10802+#if defined(CONFIG_ISO9660_FS) || defined(CONFIG_ISO9660_FS_MODULE)
10803+ return sb->s_magic == ISOFS_SUPER_MAGIC;
dece6358
AM
10804+#else
10805+ return 0;
10806+#endif
10807+}
10808+
1308ab2a 10809+static inline int au_test_cramfs(struct super_block *sb __maybe_unused)
dece6358 10810+{
1308ab2a 10811+#if defined(CONFIG_CRAMFS) || defined(CONFIG_CRAMFS_MODULE)
10812+ return sb->s_magic == CRAMFS_MAGIC;
10813+#endif
10814+ return 0;
10815+}
10816+
10817+static inline int au_test_nfs(struct super_block *sb __maybe_unused)
10818+{
10819+#if defined(CONFIG_NFS_FS) || defined(CONFIG_NFS_FS_MODULE)
10820+ return sb->s_magic == NFS_SUPER_MAGIC;
dece6358
AM
10821+#else
10822+ return 0;
10823+#endif
10824+}
10825+
1308ab2a 10826+static inline int au_test_fuse(struct super_block *sb __maybe_unused)
dece6358 10827+{
1308ab2a 10828+#if defined(CONFIG_FUSE_FS) || defined(CONFIG_FUSE_FS_MODULE)
10829+ return sb->s_magic == FUSE_SUPER_MAGIC;
dece6358
AM
10830+#else
10831+ return 0;
10832+#endif
10833+}
10834+
1308ab2a 10835+static inline int au_test_xfs(struct super_block *sb __maybe_unused)
dece6358 10836+{
1308ab2a 10837+#if defined(CONFIG_XFS_FS) || defined(CONFIG_XFS_FS_MODULE)
10838+ return sb->s_magic == XFS_SB_MAGIC;
dece6358
AM
10839+#else
10840+ return 0;
10841+#endif
10842+}
10843+
1308ab2a 10844+static inline int au_test_tmpfs(struct super_block *sb __maybe_unused)
dece6358 10845+{
1308ab2a 10846+#ifdef CONFIG_TMPFS
10847+ return sb->s_magic == TMPFS_MAGIC;
10848+#else
10849+ return 0;
dece6358 10850+#endif
dece6358
AM
10851+}
10852+
1308ab2a 10853+static inline int au_test_ecryptfs(struct super_block *sb __maybe_unused)
1facf9fc 10854+{
1308ab2a 10855+#if defined(CONFIG_ECRYPT_FS) || defined(CONFIG_ECRYPT_FS_MODULE)
10856+ return !strcmp(au_sbtype(sb), "ecryptfs");
10857+#else
10858+ return 0;
10859+#endif
1facf9fc 10860+}
10861+
1308ab2a 10862+static inline int au_test_smbfs(struct super_block *sb __maybe_unused)
1facf9fc 10863+{
1308ab2a 10864+#if defined(CONFIG_SMB_FS) || defined(CONFIG_SMB_FS_MODULE)
10865+ return sb->s_magic == SMB_SUPER_MAGIC;
10866+#else
10867+ return 0;
1facf9fc 10868+#endif
1facf9fc 10869+}
10870+
1308ab2a 10871+static inline int au_test_ocfs2(struct super_block *sb __maybe_unused)
1facf9fc 10872+{
1308ab2a 10873+#if defined(CONFIG_OCFS2_FS) || defined(CONFIG_OCFS2_FS_MODULE)
10874+ return sb->s_magic == OCFS2_SUPER_MAGIC;
10875+#else
10876+ return 0;
10877+#endif
1facf9fc 10878+}
10879+
1308ab2a 10880+static inline int au_test_ocfs2_dlmfs(struct super_block *sb __maybe_unused)
1facf9fc 10881+{
1308ab2a 10882+#if defined(CONFIG_OCFS2_FS_O2CB) || defined(CONFIG_OCFS2_FS_O2CB_MODULE)
10883+ return sb->s_magic == DLMFS_MAGIC;
10884+#else
10885+ return 0;
10886+#endif
1facf9fc 10887+}
10888+
1308ab2a 10889+static inline int au_test_coda(struct super_block *sb __maybe_unused)
1facf9fc 10890+{
1308ab2a 10891+#if defined(CONFIG_CODA_FS) || defined(CONFIG_CODA_FS_MODULE)
10892+ return sb->s_magic == CODA_SUPER_MAGIC;
10893+#else
10894+ return 0;
10895+#endif
10896+}
10897+
10898+static inline int au_test_v9fs(struct super_block *sb __maybe_unused)
10899+{
10900+#if defined(CONFIG_9P_FS) || defined(CONFIG_9P_FS_MODULE)
10901+ return sb->s_magic == V9FS_MAGIC;
10902+#else
10903+ return 0;
10904+#endif
10905+}
10906+
10907+static inline int au_test_ext4(struct super_block *sb __maybe_unused)
10908+{
10909+#if defined(CONFIG_EXT4DEV_FS) || defined(CONFIG_EXT4DEV_FS_MODULE)
10910+ return sb->s_magic == EXT4_SUPER_MAGIC;
10911+#else
10912+ return 0;
10913+#endif
10914+}
10915+
10916+static inline int au_test_sysv(struct super_block *sb __maybe_unused)
10917+{
10918+#if defined(CONFIG_SYSV_FS) || defined(CONFIG_SYSV_FS_MODULE)
10919+ return !strcmp(au_sbtype(sb), "sysv");
10920+#else
10921+ return 0;
10922+#endif
10923+}
10924+
10925+static inline int au_test_ramfs(struct super_block *sb)
10926+{
10927+ return sb->s_magic == RAMFS_MAGIC;
10928+}
10929+
10930+static inline int au_test_ubifs(struct super_block *sb __maybe_unused)
10931+{
10932+#if defined(CONFIG_UBIFS_FS) || defined(CONFIG_UBIFS_FS_MODULE)
10933+ return sb->s_magic == UBIFS_SUPER_MAGIC;
10934+#else
10935+ return 0;
10936+#endif
10937+}
10938+
10939+static inline int au_test_procfs(struct super_block *sb __maybe_unused)
10940+{
10941+#ifdef CONFIG_PROC_FS
10942+ return sb->s_magic == PROC_SUPER_MAGIC;
10943+#else
10944+ return 0;
10945+#endif
10946+}
10947+
10948+static inline int au_test_sysfs(struct super_block *sb __maybe_unused)
10949+{
10950+#ifdef CONFIG_SYSFS
10951+ return sb->s_magic == SYSFS_MAGIC;
10952+#else
10953+ return 0;
10954+#endif
10955+}
10956+
10957+static inline int au_test_configfs(struct super_block *sb __maybe_unused)
10958+{
10959+#if defined(CONFIG_CONFIGFS_FS) || defined(CONFIG_CONFIGFS_FS_MODULE)
10960+ return sb->s_magic == CONFIGFS_MAGIC;
10961+#else
10962+ return 0;
10963+#endif
10964+}
10965+
10966+static inline int au_test_minix(struct super_block *sb __maybe_unused)
10967+{
10968+#if defined(CONFIG_MINIX_FS) || defined(CONFIG_MINIX_FS_MODULE)
10969+ return sb->s_magic == MINIX3_SUPER_MAGIC
10970+ || sb->s_magic == MINIX2_SUPER_MAGIC
10971+ || sb->s_magic == MINIX2_SUPER_MAGIC2
10972+ || sb->s_magic == MINIX_SUPER_MAGIC
10973+ || sb->s_magic == MINIX_SUPER_MAGIC2;
10974+#else
10975+ return 0;
10976+#endif
10977+}
10978+
10979+static inline int au_test_cifs(struct super_block *sb __maybe_unused)
10980+{
10981+#if defined(CONFIG_CIFS_FS) || defined(CONFIGCIFS_FS_MODULE)
10982+ return sb->s_magic == CIFS_MAGIC_NUMBER;
10983+#else
10984+ return 0;
10985+#endif
10986+}
10987+
10988+static inline int au_test_fat(struct super_block *sb __maybe_unused)
10989+{
10990+#if defined(CONFIG_FAT_FS) || defined(CONFIG_FAT_FS_MODULE)
10991+ return sb->s_magic == MSDOS_SUPER_MAGIC;
10992+#else
10993+ return 0;
10994+#endif
10995+}
10996+
10997+static inline int au_test_msdos(struct super_block *sb)
10998+{
10999+ return au_test_fat(sb);
11000+}
11001+
11002+static inline int au_test_vfat(struct super_block *sb)
11003+{
11004+ return au_test_fat(sb);
11005+}
11006+
11007+static inline int au_test_securityfs(struct super_block *sb __maybe_unused)
11008+{
11009+#ifdef CONFIG_SECURITYFS
11010+ return sb->s_magic == SECURITYFS_MAGIC;
11011+#else
11012+ return 0;
11013+#endif
11014+}
11015+
11016+static inline int au_test_squashfs(struct super_block *sb __maybe_unused)
11017+{
11018+#if defined(CONFIG_SQUASHFS) || defined(CONFIG_SQUASHFS_MODULE)
11019+ return sb->s_magic == SQUASHFS_MAGIC;
11020+#else
11021+ return 0;
11022+#endif
11023+}
11024+
11025+static inline int au_test_btrfs(struct super_block *sb __maybe_unused)
11026+{
11027+#if defined(CONFIG_BTRFS_FS) || defined(CONFIG_BTRFS_FS_MODULE)
11028+ return sb->s_magic == BTRFS_SUPER_MAGIC;
11029+#else
11030+ return 0;
11031+#endif
11032+}
11033+
11034+static inline int au_test_xenfs(struct super_block *sb __maybe_unused)
11035+{
11036+#if defined(CONFIG_XENFS) || defined(CONFIG_XENFS_MODULE)
11037+ return sb->s_magic == XENFS_SUPER_MAGIC;
11038+#else
11039+ return 0;
11040+#endif
11041+}
11042+
11043+static inline int au_test_debugfs(struct super_block *sb __maybe_unused)
11044+{
11045+#ifdef CONFIG_DEBUG_FS
11046+ return sb->s_magic == DEBUGFS_MAGIC;
11047+#else
11048+ return 0;
11049+#endif
11050+}
11051+
11052+static inline int au_test_nilfs(struct super_block *sb __maybe_unused)
11053+{
11054+#if defined(CONFIG_NILFS) || defined(CONFIG_NILFS_MODULE)
11055+ return sb->s_magic == NILFS_SUPER_MAGIC;
11056+#else
11057+ return 0;
11058+#endif
11059+}
11060+
4a4d8108
AM
11061+static inline int au_test_hfsplus(struct super_block *sb __maybe_unused)
11062+{
11063+#if defined(CONFIG_HFSPLUS_FS) || defined(CONFIG_HFSPLUS_FS_MODULE)
11064+ return sb->s_magic == HFSPLUS_SUPER_MAGIC;
11065+#else
11066+ return 0;
11067+#endif
11068+}
11069+
1308ab2a 11070+/* ---------------------------------------------------------------------- */
11071+/*
11072+ * they can't be an aufs branch.
11073+ */
11074+static inline int au_test_fs_unsuppoted(struct super_block *sb)
11075+{
11076+ return
11077+#ifndef CONFIG_AUFS_BR_RAMFS
11078+ au_test_ramfs(sb) ||
11079+#endif
11080+ au_test_procfs(sb)
11081+ || au_test_sysfs(sb)
11082+ || au_test_configfs(sb)
11083+ || au_test_debugfs(sb)
11084+ || au_test_securityfs(sb)
11085+ || au_test_xenfs(sb)
11086+ || au_test_ecryptfs(sb)
11087+ /* || !strcmp(au_sbtype(sb), "unionfs") */
11088+ || au_test_aufs(sb); /* will be supported in next version */
11089+}
11090+
11091+/*
11092+ * If the filesystem supports NFS-export, then it has to support NULL as
11093+ * a nameidata parameter for ->create(), ->lookup() and ->d_revalidate().
11094+ * We can apply this principle when we handle a lower filesystem.
11095+ */
11096+static inline int au_test_fs_null_nd(struct super_block *sb)
11097+{
11098+ return !!sb->s_export_op;
11099+}
11100+
11101+static inline int au_test_fs_remote(struct super_block *sb)
11102+{
11103+ return !au_test_tmpfs(sb)
11104+#ifdef CONFIG_AUFS_BR_RAMFS
11105+ && !au_test_ramfs(sb)
11106+#endif
11107+ && !(sb->s_type->fs_flags & FS_REQUIRES_DEV);
11108+}
11109+
11110+/* ---------------------------------------------------------------------- */
11111+
11112+/*
11113+ * Note: these functions (below) are created after reading ->getattr() in all
11114+ * filesystems under linux/fs. it means we have to do so in every update...
11115+ */
11116+
11117+/*
11118+ * some filesystems require getattr to refresh the inode attributes before
11119+ * referencing.
11120+ * in most cases, we can rely on the inode attribute in NFS (or every remote fs)
11121+ * and leave the work for d_revalidate()
11122+ */
11123+static inline int au_test_fs_refresh_iattr(struct super_block *sb)
11124+{
11125+ return au_test_nfs(sb)
11126+ || au_test_fuse(sb)
11127+ /* || au_test_smbfs(sb) */ /* untested */
11128+ /* || au_test_ocfs2(sb) */ /* untested */
11129+ /* || au_test_btrfs(sb) */ /* untested */
11130+ /* || au_test_coda(sb) */ /* untested */
11131+ /* || au_test_v9fs(sb) */ /* untested */
11132+ ;
11133+}
11134+
11135+/*
11136+ * filesystems which don't maintain i_size or i_blocks.
11137+ */
11138+static inline int au_test_fs_bad_iattr_size(struct super_block *sb)
11139+{
11140+ return au_test_xfs(sb)
4a4d8108
AM
11141+ || au_test_btrfs(sb)
11142+ || au_test_ubifs(sb)
11143+ || au_test_hfsplus(sb) /* maintained, but incorrect */
1308ab2a 11144+ /* || au_test_ext4(sb) */ /* untested */
11145+ /* || au_test_ocfs2(sb) */ /* untested */
11146+ /* || au_test_ocfs2_dlmfs(sb) */ /* untested */
11147+ /* || au_test_sysv(sb) */ /* untested */
1308ab2a 11148+ /* || au_test_minix(sb) */ /* untested */
11149+ ;
11150+}
11151+
11152+/*
11153+ * filesystems which don't store the correct value in some of their inode
11154+ * attributes.
11155+ */
11156+static inline int au_test_fs_bad_iattr(struct super_block *sb)
11157+{
11158+ return au_test_fs_bad_iattr_size(sb)
11159+ /* || au_test_cifs(sb) */ /* untested */
11160+ || au_test_fat(sb)
11161+ || au_test_msdos(sb)
11162+ || au_test_vfat(sb);
1facf9fc 11163+}
11164+
11165+/* they don't check i_nlink in link(2) */
11166+static inline int au_test_fs_no_limit_nlink(struct super_block *sb)
11167+{
11168+ return au_test_tmpfs(sb)
11169+#ifdef CONFIG_AUFS_BR_RAMFS
11170+ || au_test_ramfs(sb)
11171+#endif
4a4d8108
AM
11172+ || au_test_ubifs(sb)
11173+ || au_test_btrfs(sb)
11174+ || au_test_hfsplus(sb);
1facf9fc 11175+}
11176+
11177+/*
11178+ * filesystems which sets S_NOATIME and S_NOCMTIME.
11179+ */
11180+static inline int au_test_fs_notime(struct super_block *sb)
11181+{
11182+ return au_test_nfs(sb)
11183+ || au_test_fuse(sb)
dece6358 11184+ || au_test_ubifs(sb)
1facf9fc 11185+ /* || au_test_cifs(sb) */ /* untested */
1facf9fc 11186+ ;
11187+}
11188+
11189+/*
11190+ * filesystems which requires replacing i_mapping.
11191+ */
11192+static inline int au_test_fs_bad_mapping(struct super_block *sb)
11193+{
dece6358
AM
11194+ return au_test_fuse(sb)
11195+ || au_test_ubifs(sb);
1facf9fc 11196+}
11197+
11198+/* temporary support for i#1 in cramfs */
11199+static inline int au_test_fs_unique_ino(struct inode *inode)
11200+{
11201+ if (au_test_cramfs(inode->i_sb))
11202+ return inode->i_ino != 1;
11203+ return 1;
11204+}
11205+
11206+/* ---------------------------------------------------------------------- */
11207+
11208+/*
11209+ * the filesystem where the xino files placed must support i/o after unlink and
11210+ * maintain i_size and i_blocks.
11211+ */
11212+static inline int au_test_fs_bad_xino(struct super_block *sb)
11213+{
11214+ return au_test_fs_remote(sb)
11215+ || au_test_fs_bad_iattr_size(sb)
11216+#ifdef CONFIG_AUFS_BR_RAMFS
11217+ || !(au_test_ramfs(sb) || au_test_fs_null_nd(sb))
11218+#else
11219+ || !au_test_fs_null_nd(sb) /* to keep xino code simple */
11220+#endif
11221+ /* don't want unnecessary work for xino */
11222+ || au_test_aufs(sb)
1308ab2a 11223+ || au_test_ecryptfs(sb)
11224+ || au_test_nilfs(sb);
1facf9fc 11225+}
11226+
11227+static inline int au_test_fs_trunc_xino(struct super_block *sb)
11228+{
11229+ return au_test_tmpfs(sb)
11230+ || au_test_ramfs(sb);
11231+}
11232+
11233+/*
11234+ * test if the @sb is real-readonly.
11235+ */
11236+static inline int au_test_fs_rr(struct super_block *sb)
11237+{
11238+ return au_test_squashfs(sb)
11239+ || au_test_iso9660(sb)
11240+ || au_test_cramfs(sb)
11241+ || au_test_romfs(sb);
11242+}
11243+
11244+#endif /* __KERNEL__ */
11245+#endif /* __AUFS_FSTYPE_H__ */
7f207e10
AM
11246diff -urN /usr/share/empty/fs/aufs/hfsnotify.c linux/fs/aufs/hfsnotify.c
11247--- /usr/share/empty/fs/aufs/hfsnotify.c 1970-01-01 01:00:00.000000000 +0100
87a755f4 11248+++ linux/fs/aufs/hfsnotify.c 2011-03-17 10:46:59.000000000 +0100
027c5e7a 11249@@ -0,0 +1,247 @@
1facf9fc 11250+/*
027c5e7a 11251+ * Copyright (C) 2005-2011 Junjiro R. Okajima
1facf9fc 11252+ *
11253+ * This program, aufs is free software; you can redistribute it and/or modify
11254+ * it under the terms of the GNU General Public License as published by
11255+ * the Free Software Foundation; either version 2 of the License, or
11256+ * (at your option) any later version.
dece6358
AM
11257+ *
11258+ * This program is distributed in the hope that it will be useful,
11259+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
11260+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11261+ * GNU General Public License for more details.
11262+ *
11263+ * You should have received a copy of the GNU General Public License
11264+ * along with this program; if not, write to the Free Software
11265+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 11266+ */
11267+
11268+/*
4a4d8108 11269+ * fsnotify for the lower directories
1facf9fc 11270+ */
11271+
11272+#include "aufs.h"
11273+
4a4d8108
AM
11274+/* FS_IN_IGNORED is unnecessary */
11275+static const __u32 AuHfsnMask = (FS_MOVED_TO | FS_MOVED_FROM | FS_DELETE
11276+ | FS_CREATE | FS_EVENT_ON_CHILD);
7f207e10 11277+static DECLARE_WAIT_QUEUE_HEAD(au_hfsn_wq);
1facf9fc 11278+
0c5527e5 11279+static void au_hfsn_free_mark(struct fsnotify_mark *mark)
1facf9fc 11280+{
0c5527e5
AM
11281+ struct au_hnotify *hn = container_of(mark, struct au_hnotify,
11282+ hn_mark);
4a4d8108 11283+ AuDbg("here\n");
7f207e10
AM
11284+ hn->hn_mark_dead = 1;
11285+ smp_mb();
11286+ wake_up_all(&au_hfsn_wq);
4a4d8108 11287+}
1facf9fc 11288+
027c5e7a 11289+static int au_hfsn_alloc(struct au_hinode *hinode)
4a4d8108 11290+{
027c5e7a
AM
11291+ struct au_hnotify *hn;
11292+ struct super_block *sb;
11293+ struct au_branch *br;
0c5527e5 11294+ struct fsnotify_mark *mark;
027c5e7a 11295+ aufs_bindex_t bindex;
1facf9fc 11296+
027c5e7a
AM
11297+ hn = hinode->hi_notify;
11298+ sb = hn->hn_aufs_inode->i_sb;
11299+ bindex = au_br_index(sb, hinode->hi_id);
11300+ br = au_sbr(sb, bindex);
7f207e10 11301+ hn->hn_mark_dead = 0;
0c5527e5
AM
11302+ mark = &hn->hn_mark;
11303+ fsnotify_init_mark(mark, au_hfsn_free_mark);
11304+ mark->mask = AuHfsnMask;
7f207e10
AM
11305+ /*
11306+ * by udba rename or rmdir, aufs assign a new inode to the known
11307+ * h_inode, so specify 1 to allow dups.
11308+ */
027c5e7a
AM
11309+ return fsnotify_add_mark(mark, br->br_hfsn_group, hinode->hi_inode,
11310+ /*mnt*/NULL, /*allow_dups*/1);
1facf9fc 11311+}
11312+
027c5e7a 11313+static void au_hfsn_free(struct au_hinode *hinode)
1facf9fc 11314+{
027c5e7a 11315+ struct au_hnotify *hn;
0c5527e5 11316+ struct fsnotify_mark *mark;
953406b4 11317+
027c5e7a 11318+ hn = hinode->hi_notify;
0c5527e5
AM
11319+ mark = &hn->hn_mark;
11320+ fsnotify_destroy_mark(mark);
11321+ fsnotify_put_mark(mark);
7f207e10
AM
11322+
11323+ /* TODO: bad approach */
11324+ wait_event(au_hfsn_wq, hn->hn_mark_dead);
1facf9fc 11325+}
11326+
11327+/* ---------------------------------------------------------------------- */
11328+
4a4d8108 11329+static void au_hfsn_ctl(struct au_hinode *hinode, int do_set)
1facf9fc 11330+{
0c5527e5 11331+ struct fsnotify_mark *mark;
1facf9fc 11332+
0c5527e5
AM
11333+ mark = &hinode->hi_notify->hn_mark;
11334+ spin_lock(&mark->lock);
1facf9fc 11335+ if (do_set) {
0c5527e5
AM
11336+ AuDebugOn(mark->mask & AuHfsnMask);
11337+ mark->mask |= AuHfsnMask;
1facf9fc 11338+ } else {
0c5527e5
AM
11339+ AuDebugOn(!(mark->mask & AuHfsnMask));
11340+ mark->mask &= ~AuHfsnMask;
1facf9fc 11341+ }
0c5527e5 11342+ spin_unlock(&mark->lock);
4a4d8108 11343+ /* fsnotify_recalc_inode_mask(hinode->hi_inode); */
1facf9fc 11344+}
11345+
4a4d8108 11346+/* ---------------------------------------------------------------------- */
1facf9fc 11347+
4a4d8108
AM
11348+/* #define AuDbgHnotify */
11349+#ifdef AuDbgHnotify
11350+static char *au_hfsn_name(u32 mask)
11351+{
11352+#ifdef CONFIG_AUFS_DEBUG
11353+#define test_ret(flag) if (mask & flag) \
11354+ return #flag;
11355+ test_ret(FS_ACCESS);
11356+ test_ret(FS_MODIFY);
11357+ test_ret(FS_ATTRIB);
11358+ test_ret(FS_CLOSE_WRITE);
11359+ test_ret(FS_CLOSE_NOWRITE);
11360+ test_ret(FS_OPEN);
11361+ test_ret(FS_MOVED_FROM);
11362+ test_ret(FS_MOVED_TO);
11363+ test_ret(FS_CREATE);
11364+ test_ret(FS_DELETE);
11365+ test_ret(FS_DELETE_SELF);
11366+ test_ret(FS_MOVE_SELF);
11367+ test_ret(FS_UNMOUNT);
11368+ test_ret(FS_Q_OVERFLOW);
11369+ test_ret(FS_IN_IGNORED);
11370+ test_ret(FS_IN_ISDIR);
11371+ test_ret(FS_IN_ONESHOT);
11372+ test_ret(FS_EVENT_ON_CHILD);
11373+ return "";
11374+#undef test_ret
11375+#else
11376+ return "??";
11377+#endif
1facf9fc 11378+}
4a4d8108 11379+#endif
1facf9fc 11380+
11381+/* ---------------------------------------------------------------------- */
11382+
4a4d8108 11383+static int au_hfsn_handle_event(struct fsnotify_group *group,
0c5527e5
AM
11384+ struct fsnotify_mark *inode_mark,
11385+ struct fsnotify_mark *vfsmount_mark,
4a4d8108 11386+ struct fsnotify_event *event)
1facf9fc 11387+{
11388+ int err;
4a4d8108
AM
11389+ struct au_hnotify *hnotify;
11390+ struct inode *h_dir, *h_inode;
11391+ __u32 mask;
4a4d8108
AM
11392+ struct qstr h_child_qstr = {
11393+ .name = event->file_name,
11394+ .len = event->name_len
11395+ };
11396+
11397+ AuDebugOn(event->data_type != FSNOTIFY_EVENT_INODE);
1facf9fc 11398+
11399+ err = 0;
0c5527e5 11400+ /* if FS_UNMOUNT happens, there must be another bug */
4a4d8108
AM
11401+ mask = event->mask;
11402+ AuDebugOn(mask & FS_UNMOUNT);
0c5527e5 11403+ if (mask & (FS_IN_IGNORED | FS_UNMOUNT))
1facf9fc 11404+ goto out;
1facf9fc 11405+
4a4d8108
AM
11406+ h_dir = event->to_tell;
11407+ h_inode = event->inode;
11408+#ifdef AuDbgHnotify
11409+ au_debug(1);
11410+ if (1 || h_child_qstr.len != sizeof(AUFS_XINO_FNAME) - 1
11411+ || strncmp(h_child_qstr.name, AUFS_XINO_FNAME, h_child_qstr.len)) {
11412+ AuDbg("i%lu, mask 0x%x %s, hcname %.*s, hi%lu\n",
11413+ h_dir->i_ino, mask, au_hfsn_name(mask),
11414+ AuLNPair(&h_child_qstr), h_inode ? h_inode->i_ino : 0);
11415+ /* WARN_ON(1); */
1facf9fc 11416+ }
4a4d8108 11417+ au_debug(0);
1facf9fc 11418+#endif
4a4d8108 11419+
0c5527e5
AM
11420+ AuDebugOn(!inode_mark);
11421+ hnotify = container_of(inode_mark, struct au_hnotify, hn_mark);
11422+ err = au_hnotify(h_dir, hnotify, mask, &h_child_qstr, h_inode);
1facf9fc 11423+
4a4d8108
AM
11424+out:
11425+ return err;
11426+}
1facf9fc 11427+
027c5e7a 11428+/* isn't it waste to ask every registered 'group'? */
7f207e10 11429+/* copied from linux/fs/notify/inotify/inotify_fsnotiry.c */
4a4d8108 11430+/* it should be exported to modules */
7f207e10
AM
11431+static bool au_hfsn_should_send_event(struct fsnotify_group *group,
11432+ struct inode *h_inode,
0c5527e5
AM
11433+ struct fsnotify_mark *inode_mark,
11434+ struct fsnotify_mark *vfsmount_mark,
11435+ __u32 mask, void *data, int data_type)
4a4d8108 11436+{
4a4d8108 11437+ mask = (mask & ~FS_EVENT_ON_CHILD);
7f207e10 11438+ return inode_mark->mask & mask;
4a4d8108
AM
11439+}
11440+
11441+static struct fsnotify_ops au_hfsn_ops = {
11442+ .should_send_event = au_hfsn_should_send_event,
11443+ .handle_event = au_hfsn_handle_event
11444+};
11445+
11446+/* ---------------------------------------------------------------------- */
11447+
027c5e7a
AM
11448+static void au_hfsn_fin_br(struct au_branch *br)
11449+{
11450+ if (br->br_hfsn_group)
11451+ fsnotify_put_group(br->br_hfsn_group);
11452+}
11453+
11454+static int au_hfsn_init_br(struct au_branch *br, int perm)
11455+{
11456+ br->br_hfsn_group = NULL;
11457+ br->br_hfsn_ops = au_hfsn_ops;
11458+ return 0;
11459+}
11460+
11461+static int au_hfsn_reset_br(unsigned int udba, struct au_branch *br, int perm)
4a4d8108
AM
11462+{
11463+ int err;
1facf9fc 11464+
4a4d8108 11465+ err = 0;
027c5e7a
AM
11466+ if (udba != AuOpt_UDBA_HNOTIFY
11467+ || !au_br_hnotifyable(perm)) {
11468+ au_hfsn_fin_br(br);
11469+ br->br_hfsn_group = NULL;
11470+ goto out;
11471+ }
11472+
11473+ if (br->br_hfsn_group)
11474+ goto out;
11475+
11476+ br->br_hfsn_group = fsnotify_alloc_group(&br->br_hfsn_ops);
11477+ if (IS_ERR(br->br_hfsn_group)) {
11478+ err = PTR_ERR(br->br_hfsn_group);
0c5527e5 11479+ pr_err("fsnotify_alloc_group() failed, %d\n", err);
027c5e7a 11480+ br->br_hfsn_group = NULL;
4a4d8108 11481+ }
1facf9fc 11482+
027c5e7a 11483+out:
1facf9fc 11484+ AuTraceErr(err);
11485+ return err;
11486+}
11487+
4a4d8108
AM
11488+const struct au_hnotify_op au_hnotify_op = {
11489+ .ctl = au_hfsn_ctl,
11490+ .alloc = au_hfsn_alloc,
11491+ .free = au_hfsn_free,
1facf9fc 11492+
027c5e7a
AM
11493+ .reset_br = au_hfsn_reset_br,
11494+ .fin_br = au_hfsn_fin_br,
11495+ .init_br = au_hfsn_init_br
4a4d8108 11496+};
7f207e10
AM
11497diff -urN /usr/share/empty/fs/aufs/hfsplus.c linux/fs/aufs/hfsplus.c
11498--- /usr/share/empty/fs/aufs/hfsplus.c 1970-01-01 01:00:00.000000000 +0100
87a755f4 11499+++ linux/fs/aufs/hfsplus.c 2011-03-17 10:46:59.000000000 +0100
4a4d8108
AM
11500@@ -0,0 +1,58 @@
11501+/*
027c5e7a 11502+ * Copyright (C) 2010-2011 Junjiro R. Okajima
4a4d8108
AM
11503+ *
11504+ * This program, aufs is free software; you can redistribute it and/or modify
11505+ * it under the terms of the GNU General Public License as published by
11506+ * the Free Software Foundation; either version 2 of the License, or
11507+ * (at your option) any later version.
11508+ *
11509+ * This program is distributed in the hope that it will be useful,
11510+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
11511+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11512+ * GNU General Public License for more details.
11513+ *
11514+ * You should have received a copy of the GNU General Public License
11515+ * along with this program; if not, write to the Free Software
11516+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
11517+ */
1facf9fc 11518+
4a4d8108
AM
11519+/*
11520+ * special support for filesystems which aqucires an inode mutex
11521+ * at final closing a file, eg, hfsplus.
11522+ *
11523+ * This trick is very simple and stupid, just to open the file before really
11524+ * neceeary open to tell hfsplus that this is not the final closing.
11525+ * The caller should call au_h_open_pre() after acquiring the inode mutex,
11526+ * and au_h_open_post() after releasing it.
11527+ */
1facf9fc 11528+
4a4d8108
AM
11529+#include <linux/file.h>
11530+#include "aufs.h"
1facf9fc 11531+
4a4d8108
AM
11532+struct file *au_h_open_pre(struct dentry *dentry, aufs_bindex_t bindex)
11533+{
11534+ struct file *h_file;
11535+ struct dentry *h_dentry;
1facf9fc 11536+
4a4d8108
AM
11537+ h_dentry = au_h_dptr(dentry, bindex);
11538+ AuDebugOn(!h_dentry);
11539+ AuDebugOn(!h_dentry->d_inode);
11540+ IMustLock(h_dentry->d_inode);
11541+
11542+ h_file = NULL;
11543+ if (au_test_hfsplus(h_dentry->d_sb)
11544+ && S_ISREG(h_dentry->d_inode->i_mode))
11545+ h_file = au_h_open(dentry, bindex,
11546+ O_RDONLY | O_NOATIME | O_LARGEFILE,
11547+ /*file*/NULL);
11548+ return h_file;
1facf9fc 11549+}
11550+
4a4d8108
AM
11551+void au_h_open_post(struct dentry *dentry, aufs_bindex_t bindex,
11552+ struct file *h_file)
11553+{
11554+ if (h_file) {
11555+ fput(h_file);
11556+ au_sbr_put(dentry->d_sb, bindex);
11557+ }
11558+}
7f207e10
AM
11559diff -urN /usr/share/empty/fs/aufs/hnotify.c linux/fs/aufs/hnotify.c
11560--- /usr/share/empty/fs/aufs/hnotify.c 1970-01-01 01:00:00.000000000 +0100
87a755f4 11561+++ linux/fs/aufs/hnotify.c 2011-03-17 10:46:59.000000000 +0100
027c5e7a 11562@@ -0,0 +1,709 @@
e49829fe 11563+/*
027c5e7a 11564+ * Copyright (C) 2005-2011 Junjiro R. Okajima
e49829fe
JR
11565+ *
11566+ * This program, aufs is free software; you can redistribute it and/or modify
11567+ * it under the terms of the GNU General Public License as published by
11568+ * the Free Software Foundation; either version 2 of the License, or
11569+ * (at your option) any later version.
11570+ *
11571+ * This program is distributed in the hope that it will be useful,
11572+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
11573+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11574+ * GNU General Public License for more details.
11575+ *
11576+ * You should have received a copy of the GNU General Public License
11577+ * along with this program; if not, write to the Free Software
11578+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
11579+ */
11580+
11581+/*
7f207e10 11582+ * abstraction to notify the direct changes on lower directories
e49829fe
JR
11583+ */
11584+
11585+#include "aufs.h"
11586+
027c5e7a 11587+int au_hn_alloc(struct au_hinode *hinode, struct inode *inode)
e49829fe
JR
11588+{
11589+ int err;
7f207e10 11590+ struct au_hnotify *hn;
1facf9fc 11591+
4a4d8108
AM
11592+ err = -ENOMEM;
11593+ hn = au_cache_alloc_hnotify();
11594+ if (hn) {
11595+ hn->hn_aufs_inode = inode;
027c5e7a
AM
11596+ hinode->hi_notify = hn;
11597+ err = au_hnotify_op.alloc(hinode);
11598+ AuTraceErr(err);
11599+ if (unlikely(err)) {
11600+ hinode->hi_notify = NULL;
4a4d8108
AM
11601+ au_cache_free_hnotify(hn);
11602+ /*
11603+ * The upper dir was removed by udba, but the same named
11604+ * dir left. In this case, aufs assignes a new inode
11605+ * number and set the monitor again.
11606+ * For the lower dir, the old monitnor is still left.
11607+ */
11608+ if (err == -EEXIST)
11609+ err = 0;
11610+ }
1308ab2a 11611+ }
1308ab2a 11612+
027c5e7a 11613+ AuTraceErr(err);
1308ab2a 11614+ return err;
dece6358 11615+}
1facf9fc 11616+
4a4d8108 11617+void au_hn_free(struct au_hinode *hinode)
dece6358 11618+{
4a4d8108 11619+ struct au_hnotify *hn;
1facf9fc 11620+
4a4d8108
AM
11621+ hn = hinode->hi_notify;
11622+ if (hn) {
027c5e7a 11623+ au_hnotify_op.free(hinode);
4a4d8108
AM
11624+ au_cache_free_hnotify(hn);
11625+ hinode->hi_notify = NULL;
11626+ }
11627+}
dece6358 11628+
4a4d8108 11629+/* ---------------------------------------------------------------------- */
dece6358 11630+
4a4d8108
AM
11631+void au_hn_ctl(struct au_hinode *hinode, int do_set)
11632+{
11633+ if (hinode->hi_notify)
11634+ au_hnotify_op.ctl(hinode, do_set);
11635+}
11636+
11637+void au_hn_reset(struct inode *inode, unsigned int flags)
11638+{
11639+ aufs_bindex_t bindex, bend;
11640+ struct inode *hi;
11641+ struct dentry *iwhdentry;
1facf9fc 11642+
1308ab2a 11643+ bend = au_ibend(inode);
4a4d8108
AM
11644+ for (bindex = au_ibstart(inode); bindex <= bend; bindex++) {
11645+ hi = au_h_iptr(inode, bindex);
11646+ if (!hi)
11647+ continue;
1308ab2a 11648+
4a4d8108
AM
11649+ /* mutex_lock_nested(&hi->i_mutex, AuLsc_I_CHILD); */
11650+ iwhdentry = au_hi_wh(inode, bindex);
11651+ if (iwhdentry)
11652+ dget(iwhdentry);
11653+ au_igrab(hi);
11654+ au_set_h_iptr(inode, bindex, NULL, 0);
11655+ au_set_h_iptr(inode, bindex, au_igrab(hi),
11656+ flags & ~AuHi_XINO);
11657+ iput(hi);
11658+ dput(iwhdentry);
11659+ /* mutex_unlock(&hi->i_mutex); */
1facf9fc 11660+ }
1facf9fc 11661+}
11662+
1308ab2a 11663+/* ---------------------------------------------------------------------- */
1facf9fc 11664+
4a4d8108 11665+static int hn_xino(struct inode *inode, struct inode *h_inode)
1facf9fc 11666+{
4a4d8108
AM
11667+ int err;
11668+ aufs_bindex_t bindex, bend, bfound, bstart;
11669+ struct inode *h_i;
1facf9fc 11670+
4a4d8108
AM
11671+ err = 0;
11672+ if (unlikely(inode->i_ino == AUFS_ROOT_INO)) {
11673+ pr_warning("branch root dir was changed\n");
11674+ goto out;
11675+ }
1facf9fc 11676+
4a4d8108
AM
11677+ bfound = -1;
11678+ bend = au_ibend(inode);
11679+ bstart = au_ibstart(inode);
11680+#if 0 /* reserved for future use */
11681+ if (bindex == bend) {
11682+ /* keep this ino in rename case */
11683+ goto out;
11684+ }
11685+#endif
11686+ for (bindex = bstart; bindex <= bend; bindex++)
11687+ if (au_h_iptr(inode, bindex) == h_inode) {
11688+ bfound = bindex;
11689+ break;
11690+ }
11691+ if (bfound < 0)
1308ab2a 11692+ goto out;
1facf9fc 11693+
4a4d8108
AM
11694+ for (bindex = bstart; bindex <= bend; bindex++) {
11695+ h_i = au_h_iptr(inode, bindex);
11696+ if (!h_i)
11697+ continue;
1facf9fc 11698+
4a4d8108
AM
11699+ err = au_xino_write(inode->i_sb, bindex, h_i->i_ino, /*ino*/0);
11700+ /* ignore this error */
11701+ /* bad action? */
1facf9fc 11702+ }
1facf9fc 11703+
4a4d8108 11704+ /* children inode number will be broken */
1facf9fc 11705+
4f0767ce 11706+out:
4a4d8108
AM
11707+ AuTraceErr(err);
11708+ return err;
1facf9fc 11709+}
11710+
4a4d8108 11711+static int hn_gen_tree(struct dentry *dentry)
1facf9fc 11712+{
4a4d8108
AM
11713+ int err, i, j, ndentry;
11714+ struct au_dcsub_pages dpages;
11715+ struct au_dpage *dpage;
11716+ struct dentry **dentries;
1facf9fc 11717+
4a4d8108
AM
11718+ err = au_dpages_init(&dpages, GFP_NOFS);
11719+ if (unlikely(err))
11720+ goto out;
11721+ err = au_dcsub_pages(&dpages, dentry, NULL, NULL);
11722+ if (unlikely(err))
11723+ goto out_dpages;
1facf9fc 11724+
4a4d8108
AM
11725+ for (i = 0; i < dpages.ndpage; i++) {
11726+ dpage = dpages.dpages + i;
11727+ dentries = dpage->dentries;
11728+ ndentry = dpage->ndentry;
11729+ for (j = 0; j < ndentry; j++) {
11730+ struct dentry *d;
11731+
11732+ d = dentries[j];
11733+ if (IS_ROOT(d))
11734+ continue;
11735+
4a4d8108
AM
11736+ au_digen_dec(d);
11737+ if (d->d_inode)
11738+ /* todo: reset children xino?
11739+ cached children only? */
11740+ au_iigen_dec(d->d_inode);
1308ab2a 11741+ }
dece6358 11742+ }
1facf9fc 11743+
4f0767ce 11744+out_dpages:
4a4d8108 11745+ au_dpages_free(&dpages);
dece6358 11746+
027c5e7a 11747+#if 0
4a4d8108
AM
11748+ /* discard children */
11749+ dentry_unhash(dentry);
11750+ dput(dentry);
027c5e7a 11751+#endif
4f0767ce 11752+out:
dece6358
AM
11753+ return err;
11754+}
11755+
1308ab2a 11756+/*
4a4d8108 11757+ * return 0 if processed.
1308ab2a 11758+ */
4a4d8108
AM
11759+static int hn_gen_by_inode(char *name, unsigned int nlen, struct inode *inode,
11760+ const unsigned int isdir)
dece6358 11761+{
1308ab2a 11762+ int err;
4a4d8108
AM
11763+ struct dentry *d;
11764+ struct qstr *dname;
1facf9fc 11765+
4a4d8108
AM
11766+ err = 1;
11767+ if (unlikely(inode->i_ino == AUFS_ROOT_INO)) {
11768+ pr_warning("branch root dir was changed\n");
11769+ err = 0;
11770+ goto out;
11771+ }
dece6358 11772+
4a4d8108
AM
11773+ if (!isdir) {
11774+ AuDebugOn(!name);
11775+ au_iigen_dec(inode);
027c5e7a 11776+ spin_lock(&inode->i_lock);
4a4d8108 11777+ list_for_each_entry(d, &inode->i_dentry, d_alias) {
027c5e7a 11778+ spin_lock(&d->d_lock);
4a4d8108
AM
11779+ dname = &d->d_name;
11780+ if (dname->len != nlen
027c5e7a
AM
11781+ && memcmp(dname->name, name, nlen)) {
11782+ spin_unlock(&d->d_lock);
4a4d8108 11783+ continue;
027c5e7a 11784+ }
4a4d8108 11785+ err = 0;
4a4d8108
AM
11786+ au_digen_dec(d);
11787+ spin_unlock(&d->d_lock);
11788+ break;
1facf9fc 11789+ }
027c5e7a 11790+ spin_unlock(&inode->i_lock);
1308ab2a 11791+ } else {
027c5e7a 11792+ au_fset_si(au_sbi(inode->i_sb), FAILED_REFRESH_DIR);
4a4d8108
AM
11793+ d = d_find_alias(inode);
11794+ if (!d) {
11795+ au_iigen_dec(inode);
11796+ goto out;
11797+ }
1facf9fc 11798+
027c5e7a 11799+ spin_lock(&d->d_lock);
4a4d8108 11800+ dname = &d->d_name;
027c5e7a
AM
11801+ if (dname->len == nlen && !memcmp(dname->name, name, nlen)) {
11802+ spin_unlock(&d->d_lock);
4a4d8108 11803+ err = hn_gen_tree(d);
027c5e7a
AM
11804+ spin_lock(&d->d_lock);
11805+ }
11806+ spin_unlock(&d->d_lock);
4a4d8108
AM
11807+ dput(d);
11808+ }
1facf9fc 11809+
4f0767ce 11810+out:
4a4d8108 11811+ AuTraceErr(err);
1308ab2a 11812+ return err;
11813+}
dece6358 11814+
4a4d8108 11815+static int hn_gen_by_name(struct dentry *dentry, const unsigned int isdir)
1facf9fc 11816+{
4a4d8108
AM
11817+ int err;
11818+ struct inode *inode;
1facf9fc 11819+
4a4d8108
AM
11820+ inode = dentry->d_inode;
11821+ if (IS_ROOT(dentry)
11822+ /* || (inode && inode->i_ino == AUFS_ROOT_INO) */
11823+ ) {
11824+ pr_warning("branch root dir was changed\n");
11825+ return 0;
11826+ }
1308ab2a 11827+
4a4d8108
AM
11828+ err = 0;
11829+ if (!isdir) {
4a4d8108
AM
11830+ au_digen_dec(dentry);
11831+ if (inode)
11832+ au_iigen_dec(inode);
11833+ } else {
027c5e7a 11834+ au_fset_si(au_sbi(dentry->d_sb), FAILED_REFRESH_DIR);
4a4d8108
AM
11835+ if (inode)
11836+ err = hn_gen_tree(dentry);
11837+ }
11838+
11839+ AuTraceErr(err);
11840+ return err;
1facf9fc 11841+}
11842+
4a4d8108 11843+/* ---------------------------------------------------------------------- */
1facf9fc 11844+
4a4d8108
AM
11845+/* hnotify job flags */
11846+#define AuHnJob_XINO0 1
11847+#define AuHnJob_GEN (1 << 1)
11848+#define AuHnJob_DIRENT (1 << 2)
11849+#define AuHnJob_ISDIR (1 << 3)
11850+#define AuHnJob_TRYXINO0 (1 << 4)
11851+#define AuHnJob_MNTPNT (1 << 5)
11852+#define au_ftest_hnjob(flags, name) ((flags) & AuHnJob_##name)
7f207e10
AM
11853+#define au_fset_hnjob(flags, name) \
11854+ do { (flags) |= AuHnJob_##name; } while (0)
11855+#define au_fclr_hnjob(flags, name) \
11856+ do { (flags) &= ~AuHnJob_##name; } while (0)
1facf9fc 11857+
4a4d8108
AM
11858+enum {
11859+ AuHn_CHILD,
11860+ AuHn_PARENT,
11861+ AuHnLast
11862+};
1facf9fc 11863+
4a4d8108
AM
11864+struct au_hnotify_args {
11865+ struct inode *h_dir, *dir, *h_child_inode;
11866+ u32 mask;
11867+ unsigned int flags[AuHnLast];
11868+ unsigned int h_child_nlen;
11869+ char h_child_name[];
11870+};
1facf9fc 11871+
4a4d8108
AM
11872+struct hn_job_args {
11873+ unsigned int flags;
11874+ struct inode *inode, *h_inode, *dir, *h_dir;
11875+ struct dentry *dentry;
11876+ char *h_name;
11877+ int h_nlen;
11878+};
1308ab2a 11879+
4a4d8108
AM
11880+static int hn_job(struct hn_job_args *a)
11881+{
11882+ const unsigned int isdir = au_ftest_hnjob(a->flags, ISDIR);
1308ab2a 11883+
4a4d8108
AM
11884+ /* reset xino */
11885+ if (au_ftest_hnjob(a->flags, XINO0) && a->inode)
11886+ hn_xino(a->inode, a->h_inode); /* ignore this error */
1308ab2a 11887+
4a4d8108
AM
11888+ if (au_ftest_hnjob(a->flags, TRYXINO0)
11889+ && a->inode
11890+ && a->h_inode) {
11891+ mutex_lock_nested(&a->h_inode->i_mutex, AuLsc_I_CHILD);
11892+ if (!a->h_inode->i_nlink)
11893+ hn_xino(a->inode, a->h_inode); /* ignore this error */
11894+ mutex_unlock(&a->h_inode->i_mutex);
1308ab2a 11895+ }
1facf9fc 11896+
4a4d8108
AM
11897+ /* make the generation obsolete */
11898+ if (au_ftest_hnjob(a->flags, GEN)) {
11899+ int err = -1;
11900+ if (a->inode)
11901+ err = hn_gen_by_inode(a->h_name, a->h_nlen, a->inode,
11902+ isdir);
11903+ if (err && a->dentry)
11904+ hn_gen_by_name(a->dentry, isdir);
11905+ /* ignore this error */
1facf9fc 11906+ }
1facf9fc 11907+
4a4d8108
AM
11908+ /* make dir entries obsolete */
11909+ if (au_ftest_hnjob(a->flags, DIRENT) && a->inode) {
11910+ struct au_vdir *vdir;
1facf9fc 11911+
4a4d8108
AM
11912+ vdir = au_ivdir(a->inode);
11913+ if (vdir)
11914+ vdir->vd_jiffy = 0;
11915+ /* IMustLock(a->inode); */
11916+ /* a->inode->i_version++; */
11917+ }
1facf9fc 11918+
4a4d8108
AM
11919+ /* can do nothing but warn */
11920+ if (au_ftest_hnjob(a->flags, MNTPNT)
11921+ && a->dentry
11922+ && d_mountpoint(a->dentry))
11923+ pr_warning("mount-point %.*s is removed or renamed\n",
11924+ AuDLNPair(a->dentry));
1facf9fc 11925+
4a4d8108 11926+ return 0;
1308ab2a 11927+}
1facf9fc 11928+
1308ab2a 11929+/* ---------------------------------------------------------------------- */
1facf9fc 11930+
4a4d8108
AM
11931+static struct dentry *lookup_wlock_by_name(char *name, unsigned int nlen,
11932+ struct inode *dir)
1308ab2a 11933+{
4a4d8108
AM
11934+ struct dentry *dentry, *d, *parent;
11935+ struct qstr *dname;
1308ab2a 11936+
4a4d8108
AM
11937+ parent = d_find_alias(dir);
11938+ if (!parent)
11939+ return NULL;
1308ab2a 11940+
4a4d8108 11941+ dentry = NULL;
027c5e7a 11942+ spin_lock(&parent->d_lock);
4a4d8108
AM
11943+ list_for_each_entry(d, &parent->d_subdirs, d_u.d_child) {
11944+ /* AuDbg("%.*s\n", AuDLNPair(d)); */
027c5e7a 11945+ spin_lock_nested(&d->d_lock, DENTRY_D_LOCK_NESTED);
4a4d8108
AM
11946+ dname = &d->d_name;
11947+ if (dname->len != nlen || memcmp(dname->name, name, nlen))
027c5e7a
AM
11948+ goto cont_unlock;
11949+ if (au_di(d))
11950+ au_digen_dec(d);
11951+ else
11952+ goto cont_unlock;
11953+ if (d->d_count) {
11954+ dentry = dget_dlock(d);
4a4d8108 11955+ spin_unlock(&d->d_lock);
027c5e7a 11956+ break;
dece6358 11957+ }
1facf9fc 11958+
027c5e7a
AM
11959+ cont_unlock:
11960+ spin_unlock(&d->d_lock);
1308ab2a 11961+ }
027c5e7a 11962+ spin_unlock(&parent->d_lock);
4a4d8108 11963+ dput(parent);
1facf9fc 11964+
4a4d8108
AM
11965+ if (dentry)
11966+ di_write_lock_child(dentry);
1308ab2a 11967+
4a4d8108
AM
11968+ return dentry;
11969+}
dece6358 11970+
4a4d8108
AM
11971+static struct inode *lookup_wlock_by_ino(struct super_block *sb,
11972+ aufs_bindex_t bindex, ino_t h_ino)
11973+{
11974+ struct inode *inode;
11975+ ino_t ino;
11976+ int err;
11977+
11978+ inode = NULL;
11979+ err = au_xino_read(sb, bindex, h_ino, &ino);
11980+ if (!err && ino)
11981+ inode = ilookup(sb, ino);
11982+ if (!inode)
11983+ goto out;
11984+
11985+ if (unlikely(inode->i_ino == AUFS_ROOT_INO)) {
11986+ pr_warning("wrong root branch\n");
11987+ iput(inode);
11988+ inode = NULL;
11989+ goto out;
1308ab2a 11990+ }
11991+
4a4d8108 11992+ ii_write_lock_child(inode);
1308ab2a 11993+
4f0767ce 11994+out:
4a4d8108 11995+ return inode;
dece6358
AM
11996+}
11997+
4a4d8108 11998+static void au_hn_bh(void *_args)
1facf9fc 11999+{
4a4d8108
AM
12000+ struct au_hnotify_args *a = _args;
12001+ struct super_block *sb;
12002+ aufs_bindex_t bindex, bend, bfound;
12003+ unsigned char xino, try_iput;
1facf9fc 12004+ int err;
1308ab2a 12005+ struct inode *inode;
4a4d8108
AM
12006+ ino_t h_ino;
12007+ struct hn_job_args args;
12008+ struct dentry *dentry;
12009+ struct au_sbinfo *sbinfo;
1facf9fc 12010+
4a4d8108
AM
12011+ AuDebugOn(!_args);
12012+ AuDebugOn(!a->h_dir);
12013+ AuDebugOn(!a->dir);
12014+ AuDebugOn(!a->mask);
12015+ AuDbg("mask 0x%x, i%lu, hi%lu, hci%lu\n",
12016+ a->mask, a->dir->i_ino, a->h_dir->i_ino,
12017+ a->h_child_inode ? a->h_child_inode->i_ino : 0);
1facf9fc 12018+
4a4d8108
AM
12019+ inode = NULL;
12020+ dentry = NULL;
12021+ /*
12022+ * do not lock a->dir->i_mutex here
12023+ * because of d_revalidate() may cause a deadlock.
12024+ */
12025+ sb = a->dir->i_sb;
12026+ AuDebugOn(!sb);
12027+ sbinfo = au_sbi(sb);
12028+ AuDebugOn(!sbinfo);
7f207e10 12029+ si_write_lock(sb, AuLock_NOPLMW);
1facf9fc 12030+
4a4d8108
AM
12031+ ii_read_lock_parent(a->dir);
12032+ bfound = -1;
12033+ bend = au_ibend(a->dir);
12034+ for (bindex = au_ibstart(a->dir); bindex <= bend; bindex++)
12035+ if (au_h_iptr(a->dir, bindex) == a->h_dir) {
12036+ bfound = bindex;
12037+ break;
12038+ }
12039+ ii_read_unlock(a->dir);
12040+ if (unlikely(bfound < 0))
12041+ goto out;
1facf9fc 12042+
4a4d8108
AM
12043+ xino = !!au_opt_test(au_mntflags(sb), XINO);
12044+ h_ino = 0;
12045+ if (a->h_child_inode)
12046+ h_ino = a->h_child_inode->i_ino;
1facf9fc 12047+
4a4d8108
AM
12048+ if (a->h_child_nlen
12049+ && (au_ftest_hnjob(a->flags[AuHn_CHILD], GEN)
12050+ || au_ftest_hnjob(a->flags[AuHn_CHILD], MNTPNT)))
12051+ dentry = lookup_wlock_by_name(a->h_child_name, a->h_child_nlen,
12052+ a->dir);
12053+ try_iput = 0;
12054+ if (dentry)
12055+ inode = dentry->d_inode;
12056+ if (xino && !inode && h_ino
12057+ && (au_ftest_hnjob(a->flags[AuHn_CHILD], XINO0)
12058+ || au_ftest_hnjob(a->flags[AuHn_CHILD], TRYXINO0)
12059+ || au_ftest_hnjob(a->flags[AuHn_CHILD], GEN))) {
12060+ inode = lookup_wlock_by_ino(sb, bfound, h_ino);
12061+ try_iput = 1;
12062+ }
1facf9fc 12063+
4a4d8108
AM
12064+ args.flags = a->flags[AuHn_CHILD];
12065+ args.dentry = dentry;
12066+ args.inode = inode;
12067+ args.h_inode = a->h_child_inode;
12068+ args.dir = a->dir;
12069+ args.h_dir = a->h_dir;
12070+ args.h_name = a->h_child_name;
12071+ args.h_nlen = a->h_child_nlen;
12072+ err = hn_job(&args);
12073+ if (dentry) {
027c5e7a 12074+ if (au_di(dentry))
4a4d8108
AM
12075+ di_write_unlock(dentry);
12076+ dput(dentry);
12077+ }
12078+ if (inode && try_iput) {
12079+ ii_write_unlock(inode);
12080+ iput(inode);
12081+ }
1facf9fc 12082+
4a4d8108
AM
12083+ ii_write_lock_parent(a->dir);
12084+ args.flags = a->flags[AuHn_PARENT];
12085+ args.dentry = NULL;
12086+ args.inode = a->dir;
12087+ args.h_inode = a->h_dir;
12088+ args.dir = NULL;
12089+ args.h_dir = NULL;
12090+ args.h_name = NULL;
12091+ args.h_nlen = 0;
12092+ err = hn_job(&args);
12093+ ii_write_unlock(a->dir);
1facf9fc 12094+
4f0767ce 12095+out:
4a4d8108
AM
12096+ iput(a->h_child_inode);
12097+ iput(a->h_dir);
12098+ iput(a->dir);
027c5e7a
AM
12099+ si_write_unlock(sb);
12100+ au_nwt_done(&sbinfo->si_nowait);
1308ab2a 12101+ kfree(a);
dece6358 12102+}
1facf9fc 12103+
4a4d8108
AM
12104+/* ---------------------------------------------------------------------- */
12105+
12106+int au_hnotify(struct inode *h_dir, struct au_hnotify *hnotify, u32 mask,
12107+ struct qstr *h_child_qstr, struct inode *h_child_inode)
dece6358 12108+{
4a4d8108
AM
12109+ int err, len;
12110+ unsigned int flags[AuHnLast];
12111+ unsigned char isdir, isroot, wh;
12112+ struct inode *dir;
12113+ struct au_hnotify_args *args;
12114+ char *p, *h_child_name;
dece6358 12115+
1308ab2a 12116+ err = 0;
4a4d8108
AM
12117+ AuDebugOn(!hnotify || !hnotify->hn_aufs_inode);
12118+ dir = igrab(hnotify->hn_aufs_inode);
12119+ if (!dir)
12120+ goto out;
1facf9fc 12121+
4a4d8108
AM
12122+ isroot = (dir->i_ino == AUFS_ROOT_INO);
12123+ wh = 0;
12124+ h_child_name = (void *)h_child_qstr->name;
12125+ len = h_child_qstr->len;
12126+ if (h_child_name) {
12127+ if (len > AUFS_WH_PFX_LEN
12128+ && !memcmp(h_child_name, AUFS_WH_PFX, AUFS_WH_PFX_LEN)) {
12129+ h_child_name += AUFS_WH_PFX_LEN;
12130+ len -= AUFS_WH_PFX_LEN;
12131+ wh = 1;
12132+ }
1facf9fc 12133+ }
dece6358 12134+
4a4d8108
AM
12135+ isdir = 0;
12136+ if (h_child_inode)
12137+ isdir = !!S_ISDIR(h_child_inode->i_mode);
12138+ flags[AuHn_PARENT] = AuHnJob_ISDIR;
12139+ flags[AuHn_CHILD] = 0;
12140+ if (isdir)
12141+ flags[AuHn_CHILD] = AuHnJob_ISDIR;
12142+ au_fset_hnjob(flags[AuHn_PARENT], DIRENT);
12143+ au_fset_hnjob(flags[AuHn_CHILD], GEN);
12144+ switch (mask & FS_EVENTS_POSS_ON_CHILD) {
12145+ case FS_MOVED_FROM:
12146+ case FS_MOVED_TO:
12147+ au_fset_hnjob(flags[AuHn_CHILD], XINO0);
12148+ au_fset_hnjob(flags[AuHn_CHILD], MNTPNT);
12149+ /*FALLTHROUGH*/
12150+ case FS_CREATE:
12151+ AuDebugOn(!h_child_name || !h_child_inode);
12152+ break;
1facf9fc 12153+
4a4d8108
AM
12154+ case FS_DELETE:
12155+ /*
12156+ * aufs never be able to get this child inode.
12157+ * revalidation should be in d_revalidate()
12158+ * by checking i_nlink, i_generation or d_unhashed().
12159+ */
12160+ AuDebugOn(!h_child_name);
12161+ au_fset_hnjob(flags[AuHn_CHILD], TRYXINO0);
12162+ au_fset_hnjob(flags[AuHn_CHILD], MNTPNT);
12163+ break;
dece6358 12164+
4a4d8108
AM
12165+ default:
12166+ AuDebugOn(1);
12167+ }
1308ab2a 12168+
4a4d8108
AM
12169+ if (wh)
12170+ h_child_inode = NULL;
1308ab2a 12171+
4a4d8108
AM
12172+ err = -ENOMEM;
12173+ /* iput() and kfree() will be called in au_hnotify() */
4a4d8108 12174+ args = kmalloc(sizeof(*args) + len + 1, GFP_NOFS);
4a4d8108
AM
12175+ if (unlikely(!args)) {
12176+ AuErr1("no memory\n");
12177+ iput(dir);
12178+ goto out;
12179+ }
12180+ args->flags[AuHn_PARENT] = flags[AuHn_PARENT];
12181+ args->flags[AuHn_CHILD] = flags[AuHn_CHILD];
12182+ args->mask = mask;
12183+ args->dir = dir;
12184+ args->h_dir = igrab(h_dir);
12185+ if (h_child_inode)
12186+ h_child_inode = igrab(h_child_inode); /* can be NULL */
12187+ args->h_child_inode = h_child_inode;
12188+ args->h_child_nlen = len;
12189+ if (len) {
12190+ p = (void *)args;
12191+ p += sizeof(*args);
12192+ memcpy(p, h_child_name, len);
12193+ p[len] = 0;
1308ab2a 12194+ }
1308ab2a 12195+
4a4d8108 12196+ err = au_wkq_nowait(au_hn_bh, args, dir->i_sb);
4a4d8108
AM
12197+ if (unlikely(err)) {
12198+ pr_err("wkq %d\n", err);
12199+ iput(args->h_child_inode);
12200+ iput(args->h_dir);
12201+ iput(args->dir);
12202+ kfree(args);
1facf9fc 12203+ }
1facf9fc 12204+
4a4d8108 12205+out:
1facf9fc 12206+ return err;
12207+}
12208+
027c5e7a
AM
12209+/* ---------------------------------------------------------------------- */
12210+
12211+int au_hnotify_reset_br(unsigned int udba, struct au_branch *br, int perm)
12212+{
12213+ int err;
12214+
12215+ AuDebugOn(!(udba & AuOptMask_UDBA));
12216+
12217+ err = 0;
12218+ if (au_hnotify_op.reset_br)
12219+ err = au_hnotify_op.reset_br(udba, br, perm);
12220+
12221+ return err;
12222+}
12223+
12224+int au_hnotify_init_br(struct au_branch *br, int perm)
12225+{
12226+ int err;
12227+
12228+ err = 0;
12229+ if (au_hnotify_op.init_br)
12230+ err = au_hnotify_op.init_br(br, perm);
12231+
12232+ return err;
12233+}
12234+
12235+void au_hnotify_fin_br(struct au_branch *br)
12236+{
12237+ if (au_hnotify_op.fin_br)
12238+ au_hnotify_op.fin_br(br);
12239+}
12240+
4a4d8108
AM
12241+static void au_hn_destroy_cache(void)
12242+{
12243+ kmem_cache_destroy(au_cachep[AuCache_HNOTIFY]);
12244+ au_cachep[AuCache_HNOTIFY] = NULL;
12245+}
1308ab2a 12246+
4a4d8108 12247+int __init au_hnotify_init(void)
1facf9fc 12248+{
1308ab2a 12249+ int err;
1308ab2a 12250+
4a4d8108
AM
12251+ err = -ENOMEM;
12252+ au_cachep[AuCache_HNOTIFY] = AuCache(au_hnotify);
12253+ if (au_cachep[AuCache_HNOTIFY]) {
027c5e7a
AM
12254+ err = 0;
12255+ if (au_hnotify_op.init)
12256+ err = au_hnotify_op.init();
4a4d8108
AM
12257+ if (unlikely(err))
12258+ au_hn_destroy_cache();
1308ab2a 12259+ }
1308ab2a 12260+ AuTraceErr(err);
4a4d8108 12261+ return err;
1308ab2a 12262+}
12263+
4a4d8108 12264+void au_hnotify_fin(void)
1308ab2a 12265+{
027c5e7a
AM
12266+ if (au_hnotify_op.fin)
12267+ au_hnotify_op.fin();
4a4d8108
AM
12268+ /* cf. au_cache_fin() */
12269+ if (au_cachep[AuCache_HNOTIFY])
12270+ au_hn_destroy_cache();
dece6358 12271+}
7f207e10
AM
12272diff -urN /usr/share/empty/fs/aufs/iinfo.c linux/fs/aufs/iinfo.c
12273--- /usr/share/empty/fs/aufs/iinfo.c 1970-01-01 01:00:00.000000000 +0100
87a755f4 12274+++ linux/fs/aufs/iinfo.c 2011-03-17 10:46:59.000000000 +0100
027c5e7a 12275@@ -0,0 +1,264 @@
dece6358 12276+/*
027c5e7a 12277+ * Copyright (C) 2005-2011 Junjiro R. Okajima
dece6358
AM
12278+ *
12279+ * This program, aufs is free software; you can redistribute it and/or modify
12280+ * it under the terms of the GNU General Public License as published by
12281+ * the Free Software Foundation; either version 2 of the License, or
12282+ * (at your option) any later version.
12283+ *
12284+ * This program is distributed in the hope that it will be useful,
12285+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
12286+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12287+ * GNU General Public License for more details.
12288+ *
12289+ * You should have received a copy of the GNU General Public License
12290+ * along with this program; if not, write to the Free Software
12291+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
12292+ */
1facf9fc 12293+
dece6358 12294+/*
4a4d8108 12295+ * inode private data
dece6358 12296+ */
1facf9fc 12297+
1308ab2a 12298+#include "aufs.h"
1facf9fc 12299+
4a4d8108 12300+struct inode *au_h_iptr(struct inode *inode, aufs_bindex_t bindex)
1308ab2a 12301+{
4a4d8108 12302+ struct inode *h_inode;
1facf9fc 12303+
4a4d8108 12304+ IiMustAnyLock(inode);
1facf9fc 12305+
4a4d8108
AM
12306+ h_inode = au_ii(inode)->ii_hinode[0 + bindex].hi_inode;
12307+ AuDebugOn(h_inode && atomic_read(&h_inode->i_count) <= 0);
12308+ return h_inode;
12309+}
1facf9fc 12310+
4a4d8108
AM
12311+/* todo: hard/soft set? */
12312+void au_hiput(struct au_hinode *hinode)
12313+{
12314+ au_hn_free(hinode);
12315+ dput(hinode->hi_whdentry);
12316+ iput(hinode->hi_inode);
12317+}
1facf9fc 12318+
4a4d8108
AM
12319+unsigned int au_hi_flags(struct inode *inode, int isdir)
12320+{
12321+ unsigned int flags;
12322+ const unsigned int mnt_flags = au_mntflags(inode->i_sb);
1facf9fc 12323+
4a4d8108
AM
12324+ flags = 0;
12325+ if (au_opt_test(mnt_flags, XINO))
12326+ au_fset_hi(flags, XINO);
12327+ if (isdir && au_opt_test(mnt_flags, UDBA_HNOTIFY))
12328+ au_fset_hi(flags, HNOTIFY);
12329+ return flags;
1facf9fc 12330+}
12331+
4a4d8108
AM
12332+void au_set_h_iptr(struct inode *inode, aufs_bindex_t bindex,
12333+ struct inode *h_inode, unsigned int flags)
1308ab2a 12334+{
4a4d8108
AM
12335+ struct au_hinode *hinode;
12336+ struct inode *hi;
12337+ struct au_iinfo *iinfo = au_ii(inode);
1facf9fc 12338+
4a4d8108 12339+ IiMustWriteLock(inode);
dece6358 12340+
4a4d8108
AM
12341+ hinode = iinfo->ii_hinode + bindex;
12342+ hi = hinode->hi_inode;
12343+ AuDebugOn(h_inode && atomic_read(&h_inode->i_count) <= 0);
12344+
12345+ if (hi)
12346+ au_hiput(hinode);
12347+ hinode->hi_inode = h_inode;
12348+ if (h_inode) {
12349+ int err;
12350+ struct super_block *sb = inode->i_sb;
12351+ struct au_branch *br;
12352+
027c5e7a
AM
12353+ AuDebugOn(inode->i_mode
12354+ && (h_inode->i_mode & S_IFMT)
12355+ != (inode->i_mode & S_IFMT));
4a4d8108
AM
12356+ if (bindex == iinfo->ii_bstart)
12357+ au_cpup_igen(inode, h_inode);
12358+ br = au_sbr(sb, bindex);
12359+ hinode->hi_id = br->br_id;
12360+ if (au_ftest_hi(flags, XINO)) {
12361+ err = au_xino_write(sb, bindex, h_inode->i_ino,
12362+ inode->i_ino);
12363+ if (unlikely(err))
12364+ AuIOErr1("failed au_xino_write() %d\n", err);
12365+ }
12366+
12367+ if (au_ftest_hi(flags, HNOTIFY)
12368+ && au_br_hnotifyable(br->br_perm)) {
027c5e7a 12369+ err = au_hn_alloc(hinode, inode);
4a4d8108
AM
12370+ if (unlikely(err))
12371+ AuIOErr1("au_hn_alloc() %d\n", err);
1308ab2a 12372+ }
12373+ }
4a4d8108 12374+}
dece6358 12375+
4a4d8108
AM
12376+void au_set_hi_wh(struct inode *inode, aufs_bindex_t bindex,
12377+ struct dentry *h_wh)
12378+{
12379+ struct au_hinode *hinode;
dece6358 12380+
4a4d8108
AM
12381+ IiMustWriteLock(inode);
12382+
12383+ hinode = au_ii(inode)->ii_hinode + bindex;
12384+ AuDebugOn(hinode->hi_whdentry);
12385+ hinode->hi_whdentry = h_wh;
1facf9fc 12386+}
12387+
4a4d8108 12388+void au_update_iigen(struct inode *inode)
1308ab2a 12389+{
4a4d8108
AM
12390+ atomic_set(&au_ii(inode)->ii_generation, au_sigen(inode->i_sb));
12391+ /* smp_mb(); */ /* atomic_set */
12392+}
1facf9fc 12393+
4a4d8108
AM
12394+/* it may be called at remount time, too */
12395+void au_update_ibrange(struct inode *inode, int do_put_zero)
12396+{
12397+ struct au_iinfo *iinfo;
027c5e7a 12398+ aufs_bindex_t bindex, bend;
1facf9fc 12399+
4a4d8108 12400+ iinfo = au_ii(inode);
027c5e7a 12401+ if (!iinfo)
4a4d8108 12402+ return;
1facf9fc 12403+
4a4d8108 12404+ IiMustWriteLock(inode);
1facf9fc 12405+
027c5e7a 12406+ if (do_put_zero && iinfo->ii_bstart >= 0) {
4a4d8108
AM
12407+ for (bindex = iinfo->ii_bstart; bindex <= iinfo->ii_bend;
12408+ bindex++) {
12409+ struct inode *h_i;
1facf9fc 12410+
4a4d8108 12411+ h_i = iinfo->ii_hinode[0 + bindex].hi_inode;
027c5e7a
AM
12412+ if (h_i && !h_i->i_nlink)
12413+ au_set_h_iptr(inode, bindex, NULL, 0);
12414+ }
4a4d8108
AM
12415+ }
12416+
027c5e7a
AM
12417+ iinfo->ii_bstart = -1;
12418+ iinfo->ii_bend = -1;
12419+ bend = au_sbend(inode->i_sb);
12420+ for (bindex = 0; bindex <= bend; bindex++)
12421+ if (iinfo->ii_hinode[0 + bindex].hi_inode) {
12422+ iinfo->ii_bstart = bindex;
4a4d8108 12423+ break;
027c5e7a
AM
12424+ }
12425+ if (iinfo->ii_bstart >= 0)
12426+ for (bindex = bend; bindex >= iinfo->ii_bstart; bindex--)
12427+ if (iinfo->ii_hinode[0 + bindex].hi_inode) {
12428+ iinfo->ii_bend = bindex;
12429+ break;
12430+ }
12431+ AuDebugOn(iinfo->ii_bstart > iinfo->ii_bend);
1308ab2a 12432+}
1facf9fc 12433+
dece6358 12434+/* ---------------------------------------------------------------------- */
1facf9fc 12435+
4a4d8108 12436+void au_icntnr_init_once(void *_c)
dece6358 12437+{
4a4d8108
AM
12438+ struct au_icntnr *c = _c;
12439+ struct au_iinfo *iinfo = &c->iinfo;
e49829fe 12440+ static struct lock_class_key aufs_ii;
1facf9fc 12441+
4a4d8108 12442+ au_rw_init(&iinfo->ii_rwsem);
e49829fe 12443+ au_rw_class(&iinfo->ii_rwsem, &aufs_ii);
4a4d8108
AM
12444+ inode_init_once(&c->vfs_inode);
12445+}
1facf9fc 12446+
4a4d8108
AM
12447+int au_iinfo_init(struct inode *inode)
12448+{
12449+ struct au_iinfo *iinfo;
12450+ struct super_block *sb;
12451+ int nbr, i;
1facf9fc 12452+
4a4d8108
AM
12453+ sb = inode->i_sb;
12454+ iinfo = &(container_of(inode, struct au_icntnr, vfs_inode)->iinfo);
12455+ nbr = au_sbend(sb) + 1;
12456+ if (unlikely(nbr <= 0))
12457+ nbr = 1;
12458+ iinfo->ii_hinode = kcalloc(nbr, sizeof(*iinfo->ii_hinode), GFP_NOFS);
12459+ if (iinfo->ii_hinode) {
7f207e10 12460+ au_ninodes_inc(sb);
4a4d8108
AM
12461+ for (i = 0; i < nbr; i++)
12462+ iinfo->ii_hinode[i].hi_id = -1;
1facf9fc 12463+
4a4d8108
AM
12464+ atomic_set(&iinfo->ii_generation, au_sigen(sb));
12465+ /* smp_mb(); */ /* atomic_set */
12466+ iinfo->ii_bstart = -1;
12467+ iinfo->ii_bend = -1;
12468+ iinfo->ii_vdir = NULL;
12469+ return 0;
1308ab2a 12470+ }
4a4d8108
AM
12471+ return -ENOMEM;
12472+}
1facf9fc 12473+
4a4d8108
AM
12474+int au_ii_realloc(struct au_iinfo *iinfo, int nbr)
12475+{
12476+ int err, sz;
12477+ struct au_hinode *hip;
1facf9fc 12478+
4a4d8108
AM
12479+ AuRwMustWriteLock(&iinfo->ii_rwsem);
12480+
12481+ err = -ENOMEM;
12482+ sz = sizeof(*hip) * (iinfo->ii_bend + 1);
12483+ if (!sz)
12484+ sz = sizeof(*hip);
12485+ hip = au_kzrealloc(iinfo->ii_hinode, sz, sizeof(*hip) * nbr, GFP_NOFS);
12486+ if (hip) {
12487+ iinfo->ii_hinode = hip;
12488+ err = 0;
1308ab2a 12489+ }
4a4d8108 12490+
1308ab2a 12491+ return err;
1facf9fc 12492+}
12493+
4a4d8108 12494+void au_iinfo_fin(struct inode *inode)
1facf9fc 12495+{
4a4d8108
AM
12496+ struct au_iinfo *iinfo;
12497+ struct au_hinode *hi;
12498+ struct super_block *sb;
b752ccd1
AM
12499+ aufs_bindex_t bindex, bend;
12500+ const unsigned char unlinked = !inode->i_nlink;
1308ab2a 12501+
4a4d8108
AM
12502+ iinfo = au_ii(inode);
12503+ /* bad_inode case */
12504+ if (!iinfo)
12505+ return;
1308ab2a 12506+
b752ccd1 12507+ sb = inode->i_sb;
7f207e10 12508+ au_ninodes_dec(sb);
b752ccd1
AM
12509+ if (si_pid_test(sb))
12510+ au_xino_delete_inode(inode, unlinked);
12511+ else {
12512+ /*
12513+ * it is safe to hide the dependency between sbinfo and
12514+ * sb->s_umount.
12515+ */
12516+ lockdep_off();
12517+ si_noflush_read_lock(sb);
12518+ au_xino_delete_inode(inode, unlinked);
12519+ si_read_unlock(sb);
12520+ lockdep_on();
12521+ }
12522+
4a4d8108
AM
12523+ if (iinfo->ii_vdir)
12524+ au_vdir_free(iinfo->ii_vdir);
1308ab2a 12525+
b752ccd1
AM
12526+ bindex = iinfo->ii_bstart;
12527+ if (bindex >= 0) {
12528+ hi = iinfo->ii_hinode + bindex;
4a4d8108 12529+ bend = iinfo->ii_bend;
b752ccd1
AM
12530+ while (bindex++ <= bend) {
12531+ if (hi->hi_inode)
4a4d8108 12532+ au_hiput(hi);
4a4d8108
AM
12533+ hi++;
12534+ }
12535+ }
4a4d8108 12536+ kfree(iinfo->ii_hinode);
027c5e7a 12537+ iinfo->ii_hinode = NULL;
4a4d8108 12538+ AuRwDestroy(&iinfo->ii_rwsem);
dece6358 12539+}
7f207e10
AM
12540diff -urN /usr/share/empty/fs/aufs/inode.c linux/fs/aufs/inode.c
12541--- /usr/share/empty/fs/aufs/inode.c 1970-01-01 01:00:00.000000000 +0100
87a755f4 12542+++ linux/fs/aufs/inode.c 2011-03-17 10:46:59.000000000 +0100
027c5e7a 12543@@ -0,0 +1,471 @@
4a4d8108 12544+/*
027c5e7a 12545+ * Copyright (C) 2005-2011 Junjiro R. Okajima
4a4d8108
AM
12546+ *
12547+ * This program, aufs is free software; you can redistribute it and/or modify
12548+ * it under the terms of the GNU General Public License as published by
12549+ * the Free Software Foundation; either version 2 of the License, or
12550+ * (at your option) any later version.
12551+ *
12552+ * This program is distributed in the hope that it will be useful,
12553+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
12554+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12555+ * GNU General Public License for more details.
12556+ *
12557+ * You should have received a copy of the GNU General Public License
12558+ * along with this program; if not, write to the Free Software
12559+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
12560+ */
1facf9fc 12561+
4a4d8108
AM
12562+/*
12563+ * inode functions
12564+ */
1facf9fc 12565+
4a4d8108 12566+#include "aufs.h"
1308ab2a 12567+
4a4d8108
AM
12568+struct inode *au_igrab(struct inode *inode)
12569+{
12570+ if (inode) {
12571+ AuDebugOn(!atomic_read(&inode->i_count));
027c5e7a 12572+ ihold(inode);
1facf9fc 12573+ }
4a4d8108
AM
12574+ return inode;
12575+}
1facf9fc 12576+
4a4d8108
AM
12577+static void au_refresh_hinode_attr(struct inode *inode, int do_version)
12578+{
12579+ au_cpup_attr_all(inode, /*force*/0);
12580+ au_update_iigen(inode);
12581+ if (do_version)
12582+ inode->i_version++;
dece6358 12583+}
1facf9fc 12584+
027c5e7a 12585+static int au_ii_refresh(struct inode *inode, int *update)
dece6358 12586+{
4a4d8108 12587+ int err, e;
027c5e7a 12588+ umode_t type;
4a4d8108 12589+ aufs_bindex_t bindex, new_bindex;
1308ab2a 12590+ struct super_block *sb;
4a4d8108 12591+ struct au_iinfo *iinfo;
027c5e7a 12592+ struct au_hinode *p, *q, tmp;
1facf9fc 12593+
4a4d8108 12594+ IiMustWriteLock(inode);
1facf9fc 12595+
027c5e7a 12596+ *update = 0;
4a4d8108 12597+ sb = inode->i_sb;
027c5e7a 12598+ type = inode->i_mode & S_IFMT;
4a4d8108
AM
12599+ iinfo = au_ii(inode);
12600+ err = au_ii_realloc(iinfo, au_sbend(sb) + 1);
12601+ if (unlikely(err))
1308ab2a 12602+ goto out;
1facf9fc 12603+
027c5e7a 12604+ AuDebugOn(iinfo->ii_bstart < 0);
4a4d8108 12605+ p = iinfo->ii_hinode + iinfo->ii_bstart;
4a4d8108
AM
12606+ for (bindex = iinfo->ii_bstart; bindex <= iinfo->ii_bend;
12607+ bindex++, p++) {
12608+ if (!p->hi_inode)
12609+ continue;
1facf9fc 12610+
027c5e7a 12611+ AuDebugOn(type != (p->hi_inode->i_mode & S_IFMT));
4a4d8108
AM
12612+ new_bindex = au_br_index(sb, p->hi_id);
12613+ if (new_bindex == bindex)
12614+ continue;
1facf9fc 12615+
4a4d8108 12616+ if (new_bindex < 0) {
027c5e7a 12617+ *update = 1;
4a4d8108
AM
12618+ au_hiput(p);
12619+ p->hi_inode = NULL;
12620+ continue;
1308ab2a 12621+ }
4a4d8108
AM
12622+
12623+ if (new_bindex < iinfo->ii_bstart)
12624+ iinfo->ii_bstart = new_bindex;
12625+ if (iinfo->ii_bend < new_bindex)
12626+ iinfo->ii_bend = new_bindex;
12627+ /* swap two lower inode, and loop again */
12628+ q = iinfo->ii_hinode + new_bindex;
12629+ tmp = *q;
12630+ *q = *p;
12631+ *p = tmp;
12632+ if (tmp.hi_inode) {
12633+ bindex--;
12634+ p--;
1308ab2a 12635+ }
12636+ }
4a4d8108
AM
12637+ au_update_ibrange(inode, /*do_put_zero*/0);
12638+ e = au_dy_irefresh(inode);
12639+ if (unlikely(e && !err))
12640+ err = e;
1facf9fc 12641+
4f0767ce 12642+out:
027c5e7a
AM
12643+ AuTraceErr(err);
12644+ return err;
12645+}
12646+
12647+int au_refresh_hinode_self(struct inode *inode)
12648+{
12649+ int err, update;
12650+
12651+ err = au_ii_refresh(inode, &update);
12652+ if (!err)
12653+ au_refresh_hinode_attr(inode, update && S_ISDIR(inode->i_mode));
12654+
12655+ AuTraceErr(err);
4a4d8108
AM
12656+ return err;
12657+}
1facf9fc 12658+
4a4d8108
AM
12659+int au_refresh_hinode(struct inode *inode, struct dentry *dentry)
12660+{
027c5e7a 12661+ int err, e, update;
4a4d8108 12662+ unsigned int flags;
027c5e7a 12663+ umode_t mode;
4a4d8108 12664+ aufs_bindex_t bindex, bend;
027c5e7a 12665+ unsigned char isdir;
4a4d8108
AM
12666+ struct au_hinode *p;
12667+ struct au_iinfo *iinfo;
1facf9fc 12668+
027c5e7a 12669+ err = au_ii_refresh(inode, &update);
4a4d8108
AM
12670+ if (unlikely(err))
12671+ goto out;
12672+
12673+ update = 0;
12674+ iinfo = au_ii(inode);
12675+ p = iinfo->ii_hinode + iinfo->ii_bstart;
027c5e7a
AM
12676+ mode = (inode->i_mode & S_IFMT);
12677+ isdir = S_ISDIR(mode);
4a4d8108
AM
12678+ flags = au_hi_flags(inode, isdir);
12679+ bend = au_dbend(dentry);
12680+ for (bindex = au_dbstart(dentry); bindex <= bend; bindex++) {
12681+ struct inode *h_i;
12682+ struct dentry *h_d;
12683+
12684+ h_d = au_h_dptr(dentry, bindex);
12685+ if (!h_d || !h_d->d_inode)
12686+ continue;
12687+
027c5e7a 12688+ AuDebugOn(mode != (h_d->d_inode->i_mode & S_IFMT));
4a4d8108
AM
12689+ if (iinfo->ii_bstart <= bindex && bindex <= iinfo->ii_bend) {
12690+ h_i = au_h_iptr(inode, bindex);
12691+ if (h_i) {
12692+ if (h_i == h_d->d_inode)
12693+ continue;
12694+ err = -EIO;
12695+ break;
12696+ }
12697+ }
12698+ if (bindex < iinfo->ii_bstart)
12699+ iinfo->ii_bstart = bindex;
12700+ if (iinfo->ii_bend < bindex)
12701+ iinfo->ii_bend = bindex;
12702+ au_set_h_iptr(inode, bindex, au_igrab(h_d->d_inode), flags);
12703+ update = 1;
1308ab2a 12704+ }
4a4d8108
AM
12705+ au_update_ibrange(inode, /*do_put_zero*/0);
12706+ e = au_dy_irefresh(inode);
12707+ if (unlikely(e && !err))
12708+ err = e;
027c5e7a
AM
12709+ if (!err)
12710+ au_refresh_hinode_attr(inode, update && isdir);
4a4d8108 12711+
4f0767ce 12712+out:
4a4d8108 12713+ AuTraceErr(err);
1308ab2a 12714+ return err;
dece6358
AM
12715+}
12716+
4a4d8108 12717+static int set_inode(struct inode *inode, struct dentry *dentry)
dece6358 12718+{
4a4d8108
AM
12719+ int err;
12720+ unsigned int flags;
12721+ umode_t mode;
12722+ aufs_bindex_t bindex, bstart, btail;
12723+ unsigned char isdir;
12724+ struct dentry *h_dentry;
12725+ struct inode *h_inode;
12726+ struct au_iinfo *iinfo;
dece6358 12727+
4a4d8108 12728+ IiMustWriteLock(inode);
dece6358 12729+
4a4d8108
AM
12730+ err = 0;
12731+ isdir = 0;
12732+ bstart = au_dbstart(dentry);
12733+ h_inode = au_h_dptr(dentry, bstart)->d_inode;
12734+ mode = h_inode->i_mode;
12735+ switch (mode & S_IFMT) {
12736+ case S_IFREG:
12737+ btail = au_dbtail(dentry);
12738+ inode->i_op = &aufs_iop;
12739+ inode->i_fop = &aufs_file_fop;
12740+ err = au_dy_iaop(inode, bstart, h_inode);
12741+ if (unlikely(err))
12742+ goto out;
12743+ break;
12744+ case S_IFDIR:
12745+ isdir = 1;
12746+ btail = au_dbtaildir(dentry);
12747+ inode->i_op = &aufs_dir_iop;
12748+ inode->i_fop = &aufs_dir_fop;
12749+ break;
12750+ case S_IFLNK:
12751+ btail = au_dbtail(dentry);
12752+ inode->i_op = &aufs_symlink_iop;
12753+ break;
12754+ case S_IFBLK:
12755+ case S_IFCHR:
12756+ case S_IFIFO:
12757+ case S_IFSOCK:
12758+ btail = au_dbtail(dentry);
12759+ inode->i_op = &aufs_iop;
12760+ au_init_special_fop(inode, mode, h_inode->i_rdev);
12761+ break;
12762+ default:
12763+ AuIOErr("Unknown file type 0%o\n", mode);
12764+ err = -EIO;
1308ab2a 12765+ goto out;
4a4d8108 12766+ }
dece6358 12767+
4a4d8108
AM
12768+ /* do not set hnotify for whiteouted dirs (SHWH mode) */
12769+ flags = au_hi_flags(inode, isdir);
12770+ if (au_opt_test(au_mntflags(dentry->d_sb), SHWH)
12771+ && au_ftest_hi(flags, HNOTIFY)
12772+ && dentry->d_name.len > AUFS_WH_PFX_LEN
12773+ && !memcmp(dentry->d_name.name, AUFS_WH_PFX, AUFS_WH_PFX_LEN))
12774+ au_fclr_hi(flags, HNOTIFY);
12775+ iinfo = au_ii(inode);
12776+ iinfo->ii_bstart = bstart;
12777+ iinfo->ii_bend = btail;
12778+ for (bindex = bstart; bindex <= btail; bindex++) {
12779+ h_dentry = au_h_dptr(dentry, bindex);
12780+ if (h_dentry)
12781+ au_set_h_iptr(inode, bindex,
12782+ au_igrab(h_dentry->d_inode), flags);
12783+ }
12784+ au_cpup_attr_all(inode, /*force*/1);
dece6358 12785+
4f0767ce 12786+out:
4a4d8108
AM
12787+ return err;
12788+}
dece6358 12789+
027c5e7a
AM
12790+/*
12791+ * successful returns with iinfo write_locked
12792+ * minus: errno
12793+ * zero: success, matched
12794+ * plus: no error, but unmatched
12795+ */
12796+static int reval_inode(struct inode *inode, struct dentry *dentry)
4a4d8108
AM
12797+{
12798+ int err;
12799+ aufs_bindex_t bindex, bend;
12800+ struct inode *h_inode, *h_dinode;
dece6358 12801+
4a4d8108
AM
12802+ /*
12803+ * before this function, if aufs got any iinfo lock, it must be only
12804+ * one, the parent dir.
12805+ * it can happen by UDBA and the obsoleted inode number.
12806+ */
12807+ err = -EIO;
12808+ if (unlikely(inode->i_ino == parent_ino(dentry)))
12809+ goto out;
12810+
027c5e7a 12811+ err = 1;
4a4d8108
AM
12812+ ii_write_lock_new_child(inode);
12813+ h_dinode = au_h_dptr(dentry, au_dbstart(dentry))->d_inode;
12814+ bend = au_ibend(inode);
12815+ for (bindex = au_ibstart(inode); bindex <= bend; bindex++) {
12816+ h_inode = au_h_iptr(inode, bindex);
12817+ if (h_inode && h_inode == h_dinode) {
4a4d8108 12818+ err = 0;
027c5e7a 12819+ if (au_iigen_test(inode, au_digen(dentry)))
4a4d8108
AM
12820+ err = au_refresh_hinode(inode, dentry);
12821+ break;
1308ab2a 12822+ }
1facf9fc 12823+ }
dece6358 12824+
4a4d8108
AM
12825+ if (unlikely(err))
12826+ ii_write_unlock(inode);
4f0767ce 12827+out:
1facf9fc 12828+ return err;
12829+}
1facf9fc 12830+
4a4d8108
AM
12831+int au_ino(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino,
12832+ unsigned int d_type, ino_t *ino)
1facf9fc 12833+{
4a4d8108
AM
12834+ int err;
12835+ struct mutex *mtx;
1facf9fc 12836+
b752ccd1 12837+ /* prevent hardlinked inode number from race condition */
4a4d8108 12838+ mtx = NULL;
b752ccd1 12839+ if (d_type != DT_DIR) {
4a4d8108
AM
12840+ mtx = &au_sbr(sb, bindex)->br_xino.xi_nondir_mtx;
12841+ mutex_lock(mtx);
12842+ }
12843+ err = au_xino_read(sb, bindex, h_ino, ino);
12844+ if (unlikely(err))
12845+ goto out;
1308ab2a 12846+
4a4d8108
AM
12847+ if (!*ino) {
12848+ err = -EIO;
12849+ *ino = au_xino_new_ino(sb);
12850+ if (unlikely(!*ino))
1facf9fc 12851+ goto out;
4a4d8108
AM
12852+ err = au_xino_write(sb, bindex, h_ino, *ino);
12853+ if (unlikely(err))
1308ab2a 12854+ goto out;
1308ab2a 12855+ }
1facf9fc 12856+
4f0767ce 12857+out:
b752ccd1 12858+ if (mtx)
4a4d8108 12859+ mutex_unlock(mtx);
1facf9fc 12860+ return err;
12861+}
12862+
4a4d8108
AM
12863+/* successful returns with iinfo write_locked */
12864+/* todo: return with unlocked? */
12865+struct inode *au_new_inode(struct dentry *dentry, int must_new)
1facf9fc 12866+{
b752ccd1 12867+ struct inode *inode, *h_inode;
4a4d8108
AM
12868+ struct dentry *h_dentry;
12869+ struct super_block *sb;
b752ccd1 12870+ struct mutex *mtx;
4a4d8108 12871+ ino_t h_ino, ino;
027c5e7a 12872+ int err;
4a4d8108 12873+ aufs_bindex_t bstart;
1facf9fc 12874+
4a4d8108
AM
12875+ sb = dentry->d_sb;
12876+ bstart = au_dbstart(dentry);
12877+ h_dentry = au_h_dptr(dentry, bstart);
b752ccd1
AM
12878+ h_inode = h_dentry->d_inode;
12879+ h_ino = h_inode->i_ino;
12880+
12881+ /*
12882+ * stop 'race'-ing between hardlinks under different
12883+ * parents.
12884+ */
12885+ mtx = NULL;
12886+ if (!S_ISDIR(h_inode->i_mode))
12887+ mtx = &au_sbr(sb, bstart)->br_xino.xi_nondir_mtx;
12888+
4f0767ce 12889+new_ino:
b752ccd1
AM
12890+ if (mtx)
12891+ mutex_lock(mtx);
4a4d8108
AM
12892+ err = au_xino_read(sb, bstart, h_ino, &ino);
12893+ inode = ERR_PTR(err);
12894+ if (unlikely(err))
12895+ goto out;
b752ccd1 12896+
4a4d8108
AM
12897+ if (!ino) {
12898+ ino = au_xino_new_ino(sb);
12899+ if (unlikely(!ino)) {
12900+ inode = ERR_PTR(-EIO);
dece6358
AM
12901+ goto out;
12902+ }
12903+ }
1facf9fc 12904+
4a4d8108
AM
12905+ AuDbg("i%lu\n", (unsigned long)ino);
12906+ inode = au_iget_locked(sb, ino);
12907+ err = PTR_ERR(inode);
12908+ if (IS_ERR(inode))
1facf9fc 12909+ goto out;
1facf9fc 12910+
4a4d8108
AM
12911+ AuDbg("%lx, new %d\n", inode->i_state, !!(inode->i_state & I_NEW));
12912+ if (inode->i_state & I_NEW) {
12913+ ii_write_lock_new_child(inode);
12914+ err = set_inode(inode, dentry);
12915+ if (!err) {
12916+ unlock_new_inode(inode);
12917+ goto out; /* success */
12918+ }
1308ab2a 12919+
027c5e7a
AM
12920+ /*
12921+ * iget_failed() calls iput(), but we need to call
12922+ * ii_write_unlock() after iget_failed(). so dirty hack for
12923+ * i_count.
12924+ */
12925+ atomic_inc(&inode->i_count);
4a4d8108 12926+ iget_failed(inode);
027c5e7a
AM
12927+ ii_write_unlock(inode);
12928+ au_xino_write(sb, bstart, h_ino, /*ino*/0);
12929+ /* ignore this error */
12930+ goto out_iput;
12931+ } else if (!must_new && !IS_DEADDIR(inode) && inode->i_nlink) {
b752ccd1
AM
12932+ /*
12933+ * horrible race condition between lookup, readdir and copyup
12934+ * (or something).
12935+ */
12936+ if (mtx)
12937+ mutex_unlock(mtx);
027c5e7a
AM
12938+ err = reval_inode(inode, dentry);
12939+ if (unlikely(err < 0)) {
12940+ mtx = NULL;
12941+ goto out_iput;
12942+ }
12943+
b752ccd1
AM
12944+ if (!err) {
12945+ mtx = NULL;
4a4d8108 12946+ goto out; /* success */
b752ccd1
AM
12947+ } else if (mtx)
12948+ mutex_lock(mtx);
4a4d8108
AM
12949+ }
12950+
12951+ if (unlikely(au_test_fs_unique_ino(h_dentry->d_inode)))
12952+ AuWarn1("Warning: Un-notified UDBA or repeatedly renamed dir,"
12953+ " b%d, %s, %.*s, hi%lu, i%lu.\n",
12954+ bstart, au_sbtype(h_dentry->d_sb), AuDLNPair(dentry),
12955+ (unsigned long)h_ino, (unsigned long)ino);
12956+ ino = 0;
12957+ err = au_xino_write(sb, bstart, h_ino, /*ino*/0);
12958+ if (!err) {
12959+ iput(inode);
b752ccd1
AM
12960+ if (mtx)
12961+ mutex_unlock(mtx);
4a4d8108
AM
12962+ goto new_ino;
12963+ }
1308ab2a 12964+
4f0767ce 12965+out_iput:
4a4d8108 12966+ iput(inode);
4a4d8108 12967+ inode = ERR_PTR(err);
4f0767ce 12968+out:
b752ccd1
AM
12969+ if (mtx)
12970+ mutex_unlock(mtx);
4a4d8108 12971+ return inode;
1facf9fc 12972+}
12973+
4a4d8108 12974+/* ---------------------------------------------------------------------- */
1facf9fc 12975+
4a4d8108
AM
12976+int au_test_ro(struct super_block *sb, aufs_bindex_t bindex,
12977+ struct inode *inode)
12978+{
12979+ int err;
1facf9fc 12980+
4a4d8108 12981+ err = au_br_rdonly(au_sbr(sb, bindex));
1facf9fc 12982+
4a4d8108
AM
12983+ /* pseudo-link after flushed may happen out of bounds */
12984+ if (!err
12985+ && inode
12986+ && au_ibstart(inode) <= bindex
12987+ && bindex <= au_ibend(inode)) {
12988+ /*
12989+ * permission check is unnecessary since vfsub routine
12990+ * will be called later
12991+ */
12992+ struct inode *hi = au_h_iptr(inode, bindex);
12993+ if (hi)
12994+ err = IS_IMMUTABLE(hi) ? -EROFS : 0;
1facf9fc 12995+ }
12996+
4a4d8108
AM
12997+ return err;
12998+}
dece6358 12999+
4a4d8108
AM
13000+int au_test_h_perm(struct inode *h_inode, int mask)
13001+{
13002+ if (!current_fsuid())
13003+ return 0;
13004+ return inode_permission(h_inode, mask);
13005+}
1facf9fc 13006+
4a4d8108
AM
13007+int au_test_h_perm_sio(struct inode *h_inode, int mask)
13008+{
13009+ if (au_test_nfs(h_inode->i_sb)
13010+ && (mask & MAY_WRITE)
13011+ && S_ISDIR(h_inode->i_mode))
13012+ mask |= MAY_READ; /* force permission check */
13013+ return au_test_h_perm(h_inode, mask);
1facf9fc 13014+}
7f207e10
AM
13015diff -urN /usr/share/empty/fs/aufs/inode.h linux/fs/aufs/inode.h
13016--- /usr/share/empty/fs/aufs/inode.h 1970-01-01 01:00:00.000000000 +0100
87a755f4 13017+++ linux/fs/aufs/inode.h 2011-03-17 10:46:59.000000000 +0100
027c5e7a 13018@@ -0,0 +1,546 @@
4a4d8108 13019+/*
027c5e7a 13020+ * Copyright (C) 2005-2011 Junjiro R. Okajima
4a4d8108
AM
13021+ *
13022+ * This program, aufs is free software; you can redistribute it and/or modify
13023+ * it under the terms of the GNU General Public License as published by
13024+ * the Free Software Foundation; either version 2 of the License, or
13025+ * (at your option) any later version.
13026+ *
13027+ * This program is distributed in the hope that it will be useful,
13028+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
13029+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13030+ * GNU General Public License for more details.
13031+ *
13032+ * You should have received a copy of the GNU General Public License
13033+ * along with this program; if not, write to the Free Software
13034+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
13035+ */
1facf9fc 13036+
1308ab2a 13037+/*
4a4d8108 13038+ * inode operations
1308ab2a 13039+ */
dece6358 13040+
4a4d8108
AM
13041+#ifndef __AUFS_INODE_H__
13042+#define __AUFS_INODE_H__
dece6358 13043+
4a4d8108 13044+#ifdef __KERNEL__
1308ab2a 13045+
4a4d8108
AM
13046+#include <linux/fs.h>
13047+#include <linux/fsnotify.h>
13048+#include <linux/aufs_type.h>
13049+#include "rwsem.h"
1308ab2a 13050+
4a4d8108 13051+struct vfsmount;
1facf9fc 13052+
4a4d8108
AM
13053+struct au_hnotify {
13054+#ifdef CONFIG_AUFS_HNOTIFY
13055+#ifdef CONFIG_AUFS_HFSNOTIFY
7f207e10 13056+ /* never use fsnotify_add_vfsmount_mark() */
0c5527e5 13057+ struct fsnotify_mark hn_mark;
7f207e10 13058+ int hn_mark_dead;
4a4d8108 13059+#endif
7f207e10 13060+ struct inode *hn_aufs_inode; /* no get/put */
4a4d8108
AM
13061+#endif
13062+} ____cacheline_aligned_in_smp;
1facf9fc 13063+
4a4d8108
AM
13064+struct au_hinode {
13065+ struct inode *hi_inode;
13066+ aufs_bindex_t hi_id;
13067+#ifdef CONFIG_AUFS_HNOTIFY
13068+ struct au_hnotify *hi_notify;
13069+#endif
dece6358 13070+
4a4d8108
AM
13071+ /* reference to the copied-up whiteout with get/put */
13072+ struct dentry *hi_whdentry;
13073+};
dece6358 13074+
4a4d8108
AM
13075+struct au_vdir;
13076+struct au_iinfo {
13077+ atomic_t ii_generation;
13078+ struct super_block *ii_hsb1; /* no get/put */
1facf9fc 13079+
4a4d8108
AM
13080+ struct au_rwsem ii_rwsem;
13081+ aufs_bindex_t ii_bstart, ii_bend;
13082+ __u32 ii_higen;
13083+ struct au_hinode *ii_hinode;
13084+ struct au_vdir *ii_vdir;
13085+};
1facf9fc 13086+
4a4d8108
AM
13087+struct au_icntnr {
13088+ struct au_iinfo iinfo;
13089+ struct inode vfs_inode;
13090+} ____cacheline_aligned_in_smp;
1308ab2a 13091+
4a4d8108
AM
13092+/* au_pin flags */
13093+#define AuPin_DI_LOCKED 1
13094+#define AuPin_MNT_WRITE (1 << 1)
13095+#define au_ftest_pin(flags, name) ((flags) & AuPin_##name)
7f207e10
AM
13096+#define au_fset_pin(flags, name) \
13097+ do { (flags) |= AuPin_##name; } while (0)
13098+#define au_fclr_pin(flags, name) \
13099+ do { (flags) &= ~AuPin_##name; } while (0)
4a4d8108
AM
13100+
13101+struct au_pin {
13102+ /* input */
13103+ struct dentry *dentry;
13104+ unsigned int udba;
13105+ unsigned char lsc_di, lsc_hi, flags;
13106+ aufs_bindex_t bindex;
13107+
13108+ /* output */
13109+ struct dentry *parent;
13110+ struct au_hinode *hdir;
13111+ struct vfsmount *h_mnt;
13112+};
1facf9fc 13113+
1308ab2a 13114+/* ---------------------------------------------------------------------- */
13115+
4a4d8108 13116+static inline struct au_iinfo *au_ii(struct inode *inode)
1facf9fc 13117+{
4a4d8108 13118+ struct au_iinfo *iinfo;
1facf9fc 13119+
4a4d8108
AM
13120+ iinfo = &(container_of(inode, struct au_icntnr, vfs_inode)->iinfo);
13121+ if (iinfo->ii_hinode)
13122+ return iinfo;
13123+ return NULL; /* debugging bad_inode case */
13124+}
1facf9fc 13125+
4a4d8108 13126+/* ---------------------------------------------------------------------- */
1facf9fc 13127+
4a4d8108
AM
13128+/* inode.c */
13129+struct inode *au_igrab(struct inode *inode);
027c5e7a 13130+int au_refresh_hinode_self(struct inode *inode);
4a4d8108
AM
13131+int au_refresh_hinode(struct inode *inode, struct dentry *dentry);
13132+int au_ino(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino,
13133+ unsigned int d_type, ino_t *ino);
13134+struct inode *au_new_inode(struct dentry *dentry, int must_new);
13135+int au_test_ro(struct super_block *sb, aufs_bindex_t bindex,
13136+ struct inode *inode);
13137+int au_test_h_perm(struct inode *h_inode, int mask);
13138+int au_test_h_perm_sio(struct inode *h_inode, int mask);
1facf9fc 13139+
4a4d8108
AM
13140+static inline int au_wh_ino(struct super_block *sb, aufs_bindex_t bindex,
13141+ ino_t h_ino, unsigned int d_type, ino_t *ino)
13142+{
13143+#ifdef CONFIG_AUFS_SHWH
13144+ return au_ino(sb, bindex, h_ino, d_type, ino);
13145+#else
13146+ return 0;
13147+#endif
13148+}
1facf9fc 13149+
4a4d8108
AM
13150+/* i_op.c */
13151+extern struct inode_operations aufs_iop, aufs_symlink_iop, aufs_dir_iop;
1308ab2a 13152+
4a4d8108
AM
13153+/* au_wr_dir flags */
13154+#define AuWrDir_ADD_ENTRY 1
13155+#define AuWrDir_ISDIR (1 << 1)
13156+#define au_ftest_wrdir(flags, name) ((flags) & AuWrDir_##name)
7f207e10
AM
13157+#define au_fset_wrdir(flags, name) \
13158+ do { (flags) |= AuWrDir_##name; } while (0)
13159+#define au_fclr_wrdir(flags, name) \
13160+ do { (flags) &= ~AuWrDir_##name; } while (0)
1facf9fc 13161+
4a4d8108
AM
13162+struct au_wr_dir_args {
13163+ aufs_bindex_t force_btgt;
13164+ unsigned char flags;
13165+};
13166+int au_wr_dir(struct dentry *dentry, struct dentry *src_dentry,
13167+ struct au_wr_dir_args *args);
dece6358 13168+
4a4d8108
AM
13169+struct dentry *au_pinned_h_parent(struct au_pin *pin);
13170+void au_pin_init(struct au_pin *pin, struct dentry *dentry,
13171+ aufs_bindex_t bindex, int lsc_di, int lsc_hi,
13172+ unsigned int udba, unsigned char flags);
13173+int au_pin(struct au_pin *pin, struct dentry *dentry, aufs_bindex_t bindex,
13174+ unsigned int udba, unsigned char flags) __must_check;
13175+int au_do_pin(struct au_pin *pin) __must_check;
13176+void au_unpin(struct au_pin *pin);
1facf9fc 13177+
4a4d8108
AM
13178+/* i_op_add.c */
13179+int au_may_add(struct dentry *dentry, aufs_bindex_t bindex,
13180+ struct dentry *h_parent, int isdir);
13181+int aufs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev);
13182+int aufs_symlink(struct inode *dir, struct dentry *dentry, const char *symname);
13183+int aufs_create(struct inode *dir, struct dentry *dentry, int mode,
13184+ struct nameidata *nd);
13185+int aufs_link(struct dentry *src_dentry, struct inode *dir,
13186+ struct dentry *dentry);
13187+int aufs_mkdir(struct inode *dir, struct dentry *dentry, int mode);
1facf9fc 13188+
4a4d8108
AM
13189+/* i_op_del.c */
13190+int au_wr_dir_need_wh(struct dentry *dentry, int isdir, aufs_bindex_t *bcpup);
13191+int au_may_del(struct dentry *dentry, aufs_bindex_t bindex,
13192+ struct dentry *h_parent, int isdir);
13193+int aufs_unlink(struct inode *dir, struct dentry *dentry);
13194+int aufs_rmdir(struct inode *dir, struct dentry *dentry);
1308ab2a 13195+
4a4d8108
AM
13196+/* i_op_ren.c */
13197+int au_wbr(struct dentry *dentry, aufs_bindex_t btgt);
13198+int aufs_rename(struct inode *src_dir, struct dentry *src_dentry,
13199+ struct inode *dir, struct dentry *dentry);
1facf9fc 13200+
4a4d8108
AM
13201+/* iinfo.c */
13202+struct inode *au_h_iptr(struct inode *inode, aufs_bindex_t bindex);
13203+void au_hiput(struct au_hinode *hinode);
13204+void au_set_hi_wh(struct inode *inode, aufs_bindex_t bindex,
13205+ struct dentry *h_wh);
13206+unsigned int au_hi_flags(struct inode *inode, int isdir);
1308ab2a 13207+
4a4d8108
AM
13208+/* hinode flags */
13209+#define AuHi_XINO 1
13210+#define AuHi_HNOTIFY (1 << 1)
13211+#define au_ftest_hi(flags, name) ((flags) & AuHi_##name)
7f207e10
AM
13212+#define au_fset_hi(flags, name) \
13213+ do { (flags) |= AuHi_##name; } while (0)
13214+#define au_fclr_hi(flags, name) \
13215+ do { (flags) &= ~AuHi_##name; } while (0)
1facf9fc 13216+
4a4d8108
AM
13217+#ifndef CONFIG_AUFS_HNOTIFY
13218+#undef AuHi_HNOTIFY
13219+#define AuHi_HNOTIFY 0
13220+#endif
1facf9fc 13221+
4a4d8108
AM
13222+void au_set_h_iptr(struct inode *inode, aufs_bindex_t bindex,
13223+ struct inode *h_inode, unsigned int flags);
1facf9fc 13224+
4a4d8108
AM
13225+void au_update_iigen(struct inode *inode);
13226+void au_update_ibrange(struct inode *inode, int do_put_zero);
1facf9fc 13227+
4a4d8108
AM
13228+void au_icntnr_init_once(void *_c);
13229+int au_iinfo_init(struct inode *inode);
13230+void au_iinfo_fin(struct inode *inode);
13231+int au_ii_realloc(struct au_iinfo *iinfo, int nbr);
1308ab2a 13232+
e49829fe 13233+#ifdef CONFIG_PROC_FS
4a4d8108 13234+/* plink.c */
e49829fe
JR
13235+int au_plink_maint(struct super_block *sb, int flags);
13236+void au_plink_maint_leave(struct au_sbinfo *sbinfo);
13237+int au_plink_maint_enter(struct super_block *sb);
4a4d8108
AM
13238+#ifdef CONFIG_AUFS_DEBUG
13239+void au_plink_list(struct super_block *sb);
13240+#else
13241+AuStubVoid(au_plink_list, struct super_block *sb)
13242+#endif
13243+int au_plink_test(struct inode *inode);
13244+struct dentry *au_plink_lkup(struct inode *inode, aufs_bindex_t bindex);
13245+void au_plink_append(struct inode *inode, aufs_bindex_t bindex,
13246+ struct dentry *h_dentry);
e49829fe
JR
13247+void au_plink_put(struct super_block *sb, int verbose);
13248+void au_plink_clean(struct super_block *sb, int verbose);
4a4d8108 13249+void au_plink_half_refresh(struct super_block *sb, aufs_bindex_t br_id);
e49829fe
JR
13250+#else
13251+AuStubInt0(au_plink_maint, struct super_block *sb, int flags);
13252+AuStubVoid(au_plink_maint_leave, struct au_sbinfo *sbinfo);
13253+AuStubInt0(au_plink_maint_enter, struct super_block *sb);
13254+AuStubVoid(au_plink_list, struct super_block *sb);
13255+AuStubInt0(au_plink_test, struct inode *inode);
13256+AuStub(struct dentry *, au_plink_lkup, return NULL,
13257+ struct inode *inode, aufs_bindex_t bindex);
13258+AuStubVoid(au_plink_append, struct inode *inode, aufs_bindex_t bindex,
13259+ struct dentry *h_dentry);
13260+AuStubVoid(au_plink_put, struct super_block *sb, int verbose);
13261+AuStubVoid(au_plink_clean, struct super_block *sb, int verbose);
13262+AuStubVoid(au_plink_half_refresh, struct super_block *sb, aufs_bindex_t br_id);
13263+#endif /* CONFIG_PROC_FS */
1facf9fc 13264+
4a4d8108 13265+/* ---------------------------------------------------------------------- */
1308ab2a 13266+
4a4d8108
AM
13267+/* lock subclass for iinfo */
13268+enum {
13269+ AuLsc_II_CHILD, /* child first */
13270+ AuLsc_II_CHILD2, /* rename(2), link(2), and cpup at hnotify */
13271+ AuLsc_II_CHILD3, /* copyup dirs */
13272+ AuLsc_II_PARENT, /* see AuLsc_I_PARENT in vfsub.h */
13273+ AuLsc_II_PARENT2,
13274+ AuLsc_II_PARENT3, /* copyup dirs */
13275+ AuLsc_II_NEW_CHILD
13276+};
1308ab2a 13277+
1facf9fc 13278+/*
4a4d8108
AM
13279+ * ii_read_lock_child, ii_write_lock_child,
13280+ * ii_read_lock_child2, ii_write_lock_child2,
13281+ * ii_read_lock_child3, ii_write_lock_child3,
13282+ * ii_read_lock_parent, ii_write_lock_parent,
13283+ * ii_read_lock_parent2, ii_write_lock_parent2,
13284+ * ii_read_lock_parent3, ii_write_lock_parent3,
13285+ * ii_read_lock_new_child, ii_write_lock_new_child,
1facf9fc 13286+ */
4a4d8108
AM
13287+#define AuReadLockFunc(name, lsc) \
13288+static inline void ii_read_lock_##name(struct inode *i) \
13289+{ \
13290+ au_rw_read_lock_nested(&au_ii(i)->ii_rwsem, AuLsc_II_##lsc); \
13291+}
13292+
13293+#define AuWriteLockFunc(name, lsc) \
13294+static inline void ii_write_lock_##name(struct inode *i) \
13295+{ \
13296+ au_rw_write_lock_nested(&au_ii(i)->ii_rwsem, AuLsc_II_##lsc); \
13297+}
13298+
13299+#define AuRWLockFuncs(name, lsc) \
13300+ AuReadLockFunc(name, lsc) \
13301+ AuWriteLockFunc(name, lsc)
13302+
13303+AuRWLockFuncs(child, CHILD);
13304+AuRWLockFuncs(child2, CHILD2);
13305+AuRWLockFuncs(child3, CHILD3);
13306+AuRWLockFuncs(parent, PARENT);
13307+AuRWLockFuncs(parent2, PARENT2);
13308+AuRWLockFuncs(parent3, PARENT3);
13309+AuRWLockFuncs(new_child, NEW_CHILD);
13310+
13311+#undef AuReadLockFunc
13312+#undef AuWriteLockFunc
13313+#undef AuRWLockFuncs
1facf9fc 13314+
13315+/*
4a4d8108 13316+ * ii_read_unlock, ii_write_unlock, ii_downgrade_lock
1facf9fc 13317+ */
4a4d8108 13318+AuSimpleUnlockRwsemFuncs(ii, struct inode *i, &au_ii(i)->ii_rwsem);
1facf9fc 13319+
4a4d8108
AM
13320+#define IiMustNoWaiters(i) AuRwMustNoWaiters(&au_ii(i)->ii_rwsem)
13321+#define IiMustAnyLock(i) AuRwMustAnyLock(&au_ii(i)->ii_rwsem)
13322+#define IiMustWriteLock(i) AuRwMustWriteLock(&au_ii(i)->ii_rwsem)
1facf9fc 13323+
4a4d8108 13324+/* ---------------------------------------------------------------------- */
1308ab2a 13325+
027c5e7a
AM
13326+static inline void au_icntnr_init(struct au_icntnr *c)
13327+{
13328+#ifdef CONFIG_AUFS_DEBUG
13329+ c->vfs_inode.i_mode = 0;
13330+#endif
13331+}
13332+
4a4d8108
AM
13333+static inline unsigned int au_iigen(struct inode *inode)
13334+{
13335+ return atomic_read(&au_ii(inode)->ii_generation);
13336+}
1308ab2a 13337+
4a4d8108
AM
13338+/* tiny test for inode number */
13339+/* tmpfs generation is too rough */
13340+static inline int au_test_higen(struct inode *inode, struct inode *h_inode)
13341+{
13342+ struct au_iinfo *iinfo;
1308ab2a 13343+
4a4d8108
AM
13344+ iinfo = au_ii(inode);
13345+ AuRwMustAnyLock(&iinfo->ii_rwsem);
13346+ return !(iinfo->ii_hsb1 == h_inode->i_sb
13347+ && iinfo->ii_higen == h_inode->i_generation);
13348+}
1308ab2a 13349+
4a4d8108
AM
13350+static inline void au_iigen_dec(struct inode *inode)
13351+{
e49829fe 13352+ atomic_dec(&au_ii(inode)->ii_generation);
027c5e7a
AM
13353+}
13354+
13355+static inline int au_iigen_test(struct inode *inode, unsigned int sigen)
13356+{
13357+ int err;
13358+
13359+ err = 0;
13360+ if (unlikely(inode && au_iigen(inode) != sigen))
13361+ err = -EIO;
13362+
13363+ return err;
4a4d8108 13364+}
1308ab2a 13365+
4a4d8108 13366+/* ---------------------------------------------------------------------- */
1308ab2a 13367+
4a4d8108
AM
13368+static inline aufs_bindex_t au_ii_br_id(struct inode *inode,
13369+ aufs_bindex_t bindex)
13370+{
13371+ IiMustAnyLock(inode);
13372+ return au_ii(inode)->ii_hinode[0 + bindex].hi_id;
13373+}
1308ab2a 13374+
4a4d8108
AM
13375+static inline aufs_bindex_t au_ibstart(struct inode *inode)
13376+{
13377+ IiMustAnyLock(inode);
13378+ return au_ii(inode)->ii_bstart;
13379+}
1308ab2a 13380+
4a4d8108
AM
13381+static inline aufs_bindex_t au_ibend(struct inode *inode)
13382+{
13383+ IiMustAnyLock(inode);
13384+ return au_ii(inode)->ii_bend;
13385+}
1308ab2a 13386+
4a4d8108
AM
13387+static inline struct au_vdir *au_ivdir(struct inode *inode)
13388+{
13389+ IiMustAnyLock(inode);
13390+ return au_ii(inode)->ii_vdir;
13391+}
1308ab2a 13392+
4a4d8108
AM
13393+static inline struct dentry *au_hi_wh(struct inode *inode, aufs_bindex_t bindex)
13394+{
13395+ IiMustAnyLock(inode);
13396+ return au_ii(inode)->ii_hinode[0 + bindex].hi_whdentry;
13397+}
1308ab2a 13398+
4a4d8108 13399+static inline void au_set_ibstart(struct inode *inode, aufs_bindex_t bindex)
1308ab2a 13400+{
4a4d8108
AM
13401+ IiMustWriteLock(inode);
13402+ au_ii(inode)->ii_bstart = bindex;
13403+}
1308ab2a 13404+
4a4d8108
AM
13405+static inline void au_set_ibend(struct inode *inode, aufs_bindex_t bindex)
13406+{
13407+ IiMustWriteLock(inode);
13408+ au_ii(inode)->ii_bend = bindex;
1308ab2a 13409+}
13410+
4a4d8108
AM
13411+static inline void au_set_ivdir(struct inode *inode, struct au_vdir *vdir)
13412+{
13413+ IiMustWriteLock(inode);
13414+ au_ii(inode)->ii_vdir = vdir;
13415+}
1facf9fc 13416+
4a4d8108 13417+static inline struct au_hinode *au_hi(struct inode *inode, aufs_bindex_t bindex)
1308ab2a 13418+{
4a4d8108
AM
13419+ IiMustAnyLock(inode);
13420+ return au_ii(inode)->ii_hinode + bindex;
13421+}
dece6358 13422+
4a4d8108 13423+/* ---------------------------------------------------------------------- */
1facf9fc 13424+
4a4d8108
AM
13425+static inline struct dentry *au_pinned_parent(struct au_pin *pin)
13426+{
13427+ if (pin)
13428+ return pin->parent;
13429+ return NULL;
1facf9fc 13430+}
13431+
4a4d8108 13432+static inline struct inode *au_pinned_h_dir(struct au_pin *pin)
1facf9fc 13433+{
4a4d8108
AM
13434+ if (pin && pin->hdir)
13435+ return pin->hdir->hi_inode;
13436+ return NULL;
1308ab2a 13437+}
1facf9fc 13438+
4a4d8108
AM
13439+static inline struct au_hinode *au_pinned_hdir(struct au_pin *pin)
13440+{
13441+ if (pin)
13442+ return pin->hdir;
13443+ return NULL;
13444+}
1facf9fc 13445+
4a4d8108 13446+static inline void au_pin_set_dentry(struct au_pin *pin, struct dentry *dentry)
1308ab2a 13447+{
4a4d8108
AM
13448+ if (pin)
13449+ pin->dentry = dentry;
13450+}
1308ab2a 13451+
4a4d8108
AM
13452+static inline void au_pin_set_parent_lflag(struct au_pin *pin,
13453+ unsigned char lflag)
13454+{
13455+ if (pin) {
7f207e10 13456+ if (lflag)
4a4d8108 13457+ au_fset_pin(pin->flags, DI_LOCKED);
7f207e10 13458+ else
4a4d8108 13459+ au_fclr_pin(pin->flags, DI_LOCKED);
1308ab2a 13460+ }
4a4d8108
AM
13461+}
13462+
13463+static inline void au_pin_set_parent(struct au_pin *pin, struct dentry *parent)
13464+{
13465+ if (pin) {
13466+ dput(pin->parent);
13467+ pin->parent = dget(parent);
1facf9fc 13468+ }
4a4d8108 13469+}
1facf9fc 13470+
4a4d8108
AM
13471+/* ---------------------------------------------------------------------- */
13472+
027c5e7a 13473+struct au_branch;
4a4d8108
AM
13474+#ifdef CONFIG_AUFS_HNOTIFY
13475+struct au_hnotify_op {
13476+ void (*ctl)(struct au_hinode *hinode, int do_set);
027c5e7a
AM
13477+ int (*alloc)(struct au_hinode *hinode);
13478+ void (*free)(struct au_hinode *hinode);
4a4d8108
AM
13479+
13480+ void (*fin)(void);
13481+ int (*init)(void);
027c5e7a
AM
13482+
13483+ int (*reset_br)(unsigned int udba, struct au_branch *br, int perm);
13484+ void (*fin_br)(struct au_branch *br);
13485+ int (*init_br)(struct au_branch *br, int perm);
4a4d8108
AM
13486+};
13487+
13488+/* hnotify.c */
027c5e7a 13489+int au_hn_alloc(struct au_hinode *hinode, struct inode *inode);
4a4d8108
AM
13490+void au_hn_free(struct au_hinode *hinode);
13491+void au_hn_ctl(struct au_hinode *hinode, int do_set);
13492+void au_hn_reset(struct inode *inode, unsigned int flags);
13493+int au_hnotify(struct inode *h_dir, struct au_hnotify *hnotify, u32 mask,
13494+ struct qstr *h_child_qstr, struct inode *h_child_inode);
027c5e7a
AM
13495+int au_hnotify_reset_br(unsigned int udba, struct au_branch *br, int perm);
13496+int au_hnotify_init_br(struct au_branch *br, int perm);
13497+void au_hnotify_fin_br(struct au_branch *br);
4a4d8108
AM
13498+int __init au_hnotify_init(void);
13499+void au_hnotify_fin(void);
13500+
7f207e10 13501+/* hfsnotify.c */
4a4d8108
AM
13502+extern const struct au_hnotify_op au_hnotify_op;
13503+
13504+static inline
13505+void au_hn_init(struct au_hinode *hinode)
13506+{
13507+ hinode->hi_notify = NULL;
1308ab2a 13508+}
13509+
4a4d8108
AM
13510+#else
13511+static inline
13512+int au_hn_alloc(struct au_hinode *hinode __maybe_unused,
027c5e7a 13513+ struct inode *inode __maybe_unused)
1308ab2a 13514+{
4a4d8108
AM
13515+ return -EOPNOTSUPP;
13516+}
1308ab2a 13517+
4a4d8108
AM
13518+AuStubVoid(au_hn_free, struct au_hinode *hinode __maybe_unused)
13519+AuStubVoid(au_hn_ctl, struct au_hinode *hinode __maybe_unused,
13520+ int do_set __maybe_unused)
13521+AuStubVoid(au_hn_reset, struct inode *inode __maybe_unused,
13522+ unsigned int flags __maybe_unused)
027c5e7a
AM
13523+AuStubInt0(au_hnotify_reset_br, unsigned int udba __maybe_unused,
13524+ struct au_branch *br __maybe_unused,
13525+ int perm __maybe_unused)
13526+AuStubInt0(au_hnotify_init_br, struct au_branch *br __maybe_unused,
13527+ int perm __maybe_unused)
13528+AuStubVoid(au_hnotify_fin_br, struct au_branch *br __maybe_unused)
4a4d8108
AM
13529+AuStubInt0(__init au_hnotify_init, void)
13530+AuStubVoid(au_hnotify_fin, void)
13531+AuStubVoid(au_hn_init, struct au_hinode *hinode __maybe_unused)
13532+#endif /* CONFIG_AUFS_HNOTIFY */
13533+
13534+static inline void au_hn_suspend(struct au_hinode *hdir)
13535+{
13536+ au_hn_ctl(hdir, /*do_set*/0);
1308ab2a 13537+}
13538+
4a4d8108 13539+static inline void au_hn_resume(struct au_hinode *hdir)
1308ab2a 13540+{
4a4d8108
AM
13541+ au_hn_ctl(hdir, /*do_set*/1);
13542+}
1308ab2a 13543+
4a4d8108
AM
13544+static inline void au_hn_imtx_lock(struct au_hinode *hdir)
13545+{
13546+ mutex_lock(&hdir->hi_inode->i_mutex);
13547+ au_hn_suspend(hdir);
13548+}
dece6358 13549+
4a4d8108
AM
13550+static inline void au_hn_imtx_lock_nested(struct au_hinode *hdir,
13551+ unsigned int sc __maybe_unused)
13552+{
13553+ mutex_lock_nested(&hdir->hi_inode->i_mutex, sc);
13554+ au_hn_suspend(hdir);
1facf9fc 13555+}
1facf9fc 13556+
4a4d8108
AM
13557+static inline void au_hn_imtx_unlock(struct au_hinode *hdir)
13558+{
13559+ au_hn_resume(hdir);
13560+ mutex_unlock(&hdir->hi_inode->i_mutex);
13561+}
13562+
13563+#endif /* __KERNEL__ */
13564+#endif /* __AUFS_INODE_H__ */
7f207e10
AM
13565diff -urN /usr/share/empty/fs/aufs/ioctl.c linux/fs/aufs/ioctl.c
13566--- /usr/share/empty/fs/aufs/ioctl.c 1970-01-01 01:00:00.000000000 +0100
87a755f4 13567+++ linux/fs/aufs/ioctl.c 2011-03-17 10:46:59.000000000 +0100
027c5e7a 13568@@ -0,0 +1,158 @@
4a4d8108 13569+/*
027c5e7a 13570+ * Copyright (C) 2005-2011 Junjiro R. Okajima
4a4d8108
AM
13571+ *
13572+ * This program, aufs is free software; you can redistribute it and/or modify
13573+ * it under the terms of the GNU General Public License as published by
13574+ * the Free Software Foundation; either version 2 of the License, or
13575+ * (at your option) any later version.
13576+ *
13577+ * This program is distributed in the hope that it will be useful,
13578+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
13579+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13580+ * GNU General Public License for more details.
13581+ *
13582+ * You should have received a copy of the GNU General Public License
13583+ * along with this program; if not, write to the Free Software
13584+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
13585+ */
13586+
13587+/*
13588+ * ioctl
13589+ * plink-management and readdir in userspace.
13590+ * assist the pathconf(3) wrapper library.
13591+ */
13592+
13593+#include <linux/file.h>
13594+#include "aufs.h"
13595+
13596+static int au_wbr_fd(struct path *path)
13597+{
13598+ int err, fd;
13599+ aufs_bindex_t wbi, bindex, bend;
13600+ struct file *h_file;
13601+ struct super_block *sb;
13602+ struct dentry *root;
13603+ struct au_branch *wbr;
13604+
13605+ err = get_unused_fd();
13606+ if (unlikely(err < 0))
13607+ goto out;
13608+ fd = err;
13609+
13610+ wbi = 0;
13611+ sb = path->dentry->d_sb;
13612+ root = sb->s_root;
13613+ aufs_read_lock(root, AuLock_IR);
13614+ wbr = au_sbr(sb, wbi);
13615+ if (!(path->mnt->mnt_flags & MNT_READONLY)
13616+ && !au_br_writable(wbr->br_perm)) {
13617+ bend = au_sbend(sb);
13618+ for (bindex = 1; bindex <= bend; bindex++) {
13619+ wbr = au_sbr(sb, bindex);
13620+ if (au_br_writable(wbr->br_perm)) {
13621+ wbi = bindex;
13622+ break;
13623+ }
13624+ }
13625+ wbr = au_sbr(sb, wbi);
13626+ }
13627+ AuDbg("wbi %d\n", wbi);
13628+ h_file = au_h_open(root, wbi, O_RDONLY | O_DIRECTORY | O_LARGEFILE,
13629+ NULL);
13630+ aufs_read_unlock(root, AuLock_IR);
13631+ err = PTR_ERR(h_file);
13632+ if (IS_ERR(h_file))
13633+ goto out_fd;
13634+
13635+ atomic_dec(&wbr->br_count); /* cf. au_h_open() */
13636+ fd_install(fd, h_file);
13637+ err = fd;
13638+ goto out; /* success */
13639+
4f0767ce 13640+out_fd:
4a4d8108 13641+ put_unused_fd(fd);
4f0767ce 13642+out:
4a4d8108
AM
13643+ return err;
13644+}
13645+
13646+/* ---------------------------------------------------------------------- */
13647+
13648+long aufs_ioctl_dir(struct file *file, unsigned int cmd, unsigned long arg)
13649+{
13650+ long err;
13651+
13652+ switch (cmd) {
4a4d8108
AM
13653+ case AUFS_CTL_RDU:
13654+ case AUFS_CTL_RDU_INO:
13655+ err = au_rdu_ioctl(file, cmd, arg);
13656+ break;
13657+
13658+ case AUFS_CTL_WBR_FD:
13659+ err = au_wbr_fd(&file->f_path);
13660+ break;
13661+
027c5e7a
AM
13662+ case AUFS_CTL_IBUSY:
13663+ err = au_ibusy_ioctl(file, arg);
13664+ break;
13665+
4a4d8108
AM
13666+ default:
13667+ /* do not call the lower */
13668+ AuDbg("0x%x\n", cmd);
13669+ err = -ENOTTY;
13670+ }
13671+
13672+ AuTraceErr(err);
13673+ return err;
13674+}
13675+
13676+long aufs_ioctl_nondir(struct file *file, unsigned int cmd, unsigned long arg)
13677+{
13678+ long err;
13679+
13680+ switch (cmd) {
13681+ case AUFS_CTL_WBR_FD:
13682+ err = au_wbr_fd(&file->f_path);
13683+ break;
13684+
13685+ default:
13686+ /* do not call the lower */
13687+ AuDbg("0x%x\n", cmd);
13688+ err = -ENOTTY;
13689+ }
13690+
13691+ AuTraceErr(err);
13692+ return err;
13693+}
b752ccd1
AM
13694+
13695+#ifdef CONFIG_COMPAT
13696+long aufs_compat_ioctl_dir(struct file *file, unsigned int cmd,
13697+ unsigned long arg)
13698+{
13699+ long err;
13700+
13701+ switch (cmd) {
13702+ case AUFS_CTL_RDU:
13703+ case AUFS_CTL_RDU_INO:
13704+ err = au_rdu_compat_ioctl(file, cmd, arg);
13705+ break;
13706+
027c5e7a
AM
13707+ case AUFS_CTL_IBUSY:
13708+ err = au_ibusy_compat_ioctl(file, arg);
13709+ break;
13710+
b752ccd1
AM
13711+ default:
13712+ err = aufs_ioctl_dir(file, cmd, arg);
13713+ }
13714+
13715+ AuTraceErr(err);
13716+ return err;
13717+}
13718+
13719+#if 0 /* unused yet */
13720+long aufs_compat_ioctl_nondir(struct file *file, unsigned int cmd,
13721+ unsigned long arg)
13722+{
13723+ return aufs_ioctl_nondir(file, cmd, (unsigned long)compat_ptr(arg));
13724+}
13725+#endif
13726+#endif
7f207e10
AM
13727diff -urN /usr/share/empty/fs/aufs/i_op_add.c linux/fs/aufs/i_op_add.c
13728--- /usr/share/empty/fs/aufs/i_op_add.c 1970-01-01 01:00:00.000000000 +0100
87a755f4 13729+++ linux/fs/aufs/i_op_add.c 2011-07-22 08:26:47.857636522 +0200
2cbb1c4b 13730@@ -0,0 +1,711 @@
4a4d8108 13731+/*
027c5e7a 13732+ * Copyright (C) 2005-2011 Junjiro R. Okajima
4a4d8108
AM
13733+ *
13734+ * This program, aufs is free software; you can redistribute it and/or modify
13735+ * it under the terms of the GNU General Public License as published by
13736+ * the Free Software Foundation; either version 2 of the License, or
13737+ * (at your option) any later version.
13738+ *
13739+ * This program is distributed in the hope that it will be useful,
13740+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
13741+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13742+ * GNU General Public License for more details.
13743+ *
13744+ * You should have received a copy of the GNU General Public License
13745+ * along with this program; if not, write to the Free Software
13746+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
13747+ */
13748+
13749+/*
13750+ * inode operations (add entry)
13751+ */
13752+
13753+#include "aufs.h"
13754+
13755+/*
13756+ * final procedure of adding a new entry, except link(2).
13757+ * remove whiteout, instantiate, copyup the parent dir's times and size
13758+ * and update version.
13759+ * if it failed, re-create the removed whiteout.
13760+ */
13761+static int epilog(struct inode *dir, aufs_bindex_t bindex,
13762+ struct dentry *wh_dentry, struct dentry *dentry)
13763+{
13764+ int err, rerr;
13765+ aufs_bindex_t bwh;
13766+ struct path h_path;
13767+ struct inode *inode, *h_dir;
13768+ struct dentry *wh;
13769+
13770+ bwh = -1;
13771+ if (wh_dentry) {
13772+ h_dir = wh_dentry->d_parent->d_inode; /* dir inode is locked */
13773+ IMustLock(h_dir);
13774+ AuDebugOn(au_h_iptr(dir, bindex) != h_dir);
13775+ bwh = au_dbwh(dentry);
13776+ h_path.dentry = wh_dentry;
13777+ h_path.mnt = au_sbr_mnt(dir->i_sb, bindex);
13778+ err = au_wh_unlink_dentry(au_h_iptr(dir, bindex), &h_path,
13779+ dentry);
13780+ if (unlikely(err))
13781+ goto out;
13782+ }
13783+
13784+ inode = au_new_inode(dentry, /*must_new*/1);
13785+ if (!IS_ERR(inode)) {
13786+ d_instantiate(dentry, inode);
13787+ dir = dentry->d_parent->d_inode; /* dir inode is locked */
13788+ IMustLock(dir);
13789+ if (au_ibstart(dir) == au_dbstart(dentry))
13790+ au_cpup_attr_timesizes(dir);
13791+ dir->i_version++;
13792+ return 0; /* success */
13793+ }
13794+
13795+ err = PTR_ERR(inode);
13796+ if (!wh_dentry)
13797+ goto out;
13798+
13799+ /* revert */
13800+ /* dir inode is locked */
13801+ wh = au_wh_create(dentry, bwh, wh_dentry->d_parent);
13802+ rerr = PTR_ERR(wh);
13803+ if (IS_ERR(wh)) {
13804+ AuIOErr("%.*s reverting whiteout failed(%d, %d)\n",
13805+ AuDLNPair(dentry), err, rerr);
13806+ err = -EIO;
13807+ } else
13808+ dput(wh);
13809+
4f0767ce 13810+out:
4a4d8108
AM
13811+ return err;
13812+}
13813+
027c5e7a
AM
13814+static int au_d_may_add(struct dentry *dentry)
13815+{
13816+ int err;
13817+
13818+ err = 0;
13819+ if (unlikely(d_unhashed(dentry)))
13820+ err = -ENOENT;
13821+ if (unlikely(dentry->d_inode))
13822+ err = -EEXIST;
13823+ return err;
13824+}
13825+
4a4d8108
AM
13826+/*
13827+ * simple tests for the adding inode operations.
13828+ * following the checks in vfs, plus the parent-child relationship.
13829+ */
13830+int au_may_add(struct dentry *dentry, aufs_bindex_t bindex,
13831+ struct dentry *h_parent, int isdir)
13832+{
13833+ int err;
13834+ umode_t h_mode;
13835+ struct dentry *h_dentry;
13836+ struct inode *h_inode;
13837+
13838+ err = -ENAMETOOLONG;
13839+ if (unlikely(dentry->d_name.len > AUFS_MAX_NAMELEN))
13840+ goto out;
13841+
13842+ h_dentry = au_h_dptr(dentry, bindex);
13843+ h_inode = h_dentry->d_inode;
13844+ if (!dentry->d_inode) {
13845+ err = -EEXIST;
13846+ if (unlikely(h_inode))
13847+ goto out;
13848+ } else {
13849+ /* rename(2) case */
13850+ err = -EIO;
13851+ if (unlikely(!h_inode || !h_inode->i_nlink))
13852+ goto out;
13853+
13854+ h_mode = h_inode->i_mode;
13855+ if (!isdir) {
13856+ err = -EISDIR;
13857+ if (unlikely(S_ISDIR(h_mode)))
13858+ goto out;
13859+ } else if (unlikely(!S_ISDIR(h_mode))) {
13860+ err = -ENOTDIR;
13861+ goto out;
13862+ }
13863+ }
13864+
13865+ err = 0;
13866+ /* expected parent dir is locked */
13867+ if (unlikely(h_parent != h_dentry->d_parent))
13868+ err = -EIO;
13869+
4f0767ce 13870+out:
4a4d8108
AM
13871+ AuTraceErr(err);
13872+ return err;
13873+}
13874+
13875+/*
13876+ * initial procedure of adding a new entry.
13877+ * prepare writable branch and the parent dir, lock it,
13878+ * and lookup whiteout for the new entry.
13879+ */
13880+static struct dentry*
13881+lock_hdir_lkup_wh(struct dentry *dentry, struct au_dtime *dt,
13882+ struct dentry *src_dentry, struct au_pin *pin,
13883+ struct au_wr_dir_args *wr_dir_args)
13884+{
13885+ struct dentry *wh_dentry, *h_parent;
13886+ struct super_block *sb;
13887+ struct au_branch *br;
13888+ int err;
13889+ unsigned int udba;
13890+ aufs_bindex_t bcpup;
13891+
13892+ AuDbg("%.*s\n", AuDLNPair(dentry));
13893+
13894+ err = au_wr_dir(dentry, src_dentry, wr_dir_args);
13895+ bcpup = err;
13896+ wh_dentry = ERR_PTR(err);
13897+ if (unlikely(err < 0))
13898+ goto out;
13899+
13900+ sb = dentry->d_sb;
13901+ udba = au_opt_udba(sb);
13902+ err = au_pin(pin, dentry, bcpup, udba,
13903+ AuPin_DI_LOCKED | AuPin_MNT_WRITE);
13904+ wh_dentry = ERR_PTR(err);
13905+ if (unlikely(err))
13906+ goto out;
13907+
13908+ h_parent = au_pinned_h_parent(pin);
13909+ if (udba != AuOpt_UDBA_NONE
13910+ && au_dbstart(dentry) == bcpup)
13911+ err = au_may_add(dentry, bcpup, h_parent,
13912+ au_ftest_wrdir(wr_dir_args->flags, ISDIR));
13913+ else if (unlikely(dentry->d_name.len > AUFS_MAX_NAMELEN))
13914+ err = -ENAMETOOLONG;
13915+ wh_dentry = ERR_PTR(err);
13916+ if (unlikely(err))
13917+ goto out_unpin;
13918+
13919+ br = au_sbr(sb, bcpup);
13920+ if (dt) {
13921+ struct path tmp = {
13922+ .dentry = h_parent,
13923+ .mnt = br->br_mnt
13924+ };
13925+ au_dtime_store(dt, au_pinned_parent(pin), &tmp);
13926+ }
13927+
13928+ wh_dentry = NULL;
13929+ if (bcpup != au_dbwh(dentry))
13930+ goto out; /* success */
13931+
13932+ wh_dentry = au_wh_lkup(h_parent, &dentry->d_name, br);
13933+
4f0767ce 13934+out_unpin:
4a4d8108
AM
13935+ if (IS_ERR(wh_dentry))
13936+ au_unpin(pin);
4f0767ce 13937+out:
4a4d8108
AM
13938+ return wh_dentry;
13939+}
13940+
13941+/* ---------------------------------------------------------------------- */
13942+
13943+enum { Mknod, Symlink, Creat };
13944+struct simple_arg {
13945+ int type;
13946+ union {
13947+ struct {
13948+ int mode;
13949+ struct nameidata *nd;
13950+ } c;
13951+ struct {
13952+ const char *symname;
13953+ } s;
13954+ struct {
13955+ int mode;
13956+ dev_t dev;
13957+ } m;
13958+ } u;
13959+};
13960+
13961+static int add_simple(struct inode *dir, struct dentry *dentry,
13962+ struct simple_arg *arg)
13963+{
13964+ int err;
13965+ aufs_bindex_t bstart;
13966+ unsigned char created;
13967+ struct au_dtime dt;
13968+ struct au_pin pin;
13969+ struct path h_path;
13970+ struct dentry *wh_dentry, *parent;
13971+ struct inode *h_dir;
13972+ struct au_wr_dir_args wr_dir_args = {
13973+ .force_btgt = -1,
13974+ .flags = AuWrDir_ADD_ENTRY
13975+ };
13976+
13977+ AuDbg("%.*s\n", AuDLNPair(dentry));
13978+ IMustLock(dir);
13979+
13980+ parent = dentry->d_parent; /* dir inode is locked */
027c5e7a
AM
13981+ err = aufs_read_lock(dentry, AuLock_DW | AuLock_GEN);
13982+ if (unlikely(err))
13983+ goto out;
13984+ err = au_d_may_add(dentry);
13985+ if (unlikely(err))
13986+ goto out_unlock;
4a4d8108
AM
13987+ di_write_lock_parent(parent);
13988+ wh_dentry = lock_hdir_lkup_wh(dentry, &dt, /*src_dentry*/NULL, &pin,
13989+ &wr_dir_args);
13990+ err = PTR_ERR(wh_dentry);
13991+ if (IS_ERR(wh_dentry))
027c5e7a 13992+ goto out_parent;
4a4d8108
AM
13993+
13994+ bstart = au_dbstart(dentry);
13995+ h_path.dentry = au_h_dptr(dentry, bstart);
13996+ h_path.mnt = au_sbr_mnt(dentry->d_sb, bstart);
13997+ h_dir = au_pinned_h_dir(&pin);
13998+ switch (arg->type) {
13999+ case Creat:
14000+ err = vfsub_create(h_dir, &h_path, arg->u.c.mode);
14001+ break;
14002+ case Symlink:
14003+ err = vfsub_symlink(h_dir, &h_path, arg->u.s.symname);
14004+ break;
14005+ case Mknod:
14006+ err = vfsub_mknod(h_dir, &h_path, arg->u.m.mode, arg->u.m.dev);
14007+ break;
14008+ default:
14009+ BUG();
14010+ }
14011+ created = !err;
14012+ if (!err)
14013+ err = epilog(dir, bstart, wh_dentry, dentry);
14014+
14015+ /* revert */
14016+ if (unlikely(created && err && h_path.dentry->d_inode)) {
14017+ int rerr;
14018+ rerr = vfsub_unlink(h_dir, &h_path, /*force*/0);
14019+ if (rerr) {
14020+ AuIOErr("%.*s revert failure(%d, %d)\n",
14021+ AuDLNPair(dentry), err, rerr);
14022+ err = -EIO;
14023+ }
14024+ au_dtime_revert(&dt);
4a4d8108
AM
14025+ }
14026+
14027+ au_unpin(&pin);
14028+ dput(wh_dentry);
14029+
027c5e7a
AM
14030+out_parent:
14031+ di_write_unlock(parent);
14032+out_unlock:
4a4d8108
AM
14033+ if (unlikely(err)) {
14034+ au_update_dbstart(dentry);
14035+ d_drop(dentry);
14036+ }
4a4d8108 14037+ aufs_read_unlock(dentry, AuLock_DW);
027c5e7a 14038+out:
4a4d8108
AM
14039+ return err;
14040+}
14041+
14042+int aufs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev)
14043+{
14044+ struct simple_arg arg = {
14045+ .type = Mknod,
14046+ .u.m = {
14047+ .mode = mode,
14048+ .dev = dev
14049+ }
14050+ };
14051+ return add_simple(dir, dentry, &arg);
14052+}
14053+
14054+int aufs_symlink(struct inode *dir, struct dentry *dentry, const char *symname)
14055+{
14056+ struct simple_arg arg = {
14057+ .type = Symlink,
14058+ .u.s.symname = symname
14059+ };
14060+ return add_simple(dir, dentry, &arg);
14061+}
14062+
14063+int aufs_create(struct inode *dir, struct dentry *dentry, int mode,
14064+ struct nameidata *nd)
14065+{
14066+ struct simple_arg arg = {
14067+ .type = Creat,
14068+ .u.c = {
14069+ .mode = mode,
14070+ .nd = nd
14071+ }
14072+ };
14073+ return add_simple(dir, dentry, &arg);
14074+}
14075+
14076+/* ---------------------------------------------------------------------- */
14077+
14078+struct au_link_args {
14079+ aufs_bindex_t bdst, bsrc;
14080+ struct au_pin pin;
14081+ struct path h_path;
14082+ struct dentry *src_parent, *parent;
14083+};
14084+
14085+static int au_cpup_before_link(struct dentry *src_dentry,
14086+ struct au_link_args *a)
14087+{
14088+ int err;
14089+ struct dentry *h_src_dentry;
14090+ struct mutex *h_mtx;
14091+ struct file *h_file;
14092+
14093+ di_read_lock_parent(a->src_parent, AuLock_IR);
14094+ err = au_test_and_cpup_dirs(src_dentry, a->bdst);
14095+ if (unlikely(err))
14096+ goto out;
14097+
14098+ h_src_dentry = au_h_dptr(src_dentry, a->bsrc);
14099+ h_mtx = &h_src_dentry->d_inode->i_mutex;
14100+ err = au_pin(&a->pin, src_dentry, a->bdst,
14101+ au_opt_udba(src_dentry->d_sb),
14102+ AuPin_DI_LOCKED | AuPin_MNT_WRITE);
14103+ if (unlikely(err))
14104+ goto out;
14105+ mutex_lock_nested(h_mtx, AuLsc_I_CHILD);
14106+ h_file = au_h_open_pre(src_dentry, a->bsrc);
14107+ if (IS_ERR(h_file)) {
14108+ err = PTR_ERR(h_file);
14109+ h_file = NULL;
14110+ } else
14111+ err = au_sio_cpup_simple(src_dentry, a->bdst, a->bsrc,
14112+ AuCpup_DTIME /* | AuCpup_KEEPLINO */);
14113+ mutex_unlock(h_mtx);
14114+ au_h_open_post(src_dentry, a->bsrc, h_file);
14115+ au_unpin(&a->pin);
14116+
4f0767ce 14117+out:
4a4d8108
AM
14118+ di_read_unlock(a->src_parent, AuLock_IR);
14119+ return err;
14120+}
14121+
14122+static int au_cpup_or_link(struct dentry *src_dentry, struct au_link_args *a)
14123+{
14124+ int err;
14125+ unsigned char plink;
14126+ struct inode *h_inode, *inode;
14127+ struct dentry *h_src_dentry;
14128+ struct super_block *sb;
14129+ struct file *h_file;
14130+
14131+ plink = 0;
14132+ h_inode = NULL;
14133+ sb = src_dentry->d_sb;
14134+ inode = src_dentry->d_inode;
14135+ if (au_ibstart(inode) <= a->bdst)
14136+ h_inode = au_h_iptr(inode, a->bdst);
14137+ if (!h_inode || !h_inode->i_nlink) {
14138+ /* copyup src_dentry as the name of dentry. */
14139+ au_set_dbstart(src_dentry, a->bdst);
14140+ au_set_h_dptr(src_dentry, a->bdst, dget(a->h_path.dentry));
14141+ h_inode = au_h_dptr(src_dentry, a->bsrc)->d_inode;
14142+ mutex_lock_nested(&h_inode->i_mutex, AuLsc_I_CHILD);
14143+ h_file = au_h_open_pre(src_dentry, a->bsrc);
14144+ if (IS_ERR(h_file)) {
14145+ err = PTR_ERR(h_file);
14146+ h_file = NULL;
14147+ } else
14148+ err = au_sio_cpup_single(src_dentry, a->bdst, a->bsrc,
14149+ -1, AuCpup_KEEPLINO,
14150+ a->parent);
14151+ mutex_unlock(&h_inode->i_mutex);
14152+ au_h_open_post(src_dentry, a->bsrc, h_file);
14153+ au_set_h_dptr(src_dentry, a->bdst, NULL);
14154+ au_set_dbstart(src_dentry, a->bsrc);
14155+ } else {
14156+ /* the inode of src_dentry already exists on a.bdst branch */
14157+ h_src_dentry = d_find_alias(h_inode);
14158+ if (!h_src_dentry && au_plink_test(inode)) {
14159+ plink = 1;
14160+ h_src_dentry = au_plink_lkup(inode, a->bdst);
14161+ err = PTR_ERR(h_src_dentry);
14162+ if (IS_ERR(h_src_dentry))
14163+ goto out;
14164+
14165+ if (unlikely(!h_src_dentry->d_inode)) {
14166+ dput(h_src_dentry);
14167+ h_src_dentry = NULL;
14168+ }
14169+
14170+ }
14171+ if (h_src_dentry) {
14172+ err = vfsub_link(h_src_dentry, au_pinned_h_dir(&a->pin),
14173+ &a->h_path);
14174+ dput(h_src_dentry);
14175+ } else {
14176+ AuIOErr("no dentry found for hi%lu on b%d\n",
14177+ h_inode->i_ino, a->bdst);
14178+ err = -EIO;
14179+ }
14180+ }
14181+
14182+ if (!err && !plink)
14183+ au_plink_append(inode, a->bdst, a->h_path.dentry);
14184+
14185+out:
2cbb1c4b 14186+ AuTraceErr(err);
4a4d8108
AM
14187+ return err;
14188+}
14189+
14190+int aufs_link(struct dentry *src_dentry, struct inode *dir,
14191+ struct dentry *dentry)
14192+{
14193+ int err, rerr;
14194+ struct au_dtime dt;
14195+ struct au_link_args *a;
14196+ struct dentry *wh_dentry, *h_src_dentry;
14197+ struct inode *inode;
14198+ struct super_block *sb;
14199+ struct au_wr_dir_args wr_dir_args = {
14200+ /* .force_btgt = -1, */
14201+ .flags = AuWrDir_ADD_ENTRY
14202+ };
14203+
14204+ IMustLock(dir);
14205+ inode = src_dentry->d_inode;
14206+ IMustLock(inode);
14207+
4a4d8108
AM
14208+ err = -ENOMEM;
14209+ a = kzalloc(sizeof(*a), GFP_NOFS);
14210+ if (unlikely(!a))
14211+ goto out;
14212+
14213+ a->parent = dentry->d_parent; /* dir inode is locked */
027c5e7a
AM
14214+ err = aufs_read_and_write_lock2(dentry, src_dentry,
14215+ AuLock_NOPLM | AuLock_GEN);
e49829fe
JR
14216+ if (unlikely(err))
14217+ goto out_kfree;
027c5e7a
AM
14218+ err = au_d_hashed_positive(src_dentry);
14219+ if (unlikely(err))
14220+ goto out_unlock;
14221+ err = au_d_may_add(dentry);
14222+ if (unlikely(err))
14223+ goto out_unlock;
e49829fe 14224+
4a4d8108 14225+ a->src_parent = dget_parent(src_dentry);
2cbb1c4b 14226+ wr_dir_args.force_btgt = au_ibstart(inode);
4a4d8108
AM
14227+
14228+ di_write_lock_parent(a->parent);
14229+ wr_dir_args.force_btgt = au_wbr(dentry, wr_dir_args.force_btgt);
14230+ wh_dentry = lock_hdir_lkup_wh(dentry, &dt, src_dentry, &a->pin,
14231+ &wr_dir_args);
14232+ err = PTR_ERR(wh_dentry);
14233+ if (IS_ERR(wh_dentry))
027c5e7a 14234+ goto out_parent;
4a4d8108
AM
14235+
14236+ err = 0;
14237+ sb = dentry->d_sb;
14238+ a->bdst = au_dbstart(dentry);
14239+ a->h_path.dentry = au_h_dptr(dentry, a->bdst);
14240+ a->h_path.mnt = au_sbr_mnt(sb, a->bdst);
2cbb1c4b
JR
14241+ a->bsrc = au_ibstart(inode);
14242+ h_src_dentry = au_h_d_alias(src_dentry, a->bsrc);
14243+ if (!h_src_dentry) {
14244+ a->bsrc = au_dbstart(src_dentry);
14245+ h_src_dentry = au_h_d_alias(src_dentry, a->bsrc);
14246+ AuDebugOn(!h_src_dentry);
14247+ } else if (IS_ERR(h_src_dentry))
14248+ goto out_parent;
14249+
4a4d8108
AM
14250+ if (au_opt_test(au_mntflags(sb), PLINK)) {
14251+ if (a->bdst < a->bsrc
14252+ /* && h_src_dentry->d_sb != a->h_path.dentry->d_sb */)
14253+ err = au_cpup_or_link(src_dentry, a);
2cbb1c4b 14254+ else
4a4d8108
AM
14255+ err = vfsub_link(h_src_dentry, au_pinned_h_dir(&a->pin),
14256+ &a->h_path);
2cbb1c4b 14257+ dput(h_src_dentry);
4a4d8108
AM
14258+ } else {
14259+ /*
14260+ * copyup src_dentry to the branch we process,
14261+ * and then link(2) to it.
14262+ */
2cbb1c4b 14263+ dput(h_src_dentry);
4a4d8108
AM
14264+ if (a->bdst < a->bsrc
14265+ /* && h_src_dentry->d_sb != a->h_path.dentry->d_sb */) {
14266+ au_unpin(&a->pin);
14267+ di_write_unlock(a->parent);
14268+ err = au_cpup_before_link(src_dentry, a);
14269+ di_write_lock_parent(a->parent);
14270+ if (!err)
14271+ err = au_pin(&a->pin, dentry, a->bdst,
14272+ au_opt_udba(sb),
14273+ AuPin_DI_LOCKED | AuPin_MNT_WRITE);
14274+ if (unlikely(err))
14275+ goto out_wh;
14276+ }
14277+ if (!err) {
14278+ h_src_dentry = au_h_dptr(src_dentry, a->bdst);
14279+ err = -ENOENT;
14280+ if (h_src_dentry && h_src_dentry->d_inode)
14281+ err = vfsub_link(h_src_dentry,
14282+ au_pinned_h_dir(&a->pin),
14283+ &a->h_path);
14284+ }
14285+ }
14286+ if (unlikely(err))
14287+ goto out_unpin;
14288+
14289+ if (wh_dentry) {
14290+ a->h_path.dentry = wh_dentry;
14291+ err = au_wh_unlink_dentry(au_pinned_h_dir(&a->pin), &a->h_path,
14292+ dentry);
14293+ if (unlikely(err))
14294+ goto out_revert;
14295+ }
14296+
14297+ dir->i_version++;
14298+ if (au_ibstart(dir) == au_dbstart(dentry))
14299+ au_cpup_attr_timesizes(dir);
14300+ inc_nlink(inode);
14301+ inode->i_ctime = dir->i_ctime;
027c5e7a
AM
14302+ d_instantiate(dentry, au_igrab(inode));
14303+ if (d_unhashed(a->h_path.dentry))
4a4d8108
AM
14304+ /* some filesystem calls d_drop() */
14305+ d_drop(dentry);
14306+ goto out_unpin; /* success */
14307+
4f0767ce 14308+out_revert:
4a4d8108 14309+ rerr = vfsub_unlink(au_pinned_h_dir(&a->pin), &a->h_path, /*force*/0);
027c5e7a
AM
14310+ if (unlikely(rerr)) {
14311+ AuIOErr("%.*s reverting failed(%d, %d)\n",
14312+ AuDLNPair(dentry), err, rerr);
14313+ err = -EIO;
14314+ }
4a4d8108 14315+ au_dtime_revert(&dt);
4f0767ce 14316+out_unpin:
4a4d8108 14317+ au_unpin(&a->pin);
4f0767ce 14318+out_wh:
4a4d8108 14319+ dput(wh_dentry);
027c5e7a
AM
14320+out_parent:
14321+ di_write_unlock(a->parent);
14322+ dput(a->src_parent);
4f0767ce 14323+out_unlock:
4a4d8108
AM
14324+ if (unlikely(err)) {
14325+ au_update_dbstart(dentry);
14326+ d_drop(dentry);
14327+ }
4a4d8108 14328+ aufs_read_and_write_unlock2(dentry, src_dentry);
e49829fe 14329+out_kfree:
4a4d8108 14330+ kfree(a);
4f0767ce 14331+out:
4a4d8108
AM
14332+ return err;
14333+}
14334+
14335+int aufs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
14336+{
14337+ int err, rerr;
14338+ aufs_bindex_t bindex;
14339+ unsigned char diropq;
14340+ struct path h_path;
14341+ struct dentry *wh_dentry, *parent, *opq_dentry;
14342+ struct mutex *h_mtx;
14343+ struct super_block *sb;
14344+ struct {
14345+ struct au_pin pin;
14346+ struct au_dtime dt;
14347+ } *a; /* reduce the stack usage */
14348+ struct au_wr_dir_args wr_dir_args = {
14349+ .force_btgt = -1,
14350+ .flags = AuWrDir_ADD_ENTRY | AuWrDir_ISDIR
14351+ };
14352+
14353+ IMustLock(dir);
14354+
14355+ err = -ENOMEM;
14356+ a = kmalloc(sizeof(*a), GFP_NOFS);
14357+ if (unlikely(!a))
14358+ goto out;
14359+
027c5e7a
AM
14360+ err = aufs_read_lock(dentry, AuLock_DW | AuLock_GEN);
14361+ if (unlikely(err))
14362+ goto out_free;
14363+ err = au_d_may_add(dentry);
14364+ if (unlikely(err))
14365+ goto out_unlock;
14366+
4a4d8108
AM
14367+ parent = dentry->d_parent; /* dir inode is locked */
14368+ di_write_lock_parent(parent);
14369+ wh_dentry = lock_hdir_lkup_wh(dentry, &a->dt, /*src_dentry*/NULL,
14370+ &a->pin, &wr_dir_args);
14371+ err = PTR_ERR(wh_dentry);
14372+ if (IS_ERR(wh_dentry))
027c5e7a 14373+ goto out_parent;
4a4d8108
AM
14374+
14375+ sb = dentry->d_sb;
14376+ bindex = au_dbstart(dentry);
14377+ h_path.dentry = au_h_dptr(dentry, bindex);
14378+ h_path.mnt = au_sbr_mnt(sb, bindex);
14379+ err = vfsub_mkdir(au_pinned_h_dir(&a->pin), &h_path, mode);
14380+ if (unlikely(err))
027c5e7a 14381+ goto out_unpin;
4a4d8108
AM
14382+
14383+ /* make the dir opaque */
14384+ diropq = 0;
14385+ h_mtx = &h_path.dentry->d_inode->i_mutex;
14386+ if (wh_dentry
14387+ || au_opt_test(au_mntflags(sb), ALWAYS_DIROPQ)) {
14388+ mutex_lock_nested(h_mtx, AuLsc_I_CHILD);
14389+ opq_dentry = au_diropq_create(dentry, bindex);
14390+ mutex_unlock(h_mtx);
14391+ err = PTR_ERR(opq_dentry);
14392+ if (IS_ERR(opq_dentry))
14393+ goto out_dir;
14394+ dput(opq_dentry);
14395+ diropq = 1;
14396+ }
14397+
14398+ err = epilog(dir, bindex, wh_dentry, dentry);
14399+ if (!err) {
14400+ inc_nlink(dir);
027c5e7a 14401+ goto out_unpin; /* success */
4a4d8108
AM
14402+ }
14403+
14404+ /* revert */
14405+ if (diropq) {
14406+ AuLabel(revert opq);
14407+ mutex_lock_nested(h_mtx, AuLsc_I_CHILD);
14408+ rerr = au_diropq_remove(dentry, bindex);
14409+ mutex_unlock(h_mtx);
14410+ if (rerr) {
14411+ AuIOErr("%.*s reverting diropq failed(%d, %d)\n",
14412+ AuDLNPair(dentry), err, rerr);
14413+ err = -EIO;
14414+ }
14415+ }
14416+
4f0767ce 14417+out_dir:
4a4d8108
AM
14418+ AuLabel(revert dir);
14419+ rerr = vfsub_rmdir(au_pinned_h_dir(&a->pin), &h_path);
14420+ if (rerr) {
14421+ AuIOErr("%.*s reverting dir failed(%d, %d)\n",
14422+ AuDLNPair(dentry), err, rerr);
14423+ err = -EIO;
14424+ }
4a4d8108 14425+ au_dtime_revert(&a->dt);
027c5e7a 14426+out_unpin:
4a4d8108
AM
14427+ au_unpin(&a->pin);
14428+ dput(wh_dentry);
027c5e7a
AM
14429+out_parent:
14430+ di_write_unlock(parent);
14431+out_unlock:
4a4d8108
AM
14432+ if (unlikely(err)) {
14433+ au_update_dbstart(dentry);
14434+ d_drop(dentry);
14435+ }
4a4d8108 14436+ aufs_read_unlock(dentry, AuLock_DW);
027c5e7a 14437+out_free:
4a4d8108 14438+ kfree(a);
4f0767ce 14439+out:
4a4d8108
AM
14440+ return err;
14441+}
7f207e10
AM
14442diff -urN /usr/share/empty/fs/aufs/i_op.c linux/fs/aufs/i_op.c
14443--- /usr/share/empty/fs/aufs/i_op.c 1970-01-01 01:00:00.000000000 +0100
87a755f4 14444+++ linux/fs/aufs/i_op.c 2011-03-17 10:46:59.000000000 +0100
027c5e7a 14445@@ -0,0 +1,976 @@
4a4d8108 14446+/*
027c5e7a 14447+ * Copyright (C) 2005-2011 Junjiro R. Okajima
4a4d8108
AM
14448+ *
14449+ * This program, aufs is free software; you can redistribute it and/or modify
14450+ * it under the terms of the GNU General Public License as published by
14451+ * the Free Software Foundation; either version 2 of the License, or
14452+ * (at your option) any later version.
14453+ *
14454+ * This program is distributed in the hope that it will be useful,
14455+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
14456+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14457+ * GNU General Public License for more details.
14458+ *
14459+ * You should have received a copy of the GNU General Public License
14460+ * along with this program; if not, write to the Free Software
14461+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
14462+ */
1facf9fc 14463+
1308ab2a 14464+/*
4a4d8108 14465+ * inode operations (except add/del/rename)
1308ab2a 14466+ */
4a4d8108
AM
14467+
14468+#include <linux/device_cgroup.h>
14469+#include <linux/fs_stack.h>
14470+#include <linux/mm.h>
14471+#include <linux/namei.h>
14472+#include <linux/security.h>
14473+#include <linux/uaccess.h>
14474+#include "aufs.h"
14475+
027c5e7a 14476+static int h_permission(struct inode *h_inode, int mask, unsigned int flags,
4a4d8108 14477+ struct vfsmount *h_mnt, int brperm)
1facf9fc 14478+{
1308ab2a 14479+ int err;
4a4d8108 14480+ const unsigned char write_mask = !!(mask & (MAY_WRITE | MAY_APPEND));
1facf9fc 14481+
4a4d8108
AM
14482+ err = -EACCES;
14483+ if ((write_mask && IS_IMMUTABLE(h_inode))
14484+ || ((mask & MAY_EXEC)
14485+ && S_ISREG(h_inode->i_mode)
14486+ && ((h_mnt->mnt_flags & MNT_NOEXEC)
14487+ || !(h_inode->i_mode & S_IXUGO))))
14488+ goto out;
14489+
14490+ /*
14491+ * - skip the lower fs test in the case of write to ro branch.
14492+ * - nfs dir permission write check is optimized, but a policy for
14493+ * link/rename requires a real check.
14494+ */
14495+ if ((write_mask && !au_br_writable(brperm))
14496+ || (au_test_nfs(h_inode->i_sb) && S_ISDIR(h_inode->i_mode)
14497+ && write_mask && !(mask & MAY_READ))
14498+ || !h_inode->i_op->permission) {
14499+ /* AuLabel(generic_permission); */
027c5e7a 14500+ err = generic_permission(h_inode, mask, flags,
4a4d8108 14501+ h_inode->i_op->check_acl);
1308ab2a 14502+ } else {
4a4d8108 14503+ /* AuLabel(h_inode->permission); */
027c5e7a 14504+ err = h_inode->i_op->permission(h_inode, mask, flags);
4a4d8108
AM
14505+ AuTraceErr(err);
14506+ }
1facf9fc 14507+
4a4d8108
AM
14508+ if (!err)
14509+ err = devcgroup_inode_permission(h_inode, mask);
7f207e10 14510+ if (!err)
4a4d8108 14511+ err = security_inode_permission(h_inode, mask);
4a4d8108
AM
14512+
14513+#if 0
14514+ if (!err) {
14515+ /* todo: do we need to call ima_path_check()? */
14516+ struct path h_path = {
14517+ .dentry =
14518+ .mnt = h_mnt
14519+ };
14520+ err = ima_path_check(&h_path,
14521+ mask & (MAY_READ | MAY_WRITE | MAY_EXEC),
14522+ IMA_COUNT_LEAVE);
1308ab2a 14523+ }
4a4d8108 14524+#endif
dece6358 14525+
4f0767ce 14526+out:
1308ab2a 14527+ return err;
14528+}
dece6358 14529+
027c5e7a 14530+static int aufs_permission(struct inode *inode, int mask, unsigned int flags)
1308ab2a 14531+{
14532+ int err;
4a4d8108
AM
14533+ aufs_bindex_t bindex, bend;
14534+ const unsigned char isdir = !!S_ISDIR(inode->i_mode),
14535+ write_mask = !!(mask & (MAY_WRITE | MAY_APPEND));
14536+ struct inode *h_inode;
14537+ struct super_block *sb;
14538+ struct au_branch *br;
1facf9fc 14539+
027c5e7a
AM
14540+ /* todo: support rcu-walk? */
14541+ if (flags & IPERM_FLAG_RCU)
14542+ return -ECHILD;
14543+
4a4d8108
AM
14544+ sb = inode->i_sb;
14545+ si_read_lock(sb, AuLock_FLUSH);
14546+ ii_read_lock_child(inode);
027c5e7a
AM
14547+#if 0
14548+ err = au_iigen_test(inode, au_sigen(sb));
14549+ if (unlikely(err))
14550+ goto out;
14551+#endif
dece6358 14552+
4a4d8108
AM
14553+ if (!isdir || write_mask) {
14554+ err = au_busy_or_stale();
14555+ h_inode = au_h_iptr(inode, au_ibstart(inode));
14556+ if (unlikely(!h_inode
14557+ || (h_inode->i_mode & S_IFMT)
14558+ != (inode->i_mode & S_IFMT)))
14559+ goto out;
1facf9fc 14560+
4a4d8108
AM
14561+ err = 0;
14562+ bindex = au_ibstart(inode);
14563+ br = au_sbr(sb, bindex);
027c5e7a
AM
14564+ err = h_permission(h_inode, mask, flags, br->br_mnt,
14565+ br->br_perm);
4a4d8108
AM
14566+ if (write_mask
14567+ && !err
14568+ && !special_file(h_inode->i_mode)) {
14569+ /* test whether the upper writable branch exists */
14570+ err = -EROFS;
14571+ for (; bindex >= 0; bindex--)
14572+ if (!au_br_rdonly(au_sbr(sb, bindex))) {
14573+ err = 0;
14574+ break;
14575+ }
14576+ }
14577+ goto out;
14578+ }
dece6358 14579+
4a4d8108 14580+ /* non-write to dir */
1308ab2a 14581+ err = 0;
4a4d8108
AM
14582+ bend = au_ibend(inode);
14583+ for (bindex = au_ibstart(inode); !err && bindex <= bend; bindex++) {
14584+ h_inode = au_h_iptr(inode, bindex);
14585+ if (h_inode) {
14586+ err = au_busy_or_stale();
14587+ if (unlikely(!S_ISDIR(h_inode->i_mode)))
14588+ break;
14589+
14590+ br = au_sbr(sb, bindex);
027c5e7a 14591+ err = h_permission(h_inode, mask, flags, br->br_mnt,
4a4d8108
AM
14592+ br->br_perm);
14593+ }
14594+ }
1308ab2a 14595+
4f0767ce 14596+out:
4a4d8108
AM
14597+ ii_read_unlock(inode);
14598+ si_read_unlock(sb);
1308ab2a 14599+ return err;
14600+}
14601+
4a4d8108 14602+/* ---------------------------------------------------------------------- */
1facf9fc 14603+
4a4d8108
AM
14604+static struct dentry *aufs_lookup(struct inode *dir, struct dentry *dentry,
14605+ struct nameidata *nd)
14606+{
14607+ struct dentry *ret, *parent;
b752ccd1 14608+ struct inode *inode;
4a4d8108
AM
14609+ struct super_block *sb;
14610+ int err, npositive;
dece6358 14611+
4a4d8108 14612+ IMustLock(dir);
1308ab2a 14613+
4a4d8108 14614+ sb = dir->i_sb;
7f207e10
AM
14615+ err = si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLM);
14616+ ret = ERR_PTR(err);
14617+ if (unlikely(err))
14618+ goto out;
14619+
4a4d8108
AM
14620+ ret = ERR_PTR(-ENAMETOOLONG);
14621+ if (unlikely(dentry->d_name.len > AUFS_MAX_NAMELEN))
7f207e10 14622+ goto out_si;
4a4d8108
AM
14623+ err = au_di_init(dentry);
14624+ ret = ERR_PTR(err);
14625+ if (unlikely(err))
7f207e10 14626+ goto out_si;
1308ab2a 14627+
027c5e7a 14628+ npositive = 0; /* suppress a warning */
4a4d8108
AM
14629+ parent = dentry->d_parent; /* dir inode is locked */
14630+ di_read_lock_parent(parent, AuLock_IR);
027c5e7a
AM
14631+ err = au_alive_dir(parent);
14632+ if (!err)
14633+ err = au_digen_test(parent, au_sigen(sb));
14634+ if (!err) {
14635+ npositive = au_lkup_dentry(dentry, au_dbstart(parent),
14636+ /*type*/0, nd);
14637+ err = npositive;
14638+ }
4a4d8108 14639+ di_read_unlock(parent, AuLock_IR);
4a4d8108
AM
14640+ ret = ERR_PTR(err);
14641+ if (unlikely(err < 0))
14642+ goto out_unlock;
1308ab2a 14643+
4a4d8108
AM
14644+ inode = NULL;
14645+ if (npositive) {
b752ccd1 14646+ inode = au_new_inode(dentry, /*must_new*/0);
4a4d8108 14647+ ret = (void *)inode;
1facf9fc 14648+ }
4a4d8108
AM
14649+ if (IS_ERR(inode))
14650+ goto out_unlock;
14651+
14652+ ret = d_splice_alias(inode, dentry);
7f207e10 14653+ if (unlikely(IS_ERR(ret) && inode)) {
4a4d8108 14654+ ii_write_unlock(inode);
7f207e10
AM
14655+ iput(inode);
14656+ }
1facf9fc 14657+
4f0767ce 14658+out_unlock:
4a4d8108 14659+ di_write_unlock(dentry);
7f207e10 14660+out_si:
4a4d8108 14661+ si_read_unlock(sb);
7f207e10 14662+out:
4a4d8108
AM
14663+ return ret;
14664+}
1facf9fc 14665+
4a4d8108 14666+/* ---------------------------------------------------------------------- */
1facf9fc 14667+
4a4d8108
AM
14668+static int au_wr_dir_cpup(struct dentry *dentry, struct dentry *parent,
14669+ const unsigned char add_entry, aufs_bindex_t bcpup,
14670+ aufs_bindex_t bstart)
14671+{
14672+ int err;
14673+ struct dentry *h_parent;
14674+ struct inode *h_dir;
1facf9fc 14675+
027c5e7a 14676+ if (add_entry)
4a4d8108 14677+ IMustLock(parent->d_inode);
027c5e7a 14678+ else
4a4d8108
AM
14679+ di_write_lock_parent(parent);
14680+
14681+ err = 0;
14682+ if (!au_h_dptr(parent, bcpup)) {
14683+ if (bstart < bcpup)
14684+ err = au_cpdown_dirs(dentry, bcpup);
14685+ else
14686+ err = au_cpup_dirs(dentry, bcpup);
14687+ }
14688+ if (!err && add_entry) {
14689+ h_parent = au_h_dptr(parent, bcpup);
14690+ h_dir = h_parent->d_inode;
14691+ mutex_lock_nested(&h_dir->i_mutex, AuLsc_I_PARENT);
14692+ err = au_lkup_neg(dentry, bcpup);
14693+ /* todo: no unlock here */
14694+ mutex_unlock(&h_dir->i_mutex);
027c5e7a
AM
14695+
14696+ AuDbg("bcpup %d\n", bcpup);
14697+ if (!err) {
14698+ if (!dentry->d_inode)
14699+ au_set_h_dptr(dentry, bstart, NULL);
4a4d8108
AM
14700+ au_update_dbrange(dentry, /*do_put_zero*/0);
14701+ }
1308ab2a 14702+ }
1facf9fc 14703+
4a4d8108
AM
14704+ if (!add_entry)
14705+ di_write_unlock(parent);
14706+ if (!err)
14707+ err = bcpup; /* success */
1308ab2a 14708+
027c5e7a 14709+ AuTraceErr(err);
4a4d8108
AM
14710+ return err;
14711+}
1facf9fc 14712+
4a4d8108
AM
14713+/*
14714+ * decide the branch and the parent dir where we will create a new entry.
14715+ * returns new bindex or an error.
14716+ * copyup the parent dir if needed.
14717+ */
14718+int au_wr_dir(struct dentry *dentry, struct dentry *src_dentry,
14719+ struct au_wr_dir_args *args)
14720+{
14721+ int err;
14722+ aufs_bindex_t bcpup, bstart, src_bstart;
14723+ const unsigned char add_entry = !!au_ftest_wrdir(args->flags,
14724+ ADD_ENTRY);
14725+ struct super_block *sb;
14726+ struct dentry *parent;
14727+ struct au_sbinfo *sbinfo;
1facf9fc 14728+
4a4d8108
AM
14729+ sb = dentry->d_sb;
14730+ sbinfo = au_sbi(sb);
14731+ parent = dget_parent(dentry);
14732+ bstart = au_dbstart(dentry);
14733+ bcpup = bstart;
14734+ if (args->force_btgt < 0) {
14735+ if (src_dentry) {
14736+ src_bstart = au_dbstart(src_dentry);
14737+ if (src_bstart < bstart)
14738+ bcpup = src_bstart;
14739+ } else if (add_entry) {
14740+ err = AuWbrCreate(sbinfo, dentry,
14741+ au_ftest_wrdir(args->flags, ISDIR));
14742+ bcpup = err;
14743+ }
1facf9fc 14744+
4a4d8108
AM
14745+ if (bcpup < 0 || au_test_ro(sb, bcpup, dentry->d_inode)) {
14746+ if (add_entry)
14747+ err = AuWbrCopyup(sbinfo, dentry);
14748+ else {
14749+ if (!IS_ROOT(dentry)) {
14750+ di_read_lock_parent(parent, !AuLock_IR);
14751+ err = AuWbrCopyup(sbinfo, dentry);
14752+ di_read_unlock(parent, !AuLock_IR);
14753+ } else
14754+ err = AuWbrCopyup(sbinfo, dentry);
14755+ }
14756+ bcpup = err;
14757+ if (unlikely(err < 0))
14758+ goto out;
14759+ }
14760+ } else {
14761+ bcpup = args->force_btgt;
14762+ AuDebugOn(au_test_ro(sb, bcpup, dentry->d_inode));
1308ab2a 14763+ }
027c5e7a 14764+
4a4d8108
AM
14765+ AuDbg("bstart %d, bcpup %d\n", bstart, bcpup);
14766+ err = bcpup;
14767+ if (bcpup == bstart)
14768+ goto out; /* success */
4a4d8108
AM
14769+
14770+ /* copyup the new parent into the branch we process */
14771+ err = au_wr_dir_cpup(dentry, parent, add_entry, bcpup, bstart);
027c5e7a
AM
14772+ if (err >= 0) {
14773+ if (!dentry->d_inode) {
14774+ au_set_h_dptr(dentry, bstart, NULL);
14775+ au_set_dbstart(dentry, bcpup);
14776+ au_set_dbend(dentry, bcpup);
14777+ }
14778+ AuDebugOn(add_entry && !au_h_dptr(dentry, bcpup));
14779+ }
4a4d8108 14780+
4f0767ce 14781+out:
4a4d8108 14782+ dput(parent);
dece6358
AM
14783+ return err;
14784+}
1facf9fc 14785+
1308ab2a 14786+/* ---------------------------------------------------------------------- */
14787+
4a4d8108 14788+struct dentry *au_pinned_h_parent(struct au_pin *pin)
1308ab2a 14789+{
4a4d8108
AM
14790+ if (pin && pin->parent)
14791+ return au_h_dptr(pin->parent, pin->bindex);
14792+ return NULL;
dece6358 14793+}
1facf9fc 14794+
4a4d8108 14795+void au_unpin(struct au_pin *p)
dece6358 14796+{
e49829fe 14797+ if (p->h_mnt && au_ftest_pin(p->flags, MNT_WRITE))
4a4d8108
AM
14798+ mnt_drop_write(p->h_mnt);
14799+ if (!p->hdir)
14800+ return;
1facf9fc 14801+
4a4d8108
AM
14802+ au_hn_imtx_unlock(p->hdir);
14803+ if (!au_ftest_pin(p->flags, DI_LOCKED))
14804+ di_read_unlock(p->parent, AuLock_IR);
14805+ iput(p->hdir->hi_inode);
14806+ dput(p->parent);
14807+ p->parent = NULL;
14808+ p->hdir = NULL;
14809+ p->h_mnt = NULL;
14810+}
1308ab2a 14811+
4a4d8108
AM
14812+int au_do_pin(struct au_pin *p)
14813+{
14814+ int err;
14815+ struct super_block *sb;
14816+ struct dentry *h_dentry, *h_parent;
14817+ struct au_branch *br;
14818+ struct inode *h_dir;
14819+
14820+ err = 0;
14821+ sb = p->dentry->d_sb;
14822+ br = au_sbr(sb, p->bindex);
14823+ if (IS_ROOT(p->dentry)) {
14824+ if (au_ftest_pin(p->flags, MNT_WRITE)) {
14825+ p->h_mnt = br->br_mnt;
14826+ err = mnt_want_write(p->h_mnt);
14827+ if (unlikely(err)) {
14828+ au_fclr_pin(p->flags, MNT_WRITE);
14829+ goto out_err;
14830+ }
14831+ }
dece6358 14832+ goto out;
1facf9fc 14833+ }
14834+
4a4d8108
AM
14835+ h_dentry = NULL;
14836+ if (p->bindex <= au_dbend(p->dentry))
14837+ h_dentry = au_h_dptr(p->dentry, p->bindex);
dece6358 14838+
4a4d8108
AM
14839+ p->parent = dget_parent(p->dentry);
14840+ if (!au_ftest_pin(p->flags, DI_LOCKED))
14841+ di_read_lock(p->parent, AuLock_IR, p->lsc_di);
dece6358 14842+
4a4d8108
AM
14843+ h_dir = NULL;
14844+ h_parent = au_h_dptr(p->parent, p->bindex);
14845+ p->hdir = au_hi(p->parent->d_inode, p->bindex);
14846+ if (p->hdir)
14847+ h_dir = p->hdir->hi_inode;
dece6358 14848+
b752ccd1
AM
14849+ /*
14850+ * udba case, or
14851+ * if DI_LOCKED is not set, then p->parent may be different
14852+ * and h_parent can be NULL.
14853+ */
14854+ if (unlikely(!p->hdir || !h_dir || !h_parent)) {
e49829fe 14855+ err = -EBUSY;
4a4d8108
AM
14856+ if (!au_ftest_pin(p->flags, DI_LOCKED))
14857+ di_read_unlock(p->parent, AuLock_IR);
14858+ dput(p->parent);
14859+ p->parent = NULL;
14860+ goto out_err;
14861+ }
1308ab2a 14862+
4a4d8108
AM
14863+ au_igrab(h_dir);
14864+ au_hn_imtx_lock_nested(p->hdir, p->lsc_hi);
1308ab2a 14865+
4a4d8108
AM
14866+ if (unlikely(p->hdir->hi_inode != h_parent->d_inode)) {
14867+ err = -EBUSY;
14868+ goto out_unpin;
14869+ }
14870+ if (h_dentry) {
14871+ err = au_h_verify(h_dentry, p->udba, h_dir, h_parent, br);
14872+ if (unlikely(err)) {
14873+ au_fclr_pin(p->flags, MNT_WRITE);
14874+ goto out_unpin;
14875+ }
1facf9fc 14876+ }
dece6358 14877+
4a4d8108
AM
14878+ if (au_ftest_pin(p->flags, MNT_WRITE)) {
14879+ p->h_mnt = br->br_mnt;
14880+ err = mnt_want_write(p->h_mnt);
dece6358 14881+ if (unlikely(err)) {
4a4d8108
AM
14882+ au_fclr_pin(p->flags, MNT_WRITE);
14883+ goto out_unpin;
dece6358
AM
14884+ }
14885+ }
4a4d8108
AM
14886+ goto out; /* success */
14887+
4f0767ce 14888+out_unpin:
4a4d8108 14889+ au_unpin(p);
4f0767ce 14890+out_err:
4a4d8108
AM
14891+ pr_err("err %d\n", err);
14892+ err = au_busy_or_stale();
4f0767ce 14893+out:
1facf9fc 14894+ return err;
14895+}
14896+
4a4d8108
AM
14897+void au_pin_init(struct au_pin *p, struct dentry *dentry,
14898+ aufs_bindex_t bindex, int lsc_di, int lsc_hi,
14899+ unsigned int udba, unsigned char flags)
14900+{
14901+ p->dentry = dentry;
14902+ p->udba = udba;
14903+ p->lsc_di = lsc_di;
14904+ p->lsc_hi = lsc_hi;
14905+ p->flags = flags;
14906+ p->bindex = bindex;
14907+
14908+ p->parent = NULL;
14909+ p->hdir = NULL;
14910+ p->h_mnt = NULL;
14911+}
14912+
14913+int au_pin(struct au_pin *pin, struct dentry *dentry, aufs_bindex_t bindex,
14914+ unsigned int udba, unsigned char flags)
14915+{
14916+ au_pin_init(pin, dentry, bindex, AuLsc_DI_PARENT, AuLsc_I_PARENT2,
14917+ udba, flags);
14918+ return au_do_pin(pin);
14919+}
14920+
dece6358
AM
14921+/* ---------------------------------------------------------------------- */
14922+
1308ab2a 14923+/*
4a4d8108
AM
14924+ * ->setattr() and ->getattr() are called in various cases.
14925+ * chmod, stat: dentry is revalidated.
14926+ * fchmod, fstat: file and dentry are not revalidated, additionally they may be
14927+ * unhashed.
14928+ * for ->setattr(), ia->ia_file is passed from ftruncate only.
1308ab2a 14929+ */
027c5e7a 14930+/* todo: consolidate with do_refresh() and simple_reval_dpath() */
4a4d8108 14931+static int au_reval_for_attr(struct dentry *dentry, unsigned int sigen)
1facf9fc 14932+{
4a4d8108
AM
14933+ int err;
14934+ struct inode *inode;
14935+ struct dentry *parent;
1facf9fc 14936+
1308ab2a 14937+ err = 0;
4a4d8108 14938+ inode = dentry->d_inode;
027c5e7a 14939+ if (au_digen_test(dentry, sigen)) {
4a4d8108
AM
14940+ parent = dget_parent(dentry);
14941+ di_read_lock_parent(parent, AuLock_IR);
027c5e7a 14942+ err = au_refresh_dentry(dentry, parent);
4a4d8108
AM
14943+ di_read_unlock(parent, AuLock_IR);
14944+ dput(parent);
dece6358 14945+ }
1facf9fc 14946+
4a4d8108 14947+ AuTraceErr(err);
1308ab2a 14948+ return err;
14949+}
dece6358 14950+
4a4d8108
AM
14951+#define AuIcpup_DID_CPUP 1
14952+#define au_ftest_icpup(flags, name) ((flags) & AuIcpup_##name)
7f207e10
AM
14953+#define au_fset_icpup(flags, name) \
14954+ do { (flags) |= AuIcpup_##name; } while (0)
14955+#define au_fclr_icpup(flags, name) \
14956+ do { (flags) &= ~AuIcpup_##name; } while (0)
1308ab2a 14957+
4a4d8108
AM
14958+struct au_icpup_args {
14959+ unsigned char flags;
14960+ unsigned char pin_flags;
14961+ aufs_bindex_t btgt;
14962+ unsigned int udba;
14963+ struct au_pin pin;
14964+ struct path h_path;
14965+ struct inode *h_inode;
14966+};
1308ab2a 14967+
4a4d8108
AM
14968+static int au_pin_and_icpup(struct dentry *dentry, struct iattr *ia,
14969+ struct au_icpup_args *a)
1308ab2a 14970+{
14971+ int err;
4a4d8108 14972+ loff_t sz;
e49829fe 14973+ aufs_bindex_t bstart, ibstart;
4a4d8108
AM
14974+ struct dentry *hi_wh, *parent;
14975+ struct inode *inode;
14976+ struct file *h_file;
14977+ struct au_wr_dir_args wr_dir_args = {
14978+ .force_btgt = -1,
14979+ .flags = 0
14980+ };
14981+
14982+ bstart = au_dbstart(dentry);
14983+ inode = dentry->d_inode;
14984+ if (S_ISDIR(inode->i_mode))
14985+ au_fset_wrdir(wr_dir_args.flags, ISDIR);
14986+ /* plink or hi_wh() case */
e49829fe 14987+ ibstart = au_ibstart(inode);
027c5e7a 14988+ if (bstart != ibstart && !au_test_ro(inode->i_sb, ibstart, inode))
e49829fe 14989+ wr_dir_args.force_btgt = ibstart;
4a4d8108
AM
14990+ err = au_wr_dir(dentry, /*src_dentry*/NULL, &wr_dir_args);
14991+ if (unlikely(err < 0))
14992+ goto out;
14993+ a->btgt = err;
14994+ if (err != bstart)
14995+ au_fset_icpup(a->flags, DID_CPUP);
14996+
14997+ err = 0;
14998+ a->pin_flags = AuPin_MNT_WRITE;
14999+ parent = NULL;
15000+ if (!IS_ROOT(dentry)) {
15001+ au_fset_pin(a->pin_flags, DI_LOCKED);
15002+ parent = dget_parent(dentry);
15003+ di_write_lock_parent(parent);
15004+ }
15005+
15006+ err = au_pin(&a->pin, dentry, a->btgt, a->udba, a->pin_flags);
15007+ if (unlikely(err))
15008+ goto out_parent;
15009+
15010+ a->h_path.dentry = au_h_dptr(dentry, bstart);
15011+ a->h_inode = a->h_path.dentry->d_inode;
15012+ mutex_lock_nested(&a->h_inode->i_mutex, AuLsc_I_CHILD);
15013+ sz = -1;
15014+ if ((ia->ia_valid & ATTR_SIZE) && ia->ia_size < i_size_read(a->h_inode))
15015+ sz = ia->ia_size;
15016+
15017+ h_file = NULL;
15018+ hi_wh = NULL;
027c5e7a 15019+ if (au_ftest_icpup(a->flags, DID_CPUP) && d_unlinked(dentry)) {
4a4d8108
AM
15020+ hi_wh = au_hi_wh(inode, a->btgt);
15021+ if (!hi_wh) {
15022+ err = au_sio_cpup_wh(dentry, a->btgt, sz, /*file*/NULL);
15023+ if (unlikely(err))
15024+ goto out_unlock;
15025+ hi_wh = au_hi_wh(inode, a->btgt);
15026+ /* todo: revalidate hi_wh? */
15027+ }
15028+ }
15029+
15030+ if (parent) {
15031+ au_pin_set_parent_lflag(&a->pin, /*lflag*/0);
15032+ di_downgrade_lock(parent, AuLock_IR);
15033+ dput(parent);
15034+ parent = NULL;
15035+ }
15036+ if (!au_ftest_icpup(a->flags, DID_CPUP))
15037+ goto out; /* success */
15038+
15039+ if (!d_unhashed(dentry)) {
15040+ h_file = au_h_open_pre(dentry, bstart);
15041+ if (IS_ERR(h_file)) {
15042+ err = PTR_ERR(h_file);
15043+ h_file = NULL;
15044+ } else
15045+ err = au_sio_cpup_simple(dentry, a->btgt, sz,
15046+ AuCpup_DTIME);
15047+ if (!err)
15048+ a->h_path.dentry = au_h_dptr(dentry, a->btgt);
15049+ } else if (!hi_wh)
15050+ a->h_path.dentry = au_h_dptr(dentry, a->btgt);
15051+ else
15052+ a->h_path.dentry = hi_wh; /* do not dget here */
1308ab2a 15053+
4f0767ce 15054+out_unlock:
4a4d8108
AM
15055+ mutex_unlock(&a->h_inode->i_mutex);
15056+ au_h_open_post(dentry, bstart, h_file);
15057+ a->h_inode = a->h_path.dentry->d_inode;
dece6358 15058+ if (!err) {
4a4d8108 15059+ mutex_lock_nested(&a->h_inode->i_mutex, AuLsc_I_CHILD);
dece6358 15060+ goto out; /* success */
1facf9fc 15061+ }
dece6358 15062+
4a4d8108 15063+ au_unpin(&a->pin);
4f0767ce 15064+out_parent:
4a4d8108
AM
15065+ if (parent) {
15066+ di_write_unlock(parent);
15067+ dput(parent);
15068+ }
4f0767ce 15069+out:
1facf9fc 15070+ return err;
15071+}
15072+
4a4d8108 15073+static int aufs_setattr(struct dentry *dentry, struct iattr *ia)
1facf9fc 15074+{
4a4d8108
AM
15075+ int err;
15076+ struct inode *inode;
15077+ struct super_block *sb;
15078+ struct file *file;
15079+ struct au_icpup_args *a;
1facf9fc 15080+
4a4d8108
AM
15081+ inode = dentry->d_inode;
15082+ IMustLock(inode);
dece6358 15083+
4a4d8108
AM
15084+ err = -ENOMEM;
15085+ a = kzalloc(sizeof(*a), GFP_NOFS);
15086+ if (unlikely(!a))
15087+ goto out;
1facf9fc 15088+
4a4d8108
AM
15089+ if (ia->ia_valid & (ATTR_KILL_SUID | ATTR_KILL_SGID))
15090+ ia->ia_valid &= ~ATTR_MODE;
dece6358 15091+
4a4d8108
AM
15092+ file = NULL;
15093+ sb = dentry->d_sb;
e49829fe
JR
15094+ err = si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLM);
15095+ if (unlikely(err))
15096+ goto out_kfree;
15097+
4a4d8108
AM
15098+ if (ia->ia_valid & ATTR_FILE) {
15099+ /* currently ftruncate(2) only */
15100+ AuDebugOn(!S_ISREG(inode->i_mode));
15101+ file = ia->ia_file;
15102+ err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/1);
15103+ if (unlikely(err))
15104+ goto out_si;
15105+ ia->ia_file = au_hf_top(file);
15106+ a->udba = AuOpt_UDBA_NONE;
15107+ } else {
15108+ /* fchmod() doesn't pass ia_file */
15109+ a->udba = au_opt_udba(sb);
027c5e7a
AM
15110+ di_write_lock_child(dentry);
15111+ /* no d_unlinked(), to set UDBA_NONE for root */
4a4d8108
AM
15112+ if (d_unhashed(dentry))
15113+ a->udba = AuOpt_UDBA_NONE;
4a4d8108
AM
15114+ if (a->udba != AuOpt_UDBA_NONE) {
15115+ AuDebugOn(IS_ROOT(dentry));
15116+ err = au_reval_for_attr(dentry, au_sigen(sb));
15117+ if (unlikely(err))
15118+ goto out_dentry;
15119+ }
dece6358 15120+ }
dece6358 15121+
4a4d8108
AM
15122+ err = au_pin_and_icpup(dentry, ia, a);
15123+ if (unlikely(err < 0))
15124+ goto out_dentry;
15125+ if (au_ftest_icpup(a->flags, DID_CPUP)) {
15126+ ia->ia_file = NULL;
15127+ ia->ia_valid &= ~ATTR_FILE;
1308ab2a 15128+ }
dece6358 15129+
4a4d8108
AM
15130+ a->h_path.mnt = au_sbr_mnt(sb, a->btgt);
15131+ if ((ia->ia_valid & (ATTR_MODE | ATTR_CTIME))
15132+ == (ATTR_MODE | ATTR_CTIME)) {
15133+ err = security_path_chmod(a->h_path.dentry, a->h_path.mnt,
15134+ ia->ia_mode);
15135+ if (unlikely(err))
15136+ goto out_unlock;
15137+ } else if ((ia->ia_valid & (ATTR_UID | ATTR_GID))
15138+ && (ia->ia_valid & ATTR_CTIME)) {
15139+ err = security_path_chown(&a->h_path, ia->ia_uid, ia->ia_gid);
15140+ if (unlikely(err))
15141+ goto out_unlock;
15142+ }
dece6358 15143+
4a4d8108
AM
15144+ if (ia->ia_valid & ATTR_SIZE) {
15145+ struct file *f;
1308ab2a 15146+
953406b4 15147+ if (ia->ia_size < i_size_read(inode))
4a4d8108 15148+ /* unmap only */
953406b4 15149+ truncate_setsize(inode, ia->ia_size);
1308ab2a 15150+
4a4d8108
AM
15151+ f = NULL;
15152+ if (ia->ia_valid & ATTR_FILE)
15153+ f = ia->ia_file;
15154+ mutex_unlock(&a->h_inode->i_mutex);
15155+ err = vfsub_trunc(&a->h_path, ia->ia_size, ia->ia_valid, f);
15156+ mutex_lock_nested(&a->h_inode->i_mutex, AuLsc_I_CHILD);
15157+ } else
15158+ err = vfsub_notify_change(&a->h_path, ia);
15159+ if (!err)
15160+ au_cpup_attr_changeable(inode);
1308ab2a 15161+
4f0767ce 15162+out_unlock:
4a4d8108
AM
15163+ mutex_unlock(&a->h_inode->i_mutex);
15164+ au_unpin(&a->pin);
027c5e7a
AM
15165+ if (unlikely(err))
15166+ au_update_dbstart(dentry);
4f0767ce 15167+out_dentry:
4a4d8108
AM
15168+ di_write_unlock(dentry);
15169+ if (file) {
15170+ fi_write_unlock(file);
15171+ ia->ia_file = file;
15172+ ia->ia_valid |= ATTR_FILE;
15173+ }
4f0767ce 15174+out_si:
4a4d8108 15175+ si_read_unlock(sb);
e49829fe 15176+out_kfree:
4a4d8108 15177+ kfree(a);
4f0767ce 15178+out:
4a4d8108
AM
15179+ AuTraceErr(err);
15180+ return err;
1facf9fc 15181+}
15182+
4a4d8108
AM
15183+static void au_refresh_iattr(struct inode *inode, struct kstat *st,
15184+ unsigned int nlink)
1facf9fc 15185+{
4a4d8108
AM
15186+ inode->i_mode = st->mode;
15187+ inode->i_uid = st->uid;
15188+ inode->i_gid = st->gid;
15189+ inode->i_atime = st->atime;
15190+ inode->i_mtime = st->mtime;
15191+ inode->i_ctime = st->ctime;
1facf9fc 15192+
4a4d8108
AM
15193+ au_cpup_attr_nlink(inode, /*force*/0);
15194+ if (S_ISDIR(inode->i_mode)) {
15195+ inode->i_nlink -= nlink;
15196+ inode->i_nlink += st->nlink;
15197+ }
1facf9fc 15198+
4a4d8108
AM
15199+ spin_lock(&inode->i_lock);
15200+ inode->i_blocks = st->blocks;
15201+ i_size_write(inode, st->size);
15202+ spin_unlock(&inode->i_lock);
1facf9fc 15203+}
15204+
4a4d8108
AM
15205+static int aufs_getattr(struct vfsmount *mnt __maybe_unused,
15206+ struct dentry *dentry, struct kstat *st)
1facf9fc 15207+{
4a4d8108
AM
15208+ int err;
15209+ unsigned int mnt_flags;
15210+ aufs_bindex_t bindex;
15211+ unsigned char udba_none, positive;
15212+ struct super_block *sb, *h_sb;
15213+ struct inode *inode;
15214+ struct vfsmount *h_mnt;
15215+ struct dentry *h_dentry;
1facf9fc 15216+
4a4d8108
AM
15217+ sb = dentry->d_sb;
15218+ inode = dentry->d_inode;
7f207e10
AM
15219+ err = si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLM);
15220+ if (unlikely(err))
15221+ goto out;
4a4d8108
AM
15222+ mnt_flags = au_mntflags(sb);
15223+ udba_none = !!au_opt_test(mnt_flags, UDBA_NONE);
1facf9fc 15224+
4a4d8108 15225+ /* support fstat(2) */
027c5e7a 15226+ if (!d_unlinked(dentry) && !udba_none) {
4a4d8108 15227+ unsigned int sigen = au_sigen(sb);
027c5e7a
AM
15228+ err = au_digen_test(dentry, sigen);
15229+ if (!err) {
4a4d8108 15230+ di_read_lock_child(dentry, AuLock_IR);
027c5e7a
AM
15231+ err = au_dbrange_test(dentry);
15232+ if (unlikely(err))
15233+ goto out_unlock;
15234+ } else {
4a4d8108
AM
15235+ AuDebugOn(IS_ROOT(dentry));
15236+ di_write_lock_child(dentry);
027c5e7a
AM
15237+ err = au_dbrange_test(dentry);
15238+ if (!err)
15239+ err = au_reval_for_attr(dentry, sigen);
4a4d8108
AM
15240+ di_downgrade_lock(dentry, AuLock_IR);
15241+ if (unlikely(err))
7f207e10 15242+ goto out_unlock;
4a4d8108
AM
15243+ }
15244+ } else
15245+ di_read_lock_child(dentry, AuLock_IR);
1facf9fc 15246+
4a4d8108
AM
15247+ bindex = au_ibstart(inode);
15248+ h_mnt = au_sbr_mnt(sb, bindex);
15249+ h_sb = h_mnt->mnt_sb;
15250+ if (!au_test_fs_bad_iattr(h_sb) && udba_none)
15251+ goto out_fill; /* success */
1facf9fc 15252+
4a4d8108
AM
15253+ h_dentry = NULL;
15254+ if (au_dbstart(dentry) == bindex)
15255+ h_dentry = dget(au_h_dptr(dentry, bindex));
15256+ else if (au_opt_test(mnt_flags, PLINK) && au_plink_test(inode)) {
15257+ h_dentry = au_plink_lkup(inode, bindex);
15258+ if (IS_ERR(h_dentry))
15259+ goto out_fill; /* pretending success */
15260+ }
15261+ /* illegally overlapped or something */
15262+ if (unlikely(!h_dentry))
15263+ goto out_fill; /* pretending success */
15264+
15265+ positive = !!h_dentry->d_inode;
15266+ if (positive)
15267+ err = vfs_getattr(h_mnt, h_dentry, st);
15268+ dput(h_dentry);
15269+ if (!err) {
15270+ if (positive)
15271+ au_refresh_iattr(inode, st, h_dentry->d_inode->i_nlink);
15272+ goto out_fill; /* success */
1facf9fc 15273+ }
7f207e10
AM
15274+ AuTraceErr(err);
15275+ goto out_unlock;
4a4d8108 15276+
4f0767ce 15277+out_fill:
4a4d8108 15278+ generic_fillattr(inode, st);
7f207e10 15279+out_unlock:
4a4d8108
AM
15280+ di_read_unlock(dentry, AuLock_IR);
15281+ si_read_unlock(sb);
7f207e10
AM
15282+out:
15283+ AuTraceErr(err);
4a4d8108 15284+ return err;
1facf9fc 15285+}
15286+
15287+/* ---------------------------------------------------------------------- */
15288+
4a4d8108
AM
15289+static int h_readlink(struct dentry *dentry, int bindex, char __user *buf,
15290+ int bufsiz)
1facf9fc 15291+{
15292+ int err;
4a4d8108
AM
15293+ struct super_block *sb;
15294+ struct dentry *h_dentry;
1facf9fc 15295+
4a4d8108
AM
15296+ err = -EINVAL;
15297+ h_dentry = au_h_dptr(dentry, bindex);
15298+ if (unlikely(!h_dentry->d_inode->i_op->readlink))
15299+ goto out;
1facf9fc 15300+
4a4d8108
AM
15301+ err = security_inode_readlink(h_dentry);
15302+ if (unlikely(err))
dece6358 15303+ goto out;
1facf9fc 15304+
4a4d8108
AM
15305+ sb = dentry->d_sb;
15306+ if (!au_test_ro(sb, bindex, dentry->d_inode)) {
15307+ vfsub_touch_atime(au_sbr_mnt(sb, bindex), h_dentry);
15308+ fsstack_copy_attr_atime(dentry->d_inode, h_dentry->d_inode);
1facf9fc 15309+ }
4a4d8108 15310+ err = h_dentry->d_inode->i_op->readlink(h_dentry, buf, bufsiz);
1facf9fc 15311+
4f0767ce 15312+out:
4a4d8108
AM
15313+ return err;
15314+}
1facf9fc 15315+
4a4d8108
AM
15316+static int aufs_readlink(struct dentry *dentry, char __user *buf, int bufsiz)
15317+{
15318+ int err;
1facf9fc 15319+
027c5e7a
AM
15320+ err = aufs_read_lock(dentry, AuLock_IR | AuLock_GEN);
15321+ if (unlikely(err))
15322+ goto out;
15323+ err = au_d_hashed_positive(dentry);
15324+ if (!err)
15325+ err = h_readlink(dentry, au_dbstart(dentry), buf, bufsiz);
4a4d8108 15326+ aufs_read_unlock(dentry, AuLock_IR);
1facf9fc 15327+
027c5e7a 15328+out:
4a4d8108
AM
15329+ return err;
15330+}
1facf9fc 15331+
4a4d8108
AM
15332+static void *aufs_follow_link(struct dentry *dentry, struct nameidata *nd)
15333+{
15334+ int err;
4a4d8108 15335+ mm_segment_t old_fs;
b752ccd1
AM
15336+ union {
15337+ char *k;
15338+ char __user *u;
15339+ } buf;
1facf9fc 15340+
4a4d8108 15341+ err = -ENOMEM;
b752ccd1
AM
15342+ buf.k = __getname_gfp(GFP_NOFS);
15343+ if (unlikely(!buf.k))
4a4d8108 15344+ goto out;
1facf9fc 15345+
027c5e7a
AM
15346+ err = aufs_read_lock(dentry, AuLock_IR | AuLock_GEN);
15347+ if (unlikely(err))
15348+ goto out_name;
15349+
15350+ err = au_d_hashed_positive(dentry);
15351+ if (!err) {
15352+ old_fs = get_fs();
15353+ set_fs(KERNEL_DS);
15354+ err = h_readlink(dentry, au_dbstart(dentry), buf.u, PATH_MAX);
15355+ set_fs(old_fs);
15356+ }
4a4d8108 15357+ aufs_read_unlock(dentry, AuLock_IR);
1facf9fc 15358+
4a4d8108 15359+ if (err >= 0) {
b752ccd1 15360+ buf.k[err] = 0;
4a4d8108 15361+ /* will be freed by put_link */
b752ccd1 15362+ nd_set_link(nd, buf.k);
4a4d8108 15363+ return NULL; /* success */
1308ab2a 15364+ }
1facf9fc 15365+
027c5e7a
AM
15366+out_name:
15367+ __putname(buf.k);
4f0767ce 15368+out:
4a4d8108
AM
15369+ path_put(&nd->path);
15370+ AuTraceErr(err);
15371+ return ERR_PTR(err);
15372+}
1facf9fc 15373+
4a4d8108
AM
15374+static void aufs_put_link(struct dentry *dentry __maybe_unused,
15375+ struct nameidata *nd, void *cookie __maybe_unused)
15376+{
15377+ __putname(nd_get_link(nd));
15378+}
1facf9fc 15379+
4a4d8108 15380+/* ---------------------------------------------------------------------- */
1facf9fc 15381+
4a4d8108
AM
15382+static void aufs_truncate_range(struct inode *inode __maybe_unused,
15383+ loff_t start __maybe_unused,
15384+ loff_t end __maybe_unused)
15385+{
15386+ AuUnsupport();
15387+}
1facf9fc 15388+
4a4d8108 15389+/* ---------------------------------------------------------------------- */
1308ab2a 15390+
4a4d8108
AM
15391+struct inode_operations aufs_symlink_iop = {
15392+ .permission = aufs_permission,
15393+ .setattr = aufs_setattr,
15394+ .getattr = aufs_getattr,
15395+ .readlink = aufs_readlink,
15396+ .follow_link = aufs_follow_link,
15397+ .put_link = aufs_put_link
15398+};
15399+
15400+struct inode_operations aufs_dir_iop = {
15401+ .create = aufs_create,
15402+ .lookup = aufs_lookup,
15403+ .link = aufs_link,
15404+ .unlink = aufs_unlink,
15405+ .symlink = aufs_symlink,
15406+ .mkdir = aufs_mkdir,
15407+ .rmdir = aufs_rmdir,
15408+ .mknod = aufs_mknod,
15409+ .rename = aufs_rename,
15410+
15411+ .permission = aufs_permission,
15412+ .setattr = aufs_setattr,
15413+ .getattr = aufs_getattr
15414+};
15415+
15416+struct inode_operations aufs_iop = {
15417+ .permission = aufs_permission,
15418+ .setattr = aufs_setattr,
15419+ .getattr = aufs_getattr,
15420+ .truncate_range = aufs_truncate_range
15421+};
7f207e10
AM
15422diff -urN /usr/share/empty/fs/aufs/i_op_del.c linux/fs/aufs/i_op_del.c
15423--- /usr/share/empty/fs/aufs/i_op_del.c 1970-01-01 01:00:00.000000000 +0100
87a755f4 15424+++ linux/fs/aufs/i_op_del.c 2011-03-17 10:46:59.000000000 +0100
027c5e7a 15425@@ -0,0 +1,481 @@
1facf9fc 15426+/*
027c5e7a 15427+ * Copyright (C) 2005-2011 Junjiro R. Okajima
1facf9fc 15428+ *
15429+ * This program, aufs is free software; you can redistribute it and/or modify
15430+ * it under the terms of the GNU General Public License as published by
15431+ * the Free Software Foundation; either version 2 of the License, or
15432+ * (at your option) any later version.
dece6358
AM
15433+ *
15434+ * This program is distributed in the hope that it will be useful,
15435+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
15436+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15437+ * GNU General Public License for more details.
15438+ *
15439+ * You should have received a copy of the GNU General Public License
15440+ * along with this program; if not, write to the Free Software
15441+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 15442+ */
15443+
15444+/*
4a4d8108 15445+ * inode operations (del entry)
1308ab2a 15446+ */
dece6358 15447+
1308ab2a 15448+#include "aufs.h"
dece6358 15449+
4a4d8108
AM
15450+/*
15451+ * decide if a new whiteout for @dentry is necessary or not.
15452+ * when it is necessary, prepare the parent dir for the upper branch whose
15453+ * branch index is @bcpup for creation. the actual creation of the whiteout will
15454+ * be done by caller.
15455+ * return value:
15456+ * 0: wh is unnecessary
15457+ * plus: wh is necessary
15458+ * minus: error
15459+ */
15460+int au_wr_dir_need_wh(struct dentry *dentry, int isdir, aufs_bindex_t *bcpup)
1308ab2a 15461+{
4a4d8108
AM
15462+ int need_wh, err;
15463+ aufs_bindex_t bstart;
15464+ struct super_block *sb;
dece6358 15465+
4a4d8108
AM
15466+ sb = dentry->d_sb;
15467+ bstart = au_dbstart(dentry);
15468+ if (*bcpup < 0) {
15469+ *bcpup = bstart;
15470+ if (au_test_ro(sb, bstart, dentry->d_inode)) {
15471+ err = AuWbrCopyup(au_sbi(sb), dentry);
15472+ *bcpup = err;
15473+ if (unlikely(err < 0))
15474+ goto out;
15475+ }
15476+ } else
15477+ AuDebugOn(bstart < *bcpup
15478+ || au_test_ro(sb, *bcpup, dentry->d_inode));
15479+ AuDbg("bcpup %d, bstart %d\n", *bcpup, bstart);
1308ab2a 15480+
4a4d8108
AM
15481+ if (*bcpup != bstart) {
15482+ err = au_cpup_dirs(dentry, *bcpup);
15483+ if (unlikely(err))
15484+ goto out;
15485+ need_wh = 1;
15486+ } else {
027c5e7a 15487+ struct au_dinfo *dinfo, *tmp;
4a4d8108 15488+
027c5e7a
AM
15489+ need_wh = -ENOMEM;
15490+ dinfo = au_di(dentry);
15491+ tmp = au_di_alloc(sb, AuLsc_DI_TMP);
15492+ if (tmp) {
15493+ au_di_cp(tmp, dinfo);
15494+ au_di_swap(tmp, dinfo);
15495+ /* returns the number of positive dentries */
15496+ need_wh = au_lkup_dentry(dentry, bstart + 1, /*type*/0,
15497+ /*nd*/NULL);
15498+ au_di_swap(tmp, dinfo);
15499+ au_rw_write_unlock(&tmp->di_rwsem);
15500+ au_di_free(tmp);
4a4d8108
AM
15501+ }
15502+ }
15503+ AuDbg("need_wh %d\n", need_wh);
15504+ err = need_wh;
15505+
4f0767ce 15506+out:
4a4d8108 15507+ return err;
1facf9fc 15508+}
15509+
4a4d8108
AM
15510+/*
15511+ * simple tests for the del-entry operations.
15512+ * following the checks in vfs, plus the parent-child relationship.
15513+ */
15514+int au_may_del(struct dentry *dentry, aufs_bindex_t bindex,
15515+ struct dentry *h_parent, int isdir)
1facf9fc 15516+{
4a4d8108
AM
15517+ int err;
15518+ umode_t h_mode;
15519+ struct dentry *h_dentry, *h_latest;
1308ab2a 15520+ struct inode *h_inode;
1facf9fc 15521+
4a4d8108
AM
15522+ h_dentry = au_h_dptr(dentry, bindex);
15523+ h_inode = h_dentry->d_inode;
15524+ if (dentry->d_inode) {
15525+ err = -ENOENT;
15526+ if (unlikely(!h_inode || !h_inode->i_nlink))
15527+ goto out;
1facf9fc 15528+
4a4d8108
AM
15529+ h_mode = h_inode->i_mode;
15530+ if (!isdir) {
15531+ err = -EISDIR;
15532+ if (unlikely(S_ISDIR(h_mode)))
15533+ goto out;
15534+ } else if (unlikely(!S_ISDIR(h_mode))) {
15535+ err = -ENOTDIR;
15536+ goto out;
15537+ }
15538+ } else {
15539+ /* rename(2) case */
15540+ err = -EIO;
15541+ if (unlikely(h_inode))
15542+ goto out;
15543+ }
1facf9fc 15544+
4a4d8108
AM
15545+ err = -ENOENT;
15546+ /* expected parent dir is locked */
15547+ if (unlikely(h_parent != h_dentry->d_parent))
15548+ goto out;
15549+ err = 0;
15550+
15551+ /*
15552+ * rmdir a dir may break the consistency on some filesystem.
15553+ * let's try heavy test.
15554+ */
15555+ err = -EACCES;
15556+ if (unlikely(au_test_h_perm(h_parent->d_inode, MAY_EXEC | MAY_WRITE)))
15557+ goto out;
15558+
15559+ h_latest = au_sio_lkup_one(&dentry->d_name, h_parent,
15560+ au_sbr(dentry->d_sb, bindex));
15561+ err = -EIO;
15562+ if (IS_ERR(h_latest))
15563+ goto out;
15564+ if (h_latest == h_dentry)
15565+ err = 0;
15566+ dput(h_latest);
15567+
4f0767ce 15568+out:
4a4d8108 15569+ return err;
1308ab2a 15570+}
1facf9fc 15571+
4a4d8108
AM
15572+/*
15573+ * decide the branch where we operate for @dentry. the branch index will be set
15574+ * @rbcpup. after diciding it, 'pin' it and store the timestamps of the parent
15575+ * dir for reverting.
15576+ * when a new whiteout is necessary, create it.
15577+ */
15578+static struct dentry*
15579+lock_hdir_create_wh(struct dentry *dentry, int isdir, aufs_bindex_t *rbcpup,
15580+ struct au_dtime *dt, struct au_pin *pin)
1308ab2a 15581+{
4a4d8108
AM
15582+ struct dentry *wh_dentry;
15583+ struct super_block *sb;
15584+ struct path h_path;
15585+ int err, need_wh;
15586+ unsigned int udba;
15587+ aufs_bindex_t bcpup;
dece6358 15588+
4a4d8108
AM
15589+ need_wh = au_wr_dir_need_wh(dentry, isdir, rbcpup);
15590+ wh_dentry = ERR_PTR(need_wh);
15591+ if (unlikely(need_wh < 0))
15592+ goto out;
15593+
15594+ sb = dentry->d_sb;
15595+ udba = au_opt_udba(sb);
15596+ bcpup = *rbcpup;
15597+ err = au_pin(pin, dentry, bcpup, udba,
15598+ AuPin_DI_LOCKED | AuPin_MNT_WRITE);
15599+ wh_dentry = ERR_PTR(err);
15600+ if (unlikely(err))
15601+ goto out;
15602+
15603+ h_path.dentry = au_pinned_h_parent(pin);
15604+ if (udba != AuOpt_UDBA_NONE
15605+ && au_dbstart(dentry) == bcpup) {
15606+ err = au_may_del(dentry, bcpup, h_path.dentry, isdir);
15607+ wh_dentry = ERR_PTR(err);
15608+ if (unlikely(err))
15609+ goto out_unpin;
15610+ }
15611+
15612+ h_path.mnt = au_sbr_mnt(sb, bcpup);
15613+ au_dtime_store(dt, au_pinned_parent(pin), &h_path);
15614+ wh_dentry = NULL;
15615+ if (!need_wh)
15616+ goto out; /* success, no need to create whiteout */
15617+
15618+ wh_dentry = au_wh_create(dentry, bcpup, h_path.dentry);
15619+ if (IS_ERR(wh_dentry))
15620+ goto out_unpin;
15621+
15622+ /* returns with the parent is locked and wh_dentry is dget-ed */
15623+ goto out; /* success */
15624+
4f0767ce 15625+out_unpin:
4a4d8108 15626+ au_unpin(pin);
4f0767ce 15627+out:
4a4d8108 15628+ return wh_dentry;
1facf9fc 15629+}
15630+
4a4d8108
AM
15631+/*
15632+ * when removing a dir, rename it to a unique temporary whiteout-ed name first
15633+ * in order to be revertible and save time for removing many child whiteouts
15634+ * under the dir.
15635+ * returns 1 when there are too many child whiteout and caller should remove
15636+ * them asynchronously. returns 0 when the number of children is enough small to
15637+ * remove now or the branch fs is a remote fs.
15638+ * otherwise return an error.
15639+ */
15640+static int renwh_and_rmdir(struct dentry *dentry, aufs_bindex_t bindex,
15641+ struct au_nhash *whlist, struct inode *dir)
1facf9fc 15642+{
4a4d8108
AM
15643+ int rmdir_later, err, dirwh;
15644+ struct dentry *h_dentry;
15645+ struct super_block *sb;
15646+
15647+ sb = dentry->d_sb;
15648+ SiMustAnyLock(sb);
15649+ h_dentry = au_h_dptr(dentry, bindex);
15650+ err = au_whtmp_ren(h_dentry, au_sbr(sb, bindex));
15651+ if (unlikely(err))
15652+ goto out;
15653+
15654+ /* stop monitoring */
15655+ au_hn_free(au_hi(dentry->d_inode, bindex));
15656+
15657+ if (!au_test_fs_remote(h_dentry->d_sb)) {
15658+ dirwh = au_sbi(sb)->si_dirwh;
15659+ rmdir_later = (dirwh <= 1);
15660+ if (!rmdir_later)
15661+ rmdir_later = au_nhash_test_longer_wh(whlist, bindex,
15662+ dirwh);
15663+ if (rmdir_later)
15664+ return rmdir_later;
15665+ }
1facf9fc 15666+
4a4d8108
AM
15667+ err = au_whtmp_rmdir(dir, bindex, h_dentry, whlist);
15668+ if (unlikely(err)) {
15669+ AuIOErr("rmdir %.*s, b%d failed, %d. ignored\n",
15670+ AuDLNPair(h_dentry), bindex, err);
15671+ err = 0;
15672+ }
dece6358 15673+
4f0767ce 15674+out:
4a4d8108
AM
15675+ AuTraceErr(err);
15676+ return err;
15677+}
1308ab2a 15678+
4a4d8108
AM
15679+/*
15680+ * final procedure for deleting a entry.
15681+ * maintain dentry and iattr.
15682+ */
15683+static void epilog(struct inode *dir, struct dentry *dentry,
15684+ aufs_bindex_t bindex)
15685+{
15686+ struct inode *inode;
1308ab2a 15687+
4a4d8108
AM
15688+ inode = dentry->d_inode;
15689+ d_drop(dentry);
15690+ inode->i_ctime = dir->i_ctime;
1308ab2a 15691+
4a4d8108
AM
15692+ if (au_ibstart(dir) == bindex)
15693+ au_cpup_attr_timesizes(dir);
15694+ dir->i_version++;
1facf9fc 15695+}
15696+
4a4d8108
AM
15697+/*
15698+ * when an error happened, remove the created whiteout and revert everything.
15699+ */
7f207e10
AM
15700+static int do_revert(int err, struct inode *dir, aufs_bindex_t bindex,
15701+ aufs_bindex_t bwh, struct dentry *wh_dentry,
15702+ struct dentry *dentry, struct au_dtime *dt)
1facf9fc 15703+{
4a4d8108
AM
15704+ int rerr;
15705+ struct path h_path = {
15706+ .dentry = wh_dentry,
7f207e10 15707+ .mnt = au_sbr_mnt(dir->i_sb, bindex)
4a4d8108 15708+ };
dece6358 15709+
7f207e10 15710+ rerr = au_wh_unlink_dentry(au_h_iptr(dir, bindex), &h_path, dentry);
4a4d8108
AM
15711+ if (!rerr) {
15712+ au_set_dbwh(dentry, bwh);
15713+ au_dtime_revert(dt);
15714+ return 0;
15715+ }
dece6358 15716+
4a4d8108
AM
15717+ AuIOErr("%.*s reverting whiteout failed(%d, %d)\n",
15718+ AuDLNPair(dentry), err, rerr);
15719+ return -EIO;
1facf9fc 15720+}
15721+
4a4d8108 15722+/* ---------------------------------------------------------------------- */
1facf9fc 15723+
4a4d8108 15724+int aufs_unlink(struct inode *dir, struct dentry *dentry)
1308ab2a 15725+{
4a4d8108
AM
15726+ int err;
15727+ aufs_bindex_t bwh, bindex, bstart;
15728+ struct au_dtime dt;
15729+ struct au_pin pin;
15730+ struct path h_path;
15731+ struct inode *inode, *h_dir;
15732+ struct dentry *parent, *wh_dentry;
1facf9fc 15733+
4a4d8108 15734+ IMustLock(dir);
027c5e7a
AM
15735+
15736+ err = aufs_read_lock(dentry, AuLock_DW | AuLock_GEN);
15737+ if (unlikely(err))
15738+ goto out;
15739+ err = au_d_hashed_positive(dentry);
15740+ if (unlikely(err))
15741+ goto out_unlock;
4a4d8108 15742+ inode = dentry->d_inode;
4a4d8108 15743+ IMustLock(inode);
027c5e7a
AM
15744+ err = -EISDIR;
15745+ if (unlikely(S_ISDIR(inode->i_mode)))
15746+ goto out_unlock; /* possible? */
1facf9fc 15747+
4a4d8108
AM
15748+ bstart = au_dbstart(dentry);
15749+ bwh = au_dbwh(dentry);
15750+ bindex = -1;
027c5e7a
AM
15751+ parent = dentry->d_parent; /* dir inode is locked */
15752+ di_write_lock_parent(parent);
4a4d8108
AM
15753+ wh_dentry = lock_hdir_create_wh(dentry, /*isdir*/0, &bindex, &dt, &pin);
15754+ err = PTR_ERR(wh_dentry);
15755+ if (IS_ERR(wh_dentry))
027c5e7a 15756+ goto out_parent;
1facf9fc 15757+
4a4d8108
AM
15758+ h_path.mnt = au_sbr_mnt(dentry->d_sb, bstart);
15759+ h_path.dentry = au_h_dptr(dentry, bstart);
15760+ dget(h_path.dentry);
15761+ if (bindex == bstart) {
15762+ h_dir = au_pinned_h_dir(&pin);
15763+ err = vfsub_unlink(h_dir, &h_path, /*force*/0);
15764+ } else {
15765+ /* dir inode is locked */
15766+ h_dir = wh_dentry->d_parent->d_inode;
15767+ IMustLock(h_dir);
15768+ err = 0;
15769+ }
dece6358 15770+
4a4d8108 15771+ if (!err) {
7f207e10 15772+ vfsub_drop_nlink(inode);
4a4d8108
AM
15773+ epilog(dir, dentry, bindex);
15774+
15775+ /* update target timestamps */
15776+ if (bindex == bstart) {
15777+ vfsub_update_h_iattr(&h_path, /*did*/NULL); /*ignore*/
15778+ inode->i_ctime = h_path.dentry->d_inode->i_ctime;
15779+ } else
15780+ /* todo: this timestamp may be reverted later */
15781+ inode->i_ctime = h_dir->i_ctime;
027c5e7a 15782+ goto out_unpin; /* success */
1facf9fc 15783+ }
15784+
4a4d8108
AM
15785+ /* revert */
15786+ if (wh_dentry) {
15787+ int rerr;
15788+
7f207e10 15789+ rerr = do_revert(err, dir, bindex, bwh, wh_dentry, dentry, &dt);
4a4d8108
AM
15790+ if (rerr)
15791+ err = rerr;
dece6358 15792+ }
1facf9fc 15793+
027c5e7a 15794+out_unpin:
4a4d8108
AM
15795+ au_unpin(&pin);
15796+ dput(wh_dentry);
15797+ dput(h_path.dentry);
027c5e7a 15798+out_parent:
4a4d8108 15799+ di_write_unlock(parent);
027c5e7a 15800+out_unlock:
4a4d8108 15801+ aufs_read_unlock(dentry, AuLock_DW);
027c5e7a 15802+out:
4a4d8108 15803+ return err;
dece6358
AM
15804+}
15805+
4a4d8108 15806+int aufs_rmdir(struct inode *dir, struct dentry *dentry)
1308ab2a 15807+{
4a4d8108
AM
15808+ int err, rmdir_later;
15809+ aufs_bindex_t bwh, bindex, bstart;
15810+ struct au_dtime dt;
15811+ struct au_pin pin;
15812+ struct inode *inode;
15813+ struct dentry *parent, *wh_dentry, *h_dentry;
15814+ struct au_whtmp_rmdir *args;
1facf9fc 15815+
4a4d8108 15816+ IMustLock(dir);
027c5e7a
AM
15817+
15818+ err = aufs_read_lock(dentry, AuLock_DW | AuLock_FLUSH | AuLock_GEN);
15819+ if (unlikely(err))
4a4d8108 15820+ goto out;
027c5e7a
AM
15821+
15822+ /* VFS already unhashes it */
15823+ inode = dentry->d_inode;
15824+ err = -ENOENT;
15825+ if (unlikely(!inode || !inode->i_nlink
15826+ || IS_DEADDIR(inode)))
15827+ goto out_unlock;
4a4d8108 15828+ IMustLock(inode);
027c5e7a
AM
15829+ err = -ENOTDIR;
15830+ if (unlikely(!S_ISDIR(inode->i_mode)))
15831+ goto out_unlock; /* possible? */
dece6358 15832+
4a4d8108
AM
15833+ err = -ENOMEM;
15834+ args = au_whtmp_rmdir_alloc(dir->i_sb, GFP_NOFS);
15835+ if (unlikely(!args))
15836+ goto out_unlock;
dece6358 15837+
4a4d8108
AM
15838+ parent = dentry->d_parent; /* dir inode is locked */
15839+ di_write_lock_parent(parent);
15840+ err = au_test_empty(dentry, &args->whlist);
15841+ if (unlikely(err))
027c5e7a 15842+ goto out_parent;
1facf9fc 15843+
4a4d8108
AM
15844+ bstart = au_dbstart(dentry);
15845+ bwh = au_dbwh(dentry);
15846+ bindex = -1;
15847+ wh_dentry = lock_hdir_create_wh(dentry, /*isdir*/1, &bindex, &dt, &pin);
15848+ err = PTR_ERR(wh_dentry);
15849+ if (IS_ERR(wh_dentry))
027c5e7a 15850+ goto out_parent;
1facf9fc 15851+
4a4d8108
AM
15852+ h_dentry = au_h_dptr(dentry, bstart);
15853+ dget(h_dentry);
15854+ rmdir_later = 0;
15855+ if (bindex == bstart) {
15856+ err = renwh_and_rmdir(dentry, bstart, &args->whlist, dir);
15857+ if (err > 0) {
15858+ rmdir_later = err;
15859+ err = 0;
15860+ }
15861+ } else {
15862+ /* stop monitoring */
15863+ au_hn_free(au_hi(inode, bstart));
15864+
15865+ /* dir inode is locked */
15866+ IMustLock(wh_dentry->d_parent->d_inode);
1facf9fc 15867+ err = 0;
15868+ }
15869+
4a4d8108 15870+ if (!err) {
027c5e7a 15871+ vfsub_dead_dir(inode);
4a4d8108
AM
15872+ au_set_dbdiropq(dentry, -1);
15873+ epilog(dir, dentry, bindex);
1308ab2a 15874+
4a4d8108
AM
15875+ if (rmdir_later) {
15876+ au_whtmp_kick_rmdir(dir, bstart, h_dentry, args);
15877+ args = NULL;
15878+ }
1308ab2a 15879+
4a4d8108 15880+ goto out_unpin; /* success */
1facf9fc 15881+ }
15882+
4a4d8108
AM
15883+ /* revert */
15884+ AuLabel(revert);
15885+ if (wh_dentry) {
15886+ int rerr;
1308ab2a 15887+
7f207e10 15888+ rerr = do_revert(err, dir, bindex, bwh, wh_dentry, dentry, &dt);
4a4d8108
AM
15889+ if (rerr)
15890+ err = rerr;
1facf9fc 15891+ }
15892+
4f0767ce 15893+out_unpin:
4a4d8108
AM
15894+ au_unpin(&pin);
15895+ dput(wh_dentry);
15896+ dput(h_dentry);
027c5e7a 15897+out_parent:
4a4d8108
AM
15898+ di_write_unlock(parent);
15899+ if (args)
15900+ au_whtmp_rmdir_free(args);
4f0767ce 15901+out_unlock:
4a4d8108 15902+ aufs_read_unlock(dentry, AuLock_DW);
4f0767ce 15903+out:
4a4d8108
AM
15904+ AuTraceErr(err);
15905+ return err;
dece6358 15906+}
7f207e10
AM
15907diff -urN /usr/share/empty/fs/aufs/i_op_ren.c linux/fs/aufs/i_op_ren.c
15908--- /usr/share/empty/fs/aufs/i_op_ren.c 1970-01-01 01:00:00.000000000 +0100
87a755f4 15909+++ linux/fs/aufs/i_op_ren.c 2011-03-17 10:46:59.000000000 +0100
027c5e7a 15910@@ -0,0 +1,1017 @@
1facf9fc 15911+/*
027c5e7a 15912+ * Copyright (C) 2005-2011 Junjiro R. Okajima
1facf9fc 15913+ *
15914+ * This program, aufs is free software; you can redistribute it and/or modify
15915+ * it under the terms of the GNU General Public License as published by
15916+ * the Free Software Foundation; either version 2 of the License, or
15917+ * (at your option) any later version.
dece6358
AM
15918+ *
15919+ * This program is distributed in the hope that it will be useful,
15920+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
15921+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15922+ * GNU General Public License for more details.
15923+ *
15924+ * You should have received a copy of the GNU General Public License
15925+ * along with this program; if not, write to the Free Software
15926+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 15927+ */
15928+
15929+/*
4a4d8108
AM
15930+ * inode operation (rename entry)
15931+ * todo: this is crazy monster
1facf9fc 15932+ */
15933+
15934+#include "aufs.h"
15935+
4a4d8108
AM
15936+enum { AuSRC, AuDST, AuSrcDst };
15937+enum { AuPARENT, AuCHILD, AuParentChild };
1facf9fc 15938+
4a4d8108
AM
15939+#define AuRen_ISDIR 1
15940+#define AuRen_ISSAMEDIR (1 << 1)
15941+#define AuRen_WHSRC (1 << 2)
15942+#define AuRen_WHDST (1 << 3)
15943+#define AuRen_MNT_WRITE (1 << 4)
15944+#define AuRen_DT_DSTDIR (1 << 5)
15945+#define AuRen_DIROPQ (1 << 6)
15946+#define AuRen_CPUP (1 << 7)
15947+#define au_ftest_ren(flags, name) ((flags) & AuRen_##name)
7f207e10
AM
15948+#define au_fset_ren(flags, name) \
15949+ do { (flags) |= AuRen_##name; } while (0)
15950+#define au_fclr_ren(flags, name) \
15951+ do { (flags) &= ~AuRen_##name; } while (0)
1facf9fc 15952+
4a4d8108
AM
15953+struct au_ren_args {
15954+ struct {
15955+ struct dentry *dentry, *h_dentry, *parent, *h_parent,
15956+ *wh_dentry;
15957+ struct inode *dir, *inode;
15958+ struct au_hinode *hdir;
15959+ struct au_dtime dt[AuParentChild];
15960+ aufs_bindex_t bstart;
15961+ } sd[AuSrcDst];
1facf9fc 15962+
4a4d8108
AM
15963+#define src_dentry sd[AuSRC].dentry
15964+#define src_dir sd[AuSRC].dir
15965+#define src_inode sd[AuSRC].inode
15966+#define src_h_dentry sd[AuSRC].h_dentry
15967+#define src_parent sd[AuSRC].parent
15968+#define src_h_parent sd[AuSRC].h_parent
15969+#define src_wh_dentry sd[AuSRC].wh_dentry
15970+#define src_hdir sd[AuSRC].hdir
15971+#define src_h_dir sd[AuSRC].hdir->hi_inode
15972+#define src_dt sd[AuSRC].dt
15973+#define src_bstart sd[AuSRC].bstart
1facf9fc 15974+
4a4d8108
AM
15975+#define dst_dentry sd[AuDST].dentry
15976+#define dst_dir sd[AuDST].dir
15977+#define dst_inode sd[AuDST].inode
15978+#define dst_h_dentry sd[AuDST].h_dentry
15979+#define dst_parent sd[AuDST].parent
15980+#define dst_h_parent sd[AuDST].h_parent
15981+#define dst_wh_dentry sd[AuDST].wh_dentry
15982+#define dst_hdir sd[AuDST].hdir
15983+#define dst_h_dir sd[AuDST].hdir->hi_inode
15984+#define dst_dt sd[AuDST].dt
15985+#define dst_bstart sd[AuDST].bstart
15986+
15987+ struct dentry *h_trap;
15988+ struct au_branch *br;
15989+ struct au_hinode *src_hinode;
15990+ struct path h_path;
15991+ struct au_nhash whlist;
027c5e7a 15992+ aufs_bindex_t btgt, src_bwh, src_bdiropq;
1facf9fc 15993+
1308ab2a 15994+ unsigned int flags;
1facf9fc 15995+
4a4d8108
AM
15996+ struct au_whtmp_rmdir *thargs;
15997+ struct dentry *h_dst;
15998+};
1308ab2a 15999+
4a4d8108 16000+/* ---------------------------------------------------------------------- */
1308ab2a 16001+
4a4d8108
AM
16002+/*
16003+ * functions for reverting.
16004+ * when an error happened in a single rename systemcall, we should revert
16005+ * everything as if nothing happend.
16006+ * we don't need to revert the copied-up/down the parent dir since they are
16007+ * harmless.
16008+ */
1facf9fc 16009+
4a4d8108
AM
16010+#define RevertFailure(fmt, ...) do { \
16011+ AuIOErr("revert failure: " fmt " (%d, %d)\n", \
16012+ ##__VA_ARGS__, err, rerr); \
16013+ err = -EIO; \
16014+} while (0)
1facf9fc 16015+
4a4d8108 16016+static void au_ren_rev_diropq(int err, struct au_ren_args *a)
1facf9fc 16017+{
4a4d8108 16018+ int rerr;
1facf9fc 16019+
4a4d8108
AM
16020+ au_hn_imtx_lock_nested(a->src_hinode, AuLsc_I_CHILD);
16021+ rerr = au_diropq_remove(a->src_dentry, a->btgt);
16022+ au_hn_imtx_unlock(a->src_hinode);
027c5e7a 16023+ au_set_dbdiropq(a->src_dentry, a->src_bdiropq);
4a4d8108
AM
16024+ if (rerr)
16025+ RevertFailure("remove diropq %.*s", AuDLNPair(a->src_dentry));
16026+}
1facf9fc 16027+
4a4d8108
AM
16028+static void au_ren_rev_rename(int err, struct au_ren_args *a)
16029+{
16030+ int rerr;
1facf9fc 16031+
4a4d8108
AM
16032+ a->h_path.dentry = au_lkup_one(&a->src_dentry->d_name, a->src_h_parent,
16033+ a->br, /*nd*/NULL);
16034+ rerr = PTR_ERR(a->h_path.dentry);
16035+ if (IS_ERR(a->h_path.dentry)) {
16036+ RevertFailure("au_lkup_one %.*s", AuDLNPair(a->src_dentry));
16037+ return;
1facf9fc 16038+ }
16039+
4a4d8108
AM
16040+ rerr = vfsub_rename(a->dst_h_dir,
16041+ au_h_dptr(a->src_dentry, a->btgt),
16042+ a->src_h_dir, &a->h_path);
16043+ d_drop(a->h_path.dentry);
16044+ dput(a->h_path.dentry);
16045+ /* au_set_h_dptr(a->src_dentry, a->btgt, NULL); */
16046+ if (rerr)
16047+ RevertFailure("rename %.*s", AuDLNPair(a->src_dentry));
1facf9fc 16048+}
16049+
4a4d8108 16050+static void au_ren_rev_cpup(int err, struct au_ren_args *a)
1facf9fc 16051+{
4a4d8108 16052+ int rerr;
1facf9fc 16053+
4a4d8108
AM
16054+ a->h_path.dentry = a->dst_h_dentry;
16055+ rerr = vfsub_unlink(a->dst_h_dir, &a->h_path, /*force*/0);
16056+ au_set_h_dptr(a->src_dentry, a->btgt, NULL);
16057+ au_set_dbstart(a->src_dentry, a->src_bstart);
16058+ if (rerr)
16059+ RevertFailure("unlink %.*s", AuDLNPair(a->dst_h_dentry));
1facf9fc 16060+}
16061+
4a4d8108 16062+static void au_ren_rev_whtmp(int err, struct au_ren_args *a)
1facf9fc 16063+{
4a4d8108 16064+ int rerr;
dece6358 16065+
4a4d8108
AM
16066+ a->h_path.dentry = au_lkup_one(&a->dst_dentry->d_name, a->dst_h_parent,
16067+ a->br, /*nd*/NULL);
16068+ rerr = PTR_ERR(a->h_path.dentry);
16069+ if (IS_ERR(a->h_path.dentry)) {
16070+ RevertFailure("lookup %.*s", AuDLNPair(a->dst_dentry));
16071+ return;
16072+ }
16073+ if (a->h_path.dentry->d_inode) {
16074+ d_drop(a->h_path.dentry);
16075+ dput(a->h_path.dentry);
16076+ return;
dece6358
AM
16077+ }
16078+
4a4d8108
AM
16079+ rerr = vfsub_rename(a->dst_h_dir, a->h_dst, a->dst_h_dir, &a->h_path);
16080+ d_drop(a->h_path.dentry);
16081+ dput(a->h_path.dentry);
16082+ if (!rerr)
16083+ au_set_h_dptr(a->dst_dentry, a->btgt, dget(a->h_dst));
16084+ else
16085+ RevertFailure("rename %.*s", AuDLNPair(a->h_dst));
16086+}
1308ab2a 16087+
4a4d8108
AM
16088+static void au_ren_rev_whsrc(int err, struct au_ren_args *a)
16089+{
16090+ int rerr;
1308ab2a 16091+
4a4d8108
AM
16092+ a->h_path.dentry = a->src_wh_dentry;
16093+ rerr = au_wh_unlink_dentry(a->src_h_dir, &a->h_path, a->src_dentry);
027c5e7a 16094+ au_set_dbwh(a->src_dentry, a->src_bwh);
4a4d8108
AM
16095+ if (rerr)
16096+ RevertFailure("unlink %.*s", AuDLNPair(a->src_wh_dentry));
16097+}
4a4d8108 16098+#undef RevertFailure
1facf9fc 16099+
1308ab2a 16100+/* ---------------------------------------------------------------------- */
16101+
4a4d8108
AM
16102+/*
16103+ * when we have to copyup the renaming entry, do it with the rename-target name
16104+ * in order to minimize the cost (the later actual rename is unnecessary).
16105+ * otherwise rename it on the target branch.
16106+ */
16107+static int au_ren_or_cpup(struct au_ren_args *a)
1facf9fc 16108+{
dece6358 16109+ int err;
4a4d8108 16110+ struct dentry *d;
1facf9fc 16111+
4a4d8108
AM
16112+ d = a->src_dentry;
16113+ if (au_dbstart(d) == a->btgt) {
16114+ a->h_path.dentry = a->dst_h_dentry;
16115+ if (au_ftest_ren(a->flags, DIROPQ)
16116+ && au_dbdiropq(d) == a->btgt)
16117+ au_fclr_ren(a->flags, DIROPQ);
16118+ AuDebugOn(au_dbstart(d) != a->btgt);
16119+ err = vfsub_rename(a->src_h_dir, au_h_dptr(d, a->btgt),
16120+ a->dst_h_dir, &a->h_path);
16121+ } else {
16122+ struct mutex *h_mtx = &a->src_h_dentry->d_inode->i_mutex;
16123+ struct file *h_file;
1308ab2a 16124+
4a4d8108
AM
16125+ au_fset_ren(a->flags, CPUP);
16126+ mutex_lock_nested(h_mtx, AuLsc_I_CHILD);
16127+ au_set_dbstart(d, a->btgt);
16128+ au_set_h_dptr(d, a->btgt, dget(a->dst_h_dentry));
16129+ h_file = au_h_open_pre(d, a->src_bstart);
16130+ if (IS_ERR(h_file)) {
16131+ err = PTR_ERR(h_file);
16132+ h_file = NULL;
16133+ } else
16134+ err = au_sio_cpup_single(d, a->btgt, a->src_bstart, -1,
16135+ !AuCpup_DTIME, a->dst_parent);
16136+ mutex_unlock(h_mtx);
16137+ au_h_open_post(d, a->src_bstart, h_file);
16138+ if (!err) {
16139+ d = a->dst_dentry;
16140+ au_set_h_dptr(d, a->btgt, NULL);
16141+ au_update_dbstart(d);
16142+ } else {
16143+ au_set_h_dptr(d, a->btgt, NULL);
16144+ au_set_dbstart(d, a->src_bstart);
16145+ }
1308ab2a 16146+ }
027c5e7a
AM
16147+ if (!err && a->h_dst)
16148+ /* it will be set to dinfo later */
16149+ dget(a->h_dst);
1facf9fc 16150+
dece6358
AM
16151+ return err;
16152+}
1facf9fc 16153+
4a4d8108
AM
16154+/* cf. aufs_rmdir() */
16155+static int au_ren_del_whtmp(struct au_ren_args *a)
dece6358 16156+{
4a4d8108
AM
16157+ int err;
16158+ struct inode *dir;
1facf9fc 16159+
4a4d8108
AM
16160+ dir = a->dst_dir;
16161+ SiMustAnyLock(dir->i_sb);
16162+ if (!au_nhash_test_longer_wh(&a->whlist, a->btgt,
16163+ au_sbi(dir->i_sb)->si_dirwh)
16164+ || au_test_fs_remote(a->h_dst->d_sb)) {
16165+ err = au_whtmp_rmdir(dir, a->btgt, a->h_dst, &a->whlist);
16166+ if (unlikely(err))
16167+ pr_warning("failed removing whtmp dir %.*s (%d), "
16168+ "ignored.\n", AuDLNPair(a->h_dst), err);
16169+ } else {
16170+ au_nhash_wh_free(&a->thargs->whlist);
16171+ a->thargs->whlist = a->whlist;
16172+ a->whlist.nh_num = 0;
16173+ au_whtmp_kick_rmdir(dir, a->btgt, a->h_dst, a->thargs);
16174+ dput(a->h_dst);
16175+ a->thargs = NULL;
16176+ }
16177+
16178+ return 0;
1308ab2a 16179+}
1facf9fc 16180+
4a4d8108
AM
16181+/* make it 'opaque' dir. */
16182+static int au_ren_diropq(struct au_ren_args *a)
16183+{
16184+ int err;
16185+ struct dentry *diropq;
1facf9fc 16186+
4a4d8108 16187+ err = 0;
027c5e7a 16188+ a->src_bdiropq = au_dbdiropq(a->src_dentry);
4a4d8108
AM
16189+ a->src_hinode = au_hi(a->src_inode, a->btgt);
16190+ au_hn_imtx_lock_nested(a->src_hinode, AuLsc_I_CHILD);
16191+ diropq = au_diropq_create(a->src_dentry, a->btgt);
16192+ au_hn_imtx_unlock(a->src_hinode);
16193+ if (IS_ERR(diropq))
16194+ err = PTR_ERR(diropq);
16195+ dput(diropq);
1facf9fc 16196+
4a4d8108
AM
16197+ return err;
16198+}
1facf9fc 16199+
4a4d8108
AM
16200+static int do_rename(struct au_ren_args *a)
16201+{
16202+ int err;
16203+ struct dentry *d, *h_d;
1facf9fc 16204+
4a4d8108
AM
16205+ /* prepare workqueue args for asynchronous rmdir */
16206+ h_d = a->dst_h_dentry;
16207+ if (au_ftest_ren(a->flags, ISDIR) && h_d->d_inode) {
16208+ err = -ENOMEM;
16209+ a->thargs = au_whtmp_rmdir_alloc(a->src_dentry->d_sb, GFP_NOFS);
16210+ if (unlikely(!a->thargs))
16211+ goto out;
16212+ a->h_dst = dget(h_d);
16213+ }
1facf9fc 16214+
4a4d8108
AM
16215+ /* create whiteout for src_dentry */
16216+ if (au_ftest_ren(a->flags, WHSRC)) {
027c5e7a
AM
16217+ a->src_bwh = au_dbwh(a->src_dentry);
16218+ AuDebugOn(a->src_bwh >= 0);
4a4d8108
AM
16219+ a->src_wh_dentry
16220+ = au_wh_create(a->src_dentry, a->btgt, a->src_h_parent);
16221+ err = PTR_ERR(a->src_wh_dentry);
16222+ if (IS_ERR(a->src_wh_dentry))
16223+ goto out_thargs;
16224+ }
1facf9fc 16225+
4a4d8108
AM
16226+ /* lookup whiteout for dentry */
16227+ if (au_ftest_ren(a->flags, WHDST)) {
16228+ h_d = au_wh_lkup(a->dst_h_parent, &a->dst_dentry->d_name,
16229+ a->br);
16230+ err = PTR_ERR(h_d);
16231+ if (IS_ERR(h_d))
16232+ goto out_whsrc;
16233+ if (!h_d->d_inode)
16234+ dput(h_d);
16235+ else
16236+ a->dst_wh_dentry = h_d;
16237+ }
1facf9fc 16238+
4a4d8108
AM
16239+ /* rename dentry to tmpwh */
16240+ if (a->thargs) {
16241+ err = au_whtmp_ren(a->dst_h_dentry, a->br);
16242+ if (unlikely(err))
16243+ goto out_whdst;
dece6358 16244+
4a4d8108
AM
16245+ d = a->dst_dentry;
16246+ au_set_h_dptr(d, a->btgt, NULL);
16247+ err = au_lkup_neg(d, a->btgt);
16248+ if (unlikely(err))
16249+ goto out_whtmp;
16250+ a->dst_h_dentry = au_h_dptr(d, a->btgt);
16251+ }
1facf9fc 16252+
4a4d8108
AM
16253+ /* cpup src */
16254+ if (a->dst_h_dentry->d_inode && a->src_bstart != a->btgt) {
16255+ struct mutex *h_mtx = &a->src_h_dentry->d_inode->i_mutex;
16256+ struct file *h_file;
1facf9fc 16257+
4a4d8108
AM
16258+ mutex_lock_nested(h_mtx, AuLsc_I_CHILD);
16259+ AuDebugOn(au_dbstart(a->src_dentry) != a->src_bstart);
16260+ h_file = au_h_open_pre(a->src_dentry, a->src_bstart);
16261+ if (IS_ERR(h_file)) {
16262+ err = PTR_ERR(h_file);
16263+ h_file = NULL;
16264+ } else
16265+ err = au_sio_cpup_simple(a->src_dentry, a->btgt, -1,
16266+ !AuCpup_DTIME);
16267+ mutex_unlock(h_mtx);
16268+ au_h_open_post(a->src_dentry, a->src_bstart, h_file);
16269+ if (unlikely(err))
16270+ goto out_whtmp;
16271+ }
1facf9fc 16272+
4a4d8108
AM
16273+ /* rename by vfs_rename or cpup */
16274+ d = a->dst_dentry;
16275+ if (au_ftest_ren(a->flags, ISDIR)
16276+ && (a->dst_wh_dentry
16277+ || au_dbdiropq(d) == a->btgt
16278+ /* hide the lower to keep xino */
16279+ || a->btgt < au_dbend(d)
16280+ || au_opt_test(au_mntflags(d->d_sb), ALWAYS_DIROPQ)))
16281+ au_fset_ren(a->flags, DIROPQ);
16282+ err = au_ren_or_cpup(a);
16283+ if (unlikely(err))
16284+ /* leave the copied-up one */
16285+ goto out_whtmp;
1308ab2a 16286+
4a4d8108
AM
16287+ /* make dir opaque */
16288+ if (au_ftest_ren(a->flags, DIROPQ)) {
16289+ err = au_ren_diropq(a);
16290+ if (unlikely(err))
16291+ goto out_rename;
16292+ }
1308ab2a 16293+
4a4d8108
AM
16294+ /* update target timestamps */
16295+ AuDebugOn(au_dbstart(a->src_dentry) != a->btgt);
16296+ a->h_path.dentry = au_h_dptr(a->src_dentry, a->btgt);
16297+ vfsub_update_h_iattr(&a->h_path, /*did*/NULL); /*ignore*/
16298+ a->src_inode->i_ctime = a->h_path.dentry->d_inode->i_ctime;
1facf9fc 16299+
4a4d8108
AM
16300+ /* remove whiteout for dentry */
16301+ if (a->dst_wh_dentry) {
16302+ a->h_path.dentry = a->dst_wh_dentry;
16303+ err = au_wh_unlink_dentry(a->dst_h_dir, &a->h_path,
16304+ a->dst_dentry);
16305+ if (unlikely(err))
16306+ goto out_diropq;
16307+ }
1facf9fc 16308+
4a4d8108
AM
16309+ /* remove whtmp */
16310+ if (a->thargs)
16311+ au_ren_del_whtmp(a); /* ignore this error */
1308ab2a 16312+
4a4d8108
AM
16313+ err = 0;
16314+ goto out_success;
16315+
4f0767ce 16316+out_diropq:
4a4d8108
AM
16317+ if (au_ftest_ren(a->flags, DIROPQ))
16318+ au_ren_rev_diropq(err, a);
4f0767ce 16319+out_rename:
4a4d8108
AM
16320+ if (!au_ftest_ren(a->flags, CPUP))
16321+ au_ren_rev_rename(err, a);
16322+ else
16323+ au_ren_rev_cpup(err, a);
027c5e7a 16324+ dput(a->h_dst);
4f0767ce 16325+out_whtmp:
4a4d8108
AM
16326+ if (a->thargs)
16327+ au_ren_rev_whtmp(err, a);
4f0767ce 16328+out_whdst:
4a4d8108
AM
16329+ dput(a->dst_wh_dentry);
16330+ a->dst_wh_dentry = NULL;
4f0767ce 16331+out_whsrc:
4a4d8108
AM
16332+ if (a->src_wh_dentry)
16333+ au_ren_rev_whsrc(err, a);
4f0767ce 16334+out_success:
4a4d8108
AM
16335+ dput(a->src_wh_dentry);
16336+ dput(a->dst_wh_dentry);
4f0767ce 16337+out_thargs:
4a4d8108
AM
16338+ if (a->thargs) {
16339+ dput(a->h_dst);
16340+ au_whtmp_rmdir_free(a->thargs);
16341+ a->thargs = NULL;
16342+ }
4f0767ce 16343+out:
4a4d8108 16344+ return err;
dece6358 16345+}
1facf9fc 16346+
1308ab2a 16347+/* ---------------------------------------------------------------------- */
1facf9fc 16348+
4a4d8108
AM
16349+/*
16350+ * test if @dentry dir can be rename destination or not.
16351+ * success means, it is a logically empty dir.
16352+ */
16353+static int may_rename_dstdir(struct dentry *dentry, struct au_nhash *whlist)
1308ab2a 16354+{
4a4d8108 16355+ return au_test_empty(dentry, whlist);
1308ab2a 16356+}
1facf9fc 16357+
4a4d8108
AM
16358+/*
16359+ * test if @dentry dir can be rename source or not.
16360+ * if it can, return 0 and @children is filled.
16361+ * success means,
16362+ * - it is a logically empty dir.
16363+ * - or, it exists on writable branch and has no children including whiteouts
16364+ * on the lower branch.
16365+ */
16366+static int may_rename_srcdir(struct dentry *dentry, aufs_bindex_t btgt)
16367+{
16368+ int err;
16369+ unsigned int rdhash;
16370+ aufs_bindex_t bstart;
1facf9fc 16371+
4a4d8108
AM
16372+ bstart = au_dbstart(dentry);
16373+ if (bstart != btgt) {
16374+ struct au_nhash whlist;
dece6358 16375+
4a4d8108
AM
16376+ SiMustAnyLock(dentry->d_sb);
16377+ rdhash = au_sbi(dentry->d_sb)->si_rdhash;
16378+ if (!rdhash)
16379+ rdhash = au_rdhash_est(au_dir_size(/*file*/NULL,
16380+ dentry));
16381+ err = au_nhash_alloc(&whlist, rdhash, GFP_NOFS);
16382+ if (unlikely(err))
16383+ goto out;
16384+ err = au_test_empty(dentry, &whlist);
16385+ au_nhash_wh_free(&whlist);
16386+ goto out;
16387+ }
dece6358 16388+
4a4d8108
AM
16389+ if (bstart == au_dbtaildir(dentry))
16390+ return 0; /* success */
dece6358 16391+
4a4d8108 16392+ err = au_test_empty_lower(dentry);
1facf9fc 16393+
4f0767ce 16394+out:
4a4d8108
AM
16395+ if (err == -ENOTEMPTY) {
16396+ AuWarn1("renaming dir who has child(ren) on multiple branches,"
16397+ " is not supported\n");
16398+ err = -EXDEV;
16399+ }
16400+ return err;
16401+}
1308ab2a 16402+
4a4d8108
AM
16403+/* side effect: sets whlist and h_dentry */
16404+static int au_ren_may_dir(struct au_ren_args *a)
1308ab2a 16405+{
4a4d8108
AM
16406+ int err;
16407+ unsigned int rdhash;
16408+ struct dentry *d;
1facf9fc 16409+
4a4d8108
AM
16410+ d = a->dst_dentry;
16411+ SiMustAnyLock(d->d_sb);
1facf9fc 16412+
4a4d8108
AM
16413+ err = 0;
16414+ if (au_ftest_ren(a->flags, ISDIR) && a->dst_inode) {
16415+ rdhash = au_sbi(d->d_sb)->si_rdhash;
16416+ if (!rdhash)
16417+ rdhash = au_rdhash_est(au_dir_size(/*file*/NULL, d));
16418+ err = au_nhash_alloc(&a->whlist, rdhash, GFP_NOFS);
16419+ if (unlikely(err))
16420+ goto out;
1308ab2a 16421+
4a4d8108
AM
16422+ au_set_dbstart(d, a->dst_bstart);
16423+ err = may_rename_dstdir(d, &a->whlist);
16424+ au_set_dbstart(d, a->btgt);
16425+ }
16426+ a->dst_h_dentry = au_h_dptr(d, au_dbstart(d));
16427+ if (unlikely(err))
16428+ goto out;
16429+
16430+ d = a->src_dentry;
16431+ a->src_h_dentry = au_h_dptr(d, au_dbstart(d));
16432+ if (au_ftest_ren(a->flags, ISDIR)) {
16433+ err = may_rename_srcdir(d, a->btgt);
16434+ if (unlikely(err)) {
16435+ au_nhash_wh_free(&a->whlist);
16436+ a->whlist.nh_num = 0;
16437+ }
16438+ }
4f0767ce 16439+out:
4a4d8108 16440+ return err;
1facf9fc 16441+}
16442+
4a4d8108 16443+/* ---------------------------------------------------------------------- */
1facf9fc 16444+
4a4d8108
AM
16445+/*
16446+ * simple tests for rename.
16447+ * following the checks in vfs, plus the parent-child relationship.
16448+ */
16449+static int au_may_ren(struct au_ren_args *a)
16450+{
16451+ int err, isdir;
16452+ struct inode *h_inode;
1facf9fc 16453+
4a4d8108
AM
16454+ if (a->src_bstart == a->btgt) {
16455+ err = au_may_del(a->src_dentry, a->btgt, a->src_h_parent,
16456+ au_ftest_ren(a->flags, ISDIR));
16457+ if (unlikely(err))
16458+ goto out;
16459+ err = -EINVAL;
16460+ if (unlikely(a->src_h_dentry == a->h_trap))
16461+ goto out;
16462+ }
1facf9fc 16463+
4a4d8108
AM
16464+ err = 0;
16465+ if (a->dst_bstart != a->btgt)
16466+ goto out;
1facf9fc 16467+
027c5e7a
AM
16468+ err = -ENOTEMPTY;
16469+ if (unlikely(a->dst_h_dentry == a->h_trap))
16470+ goto out;
16471+
4a4d8108
AM
16472+ err = -EIO;
16473+ h_inode = a->dst_h_dentry->d_inode;
16474+ isdir = !!au_ftest_ren(a->flags, ISDIR);
16475+ if (!a->dst_dentry->d_inode) {
16476+ if (unlikely(h_inode))
16477+ goto out;
16478+ err = au_may_add(a->dst_dentry, a->btgt, a->dst_h_parent,
16479+ isdir);
16480+ } else {
16481+ if (unlikely(!h_inode || !h_inode->i_nlink))
16482+ goto out;
16483+ err = au_may_del(a->dst_dentry, a->btgt, a->dst_h_parent,
16484+ isdir);
16485+ if (unlikely(err))
16486+ goto out;
4a4d8108 16487+ }
1facf9fc 16488+
4f0767ce 16489+out:
4a4d8108
AM
16490+ if (unlikely(err == -ENOENT || err == -EEXIST))
16491+ err = -EIO;
16492+ AuTraceErr(err);
16493+ return err;
16494+}
1facf9fc 16495+
1308ab2a 16496+/* ---------------------------------------------------------------------- */
1facf9fc 16497+
4a4d8108
AM
16498+/*
16499+ * locking order
16500+ * (VFS)
16501+ * - src_dir and dir by lock_rename()
16502+ * - inode if exitsts
16503+ * (aufs)
16504+ * - lock all
16505+ * + src_dentry and dentry by aufs_read_and_write_lock2() which calls,
16506+ * + si_read_lock
16507+ * + di_write_lock2_child()
16508+ * + di_write_lock_child()
16509+ * + ii_write_lock_child()
16510+ * + di_write_lock_child2()
16511+ * + ii_write_lock_child2()
16512+ * + src_parent and parent
16513+ * + di_write_lock_parent()
16514+ * + ii_write_lock_parent()
16515+ * + di_write_lock_parent2()
16516+ * + ii_write_lock_parent2()
16517+ * + lower src_dir and dir by vfsub_lock_rename()
16518+ * + verify the every relationships between child and parent. if any
16519+ * of them failed, unlock all and return -EBUSY.
16520+ */
16521+static void au_ren_unlock(struct au_ren_args *a)
1308ab2a 16522+{
4a4d8108
AM
16523+ struct super_block *sb;
16524+
16525+ sb = a->dst_dentry->d_sb;
16526+ if (au_ftest_ren(a->flags, MNT_WRITE))
16527+ mnt_drop_write(a->br->br_mnt);
16528+ vfsub_unlock_rename(a->src_h_parent, a->src_hdir,
16529+ a->dst_h_parent, a->dst_hdir);
1308ab2a 16530+}
16531+
4a4d8108 16532+static int au_ren_lock(struct au_ren_args *a)
1308ab2a 16533+{
4a4d8108
AM
16534+ int err;
16535+ unsigned int udba;
1308ab2a 16536+
4a4d8108
AM
16537+ err = 0;
16538+ a->src_h_parent = au_h_dptr(a->src_parent, a->btgt);
16539+ a->src_hdir = au_hi(a->src_dir, a->btgt);
16540+ a->dst_h_parent = au_h_dptr(a->dst_parent, a->btgt);
16541+ a->dst_hdir = au_hi(a->dst_dir, a->btgt);
16542+ a->h_trap = vfsub_lock_rename(a->src_h_parent, a->src_hdir,
16543+ a->dst_h_parent, a->dst_hdir);
16544+ udba = au_opt_udba(a->src_dentry->d_sb);
16545+ if (unlikely(a->src_hdir->hi_inode != a->src_h_parent->d_inode
16546+ || a->dst_hdir->hi_inode != a->dst_h_parent->d_inode))
16547+ err = au_busy_or_stale();
16548+ if (!err && au_dbstart(a->src_dentry) == a->btgt)
16549+ err = au_h_verify(a->src_h_dentry, udba,
16550+ a->src_h_parent->d_inode, a->src_h_parent,
16551+ a->br);
16552+ if (!err && au_dbstart(a->dst_dentry) == a->btgt)
16553+ err = au_h_verify(a->dst_h_dentry, udba,
16554+ a->dst_h_parent->d_inode, a->dst_h_parent,
16555+ a->br);
16556+ if (!err) {
16557+ err = mnt_want_write(a->br->br_mnt);
16558+ if (unlikely(err))
16559+ goto out_unlock;
16560+ au_fset_ren(a->flags, MNT_WRITE);
16561+ goto out; /* success */
16562+ }
16563+
16564+ err = au_busy_or_stale();
16565+
4f0767ce 16566+out_unlock:
4a4d8108 16567+ au_ren_unlock(a);
4f0767ce 16568+out:
4a4d8108 16569+ return err;
1facf9fc 16570+}
16571+
16572+/* ---------------------------------------------------------------------- */
16573+
4a4d8108 16574+static void au_ren_refresh_dir(struct au_ren_args *a)
1facf9fc 16575+{
4a4d8108 16576+ struct inode *dir;
dece6358 16577+
4a4d8108
AM
16578+ dir = a->dst_dir;
16579+ dir->i_version++;
16580+ if (au_ftest_ren(a->flags, ISDIR)) {
16581+ /* is this updating defined in POSIX? */
16582+ au_cpup_attr_timesizes(a->src_inode);
16583+ au_cpup_attr_nlink(dir, /*force*/1);
4a4d8108 16584+ }
027c5e7a 16585+
4a4d8108
AM
16586+ if (au_ibstart(dir) == a->btgt)
16587+ au_cpup_attr_timesizes(dir);
dece6358 16588+
4a4d8108
AM
16589+ if (au_ftest_ren(a->flags, ISSAMEDIR))
16590+ return;
dece6358 16591+
4a4d8108
AM
16592+ dir = a->src_dir;
16593+ dir->i_version++;
16594+ if (au_ftest_ren(a->flags, ISDIR))
16595+ au_cpup_attr_nlink(dir, /*force*/1);
16596+ if (au_ibstart(dir) == a->btgt)
16597+ au_cpup_attr_timesizes(dir);
1facf9fc 16598+}
16599+
4a4d8108 16600+static void au_ren_refresh(struct au_ren_args *a)
1facf9fc 16601+{
4a4d8108
AM
16602+ aufs_bindex_t bend, bindex;
16603+ struct dentry *d, *h_d;
16604+ struct inode *i, *h_i;
16605+ struct super_block *sb;
dece6358 16606+
027c5e7a
AM
16607+ d = a->dst_dentry;
16608+ d_drop(d);
16609+ if (a->h_dst)
16610+ /* already dget-ed by au_ren_or_cpup() */
16611+ au_set_h_dptr(d, a->btgt, a->h_dst);
16612+
16613+ i = a->dst_inode;
16614+ if (i) {
16615+ if (!au_ftest_ren(a->flags, ISDIR))
16616+ vfsub_drop_nlink(i);
16617+ else {
16618+ vfsub_dead_dir(i);
16619+ au_cpup_attr_timesizes(i);
16620+ }
16621+ au_update_dbrange(d, /*do_put_zero*/1);
16622+ } else {
16623+ bend = a->btgt;
16624+ for (bindex = au_dbstart(d); bindex < bend; bindex++)
16625+ au_set_h_dptr(d, bindex, NULL);
16626+ bend = au_dbend(d);
16627+ for (bindex = a->btgt + 1; bindex <= bend; bindex++)
16628+ au_set_h_dptr(d, bindex, NULL);
16629+ au_update_dbrange(d, /*do_put_zero*/0);
16630+ }
16631+
4a4d8108
AM
16632+ d = a->src_dentry;
16633+ au_set_dbwh(d, -1);
16634+ bend = au_dbend(d);
16635+ for (bindex = a->btgt + 1; bindex <= bend; bindex++) {
16636+ h_d = au_h_dptr(d, bindex);
16637+ if (h_d)
16638+ au_set_h_dptr(d, bindex, NULL);
16639+ }
16640+ au_set_dbend(d, a->btgt);
16641+
16642+ sb = d->d_sb;
16643+ i = a->src_inode;
16644+ if (au_opt_test(au_mntflags(sb), PLINK) && au_plink_test(i))
16645+ return; /* success */
16646+
16647+ bend = au_ibend(i);
16648+ for (bindex = a->btgt + 1; bindex <= bend; bindex++) {
16649+ h_i = au_h_iptr(i, bindex);
16650+ if (h_i) {
16651+ au_xino_write(sb, bindex, h_i->i_ino, /*ino*/0);
16652+ /* ignore this error */
16653+ au_set_h_iptr(i, bindex, NULL, 0);
16654+ }
16655+ }
16656+ au_set_ibend(i, a->btgt);
1308ab2a 16657+}
dece6358 16658+
4a4d8108
AM
16659+/* ---------------------------------------------------------------------- */
16660+
16661+/* mainly for link(2) and rename(2) */
16662+int au_wbr(struct dentry *dentry, aufs_bindex_t btgt)
1308ab2a 16663+{
4a4d8108
AM
16664+ aufs_bindex_t bdiropq, bwh;
16665+ struct dentry *parent;
16666+ struct au_branch *br;
16667+
16668+ parent = dentry->d_parent;
16669+ IMustLock(parent->d_inode); /* dir is locked */
16670+
16671+ bdiropq = au_dbdiropq(parent);
16672+ bwh = au_dbwh(dentry);
16673+ br = au_sbr(dentry->d_sb, btgt);
16674+ if (au_br_rdonly(br)
16675+ || (0 <= bdiropq && bdiropq < btgt)
16676+ || (0 <= bwh && bwh < btgt))
16677+ btgt = -1;
16678+
16679+ AuDbg("btgt %d\n", btgt);
16680+ return btgt;
1facf9fc 16681+}
16682+
4a4d8108
AM
16683+/* sets src_bstart, dst_bstart and btgt */
16684+static int au_ren_wbr(struct au_ren_args *a)
1facf9fc 16685+{
4a4d8108
AM
16686+ int err;
16687+ struct au_wr_dir_args wr_dir_args = {
16688+ /* .force_btgt = -1, */
16689+ .flags = AuWrDir_ADD_ENTRY
16690+ };
dece6358 16691+
4a4d8108
AM
16692+ a->src_bstart = au_dbstart(a->src_dentry);
16693+ a->dst_bstart = au_dbstart(a->dst_dentry);
16694+ if (au_ftest_ren(a->flags, ISDIR))
16695+ au_fset_wrdir(wr_dir_args.flags, ISDIR);
16696+ wr_dir_args.force_btgt = a->src_bstart;
16697+ if (a->dst_inode && a->dst_bstart < a->src_bstart)
16698+ wr_dir_args.force_btgt = a->dst_bstart;
16699+ wr_dir_args.force_btgt = au_wbr(a->dst_dentry, wr_dir_args.force_btgt);
16700+ err = au_wr_dir(a->dst_dentry, a->src_dentry, &wr_dir_args);
16701+ a->btgt = err;
dece6358 16702+
4a4d8108 16703+ return err;
1facf9fc 16704+}
16705+
4a4d8108 16706+static void au_ren_dt(struct au_ren_args *a)
1facf9fc 16707+{
4a4d8108
AM
16708+ a->h_path.dentry = a->src_h_parent;
16709+ au_dtime_store(a->src_dt + AuPARENT, a->src_parent, &a->h_path);
16710+ if (!au_ftest_ren(a->flags, ISSAMEDIR)) {
16711+ a->h_path.dentry = a->dst_h_parent;
16712+ au_dtime_store(a->dst_dt + AuPARENT, a->dst_parent, &a->h_path);
16713+ }
1facf9fc 16714+
4a4d8108
AM
16715+ au_fclr_ren(a->flags, DT_DSTDIR);
16716+ if (!au_ftest_ren(a->flags, ISDIR))
16717+ return;
dece6358 16718+
4a4d8108
AM
16719+ a->h_path.dentry = a->src_h_dentry;
16720+ au_dtime_store(a->src_dt + AuCHILD, a->src_dentry, &a->h_path);
16721+ if (a->dst_h_dentry->d_inode) {
16722+ au_fset_ren(a->flags, DT_DSTDIR);
16723+ a->h_path.dentry = a->dst_h_dentry;
16724+ au_dtime_store(a->dst_dt + AuCHILD, a->dst_dentry, &a->h_path);
16725+ }
1308ab2a 16726+}
dece6358 16727+
4a4d8108 16728+static void au_ren_rev_dt(int err, struct au_ren_args *a)
1308ab2a 16729+{
4a4d8108
AM
16730+ struct dentry *h_d;
16731+ struct mutex *h_mtx;
16732+
16733+ au_dtime_revert(a->src_dt + AuPARENT);
16734+ if (!au_ftest_ren(a->flags, ISSAMEDIR))
16735+ au_dtime_revert(a->dst_dt + AuPARENT);
16736+
16737+ if (au_ftest_ren(a->flags, ISDIR) && err != -EIO) {
16738+ h_d = a->src_dt[AuCHILD].dt_h_path.dentry;
16739+ h_mtx = &h_d->d_inode->i_mutex;
16740+ mutex_lock_nested(h_mtx, AuLsc_I_CHILD);
16741+ au_dtime_revert(a->src_dt + AuCHILD);
16742+ mutex_unlock(h_mtx);
16743+
16744+ if (au_ftest_ren(a->flags, DT_DSTDIR)) {
16745+ h_d = a->dst_dt[AuCHILD].dt_h_path.dentry;
16746+ h_mtx = &h_d->d_inode->i_mutex;
16747+ mutex_lock_nested(h_mtx, AuLsc_I_CHILD);
16748+ au_dtime_revert(a->dst_dt + AuCHILD);
16749+ mutex_unlock(h_mtx);
1facf9fc 16750+ }
16751+ }
16752+}
16753+
4a4d8108
AM
16754+/* ---------------------------------------------------------------------- */
16755+
16756+int aufs_rename(struct inode *_src_dir, struct dentry *_src_dentry,
16757+ struct inode *_dst_dir, struct dentry *_dst_dentry)
1facf9fc 16758+{
e49829fe 16759+ int err, flags;
4a4d8108
AM
16760+ /* reduce stack space */
16761+ struct au_ren_args *a;
16762+
16763+ AuDbg("%.*s, %.*s\n", AuDLNPair(_src_dentry), AuDLNPair(_dst_dentry));
16764+ IMustLock(_src_dir);
16765+ IMustLock(_dst_dir);
16766+
16767+ err = -ENOMEM;
16768+ BUILD_BUG_ON(sizeof(*a) > PAGE_SIZE);
16769+ a = kzalloc(sizeof(*a), GFP_NOFS);
16770+ if (unlikely(!a))
16771+ goto out;
16772+
16773+ a->src_dir = _src_dir;
16774+ a->src_dentry = _src_dentry;
16775+ a->src_inode = a->src_dentry->d_inode;
16776+ a->src_parent = a->src_dentry->d_parent; /* dir inode is locked */
16777+ a->dst_dir = _dst_dir;
16778+ a->dst_dentry = _dst_dentry;
16779+ a->dst_inode = a->dst_dentry->d_inode;
16780+ a->dst_parent = a->dst_dentry->d_parent; /* dir inode is locked */
16781+ if (a->dst_inode) {
16782+ IMustLock(a->dst_inode);
16783+ au_igrab(a->dst_inode);
1facf9fc 16784+ }
1facf9fc 16785+
4a4d8108 16786+ err = -ENOTDIR;
027c5e7a 16787+ flags = AuLock_FLUSH | AuLock_NOPLM | AuLock_GEN;
4a4d8108
AM
16788+ if (S_ISDIR(a->src_inode->i_mode)) {
16789+ au_fset_ren(a->flags, ISDIR);
16790+ if (unlikely(a->dst_inode && !S_ISDIR(a->dst_inode->i_mode)))
16791+ goto out_free;
e49829fe
JR
16792+ err = aufs_read_and_write_lock2(a->dst_dentry, a->src_dentry,
16793+ AuLock_DIR | flags);
4a4d8108 16794+ } else
e49829fe
JR
16795+ err = aufs_read_and_write_lock2(a->dst_dentry, a->src_dentry,
16796+ flags);
16797+ if (unlikely(err))
16798+ goto out_free;
1facf9fc 16799+
027c5e7a
AM
16800+ err = au_d_hashed_positive(a->src_dentry);
16801+ if (unlikely(err))
16802+ goto out_unlock;
16803+ err = -ENOENT;
16804+ if (a->dst_inode) {
16805+ /*
16806+ * If it is a dir, VFS unhash dst_dentry before this
16807+ * function. It means we cannot rely upon d_unhashed().
16808+ */
16809+ if (unlikely(!a->dst_inode->i_nlink))
16810+ goto out_unlock;
16811+ if (!S_ISDIR(a->dst_inode->i_mode)) {
16812+ err = au_d_hashed_positive(a->dst_dentry);
16813+ if (unlikely(err))
16814+ goto out_unlock;
16815+ } else if (unlikely(IS_DEADDIR(a->dst_inode)))
16816+ goto out_unlock;
16817+ } else if (unlikely(d_unhashed(a->dst_dentry)))
16818+ goto out_unlock;
16819+
4a4d8108
AM
16820+ au_fset_ren(a->flags, ISSAMEDIR); /* temporary */
16821+ di_write_lock_parent(a->dst_parent);
1facf9fc 16822+
4a4d8108
AM
16823+ /* which branch we process */
16824+ err = au_ren_wbr(a);
16825+ if (unlikely(err < 0))
027c5e7a 16826+ goto out_parent;
4a4d8108
AM
16827+ a->br = au_sbr(a->dst_dentry->d_sb, a->btgt);
16828+ a->h_path.mnt = a->br->br_mnt;
1facf9fc 16829+
4a4d8108
AM
16830+ /* are they available to be renamed */
16831+ err = au_ren_may_dir(a);
16832+ if (unlikely(err))
16833+ goto out_children;
1facf9fc 16834+
4a4d8108
AM
16835+ /* prepare the writable parent dir on the same branch */
16836+ if (a->dst_bstart == a->btgt) {
16837+ au_fset_ren(a->flags, WHDST);
16838+ } else {
16839+ err = au_cpup_dirs(a->dst_dentry, a->btgt);
16840+ if (unlikely(err))
16841+ goto out_children;
16842+ }
1facf9fc 16843+
4a4d8108
AM
16844+ if (a->src_dir != a->dst_dir) {
16845+ /*
16846+ * this temporary unlock is safe,
16847+ * because both dir->i_mutex are locked.
16848+ */
16849+ di_write_unlock(a->dst_parent);
16850+ di_write_lock_parent(a->src_parent);
16851+ err = au_wr_dir_need_wh(a->src_dentry,
16852+ au_ftest_ren(a->flags, ISDIR),
16853+ &a->btgt);
16854+ di_write_unlock(a->src_parent);
16855+ di_write_lock2_parent(a->src_parent, a->dst_parent, /*isdir*/1);
16856+ au_fclr_ren(a->flags, ISSAMEDIR);
16857+ } else
16858+ err = au_wr_dir_need_wh(a->src_dentry,
16859+ au_ftest_ren(a->flags, ISDIR),
16860+ &a->btgt);
16861+ if (unlikely(err < 0))
16862+ goto out_children;
16863+ if (err)
16864+ au_fset_ren(a->flags, WHSRC);
1facf9fc 16865+
4a4d8108
AM
16866+ /* lock them all */
16867+ err = au_ren_lock(a);
16868+ if (unlikely(err))
16869+ goto out_children;
1facf9fc 16870+
4a4d8108
AM
16871+ if (!au_opt_test(au_mntflags(a->dst_dir->i_sb), UDBA_NONE))
16872+ err = au_may_ren(a);
16873+ else if (unlikely(a->dst_dentry->d_name.len > AUFS_MAX_NAMELEN))
16874+ err = -ENAMETOOLONG;
16875+ if (unlikely(err))
16876+ goto out_hdir;
1facf9fc 16877+
4a4d8108
AM
16878+ /* store timestamps to be revertible */
16879+ au_ren_dt(a);
1facf9fc 16880+
4a4d8108
AM
16881+ /* here we go */
16882+ err = do_rename(a);
16883+ if (unlikely(err))
16884+ goto out_dt;
16885+
16886+ /* update dir attributes */
16887+ au_ren_refresh_dir(a);
16888+
16889+ /* dput/iput all lower dentries */
16890+ au_ren_refresh(a);
16891+
16892+ goto out_hdir; /* success */
16893+
4f0767ce 16894+out_dt:
4a4d8108 16895+ au_ren_rev_dt(err, a);
4f0767ce 16896+out_hdir:
4a4d8108 16897+ au_ren_unlock(a);
4f0767ce 16898+out_children:
4a4d8108 16899+ au_nhash_wh_free(&a->whlist);
027c5e7a
AM
16900+ if (err && a->dst_inode && a->dst_bstart != a->btgt) {
16901+ AuDbg("bstart %d, btgt %d\n", a->dst_bstart, a->btgt);
16902+ au_set_h_dptr(a->dst_dentry, a->btgt, NULL);
16903+ au_set_dbstart(a->dst_dentry, a->dst_bstart);
4a4d8108 16904+ }
027c5e7a 16905+out_parent:
4a4d8108
AM
16906+ if (!err)
16907+ d_move(a->src_dentry, a->dst_dentry);
027c5e7a
AM
16908+ else {
16909+ au_update_dbstart(a->dst_dentry);
16910+ if (!a->dst_inode)
16911+ d_drop(a->dst_dentry);
16912+ }
4a4d8108
AM
16913+ if (au_ftest_ren(a->flags, ISSAMEDIR))
16914+ di_write_unlock(a->dst_parent);
16915+ else
16916+ di_write_unlock2(a->src_parent, a->dst_parent);
027c5e7a 16917+out_unlock:
4a4d8108 16918+ aufs_read_and_write_unlock2(a->dst_dentry, a->src_dentry);
4f0767ce 16919+out_free:
4a4d8108
AM
16920+ iput(a->dst_inode);
16921+ if (a->thargs)
16922+ au_whtmp_rmdir_free(a->thargs);
16923+ kfree(a);
4f0767ce 16924+out:
4a4d8108
AM
16925+ AuTraceErr(err);
16926+ return err;
1308ab2a 16927+}
7f207e10
AM
16928diff -urN /usr/share/empty/fs/aufs/Kconfig linux/fs/aufs/Kconfig
16929--- /usr/share/empty/fs/aufs/Kconfig 1970-01-01 01:00:00.000000000 +0100
87a755f4 16930+++ linux/fs/aufs/Kconfig 2011-07-22 08:26:47.854303107 +0200
2cbb1c4b 16931@@ -0,0 +1,203 @@
4a4d8108
AM
16932+config AUFS_FS
16933+ tristate "Aufs (Advanced multi layered unification filesystem) support"
16934+ depends on EXPERIMENTAL
16935+ help
16936+ Aufs is a stackable unification filesystem such as Unionfs,
16937+ which unifies several directories and provides a merged single
16938+ directory.
16939+ In the early days, aufs was entirely re-designed and
16940+ re-implemented Unionfs Version 1.x series. Introducing many
16941+ original ideas, approaches and improvements, it becomes totally
16942+ different from Unionfs while keeping the basic features.
1facf9fc 16943+
4a4d8108
AM
16944+if AUFS_FS
16945+choice
16946+ prompt "Maximum number of branches"
16947+ default AUFS_BRANCH_MAX_127
16948+ help
16949+ Specifies the maximum number of branches (or member directories)
16950+ in a single aufs. The larger value consumes more system
16951+ resources and has a minor impact to performance.
16952+config AUFS_BRANCH_MAX_127
16953+ bool "127"
16954+ help
16955+ Specifies the maximum number of branches (or member directories)
16956+ in a single aufs. The larger value consumes more system
16957+ resources and has a minor impact to performance.
16958+config AUFS_BRANCH_MAX_511
16959+ bool "511"
16960+ help
16961+ Specifies the maximum number of branches (or member directories)
16962+ in a single aufs. The larger value consumes more system
16963+ resources and has a minor impact to performance.
16964+config AUFS_BRANCH_MAX_1023
16965+ bool "1023"
16966+ help
16967+ Specifies the maximum number of branches (or member directories)
16968+ in a single aufs. The larger value consumes more system
16969+ resources and has a minor impact to performance.
16970+config AUFS_BRANCH_MAX_32767
16971+ bool "32767"
16972+ help
16973+ Specifies the maximum number of branches (or member directories)
16974+ in a single aufs. The larger value consumes more system
16975+ resources and has a minor impact to performance.
16976+endchoice
1facf9fc 16977+
e49829fe
JR
16978+config AUFS_SBILIST
16979+ bool
16980+ depends on AUFS_MAGIC_SYSRQ || PROC_FS
16981+ default y
16982+ help
16983+ Automatic configuration for internal use.
16984+ When aufs supports Magic SysRq or /proc, enabled automatically.
16985+
4a4d8108
AM
16986+config AUFS_HNOTIFY
16987+ bool "Detect direct branch access (bypassing aufs)"
16988+ help
16989+ If you want to modify files on branches directly, eg. bypassing aufs,
16990+ and want aufs to detect the changes of them fully, then enable this
16991+ option and use 'udba=notify' mount option.
7f207e10 16992+ Currently there is only one available configuration, "fsnotify".
4a4d8108
AM
16993+ It will have a negative impact to the performance.
16994+ See detail in aufs.5.
dece6358 16995+
4a4d8108
AM
16996+choice
16997+ prompt "method" if AUFS_HNOTIFY
16998+ default AUFS_HFSNOTIFY
16999+config AUFS_HFSNOTIFY
17000+ bool "fsnotify"
17001+ select FSNOTIFY
4a4d8108 17002+endchoice
1facf9fc 17003+
4a4d8108
AM
17004+config AUFS_EXPORT
17005+ bool "NFS-exportable aufs"
2cbb1c4b 17006+ depends on EXPORTFS
4a4d8108
AM
17007+ help
17008+ If you want to export your mounted aufs via NFS, then enable this
17009+ option. There are several requirements for this configuration.
17010+ See detail in aufs.5.
1facf9fc 17011+
4a4d8108
AM
17012+config AUFS_INO_T_64
17013+ bool
17014+ depends on AUFS_EXPORT
17015+ depends on 64BIT && !(ALPHA || S390)
17016+ default y
17017+ help
17018+ Automatic configuration for internal use.
17019+ /* typedef unsigned long/int __kernel_ino_t */
17020+ /* alpha and s390x are int */
1facf9fc 17021+
4a4d8108
AM
17022+config AUFS_RDU
17023+ bool "Readdir in userspace"
17024+ help
17025+ Aufs has two methods to provide a merged view for a directory,
17026+ by a user-space library and by kernel-space natively. The latter
17027+ is always enabled but sometimes large and slow.
17028+ If you enable this option, install the library in aufs2-util
17029+ package, and set some environment variables for your readdir(3),
17030+ then the work will be handled in user-space which generally
17031+ shows better performance in most cases.
17032+ See detail in aufs.5.
1facf9fc 17033+
2cbb1c4b
JR
17034+config AUFS_PROC_MAP
17035+ bool "support for /proc/maps and lsof(1)"
17036+ depends on PROC_FS
17037+ help
17038+ When you issue mmap(2) in aufs, it is actually a direct mmap(2)
17039+ call to the file on the branch fs since the file in aufs is
17040+ purely virtual. And the file path printed in /proc/maps (and
17041+ others) will be the path on the branch fs. In most cases, it
17042+ does no harm. But some utilities like lsof(1) may confuse since
17043+ the utility or user may expect the file path in aufs to be
17044+ printed.
17045+ To address this issue, aufs provides a patch which introduces a
17046+ new member called vm_prfile into struct vm_are_struct. The patch
17047+ is meaningless without enabling this configuration since nobody
17048+ sets the new vm_prfile member.
17049+ If you don't apply the patch, then enabling this configuration
17050+ will cause a compile error.
17051+ This approach is fragile since if someone else make some changes
17052+ around vm_file, then vm_prfile may not work anymore. As a
17053+ workaround such case, aufs provides this configuration. If you
17054+ disable it, then lsof(1) may produce incorrect result but the
17055+ problem will be gone even if the aufs patch is applied (I hope).
17056+
4a4d8108
AM
17057+config AUFS_SP_IATTR
17058+ bool "Respect the attributes (mtime/ctime mainly) of special files"
17059+ help
17060+ When you write something to a special file, some attributes of it
17061+ (mtime/ctime mainly) may be updated. Generally such updates are
17062+ less important (actually some device drivers and NFS ignore
17063+ it). But some applications (such like test program) requires
17064+ such updates. If you need these updates, then enable this
17065+ configuration which introduces some overhead.
17066+ Currently this configuration handles FIFO only.
1facf9fc 17067+
4a4d8108
AM
17068+config AUFS_SHWH
17069+ bool "Show whiteouts"
17070+ help
17071+ If you want to make the whiteouts in aufs visible, then enable
17072+ this option and specify 'shwh' mount option. Although it may
17073+ sounds like philosophy or something, but in technically it
17074+ simply shows the name of whiteout with keeping its behaviour.
1facf9fc 17075+
4a4d8108
AM
17076+config AUFS_BR_RAMFS
17077+ bool "Ramfs (initramfs/rootfs) as an aufs branch"
17078+ help
17079+ If you want to use ramfs as an aufs branch fs, then enable this
17080+ option. Generally tmpfs is recommended.
17081+ Aufs prohibited them to be a branch fs by default, because
17082+ initramfs becomes unusable after switch_root or something
17083+ generally. If you sets initramfs as an aufs branch and boot your
17084+ system by switch_root, you will meet a problem easily since the
17085+ files in initramfs may be inaccessible.
17086+ Unless you are going to use ramfs as an aufs branch fs without
17087+ switch_root or something, leave it N.
1facf9fc 17088+
4a4d8108
AM
17089+config AUFS_BR_FUSE
17090+ bool "Fuse fs as an aufs branch"
17091+ depends on FUSE_FS
17092+ select AUFS_POLL
17093+ help
17094+ If you want to use fuse-based userspace filesystem as an aufs
17095+ branch fs, then enable this option.
17096+ It implements the internal poll(2) operation which is
17097+ implemented by fuse only (curretnly).
1facf9fc 17098+
4a4d8108
AM
17099+config AUFS_POLL
17100+ bool
17101+ help
17102+ Automatic configuration for internal use.
1facf9fc 17103+
4a4d8108
AM
17104+config AUFS_BR_HFSPLUS
17105+ bool "Hfsplus as an aufs branch"
17106+ depends on HFSPLUS_FS
17107+ default y
17108+ help
17109+ If you want to use hfsplus fs as an aufs branch fs, then enable
17110+ this option. This option introduces a small overhead at
17111+ copying-up a file on hfsplus.
1facf9fc 17112+
4a4d8108
AM
17113+config AUFS_BDEV_LOOP
17114+ bool
17115+ depends on BLK_DEV_LOOP
17116+ default y
17117+ help
17118+ Automatic configuration for internal use.
17119+ Convert =[ym] into =y.
1308ab2a 17120+
4a4d8108
AM
17121+config AUFS_DEBUG
17122+ bool "Debug aufs"
17123+ help
17124+ Enable this to compile aufs internal debug code.
17125+ It will have a negative impact to the performance.
17126+
17127+config AUFS_MAGIC_SYSRQ
17128+ bool
17129+ depends on AUFS_DEBUG && MAGIC_SYSRQ
17130+ default y
17131+ help
17132+ Automatic configuration for internal use.
17133+ When aufs supports Magic SysRq, enabled automatically.
17134+endif
7f207e10
AM
17135diff -urN /usr/share/empty/fs/aufs/loop.c linux/fs/aufs/loop.c
17136--- /usr/share/empty/fs/aufs/loop.c 1970-01-01 01:00:00.000000000 +0100
87a755f4
AM
17137+++ linux/fs/aufs/loop.c 2011-07-22 08:26:47.857636522 +0200
17138@@ -0,0 +1,133 @@
1facf9fc 17139+/*
027c5e7a 17140+ * Copyright (C) 2005-2011 Junjiro R. Okajima
1facf9fc 17141+ *
17142+ * This program, aufs is free software; you can redistribute it and/or modify
17143+ * it under the terms of the GNU General Public License as published by
17144+ * the Free Software Foundation; either version 2 of the License, or
17145+ * (at your option) any later version.
dece6358
AM
17146+ *
17147+ * This program is distributed in the hope that it will be useful,
17148+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
17149+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17150+ * GNU General Public License for more details.
17151+ *
17152+ * You should have received a copy of the GNU General Public License
17153+ * along with this program; if not, write to the Free Software
17154+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 17155+ */
17156+
17157+/*
17158+ * support for loopback block device as a branch
17159+ */
17160+
17161+#include <linux/loop.h>
17162+#include "aufs.h"
17163+
17164+/*
17165+ * test if two lower dentries have overlapping branches.
17166+ */
b752ccd1 17167+int au_test_loopback_overlap(struct super_block *sb, struct dentry *h_adding)
1facf9fc 17168+{
b752ccd1 17169+ struct super_block *h_sb;
1facf9fc 17170+ struct loop_device *l;
17171+
b752ccd1
AM
17172+ h_sb = h_adding->d_sb;
17173+ if (MAJOR(h_sb->s_dev) != LOOP_MAJOR)
1facf9fc 17174+ return 0;
17175+
b752ccd1
AM
17176+ l = h_sb->s_bdev->bd_disk->private_data;
17177+ h_adding = l->lo_backing_file->f_dentry;
17178+ /*
17179+ * h_adding can be local NFS.
17180+ * in this case aufs cannot detect the loop.
17181+ */
17182+ if (unlikely(h_adding->d_sb == sb))
1facf9fc 17183+ return 1;
b752ccd1 17184+ return !!au_test_subdir(h_adding, sb->s_root);
1facf9fc 17185+}
17186+
17187+/* true if a kernel thread named 'loop[0-9].*' accesses a file */
17188+int au_test_loopback_kthread(void)
17189+{
b752ccd1
AM
17190+ int ret;
17191+ struct task_struct *tsk = current;
17192+
17193+ ret = 0;
17194+ if (tsk->flags & PF_KTHREAD) {
17195+ const char c = tsk->comm[4];
17196+ ret = ('0' <= c && c <= '9'
17197+ && !strncmp(tsk->comm, "loop", 4));
17198+ }
1facf9fc 17199+
b752ccd1 17200+ return ret;
1facf9fc 17201+}
87a755f4
AM
17202+
17203+/* ---------------------------------------------------------------------- */
17204+
17205+#define au_warn_loopback_step 16
17206+static int au_warn_loopback_nelem = au_warn_loopback_step;
17207+static unsigned long *au_warn_loopback_array;
17208+
17209+void au_warn_loopback(struct super_block *h_sb)
17210+{
17211+ int i, new_nelem;
17212+ unsigned long *a, magic;
17213+ static DEFINE_SPINLOCK(spin);
17214+
17215+ magic = h_sb->s_magic;
17216+ spin_lock(&spin);
17217+ a = au_warn_loopback_array;
17218+ for (i = 0; i < au_warn_loopback_nelem && *a; i++)
17219+ if (a[i] == magic) {
17220+ spin_unlock(&spin);
17221+ return;
17222+ }
17223+
17224+ /* h_sb is new to us, print it */
17225+ if (i < au_warn_loopback_nelem) {
17226+ a[i] = magic;
17227+ goto pr;
17228+ }
17229+
17230+ /* expand the array */
17231+ new_nelem = au_warn_loopback_nelem + au_warn_loopback_step;
17232+ a = au_kzrealloc(au_warn_loopback_array,
17233+ au_warn_loopback_nelem * sizeof(unsigned long),
17234+ new_nelem * sizeof(unsigned long), GFP_ATOMIC);
17235+ if (a) {
17236+ au_warn_loopback_nelem = new_nelem;
17237+ au_warn_loopback_array = a;
17238+ a[i] = magic;
17239+ goto pr;
17240+ }
17241+
17242+ spin_unlock(&spin);
17243+ AuWarn1("realloc failed, ignored\n");
17244+ return;
17245+
17246+pr:
17247+ spin_unlock(&spin);
17248+ pr_warning("you may want to try another patch for loopback file "
17249+ "on %s(0x%lx) branch\n", au_sbtype(h_sb), magic);
17250+}
17251+
17252+int au_loopback_init(void)
17253+{
17254+ int err;
17255+ struct super_block *sb __maybe_unused;
17256+
17257+ AuDebugOn(sizeof(sb->s_magic) != sizeof(unsigned long));
17258+
17259+ err = 0;
17260+ au_warn_loopback_array = kcalloc(au_warn_loopback_step,
17261+ sizeof(unsigned long), GFP_NOFS);
17262+ if (unlikely(!au_warn_loopback_array))
17263+ err = -ENOMEM;
17264+
17265+ return err;
17266+}
17267+
17268+void au_loopback_fin(void)
17269+{
17270+ kfree(au_warn_loopback_array);
17271+}
7f207e10
AM
17272diff -urN /usr/share/empty/fs/aufs/loop.h linux/fs/aufs/loop.h
17273--- /usr/share/empty/fs/aufs/loop.h 1970-01-01 01:00:00.000000000 +0100
87a755f4
AM
17274+++ linux/fs/aufs/loop.h 2011-07-22 08:26:47.857636522 +0200
17275@@ -0,0 +1,50 @@
1facf9fc 17276+/*
027c5e7a 17277+ * Copyright (C) 2005-2011 Junjiro R. Okajima
1facf9fc 17278+ *
17279+ * This program, aufs is free software; you can redistribute it and/or modify
17280+ * it under the terms of the GNU General Public License as published by
17281+ * the Free Software Foundation; either version 2 of the License, or
17282+ * (at your option) any later version.
dece6358
AM
17283+ *
17284+ * This program is distributed in the hope that it will be useful,
17285+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
17286+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17287+ * GNU General Public License for more details.
17288+ *
17289+ * You should have received a copy of the GNU General Public License
17290+ * along with this program; if not, write to the Free Software
17291+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 17292+ */
17293+
17294+/*
17295+ * support for loopback mount as a branch
17296+ */
17297+
17298+#ifndef __AUFS_LOOP_H__
17299+#define __AUFS_LOOP_H__
17300+
17301+#ifdef __KERNEL__
17302+
dece6358
AM
17303+struct dentry;
17304+struct super_block;
1facf9fc 17305+
17306+#ifdef CONFIG_AUFS_BDEV_LOOP
17307+/* loop.c */
b752ccd1 17308+int au_test_loopback_overlap(struct super_block *sb, struct dentry *h_adding);
1facf9fc 17309+int au_test_loopback_kthread(void);
87a755f4
AM
17310+void au_warn_loopback(struct super_block *h_sb);
17311+
17312+int au_loopback_init(void);
17313+void au_loopback_fin(void);
1facf9fc 17314+#else
4a4d8108 17315+AuStubInt0(au_test_loopback_overlap, struct super_block *sb,
b752ccd1 17316+ struct dentry *h_adding)
4a4d8108 17317+AuStubInt0(au_test_loopback_kthread, void)
87a755f4
AM
17318+AuStubVoid(au_warn_loopback, struct super_block *h_sb)
17319+
17320+AuStubInt0(au_loopback_init, void)
17321+AuStubVoid(au_loopback_fin, void)
1facf9fc 17322+#endif /* BLK_DEV_LOOP */
17323+
17324+#endif /* __KERNEL__ */
17325+#endif /* __AUFS_LOOP_H__ */
7f207e10
AM
17326diff -urN /usr/share/empty/fs/aufs/magic.mk linux/fs/aufs/magic.mk
17327--- /usr/share/empty/fs/aufs/magic.mk 1970-01-01 01:00:00.000000000 +0100
87a755f4 17328+++ linux/fs/aufs/magic.mk 2011-03-17 10:46:59.000000000 +0100
4a4d8108 17329@@ -0,0 +1,54 @@
1facf9fc 17330+
17331+# defined in ${srctree}/fs/fuse/inode.c
17332+# tristate
17333+ifdef CONFIG_FUSE_FS
17334+ccflags-y += -DFUSE_SUPER_MAGIC=0x65735546
17335+endif
17336+
17337+# defined in ${srctree}/fs/ocfs2/ocfs2_fs.h
17338+# tristate
17339+ifdef CONFIG_OCFS2_FS
17340+ccflags-y += -DOCFS2_SUPER_MAGIC=0x7461636f
17341+endif
17342+
17343+# defined in ${srctree}/fs/ocfs2/dlm/userdlm.h
17344+# tristate
17345+ifdef CONFIG_OCFS2_FS_O2CB
17346+ccflags-y += -DDLMFS_MAGIC=0x76a9f425
17347+endif
17348+
1facf9fc 17349+# defined in ${srctree}/fs/cifs/cifsfs.c
17350+# tristate
17351+ifdef CONFIG_CIFS_FS
17352+ccflags-y += -DCIFS_MAGIC_NUMBER=0xFF534D42
17353+endif
17354+
17355+# defined in ${srctree}/fs/xfs/xfs_sb.h
17356+# tristate
17357+ifdef CONFIG_XFS_FS
17358+ccflags-y += -DXFS_SB_MAGIC=0x58465342
17359+endif
17360+
17361+# defined in ${srctree}/fs/configfs/mount.c
17362+# tristate
17363+ifdef CONFIG_CONFIGFS_FS
17364+ccflags-y += -DCONFIGFS_MAGIC=0x62656570
17365+endif
17366+
17367+# defined in ${srctree}/fs/9p/v9fs.h
17368+# tristate
17369+ifdef CONFIG_9P_FS
17370+ccflags-y += -DV9FS_MAGIC=0x01021997
17371+endif
17372+
17373+# defined in ${srctree}/fs/ubifs/ubifs.h
17374+# tristate
17375+ifdef CONFIG_UBIFS_FS
17376+ccflags-y += -DUBIFS_SUPER_MAGIC=0x24051905
17377+endif
4a4d8108
AM
17378+
17379+# defined in ${srctree}/fs/hfsplus/hfsplus_raw.h
17380+# tristate
17381+ifdef CONFIG_HFSPLUS_FS
17382+ccflags-y += -DHFSPLUS_SUPER_MAGIC=0x482b
17383+endif
7f207e10
AM
17384diff -urN /usr/share/empty/fs/aufs/Makefile linux/fs/aufs/Makefile
17385--- /usr/share/empty/fs/aufs/Makefile 1970-01-01 01:00:00.000000000 +0100
87a755f4 17386+++ linux/fs/aufs/Makefile 2011-03-17 10:46:59.000000000 +0100
7f207e10 17387@@ -0,0 +1,38 @@
4a4d8108
AM
17388+
17389+include ${src}/magic.mk
17390+ifeq (${CONFIG_AUFS_FS},m)
17391+include ${src}/conf.mk
17392+endif
17393+-include ${src}/priv_def.mk
17394+
17395+# cf. include/linux/kernel.h
17396+# enable pr_debug
17397+ccflags-y += -DDEBUG
7f207e10
AM
17398+# sparse doesn't allow spaces
17399+ccflags-y += -D'pr_fmt(fmt)=AUFS_NAME"\040%s:%d:%s[%d]:\040"fmt,__func__,__LINE__,current->comm,current->pid'
4a4d8108
AM
17400+
17401+obj-$(CONFIG_AUFS_FS) += aufs.o
17402+aufs-y := module.o sbinfo.o super.o branch.o xino.o sysaufs.o opts.o \
17403+ wkq.o vfsub.o dcsub.o \
e49829fe 17404+ cpup.o whout.o wbr_policy.o \
4a4d8108
AM
17405+ dinfo.o dentry.o \
17406+ dynop.o \
17407+ finfo.o file.o f_op.o \
17408+ dir.o vdir.o \
17409+ iinfo.o inode.o i_op.o i_op_add.o i_op_del.o i_op_ren.o \
17410+ ioctl.o
17411+
17412+# all are boolean
e49829fe 17413+aufs-$(CONFIG_PROC_FS) += procfs.o plink.o
4a4d8108
AM
17414+aufs-$(CONFIG_SYSFS) += sysfs.o
17415+aufs-$(CONFIG_DEBUG_FS) += dbgaufs.o
17416+aufs-$(CONFIG_AUFS_BDEV_LOOP) += loop.o
17417+aufs-$(CONFIG_AUFS_HNOTIFY) += hnotify.o
17418+aufs-$(CONFIG_AUFS_HFSNOTIFY) += hfsnotify.o
4a4d8108
AM
17419+aufs-$(CONFIG_AUFS_EXPORT) += export.o
17420+aufs-$(CONFIG_AUFS_POLL) += poll.o
17421+aufs-$(CONFIG_AUFS_RDU) += rdu.o
17422+aufs-$(CONFIG_AUFS_SP_IATTR) += f_op_sp.o
17423+aufs-$(CONFIG_AUFS_BR_HFSPLUS) += hfsplus.o
17424+aufs-$(CONFIG_AUFS_DEBUG) += debug.o
17425+aufs-$(CONFIG_AUFS_MAGIC_SYSRQ) += sysrq.o
7f207e10
AM
17426diff -urN /usr/share/empty/fs/aufs/module.c linux/fs/aufs/module.c
17427--- /usr/share/empty/fs/aufs/module.c 1970-01-01 01:00:00.000000000 +0100
87a755f4
AM
17428+++ linux/fs/aufs/module.c 2011-07-22 08:26:47.857636522 +0200
17429@@ -0,0 +1,189 @@
1facf9fc 17430+/*
027c5e7a 17431+ * Copyright (C) 2005-2011 Junjiro R. Okajima
1facf9fc 17432+ *
17433+ * This program, aufs is free software; you can redistribute it and/or modify
17434+ * it under the terms of the GNU General Public License as published by
17435+ * the Free Software Foundation; either version 2 of the License, or
17436+ * (at your option) any later version.
dece6358
AM
17437+ *
17438+ * This program is distributed in the hope that it will be useful,
17439+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
17440+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17441+ * GNU General Public License for more details.
17442+ *
17443+ * You should have received a copy of the GNU General Public License
17444+ * along with this program; if not, write to the Free Software
17445+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 17446+ */
17447+
17448+/*
17449+ * module global variables and operations
17450+ */
17451+
17452+#include <linux/module.h>
17453+#include <linux/seq_file.h>
17454+#include "aufs.h"
17455+
17456+void *au_kzrealloc(void *p, unsigned int nused, unsigned int new_sz, gfp_t gfp)
17457+{
17458+ if (new_sz <= nused)
17459+ return p;
17460+
17461+ p = krealloc(p, new_sz, gfp);
17462+ if (p)
17463+ memset(p + nused, 0, new_sz - nused);
17464+ return p;
17465+}
17466+
17467+/* ---------------------------------------------------------------------- */
17468+
17469+/*
17470+ * aufs caches
17471+ */
17472+struct kmem_cache *au_cachep[AuCache_Last];
17473+static int __init au_cache_init(void)
17474+{
4a4d8108 17475+ au_cachep[AuCache_DINFO] = AuCacheCtor(au_dinfo, au_di_init_once);
1facf9fc 17476+ if (au_cachep[AuCache_DINFO])
027c5e7a 17477+ /* SLAB_DESTROY_BY_RCU */
4a4d8108
AM
17478+ au_cachep[AuCache_ICNTNR] = AuCacheCtor(au_icntnr,
17479+ au_icntnr_init_once);
1facf9fc 17480+ if (au_cachep[AuCache_ICNTNR])
4a4d8108
AM
17481+ au_cachep[AuCache_FINFO] = AuCacheCtor(au_finfo,
17482+ au_fi_init_once);
1facf9fc 17483+ if (au_cachep[AuCache_FINFO])
17484+ au_cachep[AuCache_VDIR] = AuCache(au_vdir);
17485+ if (au_cachep[AuCache_VDIR])
17486+ au_cachep[AuCache_DEHSTR] = AuCache(au_vdir_dehstr);
17487+ if (au_cachep[AuCache_DEHSTR])
17488+ return 0;
17489+
17490+ return -ENOMEM;
17491+}
17492+
17493+static void au_cache_fin(void)
17494+{
17495+ int i;
4a4d8108
AM
17496+
17497+ /* including AuCache_HNOTIFY */
1facf9fc 17498+ for (i = 0; i < AuCache_Last; i++)
17499+ if (au_cachep[i]) {
17500+ kmem_cache_destroy(au_cachep[i]);
17501+ au_cachep[i] = NULL;
17502+ }
17503+}
17504+
17505+/* ---------------------------------------------------------------------- */
17506+
17507+int au_dir_roflags;
17508+
e49829fe
JR
17509+#ifdef CONFIG_AUFS_SBILIST
17510+struct au_splhead au_sbilist;
17511+#endif
17512+
1facf9fc 17513+/*
17514+ * functions for module interface.
17515+ */
17516+MODULE_LICENSE("GPL");
17517+/* MODULE_LICENSE("GPL v2"); */
dece6358 17518+MODULE_AUTHOR("Junjiro R. Okajima <aufs-users@lists.sourceforge.net>");
1facf9fc 17519+MODULE_DESCRIPTION(AUFS_NAME
17520+ " -- Advanced multi layered unification filesystem");
17521+MODULE_VERSION(AUFS_VERSION);
17522+
1facf9fc 17523+/* this module parameter has no meaning when SYSFS is disabled */
17524+int sysaufs_brs = 1;
17525+MODULE_PARM_DESC(brs, "use <sysfs>/fs/aufs/si_*/brN");
17526+module_param_named(brs, sysaufs_brs, int, S_IRUGO);
17527+
17528+/* ---------------------------------------------------------------------- */
17529+
17530+static char au_esc_chars[0x20 + 3]; /* 0x01-0x20, backslash, del, and NULL */
17531+
17532+int au_seq_path(struct seq_file *seq, struct path *path)
17533+{
17534+ return seq_path(seq, path, au_esc_chars);
17535+}
17536+
17537+/* ---------------------------------------------------------------------- */
17538+
17539+static int __init aufs_init(void)
17540+{
17541+ int err, i;
17542+ char *p;
17543+
17544+ p = au_esc_chars;
17545+ for (i = 1; i <= ' '; i++)
17546+ *p++ = i;
17547+ *p++ = '\\';
17548+ *p++ = '\x7f';
17549+ *p = 0;
17550+
17551+ au_dir_roflags = au_file_roflags(O_DIRECTORY | O_LARGEFILE);
17552+
e49829fe 17553+ au_sbilist_init();
1facf9fc 17554+ sysaufs_brs_init();
17555+ au_debug_init();
4a4d8108 17556+ au_dy_init();
1facf9fc 17557+ err = sysaufs_init();
17558+ if (unlikely(err))
17559+ goto out;
e49829fe 17560+ err = au_procfs_init();
4f0767ce 17561+ if (unlikely(err))
953406b4 17562+ goto out_sysaufs;
e49829fe
JR
17563+ err = au_wkq_init();
17564+ if (unlikely(err))
17565+ goto out_procfs;
87a755f4 17566+ err = au_loopback_init();
1facf9fc 17567+ if (unlikely(err))
17568+ goto out_wkq;
87a755f4
AM
17569+ err = au_hnotify_init();
17570+ if (unlikely(err))
17571+ goto out_loopback;
1facf9fc 17572+ err = au_sysrq_init();
17573+ if (unlikely(err))
17574+ goto out_hin;
17575+ err = au_cache_init();
17576+ if (unlikely(err))
17577+ goto out_sysrq;
17578+ err = register_filesystem(&aufs_fs_type);
17579+ if (unlikely(err))
17580+ goto out_cache;
4a4d8108
AM
17581+ /* since we define pr_fmt, call printk directly */
17582+ printk(KERN_INFO AUFS_NAME " " AUFS_VERSION "\n");
1facf9fc 17583+ goto out; /* success */
17584+
4f0767ce 17585+out_cache:
1facf9fc 17586+ au_cache_fin();
4f0767ce 17587+out_sysrq:
1facf9fc 17588+ au_sysrq_fin();
4f0767ce 17589+out_hin:
4a4d8108 17590+ au_hnotify_fin();
87a755f4
AM
17591+out_loopback:
17592+ au_loopback_fin();
4f0767ce 17593+out_wkq:
1facf9fc 17594+ au_wkq_fin();
e49829fe
JR
17595+out_procfs:
17596+ au_procfs_fin();
4f0767ce 17597+out_sysaufs:
1facf9fc 17598+ sysaufs_fin();
4a4d8108 17599+ au_dy_fin();
4f0767ce 17600+out:
1facf9fc 17601+ return err;
17602+}
17603+
17604+static void __exit aufs_exit(void)
17605+{
17606+ unregister_filesystem(&aufs_fs_type);
17607+ au_cache_fin();
17608+ au_sysrq_fin();
4a4d8108 17609+ au_hnotify_fin();
87a755f4 17610+ au_loopback_fin();
1facf9fc 17611+ au_wkq_fin();
e49829fe 17612+ au_procfs_fin();
1facf9fc 17613+ sysaufs_fin();
4a4d8108 17614+ au_dy_fin();
1facf9fc 17615+}
17616+
17617+module_init(aufs_init);
17618+module_exit(aufs_exit);
7f207e10
AM
17619diff -urN /usr/share/empty/fs/aufs/module.h linux/fs/aufs/module.h
17620--- /usr/share/empty/fs/aufs/module.h 1970-01-01 01:00:00.000000000 +0100
87a755f4 17621+++ linux/fs/aufs/module.h 2011-03-17 10:46:59.000000000 +0100
e49829fe 17622@@ -0,0 +1,91 @@
1facf9fc 17623+/*
027c5e7a 17624+ * Copyright (C) 2005-2011 Junjiro R. Okajima
1facf9fc 17625+ *
17626+ * This program, aufs is free software; you can redistribute it and/or modify
17627+ * it under the terms of the GNU General Public License as published by
17628+ * the Free Software Foundation; either version 2 of the License, or
17629+ * (at your option) any later version.
dece6358
AM
17630+ *
17631+ * This program is distributed in the hope that it will be useful,
17632+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
17633+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17634+ * GNU General Public License for more details.
17635+ *
17636+ * You should have received a copy of the GNU General Public License
17637+ * along with this program; if not, write to the Free Software
17638+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 17639+ */
17640+
17641+/*
17642+ * module initialization and module-global
17643+ */
17644+
17645+#ifndef __AUFS_MODULE_H__
17646+#define __AUFS_MODULE_H__
17647+
17648+#ifdef __KERNEL__
17649+
17650+#include <linux/slab.h>
17651+
dece6358
AM
17652+struct path;
17653+struct seq_file;
17654+
1facf9fc 17655+/* module parameters */
1facf9fc 17656+extern int sysaufs_brs;
17657+
17658+/* ---------------------------------------------------------------------- */
17659+
17660+extern int au_dir_roflags;
17661+
17662+void *au_kzrealloc(void *p, unsigned int nused, unsigned int new_sz, gfp_t gfp);
17663+int au_seq_path(struct seq_file *seq, struct path *path);
17664+
e49829fe
JR
17665+#ifdef CONFIG_PROC_FS
17666+/* procfs.c */
17667+int __init au_procfs_init(void);
17668+void au_procfs_fin(void);
17669+#else
17670+AuStubInt0(au_procfs_init, void);
17671+AuStubVoid(au_procfs_fin, void);
17672+#endif
17673+
4f0767ce
JR
17674+/* ---------------------------------------------------------------------- */
17675+
17676+/* kmem cache */
1facf9fc 17677+enum {
17678+ AuCache_DINFO,
17679+ AuCache_ICNTNR,
17680+ AuCache_FINFO,
17681+ AuCache_VDIR,
17682+ AuCache_DEHSTR,
4a4d8108
AM
17683+#ifdef CONFIG_AUFS_HNOTIFY
17684+ AuCache_HNOTIFY,
1facf9fc 17685+#endif
17686+ AuCache_Last
17687+};
17688+
4a4d8108
AM
17689+#define AuCacheFlags (SLAB_RECLAIM_ACCOUNT | SLAB_MEM_SPREAD)
17690+#define AuCache(type) KMEM_CACHE(type, AuCacheFlags)
17691+#define AuCacheCtor(type, ctor) \
17692+ kmem_cache_create(#type, sizeof(struct type), \
17693+ __alignof__(struct type), AuCacheFlags, ctor)
1facf9fc 17694+
17695+extern struct kmem_cache *au_cachep[];
17696+
17697+#define AuCacheFuncs(name, index) \
4a4d8108 17698+static inline struct au_##name *au_cache_alloc_##name(void) \
1facf9fc 17699+{ return kmem_cache_alloc(au_cachep[AuCache_##index], GFP_NOFS); } \
4a4d8108 17700+static inline void au_cache_free_##name(struct au_##name *p) \
1facf9fc 17701+{ kmem_cache_free(au_cachep[AuCache_##index], p); }
17702+
17703+AuCacheFuncs(dinfo, DINFO);
17704+AuCacheFuncs(icntnr, ICNTNR);
17705+AuCacheFuncs(finfo, FINFO);
17706+AuCacheFuncs(vdir, VDIR);
4a4d8108
AM
17707+AuCacheFuncs(vdir_dehstr, DEHSTR);
17708+#ifdef CONFIG_AUFS_HNOTIFY
17709+AuCacheFuncs(hnotify, HNOTIFY);
17710+#endif
1facf9fc 17711+
4a4d8108
AM
17712+#endif /* __KERNEL__ */
17713+#endif /* __AUFS_MODULE_H__ */
7f207e10
AM
17714diff -urN /usr/share/empty/fs/aufs/opts.c linux/fs/aufs/opts.c
17715--- /usr/share/empty/fs/aufs/opts.c 1970-01-01 01:00:00.000000000 +0100
87a755f4 17716+++ linux/fs/aufs/opts.c 2011-03-17 10:46:59.000000000 +0100
027c5e7a 17717@@ -0,0 +1,1595 @@
1facf9fc 17718+/*
027c5e7a 17719+ * Copyright (C) 2005-2011 Junjiro R. Okajima
1facf9fc 17720+ *
17721+ * This program, aufs is free software; you can redistribute it and/or modify
17722+ * it under the terms of the GNU General Public License as published by
17723+ * the Free Software Foundation; either version 2 of the License, or
17724+ * (at your option) any later version.
dece6358
AM
17725+ *
17726+ * This program is distributed in the hope that it will be useful,
17727+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
17728+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17729+ * GNU General Public License for more details.
17730+ *
17731+ * You should have received a copy of the GNU General Public License
17732+ * along with this program; if not, write to the Free Software
17733+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 17734+ */
17735+
17736+/*
17737+ * mount options/flags
17738+ */
17739+
dece6358 17740+#include <linux/file.h>
e49829fe 17741+#include <linux/jiffies.h>
dece6358 17742+#include <linux/namei.h>
1facf9fc 17743+#include <linux/types.h> /* a distribution requires */
17744+#include <linux/parser.h>
17745+#include "aufs.h"
17746+
17747+/* ---------------------------------------------------------------------- */
17748+
17749+enum {
17750+ Opt_br,
17751+ Opt_add, Opt_del, Opt_mod, Opt_reorder, Opt_append, Opt_prepend,
17752+ Opt_idel, Opt_imod, Opt_ireorder,
17753+ Opt_dirwh, Opt_rdcache, Opt_rdblk, Opt_rdhash, Opt_rendir,
dece6358 17754+ Opt_rdblk_def, Opt_rdhash_def,
1facf9fc 17755+ Opt_xino, Opt_zxino, Opt_noxino,
17756+ Opt_trunc_xino, Opt_trunc_xino_v, Opt_notrunc_xino,
17757+ Opt_trunc_xino_path, Opt_itrunc_xino,
17758+ Opt_trunc_xib, Opt_notrunc_xib,
dece6358 17759+ Opt_shwh, Opt_noshwh,
1facf9fc 17760+ Opt_plink, Opt_noplink, Opt_list_plink,
17761+ Opt_udba,
4a4d8108 17762+ Opt_dio, Opt_nodio,
1facf9fc 17763+ /* Opt_lock, Opt_unlock, */
17764+ Opt_cmd, Opt_cmd_args,
17765+ Opt_diropq_a, Opt_diropq_w,
17766+ Opt_warn_perm, Opt_nowarn_perm,
17767+ Opt_wbr_copyup, Opt_wbr_create,
17768+ Opt_refrof, Opt_norefrof,
17769+ Opt_verbose, Opt_noverbose,
17770+ Opt_sum, Opt_nosum, Opt_wsum,
17771+ Opt_tail, Opt_ignore, Opt_ignore_silent, Opt_err
17772+};
17773+
17774+static match_table_t options = {
17775+ {Opt_br, "br=%s"},
17776+ {Opt_br, "br:%s"},
17777+
17778+ {Opt_add, "add=%d:%s"},
17779+ {Opt_add, "add:%d:%s"},
17780+ {Opt_add, "ins=%d:%s"},
17781+ {Opt_add, "ins:%d:%s"},
17782+ {Opt_append, "append=%s"},
17783+ {Opt_append, "append:%s"},
17784+ {Opt_prepend, "prepend=%s"},
17785+ {Opt_prepend, "prepend:%s"},
17786+
17787+ {Opt_del, "del=%s"},
17788+ {Opt_del, "del:%s"},
17789+ /* {Opt_idel, "idel:%d"}, */
17790+ {Opt_mod, "mod=%s"},
17791+ {Opt_mod, "mod:%s"},
17792+ /* {Opt_imod, "imod:%d:%s"}, */
17793+
17794+ {Opt_dirwh, "dirwh=%d"},
17795+
17796+ {Opt_xino, "xino=%s"},
17797+ {Opt_noxino, "noxino"},
17798+ {Opt_trunc_xino, "trunc_xino"},
17799+ {Opt_trunc_xino_v, "trunc_xino_v=%d:%d"},
17800+ {Opt_notrunc_xino, "notrunc_xino"},
17801+ {Opt_trunc_xino_path, "trunc_xino=%s"},
17802+ {Opt_itrunc_xino, "itrunc_xino=%d"},
17803+ /* {Opt_zxino, "zxino=%s"}, */
17804+ {Opt_trunc_xib, "trunc_xib"},
17805+ {Opt_notrunc_xib, "notrunc_xib"},
17806+
e49829fe 17807+#ifdef CONFIG_PROC_FS
1facf9fc 17808+ {Opt_plink, "plink"},
e49829fe
JR
17809+#else
17810+ {Opt_ignore_silent, "plink"},
17811+#endif
17812+
1facf9fc 17813+ {Opt_noplink, "noplink"},
e49829fe 17814+
1facf9fc 17815+#ifdef CONFIG_AUFS_DEBUG
17816+ {Opt_list_plink, "list_plink"},
17817+#endif
17818+
17819+ {Opt_udba, "udba=%s"},
17820+
4a4d8108
AM
17821+ {Opt_dio, "dio"},
17822+ {Opt_nodio, "nodio"},
17823+
1facf9fc 17824+ {Opt_diropq_a, "diropq=always"},
17825+ {Opt_diropq_a, "diropq=a"},
17826+ {Opt_diropq_w, "diropq=whiteouted"},
17827+ {Opt_diropq_w, "diropq=w"},
17828+
17829+ {Opt_warn_perm, "warn_perm"},
17830+ {Opt_nowarn_perm, "nowarn_perm"},
17831+
17832+ /* keep them temporary */
17833+ {Opt_ignore_silent, "coo=%s"},
17834+ {Opt_ignore_silent, "nodlgt"},
17835+ {Opt_ignore_silent, "nodirperm1"},
1facf9fc 17836+ {Opt_ignore_silent, "clean_plink"},
17837+
dece6358
AM
17838+#ifdef CONFIG_AUFS_SHWH
17839+ {Opt_shwh, "shwh"},
17840+#endif
17841+ {Opt_noshwh, "noshwh"},
17842+
1facf9fc 17843+ {Opt_rendir, "rendir=%d"},
17844+
17845+ {Opt_refrof, "refrof"},
17846+ {Opt_norefrof, "norefrof"},
17847+
17848+ {Opt_verbose, "verbose"},
17849+ {Opt_verbose, "v"},
17850+ {Opt_noverbose, "noverbose"},
17851+ {Opt_noverbose, "quiet"},
17852+ {Opt_noverbose, "q"},
17853+ {Opt_noverbose, "silent"},
17854+
17855+ {Opt_sum, "sum"},
17856+ {Opt_nosum, "nosum"},
17857+ {Opt_wsum, "wsum"},
17858+
17859+ {Opt_rdcache, "rdcache=%d"},
17860+ {Opt_rdblk, "rdblk=%d"},
dece6358 17861+ {Opt_rdblk_def, "rdblk=def"},
1facf9fc 17862+ {Opt_rdhash, "rdhash=%d"},
dece6358 17863+ {Opt_rdhash_def, "rdhash=def"},
1facf9fc 17864+
17865+ {Opt_wbr_create, "create=%s"},
17866+ {Opt_wbr_create, "create_policy=%s"},
17867+ {Opt_wbr_copyup, "cpup=%s"},
17868+ {Opt_wbr_copyup, "copyup=%s"},
17869+ {Opt_wbr_copyup, "copyup_policy=%s"},
17870+
17871+ /* internal use for the scripts */
17872+ {Opt_ignore_silent, "si=%s"},
17873+
17874+ {Opt_br, "dirs=%s"},
17875+ {Opt_ignore, "debug=%d"},
17876+ {Opt_ignore, "delete=whiteout"},
17877+ {Opt_ignore, "delete=all"},
17878+ {Opt_ignore, "imap=%s"},
17879+
1308ab2a 17880+ /* temporary workaround, due to old mount(8)? */
17881+ {Opt_ignore_silent, "relatime"},
17882+
1facf9fc 17883+ {Opt_err, NULL}
17884+};
17885+
17886+/* ---------------------------------------------------------------------- */
17887+
17888+static const char *au_parser_pattern(int val, struct match_token *token)
17889+{
17890+ while (token->pattern) {
17891+ if (token->token == val)
17892+ return token->pattern;
17893+ token++;
17894+ }
17895+ BUG();
17896+ return "??";
17897+}
17898+
17899+/* ---------------------------------------------------------------------- */
17900+
17901+static match_table_t brperms = {
17902+ {AuBrPerm_RO, AUFS_BRPERM_RO},
17903+ {AuBrPerm_RR, AUFS_BRPERM_RR},
17904+ {AuBrPerm_RW, AUFS_BRPERM_RW},
17905+
17906+ {AuBrPerm_ROWH, AUFS_BRPERM_ROWH},
17907+ {AuBrPerm_RRWH, AUFS_BRPERM_RRWH},
17908+ {AuBrPerm_RWNoLinkWH, AUFS_BRPERM_RWNLWH},
17909+
17910+ {AuBrPerm_ROWH, "nfsro"},
17911+ {AuBrPerm_RO, NULL}
17912+};
17913+
4a4d8108 17914+static int noinline_for_stack br_perm_val(char *perm)
1facf9fc 17915+{
17916+ int val;
17917+ substring_t args[MAX_OPT_ARGS];
17918+
17919+ val = match_token(perm, brperms, args);
17920+ return val;
17921+}
17922+
17923+const char *au_optstr_br_perm(int brperm)
17924+{
17925+ return au_parser_pattern(brperm, (void *)brperms);
17926+}
17927+
17928+/* ---------------------------------------------------------------------- */
17929+
17930+static match_table_t udbalevel = {
17931+ {AuOpt_UDBA_REVAL, "reval"},
17932+ {AuOpt_UDBA_NONE, "none"},
4a4d8108
AM
17933+#ifdef CONFIG_AUFS_HNOTIFY
17934+ {AuOpt_UDBA_HNOTIFY, "notify"}, /* abstraction */
17935+#ifdef CONFIG_AUFS_HFSNOTIFY
17936+ {AuOpt_UDBA_HNOTIFY, "fsnotify"},
4a4d8108 17937+#endif
1facf9fc 17938+#endif
17939+ {-1, NULL}
17940+};
17941+
4a4d8108 17942+static int noinline_for_stack udba_val(char *str)
1facf9fc 17943+{
17944+ substring_t args[MAX_OPT_ARGS];
17945+
7f207e10 17946+ return match_token(str, udbalevel, args);
1facf9fc 17947+}
17948+
17949+const char *au_optstr_udba(int udba)
17950+{
17951+ return au_parser_pattern(udba, (void *)udbalevel);
17952+}
17953+
17954+/* ---------------------------------------------------------------------- */
17955+
17956+static match_table_t au_wbr_create_policy = {
17957+ {AuWbrCreate_TDP, "tdp"},
17958+ {AuWbrCreate_TDP, "top-down-parent"},
17959+ {AuWbrCreate_RR, "rr"},
17960+ {AuWbrCreate_RR, "round-robin"},
17961+ {AuWbrCreate_MFS, "mfs"},
17962+ {AuWbrCreate_MFS, "most-free-space"},
17963+ {AuWbrCreate_MFSV, "mfs:%d"},
17964+ {AuWbrCreate_MFSV, "most-free-space:%d"},
17965+
17966+ {AuWbrCreate_MFSRR, "mfsrr:%d"},
17967+ {AuWbrCreate_MFSRRV, "mfsrr:%d:%d"},
17968+ {AuWbrCreate_PMFS, "pmfs"},
17969+ {AuWbrCreate_PMFSV, "pmfs:%d"},
17970+
17971+ {-1, NULL}
17972+};
17973+
dece6358
AM
17974+/*
17975+ * cf. linux/lib/parser.c and cmdline.c
17976+ * gave up calling memparse() since it uses simple_strtoull() instead of
17977+ * strict_...().
17978+ */
4a4d8108
AM
17979+static int noinline_for_stack
17980+au_match_ull(substring_t *s, unsigned long long *result)
1facf9fc 17981+{
17982+ int err;
17983+ unsigned int len;
17984+ char a[32];
17985+
17986+ err = -ERANGE;
17987+ len = s->to - s->from;
17988+ if (len + 1 <= sizeof(a)) {
17989+ memcpy(a, s->from, len);
17990+ a[len] = '\0';
17991+ err = strict_strtoull(a, 0, result);
17992+ }
17993+ return err;
17994+}
17995+
17996+static int au_wbr_mfs_wmark(substring_t *arg, char *str,
17997+ struct au_opt_wbr_create *create)
17998+{
17999+ int err;
18000+ unsigned long long ull;
18001+
18002+ err = 0;
18003+ if (!au_match_ull(arg, &ull))
18004+ create->mfsrr_watermark = ull;
18005+ else {
4a4d8108 18006+ pr_err("bad integer in %s\n", str);
1facf9fc 18007+ err = -EINVAL;
18008+ }
18009+
18010+ return err;
18011+}
18012+
18013+static int au_wbr_mfs_sec(substring_t *arg, char *str,
18014+ struct au_opt_wbr_create *create)
18015+{
18016+ int n, err;
18017+
18018+ err = 0;
027c5e7a 18019+ if (!match_int(arg, &n) && 0 <= n && n <= AUFS_MFS_MAX_SEC)
1facf9fc 18020+ create->mfs_second = n;
18021+ else {
4a4d8108 18022+ pr_err("bad integer in %s\n", str);
1facf9fc 18023+ err = -EINVAL;
18024+ }
18025+
18026+ return err;
18027+}
18028+
4a4d8108
AM
18029+static int noinline_for_stack
18030+au_wbr_create_val(char *str, struct au_opt_wbr_create *create)
1facf9fc 18031+{
18032+ int err, e;
18033+ substring_t args[MAX_OPT_ARGS];
18034+
18035+ err = match_token(str, au_wbr_create_policy, args);
18036+ create->wbr_create = err;
18037+ switch (err) {
18038+ case AuWbrCreate_MFSRRV:
18039+ e = au_wbr_mfs_wmark(&args[0], str, create);
18040+ if (!e)
18041+ e = au_wbr_mfs_sec(&args[1], str, create);
18042+ if (unlikely(e))
18043+ err = e;
18044+ break;
18045+ case AuWbrCreate_MFSRR:
18046+ e = au_wbr_mfs_wmark(&args[0], str, create);
18047+ if (unlikely(e)) {
18048+ err = e;
18049+ break;
18050+ }
18051+ /*FALLTHROUGH*/
18052+ case AuWbrCreate_MFS:
18053+ case AuWbrCreate_PMFS:
027c5e7a 18054+ create->mfs_second = AUFS_MFS_DEF_SEC;
1facf9fc 18055+ break;
18056+ case AuWbrCreate_MFSV:
18057+ case AuWbrCreate_PMFSV:
18058+ e = au_wbr_mfs_sec(&args[0], str, create);
18059+ if (unlikely(e))
18060+ err = e;
18061+ break;
18062+ }
18063+
18064+ return err;
18065+}
18066+
18067+const char *au_optstr_wbr_create(int wbr_create)
18068+{
18069+ return au_parser_pattern(wbr_create, (void *)au_wbr_create_policy);
18070+}
18071+
18072+static match_table_t au_wbr_copyup_policy = {
18073+ {AuWbrCopyup_TDP, "tdp"},
18074+ {AuWbrCopyup_TDP, "top-down-parent"},
18075+ {AuWbrCopyup_BUP, "bup"},
18076+ {AuWbrCopyup_BUP, "bottom-up-parent"},
18077+ {AuWbrCopyup_BU, "bu"},
18078+ {AuWbrCopyup_BU, "bottom-up"},
18079+ {-1, NULL}
18080+};
18081+
4a4d8108 18082+static int noinline_for_stack au_wbr_copyup_val(char *str)
1facf9fc 18083+{
18084+ substring_t args[MAX_OPT_ARGS];
18085+
18086+ return match_token(str, au_wbr_copyup_policy, args);
18087+}
18088+
18089+const char *au_optstr_wbr_copyup(int wbr_copyup)
18090+{
18091+ return au_parser_pattern(wbr_copyup, (void *)au_wbr_copyup_policy);
18092+}
18093+
18094+/* ---------------------------------------------------------------------- */
18095+
18096+static const int lkup_dirflags = LOOKUP_FOLLOW | LOOKUP_DIRECTORY;
18097+
18098+static void dump_opts(struct au_opts *opts)
18099+{
18100+#ifdef CONFIG_AUFS_DEBUG
18101+ /* reduce stack space */
18102+ union {
18103+ struct au_opt_add *add;
18104+ struct au_opt_del *del;
18105+ struct au_opt_mod *mod;
18106+ struct au_opt_xino *xino;
18107+ struct au_opt_xino_itrunc *xino_itrunc;
18108+ struct au_opt_wbr_create *create;
18109+ } u;
18110+ struct au_opt *opt;
18111+
18112+ opt = opts->opt;
18113+ while (opt->type != Opt_tail) {
18114+ switch (opt->type) {
18115+ case Opt_add:
18116+ u.add = &opt->add;
18117+ AuDbg("add {b%d, %s, 0x%x, %p}\n",
18118+ u.add->bindex, u.add->pathname, u.add->perm,
18119+ u.add->path.dentry);
18120+ break;
18121+ case Opt_del:
18122+ case Opt_idel:
18123+ u.del = &opt->del;
18124+ AuDbg("del {%s, %p}\n",
18125+ u.del->pathname, u.del->h_path.dentry);
18126+ break;
18127+ case Opt_mod:
18128+ case Opt_imod:
18129+ u.mod = &opt->mod;
18130+ AuDbg("mod {%s, 0x%x, %p}\n",
18131+ u.mod->path, u.mod->perm, u.mod->h_root);
18132+ break;
18133+ case Opt_append:
18134+ u.add = &opt->add;
18135+ AuDbg("append {b%d, %s, 0x%x, %p}\n",
18136+ u.add->bindex, u.add->pathname, u.add->perm,
18137+ u.add->path.dentry);
18138+ break;
18139+ case Opt_prepend:
18140+ u.add = &opt->add;
18141+ AuDbg("prepend {b%d, %s, 0x%x, %p}\n",
18142+ u.add->bindex, u.add->pathname, u.add->perm,
18143+ u.add->path.dentry);
18144+ break;
18145+ case Opt_dirwh:
18146+ AuDbg("dirwh %d\n", opt->dirwh);
18147+ break;
18148+ case Opt_rdcache:
18149+ AuDbg("rdcache %d\n", opt->rdcache);
18150+ break;
18151+ case Opt_rdblk:
18152+ AuDbg("rdblk %u\n", opt->rdblk);
18153+ break;
dece6358
AM
18154+ case Opt_rdblk_def:
18155+ AuDbg("rdblk_def\n");
18156+ break;
1facf9fc 18157+ case Opt_rdhash:
18158+ AuDbg("rdhash %u\n", opt->rdhash);
18159+ break;
dece6358
AM
18160+ case Opt_rdhash_def:
18161+ AuDbg("rdhash_def\n");
18162+ break;
1facf9fc 18163+ case Opt_xino:
18164+ u.xino = &opt->xino;
18165+ AuDbg("xino {%s %.*s}\n",
18166+ u.xino->path,
18167+ AuDLNPair(u.xino->file->f_dentry));
18168+ break;
18169+ case Opt_trunc_xino:
18170+ AuLabel(trunc_xino);
18171+ break;
18172+ case Opt_notrunc_xino:
18173+ AuLabel(notrunc_xino);
18174+ break;
18175+ case Opt_trunc_xino_path:
18176+ case Opt_itrunc_xino:
18177+ u.xino_itrunc = &opt->xino_itrunc;
18178+ AuDbg("trunc_xino %d\n", u.xino_itrunc->bindex);
18179+ break;
18180+
18181+ case Opt_noxino:
18182+ AuLabel(noxino);
18183+ break;
18184+ case Opt_trunc_xib:
18185+ AuLabel(trunc_xib);
18186+ break;
18187+ case Opt_notrunc_xib:
18188+ AuLabel(notrunc_xib);
18189+ break;
dece6358
AM
18190+ case Opt_shwh:
18191+ AuLabel(shwh);
18192+ break;
18193+ case Opt_noshwh:
18194+ AuLabel(noshwh);
18195+ break;
1facf9fc 18196+ case Opt_plink:
18197+ AuLabel(plink);
18198+ break;
18199+ case Opt_noplink:
18200+ AuLabel(noplink);
18201+ break;
18202+ case Opt_list_plink:
18203+ AuLabel(list_plink);
18204+ break;
18205+ case Opt_udba:
18206+ AuDbg("udba %d, %s\n",
18207+ opt->udba, au_optstr_udba(opt->udba));
18208+ break;
4a4d8108
AM
18209+ case Opt_dio:
18210+ AuLabel(dio);
18211+ break;
18212+ case Opt_nodio:
18213+ AuLabel(nodio);
18214+ break;
1facf9fc 18215+ case Opt_diropq_a:
18216+ AuLabel(diropq_a);
18217+ break;
18218+ case Opt_diropq_w:
18219+ AuLabel(diropq_w);
18220+ break;
18221+ case Opt_warn_perm:
18222+ AuLabel(warn_perm);
18223+ break;
18224+ case Opt_nowarn_perm:
18225+ AuLabel(nowarn_perm);
18226+ break;
18227+ case Opt_refrof:
18228+ AuLabel(refrof);
18229+ break;
18230+ case Opt_norefrof:
18231+ AuLabel(norefrof);
18232+ break;
18233+ case Opt_verbose:
18234+ AuLabel(verbose);
18235+ break;
18236+ case Opt_noverbose:
18237+ AuLabel(noverbose);
18238+ break;
18239+ case Opt_sum:
18240+ AuLabel(sum);
18241+ break;
18242+ case Opt_nosum:
18243+ AuLabel(nosum);
18244+ break;
18245+ case Opt_wsum:
18246+ AuLabel(wsum);
18247+ break;
18248+ case Opt_wbr_create:
18249+ u.create = &opt->wbr_create;
18250+ AuDbg("create %d, %s\n", u.create->wbr_create,
18251+ au_optstr_wbr_create(u.create->wbr_create));
18252+ switch (u.create->wbr_create) {
18253+ case AuWbrCreate_MFSV:
18254+ case AuWbrCreate_PMFSV:
18255+ AuDbg("%d sec\n", u.create->mfs_second);
18256+ break;
18257+ case AuWbrCreate_MFSRR:
18258+ AuDbg("%llu watermark\n",
18259+ u.create->mfsrr_watermark);
18260+ break;
18261+ case AuWbrCreate_MFSRRV:
18262+ AuDbg("%llu watermark, %d sec\n",
18263+ u.create->mfsrr_watermark,
18264+ u.create->mfs_second);
18265+ break;
18266+ }
18267+ break;
18268+ case Opt_wbr_copyup:
18269+ AuDbg("copyup %d, %s\n", opt->wbr_copyup,
18270+ au_optstr_wbr_copyup(opt->wbr_copyup));
18271+ break;
18272+ default:
18273+ BUG();
18274+ }
18275+ opt++;
18276+ }
18277+#endif
18278+}
18279+
18280+void au_opts_free(struct au_opts *opts)
18281+{
18282+ struct au_opt *opt;
18283+
18284+ opt = opts->opt;
18285+ while (opt->type != Opt_tail) {
18286+ switch (opt->type) {
18287+ case Opt_add:
18288+ case Opt_append:
18289+ case Opt_prepend:
18290+ path_put(&opt->add.path);
18291+ break;
18292+ case Opt_del:
18293+ case Opt_idel:
18294+ path_put(&opt->del.h_path);
18295+ break;
18296+ case Opt_mod:
18297+ case Opt_imod:
18298+ dput(opt->mod.h_root);
18299+ break;
18300+ case Opt_xino:
18301+ fput(opt->xino.file);
18302+ break;
18303+ }
18304+ opt++;
18305+ }
18306+}
18307+
18308+static int opt_add(struct au_opt *opt, char *opt_str, unsigned long sb_flags,
18309+ aufs_bindex_t bindex)
18310+{
18311+ int err;
18312+ struct au_opt_add *add = &opt->add;
18313+ char *p;
18314+
18315+ add->bindex = bindex;
18316+ add->perm = AuBrPerm_Last;
18317+ add->pathname = opt_str;
18318+ p = strchr(opt_str, '=');
18319+ if (p) {
18320+ *p++ = 0;
18321+ if (*p)
18322+ add->perm = br_perm_val(p);
18323+ }
18324+
18325+ err = vfsub_kern_path(add->pathname, lkup_dirflags, &add->path);
18326+ if (!err) {
18327+ if (!p) {
18328+ add->perm = AuBrPerm_RO;
18329+ if (au_test_fs_rr(add->path.dentry->d_sb))
18330+ add->perm = AuBrPerm_RR;
18331+ else if (!bindex && !(sb_flags & MS_RDONLY))
18332+ add->perm = AuBrPerm_RW;
18333+ }
18334+ opt->type = Opt_add;
18335+ goto out;
18336+ }
4a4d8108 18337+ pr_err("lookup failed %s (%d)\n", add->pathname, err);
1facf9fc 18338+ err = -EINVAL;
18339+
4f0767ce 18340+out:
1facf9fc 18341+ return err;
18342+}
18343+
18344+static int au_opts_parse_del(struct au_opt_del *del, substring_t args[])
18345+{
18346+ int err;
18347+
18348+ del->pathname = args[0].from;
18349+ AuDbg("del path %s\n", del->pathname);
18350+
18351+ err = vfsub_kern_path(del->pathname, lkup_dirflags, &del->h_path);
18352+ if (unlikely(err))
4a4d8108 18353+ pr_err("lookup failed %s (%d)\n", del->pathname, err);
1facf9fc 18354+
18355+ return err;
18356+}
18357+
18358+#if 0 /* reserved for future use */
18359+static int au_opts_parse_idel(struct super_block *sb, aufs_bindex_t bindex,
18360+ struct au_opt_del *del, substring_t args[])
18361+{
18362+ int err;
18363+ struct dentry *root;
18364+
18365+ err = -EINVAL;
18366+ root = sb->s_root;
18367+ aufs_read_lock(root, AuLock_FLUSH);
18368+ if (bindex < 0 || au_sbend(sb) < bindex) {
4a4d8108 18369+ pr_err("out of bounds, %d\n", bindex);
1facf9fc 18370+ goto out;
18371+ }
18372+
18373+ err = 0;
18374+ del->h_path.dentry = dget(au_h_dptr(root, bindex));
18375+ del->h_path.mnt = mntget(au_sbr_mnt(sb, bindex));
18376+
4f0767ce 18377+out:
1facf9fc 18378+ aufs_read_unlock(root, !AuLock_IR);
18379+ return err;
18380+}
18381+#endif
18382+
4a4d8108
AM
18383+static int noinline_for_stack
18384+au_opts_parse_mod(struct au_opt_mod *mod, substring_t args[])
1facf9fc 18385+{
18386+ int err;
18387+ struct path path;
18388+ char *p;
18389+
18390+ err = -EINVAL;
18391+ mod->path = args[0].from;
18392+ p = strchr(mod->path, '=');
18393+ if (unlikely(!p)) {
4a4d8108 18394+ pr_err("no permssion %s\n", args[0].from);
1facf9fc 18395+ goto out;
18396+ }
18397+
18398+ *p++ = 0;
18399+ err = vfsub_kern_path(mod->path, lkup_dirflags, &path);
18400+ if (unlikely(err)) {
4a4d8108 18401+ pr_err("lookup failed %s (%d)\n", mod->path, err);
1facf9fc 18402+ goto out;
18403+ }
18404+
18405+ mod->perm = br_perm_val(p);
18406+ AuDbg("mod path %s, perm 0x%x, %s\n", mod->path, mod->perm, p);
18407+ mod->h_root = dget(path.dentry);
18408+ path_put(&path);
18409+
4f0767ce 18410+out:
1facf9fc 18411+ return err;
18412+}
18413+
18414+#if 0 /* reserved for future use */
18415+static int au_opts_parse_imod(struct super_block *sb, aufs_bindex_t bindex,
18416+ struct au_opt_mod *mod, substring_t args[])
18417+{
18418+ int err;
18419+ struct dentry *root;
18420+
18421+ err = -EINVAL;
18422+ root = sb->s_root;
18423+ aufs_read_lock(root, AuLock_FLUSH);
18424+ if (bindex < 0 || au_sbend(sb) < bindex) {
4a4d8108 18425+ pr_err("out of bounds, %d\n", bindex);
1facf9fc 18426+ goto out;
18427+ }
18428+
18429+ err = 0;
18430+ mod->perm = br_perm_val(args[1].from);
18431+ AuDbg("mod path %s, perm 0x%x, %s\n",
18432+ mod->path, mod->perm, args[1].from);
18433+ mod->h_root = dget(au_h_dptr(root, bindex));
18434+
4f0767ce 18435+out:
1facf9fc 18436+ aufs_read_unlock(root, !AuLock_IR);
18437+ return err;
18438+}
18439+#endif
18440+
18441+static int au_opts_parse_xino(struct super_block *sb, struct au_opt_xino *xino,
18442+ substring_t args[])
18443+{
18444+ int err;
18445+ struct file *file;
18446+
18447+ file = au_xino_create(sb, args[0].from, /*silent*/0);
18448+ err = PTR_ERR(file);
18449+ if (IS_ERR(file))
18450+ goto out;
18451+
18452+ err = -EINVAL;
18453+ if (unlikely(file->f_dentry->d_sb == sb)) {
18454+ fput(file);
4a4d8108 18455+ pr_err("%s must be outside\n", args[0].from);
1facf9fc 18456+ goto out;
18457+ }
18458+
18459+ err = 0;
18460+ xino->file = file;
18461+ xino->path = args[0].from;
18462+
4f0767ce 18463+out:
1facf9fc 18464+ return err;
18465+}
18466+
4a4d8108
AM
18467+static int noinline_for_stack
18468+au_opts_parse_xino_itrunc_path(struct super_block *sb,
18469+ struct au_opt_xino_itrunc *xino_itrunc,
18470+ substring_t args[])
1facf9fc 18471+{
18472+ int err;
18473+ aufs_bindex_t bend, bindex;
18474+ struct path path;
18475+ struct dentry *root;
18476+
18477+ err = vfsub_kern_path(args[0].from, lkup_dirflags, &path);
18478+ if (unlikely(err)) {
4a4d8108 18479+ pr_err("lookup failed %s (%d)\n", args[0].from, err);
1facf9fc 18480+ goto out;
18481+ }
18482+
18483+ xino_itrunc->bindex = -1;
18484+ root = sb->s_root;
18485+ aufs_read_lock(root, AuLock_FLUSH);
18486+ bend = au_sbend(sb);
18487+ for (bindex = 0; bindex <= bend; bindex++) {
18488+ if (au_h_dptr(root, bindex) == path.dentry) {
18489+ xino_itrunc->bindex = bindex;
18490+ break;
18491+ }
18492+ }
18493+ aufs_read_unlock(root, !AuLock_IR);
18494+ path_put(&path);
18495+
18496+ if (unlikely(xino_itrunc->bindex < 0)) {
4a4d8108 18497+ pr_err("no such branch %s\n", args[0].from);
1facf9fc 18498+ err = -EINVAL;
18499+ }
18500+
4f0767ce 18501+out:
1facf9fc 18502+ return err;
18503+}
18504+
18505+/* called without aufs lock */
18506+int au_opts_parse(struct super_block *sb, char *str, struct au_opts *opts)
18507+{
18508+ int err, n, token;
18509+ aufs_bindex_t bindex;
18510+ unsigned char skipped;
18511+ struct dentry *root;
18512+ struct au_opt *opt, *opt_tail;
18513+ char *opt_str;
18514+ /* reduce the stack space */
18515+ union {
18516+ struct au_opt_xino_itrunc *xino_itrunc;
18517+ struct au_opt_wbr_create *create;
18518+ } u;
18519+ struct {
18520+ substring_t args[MAX_OPT_ARGS];
18521+ } *a;
18522+
18523+ err = -ENOMEM;
18524+ a = kmalloc(sizeof(*a), GFP_NOFS);
18525+ if (unlikely(!a))
18526+ goto out;
18527+
18528+ root = sb->s_root;
18529+ err = 0;
18530+ bindex = 0;
18531+ opt = opts->opt;
18532+ opt_tail = opt + opts->max_opt - 1;
18533+ opt->type = Opt_tail;
18534+ while (!err && (opt_str = strsep(&str, ",")) && *opt_str) {
18535+ err = -EINVAL;
18536+ skipped = 0;
18537+ token = match_token(opt_str, options, a->args);
18538+ switch (token) {
18539+ case Opt_br:
18540+ err = 0;
18541+ while (!err && (opt_str = strsep(&a->args[0].from, ":"))
18542+ && *opt_str) {
18543+ err = opt_add(opt, opt_str, opts->sb_flags,
18544+ bindex++);
18545+ if (unlikely(!err && ++opt > opt_tail)) {
18546+ err = -E2BIG;
18547+ break;
18548+ }
18549+ opt->type = Opt_tail;
18550+ skipped = 1;
18551+ }
18552+ break;
18553+ case Opt_add:
18554+ if (unlikely(match_int(&a->args[0], &n))) {
4a4d8108 18555+ pr_err("bad integer in %s\n", opt_str);
1facf9fc 18556+ break;
18557+ }
18558+ bindex = n;
18559+ err = opt_add(opt, a->args[1].from, opts->sb_flags,
18560+ bindex);
18561+ if (!err)
18562+ opt->type = token;
18563+ break;
18564+ case Opt_append:
18565+ err = opt_add(opt, a->args[0].from, opts->sb_flags,
18566+ /*dummy bindex*/1);
18567+ if (!err)
18568+ opt->type = token;
18569+ break;
18570+ case Opt_prepend:
18571+ err = opt_add(opt, a->args[0].from, opts->sb_flags,
18572+ /*bindex*/0);
18573+ if (!err)
18574+ opt->type = token;
18575+ break;
18576+ case Opt_del:
18577+ err = au_opts_parse_del(&opt->del, a->args);
18578+ if (!err)
18579+ opt->type = token;
18580+ break;
18581+#if 0 /* reserved for future use */
18582+ case Opt_idel:
18583+ del->pathname = "(indexed)";
18584+ if (unlikely(match_int(&args[0], &n))) {
4a4d8108 18585+ pr_err("bad integer in %s\n", opt_str);
1facf9fc 18586+ break;
18587+ }
18588+ err = au_opts_parse_idel(sb, n, &opt->del, a->args);
18589+ if (!err)
18590+ opt->type = token;
18591+ break;
18592+#endif
18593+ case Opt_mod:
18594+ err = au_opts_parse_mod(&opt->mod, a->args);
18595+ if (!err)
18596+ opt->type = token;
18597+ break;
18598+#ifdef IMOD /* reserved for future use */
18599+ case Opt_imod:
18600+ u.mod->path = "(indexed)";
18601+ if (unlikely(match_int(&a->args[0], &n))) {
4a4d8108 18602+ pr_err("bad integer in %s\n", opt_str);
1facf9fc 18603+ break;
18604+ }
18605+ err = au_opts_parse_imod(sb, n, &opt->mod, a->args);
18606+ if (!err)
18607+ opt->type = token;
18608+ break;
18609+#endif
18610+ case Opt_xino:
18611+ err = au_opts_parse_xino(sb, &opt->xino, a->args);
18612+ if (!err)
18613+ opt->type = token;
18614+ break;
18615+
18616+ case Opt_trunc_xino_path:
18617+ err = au_opts_parse_xino_itrunc_path
18618+ (sb, &opt->xino_itrunc, a->args);
18619+ if (!err)
18620+ opt->type = token;
18621+ break;
18622+
18623+ case Opt_itrunc_xino:
18624+ u.xino_itrunc = &opt->xino_itrunc;
18625+ if (unlikely(match_int(&a->args[0], &n))) {
4a4d8108 18626+ pr_err("bad integer in %s\n", opt_str);
1facf9fc 18627+ break;
18628+ }
18629+ u.xino_itrunc->bindex = n;
18630+ aufs_read_lock(root, AuLock_FLUSH);
18631+ if (n < 0 || au_sbend(sb) < n) {
4a4d8108 18632+ pr_err("out of bounds, %d\n", n);
1facf9fc 18633+ aufs_read_unlock(root, !AuLock_IR);
18634+ break;
18635+ }
18636+ aufs_read_unlock(root, !AuLock_IR);
18637+ err = 0;
18638+ opt->type = token;
18639+ break;
18640+
18641+ case Opt_dirwh:
18642+ if (unlikely(match_int(&a->args[0], &opt->dirwh)))
18643+ break;
18644+ err = 0;
18645+ opt->type = token;
18646+ break;
18647+
18648+ case Opt_rdcache:
027c5e7a
AM
18649+ if (unlikely(match_int(&a->args[0], &n))) {
18650+ pr_err("bad integer in %s\n", opt_str);
1facf9fc 18651+ break;
027c5e7a
AM
18652+ }
18653+ if (unlikely(n > AUFS_RDCACHE_MAX)) {
18654+ pr_err("rdcache must be smaller than %d\n",
18655+ AUFS_RDCACHE_MAX);
18656+ break;
18657+ }
18658+ opt->rdcache = n;
1facf9fc 18659+ err = 0;
18660+ opt->type = token;
18661+ break;
18662+ case Opt_rdblk:
18663+ if (unlikely(match_int(&a->args[0], &n)
1308ab2a 18664+ || n < 0
1facf9fc 18665+ || n > KMALLOC_MAX_SIZE)) {
4a4d8108 18666+ pr_err("bad integer in %s\n", opt_str);
1facf9fc 18667+ break;
18668+ }
1308ab2a 18669+ if (unlikely(n && n < NAME_MAX)) {
4a4d8108
AM
18670+ pr_err("rdblk must be larger than %d\n",
18671+ NAME_MAX);
1facf9fc 18672+ break;
18673+ }
18674+ opt->rdblk = n;
18675+ err = 0;
18676+ opt->type = token;
18677+ break;
18678+ case Opt_rdhash:
18679+ if (unlikely(match_int(&a->args[0], &n)
1308ab2a 18680+ || n < 0
1facf9fc 18681+ || n * sizeof(struct hlist_head)
18682+ > KMALLOC_MAX_SIZE)) {
4a4d8108 18683+ pr_err("bad integer in %s\n", opt_str);
1facf9fc 18684+ break;
18685+ }
18686+ opt->rdhash = n;
18687+ err = 0;
18688+ opt->type = token;
18689+ break;
18690+
18691+ case Opt_trunc_xino:
18692+ case Opt_notrunc_xino:
18693+ case Opt_noxino:
18694+ case Opt_trunc_xib:
18695+ case Opt_notrunc_xib:
dece6358
AM
18696+ case Opt_shwh:
18697+ case Opt_noshwh:
1facf9fc 18698+ case Opt_plink:
18699+ case Opt_noplink:
18700+ case Opt_list_plink:
4a4d8108
AM
18701+ case Opt_dio:
18702+ case Opt_nodio:
1facf9fc 18703+ case Opt_diropq_a:
18704+ case Opt_diropq_w:
18705+ case Opt_warn_perm:
18706+ case Opt_nowarn_perm:
18707+ case Opt_refrof:
18708+ case Opt_norefrof:
18709+ case Opt_verbose:
18710+ case Opt_noverbose:
18711+ case Opt_sum:
18712+ case Opt_nosum:
18713+ case Opt_wsum:
dece6358
AM
18714+ case Opt_rdblk_def:
18715+ case Opt_rdhash_def:
1facf9fc 18716+ err = 0;
18717+ opt->type = token;
18718+ break;
18719+
18720+ case Opt_udba:
18721+ opt->udba = udba_val(a->args[0].from);
18722+ if (opt->udba >= 0) {
18723+ err = 0;
18724+ opt->type = token;
18725+ } else
4a4d8108 18726+ pr_err("wrong value, %s\n", opt_str);
1facf9fc 18727+ break;
18728+
18729+ case Opt_wbr_create:
18730+ u.create = &opt->wbr_create;
18731+ u.create->wbr_create
18732+ = au_wbr_create_val(a->args[0].from, u.create);
18733+ if (u.create->wbr_create >= 0) {
18734+ err = 0;
18735+ opt->type = token;
18736+ } else
4a4d8108 18737+ pr_err("wrong value, %s\n", opt_str);
1facf9fc 18738+ break;
18739+ case Opt_wbr_copyup:
18740+ opt->wbr_copyup = au_wbr_copyup_val(a->args[0].from);
18741+ if (opt->wbr_copyup >= 0) {
18742+ err = 0;
18743+ opt->type = token;
18744+ } else
4a4d8108 18745+ pr_err("wrong value, %s\n", opt_str);
1facf9fc 18746+ break;
18747+
18748+ case Opt_ignore:
4a4d8108 18749+ pr_warning("ignored %s\n", opt_str);
1facf9fc 18750+ /*FALLTHROUGH*/
18751+ case Opt_ignore_silent:
18752+ skipped = 1;
18753+ err = 0;
18754+ break;
18755+ case Opt_err:
4a4d8108 18756+ pr_err("unknown option %s\n", opt_str);
1facf9fc 18757+ break;
18758+ }
18759+
18760+ if (!err && !skipped) {
18761+ if (unlikely(++opt > opt_tail)) {
18762+ err = -E2BIG;
18763+ opt--;
18764+ opt->type = Opt_tail;
18765+ break;
18766+ }
18767+ opt->type = Opt_tail;
18768+ }
18769+ }
18770+
18771+ kfree(a);
18772+ dump_opts(opts);
18773+ if (unlikely(err))
18774+ au_opts_free(opts);
18775+
4f0767ce 18776+out:
1facf9fc 18777+ return err;
18778+}
18779+
18780+static int au_opt_wbr_create(struct super_block *sb,
18781+ struct au_opt_wbr_create *create)
18782+{
18783+ int err;
18784+ struct au_sbinfo *sbinfo;
18785+
dece6358
AM
18786+ SiMustWriteLock(sb);
18787+
1facf9fc 18788+ err = 1; /* handled */
18789+ sbinfo = au_sbi(sb);
18790+ if (sbinfo->si_wbr_create_ops->fin) {
18791+ err = sbinfo->si_wbr_create_ops->fin(sb);
18792+ if (!err)
18793+ err = 1;
18794+ }
18795+
18796+ sbinfo->si_wbr_create = create->wbr_create;
18797+ sbinfo->si_wbr_create_ops = au_wbr_create_ops + create->wbr_create;
18798+ switch (create->wbr_create) {
18799+ case AuWbrCreate_MFSRRV:
18800+ case AuWbrCreate_MFSRR:
18801+ sbinfo->si_wbr_mfs.mfsrr_watermark = create->mfsrr_watermark;
18802+ /*FALLTHROUGH*/
18803+ case AuWbrCreate_MFS:
18804+ case AuWbrCreate_MFSV:
18805+ case AuWbrCreate_PMFS:
18806+ case AuWbrCreate_PMFSV:
e49829fe
JR
18807+ sbinfo->si_wbr_mfs.mfs_expire
18808+ = msecs_to_jiffies(create->mfs_second * MSEC_PER_SEC);
1facf9fc 18809+ break;
18810+ }
18811+
18812+ if (sbinfo->si_wbr_create_ops->init)
18813+ sbinfo->si_wbr_create_ops->init(sb); /* ignore */
18814+
18815+ return err;
18816+}
18817+
18818+/*
18819+ * returns,
18820+ * plus: processed without an error
18821+ * zero: unprocessed
18822+ */
18823+static int au_opt_simple(struct super_block *sb, struct au_opt *opt,
18824+ struct au_opts *opts)
18825+{
18826+ int err;
18827+ struct au_sbinfo *sbinfo;
18828+
dece6358
AM
18829+ SiMustWriteLock(sb);
18830+
1facf9fc 18831+ err = 1; /* handled */
18832+ sbinfo = au_sbi(sb);
18833+ switch (opt->type) {
18834+ case Opt_udba:
18835+ sbinfo->si_mntflags &= ~AuOptMask_UDBA;
18836+ sbinfo->si_mntflags |= opt->udba;
18837+ opts->given_udba |= opt->udba;
18838+ break;
18839+
18840+ case Opt_plink:
18841+ au_opt_set(sbinfo->si_mntflags, PLINK);
18842+ break;
18843+ case Opt_noplink:
18844+ if (au_opt_test(sbinfo->si_mntflags, PLINK))
e49829fe 18845+ au_plink_put(sb, /*verbose*/1);
1facf9fc 18846+ au_opt_clr(sbinfo->si_mntflags, PLINK);
18847+ break;
18848+ case Opt_list_plink:
18849+ if (au_opt_test(sbinfo->si_mntflags, PLINK))
18850+ au_plink_list(sb);
18851+ break;
18852+
4a4d8108
AM
18853+ case Opt_dio:
18854+ au_opt_set(sbinfo->si_mntflags, DIO);
18855+ au_fset_opts(opts->flags, REFRESH_DYAOP);
18856+ break;
18857+ case Opt_nodio:
18858+ au_opt_clr(sbinfo->si_mntflags, DIO);
18859+ au_fset_opts(opts->flags, REFRESH_DYAOP);
18860+ break;
18861+
1facf9fc 18862+ case Opt_diropq_a:
18863+ au_opt_set(sbinfo->si_mntflags, ALWAYS_DIROPQ);
18864+ break;
18865+ case Opt_diropq_w:
18866+ au_opt_clr(sbinfo->si_mntflags, ALWAYS_DIROPQ);
18867+ break;
18868+
18869+ case Opt_warn_perm:
18870+ au_opt_set(sbinfo->si_mntflags, WARN_PERM);
18871+ break;
18872+ case Opt_nowarn_perm:
18873+ au_opt_clr(sbinfo->si_mntflags, WARN_PERM);
18874+ break;
18875+
18876+ case Opt_refrof:
18877+ au_opt_set(sbinfo->si_mntflags, REFROF);
18878+ break;
18879+ case Opt_norefrof:
18880+ au_opt_clr(sbinfo->si_mntflags, REFROF);
18881+ break;
18882+
18883+ case Opt_verbose:
18884+ au_opt_set(sbinfo->si_mntflags, VERBOSE);
18885+ break;
18886+ case Opt_noverbose:
18887+ au_opt_clr(sbinfo->si_mntflags, VERBOSE);
18888+ break;
18889+
18890+ case Opt_sum:
18891+ au_opt_set(sbinfo->si_mntflags, SUM);
18892+ break;
18893+ case Opt_wsum:
18894+ au_opt_clr(sbinfo->si_mntflags, SUM);
18895+ au_opt_set(sbinfo->si_mntflags, SUM_W);
18896+ case Opt_nosum:
18897+ au_opt_clr(sbinfo->si_mntflags, SUM);
18898+ au_opt_clr(sbinfo->si_mntflags, SUM_W);
18899+ break;
18900+
18901+ case Opt_wbr_create:
18902+ err = au_opt_wbr_create(sb, &opt->wbr_create);
18903+ break;
18904+ case Opt_wbr_copyup:
18905+ sbinfo->si_wbr_copyup = opt->wbr_copyup;
18906+ sbinfo->si_wbr_copyup_ops = au_wbr_copyup_ops + opt->wbr_copyup;
18907+ break;
18908+
18909+ case Opt_dirwh:
18910+ sbinfo->si_dirwh = opt->dirwh;
18911+ break;
18912+
18913+ case Opt_rdcache:
e49829fe
JR
18914+ sbinfo->si_rdcache
18915+ = msecs_to_jiffies(opt->rdcache * MSEC_PER_SEC);
1facf9fc 18916+ break;
18917+ case Opt_rdblk:
18918+ sbinfo->si_rdblk = opt->rdblk;
18919+ break;
dece6358
AM
18920+ case Opt_rdblk_def:
18921+ sbinfo->si_rdblk = AUFS_RDBLK_DEF;
18922+ break;
1facf9fc 18923+ case Opt_rdhash:
18924+ sbinfo->si_rdhash = opt->rdhash;
18925+ break;
dece6358
AM
18926+ case Opt_rdhash_def:
18927+ sbinfo->si_rdhash = AUFS_RDHASH_DEF;
18928+ break;
18929+
18930+ case Opt_shwh:
18931+ au_opt_set(sbinfo->si_mntflags, SHWH);
18932+ break;
18933+ case Opt_noshwh:
18934+ au_opt_clr(sbinfo->si_mntflags, SHWH);
18935+ break;
1facf9fc 18936+
18937+ case Opt_trunc_xino:
18938+ au_opt_set(sbinfo->si_mntflags, TRUNC_XINO);
18939+ break;
18940+ case Opt_notrunc_xino:
18941+ au_opt_clr(sbinfo->si_mntflags, TRUNC_XINO);
18942+ break;
18943+
18944+ case Opt_trunc_xino_path:
18945+ case Opt_itrunc_xino:
18946+ err = au_xino_trunc(sb, opt->xino_itrunc.bindex);
18947+ if (!err)
18948+ err = 1;
18949+ break;
18950+
18951+ case Opt_trunc_xib:
18952+ au_fset_opts(opts->flags, TRUNC_XIB);
18953+ break;
18954+ case Opt_notrunc_xib:
18955+ au_fclr_opts(opts->flags, TRUNC_XIB);
18956+ break;
18957+
18958+ default:
18959+ err = 0;
18960+ break;
18961+ }
18962+
18963+ return err;
18964+}
18965+
18966+/*
18967+ * returns tri-state.
18968+ * plus: processed without an error
18969+ * zero: unprocessed
18970+ * minus: error
18971+ */
18972+static int au_opt_br(struct super_block *sb, struct au_opt *opt,
18973+ struct au_opts *opts)
18974+{
18975+ int err, do_refresh;
18976+
18977+ err = 0;
18978+ switch (opt->type) {
18979+ case Opt_append:
18980+ opt->add.bindex = au_sbend(sb) + 1;
18981+ if (opt->add.bindex < 0)
18982+ opt->add.bindex = 0;
18983+ goto add;
18984+ case Opt_prepend:
18985+ opt->add.bindex = 0;
18986+ add:
18987+ case Opt_add:
18988+ err = au_br_add(sb, &opt->add,
18989+ au_ftest_opts(opts->flags, REMOUNT));
18990+ if (!err) {
18991+ err = 1;
027c5e7a 18992+ au_fset_opts(opts->flags, REFRESH);
1facf9fc 18993+ }
18994+ break;
18995+
18996+ case Opt_del:
18997+ case Opt_idel:
18998+ err = au_br_del(sb, &opt->del,
18999+ au_ftest_opts(opts->flags, REMOUNT));
19000+ if (!err) {
19001+ err = 1;
19002+ au_fset_opts(opts->flags, TRUNC_XIB);
027c5e7a 19003+ au_fset_opts(opts->flags, REFRESH);
1facf9fc 19004+ }
19005+ break;
19006+
19007+ case Opt_mod:
19008+ case Opt_imod:
19009+ err = au_br_mod(sb, &opt->mod,
19010+ au_ftest_opts(opts->flags, REMOUNT),
19011+ &do_refresh);
19012+ if (!err) {
19013+ err = 1;
027c5e7a
AM
19014+ if (do_refresh)
19015+ au_fset_opts(opts->flags, REFRESH);
1facf9fc 19016+ }
19017+ break;
19018+ }
19019+
19020+ return err;
19021+}
19022+
19023+static int au_opt_xino(struct super_block *sb, struct au_opt *opt,
19024+ struct au_opt_xino **opt_xino,
19025+ struct au_opts *opts)
19026+{
19027+ int err;
19028+ aufs_bindex_t bend, bindex;
19029+ struct dentry *root, *parent, *h_root;
19030+
19031+ err = 0;
19032+ switch (opt->type) {
19033+ case Opt_xino:
19034+ err = au_xino_set(sb, &opt->xino,
19035+ !!au_ftest_opts(opts->flags, REMOUNT));
19036+ if (unlikely(err))
19037+ break;
19038+
19039+ *opt_xino = &opt->xino;
19040+ au_xino_brid_set(sb, -1);
19041+
19042+ /* safe d_parent access */
19043+ parent = opt->xino.file->f_dentry->d_parent;
19044+ root = sb->s_root;
19045+ bend = au_sbend(sb);
19046+ for (bindex = 0; bindex <= bend; bindex++) {
19047+ h_root = au_h_dptr(root, bindex);
19048+ if (h_root == parent) {
19049+ au_xino_brid_set(sb, au_sbr_id(sb, bindex));
19050+ break;
19051+ }
19052+ }
19053+ break;
19054+
19055+ case Opt_noxino:
19056+ au_xino_clr(sb);
19057+ au_xino_brid_set(sb, -1);
19058+ *opt_xino = (void *)-1;
19059+ break;
19060+ }
19061+
19062+ return err;
19063+}
19064+
19065+int au_opts_verify(struct super_block *sb, unsigned long sb_flags,
19066+ unsigned int pending)
19067+{
19068+ int err;
19069+ aufs_bindex_t bindex, bend;
19070+ unsigned char do_plink, skip, do_free;
19071+ struct au_branch *br;
19072+ struct au_wbr *wbr;
19073+ struct dentry *root;
19074+ struct inode *dir, *h_dir;
19075+ struct au_sbinfo *sbinfo;
19076+ struct au_hinode *hdir;
19077+
dece6358
AM
19078+ SiMustAnyLock(sb);
19079+
1facf9fc 19080+ sbinfo = au_sbi(sb);
19081+ AuDebugOn(!(sbinfo->si_mntflags & AuOptMask_UDBA));
19082+
dece6358
AM
19083+ if (!(sb_flags & MS_RDONLY)) {
19084+ if (unlikely(!au_br_writable(au_sbr_perm(sb, 0))))
4a4d8108 19085+ pr_warning("first branch should be rw\n");
dece6358 19086+ if (unlikely(au_opt_test(sbinfo->si_mntflags, SHWH)))
4a4d8108 19087+ pr_warning("shwh should be used with ro\n");
dece6358 19088+ }
1facf9fc 19089+
4a4d8108 19090+ if (au_opt_test((sbinfo->si_mntflags | pending), UDBA_HNOTIFY)
1facf9fc 19091+ && !au_opt_test(sbinfo->si_mntflags, XINO))
4a4d8108 19092+ pr_warning("udba=*notify requires xino\n");
1facf9fc 19093+
19094+ err = 0;
19095+ root = sb->s_root;
4a4d8108 19096+ dir = root->d_inode;
1facf9fc 19097+ do_plink = !!au_opt_test(sbinfo->si_mntflags, PLINK);
19098+ bend = au_sbend(sb);
19099+ for (bindex = 0; !err && bindex <= bend; bindex++) {
19100+ skip = 0;
19101+ h_dir = au_h_iptr(dir, bindex);
19102+ br = au_sbr(sb, bindex);
19103+ do_free = 0;
19104+
19105+ wbr = br->br_wbr;
19106+ if (wbr)
19107+ wbr_wh_read_lock(wbr);
19108+
19109+ switch (br->br_perm) {
19110+ case AuBrPerm_RO:
19111+ case AuBrPerm_ROWH:
19112+ case AuBrPerm_RR:
19113+ case AuBrPerm_RRWH:
19114+ do_free = !!wbr;
19115+ skip = (!wbr
19116+ || (!wbr->wbr_whbase
19117+ && !wbr->wbr_plink
19118+ && !wbr->wbr_orph));
19119+ break;
19120+
19121+ case AuBrPerm_RWNoLinkWH:
19122+ /* skip = (!br->br_whbase && !br->br_orph); */
19123+ skip = (!wbr || !wbr->wbr_whbase);
19124+ if (skip && wbr) {
19125+ if (do_plink)
19126+ skip = !!wbr->wbr_plink;
19127+ else
19128+ skip = !wbr->wbr_plink;
19129+ }
19130+ break;
19131+
19132+ case AuBrPerm_RW:
19133+ /* skip = (br->br_whbase && br->br_ohph); */
19134+ skip = (wbr && wbr->wbr_whbase);
19135+ if (skip) {
19136+ if (do_plink)
19137+ skip = !!wbr->wbr_plink;
19138+ else
19139+ skip = !wbr->wbr_plink;
19140+ }
19141+ break;
19142+
19143+ default:
19144+ BUG();
19145+ }
19146+ if (wbr)
19147+ wbr_wh_read_unlock(wbr);
19148+
19149+ if (skip)
19150+ continue;
19151+
19152+ hdir = au_hi(dir, bindex);
4a4d8108 19153+ au_hn_imtx_lock_nested(hdir, AuLsc_I_PARENT);
1facf9fc 19154+ if (wbr)
19155+ wbr_wh_write_lock(wbr);
19156+ err = au_wh_init(au_h_dptr(root, bindex), br, sb);
19157+ if (wbr)
19158+ wbr_wh_write_unlock(wbr);
4a4d8108 19159+ au_hn_imtx_unlock(hdir);
1facf9fc 19160+
19161+ if (!err && do_free) {
19162+ kfree(wbr);
19163+ br->br_wbr = NULL;
19164+ }
19165+ }
19166+
19167+ return err;
19168+}
19169+
19170+int au_opts_mount(struct super_block *sb, struct au_opts *opts)
19171+{
19172+ int err;
19173+ unsigned int tmp;
027c5e7a 19174+ aufs_bindex_t bindex, bend;
1facf9fc 19175+ struct au_opt *opt;
19176+ struct au_opt_xino *opt_xino, xino;
19177+ struct au_sbinfo *sbinfo;
027c5e7a 19178+ struct au_branch *br;
1facf9fc 19179+
dece6358
AM
19180+ SiMustWriteLock(sb);
19181+
1facf9fc 19182+ err = 0;
19183+ opt_xino = NULL;
19184+ opt = opts->opt;
19185+ while (err >= 0 && opt->type != Opt_tail)
19186+ err = au_opt_simple(sb, opt++, opts);
19187+ if (err > 0)
19188+ err = 0;
19189+ else if (unlikely(err < 0))
19190+ goto out;
19191+
19192+ /* disable xino and udba temporary */
19193+ sbinfo = au_sbi(sb);
19194+ tmp = sbinfo->si_mntflags;
19195+ au_opt_clr(sbinfo->si_mntflags, XINO);
19196+ au_opt_set_udba(sbinfo->si_mntflags, UDBA_REVAL);
19197+
19198+ opt = opts->opt;
19199+ while (err >= 0 && opt->type != Opt_tail)
19200+ err = au_opt_br(sb, opt++, opts);
19201+ if (err > 0)
19202+ err = 0;
19203+ else if (unlikely(err < 0))
19204+ goto out;
19205+
19206+ bend = au_sbend(sb);
19207+ if (unlikely(bend < 0)) {
19208+ err = -EINVAL;
4a4d8108 19209+ pr_err("no branches\n");
1facf9fc 19210+ goto out;
19211+ }
19212+
19213+ if (au_opt_test(tmp, XINO))
19214+ au_opt_set(sbinfo->si_mntflags, XINO);
19215+ opt = opts->opt;
19216+ while (!err && opt->type != Opt_tail)
19217+ err = au_opt_xino(sb, opt++, &opt_xino, opts);
19218+ if (unlikely(err))
19219+ goto out;
19220+
19221+ err = au_opts_verify(sb, sb->s_flags, tmp);
19222+ if (unlikely(err))
19223+ goto out;
19224+
19225+ /* restore xino */
19226+ if (au_opt_test(tmp, XINO) && !opt_xino) {
19227+ xino.file = au_xino_def(sb);
19228+ err = PTR_ERR(xino.file);
19229+ if (IS_ERR(xino.file))
19230+ goto out;
19231+
19232+ err = au_xino_set(sb, &xino, /*remount*/0);
19233+ fput(xino.file);
19234+ if (unlikely(err))
19235+ goto out;
19236+ }
19237+
19238+ /* restore udba */
027c5e7a 19239+ tmp &= AuOptMask_UDBA;
1facf9fc 19240+ sbinfo->si_mntflags &= ~AuOptMask_UDBA;
027c5e7a
AM
19241+ sbinfo->si_mntflags |= tmp;
19242+ bend = au_sbend(sb);
19243+ for (bindex = 0; bindex <= bend; bindex++) {
19244+ br = au_sbr(sb, bindex);
19245+ err = au_hnotify_reset_br(tmp, br, br->br_perm);
19246+ if (unlikely(err))
19247+ AuIOErr("hnotify failed on br %d, %d, ignored\n",
19248+ bindex, err);
19249+ /* go on even if err */
19250+ }
4a4d8108 19251+ if (au_opt_test(tmp, UDBA_HNOTIFY)) {
1facf9fc 19252+ struct inode *dir = sb->s_root->d_inode;
4a4d8108 19253+ au_hn_reset(dir, au_hi_flags(dir, /*isdir*/1) & ~AuHi_XINO);
1facf9fc 19254+ }
19255+
4f0767ce 19256+out:
1facf9fc 19257+ return err;
19258+}
19259+
19260+int au_opts_remount(struct super_block *sb, struct au_opts *opts)
19261+{
19262+ int err, rerr;
19263+ struct inode *dir;
19264+ struct au_opt_xino *opt_xino;
19265+ struct au_opt *opt;
19266+ struct au_sbinfo *sbinfo;
19267+
dece6358
AM
19268+ SiMustWriteLock(sb);
19269+
1facf9fc 19270+ dir = sb->s_root->d_inode;
19271+ sbinfo = au_sbi(sb);
19272+ err = 0;
19273+ opt_xino = NULL;
19274+ opt = opts->opt;
19275+ while (err >= 0 && opt->type != Opt_tail) {
19276+ err = au_opt_simple(sb, opt, opts);
19277+ if (!err)
19278+ err = au_opt_br(sb, opt, opts);
19279+ if (!err)
19280+ err = au_opt_xino(sb, opt, &opt_xino, opts);
19281+ opt++;
19282+ }
19283+ if (err > 0)
19284+ err = 0;
19285+ AuTraceErr(err);
19286+ /* go on even err */
19287+
19288+ rerr = au_opts_verify(sb, opts->sb_flags, /*pending*/0);
19289+ if (unlikely(rerr && !err))
19290+ err = rerr;
19291+
19292+ if (au_ftest_opts(opts->flags, TRUNC_XIB)) {
19293+ rerr = au_xib_trunc(sb);
19294+ if (unlikely(rerr && !err))
19295+ err = rerr;
19296+ }
19297+
19298+ /* will be handled by the caller */
027c5e7a 19299+ if (!au_ftest_opts(opts->flags, REFRESH)
1facf9fc 19300+ && (opts->given_udba || au_opt_test(sbinfo->si_mntflags, XINO)))
027c5e7a 19301+ au_fset_opts(opts->flags, REFRESH);
1facf9fc 19302+
19303+ AuDbg("status 0x%x\n", opts->flags);
19304+ return err;
19305+}
19306+
19307+/* ---------------------------------------------------------------------- */
19308+
19309+unsigned int au_opt_udba(struct super_block *sb)
19310+{
19311+ return au_mntflags(sb) & AuOptMask_UDBA;
19312+}
7f207e10
AM
19313diff -urN /usr/share/empty/fs/aufs/opts.h linux/fs/aufs/opts.h
19314--- /usr/share/empty/fs/aufs/opts.h 1970-01-01 01:00:00.000000000 +0100
87a755f4 19315+++ linux/fs/aufs/opts.h 2011-03-17 10:46:59.000000000 +0100
027c5e7a 19316@@ -0,0 +1,210 @@
1facf9fc 19317+/*
027c5e7a 19318+ * Copyright (C) 2005-2011 Junjiro R. Okajima
1facf9fc 19319+ *
19320+ * This program, aufs is free software; you can redistribute it and/or modify
19321+ * it under the terms of the GNU General Public License as published by
19322+ * the Free Software Foundation; either version 2 of the License, or
19323+ * (at your option) any later version.
dece6358
AM
19324+ *
19325+ * This program is distributed in the hope that it will be useful,
19326+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
19327+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19328+ * GNU General Public License for more details.
19329+ *
19330+ * You should have received a copy of the GNU General Public License
19331+ * along with this program; if not, write to the Free Software
19332+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 19333+ */
19334+
19335+/*
19336+ * mount options/flags
19337+ */
19338+
19339+#ifndef __AUFS_OPTS_H__
19340+#define __AUFS_OPTS_H__
19341+
19342+#ifdef __KERNEL__
19343+
dece6358 19344+#include <linux/path.h>
1facf9fc 19345+#include <linux/aufs_type.h>
19346+
dece6358
AM
19347+struct file;
19348+struct super_block;
19349+
1facf9fc 19350+/* ---------------------------------------------------------------------- */
19351+
19352+/* mount flags */
19353+#define AuOpt_XINO 1 /* external inode number bitmap
19354+ and translation table */
19355+#define AuOpt_TRUNC_XINO (1 << 1) /* truncate xino files */
19356+#define AuOpt_UDBA_NONE (1 << 2) /* users direct branch access */
19357+#define AuOpt_UDBA_REVAL (1 << 3)
4a4d8108 19358+#define AuOpt_UDBA_HNOTIFY (1 << 4)
dece6358
AM
19359+#define AuOpt_SHWH (1 << 5) /* show whiteout */
19360+#define AuOpt_PLINK (1 << 6) /* pseudo-link */
19361+#define AuOpt_DIRPERM1 (1 << 7) /* unimplemented */
19362+#define AuOpt_REFROF (1 << 8) /* unimplemented */
19363+#define AuOpt_ALWAYS_DIROPQ (1 << 9) /* policy to creating diropq */
19364+#define AuOpt_SUM (1 << 10) /* summation for statfs(2) */
19365+#define AuOpt_SUM_W (1 << 11) /* unimplemented */
19366+#define AuOpt_WARN_PERM (1 << 12) /* warn when add-branch */
19367+#define AuOpt_VERBOSE (1 << 13) /* busy inode when del-branch */
4a4d8108 19368+#define AuOpt_DIO (1 << 14) /* direct io */
1facf9fc 19369+
4a4d8108
AM
19370+#ifndef CONFIG_AUFS_HNOTIFY
19371+#undef AuOpt_UDBA_HNOTIFY
19372+#define AuOpt_UDBA_HNOTIFY 0
1facf9fc 19373+#endif
dece6358
AM
19374+#ifndef CONFIG_AUFS_SHWH
19375+#undef AuOpt_SHWH
19376+#define AuOpt_SHWH 0
19377+#endif
1facf9fc 19378+
19379+#define AuOpt_Def (AuOpt_XINO \
19380+ | AuOpt_UDBA_REVAL \
19381+ | AuOpt_PLINK \
19382+ /* | AuOpt_DIRPERM1 */ \
19383+ | AuOpt_WARN_PERM)
19384+#define AuOptMask_UDBA (AuOpt_UDBA_NONE \
19385+ | AuOpt_UDBA_REVAL \
4a4d8108 19386+ | AuOpt_UDBA_HNOTIFY)
1facf9fc 19387+
19388+#define au_opt_test(flags, name) (flags & AuOpt_##name)
19389+#define au_opt_set(flags, name) do { \
19390+ BUILD_BUG_ON(AuOpt_##name & AuOptMask_UDBA); \
19391+ ((flags) |= AuOpt_##name); \
19392+} while (0)
19393+#define au_opt_set_udba(flags, name) do { \
19394+ (flags) &= ~AuOptMask_UDBA; \
19395+ ((flags) |= AuOpt_##name); \
19396+} while (0)
7f207e10
AM
19397+#define au_opt_clr(flags, name) do { \
19398+ ((flags) &= ~AuOpt_##name); \
19399+} while (0)
1facf9fc 19400+
e49829fe
JR
19401+static inline unsigned int au_opts_plink(unsigned int mntflags)
19402+{
19403+#ifdef CONFIG_PROC_FS
19404+ return mntflags;
19405+#else
19406+ return mntflags & ~AuOpt_PLINK;
19407+#endif
19408+}
19409+
1facf9fc 19410+/* ---------------------------------------------------------------------- */
19411+
19412+/* policies to select one among multiple writable branches */
19413+enum {
19414+ AuWbrCreate_TDP, /* top down parent */
19415+ AuWbrCreate_RR, /* round robin */
19416+ AuWbrCreate_MFS, /* most free space */
19417+ AuWbrCreate_MFSV, /* mfs with seconds */
19418+ AuWbrCreate_MFSRR, /* mfs then rr */
19419+ AuWbrCreate_MFSRRV, /* mfs then rr with seconds */
19420+ AuWbrCreate_PMFS, /* parent and mfs */
19421+ AuWbrCreate_PMFSV, /* parent and mfs with seconds */
19422+
19423+ AuWbrCreate_Def = AuWbrCreate_TDP
19424+};
19425+
19426+enum {
19427+ AuWbrCopyup_TDP, /* top down parent */
19428+ AuWbrCopyup_BUP, /* bottom up parent */
19429+ AuWbrCopyup_BU, /* bottom up */
19430+
19431+ AuWbrCopyup_Def = AuWbrCopyup_TDP
19432+};
19433+
19434+/* ---------------------------------------------------------------------- */
19435+
19436+struct au_opt_add {
19437+ aufs_bindex_t bindex;
19438+ char *pathname;
19439+ int perm;
19440+ struct path path;
19441+};
19442+
19443+struct au_opt_del {
19444+ char *pathname;
19445+ struct path h_path;
19446+};
19447+
19448+struct au_opt_mod {
19449+ char *path;
19450+ int perm;
19451+ struct dentry *h_root;
19452+};
19453+
19454+struct au_opt_xino {
19455+ char *path;
19456+ struct file *file;
19457+};
19458+
19459+struct au_opt_xino_itrunc {
19460+ aufs_bindex_t bindex;
19461+};
19462+
19463+struct au_opt_wbr_create {
19464+ int wbr_create;
19465+ int mfs_second;
19466+ unsigned long long mfsrr_watermark;
19467+};
19468+
19469+struct au_opt {
19470+ int type;
19471+ union {
19472+ struct au_opt_xino xino;
19473+ struct au_opt_xino_itrunc xino_itrunc;
19474+ struct au_opt_add add;
19475+ struct au_opt_del del;
19476+ struct au_opt_mod mod;
19477+ int dirwh;
19478+ int rdcache;
19479+ unsigned int rdblk;
19480+ unsigned int rdhash;
19481+ int udba;
19482+ struct au_opt_wbr_create wbr_create;
19483+ int wbr_copyup;
19484+ };
19485+};
19486+
19487+/* opts flags */
19488+#define AuOpts_REMOUNT 1
027c5e7a
AM
19489+#define AuOpts_REFRESH (1 << 1)
19490+#define AuOpts_TRUNC_XIB (1 << 2)
19491+#define AuOpts_REFRESH_DYAOP (1 << 3)
1facf9fc 19492+#define au_ftest_opts(flags, name) ((flags) & AuOpts_##name)
7f207e10
AM
19493+#define au_fset_opts(flags, name) \
19494+ do { (flags) |= AuOpts_##name; } while (0)
19495+#define au_fclr_opts(flags, name) \
19496+ do { (flags) &= ~AuOpts_##name; } while (0)
1facf9fc 19497+
19498+struct au_opts {
19499+ struct au_opt *opt;
19500+ int max_opt;
19501+
19502+ unsigned int given_udba;
19503+ unsigned int flags;
19504+ unsigned long sb_flags;
19505+};
19506+
19507+/* ---------------------------------------------------------------------- */
19508+
19509+const char *au_optstr_br_perm(int brperm);
19510+const char *au_optstr_udba(int udba);
19511+const char *au_optstr_wbr_copyup(int wbr_copyup);
19512+const char *au_optstr_wbr_create(int wbr_create);
19513+
19514+void au_opts_free(struct au_opts *opts);
19515+int au_opts_parse(struct super_block *sb, char *str, struct au_opts *opts);
19516+int au_opts_verify(struct super_block *sb, unsigned long sb_flags,
19517+ unsigned int pending);
19518+int au_opts_mount(struct super_block *sb, struct au_opts *opts);
19519+int au_opts_remount(struct super_block *sb, struct au_opts *opts);
19520+
19521+unsigned int au_opt_udba(struct super_block *sb);
19522+
19523+/* ---------------------------------------------------------------------- */
19524+
19525+#endif /* __KERNEL__ */
19526+#endif /* __AUFS_OPTS_H__ */
7f207e10
AM
19527diff -urN /usr/share/empty/fs/aufs/plink.c linux/fs/aufs/plink.c
19528--- /usr/share/empty/fs/aufs/plink.c 1970-01-01 01:00:00.000000000 +0100
87a755f4 19529+++ linux/fs/aufs/plink.c 2011-03-17 10:46:59.000000000 +0100
027c5e7a 19530@@ -0,0 +1,515 @@
1facf9fc 19531+/*
027c5e7a 19532+ * Copyright (C) 2005-2011 Junjiro R. Okajima
1facf9fc 19533+ *
19534+ * This program, aufs is free software; you can redistribute it and/or modify
19535+ * it under the terms of the GNU General Public License as published by
19536+ * the Free Software Foundation; either version 2 of the License, or
19537+ * (at your option) any later version.
dece6358
AM
19538+ *
19539+ * This program is distributed in the hope that it will be useful,
19540+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
19541+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19542+ * GNU General Public License for more details.
19543+ *
19544+ * You should have received a copy of the GNU General Public License
19545+ * along with this program; if not, write to the Free Software
19546+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 19547+ */
19548+
19549+/*
19550+ * pseudo-link
19551+ */
19552+
19553+#include "aufs.h"
19554+
19555+/*
e49829fe 19556+ * the pseudo-link maintenance mode.
1facf9fc 19557+ * during a user process maintains the pseudo-links,
19558+ * prohibit adding a new plink and branch manipulation.
e49829fe
JR
19559+ *
19560+ * Flags
19561+ * NOPLM:
19562+ * For entry functions which will handle plink, and i_mutex is already held
19563+ * in VFS.
19564+ * They cannot wait and should return an error at once.
19565+ * Callers has to check the error.
19566+ * NOPLMW:
19567+ * For entry functions which will handle plink, but i_mutex is not held
19568+ * in VFS.
19569+ * They can wait the plink maintenance mode to finish.
19570+ *
19571+ * They behave like F_SETLK and F_SETLKW.
19572+ * If the caller never handle plink, then both flags are unnecessary.
1facf9fc 19573+ */
e49829fe
JR
19574+
19575+int au_plink_maint(struct super_block *sb, int flags)
1facf9fc 19576+{
e49829fe
JR
19577+ int err;
19578+ pid_t pid, ppid;
19579+ struct au_sbinfo *sbi;
dece6358
AM
19580+
19581+ SiMustAnyLock(sb);
19582+
e49829fe
JR
19583+ err = 0;
19584+ if (!au_opt_test(au_mntflags(sb), PLINK))
19585+ goto out;
19586+
19587+ sbi = au_sbi(sb);
19588+ pid = sbi->si_plink_maint_pid;
19589+ if (!pid || pid == current->pid)
19590+ goto out;
19591+
19592+ /* todo: it highly depends upon /sbin/mount.aufs */
19593+ rcu_read_lock();
19594+ ppid = task_pid_vnr(rcu_dereference(current->real_parent));
19595+ rcu_read_unlock();
19596+ if (pid == ppid)
19597+ goto out;
19598+
19599+ if (au_ftest_lock(flags, NOPLMW)) {
027c5e7a
AM
19600+ /* if there is no i_mutex lock in VFS, we don't need to wait */
19601+ /* AuDebugOn(!lockdep_depth(current)); */
e49829fe
JR
19602+ while (sbi->si_plink_maint_pid) {
19603+ si_read_unlock(sb);
19604+ /* gave up wake_up_bit() */
19605+ wait_event(sbi->si_plink_wq, !sbi->si_plink_maint_pid);
19606+
19607+ if (au_ftest_lock(flags, FLUSH))
19608+ au_nwt_flush(&sbi->si_nowait);
19609+ si_noflush_read_lock(sb);
19610+ }
19611+ } else if (au_ftest_lock(flags, NOPLM)) {
19612+ AuDbg("ppid %d, pid %d\n", ppid, pid);
19613+ err = -EAGAIN;
19614+ }
19615+
19616+out:
19617+ return err;
4a4d8108
AM
19618+}
19619+
e49829fe 19620+void au_plink_maint_leave(struct au_sbinfo *sbinfo)
4a4d8108 19621+{
4a4d8108 19622+ spin_lock(&sbinfo->si_plink_maint_lock);
027c5e7a 19623+ sbinfo->si_plink_maint_pid = 0;
4a4d8108 19624+ spin_unlock(&sbinfo->si_plink_maint_lock);
027c5e7a 19625+ wake_up_all(&sbinfo->si_plink_wq);
4a4d8108
AM
19626+}
19627+
e49829fe 19628+int au_plink_maint_enter(struct super_block *sb)
4a4d8108
AM
19629+{
19630+ int err;
4a4d8108
AM
19631+ struct au_sbinfo *sbinfo;
19632+
19633+ err = 0;
4a4d8108
AM
19634+ sbinfo = au_sbi(sb);
19635+ /* make sure i am the only one in this fs */
e49829fe
JR
19636+ si_write_lock(sb, AuLock_FLUSH);
19637+ if (au_opt_test(au_mntflags(sb), PLINK)) {
19638+ spin_lock(&sbinfo->si_plink_maint_lock);
19639+ if (!sbinfo->si_plink_maint_pid)
19640+ sbinfo->si_plink_maint_pid = current->pid;
19641+ else
19642+ err = -EBUSY;
19643+ spin_unlock(&sbinfo->si_plink_maint_lock);
19644+ }
4a4d8108
AM
19645+ si_write_unlock(sb);
19646+
19647+ return err;
1facf9fc 19648+}
19649+
19650+/* ---------------------------------------------------------------------- */
19651+
19652+struct pseudo_link {
4a4d8108
AM
19653+ union {
19654+ struct list_head list;
19655+ struct rcu_head rcu;
19656+ };
1facf9fc 19657+ struct inode *inode;
19658+};
19659+
19660+#ifdef CONFIG_AUFS_DEBUG
19661+void au_plink_list(struct super_block *sb)
19662+{
19663+ struct au_sbinfo *sbinfo;
19664+ struct list_head *plink_list;
19665+ struct pseudo_link *plink;
19666+
dece6358
AM
19667+ SiMustAnyLock(sb);
19668+
1facf9fc 19669+ sbinfo = au_sbi(sb);
19670+ AuDebugOn(!au_opt_test(au_mntflags(sb), PLINK));
e49829fe 19671+ AuDebugOn(au_plink_maint(sb, AuLock_NOPLM));
1facf9fc 19672+
19673+ plink_list = &sbinfo->si_plink.head;
4a4d8108
AM
19674+ rcu_read_lock();
19675+ list_for_each_entry_rcu(plink, plink_list, list)
1facf9fc 19676+ AuDbg("%lu\n", plink->inode->i_ino);
4a4d8108 19677+ rcu_read_unlock();
1facf9fc 19678+}
19679+#endif
19680+
19681+/* is the inode pseudo-linked? */
19682+int au_plink_test(struct inode *inode)
19683+{
19684+ int found;
19685+ struct au_sbinfo *sbinfo;
19686+ struct list_head *plink_list;
19687+ struct pseudo_link *plink;
19688+
19689+ sbinfo = au_sbi(inode->i_sb);
dece6358 19690+ AuRwMustAnyLock(&sbinfo->si_rwsem);
1facf9fc 19691+ AuDebugOn(!au_opt_test(au_mntflags(inode->i_sb), PLINK));
e49829fe 19692+ AuDebugOn(au_plink_maint(inode->i_sb, AuLock_NOPLM));
1facf9fc 19693+
19694+ found = 0;
19695+ plink_list = &sbinfo->si_plink.head;
4a4d8108
AM
19696+ rcu_read_lock();
19697+ list_for_each_entry_rcu(plink, plink_list, list)
1facf9fc 19698+ if (plink->inode == inode) {
19699+ found = 1;
19700+ break;
19701+ }
4a4d8108 19702+ rcu_read_unlock();
1facf9fc 19703+ return found;
19704+}
19705+
19706+/* ---------------------------------------------------------------------- */
19707+
19708+/*
19709+ * generate a name for plink.
19710+ * the file will be stored under AUFS_WH_PLINKDIR.
19711+ */
19712+/* 20 is max digits length of ulong 64 */
19713+#define PLINK_NAME_LEN ((20 + 1) * 2)
19714+
19715+static int plink_name(char *name, int len, struct inode *inode,
19716+ aufs_bindex_t bindex)
19717+{
19718+ int rlen;
19719+ struct inode *h_inode;
19720+
19721+ h_inode = au_h_iptr(inode, bindex);
19722+ rlen = snprintf(name, len, "%lu.%lu", inode->i_ino, h_inode->i_ino);
19723+ return rlen;
19724+}
19725+
7f207e10
AM
19726+struct au_do_plink_lkup_args {
19727+ struct dentry **errp;
19728+ struct qstr *tgtname;
19729+ struct dentry *h_parent;
19730+ struct au_branch *br;
19731+};
19732+
19733+static struct dentry *au_do_plink_lkup(struct qstr *tgtname,
19734+ struct dentry *h_parent,
19735+ struct au_branch *br)
19736+{
19737+ struct dentry *h_dentry;
19738+ struct mutex *h_mtx;
19739+
19740+ h_mtx = &h_parent->d_inode->i_mutex;
19741+ mutex_lock_nested(h_mtx, AuLsc_I_CHILD2);
19742+ h_dentry = au_lkup_one(tgtname, h_parent, br, /*nd*/NULL);
19743+ mutex_unlock(h_mtx);
19744+ return h_dentry;
19745+}
19746+
19747+static void au_call_do_plink_lkup(void *args)
19748+{
19749+ struct au_do_plink_lkup_args *a = args;
19750+ *a->errp = au_do_plink_lkup(a->tgtname, a->h_parent, a->br);
19751+}
19752+
1facf9fc 19753+/* lookup the plink-ed @inode under the branch at @bindex */
19754+struct dentry *au_plink_lkup(struct inode *inode, aufs_bindex_t bindex)
19755+{
19756+ struct dentry *h_dentry, *h_parent;
19757+ struct au_branch *br;
19758+ struct inode *h_dir;
7f207e10 19759+ int wkq_err;
1facf9fc 19760+ char a[PLINK_NAME_LEN];
19761+ struct qstr tgtname = {
19762+ .name = a
19763+ };
19764+
e49829fe
JR
19765+ AuDebugOn(au_plink_maint(inode->i_sb, AuLock_NOPLM));
19766+
1facf9fc 19767+ br = au_sbr(inode->i_sb, bindex);
19768+ h_parent = br->br_wbr->wbr_plink;
19769+ h_dir = h_parent->d_inode;
19770+ tgtname.len = plink_name(a, sizeof(a), inode, bindex);
19771+
7f207e10
AM
19772+ if (current_fsuid()) {
19773+ struct au_do_plink_lkup_args args = {
19774+ .errp = &h_dentry,
19775+ .tgtname = &tgtname,
19776+ .h_parent = h_parent,
19777+ .br = br
19778+ };
19779+
19780+ wkq_err = au_wkq_wait(au_call_do_plink_lkup, &args);
19781+ if (unlikely(wkq_err))
19782+ h_dentry = ERR_PTR(wkq_err);
19783+ } else
19784+ h_dentry = au_do_plink_lkup(&tgtname, h_parent, br);
19785+
1facf9fc 19786+ return h_dentry;
19787+}
19788+
19789+/* create a pseudo-link */
19790+static int do_whplink(struct qstr *tgt, struct dentry *h_parent,
19791+ struct dentry *h_dentry, struct au_branch *br)
19792+{
19793+ int err;
19794+ struct path h_path = {
19795+ .mnt = br->br_mnt
19796+ };
19797+ struct inode *h_dir;
19798+
19799+ h_dir = h_parent->d_inode;
7f207e10 19800+ mutex_lock_nested(&h_dir->i_mutex, AuLsc_I_CHILD2);
4f0767ce 19801+again:
1facf9fc 19802+ h_path.dentry = au_lkup_one(tgt, h_parent, br, /*nd*/NULL);
19803+ err = PTR_ERR(h_path.dentry);
19804+ if (IS_ERR(h_path.dentry))
19805+ goto out;
19806+
19807+ err = 0;
19808+ /* wh.plink dir is not monitored */
7f207e10 19809+ /* todo: is it really safe? */
1facf9fc 19810+ if (h_path.dentry->d_inode
19811+ && h_path.dentry->d_inode != h_dentry->d_inode) {
19812+ err = vfsub_unlink(h_dir, &h_path, /*force*/0);
19813+ dput(h_path.dentry);
19814+ h_path.dentry = NULL;
19815+ if (!err)
19816+ goto again;
19817+ }
19818+ if (!err && !h_path.dentry->d_inode)
19819+ err = vfsub_link(h_dentry, h_dir, &h_path);
19820+ dput(h_path.dentry);
19821+
4f0767ce 19822+out:
7f207e10 19823+ mutex_unlock(&h_dir->i_mutex);
1facf9fc 19824+ return err;
19825+}
19826+
19827+struct do_whplink_args {
19828+ int *errp;
19829+ struct qstr *tgt;
19830+ struct dentry *h_parent;
19831+ struct dentry *h_dentry;
19832+ struct au_branch *br;
19833+};
19834+
19835+static void call_do_whplink(void *args)
19836+{
19837+ struct do_whplink_args *a = args;
19838+ *a->errp = do_whplink(a->tgt, a->h_parent, a->h_dentry, a->br);
19839+}
19840+
19841+static int whplink(struct dentry *h_dentry, struct inode *inode,
19842+ aufs_bindex_t bindex, struct au_branch *br)
19843+{
19844+ int err, wkq_err;
19845+ struct au_wbr *wbr;
19846+ struct dentry *h_parent;
19847+ struct inode *h_dir;
19848+ char a[PLINK_NAME_LEN];
19849+ struct qstr tgtname = {
19850+ .name = a
19851+ };
19852+
19853+ wbr = au_sbr(inode->i_sb, bindex)->br_wbr;
19854+ h_parent = wbr->wbr_plink;
19855+ h_dir = h_parent->d_inode;
19856+ tgtname.len = plink_name(a, sizeof(a), inode, bindex);
19857+
19858+ /* always superio. */
b752ccd1 19859+ if (current_fsuid()) {
1facf9fc 19860+ struct do_whplink_args args = {
19861+ .errp = &err,
19862+ .tgt = &tgtname,
19863+ .h_parent = h_parent,
19864+ .h_dentry = h_dentry,
19865+ .br = br
19866+ };
19867+ wkq_err = au_wkq_wait(call_do_whplink, &args);
19868+ if (unlikely(wkq_err))
19869+ err = wkq_err;
19870+ } else
19871+ err = do_whplink(&tgtname, h_parent, h_dentry, br);
1facf9fc 19872+
19873+ return err;
19874+}
19875+
19876+/* free a single plink */
19877+static void do_put_plink(struct pseudo_link *plink, int do_del)
19878+{
1facf9fc 19879+ if (do_del)
19880+ list_del(&plink->list);
4a4d8108
AM
19881+ iput(plink->inode);
19882+ kfree(plink);
19883+}
19884+
19885+static void do_put_plink_rcu(struct rcu_head *rcu)
19886+{
19887+ struct pseudo_link *plink;
19888+
19889+ plink = container_of(rcu, struct pseudo_link, rcu);
19890+ iput(plink->inode);
1facf9fc 19891+ kfree(plink);
19892+}
19893+
19894+/*
19895+ * create a new pseudo-link for @h_dentry on @bindex.
19896+ * the linked inode is held in aufs @inode.
19897+ */
19898+void au_plink_append(struct inode *inode, aufs_bindex_t bindex,
19899+ struct dentry *h_dentry)
19900+{
19901+ struct super_block *sb;
19902+ struct au_sbinfo *sbinfo;
19903+ struct list_head *plink_list;
4a4d8108 19904+ struct pseudo_link *plink, *tmp;
1facf9fc 19905+ int found, err, cnt;
19906+
19907+ sb = inode->i_sb;
19908+ sbinfo = au_sbi(sb);
19909+ AuDebugOn(!au_opt_test(au_mntflags(sb), PLINK));
e49829fe 19910+ AuDebugOn(au_plink_maint(sb, AuLock_NOPLM));
1facf9fc 19911+
1facf9fc 19912+ cnt = 0;
19913+ found = 0;
19914+ plink_list = &sbinfo->si_plink.head;
4a4d8108
AM
19915+ rcu_read_lock();
19916+ list_for_each_entry_rcu(plink, plink_list, list) {
1facf9fc 19917+ cnt++;
19918+ if (plink->inode == inode) {
19919+ found = 1;
19920+ break;
19921+ }
19922+ }
4a4d8108
AM
19923+ rcu_read_unlock();
19924+ if (found)
1facf9fc 19925+ return;
4a4d8108
AM
19926+
19927+ tmp = kmalloc(sizeof(*plink), GFP_NOFS);
19928+ if (tmp)
19929+ tmp->inode = au_igrab(inode);
19930+ else {
19931+ err = -ENOMEM;
19932+ goto out;
1facf9fc 19933+ }
19934+
4a4d8108
AM
19935+ spin_lock(&sbinfo->si_plink.spin);
19936+ list_for_each_entry(plink, plink_list, list) {
19937+ if (plink->inode == inode) {
19938+ found = 1;
19939+ break;
19940+ }
1facf9fc 19941+ }
4a4d8108
AM
19942+ if (!found)
19943+ list_add_rcu(&tmp->list, plink_list);
1facf9fc 19944+ spin_unlock(&sbinfo->si_plink.spin);
4a4d8108
AM
19945+ if (!found) {
19946+ cnt++;
19947+ WARN_ONCE(cnt > AUFS_PLINK_WARN,
19948+ "unexpectedly many pseudo links, %d\n", cnt);
1facf9fc 19949+ err = whplink(h_dentry, inode, bindex, au_sbr(sb, bindex));
4a4d8108
AM
19950+ } else {
19951+ do_put_plink(tmp, 0);
19952+ return;
1facf9fc 19953+ }
19954+
4a4d8108 19955+out:
1facf9fc 19956+ if (unlikely(err)) {
4a4d8108
AM
19957+ pr_warning("err %d, damaged pseudo link.\n", err);
19958+ if (tmp) {
19959+ au_spl_del_rcu(&tmp->list, &sbinfo->si_plink);
19960+ call_rcu(&tmp->rcu, do_put_plink_rcu);
19961+ }
1facf9fc 19962+ }
19963+}
19964+
19965+/* free all plinks */
e49829fe 19966+void au_plink_put(struct super_block *sb, int verbose)
1facf9fc 19967+{
19968+ struct au_sbinfo *sbinfo;
19969+ struct list_head *plink_list;
19970+ struct pseudo_link *plink, *tmp;
19971+
dece6358
AM
19972+ SiMustWriteLock(sb);
19973+
1facf9fc 19974+ sbinfo = au_sbi(sb);
19975+ AuDebugOn(!au_opt_test(au_mntflags(sb), PLINK));
e49829fe 19976+ AuDebugOn(au_plink_maint(sb, AuLock_NOPLM));
1facf9fc 19977+
19978+ plink_list = &sbinfo->si_plink.head;
19979+ /* no spin_lock since sbinfo is write-locked */
e49829fe 19980+ WARN(verbose && !list_empty(plink_list), "pseudo-link is not flushed");
1facf9fc 19981+ list_for_each_entry_safe(plink, tmp, plink_list, list)
19982+ do_put_plink(plink, 0);
19983+ INIT_LIST_HEAD(plink_list);
19984+}
19985+
e49829fe
JR
19986+void au_plink_clean(struct super_block *sb, int verbose)
19987+{
19988+ struct dentry *root;
19989+
19990+ root = sb->s_root;
19991+ aufs_write_lock(root);
19992+ if (au_opt_test(au_mntflags(sb), PLINK))
19993+ au_plink_put(sb, verbose);
19994+ aufs_write_unlock(root);
19995+}
19996+
1facf9fc 19997+/* free the plinks on a branch specified by @br_id */
19998+void au_plink_half_refresh(struct super_block *sb, aufs_bindex_t br_id)
19999+{
20000+ struct au_sbinfo *sbinfo;
20001+ struct list_head *plink_list;
20002+ struct pseudo_link *plink, *tmp;
20003+ struct inode *inode;
20004+ aufs_bindex_t bstart, bend, bindex;
20005+ unsigned char do_put;
20006+
dece6358
AM
20007+ SiMustWriteLock(sb);
20008+
1facf9fc 20009+ sbinfo = au_sbi(sb);
20010+ AuDebugOn(!au_opt_test(au_mntflags(sb), PLINK));
e49829fe 20011+ AuDebugOn(au_plink_maint(sb, AuLock_NOPLM));
1facf9fc 20012+
20013+ plink_list = &sbinfo->si_plink.head;
20014+ /* no spin_lock since sbinfo is write-locked */
20015+ list_for_each_entry_safe(plink, tmp, plink_list, list) {
20016+ do_put = 0;
20017+ inode = au_igrab(plink->inode);
20018+ ii_write_lock_child(inode);
20019+ bstart = au_ibstart(inode);
20020+ bend = au_ibend(inode);
20021+ if (bstart >= 0) {
20022+ for (bindex = bstart; bindex <= bend; bindex++) {
20023+ if (!au_h_iptr(inode, bindex)
20024+ || au_ii_br_id(inode, bindex) != br_id)
20025+ continue;
20026+ au_set_h_iptr(inode, bindex, NULL, 0);
20027+ do_put = 1;
20028+ break;
20029+ }
20030+ } else
20031+ do_put_plink(plink, 1);
20032+
dece6358
AM
20033+ if (do_put) {
20034+ for (bindex = bstart; bindex <= bend; bindex++)
20035+ if (au_h_iptr(inode, bindex)) {
20036+ do_put = 0;
20037+ break;
20038+ }
20039+ if (do_put)
20040+ do_put_plink(plink, 1);
20041+ }
20042+ ii_write_unlock(inode);
20043+ iput(inode);
20044+ }
20045+}
7f207e10
AM
20046diff -urN /usr/share/empty/fs/aufs/poll.c linux/fs/aufs/poll.c
20047--- /usr/share/empty/fs/aufs/poll.c 1970-01-01 01:00:00.000000000 +0100
87a755f4 20048+++ linux/fs/aufs/poll.c 2011-03-17 10:46:59.000000000 +0100
dece6358
AM
20049@@ -0,0 +1,56 @@
20050+/*
027c5e7a 20051+ * Copyright (C) 2005-2011 Junjiro R. Okajima
dece6358
AM
20052+ *
20053+ * This program, aufs is free software; you can redistribute it and/or modify
20054+ * it under the terms of the GNU General Public License as published by
20055+ * the Free Software Foundation; either version 2 of the License, or
20056+ * (at your option) any later version.
20057+ *
20058+ * This program is distributed in the hope that it will be useful,
20059+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
20060+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20061+ * GNU General Public License for more details.
20062+ *
20063+ * You should have received a copy of the GNU General Public License
20064+ * along with this program; if not, write to the Free Software
20065+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
20066+ */
20067+
1308ab2a 20068+/*
20069+ * poll operation
20070+ * There is only one filesystem which implements ->poll operation, currently.
20071+ */
20072+
20073+#include "aufs.h"
20074+
20075+unsigned int aufs_poll(struct file *file, poll_table *wait)
20076+{
20077+ unsigned int mask;
20078+ int err;
20079+ struct file *h_file;
20080+ struct dentry *dentry;
20081+ struct super_block *sb;
20082+
20083+ /* We should pretend an error happened. */
20084+ mask = POLLERR /* | POLLIN | POLLOUT */;
20085+ dentry = file->f_dentry;
20086+ sb = dentry->d_sb;
e49829fe 20087+ si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLMW);
1308ab2a 20088+ err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/0);
20089+ if (unlikely(err))
20090+ goto out;
20091+
20092+ /* it is not an error if h_file has no operation */
20093+ mask = DEFAULT_POLLMASK;
4a4d8108 20094+ h_file = au_hf_top(file);
1308ab2a 20095+ if (h_file->f_op && h_file->f_op->poll)
20096+ mask = h_file->f_op->poll(h_file, wait);
20097+
20098+ di_read_unlock(dentry, AuLock_IR);
20099+ fi_read_unlock(file);
20100+
4f0767ce 20101+out:
1308ab2a 20102+ si_read_unlock(sb);
20103+ AuTraceErr((int)mask);
20104+ return mask;
20105+}
7f207e10
AM
20106diff -urN /usr/share/empty/fs/aufs/procfs.c linux/fs/aufs/procfs.c
20107--- /usr/share/empty/fs/aufs/procfs.c 1970-01-01 01:00:00.000000000 +0100
87a755f4 20108+++ linux/fs/aufs/procfs.c 2011-03-17 10:46:59.000000000 +0100
e49829fe
JR
20109@@ -0,0 +1,169 @@
20110+/*
027c5e7a 20111+ * Copyright (C) 2010-2011 Junjiro R. Okajima
e49829fe
JR
20112+ *
20113+ * This program, aufs is free software; you can redistribute it and/or modify
20114+ * it under the terms of the GNU General Public License as published by
20115+ * the Free Software Foundation; either version 2 of the License, or
20116+ * (at your option) any later version.
20117+ *
20118+ * This program is distributed in the hope that it will be useful,
20119+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
20120+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20121+ * GNU General Public License for more details.
20122+ *
20123+ * You should have received a copy of the GNU General Public License
20124+ * along with this program; if not, write to the Free Software
20125+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
20126+ */
20127+
20128+/*
20129+ * procfs interfaces
20130+ */
20131+
20132+#include <linux/proc_fs.h>
20133+#include "aufs.h"
20134+
20135+static int au_procfs_plm_release(struct inode *inode, struct file *file)
20136+{
20137+ struct au_sbinfo *sbinfo;
20138+
20139+ sbinfo = file->private_data;
20140+ if (sbinfo) {
20141+ au_plink_maint_leave(sbinfo);
20142+ kobject_put(&sbinfo->si_kobj);
20143+ }
20144+
20145+ return 0;
20146+}
20147+
20148+static void au_procfs_plm_write_clean(struct file *file)
20149+{
20150+ struct au_sbinfo *sbinfo;
20151+
20152+ sbinfo = file->private_data;
20153+ if (sbinfo)
20154+ au_plink_clean(sbinfo->si_sb, /*verbose*/0);
20155+}
20156+
20157+static int au_procfs_plm_write_si(struct file *file, unsigned long id)
20158+{
20159+ int err;
20160+ struct super_block *sb;
20161+ struct au_sbinfo *sbinfo;
20162+
20163+ err = -EBUSY;
20164+ if (unlikely(file->private_data))
20165+ goto out;
20166+
20167+ sb = NULL;
20168+ spin_lock(&au_sbilist.spin);
20169+ list_for_each_entry(sbinfo, &au_sbilist.head, si_list)
20170+ if (id == sysaufs_si_id(sbinfo)) {
20171+ kobject_get(&sbinfo->si_kobj);
20172+ sb = sbinfo->si_sb;
20173+ break;
20174+ }
20175+ spin_unlock(&au_sbilist.spin);
20176+
20177+ err = -EINVAL;
20178+ if (unlikely(!sb))
20179+ goto out;
20180+
20181+ err = au_plink_maint_enter(sb);
20182+ if (!err)
20183+ /* keep kobject_get() */
20184+ file->private_data = sbinfo;
20185+ else
20186+ kobject_put(&sbinfo->si_kobj);
20187+out:
20188+ return err;
20189+}
20190+
20191+/*
20192+ * Accept a valid "si=xxxx" only.
20193+ * Once it is accepted successfully, accept "clean" too.
20194+ */
20195+static ssize_t au_procfs_plm_write(struct file *file, const char __user *ubuf,
20196+ size_t count, loff_t *ppos)
20197+{
20198+ ssize_t err;
20199+ unsigned long id;
20200+ /* last newline is allowed */
20201+ char buf[3 + sizeof(unsigned long) * 2 + 1];
20202+
20203+ err = -EACCES;
20204+ if (unlikely(!capable(CAP_SYS_ADMIN)))
20205+ goto out;
20206+
20207+ err = -EINVAL;
20208+ if (unlikely(count > sizeof(buf)))
20209+ goto out;
20210+
20211+ err = copy_from_user(buf, ubuf, count);
20212+ if (unlikely(err)) {
20213+ err = -EFAULT;
20214+ goto out;
20215+ }
20216+ buf[count] = 0;
20217+
20218+ err = -EINVAL;
20219+ if (!strcmp("clean", buf)) {
20220+ au_procfs_plm_write_clean(file);
20221+ goto out_success;
20222+ } else if (unlikely(strncmp("si=", buf, 3)))
20223+ goto out;
20224+
20225+ err = strict_strtoul(buf + 3, 16, &id);
20226+ if (unlikely(err))
20227+ goto out;
20228+
20229+ err = au_procfs_plm_write_si(file, id);
20230+ if (unlikely(err))
20231+ goto out;
20232+
20233+out_success:
20234+ err = count; /* success */
20235+out:
20236+ return err;
20237+}
20238+
20239+static const struct file_operations au_procfs_plm_fop = {
20240+ .write = au_procfs_plm_write,
20241+ .release = au_procfs_plm_release,
20242+ .owner = THIS_MODULE
20243+};
20244+
20245+/* ---------------------------------------------------------------------- */
20246+
20247+static struct proc_dir_entry *au_procfs_dir;
20248+
20249+void au_procfs_fin(void)
20250+{
20251+ remove_proc_entry(AUFS_PLINK_MAINT_NAME, au_procfs_dir);
20252+ remove_proc_entry(AUFS_PLINK_MAINT_DIR, NULL);
20253+}
20254+
20255+int __init au_procfs_init(void)
20256+{
20257+ int err;
20258+ struct proc_dir_entry *entry;
20259+
20260+ err = -ENOMEM;
20261+ au_procfs_dir = proc_mkdir(AUFS_PLINK_MAINT_DIR, NULL);
20262+ if (unlikely(!au_procfs_dir))
20263+ goto out;
20264+
20265+ entry = proc_create(AUFS_PLINK_MAINT_NAME, S_IFREG | S_IWUSR,
20266+ au_procfs_dir, &au_procfs_plm_fop);
20267+ if (unlikely(!entry))
20268+ goto out_dir;
20269+
20270+ err = 0;
20271+ goto out; /* success */
20272+
20273+
20274+out_dir:
20275+ remove_proc_entry(AUFS_PLINK_MAINT_DIR, NULL);
20276+out:
20277+ return err;
20278+}
7f207e10
AM
20279diff -urN /usr/share/empty/fs/aufs/rdu.c linux/fs/aufs/rdu.c
20280--- /usr/share/empty/fs/aufs/rdu.c 1970-01-01 01:00:00.000000000 +0100
87a755f4 20281+++ linux/fs/aufs/rdu.c 2011-03-17 10:46:59.000000000 +0100
027c5e7a 20282@@ -0,0 +1,383 @@
1308ab2a 20283+/*
027c5e7a 20284+ * Copyright (C) 2005-2011 Junjiro R. Okajima
1308ab2a 20285+ *
20286+ * This program, aufs is free software; you can redistribute it and/or modify
20287+ * it under the terms of the GNU General Public License as published by
20288+ * the Free Software Foundation; either version 2 of the License, or
20289+ * (at your option) any later version.
20290+ *
20291+ * This program is distributed in the hope that it will be useful,
20292+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
20293+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20294+ * GNU General Public License for more details.
20295+ *
20296+ * You should have received a copy of the GNU General Public License
20297+ * along with this program; if not, write to the Free Software
20298+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
20299+ */
20300+
20301+/*
20302+ * readdir in userspace.
20303+ */
20304+
b752ccd1 20305+#include <linux/compat.h>
4a4d8108 20306+#include <linux/fs_stack.h>
1308ab2a 20307+#include <linux/security.h>
20308+#include <linux/uaccess.h>
20309+#include <linux/aufs_type.h>
20310+#include "aufs.h"
20311+
20312+/* bits for struct aufs_rdu.flags */
20313+#define AuRdu_CALLED 1
20314+#define AuRdu_CONT (1 << 1)
20315+#define AuRdu_FULL (1 << 2)
20316+#define au_ftest_rdu(flags, name) ((flags) & AuRdu_##name)
7f207e10
AM
20317+#define au_fset_rdu(flags, name) \
20318+ do { (flags) |= AuRdu_##name; } while (0)
20319+#define au_fclr_rdu(flags, name) \
20320+ do { (flags) &= ~AuRdu_##name; } while (0)
1308ab2a 20321+
20322+struct au_rdu_arg {
20323+ struct aufs_rdu *rdu;
20324+ union au_rdu_ent_ul ent;
20325+ unsigned long end;
20326+
20327+ struct super_block *sb;
20328+ int err;
20329+};
20330+
20331+static int au_rdu_fill(void *__arg, const char *name, int nlen,
20332+ loff_t offset, u64 h_ino, unsigned int d_type)
20333+{
20334+ int err, len;
20335+ struct au_rdu_arg *arg = __arg;
20336+ struct aufs_rdu *rdu = arg->rdu;
20337+ struct au_rdu_ent ent;
20338+
20339+ err = 0;
20340+ arg->err = 0;
20341+ au_fset_rdu(rdu->cookie.flags, CALLED);
20342+ len = au_rdu_len(nlen);
20343+ if (arg->ent.ul + len < arg->end) {
20344+ ent.ino = h_ino;
20345+ ent.bindex = rdu->cookie.bindex;
20346+ ent.type = d_type;
20347+ ent.nlen = nlen;
4a4d8108
AM
20348+ if (unlikely(nlen > AUFS_MAX_NAMELEN))
20349+ ent.type = DT_UNKNOWN;
1308ab2a 20350+
20351+ err = -EFAULT;
20352+ if (copy_to_user(arg->ent.e, &ent, sizeof(ent)))
20353+ goto out;
20354+ if (copy_to_user(arg->ent.e->name, name, nlen))
20355+ goto out;
20356+ /* the terminating NULL */
20357+ if (__put_user(0, arg->ent.e->name + nlen))
20358+ goto out;
20359+ err = 0;
20360+ /* AuDbg("%p, %.*s\n", arg->ent.p, nlen, name); */
20361+ arg->ent.ul += len;
20362+ rdu->rent++;
20363+ } else {
20364+ err = -EFAULT;
20365+ au_fset_rdu(rdu->cookie.flags, FULL);
20366+ rdu->full = 1;
20367+ rdu->tail = arg->ent;
20368+ }
20369+
4f0767ce 20370+out:
1308ab2a 20371+ /* AuTraceErr(err); */
20372+ return err;
20373+}
20374+
20375+static int au_rdu_do(struct file *h_file, struct au_rdu_arg *arg)
20376+{
20377+ int err;
20378+ loff_t offset;
20379+ struct au_rdu_cookie *cookie = &arg->rdu->cookie;
20380+
20381+ offset = vfsub_llseek(h_file, cookie->h_pos, SEEK_SET);
20382+ err = offset;
20383+ if (unlikely(offset != cookie->h_pos))
20384+ goto out;
20385+
20386+ err = 0;
20387+ do {
20388+ arg->err = 0;
20389+ au_fclr_rdu(cookie->flags, CALLED);
20390+ /* smp_mb(); */
20391+ err = vfsub_readdir(h_file, au_rdu_fill, arg);
20392+ if (err >= 0)
20393+ err = arg->err;
20394+ } while (!err
20395+ && au_ftest_rdu(cookie->flags, CALLED)
20396+ && !au_ftest_rdu(cookie->flags, FULL));
20397+ cookie->h_pos = h_file->f_pos;
20398+
4f0767ce 20399+out:
1308ab2a 20400+ AuTraceErr(err);
20401+ return err;
20402+}
20403+
20404+static int au_rdu(struct file *file, struct aufs_rdu *rdu)
20405+{
20406+ int err;
20407+ aufs_bindex_t bend;
20408+ struct au_rdu_arg arg;
20409+ struct dentry *dentry;
20410+ struct inode *inode;
20411+ struct file *h_file;
20412+ struct au_rdu_cookie *cookie = &rdu->cookie;
20413+
20414+ err = !access_ok(VERIFY_WRITE, rdu->ent.e, rdu->sz);
20415+ if (unlikely(err)) {
20416+ err = -EFAULT;
20417+ AuTraceErr(err);
20418+ goto out;
20419+ }
20420+ rdu->rent = 0;
20421+ rdu->tail = rdu->ent;
20422+ rdu->full = 0;
20423+ arg.rdu = rdu;
20424+ arg.ent = rdu->ent;
20425+ arg.end = arg.ent.ul;
20426+ arg.end += rdu->sz;
20427+
20428+ err = -ENOTDIR;
20429+ if (unlikely(!file->f_op || !file->f_op->readdir))
20430+ goto out;
20431+
20432+ err = security_file_permission(file, MAY_READ);
20433+ AuTraceErr(err);
20434+ if (unlikely(err))
20435+ goto out;
20436+
20437+ dentry = file->f_dentry;
20438+ inode = dentry->d_inode;
20439+#if 1
20440+ mutex_lock(&inode->i_mutex);
20441+#else
20442+ err = mutex_lock_killable(&inode->i_mutex);
20443+ AuTraceErr(err);
20444+ if (unlikely(err))
20445+ goto out;
20446+#endif
1308ab2a 20447+
20448+ arg.sb = inode->i_sb;
e49829fe
JR
20449+ err = si_read_lock(arg.sb, AuLock_FLUSH | AuLock_NOPLM);
20450+ if (unlikely(err))
20451+ goto out_mtx;
027c5e7a
AM
20452+ err = au_alive_dir(dentry);
20453+ if (unlikely(err))
20454+ goto out_si;
e49829fe 20455+ /* todo: reval? */
1308ab2a 20456+ fi_read_lock(file);
20457+
20458+ err = -EAGAIN;
20459+ if (unlikely(au_ftest_rdu(cookie->flags, CONT)
20460+ && cookie->generation != au_figen(file)))
20461+ goto out_unlock;
20462+
20463+ err = 0;
20464+ if (!rdu->blk) {
20465+ rdu->blk = au_sbi(arg.sb)->si_rdblk;
20466+ if (!rdu->blk)
20467+ rdu->blk = au_dir_size(file, /*dentry*/NULL);
20468+ }
20469+ bend = au_fbstart(file);
20470+ if (cookie->bindex < bend)
20471+ cookie->bindex = bend;
4a4d8108 20472+ bend = au_fbend_dir(file);
1308ab2a 20473+ /* AuDbg("b%d, b%d\n", cookie->bindex, bend); */
20474+ for (; !err && cookie->bindex <= bend;
20475+ cookie->bindex++, cookie->h_pos = 0) {
4a4d8108 20476+ h_file = au_hf_dir(file, cookie->bindex);
1308ab2a 20477+ if (!h_file)
20478+ continue;
20479+
20480+ au_fclr_rdu(cookie->flags, FULL);
20481+ err = au_rdu_do(h_file, &arg);
20482+ AuTraceErr(err);
20483+ if (unlikely(au_ftest_rdu(cookie->flags, FULL) || err))
20484+ break;
20485+ }
20486+ AuDbg("rent %llu\n", rdu->rent);
20487+
20488+ if (!err && !au_ftest_rdu(cookie->flags, CONT)) {
20489+ rdu->shwh = !!au_opt_test(au_sbi(arg.sb)->si_mntflags, SHWH);
20490+ au_fset_rdu(cookie->flags, CONT);
20491+ cookie->generation = au_figen(file);
20492+ }
20493+
20494+ ii_read_lock_child(inode);
20495+ fsstack_copy_attr_atime(inode, au_h_iptr(inode, au_ibstart(inode)));
20496+ ii_read_unlock(inode);
20497+
4f0767ce 20498+out_unlock:
1308ab2a 20499+ fi_read_unlock(file);
027c5e7a 20500+out_si:
1308ab2a 20501+ si_read_unlock(arg.sb);
4f0767ce 20502+out_mtx:
1308ab2a 20503+ mutex_unlock(&inode->i_mutex);
4f0767ce 20504+out:
1308ab2a 20505+ AuTraceErr(err);
20506+ return err;
20507+}
20508+
20509+static int au_rdu_ino(struct file *file, struct aufs_rdu *rdu)
20510+{
20511+ int err;
20512+ ino_t ino;
20513+ unsigned long long nent;
20514+ union au_rdu_ent_ul *u;
20515+ struct au_rdu_ent ent;
20516+ struct super_block *sb;
20517+
20518+ err = 0;
20519+ nent = rdu->nent;
20520+ u = &rdu->ent;
20521+ sb = file->f_dentry->d_sb;
20522+ si_read_lock(sb, AuLock_FLUSH);
20523+ while (nent-- > 0) {
1308ab2a 20524+ err = copy_from_user(&ent, u->e, sizeof(ent));
4a4d8108
AM
20525+ if (!err)
20526+ err = !access_ok(VERIFY_WRITE, &u->e->ino, sizeof(ino));
1308ab2a 20527+ if (unlikely(err)) {
20528+ err = -EFAULT;
20529+ AuTraceErr(err);
20530+ break;
20531+ }
20532+
20533+ /* AuDbg("b%d, i%llu\n", ent.bindex, ent.ino); */
20534+ if (!ent.wh)
20535+ err = au_ino(sb, ent.bindex, ent.ino, ent.type, &ino);
20536+ else
20537+ err = au_wh_ino(sb, ent.bindex, ent.ino, ent.type,
20538+ &ino);
20539+ if (unlikely(err)) {
20540+ AuTraceErr(err);
20541+ break;
20542+ }
20543+
20544+ err = __put_user(ino, &u->e->ino);
20545+ if (unlikely(err)) {
20546+ err = -EFAULT;
20547+ AuTraceErr(err);
20548+ break;
20549+ }
20550+ u->ul += au_rdu_len(ent.nlen);
20551+ }
20552+ si_read_unlock(sb);
20553+
20554+ return err;
20555+}
20556+
20557+/* ---------------------------------------------------------------------- */
20558+
20559+static int au_rdu_verify(struct aufs_rdu *rdu)
20560+{
b752ccd1 20561+ AuDbg("rdu{%llu, %p, %u | %u | %llu, %u, %u | "
1308ab2a 20562+ "%llu, b%d, 0x%x, g%u}\n",
b752ccd1 20563+ rdu->sz, rdu->ent.e, rdu->verify[AufsCtlRduV_SZ],
1308ab2a 20564+ rdu->blk,
20565+ rdu->rent, rdu->shwh, rdu->full,
20566+ rdu->cookie.h_pos, rdu->cookie.bindex, rdu->cookie.flags,
20567+ rdu->cookie.generation);
dece6358 20568+
b752ccd1 20569+ if (rdu->verify[AufsCtlRduV_SZ] == sizeof(*rdu))
1308ab2a 20570+ return 0;
dece6358 20571+
b752ccd1
AM
20572+ AuDbg("%u:%u\n",
20573+ rdu->verify[AufsCtlRduV_SZ], (unsigned int)sizeof(*rdu));
1308ab2a 20574+ return -EINVAL;
20575+}
20576+
20577+long au_rdu_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
dece6358 20578+{
1308ab2a 20579+ long err, e;
20580+ struct aufs_rdu rdu;
20581+ void __user *p = (void __user *)arg;
dece6358 20582+
1308ab2a 20583+ err = copy_from_user(&rdu, p, sizeof(rdu));
20584+ if (unlikely(err)) {
20585+ err = -EFAULT;
20586+ AuTraceErr(err);
20587+ goto out;
20588+ }
20589+ err = au_rdu_verify(&rdu);
dece6358
AM
20590+ if (unlikely(err))
20591+ goto out;
20592+
1308ab2a 20593+ switch (cmd) {
20594+ case AUFS_CTL_RDU:
20595+ err = au_rdu(file, &rdu);
20596+ if (unlikely(err))
20597+ break;
dece6358 20598+
1308ab2a 20599+ e = copy_to_user(p, &rdu, sizeof(rdu));
20600+ if (unlikely(e)) {
20601+ err = -EFAULT;
20602+ AuTraceErr(err);
20603+ }
20604+ break;
20605+ case AUFS_CTL_RDU_INO:
20606+ err = au_rdu_ino(file, &rdu);
20607+ break;
20608+
20609+ default:
4a4d8108 20610+ /* err = -ENOTTY; */
1308ab2a 20611+ err = -EINVAL;
20612+ }
dece6358 20613+
4f0767ce 20614+out:
1308ab2a 20615+ AuTraceErr(err);
20616+ return err;
1facf9fc 20617+}
b752ccd1
AM
20618+
20619+#ifdef CONFIG_COMPAT
20620+long au_rdu_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
20621+{
20622+ long err, e;
20623+ struct aufs_rdu rdu;
20624+ void __user *p = compat_ptr(arg);
20625+
20626+ /* todo: get_user()? */
20627+ err = copy_from_user(&rdu, p, sizeof(rdu));
20628+ if (unlikely(err)) {
20629+ err = -EFAULT;
20630+ AuTraceErr(err);
20631+ goto out;
20632+ }
20633+ rdu.ent.e = compat_ptr(rdu.ent.ul);
20634+ err = au_rdu_verify(&rdu);
20635+ if (unlikely(err))
20636+ goto out;
20637+
20638+ switch (cmd) {
20639+ case AUFS_CTL_RDU:
20640+ err = au_rdu(file, &rdu);
20641+ if (unlikely(err))
20642+ break;
20643+
20644+ rdu.ent.ul = ptr_to_compat(rdu.ent.e);
20645+ rdu.tail.ul = ptr_to_compat(rdu.tail.e);
20646+ e = copy_to_user(p, &rdu, sizeof(rdu));
20647+ if (unlikely(e)) {
20648+ err = -EFAULT;
20649+ AuTraceErr(err);
20650+ }
20651+ break;
20652+ case AUFS_CTL_RDU_INO:
20653+ err = au_rdu_ino(file, &rdu);
20654+ break;
20655+
20656+ default:
20657+ /* err = -ENOTTY; */
20658+ err = -EINVAL;
20659+ }
20660+
4f0767ce 20661+out:
b752ccd1
AM
20662+ AuTraceErr(err);
20663+ return err;
20664+}
20665+#endif
7f207e10
AM
20666diff -urN /usr/share/empty/fs/aufs/rwsem.h linux/fs/aufs/rwsem.h
20667--- /usr/share/empty/fs/aufs/rwsem.h 1970-01-01 01:00:00.000000000 +0100
87a755f4 20668+++ linux/fs/aufs/rwsem.h 2011-03-17 10:46:59.000000000 +0100
e49829fe 20669@@ -0,0 +1,189 @@
1facf9fc 20670+/*
027c5e7a 20671+ * Copyright (C) 2005-2011 Junjiro R. Okajima
1facf9fc 20672+ *
20673+ * This program, aufs is free software; you can redistribute it and/or modify
20674+ * it under the terms of the GNU General Public License as published by
20675+ * the Free Software Foundation; either version 2 of the License, or
20676+ * (at your option) any later version.
dece6358
AM
20677+ *
20678+ * This program is distributed in the hope that it will be useful,
20679+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
20680+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20681+ * GNU General Public License for more details.
20682+ *
20683+ * You should have received a copy of the GNU General Public License
20684+ * along with this program; if not, write to the Free Software
20685+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 20686+ */
20687+
20688+/*
20689+ * simple read-write semaphore wrappers
20690+ */
20691+
20692+#ifndef __AUFS_RWSEM_H__
20693+#define __AUFS_RWSEM_H__
20694+
20695+#ifdef __KERNEL__
20696+
dece6358 20697+#include <linux/rwsem.h>
4a4d8108 20698+#include "debug.h"
dece6358
AM
20699+
20700+struct au_rwsem {
20701+ struct rw_semaphore rwsem;
20702+#ifdef CONFIG_AUFS_DEBUG
20703+ /* just for debugging, not almighty counter */
20704+ atomic_t rcnt, wcnt;
20705+#endif
20706+};
20707+
20708+#ifdef CONFIG_AUFS_DEBUG
20709+#define AuDbgCntInit(rw) do { \
20710+ atomic_set(&(rw)->rcnt, 0); \
20711+ atomic_set(&(rw)->wcnt, 0); \
20712+ smp_mb(); /* atomic set */ \
20713+} while (0)
20714+
e49829fe 20715+#define AuDbgRcntInc(rw) atomic_inc(&(rw)->rcnt)
dece6358 20716+#define AuDbgRcntDec(rw) WARN_ON(atomic_dec_return(&(rw)->rcnt) < 0)
e49829fe 20717+#define AuDbgWcntInc(rw) atomic_inc(&(rw)->wcnt)
dece6358
AM
20718+#define AuDbgWcntDec(rw) WARN_ON(atomic_dec_return(&(rw)->wcnt) < 0)
20719+#else
20720+#define AuDbgCntInit(rw) do {} while (0)
20721+#define AuDbgRcntInc(rw) do {} while (0)
20722+#define AuDbgRcntDec(rw) do {} while (0)
20723+#define AuDbgWcntInc(rw) do {} while (0)
20724+#define AuDbgWcntDec(rw) do {} while (0)
20725+#endif /* CONFIG_AUFS_DEBUG */
20726+
20727+/* to debug easier, do not make them inlined functions */
20728+#define AuRwMustNoWaiters(rw) AuDebugOn(!list_empty(&(rw)->rwsem.wait_list))
20729+/* rwsem_is_locked() is unusable */
20730+#define AuRwMustReadLock(rw) AuDebugOn(atomic_read(&(rw)->rcnt) <= 0)
20731+#define AuRwMustWriteLock(rw) AuDebugOn(atomic_read(&(rw)->wcnt) <= 0)
20732+#define AuRwMustAnyLock(rw) AuDebugOn(atomic_read(&(rw)->rcnt) <= 0 \
20733+ && atomic_read(&(rw)->wcnt) <= 0)
20734+#define AuRwDestroy(rw) AuDebugOn(atomic_read(&(rw)->rcnt) \
20735+ || atomic_read(&(rw)->wcnt))
20736+
e49829fe
JR
20737+#define au_rw_class(rw, key) lockdep_set_class(&(rw)->rwsem, key)
20738+
dece6358
AM
20739+static inline void au_rw_init(struct au_rwsem *rw)
20740+{
20741+ AuDbgCntInit(rw);
20742+ init_rwsem(&rw->rwsem);
20743+}
20744+
20745+static inline void au_rw_init_wlock(struct au_rwsem *rw)
20746+{
20747+ au_rw_init(rw);
20748+ down_write(&rw->rwsem);
20749+ AuDbgWcntInc(rw);
20750+}
20751+
20752+static inline void au_rw_init_wlock_nested(struct au_rwsem *rw,
20753+ unsigned int lsc)
20754+{
20755+ au_rw_init(rw);
20756+ down_write_nested(&rw->rwsem, lsc);
20757+ AuDbgWcntInc(rw);
20758+}
20759+
20760+static inline void au_rw_read_lock(struct au_rwsem *rw)
20761+{
20762+ down_read(&rw->rwsem);
20763+ AuDbgRcntInc(rw);
20764+}
20765+
20766+static inline void au_rw_read_lock_nested(struct au_rwsem *rw, unsigned int lsc)
20767+{
20768+ down_read_nested(&rw->rwsem, lsc);
20769+ AuDbgRcntInc(rw);
20770+}
20771+
20772+static inline void au_rw_read_unlock(struct au_rwsem *rw)
20773+{
20774+ AuRwMustReadLock(rw);
20775+ AuDbgRcntDec(rw);
20776+ up_read(&rw->rwsem);
20777+}
20778+
20779+static inline void au_rw_dgrade_lock(struct au_rwsem *rw)
20780+{
20781+ AuRwMustWriteLock(rw);
20782+ AuDbgRcntInc(rw);
20783+ AuDbgWcntDec(rw);
20784+ downgrade_write(&rw->rwsem);
20785+}
20786+
20787+static inline void au_rw_write_lock(struct au_rwsem *rw)
20788+{
20789+ down_write(&rw->rwsem);
20790+ AuDbgWcntInc(rw);
20791+}
20792+
20793+static inline void au_rw_write_lock_nested(struct au_rwsem *rw,
20794+ unsigned int lsc)
20795+{
20796+ down_write_nested(&rw->rwsem, lsc);
20797+ AuDbgWcntInc(rw);
20798+}
1facf9fc 20799+
dece6358
AM
20800+static inline void au_rw_write_unlock(struct au_rwsem *rw)
20801+{
20802+ AuRwMustWriteLock(rw);
20803+ AuDbgWcntDec(rw);
20804+ up_write(&rw->rwsem);
20805+}
20806+
20807+/* why is not _nested version defined */
20808+static inline int au_rw_read_trylock(struct au_rwsem *rw)
20809+{
20810+ int ret = down_read_trylock(&rw->rwsem);
20811+ if (ret)
20812+ AuDbgRcntInc(rw);
20813+ return ret;
20814+}
20815+
20816+static inline int au_rw_write_trylock(struct au_rwsem *rw)
20817+{
20818+ int ret = down_write_trylock(&rw->rwsem);
20819+ if (ret)
20820+ AuDbgWcntInc(rw);
20821+ return ret;
20822+}
20823+
20824+#undef AuDbgCntInit
20825+#undef AuDbgRcntInc
20826+#undef AuDbgRcntDec
20827+#undef AuDbgWcntInc
20828+#undef AuDbgWcntDec
1facf9fc 20829+
20830+#define AuSimpleLockRwsemFuncs(prefix, param, rwsem) \
20831+static inline void prefix##_read_lock(param) \
dece6358 20832+{ au_rw_read_lock(rwsem); } \
1facf9fc 20833+static inline void prefix##_write_lock(param) \
dece6358 20834+{ au_rw_write_lock(rwsem); } \
1facf9fc 20835+static inline int prefix##_read_trylock(param) \
dece6358 20836+{ return au_rw_read_trylock(rwsem); } \
1facf9fc 20837+static inline int prefix##_write_trylock(param) \
dece6358 20838+{ return au_rw_write_trylock(rwsem); }
1facf9fc 20839+/* why is not _nested version defined */
20840+/* static inline void prefix##_read_trylock_nested(param, lsc)
dece6358 20841+{ au_rw_read_trylock_nested(rwsem, lsc)); }
1facf9fc 20842+static inline void prefix##_write_trylock_nestd(param, lsc)
dece6358 20843+{ au_rw_write_trylock_nested(rwsem, lsc); } */
1facf9fc 20844+
20845+#define AuSimpleUnlockRwsemFuncs(prefix, param, rwsem) \
20846+static inline void prefix##_read_unlock(param) \
dece6358 20847+{ au_rw_read_unlock(rwsem); } \
1facf9fc 20848+static inline void prefix##_write_unlock(param) \
dece6358 20849+{ au_rw_write_unlock(rwsem); } \
1facf9fc 20850+static inline void prefix##_downgrade_lock(param) \
dece6358 20851+{ au_rw_dgrade_lock(rwsem); }
1facf9fc 20852+
20853+#define AuSimpleRwsemFuncs(prefix, param, rwsem) \
20854+ AuSimpleLockRwsemFuncs(prefix, param, rwsem) \
20855+ AuSimpleUnlockRwsemFuncs(prefix, param, rwsem)
20856+
20857+#endif /* __KERNEL__ */
20858+#endif /* __AUFS_RWSEM_H__ */
7f207e10
AM
20859diff -urN /usr/share/empty/fs/aufs/sbinfo.c linux/fs/aufs/sbinfo.c
20860--- /usr/share/empty/fs/aufs/sbinfo.c 1970-01-01 01:00:00.000000000 +0100
87a755f4 20861+++ linux/fs/aufs/sbinfo.c 2011-03-17 10:46:59.000000000 +0100
027c5e7a 20862@@ -0,0 +1,344 @@
1facf9fc 20863+/*
027c5e7a 20864+ * Copyright (C) 2005-2011 Junjiro R. Okajima
1facf9fc 20865+ *
20866+ * This program, aufs is free software; you can redistribute it and/or modify
20867+ * it under the terms of the GNU General Public License as published by
20868+ * the Free Software Foundation; either version 2 of the License, or
20869+ * (at your option) any later version.
dece6358
AM
20870+ *
20871+ * This program is distributed in the hope that it will be useful,
20872+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
20873+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20874+ * GNU General Public License for more details.
20875+ *
20876+ * You should have received a copy of the GNU General Public License
20877+ * along with this program; if not, write to the Free Software
20878+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 20879+ */
20880+
20881+/*
20882+ * superblock private data
20883+ */
20884+
e49829fe 20885+#include <linux/jiffies.h>
1facf9fc 20886+#include "aufs.h"
20887+
20888+/*
20889+ * they are necessary regardless sysfs is disabled.
20890+ */
20891+void au_si_free(struct kobject *kobj)
20892+{
20893+ struct au_sbinfo *sbinfo;
b752ccd1 20894+ char *locked __maybe_unused; /* debug only */
1facf9fc 20895+
20896+ sbinfo = container_of(kobj, struct au_sbinfo, si_kobj);
20897+ AuDebugOn(!list_empty(&sbinfo->si_plink.head));
e49829fe 20898+ AuDebugOn(atomic_read(&sbinfo->si_nowait.nw_len));
1facf9fc 20899+
e49829fe 20900+ au_rw_write_lock(&sbinfo->si_rwsem);
1facf9fc 20901+ au_br_free(sbinfo);
e49829fe 20902+ au_rw_write_unlock(&sbinfo->si_rwsem);
b752ccd1
AM
20903+
20904+ AuDebugOn(radix_tree_gang_lookup
20905+ (&sbinfo->au_si_pid.tree, (void **)&locked,
20906+ /*first_index*/PID_MAX_DEFAULT - 1,
20907+ /*max_items*/sizeof(locked)/sizeof(*locked)));
20908+
1facf9fc 20909+ kfree(sbinfo->si_branch);
b752ccd1 20910+ kfree(sbinfo->au_si_pid.bitmap);
1facf9fc 20911+ mutex_destroy(&sbinfo->si_xib_mtx);
dece6358 20912+ AuRwDestroy(&sbinfo->si_rwsem);
1facf9fc 20913+
20914+ kfree(sbinfo);
20915+}
20916+
20917+int au_si_alloc(struct super_block *sb)
20918+{
20919+ int err;
20920+ struct au_sbinfo *sbinfo;
e49829fe 20921+ static struct lock_class_key aufs_si;
1facf9fc 20922+
20923+ err = -ENOMEM;
4a4d8108 20924+ sbinfo = kzalloc(sizeof(*sbinfo), GFP_NOFS);
1facf9fc 20925+ if (unlikely(!sbinfo))
20926+ goto out;
20927+
b752ccd1
AM
20928+ BUILD_BUG_ON(sizeof(unsigned long) !=
20929+ sizeof(*sbinfo->au_si_pid.bitmap));
20930+ sbinfo->au_si_pid.bitmap = kcalloc(BITS_TO_LONGS(PID_MAX_DEFAULT),
20931+ sizeof(*sbinfo->au_si_pid.bitmap),
20932+ GFP_NOFS);
20933+ if (unlikely(!sbinfo->au_si_pid.bitmap))
20934+ goto out_sbinfo;
20935+
1facf9fc 20936+ /* will be reallocated separately */
20937+ sbinfo->si_branch = kzalloc(sizeof(*sbinfo->si_branch), GFP_NOFS);
20938+ if (unlikely(!sbinfo->si_branch))
b752ccd1 20939+ goto out_pidmap;
1facf9fc 20940+
1facf9fc 20941+ err = sysaufs_si_init(sbinfo);
20942+ if (unlikely(err))
20943+ goto out_br;
20944+
20945+ au_nwt_init(&sbinfo->si_nowait);
dece6358 20946+ au_rw_init_wlock(&sbinfo->si_rwsem);
e49829fe 20947+ au_rw_class(&sbinfo->si_rwsem, &aufs_si);
b752ccd1
AM
20948+ spin_lock_init(&sbinfo->au_si_pid.tree_lock);
20949+ INIT_RADIX_TREE(&sbinfo->au_si_pid.tree, GFP_ATOMIC | __GFP_NOFAIL);
20950+
7f207e10 20951+ atomic_long_set(&sbinfo->si_ninodes, 0);
7f207e10
AM
20952+ atomic_long_set(&sbinfo->si_nfiles, 0);
20953+
1facf9fc 20954+ sbinfo->si_bend = -1;
1facf9fc 20955+
20956+ sbinfo->si_wbr_copyup = AuWbrCopyup_Def;
20957+ sbinfo->si_wbr_create = AuWbrCreate_Def;
4a4d8108
AM
20958+ sbinfo->si_wbr_copyup_ops = au_wbr_copyup_ops + sbinfo->si_wbr_copyup;
20959+ sbinfo->si_wbr_create_ops = au_wbr_create_ops + sbinfo->si_wbr_create;
1facf9fc 20960+
e49829fe 20961+ sbinfo->si_mntflags = au_opts_plink(AuOpt_Def);
1facf9fc 20962+
1facf9fc 20963+ mutex_init(&sbinfo->si_xib_mtx);
1facf9fc 20964+ sbinfo->si_xino_brid = -1;
20965+ /* leave si_xib_last_pindex and si_xib_next_bit */
20966+
e49829fe 20967+ sbinfo->si_rdcache = msecs_to_jiffies(AUFS_RDCACHE_DEF * MSEC_PER_SEC);
1facf9fc 20968+ sbinfo->si_rdblk = AUFS_RDBLK_DEF;
20969+ sbinfo->si_rdhash = AUFS_RDHASH_DEF;
20970+ sbinfo->si_dirwh = AUFS_DIRWH_DEF;
20971+
20972+ au_spl_init(&sbinfo->si_plink);
20973+ init_waitqueue_head(&sbinfo->si_plink_wq);
4a4d8108 20974+ spin_lock_init(&sbinfo->si_plink_maint_lock);
1facf9fc 20975+
20976+ /* leave other members for sysaufs and si_mnt. */
20977+ sbinfo->si_sb = sb;
20978+ sb->s_fs_info = sbinfo;
b752ccd1 20979+ si_pid_set(sb);
1facf9fc 20980+ au_debug_sbinfo_init(sbinfo);
20981+ return 0; /* success */
20982+
4f0767ce 20983+out_br:
1facf9fc 20984+ kfree(sbinfo->si_branch);
4f0767ce 20985+out_pidmap:
b752ccd1 20986+ kfree(sbinfo->au_si_pid.bitmap);
4f0767ce 20987+out_sbinfo:
1facf9fc 20988+ kfree(sbinfo);
4f0767ce 20989+out:
1facf9fc 20990+ return err;
20991+}
20992+
20993+int au_sbr_realloc(struct au_sbinfo *sbinfo, int nbr)
20994+{
20995+ int err, sz;
20996+ struct au_branch **brp;
20997+
dece6358
AM
20998+ AuRwMustWriteLock(&sbinfo->si_rwsem);
20999+
1facf9fc 21000+ err = -ENOMEM;
21001+ sz = sizeof(*brp) * (sbinfo->si_bend + 1);
21002+ if (unlikely(!sz))
21003+ sz = sizeof(*brp);
21004+ brp = au_kzrealloc(sbinfo->si_branch, sz, sizeof(*brp) * nbr, GFP_NOFS);
21005+ if (brp) {
21006+ sbinfo->si_branch = brp;
21007+ err = 0;
21008+ }
21009+
21010+ return err;
21011+}
21012+
21013+/* ---------------------------------------------------------------------- */
21014+
21015+unsigned int au_sigen_inc(struct super_block *sb)
21016+{
21017+ unsigned int gen;
21018+
dece6358
AM
21019+ SiMustWriteLock(sb);
21020+
1facf9fc 21021+ gen = ++au_sbi(sb)->si_generation;
21022+ au_update_digen(sb->s_root);
21023+ au_update_iigen(sb->s_root->d_inode);
21024+ sb->s_root->d_inode->i_version++;
21025+ return gen;
21026+}
21027+
21028+aufs_bindex_t au_new_br_id(struct super_block *sb)
21029+{
21030+ aufs_bindex_t br_id;
21031+ int i;
21032+ struct au_sbinfo *sbinfo;
21033+
dece6358
AM
21034+ SiMustWriteLock(sb);
21035+
1facf9fc 21036+ sbinfo = au_sbi(sb);
21037+ for (i = 0; i <= AUFS_BRANCH_MAX; i++) {
21038+ br_id = ++sbinfo->si_last_br_id;
7f207e10 21039+ AuDebugOn(br_id < 0);
1facf9fc 21040+ if (br_id && au_br_index(sb, br_id) < 0)
21041+ return br_id;
21042+ }
21043+
21044+ return -1;
21045+}
21046+
21047+/* ---------------------------------------------------------------------- */
21048+
e49829fe
JR
21049+/* it is ok that new 'nwt' tasks are appended while we are sleeping */
21050+int si_read_lock(struct super_block *sb, int flags)
21051+{
21052+ int err;
21053+
21054+ err = 0;
21055+ if (au_ftest_lock(flags, FLUSH))
21056+ au_nwt_flush(&au_sbi(sb)->si_nowait);
21057+
21058+ si_noflush_read_lock(sb);
21059+ err = au_plink_maint(sb, flags);
21060+ if (unlikely(err))
21061+ si_read_unlock(sb);
21062+
21063+ return err;
21064+}
21065+
21066+int si_write_lock(struct super_block *sb, int flags)
21067+{
21068+ int err;
21069+
21070+ if (au_ftest_lock(flags, FLUSH))
21071+ au_nwt_flush(&au_sbi(sb)->si_nowait);
21072+
21073+ si_noflush_write_lock(sb);
21074+ err = au_plink_maint(sb, flags);
21075+ if (unlikely(err))
21076+ si_write_unlock(sb);
21077+
21078+ return err;
21079+}
21080+
1facf9fc 21081+/* dentry and super_block lock. call at entry point */
e49829fe 21082+int aufs_read_lock(struct dentry *dentry, int flags)
1facf9fc 21083+{
e49829fe 21084+ int err;
027c5e7a 21085+ struct super_block *sb;
e49829fe 21086+
027c5e7a
AM
21087+ sb = dentry->d_sb;
21088+ err = si_read_lock(sb, flags);
21089+ if (unlikely(err))
21090+ goto out;
21091+
21092+ if (au_ftest_lock(flags, DW))
21093+ di_write_lock_child(dentry);
21094+ else
21095+ di_read_lock_child(dentry, flags);
21096+
21097+ if (au_ftest_lock(flags, GEN)) {
21098+ err = au_digen_test(dentry, au_sigen(sb));
21099+ AuDebugOn(!err && au_dbrange_test(dentry));
21100+ if (unlikely(err))
21101+ aufs_read_unlock(dentry, flags);
e49829fe
JR
21102+ }
21103+
027c5e7a 21104+out:
e49829fe 21105+ return err;
1facf9fc 21106+}
21107+
21108+void aufs_read_unlock(struct dentry *dentry, int flags)
21109+{
21110+ if (au_ftest_lock(flags, DW))
21111+ di_write_unlock(dentry);
21112+ else
21113+ di_read_unlock(dentry, flags);
21114+ si_read_unlock(dentry->d_sb);
21115+}
21116+
21117+void aufs_write_lock(struct dentry *dentry)
21118+{
e49829fe 21119+ si_write_lock(dentry->d_sb, AuLock_FLUSH | AuLock_NOPLMW);
1facf9fc 21120+ di_write_lock_child(dentry);
21121+}
21122+
21123+void aufs_write_unlock(struct dentry *dentry)
21124+{
21125+ di_write_unlock(dentry);
21126+ si_write_unlock(dentry->d_sb);
21127+}
21128+
e49829fe 21129+int aufs_read_and_write_lock2(struct dentry *d1, struct dentry *d2, int flags)
1facf9fc 21130+{
e49829fe 21131+ int err;
027c5e7a
AM
21132+ unsigned int sigen;
21133+ struct super_block *sb;
e49829fe 21134+
027c5e7a
AM
21135+ sb = d1->d_sb;
21136+ err = si_read_lock(sb, flags);
21137+ if (unlikely(err))
21138+ goto out;
21139+
21140+ di_write_lock2_child(d1, d2, au_ftest_lock(flags, DIR));
21141+
21142+ if (au_ftest_lock(flags, GEN)) {
21143+ sigen = au_sigen(sb);
21144+ err = au_digen_test(d1, sigen);
21145+ AuDebugOn(!err && au_dbrange_test(d1));
21146+ if (!err) {
21147+ err = au_digen_test(d2, sigen);
21148+ AuDebugOn(!err && au_dbrange_test(d2));
21149+ }
21150+ if (unlikely(err))
21151+ aufs_read_and_write_unlock2(d1, d2);
21152+ }
21153+
21154+out:
e49829fe 21155+ return err;
1facf9fc 21156+}
21157+
21158+void aufs_read_and_write_unlock2(struct dentry *d1, struct dentry *d2)
21159+{
21160+ di_write_unlock2(d1, d2);
21161+ si_read_unlock(d1->d_sb);
21162+}
b752ccd1
AM
21163+
21164+/* ---------------------------------------------------------------------- */
21165+
21166+int si_pid_test_slow(struct super_block *sb)
21167+{
21168+ void *p;
21169+
21170+ rcu_read_lock();
21171+ p = radix_tree_lookup(&au_sbi(sb)->au_si_pid.tree, current->pid);
21172+ rcu_read_unlock();
21173+
027c5e7a 21174+ return (long)!!p;
b752ccd1
AM
21175+}
21176+
21177+void si_pid_set_slow(struct super_block *sb)
21178+{
21179+ int err;
21180+ struct au_sbinfo *sbinfo;
21181+
21182+ AuDebugOn(si_pid_test_slow(sb));
21183+
21184+ sbinfo = au_sbi(sb);
21185+ err = radix_tree_preload(GFP_NOFS | __GFP_NOFAIL);
21186+ AuDebugOn(err);
21187+ spin_lock(&sbinfo->au_si_pid.tree_lock);
21188+ err = radix_tree_insert(&sbinfo->au_si_pid.tree, current->pid,
027c5e7a 21189+ /*any valid ptr*/sb);
b752ccd1
AM
21190+ spin_unlock(&sbinfo->au_si_pid.tree_lock);
21191+ AuDebugOn(err);
21192+ radix_tree_preload_end();
21193+}
21194+
21195+void si_pid_clr_slow(struct super_block *sb)
21196+{
21197+ void *p;
21198+ struct au_sbinfo *sbinfo;
21199+
21200+ AuDebugOn(!si_pid_test_slow(sb));
21201+
21202+ sbinfo = au_sbi(sb);
21203+ spin_lock(&sbinfo->au_si_pid.tree_lock);
21204+ p = radix_tree_delete(&sbinfo->au_si_pid.tree, current->pid);
21205+ spin_unlock(&sbinfo->au_si_pid.tree_lock);
b752ccd1 21206+}
7f207e10
AM
21207diff -urN /usr/share/empty/fs/aufs/spl.h linux/fs/aufs/spl.h
21208--- /usr/share/empty/fs/aufs/spl.h 1970-01-01 01:00:00.000000000 +0100
87a755f4 21209+++ linux/fs/aufs/spl.h 2011-03-17 10:46:59.000000000 +0100
4a4d8108 21210@@ -0,0 +1,66 @@
1facf9fc 21211+/*
027c5e7a 21212+ * Copyright (C) 2005-2011 Junjiro R. Okajima
1facf9fc 21213+ *
21214+ * This program, aufs is free software; you can redistribute it and/or modify
21215+ * it under the terms of the GNU General Public License as published by
21216+ * the Free Software Foundation; either version 2 of the License, or
21217+ * (at your option) any later version.
dece6358
AM
21218+ *
21219+ * This program is distributed in the hope that it will be useful,
21220+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
21221+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21222+ * GNU General Public License for more details.
21223+ *
21224+ * You should have received a copy of the GNU General Public License
21225+ * along with this program; if not, write to the Free Software
21226+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 21227+ */
21228+
21229+/*
21230+ * simple list protected by a spinlock
21231+ */
21232+
21233+#ifndef __AUFS_SPL_H__
21234+#define __AUFS_SPL_H__
21235+
21236+#ifdef __KERNEL__
21237+
dece6358
AM
21238+#include <linux/spinlock.h>
21239+#include <linux/list.h>
4a4d8108 21240+#include <linux/rculist.h>
1facf9fc 21241+
21242+struct au_splhead {
21243+ spinlock_t spin;
21244+ struct list_head head;
21245+};
21246+
21247+static inline void au_spl_init(struct au_splhead *spl)
21248+{
21249+ spin_lock_init(&spl->spin);
21250+ INIT_LIST_HEAD(&spl->head);
21251+}
21252+
21253+static inline void au_spl_add(struct list_head *list, struct au_splhead *spl)
21254+{
21255+ spin_lock(&spl->spin);
21256+ list_add(list, &spl->head);
21257+ spin_unlock(&spl->spin);
21258+}
21259+
21260+static inline void au_spl_del(struct list_head *list, struct au_splhead *spl)
21261+{
21262+ spin_lock(&spl->spin);
21263+ list_del(list);
21264+ spin_unlock(&spl->spin);
21265+}
21266+
4a4d8108
AM
21267+static inline void au_spl_del_rcu(struct list_head *list,
21268+ struct au_splhead *spl)
21269+{
21270+ spin_lock(&spl->spin);
21271+ list_del_rcu(list);
21272+ spin_unlock(&spl->spin);
21273+}
21274+
1facf9fc 21275+#endif /* __KERNEL__ */
21276+#endif /* __AUFS_SPL_H__ */
7f207e10
AM
21277diff -urN /usr/share/empty/fs/aufs/super.c linux/fs/aufs/super.c
21278--- /usr/share/empty/fs/aufs/super.c 1970-01-01 01:00:00.000000000 +0100
87a755f4 21279+++ linux/fs/aufs/super.c 2011-07-22 08:26:47.857636522 +0200
2cbb1c4b 21280@@ -0,0 +1,930 @@
1facf9fc 21281+/*
027c5e7a 21282+ * Copyright (C) 2005-2011 Junjiro R. Okajima
1facf9fc 21283+ *
21284+ * This program, aufs is free software; you can redistribute it and/or modify
21285+ * it under the terms of the GNU General Public License as published by
21286+ * the Free Software Foundation; either version 2 of the License, or
21287+ * (at your option) any later version.
dece6358
AM
21288+ *
21289+ * This program is distributed in the hope that it will be useful,
21290+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
21291+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21292+ * GNU General Public License for more details.
21293+ *
21294+ * You should have received a copy of the GNU General Public License
21295+ * along with this program; if not, write to the Free Software
21296+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 21297+ */
21298+
21299+/*
21300+ * mount and super_block operations
21301+ */
21302+
21303+#include <linux/buffer_head.h>
e49829fe 21304+#include <linux/jiffies.h>
dece6358 21305+#include <linux/module.h>
1facf9fc 21306+#include <linux/seq_file.h>
21307+#include <linux/statfs.h>
7f207e10
AM
21308+#include <linux/vmalloc.h>
21309+#include <linux/writeback.h>
1facf9fc 21310+#include "aufs.h"
21311+
21312+/*
21313+ * super_operations
21314+ */
21315+static struct inode *aufs_alloc_inode(struct super_block *sb __maybe_unused)
21316+{
21317+ struct au_icntnr *c;
21318+
21319+ c = au_cache_alloc_icntnr();
21320+ if (c) {
027c5e7a 21321+ au_icntnr_init(c);
1facf9fc 21322+ c->vfs_inode.i_version = 1; /* sigen(sb); */
21323+ c->iinfo.ii_hinode = NULL;
21324+ return &c->vfs_inode;
21325+ }
21326+ return NULL;
21327+}
21328+
027c5e7a
AM
21329+static void aufs_destroy_inode_cb(struct rcu_head *head)
21330+{
21331+ struct inode *inode = container_of(head, struct inode, i_rcu);
21332+
21333+ INIT_LIST_HEAD(&inode->i_dentry);
21334+ au_cache_free_icntnr(container_of(inode, struct au_icntnr, vfs_inode));
21335+}
21336+
1facf9fc 21337+static void aufs_destroy_inode(struct inode *inode)
21338+{
21339+ au_iinfo_fin(inode);
027c5e7a 21340+ call_rcu(&inode->i_rcu, aufs_destroy_inode_cb);
1facf9fc 21341+}
21342+
21343+struct inode *au_iget_locked(struct super_block *sb, ino_t ino)
21344+{
21345+ struct inode *inode;
21346+ int err;
21347+
21348+ inode = iget_locked(sb, ino);
21349+ if (unlikely(!inode)) {
21350+ inode = ERR_PTR(-ENOMEM);
21351+ goto out;
21352+ }
21353+ if (!(inode->i_state & I_NEW))
21354+ goto out;
21355+
21356+ err = au_xigen_new(inode);
21357+ if (!err)
21358+ err = au_iinfo_init(inode);
21359+ if (!err)
21360+ inode->i_version++;
21361+ else {
21362+ iget_failed(inode);
21363+ inode = ERR_PTR(err);
21364+ }
21365+
4f0767ce 21366+out:
1facf9fc 21367+ /* never return NULL */
21368+ AuDebugOn(!inode);
21369+ AuTraceErrPtr(inode);
21370+ return inode;
21371+}
21372+
21373+/* lock free root dinfo */
21374+static int au_show_brs(struct seq_file *seq, struct super_block *sb)
21375+{
21376+ int err;
21377+ aufs_bindex_t bindex, bend;
21378+ struct path path;
4a4d8108 21379+ struct au_hdentry *hdp;
1facf9fc 21380+ struct au_branch *br;
21381+
21382+ err = 0;
21383+ bend = au_sbend(sb);
4a4d8108 21384+ hdp = au_di(sb->s_root)->di_hdentry;
1facf9fc 21385+ for (bindex = 0; !err && bindex <= bend; bindex++) {
21386+ br = au_sbr(sb, bindex);
21387+ path.mnt = br->br_mnt;
4a4d8108 21388+ path.dentry = hdp[bindex].hd_dentry;
1facf9fc 21389+ err = au_seq_path(seq, &path);
21390+ if (err > 0)
21391+ err = seq_printf(seq, "=%s",
21392+ au_optstr_br_perm(br->br_perm));
21393+ if (!err && bindex != bend)
21394+ err = seq_putc(seq, ':');
21395+ }
21396+
21397+ return err;
21398+}
21399+
21400+static void au_show_wbr_create(struct seq_file *m, int v,
21401+ struct au_sbinfo *sbinfo)
21402+{
21403+ const char *pat;
21404+
dece6358
AM
21405+ AuRwMustAnyLock(&sbinfo->si_rwsem);
21406+
1facf9fc 21407+ seq_printf(m, ",create=");
21408+ pat = au_optstr_wbr_create(v);
21409+ switch (v) {
21410+ case AuWbrCreate_TDP:
21411+ case AuWbrCreate_RR:
21412+ case AuWbrCreate_MFS:
21413+ case AuWbrCreate_PMFS:
21414+ seq_printf(m, pat);
21415+ break;
21416+ case AuWbrCreate_MFSV:
21417+ seq_printf(m, /*pat*/"mfs:%lu",
e49829fe
JR
21418+ jiffies_to_msecs(sbinfo->si_wbr_mfs.mfs_expire)
21419+ / MSEC_PER_SEC);
1facf9fc 21420+ break;
21421+ case AuWbrCreate_PMFSV:
21422+ seq_printf(m, /*pat*/"pmfs:%lu",
e49829fe
JR
21423+ jiffies_to_msecs(sbinfo->si_wbr_mfs.mfs_expire)
21424+ / MSEC_PER_SEC);
1facf9fc 21425+ break;
21426+ case AuWbrCreate_MFSRR:
21427+ seq_printf(m, /*pat*/"mfsrr:%llu",
21428+ sbinfo->si_wbr_mfs.mfsrr_watermark);
21429+ break;
21430+ case AuWbrCreate_MFSRRV:
21431+ seq_printf(m, /*pat*/"mfsrr:%llu:%lu",
21432+ sbinfo->si_wbr_mfs.mfsrr_watermark,
e49829fe
JR
21433+ jiffies_to_msecs(sbinfo->si_wbr_mfs.mfs_expire)
21434+ / MSEC_PER_SEC);
1facf9fc 21435+ break;
21436+ }
21437+}
21438+
21439+static int au_show_xino(struct seq_file *seq, struct vfsmount *mnt)
21440+{
21441+#ifdef CONFIG_SYSFS
21442+ return 0;
21443+#else
21444+ int err;
21445+ const int len = sizeof(AUFS_XINO_FNAME) - 1;
21446+ aufs_bindex_t bindex, brid;
21447+ struct super_block *sb;
21448+ struct qstr *name;
21449+ struct file *f;
21450+ struct dentry *d, *h_root;
4a4d8108 21451+ struct au_hdentry *hdp;
1facf9fc 21452+
dece6358
AM
21453+ AuRwMustAnyLock(&sbinfo->si_rwsem);
21454+
1facf9fc 21455+ err = 0;
21456+ sb = mnt->mnt_sb;
21457+ f = au_sbi(sb)->si_xib;
21458+ if (!f)
21459+ goto out;
21460+
21461+ /* stop printing the default xino path on the first writable branch */
21462+ h_root = NULL;
21463+ brid = au_xino_brid(sb);
21464+ if (brid >= 0) {
21465+ bindex = au_br_index(sb, brid);
4a4d8108
AM
21466+ hdp = au_di(sb->s_root)->di_hdentry;
21467+ h_root = hdp[0 + bindex].hd_dentry;
1facf9fc 21468+ }
21469+ d = f->f_dentry;
21470+ name = &d->d_name;
21471+ /* safe ->d_parent because the file is unlinked */
21472+ if (d->d_parent == h_root
21473+ && name->len == len
21474+ && !memcmp(name->name, AUFS_XINO_FNAME, len))
21475+ goto out;
21476+
21477+ seq_puts(seq, ",xino=");
21478+ err = au_xino_path(seq, f);
21479+
4f0767ce 21480+out:
1facf9fc 21481+ return err;
21482+#endif
21483+}
21484+
21485+/* seq_file will re-call me in case of too long string */
21486+static int aufs_show_options(struct seq_file *m, struct vfsmount *mnt)
21487+{
027c5e7a 21488+ int err;
1facf9fc 21489+ unsigned int mnt_flags, v;
21490+ struct super_block *sb;
21491+ struct au_sbinfo *sbinfo;
21492+
21493+#define AuBool(name, str) do { \
21494+ v = au_opt_test(mnt_flags, name); \
21495+ if (v != au_opt_test(AuOpt_Def, name)) \
21496+ seq_printf(m, ",%s" #str, v ? "" : "no"); \
21497+} while (0)
21498+
21499+#define AuStr(name, str) do { \
21500+ v = mnt_flags & AuOptMask_##name; \
21501+ if (v != (AuOpt_Def & AuOptMask_##name)) \
21502+ seq_printf(m, "," #str "=%s", au_optstr_##str(v)); \
21503+} while (0)
21504+
21505+#define AuUInt(name, str, val) do { \
21506+ if (val != AUFS_##name##_DEF) \
21507+ seq_printf(m, "," #str "=%u", val); \
21508+} while (0)
21509+
21510+ /* lock free root dinfo */
21511+ sb = mnt->mnt_sb;
21512+ si_noflush_read_lock(sb);
21513+ sbinfo = au_sbi(sb);
21514+ seq_printf(m, ",si=%lx", sysaufs_si_id(sbinfo));
21515+
21516+ mnt_flags = au_mntflags(sb);
21517+ if (au_opt_test(mnt_flags, XINO)) {
21518+ err = au_show_xino(m, mnt);
21519+ if (unlikely(err))
21520+ goto out;
21521+ } else
21522+ seq_puts(m, ",noxino");
21523+
21524+ AuBool(TRUNC_XINO, trunc_xino);
21525+ AuStr(UDBA, udba);
dece6358 21526+ AuBool(SHWH, shwh);
1facf9fc 21527+ AuBool(PLINK, plink);
4a4d8108 21528+ AuBool(DIO, dio);
1facf9fc 21529+ /* AuBool(DIRPERM1, dirperm1); */
21530+ /* AuBool(REFROF, refrof); */
21531+
21532+ v = sbinfo->si_wbr_create;
21533+ if (v != AuWbrCreate_Def)
21534+ au_show_wbr_create(m, v, sbinfo);
21535+
21536+ v = sbinfo->si_wbr_copyup;
21537+ if (v != AuWbrCopyup_Def)
21538+ seq_printf(m, ",cpup=%s", au_optstr_wbr_copyup(v));
21539+
21540+ v = au_opt_test(mnt_flags, ALWAYS_DIROPQ);
21541+ if (v != au_opt_test(AuOpt_Def, ALWAYS_DIROPQ))
21542+ seq_printf(m, ",diropq=%c", v ? 'a' : 'w');
21543+
21544+ AuUInt(DIRWH, dirwh, sbinfo->si_dirwh);
21545+
027c5e7a
AM
21546+ v = jiffies_to_msecs(sbinfo->si_rdcache) / MSEC_PER_SEC;
21547+ AuUInt(RDCACHE, rdcache, v);
1facf9fc 21548+
21549+ AuUInt(RDBLK, rdblk, sbinfo->si_rdblk);
21550+ AuUInt(RDHASH, rdhash, sbinfo->si_rdhash);
21551+
21552+ AuBool(SUM, sum);
21553+ /* AuBool(SUM_W, wsum); */
21554+ AuBool(WARN_PERM, warn_perm);
21555+ AuBool(VERBOSE, verbose);
21556+
4f0767ce 21557+out:
1facf9fc 21558+ /* be sure to print "br:" last */
21559+ if (!sysaufs_brs) {
21560+ seq_puts(m, ",br:");
21561+ au_show_brs(m, sb);
21562+ }
21563+ si_read_unlock(sb);
21564+ return 0;
21565+
1facf9fc 21566+#undef AuBool
21567+#undef AuStr
4a4d8108 21568+#undef AuUInt
1facf9fc 21569+}
21570+
21571+/* ---------------------------------------------------------------------- */
21572+
21573+/* sum mode which returns the summation for statfs(2) */
21574+
21575+static u64 au_add_till_max(u64 a, u64 b)
21576+{
21577+ u64 old;
21578+
21579+ old = a;
21580+ a += b;
21581+ if (old < a)
21582+ return a;
21583+ return ULLONG_MAX;
21584+}
21585+
21586+static int au_statfs_sum(struct super_block *sb, struct kstatfs *buf)
21587+{
21588+ int err;
21589+ u64 blocks, bfree, bavail, files, ffree;
21590+ aufs_bindex_t bend, bindex, i;
21591+ unsigned char shared;
7f207e10 21592+ struct path h_path;
1facf9fc 21593+ struct super_block *h_sb;
21594+
21595+ blocks = 0;
21596+ bfree = 0;
21597+ bavail = 0;
21598+ files = 0;
21599+ ffree = 0;
21600+
21601+ err = 0;
21602+ bend = au_sbend(sb);
21603+ for (bindex = bend; bindex >= 0; bindex--) {
7f207e10
AM
21604+ h_path.mnt = au_sbr_mnt(sb, bindex);
21605+ h_sb = h_path.mnt->mnt_sb;
1facf9fc 21606+ shared = 0;
21607+ for (i = bindex + 1; !shared && i <= bend; i++)
21608+ shared = (au_sbr_sb(sb, i) == h_sb);
21609+ if (shared)
21610+ continue;
21611+
21612+ /* sb->s_root for NFS is unreliable */
7f207e10
AM
21613+ h_path.dentry = h_path.mnt->mnt_root;
21614+ err = vfs_statfs(&h_path, buf);
1facf9fc 21615+ if (unlikely(err))
21616+ goto out;
21617+
21618+ blocks = au_add_till_max(blocks, buf->f_blocks);
21619+ bfree = au_add_till_max(bfree, buf->f_bfree);
21620+ bavail = au_add_till_max(bavail, buf->f_bavail);
21621+ files = au_add_till_max(files, buf->f_files);
21622+ ffree = au_add_till_max(ffree, buf->f_ffree);
21623+ }
21624+
21625+ buf->f_blocks = blocks;
21626+ buf->f_bfree = bfree;
21627+ buf->f_bavail = bavail;
21628+ buf->f_files = files;
21629+ buf->f_ffree = ffree;
21630+
4f0767ce 21631+out:
1facf9fc 21632+ return err;
21633+}
21634+
21635+static int aufs_statfs(struct dentry *dentry, struct kstatfs *buf)
21636+{
21637+ int err;
7f207e10 21638+ struct path h_path;
1facf9fc 21639+ struct super_block *sb;
21640+
21641+ /* lock free root dinfo */
21642+ sb = dentry->d_sb;
21643+ si_noflush_read_lock(sb);
7f207e10 21644+ if (!au_opt_test(au_mntflags(sb), SUM)) {
1facf9fc 21645+ /* sb->s_root for NFS is unreliable */
7f207e10
AM
21646+ h_path.mnt = au_sbr_mnt(sb, 0);
21647+ h_path.dentry = h_path.mnt->mnt_root;
21648+ err = vfs_statfs(&h_path, buf);
21649+ } else
1facf9fc 21650+ err = au_statfs_sum(sb, buf);
21651+ si_read_unlock(sb);
21652+
21653+ if (!err) {
21654+ buf->f_type = AUFS_SUPER_MAGIC;
4a4d8108 21655+ buf->f_namelen = AUFS_MAX_NAMELEN;
1facf9fc 21656+ memset(&buf->f_fsid, 0, sizeof(buf->f_fsid));
21657+ }
21658+ /* buf->f_bsize = buf->f_blocks = buf->f_bfree = buf->f_bavail = -1; */
21659+
21660+ return err;
21661+}
21662+
21663+/* ---------------------------------------------------------------------- */
21664+
1facf9fc 21665+/* final actions when unmounting a file system */
21666+static void aufs_put_super(struct super_block *sb)
21667+{
21668+ struct au_sbinfo *sbinfo;
21669+
21670+ sbinfo = au_sbi(sb);
21671+ if (!sbinfo)
21672+ return;
21673+
1facf9fc 21674+ dbgaufs_si_fin(sbinfo);
21675+ kobject_put(&sbinfo->si_kobj);
21676+}
21677+
21678+/* ---------------------------------------------------------------------- */
21679+
7f207e10
AM
21680+void au_array_free(void *array)
21681+{
21682+ if (array) {
21683+ if (!is_vmalloc_addr(array))
21684+ kfree(array);
21685+ else
21686+ vfree(array);
21687+ }
21688+}
21689+
21690+void *au_array_alloc(unsigned long long *hint, au_arraycb_t cb, void *arg)
21691+{
21692+ void *array;
21693+ unsigned long long n;
21694+
21695+ array = NULL;
21696+ n = 0;
21697+ if (!*hint)
21698+ goto out;
21699+
21700+ if (*hint > ULLONG_MAX / sizeof(array)) {
21701+ array = ERR_PTR(-EMFILE);
21702+ pr_err("hint %llu\n", *hint);
21703+ goto out;
21704+ }
21705+
21706+ array = kmalloc(sizeof(array) * *hint, GFP_NOFS);
21707+ if (unlikely(!array))
21708+ array = vmalloc(sizeof(array) * *hint);
21709+ if (unlikely(!array)) {
21710+ array = ERR_PTR(-ENOMEM);
21711+ goto out;
21712+ }
21713+
21714+ n = cb(array, *hint, arg);
21715+ AuDebugOn(n > *hint);
21716+
21717+out:
21718+ *hint = n;
21719+ return array;
21720+}
21721+
21722+static unsigned long long au_iarray_cb(void *a,
21723+ unsigned long long max __maybe_unused,
21724+ void *arg)
21725+{
21726+ unsigned long long n;
21727+ struct inode **p, *inode;
21728+ struct list_head *head;
21729+
21730+ n = 0;
21731+ p = a;
21732+ head = arg;
2cbb1c4b 21733+ spin_lock(&inode_sb_list_lock);
7f207e10
AM
21734+ list_for_each_entry(inode, head, i_sb_list) {
21735+ if (!is_bad_inode(inode)
21736+ && au_ii(inode)->ii_bstart >= 0) {
2cbb1c4b
JR
21737+ spin_lock(&inode->i_lock);
21738+ if (atomic_read(&inode->i_count)) {
21739+ au_igrab(inode);
21740+ *p++ = inode;
21741+ n++;
21742+ AuDebugOn(n > max);
21743+ }
21744+ spin_unlock(&inode->i_lock);
7f207e10
AM
21745+ }
21746+ }
2cbb1c4b 21747+ spin_unlock(&inode_sb_list_lock);
7f207e10
AM
21748+
21749+ return n;
21750+}
21751+
21752+struct inode **au_iarray_alloc(struct super_block *sb, unsigned long long *max)
21753+{
21754+ *max = atomic_long_read(&au_sbi(sb)->si_ninodes);
21755+ return au_array_alloc(max, au_iarray_cb, &sb->s_inodes);
21756+}
21757+
21758+void au_iarray_free(struct inode **a, unsigned long long max)
21759+{
21760+ unsigned long long ull;
21761+
21762+ for (ull = 0; ull < max; ull++)
21763+ iput(a[ull]);
21764+ au_array_free(a);
21765+}
21766+
21767+/* ---------------------------------------------------------------------- */
21768+
1facf9fc 21769+/*
21770+ * refresh dentry and inode at remount time.
21771+ */
027c5e7a
AM
21772+/* todo: consolidate with simple_reval_dpath() and au_reval_for_attr() */
21773+static int au_do_refresh(struct dentry *dentry, unsigned int dir_flags,
21774+ struct dentry *parent)
1facf9fc 21775+{
21776+ int err;
1facf9fc 21777+
21778+ di_write_lock_child(dentry);
1facf9fc 21779+ di_read_lock_parent(parent, AuLock_IR);
027c5e7a
AM
21780+ err = au_refresh_dentry(dentry, parent);
21781+ if (!err && dir_flags)
21782+ au_hn_reset(dentry->d_inode, dir_flags);
1facf9fc 21783+ di_read_unlock(parent, AuLock_IR);
1facf9fc 21784+ di_write_unlock(dentry);
21785+
21786+ return err;
21787+}
21788+
027c5e7a
AM
21789+static int au_do_refresh_d(struct dentry *dentry, unsigned int sigen,
21790+ struct au_sbinfo *sbinfo,
21791+ const unsigned int dir_flags)
1facf9fc 21792+{
027c5e7a
AM
21793+ int err;
21794+ struct dentry *parent;
21795+ struct inode *inode;
21796+
21797+ err = 0;
21798+ parent = dget_parent(dentry);
21799+ if (!au_digen_test(parent, sigen) && au_digen_test(dentry, sigen)) {
21800+ inode = dentry->d_inode;
21801+ if (inode) {
21802+ if (!S_ISDIR(inode->i_mode))
21803+ err = au_do_refresh(dentry, /*dir_flags*/0,
21804+ parent);
21805+ else {
21806+ err = au_do_refresh(dentry, dir_flags, parent);
21807+ if (unlikely(err))
21808+ au_fset_si(sbinfo, FAILED_REFRESH_DIR);
21809+ }
21810+ } else
21811+ err = au_do_refresh(dentry, /*dir_flags*/0, parent);
21812+ AuDbgDentry(dentry);
21813+ }
21814+ dput(parent);
21815+
21816+ AuTraceErr(err);
21817+ return err;
1facf9fc 21818+}
21819+
027c5e7a 21820+static int au_refresh_d(struct super_block *sb)
1facf9fc 21821+{
21822+ int err, i, j, ndentry, e;
027c5e7a 21823+ unsigned int sigen;
1facf9fc 21824+ struct au_dcsub_pages dpages;
21825+ struct au_dpage *dpage;
027c5e7a
AM
21826+ struct dentry **dentries, *d;
21827+ struct au_sbinfo *sbinfo;
21828+ struct dentry *root = sb->s_root;
21829+ const unsigned int dir_flags = au_hi_flags(root->d_inode, /*isdir*/1);
1facf9fc 21830+
027c5e7a
AM
21831+ err = au_dpages_init(&dpages, GFP_NOFS);
21832+ if (unlikely(err))
1facf9fc 21833+ goto out;
027c5e7a
AM
21834+ err = au_dcsub_pages(&dpages, root, NULL, NULL);
21835+ if (unlikely(err))
1facf9fc 21836+ goto out_dpages;
1facf9fc 21837+
027c5e7a
AM
21838+ sigen = au_sigen(sb);
21839+ sbinfo = au_sbi(sb);
21840+ for (i = 0; i < dpages.ndpage; i++) {
1facf9fc 21841+ dpage = dpages.dpages + i;
21842+ dentries = dpage->dentries;
21843+ ndentry = dpage->ndentry;
027c5e7a 21844+ for (j = 0; j < ndentry; j++) {
1facf9fc 21845+ d = dentries[j];
027c5e7a
AM
21846+ e = au_do_refresh_d(d, sigen, sbinfo, dir_flags);
21847+ if (unlikely(e && !err))
21848+ err = e;
21849+ /* go on even err */
1facf9fc 21850+ }
21851+ }
21852+
4f0767ce 21853+out_dpages:
1facf9fc 21854+ au_dpages_free(&dpages);
4f0767ce 21855+out:
1facf9fc 21856+ return err;
21857+}
21858+
027c5e7a 21859+static int au_refresh_i(struct super_block *sb)
1facf9fc 21860+{
027c5e7a
AM
21861+ int err, e;
21862+ unsigned int sigen;
21863+ unsigned long long max, ull;
21864+ struct inode *inode, **array;
1facf9fc 21865+
027c5e7a
AM
21866+ array = au_iarray_alloc(sb, &max);
21867+ err = PTR_ERR(array);
21868+ if (IS_ERR(array))
21869+ goto out;
1facf9fc 21870+
21871+ err = 0;
027c5e7a
AM
21872+ sigen = au_sigen(sb);
21873+ for (ull = 0; ull < max; ull++) {
21874+ inode = array[ull];
21875+ if (au_iigen(inode) != sigen) {
1facf9fc 21876+ ii_write_lock_child(inode);
027c5e7a 21877+ e = au_refresh_hinode_self(inode);
1facf9fc 21878+ ii_write_unlock(inode);
21879+ if (unlikely(e)) {
027c5e7a 21880+ pr_err("error %d, i%lu\n", e, inode->i_ino);
1facf9fc 21881+ if (!err)
21882+ err = e;
21883+ /* go on even if err */
21884+ }
21885+ }
1facf9fc 21886+ }
21887+
027c5e7a 21888+ au_iarray_free(array, max);
1facf9fc 21889+
4f0767ce 21890+out:
1facf9fc 21891+ return err;
21892+}
21893+
027c5e7a 21894+static void au_remount_refresh(struct super_block *sb)
1facf9fc 21895+{
027c5e7a
AM
21896+ int err, e;
21897+ unsigned int udba;
21898+ aufs_bindex_t bindex, bend;
1facf9fc 21899+ struct dentry *root;
21900+ struct inode *inode;
027c5e7a 21901+ struct au_branch *br;
1facf9fc 21902+
21903+ au_sigen_inc(sb);
027c5e7a 21904+ au_fclr_si(au_sbi(sb), FAILED_REFRESH_DIR);
1facf9fc 21905+
21906+ root = sb->s_root;
21907+ DiMustNoWaiters(root);
21908+ inode = root->d_inode;
21909+ IiMustNoWaiters(inode);
1facf9fc 21910+
027c5e7a
AM
21911+ udba = au_opt_udba(sb);
21912+ bend = au_sbend(sb);
21913+ for (bindex = 0; bindex <= bend; bindex++) {
21914+ br = au_sbr(sb, bindex);
21915+ err = au_hnotify_reset_br(udba, br, br->br_perm);
1facf9fc 21916+ if (unlikely(err))
027c5e7a
AM
21917+ AuIOErr("hnotify failed on br %d, %d, ignored\n",
21918+ bindex, err);
21919+ /* go on even if err */
1facf9fc 21920+ }
027c5e7a 21921+ au_hn_reset(inode, au_hi_flags(inode, /*isdir*/1));
1facf9fc 21922+
027c5e7a
AM
21923+ di_write_unlock(root);
21924+ err = au_refresh_d(sb);
21925+ e = au_refresh_i(sb);
21926+ if (unlikely(e && !err))
21927+ err = e;
1facf9fc 21928+ /* aufs_write_lock() calls ..._child() */
21929+ di_write_lock_child(root);
027c5e7a
AM
21930+
21931+ au_cpup_attr_all(inode, /*force*/1);
21932+
21933+ if (unlikely(err))
21934+ AuIOErr("refresh failed, ignored, %d\n", err);
1facf9fc 21935+}
21936+
21937+/* stop extra interpretation of errno in mount(8), and strange error messages */
21938+static int cvt_err(int err)
21939+{
21940+ AuTraceErr(err);
21941+
21942+ switch (err) {
21943+ case -ENOENT:
21944+ case -ENOTDIR:
21945+ case -EEXIST:
21946+ case -EIO:
21947+ err = -EINVAL;
21948+ }
21949+ return err;
21950+}
21951+
21952+static int aufs_remount_fs(struct super_block *sb, int *flags, char *data)
21953+{
4a4d8108
AM
21954+ int err, do_dx;
21955+ unsigned int mntflags;
1facf9fc 21956+ struct au_opts opts;
21957+ struct dentry *root;
21958+ struct inode *inode;
21959+ struct au_sbinfo *sbinfo;
21960+
21961+ err = 0;
21962+ root = sb->s_root;
21963+ if (!data || !*data) {
e49829fe
JR
21964+ err = si_write_lock(sb, AuLock_FLUSH | AuLock_NOPLM);
21965+ if (!err) {
21966+ di_write_lock_child(root);
21967+ err = au_opts_verify(sb, *flags, /*pending*/0);
21968+ aufs_write_unlock(root);
21969+ }
1facf9fc 21970+ goto out;
21971+ }
21972+
21973+ err = -ENOMEM;
21974+ memset(&opts, 0, sizeof(opts));
21975+ opts.opt = (void *)__get_free_page(GFP_NOFS);
21976+ if (unlikely(!opts.opt))
21977+ goto out;
21978+ opts.max_opt = PAGE_SIZE / sizeof(*opts.opt);
21979+ opts.flags = AuOpts_REMOUNT;
21980+ opts.sb_flags = *flags;
21981+
21982+ /* parse it before aufs lock */
21983+ err = au_opts_parse(sb, data, &opts);
21984+ if (unlikely(err))
21985+ goto out_opts;
21986+
21987+ sbinfo = au_sbi(sb);
21988+ inode = root->d_inode;
21989+ mutex_lock(&inode->i_mutex);
e49829fe
JR
21990+ err = si_write_lock(sb, AuLock_FLUSH | AuLock_NOPLM);
21991+ if (unlikely(err))
21992+ goto out_mtx;
21993+ di_write_lock_child(root);
1facf9fc 21994+
21995+ /* au_opts_remount() may return an error */
21996+ err = au_opts_remount(sb, &opts);
21997+ au_opts_free(&opts);
21998+
027c5e7a
AM
21999+ if (au_ftest_opts(opts.flags, REFRESH))
22000+ au_remount_refresh(sb);
1facf9fc 22001+
4a4d8108
AM
22002+ if (au_ftest_opts(opts.flags, REFRESH_DYAOP)) {
22003+ mntflags = au_mntflags(sb);
22004+ do_dx = !!au_opt_test(mntflags, DIO);
22005+ au_dy_arefresh(do_dx);
22006+ }
22007+
1facf9fc 22008+ aufs_write_unlock(root);
953406b4 22009+
e49829fe
JR
22010+out_mtx:
22011+ mutex_unlock(&inode->i_mutex);
4f0767ce 22012+out_opts:
1facf9fc 22013+ free_page((unsigned long)opts.opt);
4f0767ce 22014+out:
1facf9fc 22015+ err = cvt_err(err);
22016+ AuTraceErr(err);
22017+ return err;
22018+}
22019+
4a4d8108 22020+static const struct super_operations aufs_sop = {
1facf9fc 22021+ .alloc_inode = aufs_alloc_inode,
22022+ .destroy_inode = aufs_destroy_inode,
b752ccd1 22023+ /* always deleting, no clearing */
1facf9fc 22024+ .drop_inode = generic_delete_inode,
22025+ .show_options = aufs_show_options,
22026+ .statfs = aufs_statfs,
22027+ .put_super = aufs_put_super,
22028+ .remount_fs = aufs_remount_fs
22029+};
22030+
22031+/* ---------------------------------------------------------------------- */
22032+
22033+static int alloc_root(struct super_block *sb)
22034+{
22035+ int err;
22036+ struct inode *inode;
22037+ struct dentry *root;
22038+
22039+ err = -ENOMEM;
22040+ inode = au_iget_locked(sb, AUFS_ROOT_INO);
22041+ err = PTR_ERR(inode);
22042+ if (IS_ERR(inode))
22043+ goto out;
22044+
22045+ inode->i_op = &aufs_dir_iop;
22046+ inode->i_fop = &aufs_dir_fop;
22047+ inode->i_mode = S_IFDIR;
22048+ inode->i_nlink = 2;
22049+ unlock_new_inode(inode);
22050+
22051+ root = d_alloc_root(inode);
22052+ if (unlikely(!root))
22053+ goto out_iput;
22054+ err = PTR_ERR(root);
22055+ if (IS_ERR(root))
22056+ goto out_iput;
22057+
4a4d8108 22058+ err = au_di_init(root);
1facf9fc 22059+ if (!err) {
22060+ sb->s_root = root;
22061+ return 0; /* success */
22062+ }
22063+ dput(root);
22064+ goto out; /* do not iput */
22065+
4f0767ce 22066+out_iput:
1facf9fc 22067+ iget_failed(inode);
4f0767ce 22068+out:
1facf9fc 22069+ return err;
22070+
22071+}
22072+
22073+static int aufs_fill_super(struct super_block *sb, void *raw_data,
22074+ int silent __maybe_unused)
22075+{
22076+ int err;
22077+ struct au_opts opts;
22078+ struct dentry *root;
22079+ struct inode *inode;
22080+ char *arg = raw_data;
22081+
22082+ if (unlikely(!arg || !*arg)) {
22083+ err = -EINVAL;
4a4d8108 22084+ pr_err("no arg\n");
1facf9fc 22085+ goto out;
22086+ }
22087+
22088+ err = -ENOMEM;
22089+ memset(&opts, 0, sizeof(opts));
22090+ opts.opt = (void *)__get_free_page(GFP_NOFS);
22091+ if (unlikely(!opts.opt))
22092+ goto out;
22093+ opts.max_opt = PAGE_SIZE / sizeof(*opts.opt);
22094+ opts.sb_flags = sb->s_flags;
22095+
22096+ err = au_si_alloc(sb);
22097+ if (unlikely(err))
22098+ goto out_opts;
22099+
22100+ /* all timestamps always follow the ones on the branch */
22101+ sb->s_flags |= MS_NOATIME | MS_NODIRATIME;
22102+ sb->s_op = &aufs_sop;
027c5e7a 22103+ sb->s_d_op = &aufs_dop;
1facf9fc 22104+ sb->s_magic = AUFS_SUPER_MAGIC;
22105+ sb->s_maxbytes = 0;
22106+ au_export_init(sb);
22107+
22108+ err = alloc_root(sb);
22109+ if (unlikely(err)) {
22110+ si_write_unlock(sb);
22111+ goto out_info;
22112+ }
22113+ root = sb->s_root;
22114+ inode = root->d_inode;
22115+
22116+ /*
22117+ * actually we can parse options regardless aufs lock here.
22118+ * but at remount time, parsing must be done before aufs lock.
22119+ * so we follow the same rule.
22120+ */
22121+ ii_write_lock_parent(inode);
22122+ aufs_write_unlock(root);
22123+ err = au_opts_parse(sb, arg, &opts);
22124+ if (unlikely(err))
22125+ goto out_root;
22126+
22127+ /* lock vfs_inode first, then aufs. */
22128+ mutex_lock(&inode->i_mutex);
1facf9fc 22129+ aufs_write_lock(root);
22130+ err = au_opts_mount(sb, &opts);
22131+ au_opts_free(&opts);
1facf9fc 22132+ aufs_write_unlock(root);
22133+ mutex_unlock(&inode->i_mutex);
4a4d8108
AM
22134+ if (!err)
22135+ goto out_opts; /* success */
1facf9fc 22136+
4f0767ce 22137+out_root:
1facf9fc 22138+ dput(root);
22139+ sb->s_root = NULL;
4f0767ce 22140+out_info:
2cbb1c4b 22141+ dbgaufs_si_fin(au_sbi(sb));
1facf9fc 22142+ kobject_put(&au_sbi(sb)->si_kobj);
22143+ sb->s_fs_info = NULL;
4f0767ce 22144+out_opts:
1facf9fc 22145+ free_page((unsigned long)opts.opt);
4f0767ce 22146+out:
1facf9fc 22147+ AuTraceErr(err);
22148+ err = cvt_err(err);
22149+ AuTraceErr(err);
22150+ return err;
22151+}
22152+
22153+/* ---------------------------------------------------------------------- */
22154+
027c5e7a
AM
22155+static struct dentry *aufs_mount(struct file_system_type *fs_type, int flags,
22156+ const char *dev_name __maybe_unused,
22157+ void *raw_data)
1facf9fc 22158+{
027c5e7a 22159+ struct dentry *root;
1facf9fc 22160+ struct super_block *sb;
22161+
22162+ /* all timestamps always follow the ones on the branch */
22163+ /* mnt->mnt_flags |= MNT_NOATIME | MNT_NODIRATIME; */
027c5e7a
AM
22164+ root = mount_nodev(fs_type, flags, raw_data, aufs_fill_super);
22165+ if (IS_ERR(root))
22166+ goto out;
22167+
22168+ sb = root->d_sb;
22169+ si_write_lock(sb, !AuLock_FLUSH);
22170+ sysaufs_brs_add(sb, 0);
22171+ si_write_unlock(sb);
22172+ au_sbilist_add(sb);
22173+
22174+out:
22175+ return root;
1facf9fc 22176+}
22177+
e49829fe
JR
22178+static void aufs_kill_sb(struct super_block *sb)
22179+{
22180+ struct au_sbinfo *sbinfo;
22181+
22182+ sbinfo = au_sbi(sb);
22183+ if (sbinfo) {
22184+ au_sbilist_del(sb);
22185+ aufs_write_lock(sb->s_root);
22186+ if (sbinfo->si_wbr_create_ops->fin)
22187+ sbinfo->si_wbr_create_ops->fin(sb);
22188+ if (au_opt_test(sbinfo->si_mntflags, UDBA_HNOTIFY)) {
22189+ au_opt_set_udba(sbinfo->si_mntflags, UDBA_NONE);
027c5e7a 22190+ au_remount_refresh(sb);
e49829fe
JR
22191+ }
22192+ if (au_opt_test(sbinfo->si_mntflags, PLINK))
22193+ au_plink_put(sb, /*verbose*/1);
22194+ au_xino_clr(sb);
22195+ aufs_write_unlock(sb->s_root);
e49829fe
JR
22196+ au_nwt_flush(&sbinfo->si_nowait);
22197+ }
22198+ generic_shutdown_super(sb);
22199+}
22200+
1facf9fc 22201+struct file_system_type aufs_fs_type = {
22202+ .name = AUFS_FSTYPE,
22203+ .fs_flags =
22204+ FS_RENAME_DOES_D_MOVE /* a race between rename and others */
22205+ | FS_REVAL_DOT, /* for NFS branch and udba */
027c5e7a 22206+ .mount = aufs_mount,
e49829fe 22207+ .kill_sb = aufs_kill_sb,
1facf9fc 22208+ /* no need to __module_get() and module_put(). */
22209+ .owner = THIS_MODULE,
22210+};
7f207e10
AM
22211diff -urN /usr/share/empty/fs/aufs/super.h linux/fs/aufs/super.h
22212--- /usr/share/empty/fs/aufs/super.h 1970-01-01 01:00:00.000000000 +0100
87a755f4 22213+++ linux/fs/aufs/super.h 2011-03-17 10:46:59.000000000 +0100
027c5e7a 22214@@ -0,0 +1,527 @@
1facf9fc 22215+/*
027c5e7a 22216+ * Copyright (C) 2005-2011 Junjiro R. Okajima
1facf9fc 22217+ *
22218+ * This program, aufs is free software; you can redistribute it and/or modify
22219+ * it under the terms of the GNU General Public License as published by
22220+ * the Free Software Foundation; either version 2 of the License, or
22221+ * (at your option) any later version.
dece6358
AM
22222+ *
22223+ * This program is distributed in the hope that it will be useful,
22224+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
22225+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22226+ * GNU General Public License for more details.
22227+ *
22228+ * You should have received a copy of the GNU General Public License
22229+ * along with this program; if not, write to the Free Software
22230+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 22231+ */
22232+
22233+/*
22234+ * super_block operations
22235+ */
22236+
22237+#ifndef __AUFS_SUPER_H__
22238+#define __AUFS_SUPER_H__
22239+
22240+#ifdef __KERNEL__
22241+
22242+#include <linux/fs.h>
1facf9fc 22243+#include <linux/aufs_type.h>
22244+#include "rwsem.h"
22245+#include "spl.h"
22246+#include "wkq.h"
22247+
22248+typedef ssize_t (*au_readf_t)(struct file *, char __user *, size_t, loff_t *);
22249+typedef ssize_t (*au_writef_t)(struct file *, const char __user *, size_t,
22250+ loff_t *);
22251+
22252+/* policies to select one among multiple writable branches */
22253+struct au_wbr_copyup_operations {
22254+ int (*copyup)(struct dentry *dentry);
22255+};
22256+
22257+struct au_wbr_create_operations {
22258+ int (*create)(struct dentry *dentry, int isdir);
22259+ int (*init)(struct super_block *sb);
22260+ int (*fin)(struct super_block *sb);
22261+};
22262+
22263+struct au_wbr_mfs {
22264+ struct mutex mfs_lock; /* protect this structure */
22265+ unsigned long mfs_jiffy;
22266+ unsigned long mfs_expire;
22267+ aufs_bindex_t mfs_bindex;
22268+
22269+ unsigned long long mfsrr_bytes;
22270+ unsigned long long mfsrr_watermark;
22271+};
22272+
1facf9fc 22273+struct au_branch;
22274+struct au_sbinfo {
22275+ /* nowait tasks in the system-wide workqueue */
22276+ struct au_nowait_tasks si_nowait;
22277+
b752ccd1
AM
22278+ /*
22279+ * tried sb->s_umount, but failed due to the dependecy between i_mutex.
22280+ * rwsem for au_sbinfo is necessary.
22281+ */
dece6358 22282+ struct au_rwsem si_rwsem;
1facf9fc 22283+
b752ccd1
AM
22284+ /* prevent recursive locking in deleting inode */
22285+ struct {
22286+ unsigned long *bitmap;
22287+ spinlock_t tree_lock;
22288+ struct radix_tree_root tree;
22289+ } au_si_pid;
22290+
7f207e10
AM
22291+ /*
22292+ * dirty approach to protect sb->sb_inodes and ->s_files from remount.
22293+ */
22294+ atomic_long_t si_ninodes, si_nfiles;
22295+
1facf9fc 22296+ /* branch management */
22297+ unsigned int si_generation;
22298+
22299+ /* see above flags */
22300+ unsigned char au_si_status;
22301+
22302+ aufs_bindex_t si_bend;
7f207e10
AM
22303+
22304+ /* dirty trick to keep br_id plus */
22305+ unsigned int si_last_br_id :
22306+ sizeof(aufs_bindex_t) * BITS_PER_BYTE - 1;
1facf9fc 22307+ struct au_branch **si_branch;
22308+
22309+ /* policy to select a writable branch */
22310+ unsigned char si_wbr_copyup;
22311+ unsigned char si_wbr_create;
22312+ struct au_wbr_copyup_operations *si_wbr_copyup_ops;
22313+ struct au_wbr_create_operations *si_wbr_create_ops;
22314+
22315+ /* round robin */
22316+ atomic_t si_wbr_rr_next;
22317+
22318+ /* most free space */
22319+ struct au_wbr_mfs si_wbr_mfs;
22320+
22321+ /* mount flags */
22322+ /* include/asm-ia64/siginfo.h defines a macro named si_flags */
22323+ unsigned int si_mntflags;
22324+
22325+ /* external inode number (bitmap and translation table) */
22326+ au_readf_t si_xread;
22327+ au_writef_t si_xwrite;
22328+ struct file *si_xib;
22329+ struct mutex si_xib_mtx; /* protect xib members */
22330+ unsigned long *si_xib_buf;
22331+ unsigned long si_xib_last_pindex;
22332+ int si_xib_next_bit;
22333+ aufs_bindex_t si_xino_brid;
22334+ /* reserved for future use */
22335+ /* unsigned long long si_xib_limit; */ /* Max xib file size */
22336+
22337+#ifdef CONFIG_AUFS_EXPORT
22338+ /* i_generation */
22339+ struct file *si_xigen;
22340+ atomic_t si_xigen_next;
22341+#endif
22342+
22343+ /* vdir parameters */
e49829fe 22344+ unsigned long si_rdcache; /* max cache time in jiffies */
1facf9fc 22345+ unsigned int si_rdblk; /* deblk size */
22346+ unsigned int si_rdhash; /* hash size */
22347+
22348+ /*
22349+ * If the number of whiteouts are larger than si_dirwh, leave all of
22350+ * them after au_whtmp_ren to reduce the cost of rmdir(2).
22351+ * future fsck.aufs or kernel thread will remove them later.
22352+ * Otherwise, remove all whiteouts and the dir in rmdir(2).
22353+ */
22354+ unsigned int si_dirwh;
22355+
22356+ /*
22357+ * rename(2) a directory with all children.
22358+ */
22359+ /* reserved for future use */
22360+ /* int si_rendir; */
22361+
22362+ /* pseudo_link list */
22363+ struct au_splhead si_plink;
22364+ wait_queue_head_t si_plink_wq;
4a4d8108 22365+ spinlock_t si_plink_maint_lock;
e49829fe 22366+ pid_t si_plink_maint_pid;
1facf9fc 22367+
22368+ /*
22369+ * sysfs and lifetime management.
22370+ * this is not a small structure and it may be a waste of memory in case
22371+ * of sysfs is disabled, particulary when many aufs-es are mounted.
22372+ * but using sysfs is majority.
22373+ */
22374+ struct kobject si_kobj;
22375+#ifdef CONFIG_DEBUG_FS
22376+ struct dentry *si_dbgaufs, *si_dbgaufs_xib;
22377+#ifdef CONFIG_AUFS_EXPORT
22378+ struct dentry *si_dbgaufs_xigen;
22379+#endif
22380+#endif
22381+
e49829fe
JR
22382+#ifdef CONFIG_AUFS_SBILIST
22383+ struct list_head si_list;
22384+#endif
22385+
1facf9fc 22386+ /* dirty, necessary for unmounting, sysfs and sysrq */
22387+ struct super_block *si_sb;
22388+};
22389+
dece6358
AM
22390+/* sbinfo status flags */
22391+/*
22392+ * set true when refresh_dirs() failed at remount time.
22393+ * then try refreshing dirs at access time again.
22394+ * if it is false, refreshing dirs at access time is unnecesary
22395+ */
027c5e7a 22396+#define AuSi_FAILED_REFRESH_DIR 1
dece6358
AM
22397+static inline unsigned char au_do_ftest_si(struct au_sbinfo *sbi,
22398+ unsigned int flag)
22399+{
22400+ AuRwMustAnyLock(&sbi->si_rwsem);
22401+ return sbi->au_si_status & flag;
22402+}
22403+#define au_ftest_si(sbinfo, name) au_do_ftest_si(sbinfo, AuSi_##name)
22404+#define au_fset_si(sbinfo, name) do { \
22405+ AuRwMustWriteLock(&(sbinfo)->si_rwsem); \
22406+ (sbinfo)->au_si_status |= AuSi_##name; \
22407+} while (0)
22408+#define au_fclr_si(sbinfo, name) do { \
22409+ AuRwMustWriteLock(&(sbinfo)->si_rwsem); \
22410+ (sbinfo)->au_si_status &= ~AuSi_##name; \
22411+} while (0)
22412+
1facf9fc 22413+/* ---------------------------------------------------------------------- */
22414+
22415+/* policy to select one among writable branches */
4a4d8108
AM
22416+#define AuWbrCopyup(sbinfo, ...) \
22417+ ((sbinfo)->si_wbr_copyup_ops->copyup(__VA_ARGS__))
22418+#define AuWbrCreate(sbinfo, ...) \
22419+ ((sbinfo)->si_wbr_create_ops->create(__VA_ARGS__))
1facf9fc 22420+
22421+/* flags for si_read_lock()/aufs_read_lock()/di_read_lock() */
22422+#define AuLock_DW 1 /* write-lock dentry */
22423+#define AuLock_IR (1 << 1) /* read-lock inode */
22424+#define AuLock_IW (1 << 2) /* write-lock inode */
22425+#define AuLock_FLUSH (1 << 3) /* wait for 'nowait' tasks */
22426+#define AuLock_DIR (1 << 4) /* target is a dir */
e49829fe
JR
22427+#define AuLock_NOPLM (1 << 5) /* return err in plm mode */
22428+#define AuLock_NOPLMW (1 << 6) /* wait for plm mode ends */
027c5e7a 22429+#define AuLock_GEN (1 << 7) /* test digen/iigen */
1facf9fc 22430+#define au_ftest_lock(flags, name) ((flags) & AuLock_##name)
7f207e10
AM
22431+#define au_fset_lock(flags, name) \
22432+ do { (flags) |= AuLock_##name; } while (0)
22433+#define au_fclr_lock(flags, name) \
22434+ do { (flags) &= ~AuLock_##name; } while (0)
1facf9fc 22435+
22436+/* ---------------------------------------------------------------------- */
22437+
22438+/* super.c */
22439+extern struct file_system_type aufs_fs_type;
22440+struct inode *au_iget_locked(struct super_block *sb, ino_t ino);
7f207e10
AM
22441+typedef unsigned long long (*au_arraycb_t)(void *array, unsigned long long max,
22442+ void *arg);
22443+void au_array_free(void *array);
22444+void *au_array_alloc(unsigned long long *hint, au_arraycb_t cb, void *arg);
22445+struct inode **au_iarray_alloc(struct super_block *sb, unsigned long long *max);
22446+void au_iarray_free(struct inode **a, unsigned long long max);
1facf9fc 22447+
22448+/* sbinfo.c */
22449+void au_si_free(struct kobject *kobj);
22450+int au_si_alloc(struct super_block *sb);
22451+int au_sbr_realloc(struct au_sbinfo *sbinfo, int nbr);
22452+
22453+unsigned int au_sigen_inc(struct super_block *sb);
22454+aufs_bindex_t au_new_br_id(struct super_block *sb);
22455+
e49829fe
JR
22456+int si_read_lock(struct super_block *sb, int flags);
22457+int si_write_lock(struct super_block *sb, int flags);
22458+int aufs_read_lock(struct dentry *dentry, int flags);
1facf9fc 22459+void aufs_read_unlock(struct dentry *dentry, int flags);
22460+void aufs_write_lock(struct dentry *dentry);
22461+void aufs_write_unlock(struct dentry *dentry);
e49829fe 22462+int aufs_read_and_write_lock2(struct dentry *d1, struct dentry *d2, int flags);
1facf9fc 22463+void aufs_read_and_write_unlock2(struct dentry *d1, struct dentry *d2);
22464+
b752ccd1
AM
22465+int si_pid_test_slow(struct super_block *sb);
22466+void si_pid_set_slow(struct super_block *sb);
22467+void si_pid_clr_slow(struct super_block *sb);
22468+
1facf9fc 22469+/* wbr_policy.c */
22470+extern struct au_wbr_copyup_operations au_wbr_copyup_ops[];
22471+extern struct au_wbr_create_operations au_wbr_create_ops[];
22472+int au_cpdown_dirs(struct dentry *dentry, aufs_bindex_t bdst);
22473+
22474+/* ---------------------------------------------------------------------- */
22475+
22476+static inline struct au_sbinfo *au_sbi(struct super_block *sb)
22477+{
22478+ return sb->s_fs_info;
22479+}
22480+
22481+/* ---------------------------------------------------------------------- */
22482+
22483+#ifdef CONFIG_AUFS_EXPORT
22484+void au_export_init(struct super_block *sb);
22485+
b752ccd1 22486+static inline int au_test_nfsd(void)
1facf9fc 22487+{
b752ccd1
AM
22488+ struct task_struct *tsk = current;
22489+
22490+ return (tsk->flags & PF_KTHREAD)
22491+ && !strcmp(tsk->comm, "nfsd");
1facf9fc 22492+}
22493+
b752ccd1 22494+void au_xigen_inc(struct inode *inode);
1facf9fc 22495+int au_xigen_new(struct inode *inode);
22496+int au_xigen_set(struct super_block *sb, struct file *base);
22497+void au_xigen_clr(struct super_block *sb);
22498+
22499+static inline int au_busy_or_stale(void)
22500+{
b752ccd1 22501+ if (!au_test_nfsd())
1facf9fc 22502+ return -EBUSY;
22503+ return -ESTALE;
22504+}
22505+#else
4a4d8108 22506+AuStubVoid(au_export_init, struct super_block *sb)
b752ccd1
AM
22507+AuStubInt0(au_test_nfsd, void)
22508+AuStubVoid(au_xigen_inc, struct inode *inode)
4a4d8108
AM
22509+AuStubInt0(au_xigen_new, struct inode *inode)
22510+AuStubInt0(au_xigen_set, struct super_block *sb, struct file *base)
22511+AuStubVoid(au_xigen_clr, struct super_block *sb)
1facf9fc 22512+static inline int au_busy_or_stale(void)
22513+{
22514+ return -EBUSY;
22515+}
22516+#endif /* CONFIG_AUFS_EXPORT */
22517+
22518+/* ---------------------------------------------------------------------- */
22519+
e49829fe
JR
22520+#ifdef CONFIG_AUFS_SBILIST
22521+/* module.c */
22522+extern struct au_splhead au_sbilist;
22523+
22524+static inline void au_sbilist_init(void)
22525+{
22526+ au_spl_init(&au_sbilist);
22527+}
22528+
22529+static inline void au_sbilist_add(struct super_block *sb)
22530+{
22531+ au_spl_add(&au_sbi(sb)->si_list, &au_sbilist);
22532+}
22533+
22534+static inline void au_sbilist_del(struct super_block *sb)
22535+{
22536+ au_spl_del(&au_sbi(sb)->si_list, &au_sbilist);
22537+}
22538+#else
22539+AuStubVoid(au_sbilist_init, void)
22540+AuStubVoid(au_sbilist_add, struct super_block*)
22541+AuStubVoid(au_sbilist_del, struct super_block*)
22542+#endif
22543+
22544+/* ---------------------------------------------------------------------- */
22545+
1facf9fc 22546+static inline void dbgaufs_si_null(struct au_sbinfo *sbinfo)
22547+{
dece6358
AM
22548+ /*
22549+ * This function is a dynamic '__init' fucntion actually,
22550+ * so the tiny check for si_rwsem is unnecessary.
22551+ */
22552+ /* AuRwMustWriteLock(&sbinfo->si_rwsem); */
1facf9fc 22553+#ifdef CONFIG_DEBUG_FS
22554+ sbinfo->si_dbgaufs = NULL;
22555+ sbinfo->si_dbgaufs_xib = NULL;
22556+#ifdef CONFIG_AUFS_EXPORT
22557+ sbinfo->si_dbgaufs_xigen = NULL;
22558+#endif
22559+#endif
22560+}
22561+
22562+/* ---------------------------------------------------------------------- */
22563+
b752ccd1
AM
22564+static inline pid_t si_pid_bit(void)
22565+{
22566+ /* the origin of pid is 1, but the bitmap's is 0 */
22567+ return current->pid - 1;
22568+}
22569+
22570+static inline int si_pid_test(struct super_block *sb)
22571+{
22572+ pid_t bit = si_pid_bit();
22573+ if (bit < PID_MAX_DEFAULT)
22574+ return test_bit(bit, au_sbi(sb)->au_si_pid.bitmap);
22575+ else
22576+ return si_pid_test_slow(sb);
22577+}
22578+
22579+static inline void si_pid_set(struct super_block *sb)
22580+{
22581+ pid_t bit = si_pid_bit();
22582+ if (bit < PID_MAX_DEFAULT) {
22583+ AuDebugOn(test_bit(bit, au_sbi(sb)->au_si_pid.bitmap));
22584+ set_bit(bit, au_sbi(sb)->au_si_pid.bitmap);
22585+ /* smp_mb(); */
22586+ } else
22587+ si_pid_set_slow(sb);
22588+}
22589+
22590+static inline void si_pid_clr(struct super_block *sb)
22591+{
22592+ pid_t bit = si_pid_bit();
22593+ if (bit < PID_MAX_DEFAULT) {
22594+ AuDebugOn(!test_bit(bit, au_sbi(sb)->au_si_pid.bitmap));
22595+ clear_bit(bit, au_sbi(sb)->au_si_pid.bitmap);
22596+ /* smp_mb(); */
22597+ } else
22598+ si_pid_clr_slow(sb);
22599+}
22600+
22601+/* ---------------------------------------------------------------------- */
22602+
1facf9fc 22603+/* lock superblock. mainly for entry point functions */
22604+/*
b752ccd1
AM
22605+ * __si_read_lock, __si_write_lock,
22606+ * __si_read_unlock, __si_write_unlock, __si_downgrade_lock
1facf9fc 22607+ */
b752ccd1 22608+AuSimpleRwsemFuncs(__si, struct super_block *sb, &au_sbi(sb)->si_rwsem);
1facf9fc 22609+
dece6358
AM
22610+#define SiMustNoWaiters(sb) AuRwMustNoWaiters(&au_sbi(sb)->si_rwsem)
22611+#define SiMustAnyLock(sb) AuRwMustAnyLock(&au_sbi(sb)->si_rwsem)
22612+#define SiMustWriteLock(sb) AuRwMustWriteLock(&au_sbi(sb)->si_rwsem)
22613+
b752ccd1
AM
22614+static inline void si_noflush_read_lock(struct super_block *sb)
22615+{
22616+ __si_read_lock(sb);
22617+ si_pid_set(sb);
22618+}
22619+
22620+static inline int si_noflush_read_trylock(struct super_block *sb)
22621+{
22622+ int locked = __si_read_trylock(sb);
22623+ if (locked)
22624+ si_pid_set(sb);
22625+ return locked;
22626+}
22627+
22628+static inline void si_noflush_write_lock(struct super_block *sb)
22629+{
22630+ __si_write_lock(sb);
22631+ si_pid_set(sb);
22632+}
22633+
22634+static inline int si_noflush_write_trylock(struct super_block *sb)
22635+{
22636+ int locked = __si_write_trylock(sb);
22637+ if (locked)
22638+ si_pid_set(sb);
22639+ return locked;
22640+}
22641+
e49829fe 22642+#if 0 /* unused */
1facf9fc 22643+static inline int si_read_trylock(struct super_block *sb, int flags)
22644+{
22645+ if (au_ftest_lock(flags, FLUSH))
22646+ au_nwt_flush(&au_sbi(sb)->si_nowait);
22647+ return si_noflush_read_trylock(sb);
22648+}
e49829fe 22649+#endif
1facf9fc 22650+
b752ccd1
AM
22651+static inline void si_read_unlock(struct super_block *sb)
22652+{
22653+ si_pid_clr(sb);
22654+ __si_read_unlock(sb);
22655+}
22656+
b752ccd1 22657+#if 0 /* unused */
1facf9fc 22658+static inline int si_write_trylock(struct super_block *sb, int flags)
22659+{
22660+ if (au_ftest_lock(flags, FLUSH))
22661+ au_nwt_flush(&au_sbi(sb)->si_nowait);
22662+ return si_noflush_write_trylock(sb);
22663+}
b752ccd1
AM
22664+#endif
22665+
22666+static inline void si_write_unlock(struct super_block *sb)
22667+{
22668+ si_pid_clr(sb);
22669+ __si_write_unlock(sb);
22670+}
22671+
22672+#if 0 /* unused */
22673+static inline void si_downgrade_lock(struct super_block *sb)
22674+{
22675+ __si_downgrade_lock(sb);
22676+}
22677+#endif
1facf9fc 22678+
22679+/* ---------------------------------------------------------------------- */
22680+
22681+static inline aufs_bindex_t au_sbend(struct super_block *sb)
22682+{
dece6358 22683+ SiMustAnyLock(sb);
1facf9fc 22684+ return au_sbi(sb)->si_bend;
22685+}
22686+
22687+static inline unsigned int au_mntflags(struct super_block *sb)
22688+{
dece6358 22689+ SiMustAnyLock(sb);
1facf9fc 22690+ return au_sbi(sb)->si_mntflags;
22691+}
22692+
22693+static inline unsigned int au_sigen(struct super_block *sb)
22694+{
dece6358 22695+ SiMustAnyLock(sb);
1facf9fc 22696+ return au_sbi(sb)->si_generation;
22697+}
22698+
7f207e10
AM
22699+static inline void au_ninodes_inc(struct super_block *sb)
22700+{
22701+ atomic_long_inc(&au_sbi(sb)->si_ninodes);
22702+}
22703+
22704+static inline void au_ninodes_dec(struct super_block *sb)
22705+{
22706+ AuDebugOn(!atomic_long_read(&au_sbi(sb)->si_ninodes));
22707+ atomic_long_dec(&au_sbi(sb)->si_ninodes);
22708+}
22709+
22710+static inline void au_nfiles_inc(struct super_block *sb)
22711+{
22712+ atomic_long_inc(&au_sbi(sb)->si_nfiles);
22713+}
22714+
22715+static inline void au_nfiles_dec(struct super_block *sb)
22716+{
22717+ AuDebugOn(!atomic_long_read(&au_sbi(sb)->si_nfiles));
22718+ atomic_long_dec(&au_sbi(sb)->si_nfiles);
22719+}
22720+
1facf9fc 22721+static inline struct au_branch *au_sbr(struct super_block *sb,
22722+ aufs_bindex_t bindex)
22723+{
dece6358 22724+ SiMustAnyLock(sb);
1facf9fc 22725+ return au_sbi(sb)->si_branch[0 + bindex];
22726+}
22727+
22728+static inline void au_xino_brid_set(struct super_block *sb, aufs_bindex_t brid)
22729+{
dece6358 22730+ SiMustWriteLock(sb);
1facf9fc 22731+ au_sbi(sb)->si_xino_brid = brid;
22732+}
22733+
22734+static inline aufs_bindex_t au_xino_brid(struct super_block *sb)
22735+{
dece6358 22736+ SiMustAnyLock(sb);
1facf9fc 22737+ return au_sbi(sb)->si_xino_brid;
22738+}
22739+
22740+#endif /* __KERNEL__ */
22741+#endif /* __AUFS_SUPER_H__ */
7f207e10
AM
22742diff -urN /usr/share/empty/fs/aufs/sysaufs.c linux/fs/aufs/sysaufs.c
22743--- /usr/share/empty/fs/aufs/sysaufs.c 1970-01-01 01:00:00.000000000 +0100
87a755f4 22744+++ linux/fs/aufs/sysaufs.c 2011-03-17 10:46:59.000000000 +0100
4a4d8108 22745@@ -0,0 +1,107 @@
1facf9fc 22746+/*
027c5e7a 22747+ * Copyright (C) 2005-2011 Junjiro R. Okajima
1facf9fc 22748+ *
22749+ * This program, aufs is free software; you can redistribute it and/or modify
22750+ * it under the terms of the GNU General Public License as published by
22751+ * the Free Software Foundation; either version 2 of the License, or
22752+ * (at your option) any later version.
dece6358
AM
22753+ *
22754+ * This program is distributed in the hope that it will be useful,
22755+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
22756+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22757+ * GNU General Public License for more details.
22758+ *
22759+ * You should have received a copy of the GNU General Public License
22760+ * along with this program; if not, write to the Free Software
22761+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 22762+ */
22763+
22764+/*
22765+ * sysfs interface and lifetime management
22766+ * they are necessary regardless sysfs is disabled.
22767+ */
22768+
22769+#include <linux/fs.h>
22770+#include <linux/random.h>
22771+#include <linux/sysfs.h>
22772+#include "aufs.h"
22773+
22774+unsigned long sysaufs_si_mask;
e49829fe 22775+struct kset *sysaufs_kset;
1facf9fc 22776+
22777+#define AuSiAttr(_name) { \
22778+ .attr = { .name = __stringify(_name), .mode = 0444 }, \
22779+ .show = sysaufs_si_##_name, \
22780+}
22781+
22782+static struct sysaufs_si_attr sysaufs_si_attr_xi_path = AuSiAttr(xi_path);
22783+struct attribute *sysaufs_si_attrs[] = {
22784+ &sysaufs_si_attr_xi_path.attr,
22785+ NULL,
22786+};
22787+
4a4d8108 22788+static const struct sysfs_ops au_sbi_ops = {
1facf9fc 22789+ .show = sysaufs_si_show
22790+};
22791+
22792+static struct kobj_type au_sbi_ktype = {
22793+ .release = au_si_free,
22794+ .sysfs_ops = &au_sbi_ops,
22795+ .default_attrs = sysaufs_si_attrs
22796+};
22797+
22798+/* ---------------------------------------------------------------------- */
22799+
22800+int sysaufs_si_init(struct au_sbinfo *sbinfo)
22801+{
22802+ int err;
22803+
e49829fe 22804+ sbinfo->si_kobj.kset = sysaufs_kset;
1facf9fc 22805+ /* cf. sysaufs_name() */
22806+ err = kobject_init_and_add
e49829fe 22807+ (&sbinfo->si_kobj, &au_sbi_ktype, /*&sysaufs_kset->kobj*/NULL,
1facf9fc 22808+ SysaufsSiNamePrefix "%lx", sysaufs_si_id(sbinfo));
22809+
22810+ dbgaufs_si_null(sbinfo);
22811+ if (!err) {
22812+ err = dbgaufs_si_init(sbinfo);
22813+ if (unlikely(err))
22814+ kobject_put(&sbinfo->si_kobj);
22815+ }
22816+ return err;
22817+}
22818+
22819+void sysaufs_fin(void)
22820+{
22821+ dbgaufs_fin();
e49829fe
JR
22822+ sysfs_remove_group(&sysaufs_kset->kobj, sysaufs_attr_group);
22823+ kset_unregister(sysaufs_kset);
1facf9fc 22824+}
22825+
22826+int __init sysaufs_init(void)
22827+{
22828+ int err;
22829+
22830+ do {
22831+ get_random_bytes(&sysaufs_si_mask, sizeof(sysaufs_si_mask));
22832+ } while (!sysaufs_si_mask);
22833+
4a4d8108 22834+ err = -EINVAL;
e49829fe
JR
22835+ sysaufs_kset = kset_create_and_add(AUFS_NAME, NULL, fs_kobj);
22836+ if (unlikely(!sysaufs_kset))
4a4d8108 22837+ goto out;
e49829fe
JR
22838+ err = PTR_ERR(sysaufs_kset);
22839+ if (IS_ERR(sysaufs_kset))
1facf9fc 22840+ goto out;
e49829fe 22841+ err = sysfs_create_group(&sysaufs_kset->kobj, sysaufs_attr_group);
1facf9fc 22842+ if (unlikely(err)) {
e49829fe 22843+ kset_unregister(sysaufs_kset);
1facf9fc 22844+ goto out;
22845+ }
22846+
22847+ err = dbgaufs_init();
22848+ if (unlikely(err))
22849+ sysaufs_fin();
4f0767ce 22850+out:
1facf9fc 22851+ return err;
22852+}
7f207e10
AM
22853diff -urN /usr/share/empty/fs/aufs/sysaufs.h linux/fs/aufs/sysaufs.h
22854--- /usr/share/empty/fs/aufs/sysaufs.h 1970-01-01 01:00:00.000000000 +0100
87a755f4 22855+++ linux/fs/aufs/sysaufs.h 2011-03-17 10:46:59.000000000 +0100
4a4d8108 22856@@ -0,0 +1,105 @@
1facf9fc 22857+/*
027c5e7a 22858+ * Copyright (C) 2005-2011 Junjiro R. Okajima
1facf9fc 22859+ *
22860+ * This program, aufs is free software; you can redistribute it and/or modify
22861+ * it under the terms of the GNU General Public License as published by
22862+ * the Free Software Foundation; either version 2 of the License, or
22863+ * (at your option) any later version.
dece6358
AM
22864+ *
22865+ * This program is distributed in the hope that it will be useful,
22866+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
22867+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22868+ * GNU General Public License for more details.
22869+ *
22870+ * You should have received a copy of the GNU General Public License
22871+ * along with this program; if not, write to the Free Software
22872+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 22873+ */
22874+
22875+/*
22876+ * sysfs interface and mount lifetime management
22877+ */
22878+
22879+#ifndef __SYSAUFS_H__
22880+#define __SYSAUFS_H__
22881+
22882+#ifdef __KERNEL__
22883+
1facf9fc 22884+#include <linux/sysfs.h>
22885+#include <linux/aufs_type.h>
22886+#include "module.h"
22887+
dece6358
AM
22888+struct super_block;
22889+struct au_sbinfo;
22890+
1facf9fc 22891+struct sysaufs_si_attr {
22892+ struct attribute attr;
22893+ int (*show)(struct seq_file *seq, struct super_block *sb);
22894+};
22895+
22896+/* ---------------------------------------------------------------------- */
22897+
22898+/* sysaufs.c */
22899+extern unsigned long sysaufs_si_mask;
e49829fe 22900+extern struct kset *sysaufs_kset;
1facf9fc 22901+extern struct attribute *sysaufs_si_attrs[];
22902+int sysaufs_si_init(struct au_sbinfo *sbinfo);
22903+int __init sysaufs_init(void);
22904+void sysaufs_fin(void);
22905+
22906+/* ---------------------------------------------------------------------- */
22907+
22908+/* some people doesn't like to show a pointer in kernel */
22909+static inline unsigned long sysaufs_si_id(struct au_sbinfo *sbinfo)
22910+{
22911+ return sysaufs_si_mask ^ (unsigned long)sbinfo;
22912+}
22913+
22914+#define SysaufsSiNamePrefix "si_"
22915+#define SysaufsSiNameLen (sizeof(SysaufsSiNamePrefix) + 16)
22916+static inline void sysaufs_name(struct au_sbinfo *sbinfo, char *name)
22917+{
22918+ snprintf(name, SysaufsSiNameLen, SysaufsSiNamePrefix "%lx",
22919+ sysaufs_si_id(sbinfo));
22920+}
22921+
22922+struct au_branch;
22923+#ifdef CONFIG_SYSFS
22924+/* sysfs.c */
22925+extern struct attribute_group *sysaufs_attr_group;
22926+
22927+int sysaufs_si_xi_path(struct seq_file *seq, struct super_block *sb);
22928+ssize_t sysaufs_si_show(struct kobject *kobj, struct attribute *attr,
22929+ char *buf);
22930+
22931+void sysaufs_br_init(struct au_branch *br);
22932+void sysaufs_brs_add(struct super_block *sb, aufs_bindex_t bindex);
22933+void sysaufs_brs_del(struct super_block *sb, aufs_bindex_t bindex);
22934+
22935+#define sysaufs_brs_init() do {} while (0)
22936+
22937+#else
22938+#define sysaufs_attr_group NULL
22939+
4a4d8108 22940+AuStubInt0(sysaufs_si_xi_path, struct seq_file *seq, struct super_block *sb)
1facf9fc 22941+
22942+static inline
22943+ssize_t sysaufs_si_show(struct kobject *kobj, struct attribute *attr,
22944+ char *buf)
22945+{
22946+ return 0;
22947+}
22948+
4a4d8108
AM
22949+AuStubVoid(sysaufs_br_init, struct au_branch *br)
22950+AuStubVoid(sysaufs_brs_add, struct super_block *sb, aufs_bindex_t bindex)
22951+AuStubVoid(sysaufs_brs_del, struct super_block *sb, aufs_bindex_t bindex)
1facf9fc 22952+
22953+static inline void sysaufs_brs_init(void)
22954+{
22955+ sysaufs_brs = 0;
22956+}
22957+
22958+#endif /* CONFIG_SYSFS */
22959+
22960+#endif /* __KERNEL__ */
22961+#endif /* __SYSAUFS_H__ */
7f207e10
AM
22962diff -urN /usr/share/empty/fs/aufs/sysfs.c linux/fs/aufs/sysfs.c
22963--- /usr/share/empty/fs/aufs/sysfs.c 1970-01-01 01:00:00.000000000 +0100
87a755f4 22964+++ linux/fs/aufs/sysfs.c 2011-03-17 10:46:59.000000000 +0100
953406b4 22965@@ -0,0 +1,250 @@
1facf9fc 22966+/*
027c5e7a 22967+ * Copyright (C) 2005-2011 Junjiro R. Okajima
1facf9fc 22968+ *
22969+ * This program, aufs is free software; you can redistribute it and/or modify
22970+ * it under the terms of the GNU General Public License as published by
22971+ * the Free Software Foundation; either version 2 of the License, or
22972+ * (at your option) any later version.
dece6358
AM
22973+ *
22974+ * This program is distributed in the hope that it will be useful,
22975+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
22976+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22977+ * GNU General Public License for more details.
22978+ *
22979+ * You should have received a copy of the GNU General Public License
22980+ * along with this program; if not, write to the Free Software
22981+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 22982+ */
22983+
22984+/*
22985+ * sysfs interface
22986+ */
22987+
22988+#include <linux/fs.h>
dece6358 22989+#include <linux/module.h>
1facf9fc 22990+#include <linux/seq_file.h>
22991+#include <linux/sysfs.h>
22992+#include "aufs.h"
22993+
4a4d8108
AM
22994+#ifdef CONFIG_AUFS_FS_MODULE
22995+/* this entry violates the "one line per file" policy of sysfs */
22996+static ssize_t config_show(struct kobject *kobj, struct kobj_attribute *attr,
22997+ char *buf)
22998+{
22999+ ssize_t err;
23000+ static char *conf =
23001+/* this file is generated at compiling */
23002+#include "conf.str"
23003+ ;
23004+
23005+ err = snprintf(buf, PAGE_SIZE, conf);
23006+ if (unlikely(err >= PAGE_SIZE))
23007+ err = -EFBIG;
23008+ return err;
23009+}
23010+
23011+static struct kobj_attribute au_config_attr = __ATTR_RO(config);
23012+#endif
23013+
1facf9fc 23014+static struct attribute *au_attr[] = {
4a4d8108
AM
23015+#ifdef CONFIG_AUFS_FS_MODULE
23016+ &au_config_attr.attr,
23017+#endif
1facf9fc 23018+ NULL, /* need to NULL terminate the list of attributes */
23019+};
23020+
23021+static struct attribute_group sysaufs_attr_group_body = {
23022+ .attrs = au_attr
23023+};
23024+
23025+struct attribute_group *sysaufs_attr_group = &sysaufs_attr_group_body;
23026+
23027+/* ---------------------------------------------------------------------- */
23028+
23029+int sysaufs_si_xi_path(struct seq_file *seq, struct super_block *sb)
23030+{
23031+ int err;
23032+
dece6358
AM
23033+ SiMustAnyLock(sb);
23034+
1facf9fc 23035+ err = 0;
23036+ if (au_opt_test(au_mntflags(sb), XINO)) {
23037+ err = au_xino_path(seq, au_sbi(sb)->si_xib);
23038+ seq_putc(seq, '\n');
23039+ }
23040+ return err;
23041+}
23042+
23043+/*
23044+ * the lifetime of branch is independent from the entry under sysfs.
23045+ * sysfs handles the lifetime of the entry, and never call ->show() after it is
23046+ * unlinked.
23047+ */
23048+static int sysaufs_si_br(struct seq_file *seq, struct super_block *sb,
23049+ aufs_bindex_t bindex)
23050+{
23051+ struct path path;
23052+ struct dentry *root;
23053+ struct au_branch *br;
23054+
23055+ AuDbg("b%d\n", bindex);
23056+
23057+ root = sb->s_root;
23058+ di_read_lock_parent(root, !AuLock_IR);
23059+ br = au_sbr(sb, bindex);
23060+ path.mnt = br->br_mnt;
23061+ path.dentry = au_h_dptr(root, bindex);
23062+ au_seq_path(seq, &path);
23063+ di_read_unlock(root, !AuLock_IR);
23064+ seq_printf(seq, "=%s\n", au_optstr_br_perm(br->br_perm));
23065+ return 0;
23066+}
23067+
23068+/* ---------------------------------------------------------------------- */
23069+
23070+static struct seq_file *au_seq(char *p, ssize_t len)
23071+{
23072+ struct seq_file *seq;
23073+
23074+ seq = kzalloc(sizeof(*seq), GFP_NOFS);
23075+ if (seq) {
23076+ /* mutex_init(&seq.lock); */
23077+ seq->buf = p;
23078+ seq->size = len;
23079+ return seq; /* success */
23080+ }
23081+
23082+ seq = ERR_PTR(-ENOMEM);
23083+ return seq;
23084+}
23085+
23086+#define SysaufsBr_PREFIX "br"
23087+
23088+/* todo: file size may exceed PAGE_SIZE */
23089+ssize_t sysaufs_si_show(struct kobject *kobj, struct attribute *attr,
1308ab2a 23090+ char *buf)
1facf9fc 23091+{
23092+ ssize_t err;
23093+ long l;
23094+ aufs_bindex_t bend;
23095+ struct au_sbinfo *sbinfo;
23096+ struct super_block *sb;
23097+ struct seq_file *seq;
23098+ char *name;
23099+ struct attribute **cattr;
23100+
23101+ sbinfo = container_of(kobj, struct au_sbinfo, si_kobj);
23102+ sb = sbinfo->si_sb;
1308ab2a 23103+
23104+ /*
23105+ * prevent a race condition between sysfs and aufs.
23106+ * for instance, sysfs_file_read() calls sysfs_get_active_two() which
23107+ * prohibits maintaining the sysfs entries.
23108+ * hew we acquire read lock after sysfs_get_active_two().
23109+ * on the other hand, the remount process may maintain the sysfs/aufs
23110+ * entries after acquiring write lock.
23111+ * it can cause a deadlock.
23112+ * simply we gave up processing read here.
23113+ */
23114+ err = -EBUSY;
23115+ if (unlikely(!si_noflush_read_trylock(sb)))
23116+ goto out;
1facf9fc 23117+
23118+ seq = au_seq(buf, PAGE_SIZE);
23119+ err = PTR_ERR(seq);
23120+ if (IS_ERR(seq))
1308ab2a 23121+ goto out_unlock;
1facf9fc 23122+
23123+ name = (void *)attr->name;
23124+ cattr = sysaufs_si_attrs;
23125+ while (*cattr) {
23126+ if (!strcmp(name, (*cattr)->name)) {
23127+ err = container_of(*cattr, struct sysaufs_si_attr, attr)
23128+ ->show(seq, sb);
23129+ goto out_seq;
23130+ }
23131+ cattr++;
23132+ }
23133+
23134+ bend = au_sbend(sb);
23135+ if (!strncmp(name, SysaufsBr_PREFIX, sizeof(SysaufsBr_PREFIX) - 1)) {
23136+ name += sizeof(SysaufsBr_PREFIX) - 1;
23137+ err = strict_strtol(name, 10, &l);
23138+ if (!err) {
23139+ if (l <= bend)
23140+ err = sysaufs_si_br(seq, sb, (aufs_bindex_t)l);
23141+ else
23142+ err = -ENOENT;
23143+ }
23144+ goto out_seq;
23145+ }
23146+ BUG();
23147+
4f0767ce 23148+out_seq:
1facf9fc 23149+ if (!err) {
23150+ err = seq->count;
23151+ /* sysfs limit */
23152+ if (unlikely(err == PAGE_SIZE))
23153+ err = -EFBIG;
23154+ }
23155+ kfree(seq);
4f0767ce 23156+out_unlock:
1facf9fc 23157+ si_read_unlock(sb);
4f0767ce 23158+out:
1facf9fc 23159+ return err;
23160+}
23161+
23162+/* ---------------------------------------------------------------------- */
23163+
23164+void sysaufs_br_init(struct au_branch *br)
23165+{
4a4d8108
AM
23166+ struct attribute *attr = &br->br_attr;
23167+
23168+ sysfs_attr_init(attr);
23169+ attr->name = br->br_name;
23170+ attr->mode = S_IRUGO;
1facf9fc 23171+}
23172+
23173+void sysaufs_brs_del(struct super_block *sb, aufs_bindex_t bindex)
23174+{
23175+ struct au_branch *br;
23176+ struct kobject *kobj;
23177+ aufs_bindex_t bend;
23178+
23179+ dbgaufs_brs_del(sb, bindex);
23180+
23181+ if (!sysaufs_brs)
23182+ return;
23183+
23184+ kobj = &au_sbi(sb)->si_kobj;
23185+ bend = au_sbend(sb);
23186+ for (; bindex <= bend; bindex++) {
23187+ br = au_sbr(sb, bindex);
23188+ sysfs_remove_file(kobj, &br->br_attr);
23189+ }
23190+}
23191+
23192+void sysaufs_brs_add(struct super_block *sb, aufs_bindex_t bindex)
23193+{
23194+ int err;
23195+ aufs_bindex_t bend;
23196+ struct kobject *kobj;
23197+ struct au_branch *br;
23198+
23199+ dbgaufs_brs_add(sb, bindex);
23200+
23201+ if (!sysaufs_brs)
23202+ return;
23203+
23204+ kobj = &au_sbi(sb)->si_kobj;
23205+ bend = au_sbend(sb);
23206+ for (; bindex <= bend; bindex++) {
23207+ br = au_sbr(sb, bindex);
23208+ snprintf(br->br_name, sizeof(br->br_name), SysaufsBr_PREFIX
23209+ "%d", bindex);
23210+ err = sysfs_create_file(kobj, &br->br_attr);
23211+ if (unlikely(err))
4a4d8108
AM
23212+ pr_warning("failed %s under sysfs(%d)\n",
23213+ br->br_name, err);
1facf9fc 23214+ }
23215+}
7f207e10
AM
23216diff -urN /usr/share/empty/fs/aufs/sysrq.c linux/fs/aufs/sysrq.c
23217--- /usr/share/empty/fs/aufs/sysrq.c 1970-01-01 01:00:00.000000000 +0100
87a755f4 23218+++ linux/fs/aufs/sysrq.c 2011-07-22 08:26:47.857636522 +0200
2cbb1c4b 23219@@ -0,0 +1,151 @@
1facf9fc 23220+/*
027c5e7a 23221+ * Copyright (C) 2005-2011 Junjiro R. Okajima
1facf9fc 23222+ *
23223+ * This program, aufs is free software; you can redistribute it and/or modify
23224+ * it under the terms of the GNU General Public License as published by
23225+ * the Free Software Foundation; either version 2 of the License, or
23226+ * (at your option) any later version.
dece6358
AM
23227+ *
23228+ * This program is distributed in the hope that it will be useful,
23229+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
23230+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23231+ * GNU General Public License for more details.
23232+ *
23233+ * You should have received a copy of the GNU General Public License
23234+ * along with this program; if not, write to the Free Software
23235+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 23236+ */
23237+
23238+/*
23239+ * magic sysrq hanlder
23240+ */
23241+
23242+#include <linux/fs.h>
23243+#include <linux/module.h>
23244+#include <linux/moduleparam.h>
23245+/* #include <linux/sysrq.h> */
027c5e7a 23246+#include <linux/writeback.h>
1facf9fc 23247+#include "aufs.h"
23248+
23249+/* ---------------------------------------------------------------------- */
23250+
23251+static void sysrq_sb(struct super_block *sb)
23252+{
23253+ char *plevel;
23254+ struct au_sbinfo *sbinfo;
23255+ struct file *file;
23256+
23257+ plevel = au_plevel;
23258+ au_plevel = KERN_WARNING;
1facf9fc 23259+
23260+ sbinfo = au_sbi(sb);
4a4d8108
AM
23261+ /* since we define pr_fmt, call printk directly */
23262+ printk(KERN_WARNING "si=%lx\n", sysaufs_si_id(sbinfo));
23263+ printk(KERN_WARNING AUFS_NAME ": superblock\n");
1facf9fc 23264+ au_dpri_sb(sb);
027c5e7a
AM
23265+
23266+#if 0
4a4d8108 23267+ printk(KERN_WARNING AUFS_NAME ": root dentry\n");
1facf9fc 23268+ au_dpri_dentry(sb->s_root);
4a4d8108 23269+ printk(KERN_WARNING AUFS_NAME ": root inode\n");
1facf9fc 23270+ au_dpri_inode(sb->s_root->d_inode);
027c5e7a
AM
23271+#endif
23272+
1facf9fc 23273+#if 0
027c5e7a
AM
23274+ do {
23275+ int err, i, j, ndentry;
23276+ struct au_dcsub_pages dpages;
23277+ struct au_dpage *dpage;
23278+
23279+ err = au_dpages_init(&dpages, GFP_ATOMIC);
23280+ if (unlikely(err))
23281+ break;
23282+ err = au_dcsub_pages(&dpages, sb->s_root, NULL, NULL);
23283+ if (!err)
23284+ for (i = 0; i < dpages.ndpage; i++) {
23285+ dpage = dpages.dpages + i;
23286+ ndentry = dpage->ndentry;
23287+ for (j = 0; j < ndentry; j++)
23288+ au_dpri_dentry(dpage->dentries[j]);
23289+ }
23290+ au_dpages_free(&dpages);
23291+ } while (0);
23292+#endif
23293+
23294+#if 1
23295+ {
23296+ struct inode *i;
23297+ printk(KERN_WARNING AUFS_NAME ": isolated inode\n");
2cbb1c4b
JR
23298+ spin_lock(&inode_sb_list_lock);
23299+ list_for_each_entry(i, &sb->s_inodes, i_sb_list) {
23300+ spin_lock(&i->i_lock);
027c5e7a
AM
23301+ if (1 || list_empty(&i->i_dentry))
23302+ au_dpri_inode(i);
2cbb1c4b
JR
23303+ spin_unlock(&i->i_lock);
23304+ }
23305+ spin_unlock(&inode_sb_list_lock);
027c5e7a 23306+ }
1facf9fc 23307+#endif
4a4d8108 23308+ printk(KERN_WARNING AUFS_NAME ": files\n");
0c5527e5
AM
23309+ lg_global_lock(files_lglock);
23310+ do_file_list_for_each_entry(sb, file) {
4a4d8108
AM
23311+ umode_t mode;
23312+ mode = file->f_dentry->d_inode->i_mode;
23313+ if (!special_file(mode) || au_special_file(mode))
1facf9fc 23314+ au_dpri_file(file);
0c5527e5
AM
23315+ } while_file_list_for_each_entry;
23316+ lg_global_unlock(files_lglock);
e49829fe 23317+ printk(KERN_WARNING AUFS_NAME ": done\n");
1facf9fc 23318+
23319+ au_plevel = plevel;
1facf9fc 23320+}
23321+
23322+/* ---------------------------------------------------------------------- */
23323+
23324+/* module parameter */
23325+static char *aufs_sysrq_key = "a";
23326+module_param_named(sysrq, aufs_sysrq_key, charp, S_IRUGO);
23327+MODULE_PARM_DESC(sysrq, "MagicSysRq key for " AUFS_NAME);
23328+
0c5527e5 23329+static void au_sysrq(int key __maybe_unused)
1facf9fc 23330+{
1facf9fc 23331+ struct au_sbinfo *sbinfo;
23332+
027c5e7a 23333+ lockdep_off();
e49829fe
JR
23334+ spin_lock(&au_sbilist.spin);
23335+ list_for_each_entry(sbinfo, &au_sbilist.head, si_list)
1facf9fc 23336+ sysrq_sb(sbinfo->si_sb);
e49829fe 23337+ spin_unlock(&au_sbilist.spin);
027c5e7a 23338+ lockdep_on();
1facf9fc 23339+}
23340+
23341+static struct sysrq_key_op au_sysrq_op = {
23342+ .handler = au_sysrq,
23343+ .help_msg = "Aufs",
23344+ .action_msg = "Aufs",
23345+ .enable_mask = SYSRQ_ENABLE_DUMP
23346+};
23347+
23348+/* ---------------------------------------------------------------------- */
23349+
23350+int __init au_sysrq_init(void)
23351+{
23352+ int err;
23353+ char key;
23354+
23355+ err = -1;
23356+ key = *aufs_sysrq_key;
23357+ if ('a' <= key && key <= 'z')
23358+ err = register_sysrq_key(key, &au_sysrq_op);
23359+ if (unlikely(err))
4a4d8108 23360+ pr_err("err %d, sysrq=%c\n", err, key);
1facf9fc 23361+ return err;
23362+}
23363+
23364+void au_sysrq_fin(void)
23365+{
23366+ int err;
23367+ err = unregister_sysrq_key(*aufs_sysrq_key, &au_sysrq_op);
23368+ if (unlikely(err))
4a4d8108 23369+ pr_err("err %d (ignored)\n", err);
1facf9fc 23370+}
7f207e10
AM
23371diff -urN /usr/share/empty/fs/aufs/vdir.c linux/fs/aufs/vdir.c
23372--- /usr/share/empty/fs/aufs/vdir.c 1970-01-01 01:00:00.000000000 +0100
87a755f4 23373+++ linux/fs/aufs/vdir.c 2011-03-17 10:46:59.000000000 +0100
7f207e10 23374@@ -0,0 +1,886 @@
1facf9fc 23375+/*
027c5e7a 23376+ * Copyright (C) 2005-2011 Junjiro R. Okajima
1facf9fc 23377+ *
23378+ * This program, aufs is free software; you can redistribute it and/or modify
23379+ * it under the terms of the GNU General Public License as published by
23380+ * the Free Software Foundation; either version 2 of the License, or
23381+ * (at your option) any later version.
dece6358
AM
23382+ *
23383+ * This program is distributed in the hope that it will be useful,
23384+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
23385+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23386+ * GNU General Public License for more details.
23387+ *
23388+ * You should have received a copy of the GNU General Public License
23389+ * along with this program; if not, write to the Free Software
23390+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 23391+ */
23392+
23393+/*
23394+ * virtual or vertical directory
23395+ */
23396+
dece6358 23397+#include <linux/hash.h>
1facf9fc 23398+#include "aufs.h"
23399+
dece6358 23400+static unsigned int calc_size(int nlen)
1facf9fc 23401+{
dece6358 23402+ return ALIGN(sizeof(struct au_vdir_de) + nlen, sizeof(ino_t));
1facf9fc 23403+}
23404+
23405+static int set_deblk_end(union au_vdir_deblk_p *p,
23406+ union au_vdir_deblk_p *deblk_end)
23407+{
23408+ if (calc_size(0) <= deblk_end->deblk - p->deblk) {
23409+ p->de->de_str.len = 0;
23410+ /* smp_mb(); */
23411+ return 0;
23412+ }
23413+ return -1; /* error */
23414+}
23415+
23416+/* returns true or false */
23417+static int is_deblk_end(union au_vdir_deblk_p *p,
23418+ union au_vdir_deblk_p *deblk_end)
23419+{
23420+ if (calc_size(0) <= deblk_end->deblk - p->deblk)
23421+ return !p->de->de_str.len;
23422+ return 1;
23423+}
23424+
23425+static unsigned char *last_deblk(struct au_vdir *vdir)
23426+{
23427+ return vdir->vd_deblk[vdir->vd_nblk - 1];
23428+}
23429+
23430+/* ---------------------------------------------------------------------- */
23431+
1308ab2a 23432+/* estimate the apropriate size for name hash table */
23433+unsigned int au_rdhash_est(loff_t sz)
23434+{
23435+ unsigned int n;
23436+
23437+ n = UINT_MAX;
23438+ sz >>= 10;
23439+ if (sz < n)
23440+ n = sz;
23441+ if (sz < AUFS_RDHASH_DEF)
23442+ n = AUFS_RDHASH_DEF;
4a4d8108 23443+ /* pr_info("n %u\n", n); */
1308ab2a 23444+ return n;
23445+}
23446+
1facf9fc 23447+/*
23448+ * the allocated memory has to be freed by
dece6358 23449+ * au_nhash_wh_free() or au_nhash_de_free().
1facf9fc 23450+ */
dece6358 23451+int au_nhash_alloc(struct au_nhash *nhash, unsigned int num_hash, gfp_t gfp)
1facf9fc 23452+{
1facf9fc 23453+ struct hlist_head *head;
dece6358 23454+ unsigned int u;
1facf9fc 23455+
dece6358
AM
23456+ head = kmalloc(sizeof(*nhash->nh_head) * num_hash, gfp);
23457+ if (head) {
23458+ nhash->nh_num = num_hash;
23459+ nhash->nh_head = head;
23460+ for (u = 0; u < num_hash; u++)
1facf9fc 23461+ INIT_HLIST_HEAD(head++);
dece6358 23462+ return 0; /* success */
1facf9fc 23463+ }
1facf9fc 23464+
dece6358 23465+ return -ENOMEM;
1facf9fc 23466+}
23467+
dece6358
AM
23468+static void nhash_count(struct hlist_head *head)
23469+{
23470+#if 0
23471+ unsigned long n;
23472+ struct hlist_node *pos;
23473+
23474+ n = 0;
23475+ hlist_for_each(pos, head)
23476+ n++;
4a4d8108 23477+ pr_info("%lu\n", n);
dece6358
AM
23478+#endif
23479+}
23480+
23481+static void au_nhash_wh_do_free(struct hlist_head *head)
1facf9fc 23482+{
1facf9fc 23483+ struct au_vdir_wh *tpos;
23484+ struct hlist_node *pos, *node;
23485+
dece6358
AM
23486+ hlist_for_each_entry_safe(tpos, pos, node, head, wh_hash) {
23487+ /* hlist_del(pos); */
23488+ kfree(tpos);
1facf9fc 23489+ }
23490+}
23491+
dece6358 23492+static void au_nhash_de_do_free(struct hlist_head *head)
1facf9fc 23493+{
dece6358
AM
23494+ struct au_vdir_dehstr *tpos;
23495+ struct hlist_node *pos, *node;
1facf9fc 23496+
dece6358
AM
23497+ hlist_for_each_entry_safe(tpos, pos, node, head, hash) {
23498+ /* hlist_del(pos); */
4a4d8108 23499+ au_cache_free_vdir_dehstr(tpos);
1facf9fc 23500+ }
1facf9fc 23501+}
23502+
dece6358
AM
23503+static void au_nhash_do_free(struct au_nhash *nhash,
23504+ void (*free)(struct hlist_head *head))
1facf9fc 23505+{
1308ab2a 23506+ unsigned int n;
1facf9fc 23507+ struct hlist_head *head;
1facf9fc 23508+
dece6358 23509+ n = nhash->nh_num;
1308ab2a 23510+ if (!n)
23511+ return;
23512+
dece6358 23513+ head = nhash->nh_head;
1308ab2a 23514+ while (n-- > 0) {
dece6358
AM
23515+ nhash_count(head);
23516+ free(head++);
1facf9fc 23517+ }
dece6358 23518+ kfree(nhash->nh_head);
1facf9fc 23519+}
23520+
dece6358 23521+void au_nhash_wh_free(struct au_nhash *whlist)
1facf9fc 23522+{
dece6358
AM
23523+ au_nhash_do_free(whlist, au_nhash_wh_do_free);
23524+}
1facf9fc 23525+
dece6358
AM
23526+static void au_nhash_de_free(struct au_nhash *delist)
23527+{
23528+ au_nhash_do_free(delist, au_nhash_de_do_free);
1facf9fc 23529+}
23530+
23531+/* ---------------------------------------------------------------------- */
23532+
23533+int au_nhash_test_longer_wh(struct au_nhash *whlist, aufs_bindex_t btgt,
23534+ int limit)
23535+{
23536+ int num;
23537+ unsigned int u, n;
23538+ struct hlist_head *head;
23539+ struct au_vdir_wh *tpos;
23540+ struct hlist_node *pos;
23541+
23542+ num = 0;
23543+ n = whlist->nh_num;
23544+ head = whlist->nh_head;
1308ab2a 23545+ for (u = 0; u < n; u++, head++)
1facf9fc 23546+ hlist_for_each_entry(tpos, pos, head, wh_hash)
23547+ if (tpos->wh_bindex == btgt && ++num > limit)
23548+ return 1;
1facf9fc 23549+ return 0;
23550+}
23551+
23552+static struct hlist_head *au_name_hash(struct au_nhash *nhash,
dece6358 23553+ unsigned char *name,
1facf9fc 23554+ unsigned int len)
23555+{
dece6358
AM
23556+ unsigned int v;
23557+ /* const unsigned int magic_bit = 12; */
23558+
1308ab2a 23559+ AuDebugOn(!nhash->nh_num || !nhash->nh_head);
23560+
dece6358
AM
23561+ v = 0;
23562+ while (len--)
23563+ v += *name++;
23564+ /* v = hash_long(v, magic_bit); */
23565+ v %= nhash->nh_num;
23566+ return nhash->nh_head + v;
23567+}
23568+
23569+static int au_nhash_test_name(struct au_vdir_destr *str, const char *name,
23570+ int nlen)
23571+{
23572+ return str->len == nlen && !memcmp(str->name, name, nlen);
1facf9fc 23573+}
23574+
23575+/* returns found or not */
dece6358 23576+int au_nhash_test_known_wh(struct au_nhash *whlist, char *name, int nlen)
1facf9fc 23577+{
23578+ struct hlist_head *head;
23579+ struct au_vdir_wh *tpos;
23580+ struct hlist_node *pos;
23581+ struct au_vdir_destr *str;
23582+
dece6358 23583+ head = au_name_hash(whlist, name, nlen);
1facf9fc 23584+ hlist_for_each_entry(tpos, pos, head, wh_hash) {
23585+ str = &tpos->wh_str;
23586+ AuDbg("%.*s\n", str->len, str->name);
dece6358
AM
23587+ if (au_nhash_test_name(str, name, nlen))
23588+ return 1;
23589+ }
23590+ return 0;
23591+}
23592+
23593+/* returns found(true) or not */
23594+static int test_known(struct au_nhash *delist, char *name, int nlen)
23595+{
23596+ struct hlist_head *head;
23597+ struct au_vdir_dehstr *tpos;
23598+ struct hlist_node *pos;
23599+ struct au_vdir_destr *str;
23600+
23601+ head = au_name_hash(delist, name, nlen);
23602+ hlist_for_each_entry(tpos, pos, head, hash) {
23603+ str = tpos->str;
23604+ AuDbg("%.*s\n", str->len, str->name);
23605+ if (au_nhash_test_name(str, name, nlen))
1facf9fc 23606+ return 1;
23607+ }
23608+ return 0;
23609+}
23610+
dece6358
AM
23611+static void au_shwh_init_wh(struct au_vdir_wh *wh, ino_t ino,
23612+ unsigned char d_type)
23613+{
23614+#ifdef CONFIG_AUFS_SHWH
23615+ wh->wh_ino = ino;
23616+ wh->wh_type = d_type;
23617+#endif
23618+}
23619+
23620+/* ---------------------------------------------------------------------- */
23621+
23622+int au_nhash_append_wh(struct au_nhash *whlist, char *name, int nlen, ino_t ino,
23623+ unsigned int d_type, aufs_bindex_t bindex,
23624+ unsigned char shwh)
1facf9fc 23625+{
23626+ int err;
23627+ struct au_vdir_destr *str;
23628+ struct au_vdir_wh *wh;
23629+
dece6358 23630+ AuDbg("%.*s\n", nlen, name);
1308ab2a 23631+ AuDebugOn(!whlist->nh_num || !whlist->nh_head);
23632+
1facf9fc 23633+ err = -ENOMEM;
dece6358 23634+ wh = kmalloc(sizeof(*wh) + nlen, GFP_NOFS);
1facf9fc 23635+ if (unlikely(!wh))
23636+ goto out;
23637+
23638+ err = 0;
23639+ wh->wh_bindex = bindex;
dece6358
AM
23640+ if (shwh)
23641+ au_shwh_init_wh(wh, ino, d_type);
1facf9fc 23642+ str = &wh->wh_str;
dece6358
AM
23643+ str->len = nlen;
23644+ memcpy(str->name, name, nlen);
23645+ hlist_add_head(&wh->wh_hash, au_name_hash(whlist, name, nlen));
1facf9fc 23646+ /* smp_mb(); */
23647+
4f0767ce 23648+out:
1facf9fc 23649+ return err;
23650+}
23651+
1facf9fc 23652+static int append_deblk(struct au_vdir *vdir)
23653+{
23654+ int err;
dece6358 23655+ unsigned long ul;
1facf9fc 23656+ const unsigned int deblk_sz = vdir->vd_deblk_sz;
23657+ union au_vdir_deblk_p p, deblk_end;
23658+ unsigned char **o;
23659+
23660+ err = -ENOMEM;
dece6358
AM
23661+ o = krealloc(vdir->vd_deblk, sizeof(*o) * (vdir->vd_nblk + 1),
23662+ GFP_NOFS);
1facf9fc 23663+ if (unlikely(!o))
23664+ goto out;
23665+
23666+ vdir->vd_deblk = o;
23667+ p.deblk = kmalloc(deblk_sz, GFP_NOFS);
23668+ if (p.deblk) {
23669+ ul = vdir->vd_nblk++;
23670+ vdir->vd_deblk[ul] = p.deblk;
23671+ vdir->vd_last.ul = ul;
23672+ vdir->vd_last.p.deblk = p.deblk;
23673+ deblk_end.deblk = p.deblk + deblk_sz;
23674+ err = set_deblk_end(&p, &deblk_end);
23675+ }
23676+
4f0767ce 23677+out:
1facf9fc 23678+ return err;
23679+}
23680+
dece6358
AM
23681+static int append_de(struct au_vdir *vdir, char *name, int nlen, ino_t ino,
23682+ unsigned int d_type, struct au_nhash *delist)
23683+{
23684+ int err;
23685+ unsigned int sz;
23686+ const unsigned int deblk_sz = vdir->vd_deblk_sz;
23687+ union au_vdir_deblk_p p, *room, deblk_end;
23688+ struct au_vdir_dehstr *dehstr;
23689+
23690+ p.deblk = last_deblk(vdir);
23691+ deblk_end.deblk = p.deblk + deblk_sz;
23692+ room = &vdir->vd_last.p;
23693+ AuDebugOn(room->deblk < p.deblk || deblk_end.deblk <= room->deblk
23694+ || !is_deblk_end(room, &deblk_end));
23695+
23696+ sz = calc_size(nlen);
23697+ if (unlikely(sz > deblk_end.deblk - room->deblk)) {
23698+ err = append_deblk(vdir);
23699+ if (unlikely(err))
23700+ goto out;
23701+
23702+ p.deblk = last_deblk(vdir);
23703+ deblk_end.deblk = p.deblk + deblk_sz;
23704+ /* smp_mb(); */
23705+ AuDebugOn(room->deblk != p.deblk);
23706+ }
23707+
23708+ err = -ENOMEM;
4a4d8108 23709+ dehstr = au_cache_alloc_vdir_dehstr();
dece6358
AM
23710+ if (unlikely(!dehstr))
23711+ goto out;
23712+
23713+ dehstr->str = &room->de->de_str;
23714+ hlist_add_head(&dehstr->hash, au_name_hash(delist, name, nlen));
23715+ room->de->de_ino = ino;
23716+ room->de->de_type = d_type;
23717+ room->de->de_str.len = nlen;
23718+ memcpy(room->de->de_str.name, name, nlen);
23719+
23720+ err = 0;
23721+ room->deblk += sz;
23722+ if (unlikely(set_deblk_end(room, &deblk_end)))
23723+ err = append_deblk(vdir);
23724+ /* smp_mb(); */
23725+
4f0767ce 23726+out:
dece6358
AM
23727+ return err;
23728+}
23729+
23730+/* ---------------------------------------------------------------------- */
23731+
23732+void au_vdir_free(struct au_vdir *vdir)
23733+{
23734+ unsigned char **deblk;
23735+
23736+ deblk = vdir->vd_deblk;
23737+ while (vdir->vd_nblk--)
23738+ kfree(*deblk++);
23739+ kfree(vdir->vd_deblk);
23740+ au_cache_free_vdir(vdir);
23741+}
23742+
1308ab2a 23743+static struct au_vdir *alloc_vdir(struct file *file)
1facf9fc 23744+{
23745+ struct au_vdir *vdir;
1308ab2a 23746+ struct super_block *sb;
1facf9fc 23747+ int err;
23748+
1308ab2a 23749+ sb = file->f_dentry->d_sb;
dece6358
AM
23750+ SiMustAnyLock(sb);
23751+
1facf9fc 23752+ err = -ENOMEM;
23753+ vdir = au_cache_alloc_vdir();
23754+ if (unlikely(!vdir))
23755+ goto out;
23756+
23757+ vdir->vd_deblk = kzalloc(sizeof(*vdir->vd_deblk), GFP_NOFS);
23758+ if (unlikely(!vdir->vd_deblk))
23759+ goto out_free;
23760+
23761+ vdir->vd_deblk_sz = au_sbi(sb)->si_rdblk;
1308ab2a 23762+ if (!vdir->vd_deblk_sz) {
23763+ /* estimate the apropriate size for deblk */
23764+ vdir->vd_deblk_sz = au_dir_size(file, /*dentry*/NULL);
4a4d8108 23765+ /* pr_info("vd_deblk_sz %u\n", vdir->vd_deblk_sz); */
1308ab2a 23766+ }
1facf9fc 23767+ vdir->vd_nblk = 0;
23768+ vdir->vd_version = 0;
23769+ vdir->vd_jiffy = 0;
23770+ err = append_deblk(vdir);
23771+ if (!err)
23772+ return vdir; /* success */
23773+
23774+ kfree(vdir->vd_deblk);
23775+
4f0767ce 23776+out_free:
1facf9fc 23777+ au_cache_free_vdir(vdir);
4f0767ce 23778+out:
1facf9fc 23779+ vdir = ERR_PTR(err);
23780+ return vdir;
23781+}
23782+
23783+static int reinit_vdir(struct au_vdir *vdir)
23784+{
23785+ int err;
23786+ union au_vdir_deblk_p p, deblk_end;
23787+
23788+ while (vdir->vd_nblk > 1) {
23789+ kfree(vdir->vd_deblk[vdir->vd_nblk - 1]);
23790+ /* vdir->vd_deblk[vdir->vd_nblk - 1] = NULL; */
23791+ vdir->vd_nblk--;
23792+ }
23793+ p.deblk = vdir->vd_deblk[0];
23794+ deblk_end.deblk = p.deblk + vdir->vd_deblk_sz;
23795+ err = set_deblk_end(&p, &deblk_end);
23796+ /* keep vd_dblk_sz */
23797+ vdir->vd_last.ul = 0;
23798+ vdir->vd_last.p.deblk = vdir->vd_deblk[0];
23799+ vdir->vd_version = 0;
23800+ vdir->vd_jiffy = 0;
23801+ /* smp_mb(); */
23802+ return err;
23803+}
23804+
23805+/* ---------------------------------------------------------------------- */
23806+
1facf9fc 23807+#define AuFillVdir_CALLED 1
23808+#define AuFillVdir_WHABLE (1 << 1)
dece6358 23809+#define AuFillVdir_SHWH (1 << 2)
1facf9fc 23810+#define au_ftest_fillvdir(flags, name) ((flags) & AuFillVdir_##name)
7f207e10
AM
23811+#define au_fset_fillvdir(flags, name) \
23812+ do { (flags) |= AuFillVdir_##name; } while (0)
23813+#define au_fclr_fillvdir(flags, name) \
23814+ do { (flags) &= ~AuFillVdir_##name; } while (0)
1facf9fc 23815+
dece6358
AM
23816+#ifndef CONFIG_AUFS_SHWH
23817+#undef AuFillVdir_SHWH
23818+#define AuFillVdir_SHWH 0
23819+#endif
23820+
1facf9fc 23821+struct fillvdir_arg {
23822+ struct file *file;
23823+ struct au_vdir *vdir;
dece6358
AM
23824+ struct au_nhash delist;
23825+ struct au_nhash whlist;
1facf9fc 23826+ aufs_bindex_t bindex;
23827+ unsigned int flags;
23828+ int err;
23829+};
23830+
dece6358 23831+static int fillvdir(void *__arg, const char *__name, int nlen,
1facf9fc 23832+ loff_t offset __maybe_unused, u64 h_ino,
23833+ unsigned int d_type)
23834+{
23835+ struct fillvdir_arg *arg = __arg;
23836+ char *name = (void *)__name;
23837+ struct super_block *sb;
1facf9fc 23838+ ino_t ino;
dece6358 23839+ const unsigned char shwh = !!au_ftest_fillvdir(arg->flags, SHWH);
1facf9fc 23840+
1facf9fc 23841+ arg->err = 0;
dece6358 23842+ sb = arg->file->f_dentry->d_sb;
1facf9fc 23843+ au_fset_fillvdir(arg->flags, CALLED);
23844+ /* smp_mb(); */
dece6358 23845+ if (nlen <= AUFS_WH_PFX_LEN
1facf9fc 23846+ || memcmp(name, AUFS_WH_PFX, AUFS_WH_PFX_LEN)) {
dece6358
AM
23847+ if (test_known(&arg->delist, name, nlen)
23848+ || au_nhash_test_known_wh(&arg->whlist, name, nlen))
23849+ goto out; /* already exists or whiteouted */
1facf9fc 23850+
23851+ sb = arg->file->f_dentry->d_sb;
dece6358 23852+ arg->err = au_ino(sb, arg->bindex, h_ino, d_type, &ino);
4a4d8108
AM
23853+ if (!arg->err) {
23854+ if (unlikely(nlen > AUFS_MAX_NAMELEN))
23855+ d_type = DT_UNKNOWN;
dece6358
AM
23856+ arg->err = append_de(arg->vdir, name, nlen, ino,
23857+ d_type, &arg->delist);
4a4d8108 23858+ }
1facf9fc 23859+ } else if (au_ftest_fillvdir(arg->flags, WHABLE)) {
23860+ name += AUFS_WH_PFX_LEN;
dece6358
AM
23861+ nlen -= AUFS_WH_PFX_LEN;
23862+ if (au_nhash_test_known_wh(&arg->whlist, name, nlen))
23863+ goto out; /* already whiteouted */
1facf9fc 23864+
dece6358
AM
23865+ if (shwh)
23866+ arg->err = au_wh_ino(sb, arg->bindex, h_ino, d_type,
23867+ &ino);
4a4d8108
AM
23868+ if (!arg->err) {
23869+ if (nlen <= AUFS_MAX_NAMELEN + AUFS_WH_PFX_LEN)
23870+ d_type = DT_UNKNOWN;
1facf9fc 23871+ arg->err = au_nhash_append_wh
dece6358
AM
23872+ (&arg->whlist, name, nlen, ino, d_type,
23873+ arg->bindex, shwh);
4a4d8108 23874+ }
1facf9fc 23875+ }
23876+
4f0767ce 23877+out:
1facf9fc 23878+ if (!arg->err)
23879+ arg->vdir->vd_jiffy = jiffies;
23880+ /* smp_mb(); */
23881+ AuTraceErr(arg->err);
23882+ return arg->err;
23883+}
23884+
dece6358
AM
23885+static int au_handle_shwh(struct super_block *sb, struct au_vdir *vdir,
23886+ struct au_nhash *whlist, struct au_nhash *delist)
23887+{
23888+#ifdef CONFIG_AUFS_SHWH
23889+ int err;
23890+ unsigned int nh, u;
23891+ struct hlist_head *head;
23892+ struct au_vdir_wh *tpos;
23893+ struct hlist_node *pos, *n;
23894+ char *p, *o;
23895+ struct au_vdir_destr *destr;
23896+
23897+ AuDebugOn(!au_opt_test(au_mntflags(sb), SHWH));
23898+
23899+ err = -ENOMEM;
4a4d8108 23900+ o = p = __getname_gfp(GFP_NOFS);
dece6358
AM
23901+ if (unlikely(!p))
23902+ goto out;
23903+
23904+ err = 0;
23905+ nh = whlist->nh_num;
23906+ memcpy(p, AUFS_WH_PFX, AUFS_WH_PFX_LEN);
23907+ p += AUFS_WH_PFX_LEN;
23908+ for (u = 0; u < nh; u++) {
23909+ head = whlist->nh_head + u;
23910+ hlist_for_each_entry_safe(tpos, pos, n, head, wh_hash) {
23911+ destr = &tpos->wh_str;
23912+ memcpy(p, destr->name, destr->len);
23913+ err = append_de(vdir, o, destr->len + AUFS_WH_PFX_LEN,
23914+ tpos->wh_ino, tpos->wh_type, delist);
23915+ if (unlikely(err))
23916+ break;
23917+ }
23918+ }
23919+
23920+ __putname(o);
23921+
4f0767ce 23922+out:
dece6358
AM
23923+ AuTraceErr(err);
23924+ return err;
23925+#else
23926+ return 0;
23927+#endif
23928+}
23929+
1facf9fc 23930+static int au_do_read_vdir(struct fillvdir_arg *arg)
23931+{
23932+ int err;
dece6358 23933+ unsigned int rdhash;
1facf9fc 23934+ loff_t offset;
dece6358
AM
23935+ aufs_bindex_t bend, bindex, bstart;
23936+ unsigned char shwh;
1facf9fc 23937+ struct file *hf, *file;
23938+ struct super_block *sb;
23939+
1facf9fc 23940+ file = arg->file;
23941+ sb = file->f_dentry->d_sb;
dece6358
AM
23942+ SiMustAnyLock(sb);
23943+
23944+ rdhash = au_sbi(sb)->si_rdhash;
1308ab2a 23945+ if (!rdhash)
23946+ rdhash = au_rdhash_est(au_dir_size(file, /*dentry*/NULL));
dece6358
AM
23947+ err = au_nhash_alloc(&arg->delist, rdhash, GFP_NOFS);
23948+ if (unlikely(err))
1facf9fc 23949+ goto out;
dece6358
AM
23950+ err = au_nhash_alloc(&arg->whlist, rdhash, GFP_NOFS);
23951+ if (unlikely(err))
1facf9fc 23952+ goto out_delist;
23953+
23954+ err = 0;
23955+ arg->flags = 0;
dece6358
AM
23956+ shwh = 0;
23957+ if (au_opt_test(au_mntflags(sb), SHWH)) {
23958+ shwh = 1;
23959+ au_fset_fillvdir(arg->flags, SHWH);
23960+ }
23961+ bstart = au_fbstart(file);
4a4d8108 23962+ bend = au_fbend_dir(file);
dece6358 23963+ for (bindex = bstart; !err && bindex <= bend; bindex++) {
4a4d8108 23964+ hf = au_hf_dir(file, bindex);
1facf9fc 23965+ if (!hf)
23966+ continue;
23967+
23968+ offset = vfsub_llseek(hf, 0, SEEK_SET);
23969+ err = offset;
23970+ if (unlikely(offset))
23971+ break;
23972+
23973+ arg->bindex = bindex;
23974+ au_fclr_fillvdir(arg->flags, WHABLE);
dece6358
AM
23975+ if (shwh
23976+ || (bindex != bend
23977+ && au_br_whable(au_sbr_perm(sb, bindex))))
1facf9fc 23978+ au_fset_fillvdir(arg->flags, WHABLE);
23979+ do {
23980+ arg->err = 0;
23981+ au_fclr_fillvdir(arg->flags, CALLED);
23982+ /* smp_mb(); */
23983+ err = vfsub_readdir(hf, fillvdir, arg);
23984+ if (err >= 0)
23985+ err = arg->err;
23986+ } while (!err && au_ftest_fillvdir(arg->flags, CALLED));
23987+ }
dece6358
AM
23988+
23989+ if (!err && shwh)
23990+ err = au_handle_shwh(sb, arg->vdir, &arg->whlist, &arg->delist);
23991+
23992+ au_nhash_wh_free(&arg->whlist);
1facf9fc 23993+
4f0767ce 23994+out_delist:
dece6358 23995+ au_nhash_de_free(&arg->delist);
4f0767ce 23996+out:
1facf9fc 23997+ return err;
23998+}
23999+
24000+static int read_vdir(struct file *file, int may_read)
24001+{
24002+ int err;
24003+ unsigned long expire;
24004+ unsigned char do_read;
24005+ struct fillvdir_arg arg;
24006+ struct inode *inode;
24007+ struct au_vdir *vdir, *allocated;
24008+
24009+ err = 0;
24010+ inode = file->f_dentry->d_inode;
24011+ IMustLock(inode);
dece6358
AM
24012+ SiMustAnyLock(inode->i_sb);
24013+
1facf9fc 24014+ allocated = NULL;
24015+ do_read = 0;
24016+ expire = au_sbi(inode->i_sb)->si_rdcache;
24017+ vdir = au_ivdir(inode);
24018+ if (!vdir) {
24019+ do_read = 1;
1308ab2a 24020+ vdir = alloc_vdir(file);
1facf9fc 24021+ err = PTR_ERR(vdir);
24022+ if (IS_ERR(vdir))
24023+ goto out;
24024+ err = 0;
24025+ allocated = vdir;
24026+ } else if (may_read
24027+ && (inode->i_version != vdir->vd_version
24028+ || time_after(jiffies, vdir->vd_jiffy + expire))) {
24029+ do_read = 1;
24030+ err = reinit_vdir(vdir);
24031+ if (unlikely(err))
24032+ goto out;
24033+ }
24034+
24035+ if (!do_read)
24036+ return 0; /* success */
24037+
24038+ arg.file = file;
24039+ arg.vdir = vdir;
24040+ err = au_do_read_vdir(&arg);
24041+ if (!err) {
24042+ /* file->f_pos = 0; */
24043+ vdir->vd_version = inode->i_version;
24044+ vdir->vd_last.ul = 0;
24045+ vdir->vd_last.p.deblk = vdir->vd_deblk[0];
24046+ if (allocated)
24047+ au_set_ivdir(inode, allocated);
24048+ } else if (allocated)
24049+ au_vdir_free(allocated);
24050+
4f0767ce 24051+out:
1facf9fc 24052+ return err;
24053+}
24054+
24055+static int copy_vdir(struct au_vdir *tgt, struct au_vdir *src)
24056+{
24057+ int err, rerr;
24058+ unsigned long ul, n;
24059+ const unsigned int deblk_sz = src->vd_deblk_sz;
24060+
24061+ AuDebugOn(tgt->vd_nblk != 1);
24062+
24063+ err = -ENOMEM;
24064+ if (tgt->vd_nblk < src->vd_nblk) {
24065+ unsigned char **p;
24066+
dece6358
AM
24067+ p = krealloc(tgt->vd_deblk, sizeof(*p) * src->vd_nblk,
24068+ GFP_NOFS);
1facf9fc 24069+ if (unlikely(!p))
24070+ goto out;
24071+ tgt->vd_deblk = p;
24072+ }
24073+
1308ab2a 24074+ if (tgt->vd_deblk_sz != deblk_sz) {
24075+ unsigned char *p;
24076+
24077+ tgt->vd_deblk_sz = deblk_sz;
24078+ p = krealloc(tgt->vd_deblk[0], deblk_sz, GFP_NOFS);
24079+ if (unlikely(!p))
24080+ goto out;
24081+ tgt->vd_deblk[0] = p;
24082+ }
1facf9fc 24083+ memcpy(tgt->vd_deblk[0], src->vd_deblk[0], deblk_sz);
1facf9fc 24084+ tgt->vd_version = src->vd_version;
24085+ tgt->vd_jiffy = src->vd_jiffy;
24086+
24087+ n = src->vd_nblk;
24088+ for (ul = 1; ul < n; ul++) {
dece6358
AM
24089+ tgt->vd_deblk[ul] = kmemdup(src->vd_deblk[ul], deblk_sz,
24090+ GFP_NOFS);
24091+ if (unlikely(!tgt->vd_deblk[ul]))
1facf9fc 24092+ goto out;
1308ab2a 24093+ tgt->vd_nblk++;
1facf9fc 24094+ }
1308ab2a 24095+ tgt->vd_nblk = n;
24096+ tgt->vd_last.ul = tgt->vd_last.ul;
24097+ tgt->vd_last.p.deblk = tgt->vd_deblk[tgt->vd_last.ul];
24098+ tgt->vd_last.p.deblk += src->vd_last.p.deblk
24099+ - src->vd_deblk[src->vd_last.ul];
1facf9fc 24100+ /* smp_mb(); */
24101+ return 0; /* success */
24102+
4f0767ce 24103+out:
1facf9fc 24104+ rerr = reinit_vdir(tgt);
24105+ BUG_ON(rerr);
24106+ return err;
24107+}
24108+
24109+int au_vdir_init(struct file *file)
24110+{
24111+ int err;
24112+ struct inode *inode;
24113+ struct au_vdir *vdir_cache, *allocated;
24114+
24115+ err = read_vdir(file, !file->f_pos);
24116+ if (unlikely(err))
24117+ goto out;
24118+
24119+ allocated = NULL;
24120+ vdir_cache = au_fvdir_cache(file);
24121+ if (!vdir_cache) {
1308ab2a 24122+ vdir_cache = alloc_vdir(file);
1facf9fc 24123+ err = PTR_ERR(vdir_cache);
24124+ if (IS_ERR(vdir_cache))
24125+ goto out;
24126+ allocated = vdir_cache;
24127+ } else if (!file->f_pos && vdir_cache->vd_version != file->f_version) {
24128+ err = reinit_vdir(vdir_cache);
24129+ if (unlikely(err))
24130+ goto out;
24131+ } else
24132+ return 0; /* success */
24133+
24134+ inode = file->f_dentry->d_inode;
24135+ err = copy_vdir(vdir_cache, au_ivdir(inode));
24136+ if (!err) {
24137+ file->f_version = inode->i_version;
24138+ if (allocated)
24139+ au_set_fvdir_cache(file, allocated);
24140+ } else if (allocated)
24141+ au_vdir_free(allocated);
24142+
4f0767ce 24143+out:
1facf9fc 24144+ return err;
24145+}
24146+
24147+static loff_t calc_offset(struct au_vdir *vdir)
24148+{
24149+ loff_t offset;
24150+ union au_vdir_deblk_p p;
24151+
24152+ p.deblk = vdir->vd_deblk[vdir->vd_last.ul];
24153+ offset = vdir->vd_last.p.deblk - p.deblk;
24154+ offset += vdir->vd_deblk_sz * vdir->vd_last.ul;
24155+ return offset;
24156+}
24157+
24158+/* returns true or false */
24159+static int seek_vdir(struct file *file)
24160+{
24161+ int valid;
24162+ unsigned int deblk_sz;
24163+ unsigned long ul, n;
24164+ loff_t offset;
24165+ union au_vdir_deblk_p p, deblk_end;
24166+ struct au_vdir *vdir_cache;
24167+
24168+ valid = 1;
24169+ vdir_cache = au_fvdir_cache(file);
24170+ offset = calc_offset(vdir_cache);
24171+ AuDbg("offset %lld\n", offset);
24172+ if (file->f_pos == offset)
24173+ goto out;
24174+
24175+ vdir_cache->vd_last.ul = 0;
24176+ vdir_cache->vd_last.p.deblk = vdir_cache->vd_deblk[0];
24177+ if (!file->f_pos)
24178+ goto out;
24179+
24180+ valid = 0;
24181+ deblk_sz = vdir_cache->vd_deblk_sz;
24182+ ul = div64_u64(file->f_pos, deblk_sz);
24183+ AuDbg("ul %lu\n", ul);
24184+ if (ul >= vdir_cache->vd_nblk)
24185+ goto out;
24186+
24187+ n = vdir_cache->vd_nblk;
24188+ for (; ul < n; ul++) {
24189+ p.deblk = vdir_cache->vd_deblk[ul];
24190+ deblk_end.deblk = p.deblk + deblk_sz;
24191+ offset = ul;
24192+ offset *= deblk_sz;
24193+ while (!is_deblk_end(&p, &deblk_end) && offset < file->f_pos) {
24194+ unsigned int l;
24195+
24196+ l = calc_size(p.de->de_str.len);
24197+ offset += l;
24198+ p.deblk += l;
24199+ }
24200+ if (!is_deblk_end(&p, &deblk_end)) {
24201+ valid = 1;
24202+ vdir_cache->vd_last.ul = ul;
24203+ vdir_cache->vd_last.p = p;
24204+ break;
24205+ }
24206+ }
24207+
4f0767ce 24208+out:
1facf9fc 24209+ /* smp_mb(); */
24210+ AuTraceErr(!valid);
24211+ return valid;
24212+}
24213+
24214+int au_vdir_fill_de(struct file *file, void *dirent, filldir_t filldir)
24215+{
24216+ int err;
24217+ unsigned int l, deblk_sz;
24218+ union au_vdir_deblk_p deblk_end;
24219+ struct au_vdir *vdir_cache;
24220+ struct au_vdir_de *de;
24221+
24222+ vdir_cache = au_fvdir_cache(file);
24223+ if (!seek_vdir(file))
24224+ return 0;
24225+
24226+ deblk_sz = vdir_cache->vd_deblk_sz;
24227+ while (1) {
24228+ deblk_end.deblk = vdir_cache->vd_deblk[vdir_cache->vd_last.ul];
24229+ deblk_end.deblk += deblk_sz;
24230+ while (!is_deblk_end(&vdir_cache->vd_last.p, &deblk_end)) {
24231+ de = vdir_cache->vd_last.p.de;
24232+ AuDbg("%.*s, off%lld, i%lu, dt%d\n",
24233+ de->de_str.len, de->de_str.name, file->f_pos,
24234+ (unsigned long)de->de_ino, de->de_type);
24235+ err = filldir(dirent, de->de_str.name, de->de_str.len,
24236+ file->f_pos, de->de_ino, de->de_type);
24237+ if (unlikely(err)) {
24238+ AuTraceErr(err);
24239+ /* todo: ignore the error caused by udba? */
24240+ /* return err; */
24241+ return 0;
24242+ }
24243+
24244+ l = calc_size(de->de_str.len);
24245+ vdir_cache->vd_last.p.deblk += l;
24246+ file->f_pos += l;
24247+ }
24248+ if (vdir_cache->vd_last.ul < vdir_cache->vd_nblk - 1) {
24249+ vdir_cache->vd_last.ul++;
24250+ vdir_cache->vd_last.p.deblk
24251+ = vdir_cache->vd_deblk[vdir_cache->vd_last.ul];
24252+ file->f_pos = deblk_sz * vdir_cache->vd_last.ul;
24253+ continue;
24254+ }
24255+ break;
24256+ }
24257+
24258+ /* smp_mb(); */
24259+ return 0;
24260+}
7f207e10
AM
24261diff -urN /usr/share/empty/fs/aufs/vfsub.c linux/fs/aufs/vfsub.c
24262--- /usr/share/empty/fs/aufs/vfsub.c 1970-01-01 01:00:00.000000000 +0100
87a755f4 24263+++ linux/fs/aufs/vfsub.c 2011-07-22 08:26:47.857636522 +0200
2cbb1c4b 24264@@ -0,0 +1,818 @@
1facf9fc 24265+/*
027c5e7a 24266+ * Copyright (C) 2005-2011 Junjiro R. Okajima
1facf9fc 24267+ *
24268+ * This program, aufs is free software; you can redistribute it and/or modify
24269+ * it under the terms of the GNU General Public License as published by
24270+ * the Free Software Foundation; either version 2 of the License, or
24271+ * (at your option) any later version.
dece6358
AM
24272+ *
24273+ * This program is distributed in the hope that it will be useful,
24274+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
24275+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24276+ * GNU General Public License for more details.
24277+ *
24278+ * You should have received a copy of the GNU General Public License
24279+ * along with this program; if not, write to the Free Software
24280+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 24281+ */
24282+
24283+/*
24284+ * sub-routines for VFS
24285+ */
24286+
4a4d8108 24287+#include <linux/file.h>
1308ab2a 24288+#include <linux/ima.h>
dece6358
AM
24289+#include <linux/namei.h>
24290+#include <linux/security.h>
24291+#include <linux/splice.h>
1facf9fc 24292+#include <linux/uaccess.h>
24293+#include "aufs.h"
24294+
24295+int vfsub_update_h_iattr(struct path *h_path, int *did)
24296+{
24297+ int err;
24298+ struct kstat st;
24299+ struct super_block *h_sb;
24300+
24301+ /* for remote fs, leave work for its getattr or d_revalidate */
24302+ /* for bad i_attr fs, handle them in aufs_getattr() */
24303+ /* still some fs may acquire i_mutex. we need to skip them */
24304+ err = 0;
24305+ if (!did)
24306+ did = &err;
24307+ h_sb = h_path->dentry->d_sb;
24308+ *did = (!au_test_fs_remote(h_sb) && au_test_fs_refresh_iattr(h_sb));
24309+ if (*did)
24310+ err = vfs_getattr(h_path->mnt, h_path->dentry, &st);
24311+
24312+ return err;
24313+}
24314+
24315+/* ---------------------------------------------------------------------- */
24316+
4a4d8108 24317+struct file *vfsub_dentry_open(struct path *path, int flags)
1308ab2a 24318+{
24319+ struct file *file;
24320+
4a4d8108 24321+ path_get(path);
0c5527e5 24322+ file = dentry_open(path->dentry, path->mnt,
2cbb1c4b 24323+ flags /* | __FMODE_NONOTIFY */,
7f207e10 24324+ current_cred());
2cbb1c4b
JR
24325+ if (!IS_ERR_OR_NULL(file)
24326+ && (file->f_mode & (FMODE_READ | FMODE_WRITE)) == FMODE_READ)
24327+ i_readcount_inc(path->dentry->d_inode);
4a4d8108 24328+
1308ab2a 24329+ return file;
24330+}
24331+
1facf9fc 24332+struct file *vfsub_filp_open(const char *path, int oflags, int mode)
24333+{
24334+ struct file *file;
24335+
2cbb1c4b 24336+ lockdep_off();
7f207e10 24337+ file = filp_open(path,
2cbb1c4b 24338+ oflags /* | __FMODE_NONOTIFY */,
7f207e10 24339+ mode);
2cbb1c4b 24340+ lockdep_on();
1facf9fc 24341+ if (IS_ERR(file))
24342+ goto out;
24343+ vfsub_update_h_iattr(&file->f_path, /*did*/NULL); /*ignore*/
24344+
4f0767ce 24345+out:
1facf9fc 24346+ return file;
24347+}
24348+
24349+int vfsub_kern_path(const char *name, unsigned int flags, struct path *path)
24350+{
24351+ int err;
24352+
1facf9fc 24353+ err = kern_path(name, flags, path);
1facf9fc 24354+ if (!err && path->dentry->d_inode)
24355+ vfsub_update_h_iattr(path, /*did*/NULL); /*ignore*/
24356+ return err;
24357+}
24358+
24359+struct dentry *vfsub_lookup_one_len(const char *name, struct dentry *parent,
24360+ int len)
24361+{
24362+ struct path path = {
24363+ .mnt = NULL
24364+ };
24365+
1308ab2a 24366+ /* VFS checks it too, but by WARN_ON_ONCE() */
1facf9fc 24367+ IMustLock(parent->d_inode);
24368+
24369+ path.dentry = lookup_one_len(name, parent, len);
24370+ if (IS_ERR(path.dentry))
24371+ goto out;
24372+ if (path.dentry->d_inode)
24373+ vfsub_update_h_iattr(&path, /*did*/NULL); /*ignore*/
24374+
4f0767ce 24375+out:
4a4d8108 24376+ AuTraceErrPtr(path.dentry);
1facf9fc 24377+ return path.dentry;
24378+}
24379+
24380+struct dentry *vfsub_lookup_hash(struct nameidata *nd)
24381+{
24382+ struct path path = {
24383+ .mnt = nd->path.mnt
24384+ };
24385+
24386+ IMustLock(nd->path.dentry->d_inode);
24387+
24388+ path.dentry = lookup_hash(nd);
4a4d8108
AM
24389+ if (IS_ERR(path.dentry))
24390+ goto out;
24391+ if (path.dentry->d_inode)
1facf9fc 24392+ vfsub_update_h_iattr(&path, /*did*/NULL); /*ignore*/
24393+
4f0767ce 24394+out:
4a4d8108 24395+ AuTraceErrPtr(path.dentry);
1facf9fc 24396+ return path.dentry;
24397+}
24398+
2cbb1c4b
JR
24399+/*
24400+ * this is "VFS:__lookup_one_len()" which was removed and merged into
24401+ * VFS:lookup_one_len() by the commit.
24402+ * 6a96ba5 2011-03-14 kill __lookup_one_len()
24403+ * this function should always be equivalent to the corresponding part in
24404+ * VFS:lookup_one_len().
24405+ */
24406+int vfsub_name_hash(const char *name, struct qstr *this, int len)
24407+{
24408+ unsigned long hash;
24409+ unsigned int c;
24410+
24411+ this->name = name;
24412+ this->len = len;
24413+ if (!len)
24414+ return -EACCES;
24415+
24416+ hash = init_name_hash();
24417+ while (len--) {
24418+ c = *(const unsigned char *)name++;
24419+ if (c == '/' || c == '\0')
24420+ return -EACCES;
24421+ hash = partial_name_hash(c, hash);
24422+ }
24423+ this->hash = end_name_hash(hash);
24424+ return 0;
24425+}
24426+
1facf9fc 24427+/* ---------------------------------------------------------------------- */
24428+
24429+struct dentry *vfsub_lock_rename(struct dentry *d1, struct au_hinode *hdir1,
24430+ struct dentry *d2, struct au_hinode *hdir2)
24431+{
24432+ struct dentry *d;
24433+
2cbb1c4b 24434+ lockdep_off();
1facf9fc 24435+ d = lock_rename(d1, d2);
2cbb1c4b 24436+ lockdep_on();
4a4d8108 24437+ au_hn_suspend(hdir1);
1facf9fc 24438+ if (hdir1 != hdir2)
4a4d8108 24439+ au_hn_suspend(hdir2);
1facf9fc 24440+
24441+ return d;
24442+}
24443+
24444+void vfsub_unlock_rename(struct dentry *d1, struct au_hinode *hdir1,
24445+ struct dentry *d2, struct au_hinode *hdir2)
24446+{
4a4d8108 24447+ au_hn_resume(hdir1);
1facf9fc 24448+ if (hdir1 != hdir2)
4a4d8108 24449+ au_hn_resume(hdir2);
2cbb1c4b 24450+ lockdep_off();
1facf9fc 24451+ unlock_rename(d1, d2);
2cbb1c4b 24452+ lockdep_on();
1facf9fc 24453+}
24454+
24455+/* ---------------------------------------------------------------------- */
24456+
24457+int vfsub_create(struct inode *dir, struct path *path, int mode)
24458+{
24459+ int err;
24460+ struct dentry *d;
24461+
24462+ IMustLock(dir);
24463+
24464+ d = path->dentry;
24465+ path->dentry = d->d_parent;
b752ccd1 24466+ err = security_path_mknod(path, d, mode, 0);
1facf9fc 24467+ path->dentry = d;
24468+ if (unlikely(err))
24469+ goto out;
24470+
24471+ if (au_test_fs_null_nd(dir->i_sb))
24472+ err = vfs_create(dir, path->dentry, mode, NULL);
24473+ else {
24474+ struct nameidata h_nd;
24475+
24476+ memset(&h_nd, 0, sizeof(h_nd));
24477+ h_nd.flags = LOOKUP_CREATE;
24478+ h_nd.intent.open.flags = O_CREAT
24479+ | vfsub_fmode_to_uint(FMODE_READ);
24480+ h_nd.intent.open.create_mode = mode;
24481+ h_nd.path.dentry = path->dentry->d_parent;
24482+ h_nd.path.mnt = path->mnt;
24483+ path_get(&h_nd.path);
24484+ err = vfs_create(dir, path->dentry, mode, &h_nd);
24485+ path_put(&h_nd.path);
24486+ }
24487+
24488+ if (!err) {
24489+ struct path tmp = *path;
24490+ int did;
24491+
24492+ vfsub_update_h_iattr(&tmp, &did);
24493+ if (did) {
24494+ tmp.dentry = path->dentry->d_parent;
24495+ vfsub_update_h_iattr(&tmp, /*did*/NULL);
24496+ }
24497+ /*ignore*/
24498+ }
24499+
4f0767ce 24500+out:
1facf9fc 24501+ return err;
24502+}
24503+
24504+int vfsub_symlink(struct inode *dir, struct path *path, const char *symname)
24505+{
24506+ int err;
24507+ struct dentry *d;
24508+
24509+ IMustLock(dir);
24510+
24511+ d = path->dentry;
24512+ path->dentry = d->d_parent;
b752ccd1 24513+ err = security_path_symlink(path, d, symname);
1facf9fc 24514+ path->dentry = d;
24515+ if (unlikely(err))
24516+ goto out;
24517+
24518+ err = vfs_symlink(dir, path->dentry, symname);
24519+ if (!err) {
24520+ struct path tmp = *path;
24521+ int did;
24522+
24523+ vfsub_update_h_iattr(&tmp, &did);
24524+ if (did) {
24525+ tmp.dentry = path->dentry->d_parent;
24526+ vfsub_update_h_iattr(&tmp, /*did*/NULL);
24527+ }
24528+ /*ignore*/
24529+ }
24530+
4f0767ce 24531+out:
1facf9fc 24532+ return err;
24533+}
24534+
24535+int vfsub_mknod(struct inode *dir, struct path *path, int mode, dev_t dev)
24536+{
24537+ int err;
24538+ struct dentry *d;
24539+
24540+ IMustLock(dir);
24541+
24542+ d = path->dentry;
24543+ path->dentry = d->d_parent;
027c5e7a 24544+ err = security_path_mknod(path, d, mode, new_encode_dev(dev));
1facf9fc 24545+ path->dentry = d;
24546+ if (unlikely(err))
24547+ goto out;
24548+
24549+ err = vfs_mknod(dir, path->dentry, mode, dev);
24550+ if (!err) {
24551+ struct path tmp = *path;
24552+ int did;
24553+
24554+ vfsub_update_h_iattr(&tmp, &did);
24555+ if (did) {
24556+ tmp.dentry = path->dentry->d_parent;
24557+ vfsub_update_h_iattr(&tmp, /*did*/NULL);
24558+ }
24559+ /*ignore*/
24560+ }
24561+
4f0767ce 24562+out:
1facf9fc 24563+ return err;
24564+}
24565+
24566+static int au_test_nlink(struct inode *inode)
24567+{
24568+ const unsigned int link_max = UINT_MAX >> 1; /* rough margin */
24569+
24570+ if (!au_test_fs_no_limit_nlink(inode->i_sb)
24571+ || inode->i_nlink < link_max)
24572+ return 0;
24573+ return -EMLINK;
24574+}
24575+
24576+int vfsub_link(struct dentry *src_dentry, struct inode *dir, struct path *path)
24577+{
24578+ int err;
24579+ struct dentry *d;
24580+
24581+ IMustLock(dir);
24582+
24583+ err = au_test_nlink(src_dentry->d_inode);
24584+ if (unlikely(err))
24585+ return err;
24586+
24587+ d = path->dentry;
24588+ path->dentry = d->d_parent;
b752ccd1 24589+ err = security_path_link(src_dentry, path, d);
1facf9fc 24590+ path->dentry = d;
24591+ if (unlikely(err))
24592+ goto out;
24593+
2cbb1c4b 24594+ lockdep_off();
1facf9fc 24595+ err = vfs_link(src_dentry, dir, path->dentry);
2cbb1c4b 24596+ lockdep_on();
1facf9fc 24597+ if (!err) {
24598+ struct path tmp = *path;
24599+ int did;
24600+
24601+ /* fuse has different memory inode for the same inumber */
24602+ vfsub_update_h_iattr(&tmp, &did);
24603+ if (did) {
24604+ tmp.dentry = path->dentry->d_parent;
24605+ vfsub_update_h_iattr(&tmp, /*did*/NULL);
24606+ tmp.dentry = src_dentry;
24607+ vfsub_update_h_iattr(&tmp, /*did*/NULL);
24608+ }
24609+ /*ignore*/
24610+ }
24611+
4f0767ce 24612+out:
1facf9fc 24613+ return err;
24614+}
24615+
24616+int vfsub_rename(struct inode *src_dir, struct dentry *src_dentry,
24617+ struct inode *dir, struct path *path)
24618+{
24619+ int err;
24620+ struct path tmp = {
24621+ .mnt = path->mnt
24622+ };
24623+ struct dentry *d;
24624+
24625+ IMustLock(dir);
24626+ IMustLock(src_dir);
24627+
24628+ d = path->dentry;
24629+ path->dentry = d->d_parent;
24630+ tmp.dentry = src_dentry->d_parent;
b752ccd1 24631+ err = security_path_rename(&tmp, src_dentry, path, d);
1facf9fc 24632+ path->dentry = d;
24633+ if (unlikely(err))
24634+ goto out;
24635+
2cbb1c4b 24636+ lockdep_off();
1facf9fc 24637+ err = vfs_rename(src_dir, src_dentry, dir, path->dentry);
2cbb1c4b 24638+ lockdep_on();
1facf9fc 24639+ if (!err) {
24640+ int did;
24641+
24642+ tmp.dentry = d->d_parent;
24643+ vfsub_update_h_iattr(&tmp, &did);
24644+ if (did) {
24645+ tmp.dentry = src_dentry;
24646+ vfsub_update_h_iattr(&tmp, /*did*/NULL);
24647+ tmp.dentry = src_dentry->d_parent;
24648+ vfsub_update_h_iattr(&tmp, /*did*/NULL);
24649+ }
24650+ /*ignore*/
24651+ }
24652+
4f0767ce 24653+out:
1facf9fc 24654+ return err;
24655+}
24656+
24657+int vfsub_mkdir(struct inode *dir, struct path *path, int mode)
24658+{
24659+ int err;
24660+ struct dentry *d;
24661+
24662+ IMustLock(dir);
24663+
24664+ d = path->dentry;
24665+ path->dentry = d->d_parent;
b752ccd1 24666+ err = security_path_mkdir(path, d, mode);
1facf9fc 24667+ path->dentry = d;
24668+ if (unlikely(err))
24669+ goto out;
24670+
24671+ err = vfs_mkdir(dir, path->dentry, mode);
24672+ if (!err) {
24673+ struct path tmp = *path;
24674+ int did;
24675+
24676+ vfsub_update_h_iattr(&tmp, &did);
24677+ if (did) {
24678+ tmp.dentry = path->dentry->d_parent;
24679+ vfsub_update_h_iattr(&tmp, /*did*/NULL);
24680+ }
24681+ /*ignore*/
24682+ }
24683+
4f0767ce 24684+out:
1facf9fc 24685+ return err;
24686+}
24687+
24688+int vfsub_rmdir(struct inode *dir, struct path *path)
24689+{
24690+ int err;
24691+ struct dentry *d;
24692+
24693+ IMustLock(dir);
24694+
24695+ d = path->dentry;
24696+ path->dentry = d->d_parent;
b752ccd1 24697+ err = security_path_rmdir(path, d);
1facf9fc 24698+ path->dentry = d;
24699+ if (unlikely(err))
24700+ goto out;
24701+
2cbb1c4b 24702+ lockdep_off();
1facf9fc 24703+ err = vfs_rmdir(dir, path->dentry);
2cbb1c4b 24704+ lockdep_on();
1facf9fc 24705+ if (!err) {
24706+ struct path tmp = {
24707+ .dentry = path->dentry->d_parent,
24708+ .mnt = path->mnt
24709+ };
24710+
24711+ vfsub_update_h_iattr(&tmp, /*did*/NULL); /*ignore*/
24712+ }
24713+
4f0767ce 24714+out:
1facf9fc 24715+ return err;
24716+}
24717+
24718+/* ---------------------------------------------------------------------- */
24719+
24720+ssize_t vfsub_read_u(struct file *file, char __user *ubuf, size_t count,
24721+ loff_t *ppos)
24722+{
24723+ ssize_t err;
24724+
2cbb1c4b 24725+ lockdep_off();
1facf9fc 24726+ err = vfs_read(file, ubuf, count, ppos);
2cbb1c4b 24727+ lockdep_on();
1facf9fc 24728+ if (err >= 0)
24729+ vfsub_update_h_iattr(&file->f_path, /*did*/NULL); /*ignore*/
24730+ return err;
24731+}
24732+
24733+/* todo: kernel_read()? */
24734+ssize_t vfsub_read_k(struct file *file, void *kbuf, size_t count,
24735+ loff_t *ppos)
24736+{
24737+ ssize_t err;
24738+ mm_segment_t oldfs;
b752ccd1
AM
24739+ union {
24740+ void *k;
24741+ char __user *u;
24742+ } buf;
1facf9fc 24743+
b752ccd1 24744+ buf.k = kbuf;
1facf9fc 24745+ oldfs = get_fs();
24746+ set_fs(KERNEL_DS);
b752ccd1 24747+ err = vfsub_read_u(file, buf.u, count, ppos);
1facf9fc 24748+ set_fs(oldfs);
24749+ return err;
24750+}
24751+
24752+ssize_t vfsub_write_u(struct file *file, const char __user *ubuf, size_t count,
24753+ loff_t *ppos)
24754+{
24755+ ssize_t err;
24756+
2cbb1c4b 24757+ lockdep_off();
1facf9fc 24758+ err = vfs_write(file, ubuf, count, ppos);
2cbb1c4b 24759+ lockdep_on();
1facf9fc 24760+ if (err >= 0)
24761+ vfsub_update_h_iattr(&file->f_path, /*did*/NULL); /*ignore*/
24762+ return err;
24763+}
24764+
24765+ssize_t vfsub_write_k(struct file *file, void *kbuf, size_t count, loff_t *ppos)
24766+{
24767+ ssize_t err;
24768+ mm_segment_t oldfs;
b752ccd1
AM
24769+ union {
24770+ void *k;
24771+ const char __user *u;
24772+ } buf;
1facf9fc 24773+
b752ccd1 24774+ buf.k = kbuf;
1facf9fc 24775+ oldfs = get_fs();
24776+ set_fs(KERNEL_DS);
b752ccd1 24777+ err = vfsub_write_u(file, buf.u, count, ppos);
1facf9fc 24778+ set_fs(oldfs);
24779+ return err;
24780+}
24781+
4a4d8108
AM
24782+int vfsub_flush(struct file *file, fl_owner_t id)
24783+{
24784+ int err;
24785+
24786+ err = 0;
24787+ if (file->f_op && file->f_op->flush) {
2cbb1c4b
JR
24788+ if (!au_test_nfs(file->f_dentry->d_sb))
24789+ err = file->f_op->flush(file, id);
24790+ else {
24791+ lockdep_off();
24792+ err = file->f_op->flush(file, id);
24793+ lockdep_on();
24794+ }
4a4d8108
AM
24795+ if (!err)
24796+ vfsub_update_h_iattr(&file->f_path, /*did*/NULL);
24797+ /*ignore*/
24798+ }
24799+ return err;
24800+}
24801+
1facf9fc 24802+int vfsub_readdir(struct file *file, filldir_t filldir, void *arg)
24803+{
24804+ int err;
24805+
2cbb1c4b 24806+ lockdep_off();
1facf9fc 24807+ err = vfs_readdir(file, filldir, arg);
2cbb1c4b 24808+ lockdep_on();
1facf9fc 24809+ if (err >= 0)
24810+ vfsub_update_h_iattr(&file->f_path, /*did*/NULL); /*ignore*/
24811+ return err;
24812+}
24813+
24814+long vfsub_splice_to(struct file *in, loff_t *ppos,
24815+ struct pipe_inode_info *pipe, size_t len,
24816+ unsigned int flags)
24817+{
24818+ long err;
24819+
2cbb1c4b 24820+ lockdep_off();
0fc653ad 24821+ err = do_splice_to(in, ppos, pipe, len, flags);
2cbb1c4b 24822+ lockdep_on();
4a4d8108 24823+ file_accessed(in);
1facf9fc 24824+ if (err >= 0)
24825+ vfsub_update_h_iattr(&in->f_path, /*did*/NULL); /*ignore*/
24826+ return err;
24827+}
24828+
24829+long vfsub_splice_from(struct pipe_inode_info *pipe, struct file *out,
24830+ loff_t *ppos, size_t len, unsigned int flags)
24831+{
24832+ long err;
24833+
2cbb1c4b 24834+ lockdep_off();
0fc653ad 24835+ err = do_splice_from(pipe, out, ppos, len, flags);
2cbb1c4b 24836+ lockdep_on();
1facf9fc 24837+ if (err >= 0)
24838+ vfsub_update_h_iattr(&out->f_path, /*did*/NULL); /*ignore*/
24839+ return err;
24840+}
24841+
24842+/* cf. open.c:do_sys_truncate() and do_sys_ftruncate() */
24843+int vfsub_trunc(struct path *h_path, loff_t length, unsigned int attr,
24844+ struct file *h_file)
24845+{
24846+ int err;
24847+ struct inode *h_inode;
24848+
24849+ h_inode = h_path->dentry->d_inode;
24850+ if (!h_file) {
24851+ err = mnt_want_write(h_path->mnt);
24852+ if (err)
24853+ goto out;
24854+ err = inode_permission(h_inode, MAY_WRITE);
24855+ if (err)
24856+ goto out_mnt;
24857+ err = get_write_access(h_inode);
24858+ if (err)
24859+ goto out_mnt;
4a4d8108 24860+ err = break_lease(h_inode, O_WRONLY);
1facf9fc 24861+ if (err)
24862+ goto out_inode;
24863+ }
24864+
24865+ err = locks_verify_truncate(h_inode, h_file, length);
24866+ if (!err)
953406b4 24867+ err = security_path_truncate(h_path);
2cbb1c4b
JR
24868+ if (!err) {
24869+ lockdep_off();
1facf9fc 24870+ err = do_truncate(h_path->dentry, length, attr, h_file);
2cbb1c4b
JR
24871+ lockdep_on();
24872+ }
1facf9fc 24873+
4f0767ce 24874+out_inode:
1facf9fc 24875+ if (!h_file)
24876+ put_write_access(h_inode);
4f0767ce 24877+out_mnt:
1facf9fc 24878+ if (!h_file)
24879+ mnt_drop_write(h_path->mnt);
4f0767ce 24880+out:
1facf9fc 24881+ return err;
24882+}
24883+
24884+/* ---------------------------------------------------------------------- */
24885+
24886+struct au_vfsub_mkdir_args {
24887+ int *errp;
24888+ struct inode *dir;
24889+ struct path *path;
24890+ int mode;
24891+};
24892+
24893+static void au_call_vfsub_mkdir(void *args)
24894+{
24895+ struct au_vfsub_mkdir_args *a = args;
24896+ *a->errp = vfsub_mkdir(a->dir, a->path, a->mode);
24897+}
24898+
24899+int vfsub_sio_mkdir(struct inode *dir, struct path *path, int mode)
24900+{
24901+ int err, do_sio, wkq_err;
24902+
24903+ do_sio = au_test_h_perm_sio(dir, MAY_EXEC | MAY_WRITE);
24904+ if (!do_sio)
24905+ err = vfsub_mkdir(dir, path, mode);
24906+ else {
24907+ struct au_vfsub_mkdir_args args = {
24908+ .errp = &err,
24909+ .dir = dir,
24910+ .path = path,
24911+ .mode = mode
24912+ };
24913+ wkq_err = au_wkq_wait(au_call_vfsub_mkdir, &args);
24914+ if (unlikely(wkq_err))
24915+ err = wkq_err;
24916+ }
24917+
24918+ return err;
24919+}
24920+
24921+struct au_vfsub_rmdir_args {
24922+ int *errp;
24923+ struct inode *dir;
24924+ struct path *path;
24925+};
24926+
24927+static void au_call_vfsub_rmdir(void *args)
24928+{
24929+ struct au_vfsub_rmdir_args *a = args;
24930+ *a->errp = vfsub_rmdir(a->dir, a->path);
24931+}
24932+
24933+int vfsub_sio_rmdir(struct inode *dir, struct path *path)
24934+{
24935+ int err, do_sio, wkq_err;
24936+
24937+ do_sio = au_test_h_perm_sio(dir, MAY_EXEC | MAY_WRITE);
24938+ if (!do_sio)
24939+ err = vfsub_rmdir(dir, path);
24940+ else {
24941+ struct au_vfsub_rmdir_args args = {
24942+ .errp = &err,
24943+ .dir = dir,
24944+ .path = path
24945+ };
24946+ wkq_err = au_wkq_wait(au_call_vfsub_rmdir, &args);
24947+ if (unlikely(wkq_err))
24948+ err = wkq_err;
24949+ }
24950+
24951+ return err;
24952+}
24953+
24954+/* ---------------------------------------------------------------------- */
24955+
24956+struct notify_change_args {
24957+ int *errp;
24958+ struct path *path;
24959+ struct iattr *ia;
24960+};
24961+
24962+static void call_notify_change(void *args)
24963+{
24964+ struct notify_change_args *a = args;
24965+ struct inode *h_inode;
24966+
24967+ h_inode = a->path->dentry->d_inode;
24968+ IMustLock(h_inode);
24969+
24970+ *a->errp = -EPERM;
24971+ if (!IS_IMMUTABLE(h_inode) && !IS_APPEND(h_inode)) {
1facf9fc 24972+ *a->errp = notify_change(a->path->dentry, a->ia);
1facf9fc 24973+ if (!*a->errp)
24974+ vfsub_update_h_iattr(a->path, /*did*/NULL); /*ignore*/
24975+ }
24976+ AuTraceErr(*a->errp);
24977+}
24978+
24979+int vfsub_notify_change(struct path *path, struct iattr *ia)
24980+{
24981+ int err;
24982+ struct notify_change_args args = {
24983+ .errp = &err,
24984+ .path = path,
24985+ .ia = ia
24986+ };
24987+
24988+ call_notify_change(&args);
24989+
24990+ return err;
24991+}
24992+
24993+int vfsub_sio_notify_change(struct path *path, struct iattr *ia)
24994+{
24995+ int err, wkq_err;
24996+ struct notify_change_args args = {
24997+ .errp = &err,
24998+ .path = path,
24999+ .ia = ia
25000+ };
25001+
25002+ wkq_err = au_wkq_wait(call_notify_change, &args);
25003+ if (unlikely(wkq_err))
25004+ err = wkq_err;
25005+
25006+ return err;
25007+}
25008+
25009+/* ---------------------------------------------------------------------- */
25010+
25011+struct unlink_args {
25012+ int *errp;
25013+ struct inode *dir;
25014+ struct path *path;
25015+};
25016+
25017+static void call_unlink(void *args)
25018+{
25019+ struct unlink_args *a = args;
25020+ struct dentry *d = a->path->dentry;
25021+ struct inode *h_inode;
25022+ const int stop_sillyrename = (au_test_nfs(d->d_sb)
027c5e7a 25023+ && d->d_count == 1);
1facf9fc 25024+
25025+ IMustLock(a->dir);
25026+
25027+ a->path->dentry = d->d_parent;
25028+ *a->errp = security_path_unlink(a->path, d);
25029+ a->path->dentry = d;
25030+ if (unlikely(*a->errp))
25031+ return;
25032+
25033+ if (!stop_sillyrename)
25034+ dget(d);
25035+ h_inode = d->d_inode;
25036+ if (h_inode)
027c5e7a 25037+ ihold(h_inode);
1facf9fc 25038+
2cbb1c4b 25039+ lockdep_off();
1facf9fc 25040+ *a->errp = vfs_unlink(a->dir, d);
2cbb1c4b 25041+ lockdep_on();
1facf9fc 25042+ if (!*a->errp) {
25043+ struct path tmp = {
25044+ .dentry = d->d_parent,
25045+ .mnt = a->path->mnt
25046+ };
25047+ vfsub_update_h_iattr(&tmp, /*did*/NULL); /*ignore*/
25048+ }
25049+
25050+ if (!stop_sillyrename)
25051+ dput(d);
25052+ if (h_inode)
25053+ iput(h_inode);
25054+
25055+ AuTraceErr(*a->errp);
25056+}
25057+
25058+/*
25059+ * @dir: must be locked.
25060+ * @dentry: target dentry.
25061+ */
25062+int vfsub_unlink(struct inode *dir, struct path *path, int force)
25063+{
25064+ int err;
25065+ struct unlink_args args = {
25066+ .errp = &err,
25067+ .dir = dir,
25068+ .path = path
25069+ };
25070+
25071+ if (!force)
25072+ call_unlink(&args);
25073+ else {
25074+ int wkq_err;
25075+
25076+ wkq_err = au_wkq_wait(call_unlink, &args);
25077+ if (unlikely(wkq_err))
25078+ err = wkq_err;
25079+ }
25080+
25081+ return err;
25082+}
7f207e10
AM
25083diff -urN /usr/share/empty/fs/aufs/vfsub.h linux/fs/aufs/vfsub.h
25084--- /usr/share/empty/fs/aufs/vfsub.h 1970-01-01 01:00:00.000000000 +0100
87a755f4 25085+++ linux/fs/aufs/vfsub.h 2011-07-22 08:26:47.857636522 +0200
2cbb1c4b 25086@@ -0,0 +1,231 @@
1facf9fc 25087+/*
027c5e7a 25088+ * Copyright (C) 2005-2011 Junjiro R. Okajima
1facf9fc 25089+ *
25090+ * This program, aufs is free software; you can redistribute it and/or modify
25091+ * it under the terms of the GNU General Public License as published by
25092+ * the Free Software Foundation; either version 2 of the License, or
25093+ * (at your option) any later version.
dece6358
AM
25094+ *
25095+ * This program is distributed in the hope that it will be useful,
25096+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
25097+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
25098+ * GNU General Public License for more details.
25099+ *
25100+ * You should have received a copy of the GNU General Public License
25101+ * along with this program; if not, write to the Free Software
25102+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 25103+ */
25104+
25105+/*
25106+ * sub-routines for VFS
25107+ */
25108+
25109+#ifndef __AUFS_VFSUB_H__
25110+#define __AUFS_VFSUB_H__
25111+
25112+#ifdef __KERNEL__
25113+
25114+#include <linux/fs.h>
0c5527e5 25115+#include <linux/lglock.h>
7f207e10 25116+#include "debug.h"
1facf9fc 25117+
7f207e10 25118+/* copied from linux/fs/internal.h */
2cbb1c4b 25119+/* todo: BAD approach!! */
0c5527e5 25120+DECLARE_BRLOCK(vfsmount_lock);
0c5527e5 25121+extern void file_sb_list_del(struct file *f);
2cbb1c4b 25122+extern spinlock_t inode_sb_list_lock;
0c5527e5 25123+
7f207e10
AM
25124+/* copied from linux/fs/file_table.c */
25125+DECLARE_LGLOCK(files_lglock);
0c5527e5
AM
25126+#ifdef CONFIG_SMP
25127+/*
25128+ * These macros iterate all files on all CPUs for a given superblock.
25129+ * files_lglock must be held globally.
25130+ */
25131+#define do_file_list_for_each_entry(__sb, __file) \
25132+{ \
25133+ int i; \
25134+ for_each_possible_cpu(i) { \
25135+ struct list_head *list; \
25136+ list = per_cpu_ptr((__sb)->s_files, i); \
25137+ list_for_each_entry((__file), list, f_u.fu_list)
25138+
25139+#define while_file_list_for_each_entry \
25140+ } \
25141+}
25142+
25143+#else
25144+
25145+#define do_file_list_for_each_entry(__sb, __file) \
25146+{ \
25147+ struct list_head *list; \
25148+ list = &(sb)->s_files; \
25149+ list_for_each_entry((__file), list, f_u.fu_list)
25150+
25151+#define while_file_list_for_each_entry \
25152+}
7f207e10
AM
25153+#endif
25154+
25155+/* ---------------------------------------------------------------------- */
1facf9fc 25156+
25157+/* lock subclass for lower inode */
25158+/* default MAX_LOCKDEP_SUBCLASSES(8) is not enough */
25159+/* reduce? gave up. */
25160+enum {
25161+ AuLsc_I_Begin = I_MUTEX_QUOTA, /* 4 */
25162+ AuLsc_I_PARENT, /* lower inode, parent first */
25163+ AuLsc_I_PARENT2, /* copyup dirs */
dece6358 25164+ AuLsc_I_PARENT3, /* copyup wh */
1facf9fc 25165+ AuLsc_I_CHILD,
25166+ AuLsc_I_CHILD2,
25167+ AuLsc_I_End
25168+};
25169+
25170+/* to debug easier, do not make them inlined functions */
25171+#define MtxMustLock(mtx) AuDebugOn(!mutex_is_locked(mtx))
25172+#define IMustLock(i) MtxMustLock(&(i)->i_mutex)
25173+
25174+/* ---------------------------------------------------------------------- */
25175+
7f207e10
AM
25176+static inline void vfsub_drop_nlink(struct inode *inode)
25177+{
25178+ AuDebugOn(!inode->i_nlink);
25179+ drop_nlink(inode);
25180+}
25181+
027c5e7a
AM
25182+static inline void vfsub_dead_dir(struct inode *inode)
25183+{
25184+ AuDebugOn(!S_ISDIR(inode->i_mode));
25185+ inode->i_flags |= S_DEAD;
25186+ clear_nlink(inode);
25187+}
25188+
7f207e10
AM
25189+/* ---------------------------------------------------------------------- */
25190+
25191+int vfsub_update_h_iattr(struct path *h_path, int *did);
25192+struct file *vfsub_dentry_open(struct path *path, int flags);
25193+struct file *vfsub_filp_open(const char *path, int oflags, int mode);
1facf9fc 25194+int vfsub_kern_path(const char *name, unsigned int flags, struct path *path);
25195+struct dentry *vfsub_lookup_one_len(const char *name, struct dentry *parent,
25196+ int len);
25197+struct dentry *vfsub_lookup_hash(struct nameidata *nd);
2cbb1c4b 25198+int vfsub_name_hash(const char *name, struct qstr *this, int len);
1facf9fc 25199+
25200+/* ---------------------------------------------------------------------- */
25201+
25202+struct au_hinode;
25203+struct dentry *vfsub_lock_rename(struct dentry *d1, struct au_hinode *hdir1,
25204+ struct dentry *d2, struct au_hinode *hdir2);
25205+void vfsub_unlock_rename(struct dentry *d1, struct au_hinode *hdir1,
25206+ struct dentry *d2, struct au_hinode *hdir2);
25207+
25208+int vfsub_create(struct inode *dir, struct path *path, int mode);
25209+int vfsub_symlink(struct inode *dir, struct path *path,
25210+ const char *symname);
25211+int vfsub_mknod(struct inode *dir, struct path *path, int mode, dev_t dev);
25212+int vfsub_link(struct dentry *src_dentry, struct inode *dir,
25213+ struct path *path);
25214+int vfsub_rename(struct inode *src_hdir, struct dentry *src_dentry,
25215+ struct inode *hdir, struct path *path);
25216+int vfsub_mkdir(struct inode *dir, struct path *path, int mode);
25217+int vfsub_rmdir(struct inode *dir, struct path *path);
25218+
25219+/* ---------------------------------------------------------------------- */
25220+
25221+ssize_t vfsub_read_u(struct file *file, char __user *ubuf, size_t count,
25222+ loff_t *ppos);
25223+ssize_t vfsub_read_k(struct file *file, void *kbuf, size_t count,
25224+ loff_t *ppos);
25225+ssize_t vfsub_write_u(struct file *file, const char __user *ubuf, size_t count,
25226+ loff_t *ppos);
25227+ssize_t vfsub_write_k(struct file *file, void *kbuf, size_t count,
25228+ loff_t *ppos);
4a4d8108 25229+int vfsub_flush(struct file *file, fl_owner_t id);
1facf9fc 25230+int vfsub_readdir(struct file *file, filldir_t filldir, void *arg);
25231+
4a4d8108
AM
25232+static inline unsigned int vfsub_file_flags(struct file *file)
25233+{
25234+ unsigned int flags;
25235+
25236+ spin_lock(&file->f_lock);
25237+ flags = file->f_flags;
25238+ spin_unlock(&file->f_lock);
25239+
25240+ return flags;
25241+}
1308ab2a 25242+
1facf9fc 25243+static inline void vfsub_file_accessed(struct file *h_file)
25244+{
25245+ file_accessed(h_file);
25246+ vfsub_update_h_iattr(&h_file->f_path, /*did*/NULL); /*ignore*/
25247+}
25248+
25249+static inline void vfsub_touch_atime(struct vfsmount *h_mnt,
25250+ struct dentry *h_dentry)
25251+{
25252+ struct path h_path = {
25253+ .dentry = h_dentry,
25254+ .mnt = h_mnt
25255+ };
25256+ touch_atime(h_mnt, h_dentry);
25257+ vfsub_update_h_iattr(&h_path, /*did*/NULL); /*ignore*/
25258+}
25259+
4a4d8108
AM
25260+long vfsub_splice_to(struct file *in, loff_t *ppos,
25261+ struct pipe_inode_info *pipe, size_t len,
25262+ unsigned int flags);
25263+long vfsub_splice_from(struct pipe_inode_info *pipe, struct file *out,
25264+ loff_t *ppos, size_t len, unsigned int flags);
25265+int vfsub_trunc(struct path *h_path, loff_t length, unsigned int attr,
25266+ struct file *h_file);
25267+
1facf9fc 25268+/* ---------------------------------------------------------------------- */
25269+
25270+static inline loff_t vfsub_llseek(struct file *file, loff_t offset, int origin)
25271+{
25272+ loff_t err;
25273+
2cbb1c4b 25274+ lockdep_off();
1facf9fc 25275+ err = vfs_llseek(file, offset, origin);
2cbb1c4b 25276+ lockdep_on();
1facf9fc 25277+ return err;
25278+}
25279+
25280+/* ---------------------------------------------------------------------- */
25281+
25282+/* dirty workaround for strict type of fmode_t */
25283+union vfsub_fmu {
25284+ fmode_t fm;
25285+ unsigned int ui;
25286+};
25287+
25288+static inline unsigned int vfsub_fmode_to_uint(fmode_t fm)
25289+{
25290+ union vfsub_fmu u = {
25291+ .fm = fm
25292+ };
25293+
25294+ BUILD_BUG_ON(sizeof(u.fm) != sizeof(u.ui));
25295+
25296+ return u.ui;
25297+}
25298+
25299+static inline fmode_t vfsub_uint_to_fmode(unsigned int ui)
25300+{
25301+ union vfsub_fmu u = {
25302+ .ui = ui
25303+ };
25304+
25305+ return u.fm;
25306+}
25307+
4a4d8108
AM
25308+/* ---------------------------------------------------------------------- */
25309+
25310+int vfsub_sio_mkdir(struct inode *dir, struct path *path, int mode);
25311+int vfsub_sio_rmdir(struct inode *dir, struct path *path);
25312+int vfsub_sio_notify_change(struct path *path, struct iattr *ia);
25313+int vfsub_notify_change(struct path *path, struct iattr *ia);
25314+int vfsub_unlink(struct inode *dir, struct path *path, int force);
25315+
1facf9fc 25316+#endif /* __KERNEL__ */
25317+#endif /* __AUFS_VFSUB_H__ */
7f207e10
AM
25318diff -urN /usr/share/empty/fs/aufs/wbr_policy.c linux/fs/aufs/wbr_policy.c
25319--- /usr/share/empty/fs/aufs/wbr_policy.c 1970-01-01 01:00:00.000000000 +0100
87a755f4 25320+++ linux/fs/aufs/wbr_policy.c 2011-03-17 10:46:59.000000000 +0100
027c5e7a 25321@@ -0,0 +1,700 @@
1facf9fc 25322+/*
027c5e7a 25323+ * Copyright (C) 2005-2011 Junjiro R. Okajima
1facf9fc 25324+ *
25325+ * This program, aufs is free software; you can redistribute it and/or modify
25326+ * it under the terms of the GNU General Public License as published by
25327+ * the Free Software Foundation; either version 2 of the License, or
25328+ * (at your option) any later version.
dece6358
AM
25329+ *
25330+ * This program is distributed in the hope that it will be useful,
25331+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
25332+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
25333+ * GNU General Public License for more details.
25334+ *
25335+ * You should have received a copy of the GNU General Public License
25336+ * along with this program; if not, write to the Free Software
25337+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 25338+ */
25339+
25340+/*
25341+ * policies for selecting one among multiple writable branches
25342+ */
25343+
25344+#include <linux/statfs.h>
25345+#include "aufs.h"
25346+
25347+/* subset of cpup_attr() */
25348+static noinline_for_stack
25349+int au_cpdown_attr(struct path *h_path, struct dentry *h_src)
25350+{
25351+ int err, sbits;
25352+ struct iattr ia;
25353+ struct inode *h_isrc;
25354+
25355+ h_isrc = h_src->d_inode;
25356+ ia.ia_valid = ATTR_FORCE | ATTR_MODE | ATTR_UID | ATTR_GID;
25357+ ia.ia_mode = h_isrc->i_mode;
25358+ ia.ia_uid = h_isrc->i_uid;
25359+ ia.ia_gid = h_isrc->i_gid;
25360+ sbits = !!(ia.ia_mode & (S_ISUID | S_ISGID));
25361+ au_cpup_attr_flags(h_path->dentry->d_inode, h_isrc);
25362+ err = vfsub_sio_notify_change(h_path, &ia);
25363+
25364+ /* is this nfs only? */
25365+ if (!err && sbits && au_test_nfs(h_path->dentry->d_sb)) {
25366+ ia.ia_valid = ATTR_FORCE | ATTR_MODE;
25367+ ia.ia_mode = h_isrc->i_mode;
25368+ err = vfsub_sio_notify_change(h_path, &ia);
25369+ }
25370+
25371+ return err;
25372+}
25373+
25374+#define AuCpdown_PARENT_OPQ 1
25375+#define AuCpdown_WHED (1 << 1)
25376+#define AuCpdown_MADE_DIR (1 << 2)
25377+#define AuCpdown_DIROPQ (1 << 3)
25378+#define au_ftest_cpdown(flags, name) ((flags) & AuCpdown_##name)
7f207e10
AM
25379+#define au_fset_cpdown(flags, name) \
25380+ do { (flags) |= AuCpdown_##name; } while (0)
25381+#define au_fclr_cpdown(flags, name) \
25382+ do { (flags) &= ~AuCpdown_##name; } while (0)
1facf9fc 25383+
25384+struct au_cpdown_dir_args {
25385+ struct dentry *parent;
25386+ unsigned int flags;
25387+};
25388+
25389+static int au_cpdown_dir_opq(struct dentry *dentry, aufs_bindex_t bdst,
25390+ struct au_cpdown_dir_args *a)
25391+{
25392+ int err;
25393+ struct dentry *opq_dentry;
25394+
25395+ opq_dentry = au_diropq_create(dentry, bdst);
25396+ err = PTR_ERR(opq_dentry);
25397+ if (IS_ERR(opq_dentry))
25398+ goto out;
25399+ dput(opq_dentry);
25400+ au_fset_cpdown(a->flags, DIROPQ);
25401+
4f0767ce 25402+out:
1facf9fc 25403+ return err;
25404+}
25405+
25406+static int au_cpdown_dir_wh(struct dentry *dentry, struct dentry *h_parent,
25407+ struct inode *dir, aufs_bindex_t bdst)
25408+{
25409+ int err;
25410+ struct path h_path;
25411+ struct au_branch *br;
25412+
25413+ br = au_sbr(dentry->d_sb, bdst);
25414+ h_path.dentry = au_wh_lkup(h_parent, &dentry->d_name, br);
25415+ err = PTR_ERR(h_path.dentry);
25416+ if (IS_ERR(h_path.dentry))
25417+ goto out;
25418+
25419+ err = 0;
25420+ if (h_path.dentry->d_inode) {
25421+ h_path.mnt = br->br_mnt;
25422+ err = au_wh_unlink_dentry(au_h_iptr(dir, bdst), &h_path,
25423+ dentry);
25424+ }
25425+ dput(h_path.dentry);
25426+
4f0767ce 25427+out:
1facf9fc 25428+ return err;
25429+}
25430+
25431+static int au_cpdown_dir(struct dentry *dentry, aufs_bindex_t bdst,
25432+ struct dentry *h_parent, void *arg)
25433+{
25434+ int err, rerr;
4a4d8108 25435+ aufs_bindex_t bopq, bstart;
1facf9fc 25436+ struct path h_path;
25437+ struct dentry *parent;
25438+ struct inode *h_dir, *h_inode, *inode, *dir;
25439+ struct au_cpdown_dir_args *args = arg;
25440+
25441+ bstart = au_dbstart(dentry);
25442+ /* dentry is di-locked */
25443+ parent = dget_parent(dentry);
25444+ dir = parent->d_inode;
25445+ h_dir = h_parent->d_inode;
25446+ AuDebugOn(h_dir != au_h_iptr(dir, bdst));
25447+ IMustLock(h_dir);
25448+
25449+ err = au_lkup_neg(dentry, bdst);
25450+ if (unlikely(err < 0))
25451+ goto out;
25452+ h_path.dentry = au_h_dptr(dentry, bdst);
25453+ h_path.mnt = au_sbr_mnt(dentry->d_sb, bdst);
25454+ err = vfsub_sio_mkdir(au_h_iptr(dir, bdst), &h_path,
25455+ S_IRWXU | S_IRUGO | S_IXUGO);
25456+ if (unlikely(err))
25457+ goto out_put;
25458+ au_fset_cpdown(args->flags, MADE_DIR);
25459+
1facf9fc 25460+ bopq = au_dbdiropq(dentry);
25461+ au_fclr_cpdown(args->flags, WHED);
25462+ au_fclr_cpdown(args->flags, DIROPQ);
25463+ if (au_dbwh(dentry) == bdst)
25464+ au_fset_cpdown(args->flags, WHED);
25465+ if (!au_ftest_cpdown(args->flags, PARENT_OPQ) && bopq <= bdst)
25466+ au_fset_cpdown(args->flags, PARENT_OPQ);
1facf9fc 25467+ h_inode = h_path.dentry->d_inode;
25468+ mutex_lock_nested(&h_inode->i_mutex, AuLsc_I_CHILD);
25469+ if (au_ftest_cpdown(args->flags, WHED)) {
25470+ err = au_cpdown_dir_opq(dentry, bdst, args);
25471+ if (unlikely(err)) {
25472+ mutex_unlock(&h_inode->i_mutex);
25473+ goto out_dir;
25474+ }
25475+ }
25476+
25477+ err = au_cpdown_attr(&h_path, au_h_dptr(dentry, bstart));
25478+ mutex_unlock(&h_inode->i_mutex);
25479+ if (unlikely(err))
25480+ goto out_opq;
25481+
25482+ if (au_ftest_cpdown(args->flags, WHED)) {
25483+ err = au_cpdown_dir_wh(dentry, h_parent, dir, bdst);
25484+ if (unlikely(err))
25485+ goto out_opq;
25486+ }
25487+
25488+ inode = dentry->d_inode;
25489+ if (au_ibend(inode) < bdst)
25490+ au_set_ibend(inode, bdst);
25491+ au_set_h_iptr(inode, bdst, au_igrab(h_inode),
25492+ au_hi_flags(inode, /*isdir*/1));
25493+ goto out; /* success */
25494+
25495+ /* revert */
4f0767ce 25496+out_opq:
1facf9fc 25497+ if (au_ftest_cpdown(args->flags, DIROPQ)) {
25498+ mutex_lock_nested(&h_inode->i_mutex, AuLsc_I_CHILD);
25499+ rerr = au_diropq_remove(dentry, bdst);
25500+ mutex_unlock(&h_inode->i_mutex);
25501+ if (unlikely(rerr)) {
25502+ AuIOErr("failed removing diropq for %.*s b%d (%d)\n",
25503+ AuDLNPair(dentry), bdst, rerr);
25504+ err = -EIO;
25505+ goto out;
25506+ }
25507+ }
4f0767ce 25508+out_dir:
1facf9fc 25509+ if (au_ftest_cpdown(args->flags, MADE_DIR)) {
25510+ rerr = vfsub_sio_rmdir(au_h_iptr(dir, bdst), &h_path);
25511+ if (unlikely(rerr)) {
25512+ AuIOErr("failed removing %.*s b%d (%d)\n",
25513+ AuDLNPair(dentry), bdst, rerr);
25514+ err = -EIO;
25515+ }
25516+ }
4f0767ce 25517+out_put:
1facf9fc 25518+ au_set_h_dptr(dentry, bdst, NULL);
25519+ if (au_dbend(dentry) == bdst)
25520+ au_update_dbend(dentry);
4f0767ce 25521+out:
1facf9fc 25522+ dput(parent);
25523+ return err;
25524+}
25525+
25526+int au_cpdown_dirs(struct dentry *dentry, aufs_bindex_t bdst)
25527+{
25528+ int err;
25529+ struct au_cpdown_dir_args args = {
25530+ .parent = dget_parent(dentry),
25531+ .flags = 0
25532+ };
25533+
25534+ err = au_cp_dirs(dentry, bdst, au_cpdown_dir, &args);
25535+ dput(args.parent);
25536+
25537+ return err;
25538+}
25539+
25540+/* ---------------------------------------------------------------------- */
25541+
25542+/* policies for create */
25543+
4a4d8108
AM
25544+static int au_wbr_nonopq(struct dentry *dentry, aufs_bindex_t bindex)
25545+{
25546+ int err, i, j, ndentry;
25547+ aufs_bindex_t bopq;
25548+ struct au_dcsub_pages dpages;
25549+ struct au_dpage *dpage;
25550+ struct dentry **dentries, *parent, *d;
25551+
25552+ err = au_dpages_init(&dpages, GFP_NOFS);
25553+ if (unlikely(err))
25554+ goto out;
25555+ parent = dget_parent(dentry);
027c5e7a 25556+ err = au_dcsub_pages_rev_aufs(&dpages, parent, /*do_include*/0);
4a4d8108
AM
25557+ if (unlikely(err))
25558+ goto out_free;
25559+
25560+ err = bindex;
25561+ for (i = 0; i < dpages.ndpage; i++) {
25562+ dpage = dpages.dpages + i;
25563+ dentries = dpage->dentries;
25564+ ndentry = dpage->ndentry;
25565+ for (j = 0; j < ndentry; j++) {
25566+ d = dentries[j];
25567+ di_read_lock_parent2(d, !AuLock_IR);
25568+ bopq = au_dbdiropq(d);
25569+ di_read_unlock(d, !AuLock_IR);
25570+ if (bopq >= 0 && bopq < err)
25571+ err = bopq;
25572+ }
25573+ }
25574+
25575+out_free:
25576+ dput(parent);
25577+ au_dpages_free(&dpages);
25578+out:
25579+ return err;
25580+}
25581+
1facf9fc 25582+static int au_wbr_bu(struct super_block *sb, aufs_bindex_t bindex)
25583+{
25584+ for (; bindex >= 0; bindex--)
25585+ if (!au_br_rdonly(au_sbr(sb, bindex)))
25586+ return bindex;
25587+ return -EROFS;
25588+}
25589+
25590+/* top down parent */
25591+static int au_wbr_create_tdp(struct dentry *dentry, int isdir __maybe_unused)
25592+{
25593+ int err;
25594+ aufs_bindex_t bstart, bindex;
25595+ struct super_block *sb;
25596+ struct dentry *parent, *h_parent;
25597+
25598+ sb = dentry->d_sb;
25599+ bstart = au_dbstart(dentry);
25600+ err = bstart;
25601+ if (!au_br_rdonly(au_sbr(sb, bstart)))
25602+ goto out;
25603+
25604+ err = -EROFS;
25605+ parent = dget_parent(dentry);
25606+ for (bindex = au_dbstart(parent); bindex < bstart; bindex++) {
25607+ h_parent = au_h_dptr(parent, bindex);
25608+ if (!h_parent || !h_parent->d_inode)
25609+ continue;
25610+
25611+ if (!au_br_rdonly(au_sbr(sb, bindex))) {
25612+ err = bindex;
25613+ break;
25614+ }
25615+ }
25616+ dput(parent);
25617+
25618+ /* bottom up here */
4a4d8108 25619+ if (unlikely(err < 0)) {
1facf9fc 25620+ err = au_wbr_bu(sb, bstart - 1);
4a4d8108
AM
25621+ if (err >= 0)
25622+ err = au_wbr_nonopq(dentry, err);
25623+ }
1facf9fc 25624+
4f0767ce 25625+out:
1facf9fc 25626+ AuDbg("b%d\n", err);
25627+ return err;
25628+}
25629+
25630+/* ---------------------------------------------------------------------- */
25631+
25632+/* an exception for the policy other than tdp */
25633+static int au_wbr_create_exp(struct dentry *dentry)
25634+{
25635+ int err;
25636+ aufs_bindex_t bwh, bdiropq;
25637+ struct dentry *parent;
25638+
25639+ err = -1;
25640+ bwh = au_dbwh(dentry);
25641+ parent = dget_parent(dentry);
25642+ bdiropq = au_dbdiropq(parent);
25643+ if (bwh >= 0) {
25644+ if (bdiropq >= 0)
25645+ err = min(bdiropq, bwh);
25646+ else
25647+ err = bwh;
25648+ AuDbg("%d\n", err);
25649+ } else if (bdiropq >= 0) {
25650+ err = bdiropq;
25651+ AuDbg("%d\n", err);
25652+ }
25653+ dput(parent);
25654+
4a4d8108
AM
25655+ if (err >= 0)
25656+ err = au_wbr_nonopq(dentry, err);
25657+
1facf9fc 25658+ if (err >= 0 && au_br_rdonly(au_sbr(dentry->d_sb, err)))
25659+ err = -1;
25660+
25661+ AuDbg("%d\n", err);
25662+ return err;
25663+}
25664+
25665+/* ---------------------------------------------------------------------- */
25666+
25667+/* round robin */
25668+static int au_wbr_create_init_rr(struct super_block *sb)
25669+{
25670+ int err;
25671+
25672+ err = au_wbr_bu(sb, au_sbend(sb));
25673+ atomic_set(&au_sbi(sb)->si_wbr_rr_next, -err); /* less important */
dece6358 25674+ /* smp_mb(); */
1facf9fc 25675+
25676+ AuDbg("b%d\n", err);
25677+ return err;
25678+}
25679+
25680+static int au_wbr_create_rr(struct dentry *dentry, int isdir)
25681+{
25682+ int err, nbr;
25683+ unsigned int u;
25684+ aufs_bindex_t bindex, bend;
25685+ struct super_block *sb;
25686+ atomic_t *next;
25687+
25688+ err = au_wbr_create_exp(dentry);
25689+ if (err >= 0)
25690+ goto out;
25691+
25692+ sb = dentry->d_sb;
25693+ next = &au_sbi(sb)->si_wbr_rr_next;
25694+ bend = au_sbend(sb);
25695+ nbr = bend + 1;
25696+ for (bindex = 0; bindex <= bend; bindex++) {
25697+ if (!isdir) {
25698+ err = atomic_dec_return(next) + 1;
25699+ /* modulo for 0 is meaningless */
25700+ if (unlikely(!err))
25701+ err = atomic_dec_return(next) + 1;
25702+ } else
25703+ err = atomic_read(next);
25704+ AuDbg("%d\n", err);
25705+ u = err;
25706+ err = u % nbr;
25707+ AuDbg("%d\n", err);
25708+ if (!au_br_rdonly(au_sbr(sb, err)))
25709+ break;
25710+ err = -EROFS;
25711+ }
25712+
4a4d8108
AM
25713+ if (err >= 0)
25714+ err = au_wbr_nonopq(dentry, err);
25715+
4f0767ce 25716+out:
1facf9fc 25717+ AuDbg("%d\n", err);
25718+ return err;
25719+}
25720+
25721+/* ---------------------------------------------------------------------- */
25722+
25723+/* most free space */
25724+static void au_mfs(struct dentry *dentry)
25725+{
25726+ struct super_block *sb;
25727+ struct au_branch *br;
25728+ struct au_wbr_mfs *mfs;
25729+ aufs_bindex_t bindex, bend;
25730+ int err;
25731+ unsigned long long b, bavail;
7f207e10 25732+ struct path h_path;
1facf9fc 25733+ /* reduce the stack usage */
25734+ struct kstatfs *st;
25735+
25736+ st = kmalloc(sizeof(*st), GFP_NOFS);
25737+ if (unlikely(!st)) {
25738+ AuWarn1("failed updating mfs(%d), ignored\n", -ENOMEM);
25739+ return;
25740+ }
25741+
25742+ bavail = 0;
25743+ sb = dentry->d_sb;
25744+ mfs = &au_sbi(sb)->si_wbr_mfs;
dece6358 25745+ MtxMustLock(&mfs->mfs_lock);
1facf9fc 25746+ mfs->mfs_bindex = -EROFS;
25747+ mfs->mfsrr_bytes = 0;
25748+ bend = au_sbend(sb);
25749+ for (bindex = 0; bindex <= bend; bindex++) {
25750+ br = au_sbr(sb, bindex);
25751+ if (au_br_rdonly(br))
25752+ continue;
25753+
25754+ /* sb->s_root for NFS is unreliable */
7f207e10
AM
25755+ h_path.mnt = br->br_mnt;
25756+ h_path.dentry = h_path.mnt->mnt_root;
25757+ err = vfs_statfs(&h_path, st);
1facf9fc 25758+ if (unlikely(err)) {
25759+ AuWarn1("failed statfs, b%d, %d\n", bindex, err);
25760+ continue;
25761+ }
25762+
25763+ /* when the available size is equal, select the lower one */
25764+ BUILD_BUG_ON(sizeof(b) < sizeof(st->f_bavail)
25765+ || sizeof(b) < sizeof(st->f_bsize));
25766+ b = st->f_bavail * st->f_bsize;
25767+ br->br_wbr->wbr_bytes = b;
25768+ if (b >= bavail) {
25769+ bavail = b;
25770+ mfs->mfs_bindex = bindex;
25771+ mfs->mfs_jiffy = jiffies;
25772+ }
25773+ }
25774+
25775+ mfs->mfsrr_bytes = bavail;
25776+ AuDbg("b%d\n", mfs->mfs_bindex);
25777+ kfree(st);
25778+}
25779+
25780+static int au_wbr_create_mfs(struct dentry *dentry, int isdir __maybe_unused)
25781+{
25782+ int err;
25783+ struct super_block *sb;
25784+ struct au_wbr_mfs *mfs;
25785+
25786+ err = au_wbr_create_exp(dentry);
25787+ if (err >= 0)
25788+ goto out;
25789+
25790+ sb = dentry->d_sb;
25791+ mfs = &au_sbi(sb)->si_wbr_mfs;
25792+ mutex_lock(&mfs->mfs_lock);
25793+ if (time_after(jiffies, mfs->mfs_jiffy + mfs->mfs_expire)
25794+ || mfs->mfs_bindex < 0
25795+ || au_br_rdonly(au_sbr(sb, mfs->mfs_bindex)))
25796+ au_mfs(dentry);
25797+ mutex_unlock(&mfs->mfs_lock);
25798+ err = mfs->mfs_bindex;
25799+
4a4d8108
AM
25800+ if (err >= 0)
25801+ err = au_wbr_nonopq(dentry, err);
25802+
4f0767ce 25803+out:
1facf9fc 25804+ AuDbg("b%d\n", err);
25805+ return err;
25806+}
25807+
25808+static int au_wbr_create_init_mfs(struct super_block *sb)
25809+{
25810+ struct au_wbr_mfs *mfs;
25811+
25812+ mfs = &au_sbi(sb)->si_wbr_mfs;
25813+ mutex_init(&mfs->mfs_lock);
25814+ mfs->mfs_jiffy = 0;
25815+ mfs->mfs_bindex = -EROFS;
25816+
25817+ return 0;
25818+}
25819+
25820+static int au_wbr_create_fin_mfs(struct super_block *sb __maybe_unused)
25821+{
25822+ mutex_destroy(&au_sbi(sb)->si_wbr_mfs.mfs_lock);
25823+ return 0;
25824+}
25825+
25826+/* ---------------------------------------------------------------------- */
25827+
25828+/* most free space and then round robin */
25829+static int au_wbr_create_mfsrr(struct dentry *dentry, int isdir)
25830+{
25831+ int err;
25832+ struct au_wbr_mfs *mfs;
25833+
25834+ err = au_wbr_create_mfs(dentry, isdir);
25835+ if (err >= 0) {
25836+ mfs = &au_sbi(dentry->d_sb)->si_wbr_mfs;
dece6358 25837+ mutex_lock(&mfs->mfs_lock);
1facf9fc 25838+ if (mfs->mfsrr_bytes < mfs->mfsrr_watermark)
25839+ err = au_wbr_create_rr(dentry, isdir);
dece6358 25840+ mutex_unlock(&mfs->mfs_lock);
1facf9fc 25841+ }
25842+
25843+ AuDbg("b%d\n", err);
25844+ return err;
25845+}
25846+
25847+static int au_wbr_create_init_mfsrr(struct super_block *sb)
25848+{
25849+ int err;
25850+
25851+ au_wbr_create_init_mfs(sb); /* ignore */
25852+ err = au_wbr_create_init_rr(sb);
25853+
25854+ return err;
25855+}
25856+
25857+/* ---------------------------------------------------------------------- */
25858+
25859+/* top down parent and most free space */
25860+static int au_wbr_create_pmfs(struct dentry *dentry, int isdir)
25861+{
25862+ int err, e2;
25863+ unsigned long long b;
25864+ aufs_bindex_t bindex, bstart, bend;
25865+ struct super_block *sb;
25866+ struct dentry *parent, *h_parent;
25867+ struct au_branch *br;
25868+
25869+ err = au_wbr_create_tdp(dentry, isdir);
25870+ if (unlikely(err < 0))
25871+ goto out;
25872+ parent = dget_parent(dentry);
25873+ bstart = au_dbstart(parent);
25874+ bend = au_dbtaildir(parent);
25875+ if (bstart == bend)
25876+ goto out_parent; /* success */
25877+
25878+ e2 = au_wbr_create_mfs(dentry, isdir);
25879+ if (e2 < 0)
25880+ goto out_parent; /* success */
25881+
25882+ /* when the available size is equal, select upper one */
25883+ sb = dentry->d_sb;
25884+ br = au_sbr(sb, err);
25885+ b = br->br_wbr->wbr_bytes;
25886+ AuDbg("b%d, %llu\n", err, b);
25887+
25888+ for (bindex = bstart; bindex <= bend; bindex++) {
25889+ h_parent = au_h_dptr(parent, bindex);
25890+ if (!h_parent || !h_parent->d_inode)
25891+ continue;
25892+
25893+ br = au_sbr(sb, bindex);
25894+ if (!au_br_rdonly(br) && br->br_wbr->wbr_bytes > b) {
25895+ b = br->br_wbr->wbr_bytes;
25896+ err = bindex;
25897+ AuDbg("b%d, %llu\n", err, b);
25898+ }
25899+ }
25900+
4a4d8108
AM
25901+ if (err >= 0)
25902+ err = au_wbr_nonopq(dentry, err);
25903+
4f0767ce 25904+out_parent:
1facf9fc 25905+ dput(parent);
4f0767ce 25906+out:
1facf9fc 25907+ AuDbg("b%d\n", err);
25908+ return err;
25909+}
25910+
25911+/* ---------------------------------------------------------------------- */
25912+
25913+/* policies for copyup */
25914+
25915+/* top down parent */
25916+static int au_wbr_copyup_tdp(struct dentry *dentry)
25917+{
25918+ return au_wbr_create_tdp(dentry, /*isdir, anything is ok*/0);
25919+}
25920+
25921+/* bottom up parent */
25922+static int au_wbr_copyup_bup(struct dentry *dentry)
25923+{
25924+ int err;
25925+ aufs_bindex_t bindex, bstart;
25926+ struct dentry *parent, *h_parent;
25927+ struct super_block *sb;
25928+
25929+ err = -EROFS;
25930+ sb = dentry->d_sb;
25931+ parent = dget_parent(dentry);
25932+ bstart = au_dbstart(parent);
25933+ for (bindex = au_dbstart(dentry); bindex >= bstart; bindex--) {
25934+ h_parent = au_h_dptr(parent, bindex);
25935+ if (!h_parent || !h_parent->d_inode)
25936+ continue;
25937+
25938+ if (!au_br_rdonly(au_sbr(sb, bindex))) {
25939+ err = bindex;
25940+ break;
25941+ }
25942+ }
25943+ dput(parent);
25944+
25945+ /* bottom up here */
25946+ if (unlikely(err < 0))
25947+ err = au_wbr_bu(sb, bstart - 1);
25948+
25949+ AuDbg("b%d\n", err);
25950+ return err;
25951+}
25952+
25953+/* bottom up */
25954+static int au_wbr_copyup_bu(struct dentry *dentry)
25955+{
25956+ int err;
4a4d8108 25957+ aufs_bindex_t bstart;
1facf9fc 25958+
4a4d8108
AM
25959+ bstart = au_dbstart(dentry);
25960+ err = au_wbr_bu(dentry->d_sb, bstart);
25961+ AuDbg("b%d\n", err);
25962+ if (err > bstart)
25963+ err = au_wbr_nonopq(dentry, err);
1facf9fc 25964+
25965+ AuDbg("b%d\n", err);
25966+ return err;
25967+}
25968+
25969+/* ---------------------------------------------------------------------- */
25970+
25971+struct au_wbr_copyup_operations au_wbr_copyup_ops[] = {
25972+ [AuWbrCopyup_TDP] = {
25973+ .copyup = au_wbr_copyup_tdp
25974+ },
25975+ [AuWbrCopyup_BUP] = {
25976+ .copyup = au_wbr_copyup_bup
25977+ },
25978+ [AuWbrCopyup_BU] = {
25979+ .copyup = au_wbr_copyup_bu
25980+ }
25981+};
25982+
25983+struct au_wbr_create_operations au_wbr_create_ops[] = {
25984+ [AuWbrCreate_TDP] = {
25985+ .create = au_wbr_create_tdp
25986+ },
25987+ [AuWbrCreate_RR] = {
25988+ .create = au_wbr_create_rr,
25989+ .init = au_wbr_create_init_rr
25990+ },
25991+ [AuWbrCreate_MFS] = {
25992+ .create = au_wbr_create_mfs,
25993+ .init = au_wbr_create_init_mfs,
25994+ .fin = au_wbr_create_fin_mfs
25995+ },
25996+ [AuWbrCreate_MFSV] = {
25997+ .create = au_wbr_create_mfs,
25998+ .init = au_wbr_create_init_mfs,
25999+ .fin = au_wbr_create_fin_mfs
26000+ },
26001+ [AuWbrCreate_MFSRR] = {
26002+ .create = au_wbr_create_mfsrr,
26003+ .init = au_wbr_create_init_mfsrr,
26004+ .fin = au_wbr_create_fin_mfs
26005+ },
26006+ [AuWbrCreate_MFSRRV] = {
26007+ .create = au_wbr_create_mfsrr,
26008+ .init = au_wbr_create_init_mfsrr,
26009+ .fin = au_wbr_create_fin_mfs
26010+ },
26011+ [AuWbrCreate_PMFS] = {
26012+ .create = au_wbr_create_pmfs,
26013+ .init = au_wbr_create_init_mfs,
26014+ .fin = au_wbr_create_fin_mfs
26015+ },
26016+ [AuWbrCreate_PMFSV] = {
26017+ .create = au_wbr_create_pmfs,
26018+ .init = au_wbr_create_init_mfs,
26019+ .fin = au_wbr_create_fin_mfs
26020+ }
26021+};
7f207e10
AM
26022diff -urN /usr/share/empty/fs/aufs/whout.c linux/fs/aufs/whout.c
26023--- /usr/share/empty/fs/aufs/whout.c 1970-01-01 01:00:00.000000000 +0100
87a755f4 26024+++ linux/fs/aufs/whout.c 2011-03-17 10:46:59.000000000 +0100
027c5e7a 26025@@ -0,0 +1,1062 @@
1facf9fc 26026+/*
027c5e7a 26027+ * Copyright (C) 2005-2011 Junjiro R. Okajima
1facf9fc 26028+ *
26029+ * This program, aufs is free software; you can redistribute it and/or modify
26030+ * it under the terms of the GNU General Public License as published by
26031+ * the Free Software Foundation; either version 2 of the License, or
26032+ * (at your option) any later version.
dece6358
AM
26033+ *
26034+ * This program is distributed in the hope that it will be useful,
26035+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
26036+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
26037+ * GNU General Public License for more details.
26038+ *
26039+ * You should have received a copy of the GNU General Public License
26040+ * along with this program; if not, write to the Free Software
26041+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 26042+ */
26043+
26044+/*
26045+ * whiteout for logical deletion and opaque directory
26046+ */
26047+
26048+#include <linux/fs.h>
26049+#include "aufs.h"
26050+
26051+#define WH_MASK S_IRUGO
26052+
26053+/*
26054+ * If a directory contains this file, then it is opaque. We start with the
26055+ * .wh. flag so that it is blocked by lookup.
26056+ */
26057+static struct qstr diropq_name = {
26058+ .name = AUFS_WH_DIROPQ,
26059+ .len = sizeof(AUFS_WH_DIROPQ) - 1
26060+};
26061+
26062+/*
26063+ * generate whiteout name, which is NOT terminated by NULL.
26064+ * @name: original d_name.name
26065+ * @len: original d_name.len
26066+ * @wh: whiteout qstr
26067+ * returns zero when succeeds, otherwise error.
26068+ * succeeded value as wh->name should be freed by kfree().
26069+ */
26070+int au_wh_name_alloc(struct qstr *wh, const struct qstr *name)
26071+{
26072+ char *p;
26073+
26074+ if (unlikely(name->len > PATH_MAX - AUFS_WH_PFX_LEN))
26075+ return -ENAMETOOLONG;
26076+
26077+ wh->len = name->len + AUFS_WH_PFX_LEN;
26078+ p = kmalloc(wh->len, GFP_NOFS);
26079+ wh->name = p;
26080+ if (p) {
26081+ memcpy(p, AUFS_WH_PFX, AUFS_WH_PFX_LEN);
26082+ memcpy(p + AUFS_WH_PFX_LEN, name->name, name->len);
26083+ /* smp_mb(); */
26084+ return 0;
26085+ }
26086+ return -ENOMEM;
26087+}
26088+
26089+/* ---------------------------------------------------------------------- */
26090+
26091+/*
26092+ * test if the @wh_name exists under @h_parent.
26093+ * @try_sio specifies the necessary of super-io.
26094+ */
26095+int au_wh_test(struct dentry *h_parent, struct qstr *wh_name,
26096+ struct au_branch *br, int try_sio)
26097+{
26098+ int err;
26099+ struct dentry *wh_dentry;
1facf9fc 26100+
1facf9fc 26101+ if (!try_sio)
26102+ wh_dentry = au_lkup_one(wh_name, h_parent, br, /*nd*/NULL);
26103+ else
26104+ wh_dentry = au_sio_lkup_one(wh_name, h_parent, br);
26105+ err = PTR_ERR(wh_dentry);
26106+ if (IS_ERR(wh_dentry))
26107+ goto out;
26108+
26109+ err = 0;
26110+ if (!wh_dentry->d_inode)
26111+ goto out_wh; /* success */
26112+
26113+ err = 1;
26114+ if (S_ISREG(wh_dentry->d_inode->i_mode))
26115+ goto out_wh; /* success */
26116+
26117+ err = -EIO;
26118+ AuIOErr("%.*s Invalid whiteout entry type 0%o.\n",
26119+ AuDLNPair(wh_dentry), wh_dentry->d_inode->i_mode);
26120+
4f0767ce 26121+out_wh:
1facf9fc 26122+ dput(wh_dentry);
4f0767ce 26123+out:
1facf9fc 26124+ return err;
26125+}
26126+
26127+/*
26128+ * test if the @h_dentry sets opaque or not.
26129+ */
26130+int au_diropq_test(struct dentry *h_dentry, struct au_branch *br)
26131+{
26132+ int err;
26133+ struct inode *h_dir;
26134+
26135+ h_dir = h_dentry->d_inode;
26136+ err = au_wh_test(h_dentry, &diropq_name, br,
26137+ au_test_h_perm_sio(h_dir, MAY_EXEC));
26138+ return err;
26139+}
26140+
26141+/*
26142+ * returns a negative dentry whose name is unique and temporary.
26143+ */
26144+struct dentry *au_whtmp_lkup(struct dentry *h_parent, struct au_branch *br,
26145+ struct qstr *prefix)
26146+{
1facf9fc 26147+ struct dentry *dentry;
26148+ int i;
027c5e7a 26149+ char defname[NAME_MAX - AUFS_MAX_NAMELEN + DNAME_INLINE_LEN + 1],
4a4d8108 26150+ *name, *p;
027c5e7a 26151+ /* strict atomic_t is unnecessary here */
1facf9fc 26152+ static unsigned short cnt;
26153+ struct qstr qs;
26154+
4a4d8108
AM
26155+ BUILD_BUG_ON(sizeof(cnt) * 2 > AUFS_WH_TMP_LEN);
26156+
1facf9fc 26157+ name = defname;
027c5e7a
AM
26158+ qs.len = sizeof(defname) - DNAME_INLINE_LEN + prefix->len - 1;
26159+ if (unlikely(prefix->len > DNAME_INLINE_LEN)) {
1facf9fc 26160+ dentry = ERR_PTR(-ENAMETOOLONG);
4a4d8108 26161+ if (unlikely(qs.len > NAME_MAX))
1facf9fc 26162+ goto out;
26163+ dentry = ERR_PTR(-ENOMEM);
26164+ name = kmalloc(qs.len + 1, GFP_NOFS);
26165+ if (unlikely(!name))
26166+ goto out;
26167+ }
26168+
26169+ /* doubly whiteout-ed */
26170+ memcpy(name, AUFS_WH_PFX AUFS_WH_PFX, AUFS_WH_PFX_LEN * 2);
26171+ p = name + AUFS_WH_PFX_LEN * 2;
26172+ memcpy(p, prefix->name, prefix->len);
26173+ p += prefix->len;
26174+ *p++ = '.';
4a4d8108 26175+ AuDebugOn(name + qs.len + 1 - p <= AUFS_WH_TMP_LEN);
1facf9fc 26176+
26177+ qs.name = name;
26178+ for (i = 0; i < 3; i++) {
b752ccd1 26179+ sprintf(p, "%.*x", AUFS_WH_TMP_LEN, cnt++);
1facf9fc 26180+ dentry = au_sio_lkup_one(&qs, h_parent, br);
26181+ if (IS_ERR(dentry) || !dentry->d_inode)
26182+ goto out_name;
26183+ dput(dentry);
26184+ }
4a4d8108 26185+ /* pr_warning("could not get random name\n"); */
1facf9fc 26186+ dentry = ERR_PTR(-EEXIST);
26187+ AuDbg("%.*s\n", AuLNPair(&qs));
26188+ BUG();
26189+
4f0767ce 26190+out_name:
1facf9fc 26191+ if (name != defname)
26192+ kfree(name);
4f0767ce 26193+out:
4a4d8108 26194+ AuTraceErrPtr(dentry);
1facf9fc 26195+ return dentry;
1facf9fc 26196+}
26197+
26198+/*
26199+ * rename the @h_dentry on @br to the whiteouted temporary name.
26200+ */
26201+int au_whtmp_ren(struct dentry *h_dentry, struct au_branch *br)
26202+{
26203+ int err;
26204+ struct path h_path = {
26205+ .mnt = br->br_mnt
26206+ };
26207+ struct inode *h_dir;
26208+ struct dentry *h_parent;
26209+
26210+ h_parent = h_dentry->d_parent; /* dir inode is locked */
26211+ h_dir = h_parent->d_inode;
26212+ IMustLock(h_dir);
26213+
26214+ h_path.dentry = au_whtmp_lkup(h_parent, br, &h_dentry->d_name);
26215+ err = PTR_ERR(h_path.dentry);
26216+ if (IS_ERR(h_path.dentry))
26217+ goto out;
26218+
26219+ /* under the same dir, no need to lock_rename() */
26220+ err = vfsub_rename(h_dir, h_dentry, h_dir, &h_path);
26221+ AuTraceErr(err);
26222+ dput(h_path.dentry);
26223+
4f0767ce 26224+out:
4a4d8108 26225+ AuTraceErr(err);
1facf9fc 26226+ return err;
26227+}
26228+
26229+/* ---------------------------------------------------------------------- */
26230+/*
26231+ * functions for removing a whiteout
26232+ */
26233+
26234+static int do_unlink_wh(struct inode *h_dir, struct path *h_path)
26235+{
26236+ int force;
26237+
26238+ /*
26239+ * forces superio when the dir has a sticky bit.
26240+ * this may be a violation of unix fs semantics.
26241+ */
26242+ force = (h_dir->i_mode & S_ISVTX)
26243+ && h_path->dentry->d_inode->i_uid != current_fsuid();
26244+ return vfsub_unlink(h_dir, h_path, force);
26245+}
26246+
26247+int au_wh_unlink_dentry(struct inode *h_dir, struct path *h_path,
26248+ struct dentry *dentry)
26249+{
26250+ int err;
26251+
26252+ err = do_unlink_wh(h_dir, h_path);
26253+ if (!err && dentry)
26254+ au_set_dbwh(dentry, -1);
26255+
26256+ return err;
26257+}
26258+
26259+static int unlink_wh_name(struct dentry *h_parent, struct qstr *wh,
26260+ struct au_branch *br)
26261+{
26262+ int err;
26263+ struct path h_path = {
26264+ .mnt = br->br_mnt
26265+ };
26266+
26267+ err = 0;
26268+ h_path.dentry = au_lkup_one(wh, h_parent, br, /*nd*/NULL);
26269+ if (IS_ERR(h_path.dentry))
26270+ err = PTR_ERR(h_path.dentry);
26271+ else {
26272+ if (h_path.dentry->d_inode
26273+ && S_ISREG(h_path.dentry->d_inode->i_mode))
26274+ err = do_unlink_wh(h_parent->d_inode, &h_path);
26275+ dput(h_path.dentry);
26276+ }
26277+
26278+ return err;
26279+}
26280+
26281+/* ---------------------------------------------------------------------- */
26282+/*
26283+ * initialize/clean whiteout for a branch
26284+ */
26285+
26286+static void au_wh_clean(struct inode *h_dir, struct path *whpath,
26287+ const int isdir)
26288+{
26289+ int err;
26290+
26291+ if (!whpath->dentry->d_inode)
26292+ return;
26293+
26294+ err = mnt_want_write(whpath->mnt);
26295+ if (!err) {
26296+ if (isdir)
26297+ err = vfsub_rmdir(h_dir, whpath);
26298+ else
26299+ err = vfsub_unlink(h_dir, whpath, /*force*/0);
26300+ mnt_drop_write(whpath->mnt);
26301+ }
26302+ if (unlikely(err))
4a4d8108
AM
26303+ pr_warning("failed removing %.*s (%d), ignored.\n",
26304+ AuDLNPair(whpath->dentry), err);
1facf9fc 26305+}
26306+
26307+static int test_linkable(struct dentry *h_root)
26308+{
26309+ struct inode *h_dir = h_root->d_inode;
26310+
26311+ if (h_dir->i_op->link)
26312+ return 0;
26313+
4a4d8108
AM
26314+ pr_err("%.*s (%s) doesn't support link(2), use noplink and rw+nolwh\n",
26315+ AuDLNPair(h_root), au_sbtype(h_root->d_sb));
1facf9fc 26316+ return -ENOSYS;
26317+}
26318+
26319+/* todo: should this mkdir be done in /sbin/mount.aufs helper? */
26320+static int au_whdir(struct inode *h_dir, struct path *path)
26321+{
26322+ int err;
26323+
26324+ err = -EEXIST;
26325+ if (!path->dentry->d_inode) {
26326+ int mode = S_IRWXU;
26327+
26328+ if (au_test_nfs(path->dentry->d_sb))
26329+ mode |= S_IXUGO;
26330+ err = mnt_want_write(path->mnt);
26331+ if (!err) {
26332+ err = vfsub_mkdir(h_dir, path, mode);
26333+ mnt_drop_write(path->mnt);
26334+ }
26335+ } else if (S_ISDIR(path->dentry->d_inode->i_mode))
26336+ err = 0;
26337+ else
4a4d8108 26338+ pr_err("unknown %.*s exists\n", AuDLNPair(path->dentry));
1facf9fc 26339+
26340+ return err;
26341+}
26342+
26343+struct au_wh_base {
26344+ const struct qstr *name;
26345+ struct dentry *dentry;
26346+};
26347+
26348+static void au_wh_init_ro(struct inode *h_dir, struct au_wh_base base[],
26349+ struct path *h_path)
26350+{
26351+ h_path->dentry = base[AuBrWh_BASE].dentry;
26352+ au_wh_clean(h_dir, h_path, /*isdir*/0);
26353+ h_path->dentry = base[AuBrWh_PLINK].dentry;
26354+ au_wh_clean(h_dir, h_path, /*isdir*/1);
26355+ h_path->dentry = base[AuBrWh_ORPH].dentry;
26356+ au_wh_clean(h_dir, h_path, /*isdir*/1);
26357+}
26358+
26359+/*
26360+ * returns tri-state,
26361+ * minus: error, caller should print the mesage
26362+ * zero: succuess
26363+ * plus: error, caller should NOT print the mesage
26364+ */
26365+static int au_wh_init_rw_nolink(struct dentry *h_root, struct au_wbr *wbr,
26366+ int do_plink, struct au_wh_base base[],
26367+ struct path *h_path)
26368+{
26369+ int err;
26370+ struct inode *h_dir;
26371+
26372+ h_dir = h_root->d_inode;
26373+ h_path->dentry = base[AuBrWh_BASE].dentry;
26374+ au_wh_clean(h_dir, h_path, /*isdir*/0);
26375+ h_path->dentry = base[AuBrWh_PLINK].dentry;
26376+ if (do_plink) {
26377+ err = test_linkable(h_root);
26378+ if (unlikely(err)) {
26379+ err = 1;
26380+ goto out;
26381+ }
26382+
26383+ err = au_whdir(h_dir, h_path);
26384+ if (unlikely(err))
26385+ goto out;
26386+ wbr->wbr_plink = dget(base[AuBrWh_PLINK].dentry);
26387+ } else
26388+ au_wh_clean(h_dir, h_path, /*isdir*/1);
26389+ h_path->dentry = base[AuBrWh_ORPH].dentry;
26390+ err = au_whdir(h_dir, h_path);
26391+ if (unlikely(err))
26392+ goto out;
26393+ wbr->wbr_orph = dget(base[AuBrWh_ORPH].dentry);
26394+
4f0767ce 26395+out:
1facf9fc 26396+ return err;
26397+}
26398+
26399+/*
26400+ * for the moment, aufs supports the branch filesystem which does not support
26401+ * link(2). testing on FAT which does not support i_op->setattr() fully either,
26402+ * copyup failed. finally, such filesystem will not be used as the writable
26403+ * branch.
26404+ *
26405+ * returns tri-state, see above.
26406+ */
26407+static int au_wh_init_rw(struct dentry *h_root, struct au_wbr *wbr,
26408+ int do_plink, struct au_wh_base base[],
26409+ struct path *h_path)
26410+{
26411+ int err;
26412+ struct inode *h_dir;
26413+
1308ab2a 26414+ WbrWhMustWriteLock(wbr);
26415+
1facf9fc 26416+ err = test_linkable(h_root);
26417+ if (unlikely(err)) {
26418+ err = 1;
26419+ goto out;
26420+ }
26421+
26422+ /*
26423+ * todo: should this create be done in /sbin/mount.aufs helper?
26424+ */
26425+ err = -EEXIST;
26426+ h_dir = h_root->d_inode;
26427+ if (!base[AuBrWh_BASE].dentry->d_inode) {
26428+ err = mnt_want_write(h_path->mnt);
26429+ if (!err) {
26430+ h_path->dentry = base[AuBrWh_BASE].dentry;
26431+ err = vfsub_create(h_dir, h_path, WH_MASK);
26432+ mnt_drop_write(h_path->mnt);
26433+ }
26434+ } else if (S_ISREG(base[AuBrWh_BASE].dentry->d_inode->i_mode))
26435+ err = 0;
26436+ else
4a4d8108
AM
26437+ pr_err("unknown %.*s/%.*s exists\n",
26438+ AuDLNPair(h_root), AuDLNPair(base[AuBrWh_BASE].dentry));
1facf9fc 26439+ if (unlikely(err))
26440+ goto out;
26441+
26442+ h_path->dentry = base[AuBrWh_PLINK].dentry;
26443+ if (do_plink) {
26444+ err = au_whdir(h_dir, h_path);
26445+ if (unlikely(err))
26446+ goto out;
26447+ wbr->wbr_plink = dget(base[AuBrWh_PLINK].dentry);
26448+ } else
26449+ au_wh_clean(h_dir, h_path, /*isdir*/1);
26450+ wbr->wbr_whbase = dget(base[AuBrWh_BASE].dentry);
26451+
26452+ h_path->dentry = base[AuBrWh_ORPH].dentry;
26453+ err = au_whdir(h_dir, h_path);
26454+ if (unlikely(err))
26455+ goto out;
26456+ wbr->wbr_orph = dget(base[AuBrWh_ORPH].dentry);
26457+
4f0767ce 26458+out:
1facf9fc 26459+ return err;
26460+}
26461+
26462+/*
26463+ * initialize the whiteout base file/dir for @br.
26464+ */
26465+int au_wh_init(struct dentry *h_root, struct au_branch *br,
26466+ struct super_block *sb)
26467+{
26468+ int err, i;
26469+ const unsigned char do_plink
26470+ = !!au_opt_test(au_mntflags(sb), PLINK);
26471+ struct path path = {
26472+ .mnt = br->br_mnt
26473+ };
26474+ struct inode *h_dir;
26475+ struct au_wbr *wbr = br->br_wbr;
26476+ static const struct qstr base_name[] = {
26477+ [AuBrWh_BASE] = {
26478+ .name = AUFS_BASE_NAME,
26479+ .len = sizeof(AUFS_BASE_NAME) - 1
26480+ },
26481+ [AuBrWh_PLINK] = {
26482+ .name = AUFS_PLINKDIR_NAME,
26483+ .len = sizeof(AUFS_PLINKDIR_NAME) - 1
26484+ },
26485+ [AuBrWh_ORPH] = {
26486+ .name = AUFS_ORPHDIR_NAME,
26487+ .len = sizeof(AUFS_ORPHDIR_NAME) - 1
26488+ }
26489+ };
26490+ struct au_wh_base base[] = {
26491+ [AuBrWh_BASE] = {
26492+ .name = base_name + AuBrWh_BASE,
26493+ .dentry = NULL
26494+ },
26495+ [AuBrWh_PLINK] = {
26496+ .name = base_name + AuBrWh_PLINK,
26497+ .dentry = NULL
26498+ },
26499+ [AuBrWh_ORPH] = {
26500+ .name = base_name + AuBrWh_ORPH,
26501+ .dentry = NULL
26502+ }
26503+ };
26504+
1308ab2a 26505+ if (wbr)
26506+ WbrWhMustWriteLock(wbr);
1facf9fc 26507+
1facf9fc 26508+ for (i = 0; i < AuBrWh_Last; i++) {
26509+ /* doubly whiteouted */
26510+ struct dentry *d;
26511+
26512+ d = au_wh_lkup(h_root, (void *)base[i].name, br);
26513+ err = PTR_ERR(d);
26514+ if (IS_ERR(d))
26515+ goto out;
26516+
26517+ base[i].dentry = d;
26518+ AuDebugOn(wbr
26519+ && wbr->wbr_wh[i]
26520+ && wbr->wbr_wh[i] != base[i].dentry);
26521+ }
26522+
26523+ if (wbr)
26524+ for (i = 0; i < AuBrWh_Last; i++) {
26525+ dput(wbr->wbr_wh[i]);
26526+ wbr->wbr_wh[i] = NULL;
26527+ }
26528+
26529+ err = 0;
1facf9fc 26530+ switch (br->br_perm) {
26531+ case AuBrPerm_RO:
26532+ case AuBrPerm_ROWH:
26533+ case AuBrPerm_RR:
26534+ case AuBrPerm_RRWH:
4a4d8108 26535+ h_dir = h_root->d_inode;
1facf9fc 26536+ au_wh_init_ro(h_dir, base, &path);
26537+ break;
26538+
26539+ case AuBrPerm_RWNoLinkWH:
26540+ err = au_wh_init_rw_nolink(h_root, wbr, do_plink, base, &path);
26541+ if (err > 0)
26542+ goto out;
26543+ else if (err)
26544+ goto out_err;
26545+ break;
26546+
26547+ case AuBrPerm_RW:
26548+ err = au_wh_init_rw(h_root, wbr, do_plink, base, &path);
26549+ if (err > 0)
26550+ goto out;
26551+ else if (err)
26552+ goto out_err;
26553+ break;
26554+
26555+ default:
26556+ BUG();
26557+ }
26558+ goto out; /* success */
26559+
4f0767ce 26560+out_err:
4a4d8108
AM
26561+ pr_err("an error(%d) on the writable branch %.*s(%s)\n",
26562+ err, AuDLNPair(h_root), au_sbtype(h_root->d_sb));
4f0767ce 26563+out:
1facf9fc 26564+ for (i = 0; i < AuBrWh_Last; i++)
26565+ dput(base[i].dentry);
26566+ return err;
26567+}
26568+
26569+/* ---------------------------------------------------------------------- */
26570+/*
26571+ * whiteouts are all hard-linked usually.
26572+ * when its link count reaches a ceiling, we create a new whiteout base
26573+ * asynchronously.
26574+ */
26575+
26576+struct reinit_br_wh {
26577+ struct super_block *sb;
26578+ struct au_branch *br;
26579+};
26580+
26581+static void reinit_br_wh(void *arg)
26582+{
26583+ int err;
26584+ aufs_bindex_t bindex;
26585+ struct path h_path;
26586+ struct reinit_br_wh *a = arg;
26587+ struct au_wbr *wbr;
26588+ struct inode *dir;
26589+ struct dentry *h_root;
26590+ struct au_hinode *hdir;
26591+
26592+ err = 0;
26593+ wbr = a->br->br_wbr;
26594+ /* big aufs lock */
26595+ si_noflush_write_lock(a->sb);
26596+ if (!au_br_writable(a->br->br_perm))
26597+ goto out;
26598+ bindex = au_br_index(a->sb, a->br->br_id);
26599+ if (unlikely(bindex < 0))
26600+ goto out;
26601+
1308ab2a 26602+ di_read_lock_parent(a->sb->s_root, AuLock_IR);
1facf9fc 26603+ dir = a->sb->s_root->d_inode;
1facf9fc 26604+ hdir = au_hi(dir, bindex);
26605+ h_root = au_h_dptr(a->sb->s_root, bindex);
26606+
4a4d8108 26607+ au_hn_imtx_lock_nested(hdir, AuLsc_I_PARENT);
1facf9fc 26608+ wbr_wh_write_lock(wbr);
26609+ err = au_h_verify(wbr->wbr_whbase, au_opt_udba(a->sb), hdir->hi_inode,
26610+ h_root, a->br);
26611+ if (!err) {
26612+ err = mnt_want_write(a->br->br_mnt);
26613+ if (!err) {
26614+ h_path.dentry = wbr->wbr_whbase;
26615+ h_path.mnt = a->br->br_mnt;
26616+ err = vfsub_unlink(hdir->hi_inode, &h_path, /*force*/0);
26617+ mnt_drop_write(a->br->br_mnt);
26618+ }
26619+ } else {
4a4d8108
AM
26620+ pr_warning("%.*s is moved, ignored\n",
26621+ AuDLNPair(wbr->wbr_whbase));
1facf9fc 26622+ err = 0;
26623+ }
26624+ dput(wbr->wbr_whbase);
26625+ wbr->wbr_whbase = NULL;
26626+ if (!err)
26627+ err = au_wh_init(h_root, a->br, a->sb);
26628+ wbr_wh_write_unlock(wbr);
4a4d8108 26629+ au_hn_imtx_unlock(hdir);
1308ab2a 26630+ di_read_unlock(a->sb->s_root, AuLock_IR);
1facf9fc 26631+
4f0767ce 26632+out:
1facf9fc 26633+ if (wbr)
26634+ atomic_dec(&wbr->wbr_wh_running);
26635+ atomic_dec(&a->br->br_count);
1facf9fc 26636+ si_write_unlock(a->sb);
027c5e7a 26637+ au_nwt_done(&au_sbi(a->sb)->si_nowait);
1facf9fc 26638+ kfree(arg);
26639+ if (unlikely(err))
26640+ AuIOErr("err %d\n", err);
26641+}
26642+
26643+static void kick_reinit_br_wh(struct super_block *sb, struct au_branch *br)
26644+{
26645+ int do_dec, wkq_err;
26646+ struct reinit_br_wh *arg;
26647+
26648+ do_dec = 1;
26649+ if (atomic_inc_return(&br->br_wbr->wbr_wh_running) != 1)
26650+ goto out;
26651+
26652+ /* ignore ENOMEM */
26653+ arg = kmalloc(sizeof(*arg), GFP_NOFS);
26654+ if (arg) {
26655+ /*
26656+ * dec(wh_running), kfree(arg) and dec(br_count)
26657+ * in reinit function
26658+ */
26659+ arg->sb = sb;
26660+ arg->br = br;
26661+ atomic_inc(&br->br_count);
26662+ wkq_err = au_wkq_nowait(reinit_br_wh, arg, sb);
26663+ if (unlikely(wkq_err)) {
26664+ atomic_dec(&br->br_wbr->wbr_wh_running);
26665+ atomic_dec(&br->br_count);
26666+ kfree(arg);
26667+ }
26668+ do_dec = 0;
26669+ }
26670+
4f0767ce 26671+out:
1facf9fc 26672+ if (do_dec)
26673+ atomic_dec(&br->br_wbr->wbr_wh_running);
26674+}
26675+
26676+/* ---------------------------------------------------------------------- */
26677+
26678+/*
26679+ * create the whiteout @wh.
26680+ */
26681+static int link_or_create_wh(struct super_block *sb, aufs_bindex_t bindex,
26682+ struct dentry *wh)
26683+{
26684+ int err;
26685+ struct path h_path = {
26686+ .dentry = wh
26687+ };
26688+ struct au_branch *br;
26689+ struct au_wbr *wbr;
26690+ struct dentry *h_parent;
26691+ struct inode *h_dir;
26692+
26693+ h_parent = wh->d_parent; /* dir inode is locked */
26694+ h_dir = h_parent->d_inode;
26695+ IMustLock(h_dir);
26696+
26697+ br = au_sbr(sb, bindex);
26698+ h_path.mnt = br->br_mnt;
26699+ wbr = br->br_wbr;
26700+ wbr_wh_read_lock(wbr);
26701+ if (wbr->wbr_whbase) {
26702+ err = vfsub_link(wbr->wbr_whbase, h_dir, &h_path);
26703+ if (!err || err != -EMLINK)
26704+ goto out;
26705+
26706+ /* link count full. re-initialize br_whbase. */
26707+ kick_reinit_br_wh(sb, br);
26708+ }
26709+
26710+ /* return this error in this context */
26711+ err = vfsub_create(h_dir, &h_path, WH_MASK);
26712+
4f0767ce 26713+out:
1facf9fc 26714+ wbr_wh_read_unlock(wbr);
26715+ return err;
26716+}
26717+
26718+/* ---------------------------------------------------------------------- */
26719+
26720+/*
26721+ * create or remove the diropq.
26722+ */
26723+static struct dentry *do_diropq(struct dentry *dentry, aufs_bindex_t bindex,
26724+ unsigned int flags)
26725+{
26726+ struct dentry *opq_dentry, *h_dentry;
26727+ struct super_block *sb;
26728+ struct au_branch *br;
26729+ int err;
26730+
26731+ sb = dentry->d_sb;
26732+ br = au_sbr(sb, bindex);
26733+ h_dentry = au_h_dptr(dentry, bindex);
26734+ opq_dentry = au_lkup_one(&diropq_name, h_dentry, br, /*nd*/NULL);
26735+ if (IS_ERR(opq_dentry))
26736+ goto out;
26737+
26738+ if (au_ftest_diropq(flags, CREATE)) {
26739+ err = link_or_create_wh(sb, bindex, opq_dentry);
26740+ if (!err) {
26741+ au_set_dbdiropq(dentry, bindex);
26742+ goto out; /* success */
26743+ }
26744+ } else {
26745+ struct path tmp = {
26746+ .dentry = opq_dentry,
26747+ .mnt = br->br_mnt
26748+ };
26749+ err = do_unlink_wh(au_h_iptr(dentry->d_inode, bindex), &tmp);
26750+ if (!err)
26751+ au_set_dbdiropq(dentry, -1);
26752+ }
26753+ dput(opq_dentry);
26754+ opq_dentry = ERR_PTR(err);
26755+
4f0767ce 26756+out:
1facf9fc 26757+ return opq_dentry;
26758+}
26759+
26760+struct do_diropq_args {
26761+ struct dentry **errp;
26762+ struct dentry *dentry;
26763+ aufs_bindex_t bindex;
26764+ unsigned int flags;
26765+};
26766+
26767+static void call_do_diropq(void *args)
26768+{
26769+ struct do_diropq_args *a = args;
26770+ *a->errp = do_diropq(a->dentry, a->bindex, a->flags);
26771+}
26772+
26773+struct dentry *au_diropq_sio(struct dentry *dentry, aufs_bindex_t bindex,
26774+ unsigned int flags)
26775+{
26776+ struct dentry *diropq, *h_dentry;
26777+
26778+ h_dentry = au_h_dptr(dentry, bindex);
26779+ if (!au_test_h_perm_sio(h_dentry->d_inode, MAY_EXEC | MAY_WRITE))
26780+ diropq = do_diropq(dentry, bindex, flags);
26781+ else {
26782+ int wkq_err;
26783+ struct do_diropq_args args = {
26784+ .errp = &diropq,
26785+ .dentry = dentry,
26786+ .bindex = bindex,
26787+ .flags = flags
26788+ };
26789+
26790+ wkq_err = au_wkq_wait(call_do_diropq, &args);
26791+ if (unlikely(wkq_err))
26792+ diropq = ERR_PTR(wkq_err);
26793+ }
26794+
26795+ return diropq;
26796+}
26797+
26798+/* ---------------------------------------------------------------------- */
26799+
26800+/*
26801+ * lookup whiteout dentry.
26802+ * @h_parent: lower parent dentry which must exist and be locked
26803+ * @base_name: name of dentry which will be whiteouted
26804+ * returns dentry for whiteout.
26805+ */
26806+struct dentry *au_wh_lkup(struct dentry *h_parent, struct qstr *base_name,
26807+ struct au_branch *br)
26808+{
26809+ int err;
26810+ struct qstr wh_name;
26811+ struct dentry *wh_dentry;
26812+
26813+ err = au_wh_name_alloc(&wh_name, base_name);
26814+ wh_dentry = ERR_PTR(err);
26815+ if (!err) {
26816+ wh_dentry = au_lkup_one(&wh_name, h_parent, br, /*nd*/NULL);
26817+ kfree(wh_name.name);
26818+ }
26819+ return wh_dentry;
26820+}
26821+
26822+/*
26823+ * link/create a whiteout for @dentry on @bindex.
26824+ */
26825+struct dentry *au_wh_create(struct dentry *dentry, aufs_bindex_t bindex,
26826+ struct dentry *h_parent)
26827+{
26828+ struct dentry *wh_dentry;
26829+ struct super_block *sb;
26830+ int err;
26831+
26832+ sb = dentry->d_sb;
26833+ wh_dentry = au_wh_lkup(h_parent, &dentry->d_name, au_sbr(sb, bindex));
26834+ if (!IS_ERR(wh_dentry) && !wh_dentry->d_inode) {
26835+ err = link_or_create_wh(sb, bindex, wh_dentry);
26836+ if (!err)
26837+ au_set_dbwh(dentry, bindex);
26838+ else {
26839+ dput(wh_dentry);
26840+ wh_dentry = ERR_PTR(err);
26841+ }
26842+ }
26843+
26844+ return wh_dentry;
26845+}
26846+
26847+/* ---------------------------------------------------------------------- */
26848+
26849+/* Delete all whiteouts in this directory on branch bindex. */
26850+static int del_wh_children(struct dentry *h_dentry, struct au_nhash *whlist,
26851+ aufs_bindex_t bindex, struct au_branch *br)
26852+{
26853+ int err;
26854+ unsigned long ul, n;
26855+ struct qstr wh_name;
26856+ char *p;
26857+ struct hlist_head *head;
26858+ struct au_vdir_wh *tpos;
26859+ struct hlist_node *pos;
26860+ struct au_vdir_destr *str;
26861+
26862+ err = -ENOMEM;
4a4d8108 26863+ p = __getname_gfp(GFP_NOFS);
1facf9fc 26864+ wh_name.name = p;
26865+ if (unlikely(!wh_name.name))
26866+ goto out;
26867+
26868+ err = 0;
26869+ memcpy(p, AUFS_WH_PFX, AUFS_WH_PFX_LEN);
26870+ p += AUFS_WH_PFX_LEN;
26871+ n = whlist->nh_num;
26872+ head = whlist->nh_head;
26873+ for (ul = 0; !err && ul < n; ul++, head++) {
26874+ hlist_for_each_entry(tpos, pos, head, wh_hash) {
26875+ if (tpos->wh_bindex != bindex)
26876+ continue;
26877+
26878+ str = &tpos->wh_str;
26879+ if (str->len + AUFS_WH_PFX_LEN <= PATH_MAX) {
26880+ memcpy(p, str->name, str->len);
26881+ wh_name.len = AUFS_WH_PFX_LEN + str->len;
26882+ err = unlink_wh_name(h_dentry, &wh_name, br);
26883+ if (!err)
26884+ continue;
26885+ break;
26886+ }
26887+ AuIOErr("whiteout name too long %.*s\n",
26888+ str->len, str->name);
26889+ err = -EIO;
26890+ break;
26891+ }
26892+ }
26893+ __putname(wh_name.name);
26894+
4f0767ce 26895+out:
1facf9fc 26896+ return err;
26897+}
26898+
26899+struct del_wh_children_args {
26900+ int *errp;
26901+ struct dentry *h_dentry;
1308ab2a 26902+ struct au_nhash *whlist;
1facf9fc 26903+ aufs_bindex_t bindex;
26904+ struct au_branch *br;
26905+};
26906+
26907+static void call_del_wh_children(void *args)
26908+{
26909+ struct del_wh_children_args *a = args;
1308ab2a 26910+ *a->errp = del_wh_children(a->h_dentry, a->whlist, a->bindex, a->br);
1facf9fc 26911+}
26912+
26913+/* ---------------------------------------------------------------------- */
26914+
26915+struct au_whtmp_rmdir *au_whtmp_rmdir_alloc(struct super_block *sb, gfp_t gfp)
26916+{
26917+ struct au_whtmp_rmdir *whtmp;
dece6358 26918+ int err;
1308ab2a 26919+ unsigned int rdhash;
dece6358
AM
26920+
26921+ SiMustAnyLock(sb);
1facf9fc 26922+
26923+ whtmp = kmalloc(sizeof(*whtmp), gfp);
dece6358
AM
26924+ if (unlikely(!whtmp)) {
26925+ whtmp = ERR_PTR(-ENOMEM);
1facf9fc 26926+ goto out;
dece6358 26927+ }
1facf9fc 26928+
26929+ whtmp->dir = NULL;
027c5e7a 26930+ whtmp->br = NULL;
1facf9fc 26931+ whtmp->wh_dentry = NULL;
1308ab2a 26932+ /* no estimation for dir size */
26933+ rdhash = au_sbi(sb)->si_rdhash;
26934+ if (!rdhash)
26935+ rdhash = AUFS_RDHASH_DEF;
26936+ err = au_nhash_alloc(&whtmp->whlist, rdhash, gfp);
26937+ if (unlikely(err)) {
26938+ kfree(whtmp);
26939+ whtmp = ERR_PTR(err);
26940+ }
dece6358 26941+
4f0767ce 26942+out:
dece6358 26943+ return whtmp;
1facf9fc 26944+}
26945+
26946+void au_whtmp_rmdir_free(struct au_whtmp_rmdir *whtmp)
26947+{
027c5e7a
AM
26948+ if (whtmp->br)
26949+ atomic_dec(&whtmp->br->br_count);
1facf9fc 26950+ dput(whtmp->wh_dentry);
26951+ iput(whtmp->dir);
dece6358 26952+ au_nhash_wh_free(&whtmp->whlist);
1facf9fc 26953+ kfree(whtmp);
26954+}
26955+
26956+/*
26957+ * rmdir the whiteouted temporary named dir @h_dentry.
26958+ * @whlist: whiteouted children.
26959+ */
26960+int au_whtmp_rmdir(struct inode *dir, aufs_bindex_t bindex,
26961+ struct dentry *wh_dentry, struct au_nhash *whlist)
26962+{
26963+ int err;
26964+ struct path h_tmp;
26965+ struct inode *wh_inode, *h_dir;
26966+ struct au_branch *br;
26967+
26968+ h_dir = wh_dentry->d_parent->d_inode; /* dir inode is locked */
26969+ IMustLock(h_dir);
26970+
26971+ br = au_sbr(dir->i_sb, bindex);
26972+ wh_inode = wh_dentry->d_inode;
26973+ mutex_lock_nested(&wh_inode->i_mutex, AuLsc_I_CHILD);
26974+
26975+ /*
26976+ * someone else might change some whiteouts while we were sleeping.
26977+ * it means this whlist may have an obsoleted entry.
26978+ */
26979+ if (!au_test_h_perm_sio(wh_inode, MAY_EXEC | MAY_WRITE))
26980+ err = del_wh_children(wh_dentry, whlist, bindex, br);
26981+ else {
26982+ int wkq_err;
26983+ struct del_wh_children_args args = {
26984+ .errp = &err,
26985+ .h_dentry = wh_dentry,
1308ab2a 26986+ .whlist = whlist,
1facf9fc 26987+ .bindex = bindex,
26988+ .br = br
26989+ };
26990+
26991+ wkq_err = au_wkq_wait(call_del_wh_children, &args);
26992+ if (unlikely(wkq_err))
26993+ err = wkq_err;
26994+ }
26995+ mutex_unlock(&wh_inode->i_mutex);
26996+
26997+ if (!err) {
26998+ h_tmp.dentry = wh_dentry;
26999+ h_tmp.mnt = br->br_mnt;
27000+ err = vfsub_rmdir(h_dir, &h_tmp);
1facf9fc 27001+ }
27002+
27003+ if (!err) {
27004+ if (au_ibstart(dir) == bindex) {
7f207e10 27005+ /* todo: dir->i_mutex is necessary */
1facf9fc 27006+ au_cpup_attr_timesizes(dir);
7f207e10 27007+ vfsub_drop_nlink(dir);
1facf9fc 27008+ }
27009+ return 0; /* success */
27010+ }
27011+
4a4d8108
AM
27012+ pr_warning("failed removing %.*s(%d), ignored\n",
27013+ AuDLNPair(wh_dentry), err);
1facf9fc 27014+ return err;
27015+}
27016+
27017+static void call_rmdir_whtmp(void *args)
27018+{
27019+ int err;
e49829fe 27020+ aufs_bindex_t bindex;
1facf9fc 27021+ struct au_whtmp_rmdir *a = args;
27022+ struct super_block *sb;
27023+ struct dentry *h_parent;
27024+ struct inode *h_dir;
1facf9fc 27025+ struct au_hinode *hdir;
27026+
27027+ /* rmdir by nfsd may cause deadlock with this i_mutex */
27028+ /* mutex_lock(&a->dir->i_mutex); */
e49829fe 27029+ err = -EROFS;
1facf9fc 27030+ sb = a->dir->i_sb;
e49829fe
JR
27031+ si_read_lock(sb, !AuLock_FLUSH);
27032+ if (!au_br_writable(a->br->br_perm))
27033+ goto out;
27034+ bindex = au_br_index(sb, a->br->br_id);
27035+ if (unlikely(bindex < 0))
1facf9fc 27036+ goto out;
27037+
27038+ err = -EIO;
1facf9fc 27039+ ii_write_lock_parent(a->dir);
27040+ h_parent = dget_parent(a->wh_dentry);
27041+ h_dir = h_parent->d_inode;
e49829fe 27042+ hdir = au_hi(a->dir, bindex);
4a4d8108 27043+ au_hn_imtx_lock_nested(hdir, AuLsc_I_PARENT);
e49829fe
JR
27044+ err = au_h_verify(a->wh_dentry, au_opt_udba(sb), h_dir, h_parent,
27045+ a->br);
1facf9fc 27046+ if (!err) {
e49829fe 27047+ err = mnt_want_write(a->br->br_mnt);
1facf9fc 27048+ if (!err) {
e49829fe 27049+ err = au_whtmp_rmdir(a->dir, bindex, a->wh_dentry,
dece6358 27050+ &a->whlist);
e49829fe 27051+ mnt_drop_write(a->br->br_mnt);
1facf9fc 27052+ }
27053+ }
4a4d8108 27054+ au_hn_imtx_unlock(hdir);
1facf9fc 27055+ dput(h_parent);
27056+ ii_write_unlock(a->dir);
27057+
4f0767ce 27058+out:
1facf9fc 27059+ /* mutex_unlock(&a->dir->i_mutex); */
1facf9fc 27060+ au_whtmp_rmdir_free(a);
027c5e7a
AM
27061+ si_read_unlock(sb);
27062+ au_nwt_done(&au_sbi(sb)->si_nowait);
1facf9fc 27063+ if (unlikely(err))
27064+ AuIOErr("err %d\n", err);
27065+}
27066+
27067+void au_whtmp_kick_rmdir(struct inode *dir, aufs_bindex_t bindex,
27068+ struct dentry *wh_dentry, struct au_whtmp_rmdir *args)
27069+{
27070+ int wkq_err;
e49829fe 27071+ struct super_block *sb;
1facf9fc 27072+
27073+ IMustLock(dir);
27074+
27075+ /* all post-process will be done in do_rmdir_whtmp(). */
e49829fe 27076+ sb = dir->i_sb;
1facf9fc 27077+ args->dir = au_igrab(dir);
e49829fe
JR
27078+ args->br = au_sbr(sb, bindex);
27079+ atomic_inc(&args->br->br_count);
1facf9fc 27080+ args->wh_dentry = dget(wh_dentry);
e49829fe 27081+ wkq_err = au_wkq_nowait(call_rmdir_whtmp, args, sb);
1facf9fc 27082+ if (unlikely(wkq_err)) {
4a4d8108
AM
27083+ pr_warning("rmdir error %.*s (%d), ignored\n",
27084+ AuDLNPair(wh_dentry), wkq_err);
1facf9fc 27085+ au_whtmp_rmdir_free(args);
27086+ }
27087+}
7f207e10
AM
27088diff -urN /usr/share/empty/fs/aufs/whout.h linux/fs/aufs/whout.h
27089--- /usr/share/empty/fs/aufs/whout.h 1970-01-01 01:00:00.000000000 +0100
87a755f4 27090+++ linux/fs/aufs/whout.h 2011-03-17 10:46:59.000000000 +0100
7f207e10 27091@@ -0,0 +1,89 @@
1facf9fc 27092+/*
027c5e7a 27093+ * Copyright (C) 2005-2011 Junjiro R. Okajima
1facf9fc 27094+ *
27095+ * This program, aufs is free software; you can redistribute it and/or modify
27096+ * it under the terms of the GNU General Public License as published by
27097+ * the Free Software Foundation; either version 2 of the License, or
27098+ * (at your option) any later version.
dece6358
AM
27099+ *
27100+ * This program is distributed in the hope that it will be useful,
27101+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
27102+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
27103+ * GNU General Public License for more details.
27104+ *
27105+ * You should have received a copy of the GNU General Public License
27106+ * along with this program; if not, write to the Free Software
27107+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 27108+ */
27109+
27110+/*
27111+ * whiteout for logical deletion and opaque directory
27112+ */
27113+
27114+#ifndef __AUFS_WHOUT_H__
27115+#define __AUFS_WHOUT_H__
27116+
27117+#ifdef __KERNEL__
27118+
1facf9fc 27119+#include <linux/aufs_type.h>
27120+#include "dir.h"
27121+
27122+/* whout.c */
27123+int au_wh_name_alloc(struct qstr *wh, const struct qstr *name);
27124+struct au_branch;
27125+int au_wh_test(struct dentry *h_parent, struct qstr *wh_name,
27126+ struct au_branch *br, int try_sio);
27127+int au_diropq_test(struct dentry *h_dentry, struct au_branch *br);
27128+struct dentry *au_whtmp_lkup(struct dentry *h_parent, struct au_branch *br,
27129+ struct qstr *prefix);
27130+int au_whtmp_ren(struct dentry *h_dentry, struct au_branch *br);
27131+int au_wh_unlink_dentry(struct inode *h_dir, struct path *h_path,
27132+ struct dentry *dentry);
27133+int au_wh_init(struct dentry *h_parent, struct au_branch *br,
27134+ struct super_block *sb);
27135+
27136+/* diropq flags */
27137+#define AuDiropq_CREATE 1
27138+#define au_ftest_diropq(flags, name) ((flags) & AuDiropq_##name)
7f207e10
AM
27139+#define au_fset_diropq(flags, name) \
27140+ do { (flags) |= AuDiropq_##name; } while (0)
27141+#define au_fclr_diropq(flags, name) \
27142+ do { (flags) &= ~AuDiropq_##name; } while (0)
1facf9fc 27143+
27144+struct dentry *au_diropq_sio(struct dentry *dentry, aufs_bindex_t bindex,
27145+ unsigned int flags);
27146+struct dentry *au_wh_lkup(struct dentry *h_parent, struct qstr *base_name,
27147+ struct au_branch *br);
27148+struct dentry *au_wh_create(struct dentry *dentry, aufs_bindex_t bindex,
27149+ struct dentry *h_parent);
27150+
27151+/* real rmdir for the whiteout-ed dir */
27152+struct au_whtmp_rmdir {
27153+ struct inode *dir;
e49829fe 27154+ struct au_branch *br;
1facf9fc 27155+ struct dentry *wh_dentry;
dece6358 27156+ struct au_nhash whlist;
1facf9fc 27157+};
27158+
27159+struct au_whtmp_rmdir *au_whtmp_rmdir_alloc(struct super_block *sb, gfp_t gfp);
27160+void au_whtmp_rmdir_free(struct au_whtmp_rmdir *whtmp);
27161+int au_whtmp_rmdir(struct inode *dir, aufs_bindex_t bindex,
27162+ struct dentry *wh_dentry, struct au_nhash *whlist);
27163+void au_whtmp_kick_rmdir(struct inode *dir, aufs_bindex_t bindex,
27164+ struct dentry *wh_dentry, struct au_whtmp_rmdir *args);
27165+
27166+/* ---------------------------------------------------------------------- */
27167+
27168+static inline struct dentry *au_diropq_create(struct dentry *dentry,
27169+ aufs_bindex_t bindex)
27170+{
27171+ return au_diropq_sio(dentry, bindex, AuDiropq_CREATE);
27172+}
27173+
27174+static inline int au_diropq_remove(struct dentry *dentry, aufs_bindex_t bindex)
27175+{
27176+ return PTR_ERR(au_diropq_sio(dentry, bindex, !AuDiropq_CREATE));
27177+}
27178+
27179+#endif /* __KERNEL__ */
27180+#endif /* __AUFS_WHOUT_H__ */
7f207e10
AM
27181diff -urN /usr/share/empty/fs/aufs/wkq.c linux/fs/aufs/wkq.c
27182--- /usr/share/empty/fs/aufs/wkq.c 1970-01-01 01:00:00.000000000 +0100
87a755f4 27183+++ linux/fs/aufs/wkq.c 2011-03-17 10:46:59.000000000 +0100
027c5e7a 27184@@ -0,0 +1,236 @@
1facf9fc 27185+/*
027c5e7a 27186+ * Copyright (C) 2005-2011 Junjiro R. Okajima
1facf9fc 27187+ *
27188+ * This program, aufs is free software; you can redistribute it and/or modify
27189+ * it under the terms of the GNU General Public License as published by
27190+ * the Free Software Foundation; either version 2 of the License, or
27191+ * (at your option) any later version.
dece6358
AM
27192+ *
27193+ * This program is distributed in the hope that it will be useful,
27194+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
27195+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
27196+ * GNU General Public License for more details.
27197+ *
27198+ * You should have received a copy of the GNU General Public License
27199+ * along with this program; if not, write to the Free Software
27200+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 27201+ */
27202+
27203+/*
27204+ * workqueue for asynchronous/super-io operations
27205+ * todo: try new dredential scheme
27206+ */
27207+
dece6358 27208+#include <linux/module.h>
1facf9fc 27209+#include "aufs.h"
27210+
b752ccd1
AM
27211+/* internal workqueue named AUFS_WKQ_NAME and AUFS_WKQ_PRE_NAME */
27212+enum {
27213+ AuWkq_INORMAL,
27214+ AuWkq_IPRE
27215+};
27216+
27217+static struct {
27218+ char *name;
27219+ struct workqueue_struct *wkq;
27220+} au_wkq[] = {
27221+ [AuWkq_INORMAL] = {
27222+ .name = AUFS_WKQ_NAME
27223+ },
27224+ [AuWkq_IPRE] = {
27225+ .name = AUFS_WKQ_PRE_NAME
27226+ }
27227+};
1facf9fc 27228+
27229+struct au_wkinfo {
27230+ struct work_struct wk;
7f207e10 27231+ struct kobject *kobj;
1facf9fc 27232+
27233+ unsigned int flags; /* see wkq.h */
27234+
27235+ au_wkq_func_t func;
27236+ void *args;
27237+
1facf9fc 27238+ struct completion *comp;
27239+};
27240+
27241+/* ---------------------------------------------------------------------- */
27242+
1facf9fc 27243+static void wkq_func(struct work_struct *wk)
27244+{
27245+ struct au_wkinfo *wkinfo = container_of(wk, struct au_wkinfo, wk);
27246+
7f207e10
AM
27247+ AuDebugOn(current_fsuid());
27248+ AuDebugOn(rlimit(RLIMIT_FSIZE) != RLIM_INFINITY);
27249+
1facf9fc 27250+ wkinfo->func(wkinfo->args);
1facf9fc 27251+ if (au_ftest_wkq(wkinfo->flags, WAIT))
27252+ complete(wkinfo->comp);
27253+ else {
7f207e10 27254+ kobject_put(wkinfo->kobj);
1facf9fc 27255+ module_put(THIS_MODULE);
27256+ kfree(wkinfo);
27257+ }
27258+}
27259+
27260+/*
27261+ * Since struct completion is large, try allocating it dynamically.
27262+ */
27263+#if defined(CONFIG_4KSTACKS) || defined(AuTest4KSTACKS)
27264+#define AuWkqCompDeclare(name) struct completion *comp = NULL
27265+
27266+static int au_wkq_comp_alloc(struct au_wkinfo *wkinfo, struct completion **comp)
27267+{
27268+ *comp = kmalloc(sizeof(**comp), GFP_NOFS);
27269+ if (*comp) {
27270+ init_completion(*comp);
27271+ wkinfo->comp = *comp;
27272+ return 0;
27273+ }
27274+ return -ENOMEM;
27275+}
27276+
27277+static void au_wkq_comp_free(struct completion *comp)
27278+{
27279+ kfree(comp);
27280+}
27281+
27282+#else
27283+
27284+/* no braces */
27285+#define AuWkqCompDeclare(name) \
27286+ DECLARE_COMPLETION_ONSTACK(_ ## name); \
27287+ struct completion *comp = &_ ## name
27288+
27289+static int au_wkq_comp_alloc(struct au_wkinfo *wkinfo, struct completion **comp)
27290+{
27291+ wkinfo->comp = *comp;
27292+ return 0;
27293+}
27294+
27295+static void au_wkq_comp_free(struct completion *comp __maybe_unused)
27296+{
27297+ /* empty */
27298+}
27299+#endif /* 4KSTACKS */
27300+
b752ccd1 27301+static void au_wkq_run(struct au_wkinfo *wkinfo, unsigned int flags)
1facf9fc 27302+{
b752ccd1
AM
27303+ struct workqueue_struct *wkq;
27304+
1facf9fc 27305+ au_dbg_verify_kthread();
b752ccd1 27306+ if (flags & AuWkq_WAIT) {
a1f66529 27307+ INIT_WORK_ONSTACK(&wkinfo->wk, wkq_func);
b752ccd1
AM
27308+ wkq = au_wkq[AuWkq_INORMAL].wkq;
27309+ if (flags & AuWkq_PRE)
27310+ wkq = au_wkq[AuWkq_IPRE].wkq;
27311+ queue_work(wkq, &wkinfo->wk);
4a4d8108
AM
27312+ } else {
27313+ INIT_WORK(&wkinfo->wk, wkq_func);
27314+ schedule_work(&wkinfo->wk);
27315+ }
1facf9fc 27316+}
27317+
7f207e10
AM
27318+/*
27319+ * Be careful. It is easy to make deadlock happen.
27320+ * processA: lock, wkq and wait
27321+ * processB: wkq and wait, lock in wkq
27322+ * --> deadlock
27323+ */
b752ccd1 27324+int au_wkq_do_wait(unsigned int flags, au_wkq_func_t func, void *args)
1facf9fc 27325+{
27326+ int err;
27327+ AuWkqCompDeclare(comp);
27328+ struct au_wkinfo wkinfo = {
b752ccd1 27329+ .flags = flags,
1facf9fc 27330+ .func = func,
27331+ .args = args
27332+ };
27333+
27334+ err = au_wkq_comp_alloc(&wkinfo, &comp);
27335+ if (!err) {
b752ccd1 27336+ au_wkq_run(&wkinfo, flags);
1facf9fc 27337+ /* no timeout, no interrupt */
27338+ wait_for_completion(wkinfo.comp);
27339+ au_wkq_comp_free(comp);
4a4d8108 27340+ destroy_work_on_stack(&wkinfo.wk);
1facf9fc 27341+ }
27342+
27343+ return err;
27344+
27345+}
27346+
027c5e7a
AM
27347+/*
27348+ * Note: dget/dput() in func for aufs dentries are not supported. It will be a
27349+ * problem in a concurrent umounting.
27350+ */
1facf9fc 27351+int au_wkq_nowait(au_wkq_func_t func, void *args, struct super_block *sb)
27352+{
27353+ int err;
27354+ struct au_wkinfo *wkinfo;
27355+
27356+ atomic_inc(&au_sbi(sb)->si_nowait.nw_len);
27357+
27358+ /*
27359+ * wkq_func() must free this wkinfo.
27360+ * it highly depends upon the implementation of workqueue.
27361+ */
27362+ err = 0;
27363+ wkinfo = kmalloc(sizeof(*wkinfo), GFP_NOFS);
27364+ if (wkinfo) {
7f207e10 27365+ wkinfo->kobj = &au_sbi(sb)->si_kobj;
1facf9fc 27366+ wkinfo->flags = !AuWkq_WAIT;
27367+ wkinfo->func = func;
27368+ wkinfo->args = args;
27369+ wkinfo->comp = NULL;
7f207e10 27370+ kobject_get(wkinfo->kobj);
1facf9fc 27371+ __module_get(THIS_MODULE);
27372+
4a4d8108 27373+ au_wkq_run(wkinfo, !AuWkq_WAIT);
1facf9fc 27374+ } else {
27375+ err = -ENOMEM;
e49829fe 27376+ au_nwt_done(&au_sbi(sb)->si_nowait);
1facf9fc 27377+ }
27378+
27379+ return err;
27380+}
27381+
27382+/* ---------------------------------------------------------------------- */
27383+
27384+void au_nwt_init(struct au_nowait_tasks *nwt)
27385+{
27386+ atomic_set(&nwt->nw_len, 0);
4a4d8108 27387+ /* smp_mb(); */ /* atomic_set */
1facf9fc 27388+ init_waitqueue_head(&nwt->nw_wq);
27389+}
27390+
27391+void au_wkq_fin(void)
27392+{
b752ccd1
AM
27393+ int i;
27394+
27395+ for (i = 0; i < ARRAY_SIZE(au_wkq); i++)
27396+ if (au_wkq[i].wkq)
27397+ destroy_workqueue(au_wkq[i].wkq);
1facf9fc 27398+}
27399+
27400+int __init au_wkq_init(void)
27401+{
b752ccd1
AM
27402+ int err, i;
27403+
27404+ err = 0;
27405+ for (i = 0; !err && i < ARRAY_SIZE(au_wkq); i++) {
7f207e10
AM
27406+ BUILD_BUG_ON(!WQ_RESCUER);
27407+ au_wkq[i].wkq = alloc_workqueue(au_wkq[i].name, !WQ_RESCUER,
27408+ WQ_DFL_ACTIVE);
b752ccd1
AM
27409+ if (IS_ERR(au_wkq[i].wkq))
27410+ err = PTR_ERR(au_wkq[i].wkq);
27411+ else if (!au_wkq[i].wkq)
27412+ err = -ENOMEM;
27413+ if (unlikely(err))
27414+ au_wkq[i].wkq = NULL;
27415+ }
7f207e10 27416+ if (unlikely(err))
b752ccd1
AM
27417+ au_wkq_fin();
27418+
27419+ return err;
1facf9fc 27420+}
7f207e10
AM
27421diff -urN /usr/share/empty/fs/aufs/wkq.h linux/fs/aufs/wkq.h
27422--- /usr/share/empty/fs/aufs/wkq.h 1970-01-01 01:00:00.000000000 +0100
87a755f4 27423+++ linux/fs/aufs/wkq.h 2011-03-17 10:46:59.000000000 +0100
7f207e10 27424@@ -0,0 +1,90 @@
1facf9fc 27425+/*
027c5e7a 27426+ * Copyright (C) 2005-2011 Junjiro R. Okajima
1facf9fc 27427+ *
27428+ * This program, aufs is free software; you can redistribute it and/or modify
27429+ * it under the terms of the GNU General Public License as published by
27430+ * the Free Software Foundation; either version 2 of the License, or
27431+ * (at your option) any later version.
dece6358
AM
27432+ *
27433+ * This program is distributed in the hope that it will be useful,
27434+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
27435+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
27436+ * GNU General Public License for more details.
27437+ *
27438+ * You should have received a copy of the GNU General Public License
27439+ * along with this program; if not, write to the Free Software
27440+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 27441+ */
27442+
27443+/*
27444+ * workqueue for asynchronous/super-io operations
27445+ * todo: try new credentials management scheme
27446+ */
27447+
27448+#ifndef __AUFS_WKQ_H__
27449+#define __AUFS_WKQ_H__
27450+
27451+#ifdef __KERNEL__
27452+
1facf9fc 27453+#include <linux/sched.h>
dece6358 27454+#include <linux/wait.h>
1facf9fc 27455+#include <linux/aufs_type.h>
27456+
dece6358
AM
27457+struct super_block;
27458+
1facf9fc 27459+/* ---------------------------------------------------------------------- */
27460+
27461+/*
27462+ * in the next operation, wait for the 'nowait' tasks in system-wide workqueue
27463+ */
27464+struct au_nowait_tasks {
27465+ atomic_t nw_len;
27466+ wait_queue_head_t nw_wq;
27467+};
27468+
27469+/* ---------------------------------------------------------------------- */
27470+
27471+typedef void (*au_wkq_func_t)(void *args);
27472+
27473+/* wkq flags */
27474+#define AuWkq_WAIT 1
b752ccd1 27475+#define AuWkq_PRE (1 << 1)
1facf9fc 27476+#define au_ftest_wkq(flags, name) ((flags) & AuWkq_##name)
7f207e10
AM
27477+#define au_fset_wkq(flags, name) \
27478+ do { (flags) |= AuWkq_##name; } while (0)
27479+#define au_fclr_wkq(flags, name) \
27480+ do { (flags) &= ~AuWkq_##name; } while (0)
1facf9fc 27481+
27482+/* wkq.c */
b752ccd1 27483+int au_wkq_do_wait(unsigned int flags, au_wkq_func_t func, void *args);
1facf9fc 27484+int au_wkq_nowait(au_wkq_func_t func, void *args, struct super_block *sb);
27485+void au_nwt_init(struct au_nowait_tasks *nwt);
27486+int __init au_wkq_init(void);
27487+void au_wkq_fin(void);
27488+
27489+/* ---------------------------------------------------------------------- */
27490+
b752ccd1
AM
27491+static inline int au_wkq_wait_pre(au_wkq_func_t func, void *args)
27492+{
27493+ return au_wkq_do_wait(AuWkq_WAIT | AuWkq_PRE, func, args);
27494+}
27495+
27496+static inline int au_wkq_wait(au_wkq_func_t func, void *args)
1facf9fc 27497+{
b752ccd1 27498+ return au_wkq_do_wait(AuWkq_WAIT, func, args);
1facf9fc 27499+}
27500+
27501+static inline void au_nwt_done(struct au_nowait_tasks *nwt)
27502+{
e49829fe 27503+ if (atomic_dec_and_test(&nwt->nw_len))
1facf9fc 27504+ wake_up_all(&nwt->nw_wq);
27505+}
27506+
27507+static inline int au_nwt_flush(struct au_nowait_tasks *nwt)
27508+{
27509+ wait_event(nwt->nw_wq, !atomic_read(&nwt->nw_len));
27510+ return 0;
27511+}
27512+
27513+#endif /* __KERNEL__ */
27514+#endif /* __AUFS_WKQ_H__ */
7f207e10
AM
27515diff -urN /usr/share/empty/fs/aufs/xino.c linux/fs/aufs/xino.c
27516--- /usr/share/empty/fs/aufs/xino.c 1970-01-01 01:00:00.000000000 +0100
87a755f4 27517+++ linux/fs/aufs/xino.c 2011-07-22 08:26:47.857636522 +0200
7f207e10 27518@@ -0,0 +1,1265 @@
1facf9fc 27519+/*
027c5e7a 27520+ * Copyright (C) 2005-2011 Junjiro R. Okajima
1facf9fc 27521+ *
27522+ * This program, aufs is free software; you can redistribute it and/or modify
27523+ * it under the terms of the GNU General Public License as published by
27524+ * the Free Software Foundation; either version 2 of the License, or
27525+ * (at your option) any later version.
dece6358
AM
27526+ *
27527+ * This program is distributed in the hope that it will be useful,
27528+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
27529+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
27530+ * GNU General Public License for more details.
27531+ *
27532+ * You should have received a copy of the GNU General Public License
27533+ * along with this program; if not, write to the Free Software
27534+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 27535+ */
27536+
27537+/*
27538+ * external inode number translation table and bitmap
27539+ */
27540+
dece6358 27541+#include <linux/file.h>
1facf9fc 27542+#include <linux/seq_file.h>
27543+#include <linux/uaccess.h>
27544+#include "aufs.h"
27545+
b752ccd1 27546+ssize_t xino_fread(au_readf_t func, struct file *file, void *kbuf, size_t size,
1facf9fc 27547+ loff_t *pos)
27548+{
27549+ ssize_t err;
27550+ mm_segment_t oldfs;
b752ccd1
AM
27551+ union {
27552+ void *k;
27553+ char __user *u;
27554+ } buf;
1facf9fc 27555+
b752ccd1 27556+ buf.k = kbuf;
1facf9fc 27557+ oldfs = get_fs();
27558+ set_fs(KERNEL_DS);
27559+ do {
27560+ /* todo: signal_pending? */
b752ccd1 27561+ err = func(file, buf.u, size, pos);
1facf9fc 27562+ } while (err == -EAGAIN || err == -EINTR);
27563+ set_fs(oldfs);
27564+
27565+#if 0 /* reserved for future use */
27566+ if (err > 0)
27567+ fsnotify_access(file->f_dentry);
27568+#endif
27569+
27570+ return err;
27571+}
27572+
27573+/* ---------------------------------------------------------------------- */
27574+
b752ccd1 27575+static ssize_t do_xino_fwrite(au_writef_t func, struct file *file, void *kbuf,
1facf9fc 27576+ size_t size, loff_t *pos)
27577+{
27578+ ssize_t err;
27579+ mm_segment_t oldfs;
b752ccd1
AM
27580+ union {
27581+ void *k;
27582+ const char __user *u;
27583+ } buf;
1facf9fc 27584+
b752ccd1 27585+ buf.k = kbuf;
1facf9fc 27586+ oldfs = get_fs();
27587+ set_fs(KERNEL_DS);
1facf9fc 27588+ do {
27589+ /* todo: signal_pending? */
b752ccd1 27590+ err = func(file, buf.u, size, pos);
1facf9fc 27591+ } while (err == -EAGAIN || err == -EINTR);
1facf9fc 27592+ set_fs(oldfs);
27593+
27594+#if 0 /* reserved for future use */
27595+ if (err > 0)
27596+ fsnotify_modify(file->f_dentry);
27597+#endif
27598+
27599+ return err;
27600+}
27601+
27602+struct do_xino_fwrite_args {
27603+ ssize_t *errp;
27604+ au_writef_t func;
27605+ struct file *file;
27606+ void *buf;
27607+ size_t size;
27608+ loff_t *pos;
27609+};
27610+
27611+static void call_do_xino_fwrite(void *args)
27612+{
27613+ struct do_xino_fwrite_args *a = args;
27614+ *a->errp = do_xino_fwrite(a->func, a->file, a->buf, a->size, a->pos);
27615+}
27616+
27617+ssize_t xino_fwrite(au_writef_t func, struct file *file, void *buf, size_t size,
27618+ loff_t *pos)
27619+{
27620+ ssize_t err;
27621+
27622+ /* todo: signal block and no wkq? */
b752ccd1
AM
27623+ if (rlimit(RLIMIT_FSIZE) == RLIM_INFINITY) {
27624+ lockdep_off();
27625+ err = do_xino_fwrite(func, file, buf, size, pos);
27626+ lockdep_on();
27627+ } else {
27628+ /*
27629+ * it breaks RLIMIT_FSIZE and normal user's limit,
27630+ * users should care about quota and real 'filesystem full.'
27631+ */
1facf9fc 27632+ int wkq_err;
27633+ struct do_xino_fwrite_args args = {
27634+ .errp = &err,
27635+ .func = func,
27636+ .file = file,
27637+ .buf = buf,
27638+ .size = size,
27639+ .pos = pos
27640+ };
27641+
27642+ wkq_err = au_wkq_wait(call_do_xino_fwrite, &args);
27643+ if (unlikely(wkq_err))
27644+ err = wkq_err;
b752ccd1 27645+ }
1facf9fc 27646+
27647+ return err;
27648+}
27649+
27650+/* ---------------------------------------------------------------------- */
27651+
27652+/*
27653+ * create a new xinofile at the same place/path as @base_file.
27654+ */
27655+struct file *au_xino_create2(struct file *base_file, struct file *copy_src)
27656+{
27657+ struct file *file;
4a4d8108 27658+ struct dentry *base, *parent;
1facf9fc 27659+ struct inode *dir;
27660+ struct qstr *name;
1308ab2a 27661+ struct path path;
4a4d8108 27662+ int err;
1facf9fc 27663+
27664+ base = base_file->f_dentry;
27665+ parent = base->d_parent; /* dir inode is locked */
27666+ dir = parent->d_inode;
27667+ IMustLock(dir);
27668+
27669+ file = ERR_PTR(-EINVAL);
27670+ name = &base->d_name;
4a4d8108
AM
27671+ path.dentry = vfsub_lookup_one_len(name->name, parent, name->len);
27672+ if (IS_ERR(path.dentry)) {
27673+ file = (void *)path.dentry;
27674+ pr_err("%.*s lookup err %ld\n",
27675+ AuLNPair(name), PTR_ERR(path.dentry));
1facf9fc 27676+ goto out;
27677+ }
27678+
27679+ /* no need to mnt_want_write() since we call dentry_open() later */
4a4d8108 27680+ err = vfs_create(dir, path.dentry, S_IRUGO | S_IWUGO, NULL);
1facf9fc 27681+ if (unlikely(err)) {
27682+ file = ERR_PTR(err);
4a4d8108 27683+ pr_err("%.*s create err %d\n", AuLNPair(name), err);
1facf9fc 27684+ goto out_dput;
27685+ }
27686+
1308ab2a 27687+ path.mnt = base_file->f_vfsmnt;
4a4d8108 27688+ file = vfsub_dentry_open(&path,
7f207e10 27689+ O_RDWR | O_CREAT | O_EXCL | O_LARGEFILE
2cbb1c4b 27690+ /* | __FMODE_NONOTIFY */);
1facf9fc 27691+ if (IS_ERR(file)) {
4a4d8108 27692+ pr_err("%.*s open err %ld\n", AuLNPair(name), PTR_ERR(file));
1facf9fc 27693+ goto out_dput;
27694+ }
27695+
27696+ err = vfsub_unlink(dir, &file->f_path, /*force*/0);
27697+ if (unlikely(err)) {
4a4d8108 27698+ pr_err("%.*s unlink err %d\n", AuLNPair(name), err);
1facf9fc 27699+ goto out_fput;
27700+ }
27701+
27702+ if (copy_src) {
27703+ /* no one can touch copy_src xino */
27704+ err = au_copy_file(file, copy_src,
27705+ i_size_read(copy_src->f_dentry->d_inode));
27706+ if (unlikely(err)) {
4a4d8108 27707+ pr_err("%.*s copy err %d\n", AuLNPair(name), err);
1facf9fc 27708+ goto out_fput;
27709+ }
27710+ }
27711+ goto out_dput; /* success */
27712+
4f0767ce 27713+out_fput:
1facf9fc 27714+ fput(file);
27715+ file = ERR_PTR(err);
4f0767ce 27716+out_dput:
4a4d8108 27717+ dput(path.dentry);
4f0767ce 27718+out:
1facf9fc 27719+ return file;
27720+}
27721+
27722+struct au_xino_lock_dir {
27723+ struct au_hinode *hdir;
27724+ struct dentry *parent;
27725+ struct mutex *mtx;
27726+};
27727+
27728+static void au_xino_lock_dir(struct super_block *sb, struct file *xino,
27729+ struct au_xino_lock_dir *ldir)
27730+{
27731+ aufs_bindex_t brid, bindex;
27732+
27733+ ldir->hdir = NULL;
27734+ bindex = -1;
27735+ brid = au_xino_brid(sb);
27736+ if (brid >= 0)
27737+ bindex = au_br_index(sb, brid);
27738+ if (bindex >= 0) {
27739+ ldir->hdir = au_hi(sb->s_root->d_inode, bindex);
4a4d8108 27740+ au_hn_imtx_lock_nested(ldir->hdir, AuLsc_I_PARENT);
1facf9fc 27741+ } else {
27742+ ldir->parent = dget_parent(xino->f_dentry);
27743+ ldir->mtx = &ldir->parent->d_inode->i_mutex;
27744+ mutex_lock_nested(ldir->mtx, AuLsc_I_PARENT);
27745+ }
27746+}
27747+
27748+static void au_xino_unlock_dir(struct au_xino_lock_dir *ldir)
27749+{
27750+ if (ldir->hdir)
4a4d8108 27751+ au_hn_imtx_unlock(ldir->hdir);
1facf9fc 27752+ else {
27753+ mutex_unlock(ldir->mtx);
27754+ dput(ldir->parent);
27755+ }
27756+}
27757+
27758+/* ---------------------------------------------------------------------- */
27759+
27760+/* trucate xino files asynchronously */
27761+
27762+int au_xino_trunc(struct super_block *sb, aufs_bindex_t bindex)
27763+{
27764+ int err;
27765+ aufs_bindex_t bi, bend;
27766+ struct au_branch *br;
27767+ struct file *new_xino, *file;
27768+ struct super_block *h_sb;
27769+ struct au_xino_lock_dir ldir;
27770+
27771+ err = -EINVAL;
27772+ bend = au_sbend(sb);
27773+ if (unlikely(bindex < 0 || bend < bindex))
27774+ goto out;
27775+ br = au_sbr(sb, bindex);
27776+ file = br->br_xino.xi_file;
27777+ if (!file)
27778+ goto out;
27779+
27780+ au_xino_lock_dir(sb, file, &ldir);
27781+ /* mnt_want_write() is unnecessary here */
27782+ new_xino = au_xino_create2(file, file);
27783+ au_xino_unlock_dir(&ldir);
27784+ err = PTR_ERR(new_xino);
27785+ if (IS_ERR(new_xino))
27786+ goto out;
27787+ err = 0;
27788+ fput(file);
27789+ br->br_xino.xi_file = new_xino;
27790+
27791+ h_sb = br->br_mnt->mnt_sb;
27792+ for (bi = 0; bi <= bend; bi++) {
27793+ if (unlikely(bi == bindex))
27794+ continue;
27795+ br = au_sbr(sb, bi);
27796+ if (br->br_mnt->mnt_sb != h_sb)
27797+ continue;
27798+
27799+ fput(br->br_xino.xi_file);
27800+ br->br_xino.xi_file = new_xino;
27801+ get_file(new_xino);
27802+ }
27803+
4f0767ce 27804+out:
1facf9fc 27805+ return err;
27806+}
27807+
27808+struct xino_do_trunc_args {
27809+ struct super_block *sb;
27810+ struct au_branch *br;
27811+};
27812+
27813+static void xino_do_trunc(void *_args)
27814+{
27815+ struct xino_do_trunc_args *args = _args;
27816+ struct super_block *sb;
27817+ struct au_branch *br;
27818+ struct inode *dir;
27819+ int err;
27820+ aufs_bindex_t bindex;
27821+
27822+ err = 0;
27823+ sb = args->sb;
27824+ dir = sb->s_root->d_inode;
27825+ br = args->br;
27826+
27827+ si_noflush_write_lock(sb);
27828+ ii_read_lock_parent(dir);
27829+ bindex = au_br_index(sb, br->br_id);
27830+ err = au_xino_trunc(sb, bindex);
dece6358
AM
27831+ if (!err
27832+ && br->br_xino.xi_file->f_dentry->d_inode->i_blocks
1facf9fc 27833+ >= br->br_xino_upper)
27834+ br->br_xino_upper += AUFS_XINO_TRUNC_STEP;
27835+
1facf9fc 27836+ ii_read_unlock(dir);
27837+ if (unlikely(err))
4a4d8108 27838+ pr_warning("err b%d, (%d)\n", bindex, err);
1facf9fc 27839+ atomic_dec(&br->br_xino_running);
27840+ atomic_dec(&br->br_count);
1facf9fc 27841+ si_write_unlock(sb);
027c5e7a 27842+ au_nwt_done(&au_sbi(sb)->si_nowait);
1facf9fc 27843+ kfree(args);
27844+}
27845+
27846+static void xino_try_trunc(struct super_block *sb, struct au_branch *br)
27847+{
27848+ struct xino_do_trunc_args *args;
27849+ int wkq_err;
27850+
27851+ if (br->br_xino.xi_file->f_dentry->d_inode->i_blocks
27852+ < br->br_xino_upper)
27853+ return;
27854+
27855+ if (atomic_inc_return(&br->br_xino_running) > 1)
27856+ goto out;
27857+
27858+ /* lock and kfree() will be called in trunc_xino() */
27859+ args = kmalloc(sizeof(*args), GFP_NOFS);
27860+ if (unlikely(!args)) {
27861+ AuErr1("no memory\n");
27862+ goto out_args;
27863+ }
27864+
e49829fe 27865+ atomic_inc(&br->br_count);
1facf9fc 27866+ args->sb = sb;
27867+ args->br = br;
27868+ wkq_err = au_wkq_nowait(xino_do_trunc, args, sb);
27869+ if (!wkq_err)
27870+ return; /* success */
27871+
4a4d8108 27872+ pr_err("wkq %d\n", wkq_err);
e49829fe 27873+ atomic_dec(&br->br_count);
1facf9fc 27874+
4f0767ce 27875+out_args:
1facf9fc 27876+ kfree(args);
4f0767ce 27877+out:
e49829fe 27878+ atomic_dec(&br->br_xino_running);
1facf9fc 27879+}
27880+
27881+/* ---------------------------------------------------------------------- */
27882+
27883+static int au_xino_do_write(au_writef_t write, struct file *file,
27884+ ino_t h_ino, ino_t ino)
27885+{
27886+ loff_t pos;
27887+ ssize_t sz;
27888+
27889+ pos = h_ino;
27890+ if (unlikely(au_loff_max / sizeof(ino) - 1 < pos)) {
27891+ AuIOErr1("too large hi%lu\n", (unsigned long)h_ino);
27892+ return -EFBIG;
27893+ }
27894+ pos *= sizeof(ino);
27895+ sz = xino_fwrite(write, file, &ino, sizeof(ino), &pos);
27896+ if (sz == sizeof(ino))
27897+ return 0; /* success */
27898+
27899+ AuIOErr("write failed (%zd)\n", sz);
27900+ return -EIO;
27901+}
27902+
27903+/*
27904+ * write @ino to the xinofile for the specified branch{@sb, @bindex}
27905+ * at the position of @h_ino.
27906+ * even if @ino is zero, it is written to the xinofile and means no entry.
27907+ * if the size of the xino file on a specific filesystem exceeds the watermark,
27908+ * try truncating it.
27909+ */
27910+int au_xino_write(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino,
27911+ ino_t ino)
27912+{
27913+ int err;
27914+ unsigned int mnt_flags;
27915+ struct au_branch *br;
27916+
27917+ BUILD_BUG_ON(sizeof(long long) != sizeof(au_loff_max)
27918+ || ((loff_t)-1) > 0);
dece6358 27919+ SiMustAnyLock(sb);
1facf9fc 27920+
27921+ mnt_flags = au_mntflags(sb);
27922+ if (!au_opt_test(mnt_flags, XINO))
27923+ return 0;
27924+
27925+ br = au_sbr(sb, bindex);
27926+ err = au_xino_do_write(au_sbi(sb)->si_xwrite, br->br_xino.xi_file,
27927+ h_ino, ino);
27928+ if (!err) {
27929+ if (au_opt_test(mnt_flags, TRUNC_XINO)
27930+ && au_test_fs_trunc_xino(br->br_mnt->mnt_sb))
27931+ xino_try_trunc(sb, br);
27932+ return 0; /* success */
27933+ }
27934+
27935+ AuIOErr("write failed (%d)\n", err);
27936+ return -EIO;
27937+}
27938+
27939+/* ---------------------------------------------------------------------- */
27940+
27941+/* aufs inode number bitmap */
27942+
27943+static const int page_bits = (int)PAGE_SIZE * BITS_PER_BYTE;
27944+static ino_t xib_calc_ino(unsigned long pindex, int bit)
27945+{
27946+ ino_t ino;
27947+
27948+ AuDebugOn(bit < 0 || page_bits <= bit);
27949+ ino = AUFS_FIRST_INO + pindex * page_bits + bit;
27950+ return ino;
27951+}
27952+
27953+static void xib_calc_bit(ino_t ino, unsigned long *pindex, int *bit)
27954+{
27955+ AuDebugOn(ino < AUFS_FIRST_INO);
27956+ ino -= AUFS_FIRST_INO;
27957+ *pindex = ino / page_bits;
27958+ *bit = ino % page_bits;
27959+}
27960+
27961+static int xib_pindex(struct super_block *sb, unsigned long pindex)
27962+{
27963+ int err;
27964+ loff_t pos;
27965+ ssize_t sz;
27966+ struct au_sbinfo *sbinfo;
27967+ struct file *xib;
27968+ unsigned long *p;
27969+
27970+ sbinfo = au_sbi(sb);
27971+ MtxMustLock(&sbinfo->si_xib_mtx);
27972+ AuDebugOn(pindex > ULONG_MAX / PAGE_SIZE
27973+ || !au_opt_test(sbinfo->si_mntflags, XINO));
27974+
27975+ if (pindex == sbinfo->si_xib_last_pindex)
27976+ return 0;
27977+
27978+ xib = sbinfo->si_xib;
27979+ p = sbinfo->si_xib_buf;
27980+ pos = sbinfo->si_xib_last_pindex;
27981+ pos *= PAGE_SIZE;
27982+ sz = xino_fwrite(sbinfo->si_xwrite, xib, p, PAGE_SIZE, &pos);
27983+ if (unlikely(sz != PAGE_SIZE))
27984+ goto out;
27985+
27986+ pos = pindex;
27987+ pos *= PAGE_SIZE;
27988+ if (i_size_read(xib->f_dentry->d_inode) >= pos + PAGE_SIZE)
27989+ sz = xino_fread(sbinfo->si_xread, xib, p, PAGE_SIZE, &pos);
27990+ else {
27991+ memset(p, 0, PAGE_SIZE);
27992+ sz = xino_fwrite(sbinfo->si_xwrite, xib, p, PAGE_SIZE, &pos);
27993+ }
27994+ if (sz == PAGE_SIZE) {
27995+ sbinfo->si_xib_last_pindex = pindex;
27996+ return 0; /* success */
27997+ }
27998+
4f0767ce 27999+out:
b752ccd1
AM
28000+ AuIOErr1("write failed (%zd)\n", sz);
28001+ err = sz;
28002+ if (sz >= 0)
28003+ err = -EIO;
28004+ return err;
28005+}
28006+
28007+/* ---------------------------------------------------------------------- */
28008+
28009+static void au_xib_clear_bit(struct inode *inode)
28010+{
28011+ int err, bit;
28012+ unsigned long pindex;
28013+ struct super_block *sb;
28014+ struct au_sbinfo *sbinfo;
28015+
28016+ AuDebugOn(inode->i_nlink);
28017+
28018+ sb = inode->i_sb;
28019+ xib_calc_bit(inode->i_ino, &pindex, &bit);
28020+ AuDebugOn(page_bits <= bit);
28021+ sbinfo = au_sbi(sb);
28022+ mutex_lock(&sbinfo->si_xib_mtx);
28023+ err = xib_pindex(sb, pindex);
28024+ if (!err) {
28025+ clear_bit(bit, sbinfo->si_xib_buf);
28026+ sbinfo->si_xib_next_bit = bit;
28027+ }
28028+ mutex_unlock(&sbinfo->si_xib_mtx);
28029+}
28030+
28031+/* for s_op->delete_inode() */
28032+void au_xino_delete_inode(struct inode *inode, const int unlinked)
28033+{
28034+ int err;
28035+ unsigned int mnt_flags;
28036+ aufs_bindex_t bindex, bend, bi;
28037+ unsigned char try_trunc;
28038+ struct au_iinfo *iinfo;
28039+ struct super_block *sb;
28040+ struct au_hinode *hi;
28041+ struct inode *h_inode;
28042+ struct au_branch *br;
28043+ au_writef_t xwrite;
28044+
28045+ sb = inode->i_sb;
28046+ mnt_flags = au_mntflags(sb);
28047+ if (!au_opt_test(mnt_flags, XINO)
28048+ || inode->i_ino == AUFS_ROOT_INO)
28049+ return;
28050+
28051+ if (unlinked) {
28052+ au_xigen_inc(inode);
28053+ au_xib_clear_bit(inode);
28054+ }
28055+
28056+ iinfo = au_ii(inode);
28057+ if (!iinfo)
28058+ return;
1facf9fc 28059+
b752ccd1
AM
28060+ bindex = iinfo->ii_bstart;
28061+ if (bindex < 0)
28062+ return;
1facf9fc 28063+
b752ccd1
AM
28064+ xwrite = au_sbi(sb)->si_xwrite;
28065+ try_trunc = !!au_opt_test(mnt_flags, TRUNC_XINO);
28066+ hi = iinfo->ii_hinode + bindex;
28067+ bend = iinfo->ii_bend;
28068+ for (; bindex <= bend; bindex++, hi++) {
28069+ h_inode = hi->hi_inode;
28070+ if (!h_inode
28071+ || (!unlinked && h_inode->i_nlink))
28072+ continue;
1facf9fc 28073+
b752ccd1
AM
28074+ /* inode may not be revalidated */
28075+ bi = au_br_index(sb, hi->hi_id);
28076+ if (bi < 0)
28077+ continue;
1facf9fc 28078+
b752ccd1
AM
28079+ br = au_sbr(sb, bi);
28080+ err = au_xino_do_write(xwrite, br->br_xino.xi_file,
28081+ h_inode->i_ino, /*ino*/0);
28082+ if (!err && try_trunc
28083+ && au_test_fs_trunc_xino(br->br_mnt->mnt_sb))
28084+ xino_try_trunc(sb, br);
1facf9fc 28085+ }
1facf9fc 28086+}
28087+
28088+/* get an unused inode number from bitmap */
28089+ino_t au_xino_new_ino(struct super_block *sb)
28090+{
28091+ ino_t ino;
28092+ unsigned long *p, pindex, ul, pend;
28093+ struct au_sbinfo *sbinfo;
28094+ struct file *file;
28095+ int free_bit, err;
28096+
28097+ if (!au_opt_test(au_mntflags(sb), XINO))
28098+ return iunique(sb, AUFS_FIRST_INO);
28099+
28100+ sbinfo = au_sbi(sb);
28101+ mutex_lock(&sbinfo->si_xib_mtx);
28102+ p = sbinfo->si_xib_buf;
28103+ free_bit = sbinfo->si_xib_next_bit;
28104+ if (free_bit < page_bits && !test_bit(free_bit, p))
28105+ goto out; /* success */
28106+ free_bit = find_first_zero_bit(p, page_bits);
28107+ if (free_bit < page_bits)
28108+ goto out; /* success */
28109+
28110+ pindex = sbinfo->si_xib_last_pindex;
28111+ for (ul = pindex - 1; ul < ULONG_MAX; ul--) {
28112+ err = xib_pindex(sb, ul);
28113+ if (unlikely(err))
28114+ goto out_err;
28115+ free_bit = find_first_zero_bit(p, page_bits);
28116+ if (free_bit < page_bits)
28117+ goto out; /* success */
28118+ }
28119+
28120+ file = sbinfo->si_xib;
28121+ pend = i_size_read(file->f_dentry->d_inode) / PAGE_SIZE;
28122+ for (ul = pindex + 1; ul <= pend; ul++) {
28123+ err = xib_pindex(sb, ul);
28124+ if (unlikely(err))
28125+ goto out_err;
28126+ free_bit = find_first_zero_bit(p, page_bits);
28127+ if (free_bit < page_bits)
28128+ goto out; /* success */
28129+ }
28130+ BUG();
28131+
4f0767ce 28132+out:
1facf9fc 28133+ set_bit(free_bit, p);
7f207e10 28134+ sbinfo->si_xib_next_bit = free_bit + 1;
1facf9fc 28135+ pindex = sbinfo->si_xib_last_pindex;
28136+ mutex_unlock(&sbinfo->si_xib_mtx);
28137+ ino = xib_calc_ino(pindex, free_bit);
28138+ AuDbg("i%lu\n", (unsigned long)ino);
28139+ return ino;
4f0767ce 28140+out_err:
1facf9fc 28141+ mutex_unlock(&sbinfo->si_xib_mtx);
28142+ AuDbg("i0\n");
28143+ return 0;
28144+}
28145+
28146+/*
28147+ * read @ino from xinofile for the specified branch{@sb, @bindex}
28148+ * at the position of @h_ino.
28149+ * if @ino does not exist and @do_new is true, get new one.
28150+ */
28151+int au_xino_read(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino,
28152+ ino_t *ino)
28153+{
28154+ int err;
28155+ ssize_t sz;
28156+ loff_t pos;
28157+ struct file *file;
28158+ struct au_sbinfo *sbinfo;
28159+
28160+ *ino = 0;
28161+ if (!au_opt_test(au_mntflags(sb), XINO))
28162+ return 0; /* no xino */
28163+
28164+ err = 0;
28165+ sbinfo = au_sbi(sb);
28166+ pos = h_ino;
28167+ if (unlikely(au_loff_max / sizeof(*ino) - 1 < pos)) {
28168+ AuIOErr1("too large hi%lu\n", (unsigned long)h_ino);
28169+ return -EFBIG;
28170+ }
28171+ pos *= sizeof(*ino);
28172+
28173+ file = au_sbr(sb, bindex)->br_xino.xi_file;
28174+ if (i_size_read(file->f_dentry->d_inode) < pos + sizeof(*ino))
28175+ return 0; /* no ino */
28176+
28177+ sz = xino_fread(sbinfo->si_xread, file, ino, sizeof(*ino), &pos);
28178+ if (sz == sizeof(*ino))
28179+ return 0; /* success */
28180+
28181+ err = sz;
28182+ if (unlikely(sz >= 0)) {
28183+ err = -EIO;
28184+ AuIOErr("xino read error (%zd)\n", sz);
28185+ }
28186+
28187+ return err;
28188+}
28189+
28190+/* ---------------------------------------------------------------------- */
28191+
28192+/* create and set a new xino file */
28193+
28194+struct file *au_xino_create(struct super_block *sb, char *fname, int silent)
28195+{
28196+ struct file *file;
28197+ struct dentry *h_parent, *d;
28198+ struct inode *h_dir;
28199+ int err;
28200+
28201+ /*
28202+ * at mount-time, and the xino file is the default path,
4a4d8108 28203+ * hnotify is disabled so we have no notify events to ignore.
1facf9fc 28204+ * when a user specified the xino, we cannot get au_hdir to be ignored.
28205+ */
7f207e10 28206+ file = vfsub_filp_open(fname, O_RDWR | O_CREAT | O_EXCL | O_LARGEFILE
2cbb1c4b 28207+ /* | __FMODE_NONOTIFY */,
1facf9fc 28208+ S_IRUGO | S_IWUGO);
28209+ if (IS_ERR(file)) {
28210+ if (!silent)
4a4d8108 28211+ pr_err("open %s(%ld)\n", fname, PTR_ERR(file));
1facf9fc 28212+ return file;
28213+ }
28214+
28215+ /* keep file count */
28216+ h_parent = dget_parent(file->f_dentry);
28217+ h_dir = h_parent->d_inode;
28218+ mutex_lock_nested(&h_dir->i_mutex, AuLsc_I_PARENT);
28219+ /* mnt_want_write() is unnecessary here */
28220+ err = vfsub_unlink(h_dir, &file->f_path, /*force*/0);
28221+ mutex_unlock(&h_dir->i_mutex);
28222+ dput(h_parent);
28223+ if (unlikely(err)) {
28224+ if (!silent)
4a4d8108 28225+ pr_err("unlink %s(%d)\n", fname, err);
1facf9fc 28226+ goto out;
28227+ }
28228+
28229+ err = -EINVAL;
28230+ d = file->f_dentry;
28231+ if (unlikely(sb == d->d_sb)) {
28232+ if (!silent)
4a4d8108 28233+ pr_err("%s must be outside\n", fname);
1facf9fc 28234+ goto out;
28235+ }
28236+ if (unlikely(au_test_fs_bad_xino(d->d_sb))) {
28237+ if (!silent)
4a4d8108
AM
28238+ pr_err("xino doesn't support %s(%s)\n",
28239+ fname, au_sbtype(d->d_sb));
1facf9fc 28240+ goto out;
28241+ }
28242+ return file; /* success */
28243+
4f0767ce 28244+out:
1facf9fc 28245+ fput(file);
28246+ file = ERR_PTR(err);
28247+ return file;
28248+}
28249+
28250+/*
28251+ * find another branch who is on the same filesystem of the specified
28252+ * branch{@btgt}. search until @bend.
28253+ */
28254+static int is_sb_shared(struct super_block *sb, aufs_bindex_t btgt,
28255+ aufs_bindex_t bend)
28256+{
28257+ aufs_bindex_t bindex;
28258+ struct super_block *tgt_sb = au_sbr_sb(sb, btgt);
28259+
28260+ for (bindex = 0; bindex < btgt; bindex++)
28261+ if (unlikely(tgt_sb == au_sbr_sb(sb, bindex)))
28262+ return bindex;
28263+ for (bindex++; bindex <= bend; bindex++)
28264+ if (unlikely(tgt_sb == au_sbr_sb(sb, bindex)))
28265+ return bindex;
28266+ return -1;
28267+}
28268+
28269+/* ---------------------------------------------------------------------- */
28270+
28271+/*
28272+ * initialize the xinofile for the specified branch @br
28273+ * at the place/path where @base_file indicates.
28274+ * test whether another branch is on the same filesystem or not,
28275+ * if @do_test is true.
28276+ */
28277+int au_xino_br(struct super_block *sb, struct au_branch *br, ino_t h_ino,
28278+ struct file *base_file, int do_test)
28279+{
28280+ int err;
28281+ ino_t ino;
28282+ aufs_bindex_t bend, bindex;
28283+ struct au_branch *shared_br, *b;
28284+ struct file *file;
28285+ struct super_block *tgt_sb;
28286+
28287+ shared_br = NULL;
28288+ bend = au_sbend(sb);
28289+ if (do_test) {
28290+ tgt_sb = br->br_mnt->mnt_sb;
28291+ for (bindex = 0; bindex <= bend; bindex++) {
28292+ b = au_sbr(sb, bindex);
28293+ if (tgt_sb == b->br_mnt->mnt_sb) {
28294+ shared_br = b;
28295+ break;
28296+ }
28297+ }
28298+ }
28299+
28300+ if (!shared_br || !shared_br->br_xino.xi_file) {
28301+ struct au_xino_lock_dir ldir;
28302+
28303+ au_xino_lock_dir(sb, base_file, &ldir);
28304+ /* mnt_want_write() is unnecessary here */
28305+ file = au_xino_create2(base_file, NULL);
28306+ au_xino_unlock_dir(&ldir);
28307+ err = PTR_ERR(file);
28308+ if (IS_ERR(file))
28309+ goto out;
28310+ br->br_xino.xi_file = file;
28311+ } else {
28312+ br->br_xino.xi_file = shared_br->br_xino.xi_file;
28313+ get_file(br->br_xino.xi_file);
28314+ }
28315+
28316+ ino = AUFS_ROOT_INO;
28317+ err = au_xino_do_write(au_sbi(sb)->si_xwrite, br->br_xino.xi_file,
28318+ h_ino, ino);
b752ccd1
AM
28319+ if (unlikely(err)) {
28320+ fput(br->br_xino.xi_file);
28321+ br->br_xino.xi_file = NULL;
28322+ }
1facf9fc 28323+
4f0767ce 28324+out:
1facf9fc 28325+ return err;
28326+}
28327+
28328+/* ---------------------------------------------------------------------- */
28329+
28330+/* trucate a xino bitmap file */
28331+
28332+/* todo: slow */
28333+static int do_xib_restore(struct super_block *sb, struct file *file, void *page)
28334+{
28335+ int err, bit;
28336+ ssize_t sz;
28337+ unsigned long pindex;
28338+ loff_t pos, pend;
28339+ struct au_sbinfo *sbinfo;
28340+ au_readf_t func;
28341+ ino_t *ino;
28342+ unsigned long *p;
28343+
28344+ err = 0;
28345+ sbinfo = au_sbi(sb);
dece6358 28346+ MtxMustLock(&sbinfo->si_xib_mtx);
1facf9fc 28347+ p = sbinfo->si_xib_buf;
28348+ func = sbinfo->si_xread;
28349+ pend = i_size_read(file->f_dentry->d_inode);
28350+ pos = 0;
28351+ while (pos < pend) {
28352+ sz = xino_fread(func, file, page, PAGE_SIZE, &pos);
28353+ err = sz;
28354+ if (unlikely(sz <= 0))
28355+ goto out;
28356+
28357+ err = 0;
28358+ for (ino = page; sz > 0; ino++, sz -= sizeof(ino)) {
28359+ if (unlikely(*ino < AUFS_FIRST_INO))
28360+ continue;
28361+
28362+ xib_calc_bit(*ino, &pindex, &bit);
28363+ AuDebugOn(page_bits <= bit);
28364+ err = xib_pindex(sb, pindex);
28365+ if (!err)
28366+ set_bit(bit, p);
28367+ else
28368+ goto out;
28369+ }
28370+ }
28371+
4f0767ce 28372+out:
1facf9fc 28373+ return err;
28374+}
28375+
28376+static int xib_restore(struct super_block *sb)
28377+{
28378+ int err;
28379+ aufs_bindex_t bindex, bend;
28380+ void *page;
28381+
28382+ err = -ENOMEM;
28383+ page = (void *)__get_free_page(GFP_NOFS);
28384+ if (unlikely(!page))
28385+ goto out;
28386+
28387+ err = 0;
28388+ bend = au_sbend(sb);
28389+ for (bindex = 0; !err && bindex <= bend; bindex++)
28390+ if (!bindex || is_sb_shared(sb, bindex, bindex - 1) < 0)
28391+ err = do_xib_restore
28392+ (sb, au_sbr(sb, bindex)->br_xino.xi_file, page);
28393+ else
28394+ AuDbg("b%d\n", bindex);
28395+ free_page((unsigned long)page);
28396+
4f0767ce 28397+out:
1facf9fc 28398+ return err;
28399+}
28400+
28401+int au_xib_trunc(struct super_block *sb)
28402+{
28403+ int err;
28404+ ssize_t sz;
28405+ loff_t pos;
28406+ struct au_xino_lock_dir ldir;
28407+ struct au_sbinfo *sbinfo;
28408+ unsigned long *p;
28409+ struct file *file;
28410+
dece6358
AM
28411+ SiMustWriteLock(sb);
28412+
1facf9fc 28413+ err = 0;
28414+ sbinfo = au_sbi(sb);
28415+ if (!au_opt_test(sbinfo->si_mntflags, XINO))
28416+ goto out;
28417+
28418+ file = sbinfo->si_xib;
28419+ if (i_size_read(file->f_dentry->d_inode) <= PAGE_SIZE)
28420+ goto out;
28421+
28422+ au_xino_lock_dir(sb, file, &ldir);
28423+ /* mnt_want_write() is unnecessary here */
28424+ file = au_xino_create2(sbinfo->si_xib, NULL);
28425+ au_xino_unlock_dir(&ldir);
28426+ err = PTR_ERR(file);
28427+ if (IS_ERR(file))
28428+ goto out;
28429+ fput(sbinfo->si_xib);
28430+ sbinfo->si_xib = file;
28431+
28432+ p = sbinfo->si_xib_buf;
28433+ memset(p, 0, PAGE_SIZE);
28434+ pos = 0;
28435+ sz = xino_fwrite(sbinfo->si_xwrite, sbinfo->si_xib, p, PAGE_SIZE, &pos);
28436+ if (unlikely(sz != PAGE_SIZE)) {
28437+ err = sz;
28438+ AuIOErr("err %d\n", err);
28439+ if (sz >= 0)
28440+ err = -EIO;
28441+ goto out;
28442+ }
28443+
28444+ mutex_lock(&sbinfo->si_xib_mtx);
28445+ /* mnt_want_write() is unnecessary here */
28446+ err = xib_restore(sb);
28447+ mutex_unlock(&sbinfo->si_xib_mtx);
28448+
28449+out:
28450+ return err;
28451+}
28452+
28453+/* ---------------------------------------------------------------------- */
28454+
28455+/*
28456+ * xino mount option handlers
28457+ */
28458+static au_readf_t find_readf(struct file *h_file)
28459+{
28460+ const struct file_operations *fop = h_file->f_op;
28461+
28462+ if (fop) {
28463+ if (fop->read)
28464+ return fop->read;
28465+ if (fop->aio_read)
28466+ return do_sync_read;
28467+ }
28468+ return ERR_PTR(-ENOSYS);
28469+}
28470+
28471+static au_writef_t find_writef(struct file *h_file)
28472+{
28473+ const struct file_operations *fop = h_file->f_op;
28474+
28475+ if (fop) {
28476+ if (fop->write)
28477+ return fop->write;
28478+ if (fop->aio_write)
28479+ return do_sync_write;
28480+ }
28481+ return ERR_PTR(-ENOSYS);
28482+}
28483+
28484+/* xino bitmap */
28485+static void xino_clear_xib(struct super_block *sb)
28486+{
28487+ struct au_sbinfo *sbinfo;
28488+
dece6358
AM
28489+ SiMustWriteLock(sb);
28490+
1facf9fc 28491+ sbinfo = au_sbi(sb);
28492+ sbinfo->si_xread = NULL;
28493+ sbinfo->si_xwrite = NULL;
28494+ if (sbinfo->si_xib)
28495+ fput(sbinfo->si_xib);
28496+ sbinfo->si_xib = NULL;
28497+ free_page((unsigned long)sbinfo->si_xib_buf);
28498+ sbinfo->si_xib_buf = NULL;
28499+}
28500+
28501+static int au_xino_set_xib(struct super_block *sb, struct file *base)
28502+{
28503+ int err;
28504+ loff_t pos;
28505+ struct au_sbinfo *sbinfo;
28506+ struct file *file;
28507+
dece6358
AM
28508+ SiMustWriteLock(sb);
28509+
1facf9fc 28510+ sbinfo = au_sbi(sb);
28511+ file = au_xino_create2(base, sbinfo->si_xib);
28512+ err = PTR_ERR(file);
28513+ if (IS_ERR(file))
28514+ goto out;
28515+ if (sbinfo->si_xib)
28516+ fput(sbinfo->si_xib);
28517+ sbinfo->si_xib = file;
28518+ sbinfo->si_xread = find_readf(file);
28519+ sbinfo->si_xwrite = find_writef(file);
28520+
28521+ err = -ENOMEM;
28522+ if (!sbinfo->si_xib_buf)
28523+ sbinfo->si_xib_buf = (void *)get_zeroed_page(GFP_NOFS);
28524+ if (unlikely(!sbinfo->si_xib_buf))
28525+ goto out_unset;
28526+
28527+ sbinfo->si_xib_last_pindex = 0;
28528+ sbinfo->si_xib_next_bit = 0;
28529+ if (i_size_read(file->f_dentry->d_inode) < PAGE_SIZE) {
28530+ pos = 0;
28531+ err = xino_fwrite(sbinfo->si_xwrite, file, sbinfo->si_xib_buf,
28532+ PAGE_SIZE, &pos);
28533+ if (unlikely(err != PAGE_SIZE))
28534+ goto out_free;
28535+ }
28536+ err = 0;
28537+ goto out; /* success */
28538+
4f0767ce 28539+out_free:
1facf9fc 28540+ free_page((unsigned long)sbinfo->si_xib_buf);
b752ccd1
AM
28541+ sbinfo->si_xib_buf = NULL;
28542+ if (err >= 0)
28543+ err = -EIO;
4f0767ce 28544+out_unset:
b752ccd1
AM
28545+ fput(sbinfo->si_xib);
28546+ sbinfo->si_xib = NULL;
28547+ sbinfo->si_xread = NULL;
28548+ sbinfo->si_xwrite = NULL;
4f0767ce 28549+out:
b752ccd1 28550+ return err;
1facf9fc 28551+}
28552+
b752ccd1
AM
28553+/* xino for each branch */
28554+static void xino_clear_br(struct super_block *sb)
28555+{
28556+ aufs_bindex_t bindex, bend;
28557+ struct au_branch *br;
1facf9fc 28558+
b752ccd1
AM
28559+ bend = au_sbend(sb);
28560+ for (bindex = 0; bindex <= bend; bindex++) {
28561+ br = au_sbr(sb, bindex);
28562+ if (!br || !br->br_xino.xi_file)
28563+ continue;
28564+
28565+ fput(br->br_xino.xi_file);
28566+ br->br_xino.xi_file = NULL;
28567+ }
28568+}
28569+
28570+static int au_xino_set_br(struct super_block *sb, struct file *base)
1facf9fc 28571+{
28572+ int err;
b752ccd1
AM
28573+ ino_t ino;
28574+ aufs_bindex_t bindex, bend, bshared;
28575+ struct {
28576+ struct file *old, *new;
28577+ } *fpair, *p;
28578+ struct au_branch *br;
28579+ struct inode *inode;
28580+ au_writef_t writef;
1facf9fc 28581+
b752ccd1
AM
28582+ SiMustWriteLock(sb);
28583+
28584+ err = -ENOMEM;
28585+ bend = au_sbend(sb);
28586+ fpair = kcalloc(bend + 1, sizeof(*fpair), GFP_NOFS);
28587+ if (unlikely(!fpair))
1facf9fc 28588+ goto out;
28589+
b752ccd1
AM
28590+ inode = sb->s_root->d_inode;
28591+ ino = AUFS_ROOT_INO;
28592+ writef = au_sbi(sb)->si_xwrite;
28593+ for (bindex = 0, p = fpair; bindex <= bend; bindex++, p++) {
28594+ br = au_sbr(sb, bindex);
28595+ bshared = is_sb_shared(sb, bindex, bindex - 1);
28596+ if (bshared >= 0) {
28597+ /* shared xino */
28598+ *p = fpair[bshared];
28599+ get_file(p->new);
28600+ }
28601+
28602+ if (!p->new) {
28603+ /* new xino */
28604+ p->old = br->br_xino.xi_file;
28605+ p->new = au_xino_create2(base, br->br_xino.xi_file);
28606+ err = PTR_ERR(p->new);
28607+ if (IS_ERR(p->new)) {
28608+ p->new = NULL;
28609+ goto out_pair;
28610+ }
28611+ }
28612+
28613+ err = au_xino_do_write(writef, p->new,
28614+ au_h_iptr(inode, bindex)->i_ino, ino);
28615+ if (unlikely(err))
28616+ goto out_pair;
28617+ }
28618+
28619+ for (bindex = 0, p = fpair; bindex <= bend; bindex++, p++) {
28620+ br = au_sbr(sb, bindex);
28621+ if (br->br_xino.xi_file)
28622+ fput(br->br_xino.xi_file);
28623+ get_file(p->new);
28624+ br->br_xino.xi_file = p->new;
28625+ }
1facf9fc 28626+
4f0767ce 28627+out_pair:
b752ccd1
AM
28628+ for (bindex = 0, p = fpair; bindex <= bend; bindex++, p++)
28629+ if (p->new)
28630+ fput(p->new);
28631+ else
28632+ break;
28633+ kfree(fpair);
4f0767ce 28634+out:
1facf9fc 28635+ return err;
28636+}
b752ccd1
AM
28637+
28638+void au_xino_clr(struct super_block *sb)
28639+{
28640+ struct au_sbinfo *sbinfo;
28641+
28642+ au_xigen_clr(sb);
28643+ xino_clear_xib(sb);
28644+ xino_clear_br(sb);
28645+ sbinfo = au_sbi(sb);
28646+ /* lvalue, do not call au_mntflags() */
28647+ au_opt_clr(sbinfo->si_mntflags, XINO);
28648+}
28649+
28650+int au_xino_set(struct super_block *sb, struct au_opt_xino *xino, int remount)
28651+{
28652+ int err, skip;
28653+ struct dentry *parent, *cur_parent;
28654+ struct qstr *dname, *cur_name;
28655+ struct file *cur_xino;
28656+ struct inode *dir;
28657+ struct au_sbinfo *sbinfo;
28658+
28659+ SiMustWriteLock(sb);
28660+
28661+ err = 0;
28662+ sbinfo = au_sbi(sb);
28663+ parent = dget_parent(xino->file->f_dentry);
28664+ if (remount) {
28665+ skip = 0;
28666+ dname = &xino->file->f_dentry->d_name;
28667+ cur_xino = sbinfo->si_xib;
28668+ if (cur_xino) {
28669+ cur_parent = dget_parent(cur_xino->f_dentry);
28670+ cur_name = &cur_xino->f_dentry->d_name;
28671+ skip = (cur_parent == parent
28672+ && dname->len == cur_name->len
28673+ && !memcmp(dname->name, cur_name->name,
28674+ dname->len));
28675+ dput(cur_parent);
28676+ }
28677+ if (skip)
28678+ goto out;
28679+ }
28680+
28681+ au_opt_set(sbinfo->si_mntflags, XINO);
28682+ dir = parent->d_inode;
28683+ mutex_lock_nested(&dir->i_mutex, AuLsc_I_PARENT);
28684+ /* mnt_want_write() is unnecessary here */
28685+ err = au_xino_set_xib(sb, xino->file);
28686+ if (!err)
28687+ err = au_xigen_set(sb, xino->file);
28688+ if (!err)
28689+ err = au_xino_set_br(sb, xino->file);
28690+ mutex_unlock(&dir->i_mutex);
28691+ if (!err)
28692+ goto out; /* success */
28693+
28694+ /* reset all */
28695+ AuIOErr("failed creating xino(%d).\n", err);
28696+
4f0767ce 28697+out:
b752ccd1
AM
28698+ dput(parent);
28699+ return err;
28700+}
28701+
28702+/* ---------------------------------------------------------------------- */
28703+
28704+/*
28705+ * create a xinofile at the default place/path.
28706+ */
28707+struct file *au_xino_def(struct super_block *sb)
28708+{
28709+ struct file *file;
28710+ char *page, *p;
28711+ struct au_branch *br;
28712+ struct super_block *h_sb;
28713+ struct path path;
28714+ aufs_bindex_t bend, bindex, bwr;
28715+
28716+ br = NULL;
28717+ bend = au_sbend(sb);
28718+ bwr = -1;
28719+ for (bindex = 0; bindex <= bend; bindex++) {
28720+ br = au_sbr(sb, bindex);
28721+ if (au_br_writable(br->br_perm)
28722+ && !au_test_fs_bad_xino(br->br_mnt->mnt_sb)) {
28723+ bwr = bindex;
28724+ break;
28725+ }
28726+ }
28727+
7f207e10
AM
28728+ if (bwr >= 0) {
28729+ file = ERR_PTR(-ENOMEM);
28730+ page = __getname_gfp(GFP_NOFS);
28731+ if (unlikely(!page))
28732+ goto out;
28733+ path.mnt = br->br_mnt;
28734+ path.dentry = au_h_dptr(sb->s_root, bwr);
28735+ p = d_path(&path, page, PATH_MAX - sizeof(AUFS_XINO_FNAME));
28736+ file = (void *)p;
28737+ if (!IS_ERR(p)) {
28738+ strcat(p, "/" AUFS_XINO_FNAME);
28739+ AuDbg("%s\n", p);
28740+ file = au_xino_create(sb, p, /*silent*/0);
28741+ if (!IS_ERR(file))
28742+ au_xino_brid_set(sb, br->br_id);
28743+ }
28744+ __putname(page);
28745+ } else {
28746+ file = au_xino_create(sb, AUFS_XINO_DEFPATH, /*silent*/0);
28747+ if (IS_ERR(file))
28748+ goto out;
28749+ h_sb = file->f_dentry->d_sb;
28750+ if (unlikely(au_test_fs_bad_xino(h_sb))) {
28751+ pr_err("xino doesn't support %s(%s)\n",
28752+ AUFS_XINO_DEFPATH, au_sbtype(h_sb));
28753+ fput(file);
28754+ file = ERR_PTR(-EINVAL);
28755+ }
28756+ if (!IS_ERR(file))
28757+ au_xino_brid_set(sb, -1);
28758+ }
0c5527e5 28759+
7f207e10
AM
28760+out:
28761+ return file;
28762+}
28763+
28764+/* ---------------------------------------------------------------------- */
28765+
28766+int au_xino_path(struct seq_file *seq, struct file *file)
28767+{
28768+ int err;
28769+
28770+ err = au_seq_path(seq, &file->f_path);
28771+ if (unlikely(err < 0))
28772+ goto out;
28773+
28774+ err = 0;
28775+#define Deleted "\\040(deleted)"
28776+ seq->count -= sizeof(Deleted) - 1;
28777+ AuDebugOn(memcmp(seq->buf + seq->count, Deleted,
28778+ sizeof(Deleted) - 1));
28779+#undef Deleted
28780+
28781+out:
28782+ return err;
28783+}
28784diff -urN /usr/share/empty/include/linux/aufs_type.h linux/include/linux/aufs_type.h
28785--- /usr/share/empty/include/linux/aufs_type.h 1970-01-01 01:00:00.000000000 +0100
87a755f4 28786+++ linux/include/linux/aufs_type.h 2011-07-22 08:26:47.857636522 +0200
027c5e7a 28787@@ -0,0 +1,206 @@
7f207e10 28788+/*
027c5e7a 28789+ * Copyright (C) 2005-2011 Junjiro R. Okajima
7f207e10
AM
28790+ *
28791+ * This program, aufs is free software; you can redistribute it and/or modify
28792+ * it under the terms of the GNU General Public License as published by
28793+ * the Free Software Foundation; either version 2 of the License, or
28794+ * (at your option) any later version.
28795+ *
28796+ * This program is distributed in the hope that it will be useful,
28797+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
28798+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
28799+ * GNU General Public License for more details.
28800+ *
28801+ * You should have received a copy of the GNU General Public License
28802+ * along with this program; if not, write to the Free Software
28803+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
28804+ */
28805+
28806+#ifndef __AUFS_TYPE_H__
28807+#define __AUFS_TYPE_H__
28808+
28809+#include <linux/ioctl.h>
28810+#include <linux/kernel.h>
28811+#include <linux/limits.h>
28812+#include <linux/types.h>
28813+
87a755f4 28814+#define AUFS_VERSION "2.1-standalone.tree-3.0-rcN-20110718"
7f207e10
AM
28815+
28816+/* todo? move this to linux-2.6.19/include/magic.h */
28817+#define AUFS_SUPER_MAGIC ('a' << 24 | 'u' << 16 | 'f' << 8 | 's')
28818+
28819+/* ---------------------------------------------------------------------- */
28820+
28821+#ifdef CONFIG_AUFS_BRANCH_MAX_127
28822+typedef __s8 aufs_bindex_t;
28823+#define AUFS_BRANCH_MAX 127
28824+#else
28825+typedef __s16 aufs_bindex_t;
28826+#ifdef CONFIG_AUFS_BRANCH_MAX_511
28827+#define AUFS_BRANCH_MAX 511
28828+#elif defined(CONFIG_AUFS_BRANCH_MAX_1023)
28829+#define AUFS_BRANCH_MAX 1023
28830+#elif defined(CONFIG_AUFS_BRANCH_MAX_32767)
28831+#define AUFS_BRANCH_MAX 32767
28832+#endif
28833+#endif
28834+
28835+#ifdef __KERNEL__
28836+#ifndef AUFS_BRANCH_MAX
28837+#error unknown CONFIG_AUFS_BRANCH_MAX value
28838+#endif
28839+#endif /* __KERNEL__ */
28840+
28841+/* ---------------------------------------------------------------------- */
28842+
28843+#define AUFS_NAME "aufs"
28844+#define AUFS_FSTYPE AUFS_NAME
28845+
28846+#define AUFS_ROOT_INO 2
28847+#define AUFS_FIRST_INO 11
28848+
28849+#define AUFS_WH_PFX ".wh."
28850+#define AUFS_WH_PFX_LEN ((int)sizeof(AUFS_WH_PFX) - 1)
28851+#define AUFS_WH_TMP_LEN 4
28852+/* a limit for rmdir/rename a dir */
28853+#define AUFS_MAX_NAMELEN (NAME_MAX \
28854+ - AUFS_WH_PFX_LEN * 2 /* doubly whiteouted */\
28855+ - 1 /* dot */\
28856+ - AUFS_WH_TMP_LEN) /* hex */
28857+#define AUFS_XINO_FNAME "." AUFS_NAME ".xino"
28858+#define AUFS_XINO_DEFPATH "/tmp/" AUFS_XINO_FNAME
28859+#define AUFS_XINO_TRUNC_INIT 64 /* blocks */
28860+#define AUFS_XINO_TRUNC_STEP 4 /* blocks */
28861+#define AUFS_DIRWH_DEF 3
28862+#define AUFS_RDCACHE_DEF 10 /* seconds */
027c5e7a 28863+#define AUFS_RDCACHE_MAX 3600 /* seconds */
7f207e10
AM
28864+#define AUFS_RDBLK_DEF 512 /* bytes */
28865+#define AUFS_RDHASH_DEF 32
28866+#define AUFS_WKQ_NAME AUFS_NAME "d"
28867+#define AUFS_WKQ_PRE_NAME AUFS_WKQ_NAME "_pre"
027c5e7a
AM
28868+#define AUFS_MFS_DEF_SEC 30 /* seconds */
28869+#define AUFS_MFS_MAX_SEC 3600 /* seconds */
7f207e10
AM
28870+#define AUFS_PLINK_WARN 100 /* number of plinks */
28871+
28872+/* pseudo-link maintenace under /proc */
28873+#define AUFS_PLINK_MAINT_NAME "plink_maint"
28874+#define AUFS_PLINK_MAINT_DIR "fs/" AUFS_NAME
28875+#define AUFS_PLINK_MAINT_PATH AUFS_PLINK_MAINT_DIR "/" AUFS_PLINK_MAINT_NAME
28876+
28877+#define AUFS_DIROPQ_NAME AUFS_WH_PFX ".opq" /* whiteouted doubly */
28878+#define AUFS_WH_DIROPQ AUFS_WH_PFX AUFS_DIROPQ_NAME
28879+
28880+#define AUFS_BASE_NAME AUFS_WH_PFX AUFS_NAME
28881+#define AUFS_PLINKDIR_NAME AUFS_WH_PFX "plnk"
28882+#define AUFS_ORPHDIR_NAME AUFS_WH_PFX "orph"
28883+
28884+/* doubly whiteouted */
28885+#define AUFS_WH_BASE AUFS_WH_PFX AUFS_BASE_NAME
28886+#define AUFS_WH_PLINKDIR AUFS_WH_PFX AUFS_PLINKDIR_NAME
28887+#define AUFS_WH_ORPHDIR AUFS_WH_PFX AUFS_ORPHDIR_NAME
28888+
28889+/* branch permission */
28890+#define AUFS_BRPERM_RW "rw"
28891+#define AUFS_BRPERM_RO "ro"
28892+#define AUFS_BRPERM_RR "rr"
28893+#define AUFS_BRPERM_WH "wh"
28894+#define AUFS_BRPERM_NLWH "nolwh"
28895+#define AUFS_BRPERM_ROWH AUFS_BRPERM_RO "+" AUFS_BRPERM_WH
28896+#define AUFS_BRPERM_RRWH AUFS_BRPERM_RR "+" AUFS_BRPERM_WH
28897+#define AUFS_BRPERM_RWNLWH AUFS_BRPERM_RW "+" AUFS_BRPERM_NLWH
28898+
28899+/* ---------------------------------------------------------------------- */
28900+
28901+/* ioctl */
28902+enum {
28903+ /* readdir in userspace */
28904+ AuCtl_RDU,
28905+ AuCtl_RDU_INO,
28906+
28907+ /* pathconf wrapper */
027c5e7a
AM
28908+ AuCtl_WBR_FD,
28909+
28910+ /* busy inode */
28911+ AuCtl_IBUSY
7f207e10
AM
28912+};
28913+
28914+/* borrowed from linux/include/linux/kernel.h */
28915+#ifndef ALIGN
28916+#define ALIGN(x, a) __ALIGN_MASK(x, (typeof(x))(a)-1)
28917+#define __ALIGN_MASK(x, mask) (((x)+(mask))&~(mask))
28918+#endif
28919+
28920+/* borrowed from linux/include/linux/compiler-gcc3.h */
28921+#ifndef __aligned
28922+#define __aligned(x) __attribute__((aligned(x)))
28923+#define __packed __attribute__((packed))
28924+#endif
28925+
28926+struct au_rdu_cookie {
28927+ __u64 h_pos;
28928+ __s16 bindex;
28929+ __u8 flags;
28930+ __u8 pad;
28931+ __u32 generation;
28932+} __aligned(8);
28933+
28934+struct au_rdu_ent {
28935+ __u64 ino;
28936+ __s16 bindex;
28937+ __u8 type;
28938+ __u8 nlen;
28939+ __u8 wh;
28940+ char name[0];
28941+} __aligned(8);
28942+
28943+static inline int au_rdu_len(int nlen)
28944+{
28945+ /* include the terminating NULL */
28946+ return ALIGN(sizeof(struct au_rdu_ent) + nlen + 1,
28947+ sizeof(__u64));
28948+}
28949+
28950+union au_rdu_ent_ul {
28951+ struct au_rdu_ent __user *e;
28952+ __u64 ul;
28953+};
28954+
28955+enum {
28956+ AufsCtlRduV_SZ,
28957+ AufsCtlRduV_End
28958+};
28959+
28960+struct aufs_rdu {
28961+ /* input */
28962+ union {
28963+ __u64 sz; /* AuCtl_RDU */
28964+ __u64 nent; /* AuCtl_RDU_INO */
28965+ };
28966+ union au_rdu_ent_ul ent;
28967+ __u16 verify[AufsCtlRduV_End];
28968+
28969+ /* input/output */
28970+ __u32 blk;
28971+
28972+ /* output */
28973+ union au_rdu_ent_ul tail;
28974+ /* number of entries which were added in a single call */
28975+ __u64 rent;
28976+ __u8 full;
28977+ __u8 shwh;
28978+
28979+ struct au_rdu_cookie cookie;
28980+} __aligned(8);
28981+
027c5e7a
AM
28982+struct aufs_ibusy {
28983+ __u64 ino, h_ino;
28984+ __s16 bindex;
28985+} __aligned(8);
28986+
7f207e10
AM
28987+#define AuCtlType 'A'
28988+#define AUFS_CTL_RDU _IOWR(AuCtlType, AuCtl_RDU, struct aufs_rdu)
28989+#define AUFS_CTL_RDU_INO _IOWR(AuCtlType, AuCtl_RDU_INO, struct aufs_rdu)
28990+#define AUFS_CTL_WBR_FD _IO(AuCtlType, AuCtl_WBR_FD)
027c5e7a 28991+#define AUFS_CTL_IBUSY _IOWR(AuCtlType, AuCtl_IBUSY, struct aufs_ibusy)
7f207e10
AM
28992+
28993+#endif /* __AUFS_TYPE_H__ */
87a755f4 28994
This page took 6.234718 seconds and 4 git commands to generate.