]> git.pld-linux.org Git - packages/kernel.git/blame - kernel-aufs3.patch
- 3.4.65
[packages/kernel.git] / kernel-aufs3.patch
CommitLineData
7ce627cf 1aufs3.4 kbuild patch
7f207e10
AM
2
3diff --git a/fs/Kconfig b/fs/Kconfig
92d182d2 4index f95ae3a..6d8a9a5 100644
7f207e10
AM
5--- a/fs/Kconfig
6+++ b/fs/Kconfig
92d182d2 7@@ -220,6 +220,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
92d182d2 16index 2fb9779..abefac5 100644
7f207e10
AM
17--- a/fs/Makefile
18+++ b/fs/Makefile
92d182d2 19@@ -125,3 +125,4 @@ obj-$(CONFIG_GFS2_FS) += gfs2/
9dbd164d 20 obj-y += exofs/ # Multiple modules
7f207e10 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
92d182d2 25index 3c9b616..8704efa 100644
7f207e10
AM
26--- a/include/linux/Kbuild
27+++ b/include/linux/Kbuild
92d182d2 28@@ -66,6 +66,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
7ce627cf 36aufs3.4 base patch
7f207e10
AM
37
38diff --git a/fs/namei.c b/fs/namei.c
7ce627cf 39index c427919..7ff959b 100644
7f207e10
AM
40--- a/fs/namei.c
41+++ b/fs/namei.c
92d182d2 42@@ -1831,7 +1831,7 @@ int vfs_path_lookup(struct dentry *dentry, struct vfsmount *mnt,
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
92d182d2 52index f847684..f871233 100644
7f207e10
AM
53--- a/fs/splice.c
54+++ b/fs/splice.c
7eafdf33 55@@ -1084,8 +1084,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);
7eafdf33 66@@ -1112,9 +1112,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
9dbd164d 80index ffc0213..ef35a31 100644
7f207e10
AM
81--- a/include/linux/namei.h
82+++ b/include/linux/namei.h
9dbd164d 83@@ -85,6 +85,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 *);
1e00d052
AM
91diff --git a/include/linux/splice.h b/include/linux/splice.h
92index 26e5b61..3ffef2f 100644
93--- a/include/linux/splice.h
94+++ b/include/linux/splice.h
95@@ -91,4 +91,10 @@ extern void splice_shrink_spd(struct pipe_inode_info *,
4b3da204
AM
96 extern void spd_release_page(struct splice_pipe_desc *, unsigned int);
97
98 extern const struct pipe_buf_operations page_cache_pipe_buf_ops;
1e00d052
AM
99+
100+extern long do_splice_from(struct pipe_inode_info *pipe, struct file *out,
101+ loff_t *ppos, size_t len, unsigned int flags);
102+extern long do_splice_to(struct file *in, loff_t *ppos,
103+ struct pipe_inode_info *pipe, size_t len,
104+ unsigned int flags);
105 #endif
7ce627cf 106aufs3.4 standalone patch
7f207e10
AM
107
108diff --git a/fs/file_table.c b/fs/file_table.c
92d182d2 109index 70f2a0f..146a3d7 100644
7f207e10
AM
110--- a/fs/file_table.c
111+++ b/fs/file_table.c
92d182d2 112@@ -442,6 +442,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 /*
1e00d052 121diff --git a/fs/inode.c b/fs/inode.c
92d182d2 122index 9f4f5fe..bb0f3ba 100644
1e00d052
AM
123--- a/fs/inode.c
124+++ b/fs/inode.c
92d182d2 125@@ -56,6 +56,7 @@ static struct hlist_head *inode_hashtable __read_mostly;
4b3da204 126 static __cacheline_aligned_in_smp DEFINE_SPINLOCK(inode_hash_lock);
2cbb1c4b
JR
127
128 __cacheline_aligned_in_smp DEFINE_SPINLOCK(inode_sb_list_lock);
2cbb1c4b 129+EXPORT_SYMBOL(inode_sb_list_lock);
7f207e10
AM
130
131 /*
4b3da204 132 * Empty aops. Can be used for the cases where the user does not
7f207e10 133diff --git a/fs/namei.c b/fs/namei.c
7ce627cf 134index 7ff959b..b170167 100644
7f207e10
AM
135--- a/fs/namei.c
136+++ b/fs/namei.c
92d182d2 137@@ -1835,6 +1835,7 @@ struct dentry *lookup_hash(struct nameidata *nd)
027c5e7a 138 {
7f207e10
AM
139 return __lookup_hash(&nd->last, nd->path.dentry, nd);
140 }
141+EXPORT_SYMBOL(lookup_hash);
142
7f207e10
AM
143 /**
144 * lookup_one_len - filesystem helper to lookup single pathname component
145diff --git a/fs/namespace.c b/fs/namespace.c
7eafdf33 146index e608199..38fcc2e 100644
7f207e10
AM
147--- a/fs/namespace.c
148+++ b/fs/namespace.c
7eafdf33 149@@ -1339,6 +1339,7 @@ int iterate_mounts(int (*f)(struct vfsmount *, void *), void *arg,
7f207e10
AM
150 }
151 return 0;
152 }
153+EXPORT_SYMBOL(iterate_mounts);
154
7eafdf33 155 static void cleanup_group_ids(struct mount *mnt, struct mount *end)
7f207e10
AM
156 {
157diff --git a/fs/notify/group.c b/fs/notify/group.c
1e00d052 158index 63fc294..6f4adca 100644
7f207e10
AM
159--- a/fs/notify/group.c
160+++ b/fs/notify/group.c
161@@ -22,6 +22,7 @@
162 #include <linux/srcu.h>
163 #include <linux/rculist.h>
164 #include <linux/wait.h>
165+#include <linux/module.h>
166
167 #include <linux/fsnotify_backend.h>
168 #include "fsnotify.h"
169@@ -70,6 +71,7 @@ void fsnotify_put_group(struct fsnotify_group *group)
170 if (atomic_dec_and_test(&group->refcnt))
171 fsnotify_destroy_group(group);
172 }
173+EXPORT_SYMBOL(fsnotify_put_group);
174
175 /*
176 * Create a new fsnotify_group and hold a reference for the group returned.
177@@ -102,3 +104,4 @@ struct fsnotify_group *fsnotify_alloc_group(const struct fsnotify_ops *ops)
178
179 return group;
180 }
181+EXPORT_SYMBOL(fsnotify_alloc_group);
182diff --git a/fs/notify/mark.c b/fs/notify/mark.c
7eafdf33 183index f104d56..54f36db 100644
7f207e10
AM
184--- a/fs/notify/mark.c
185+++ b/fs/notify/mark.c
2cbb1c4b 186@@ -112,6 +112,7 @@ void fsnotify_put_mark(struct fsnotify_mark *mark)
7f207e10
AM
187 if (atomic_dec_and_test(&mark->refcnt))
188 mark->free_mark(mark);
189 }
190+EXPORT_SYMBOL(fsnotify_put_mark);
191
192 /*
193 * Any time a mark is getting freed we end up here.
7eafdf33 194@@ -191,6 +192,7 @@ void fsnotify_destroy_mark(struct fsnotify_mark *mark)
7f207e10
AM
195 if (unlikely(atomic_dec_and_test(&group->num_marks)))
196 fsnotify_final_destroy_group(group);
197 }
198+EXPORT_SYMBOL(fsnotify_destroy_mark);
199
200 void fsnotify_set_mark_mask_locked(struct fsnotify_mark *mark, __u32 mask)
201 {
7eafdf33 202@@ -278,6 +280,7 @@ err:
7f207e10
AM
203
204 return ret;
205 }
206+EXPORT_SYMBOL(fsnotify_add_mark);
207
208 /*
209 * clear any marks in a group in which mark->flags & flags is true
7eafdf33 210@@ -333,6 +336,7 @@ void fsnotify_init_mark(struct fsnotify_mark *mark,
7f207e10
AM
211 atomic_set(&mark->refcnt, 1);
212 mark->free_mark = free_mark;
213 }
214+EXPORT_SYMBOL(fsnotify_init_mark);
215
216 static int fsnotify_mark_destroy(void *ignored)
217 {
218diff --git a/fs/open.c b/fs/open.c
92d182d2 219index 5720854..ec59242 100644
7f207e10
AM
220--- a/fs/open.c
221+++ b/fs/open.c
222@@ -60,6 +60,7 @@ int do_truncate(struct dentry *dentry, loff_t length, unsigned int time_attrs,
223 mutex_unlock(&dentry->d_inode->i_mutex);
224 return ret;
225 }
226+EXPORT_SYMBOL(do_truncate);
227
228 static long do_sys_truncate(const char __user *pathname, loff_t length)
229 {
230diff --git a/fs/splice.c b/fs/splice.c
92d182d2 231index f871233..70f5481 100644
7f207e10
AM
232--- a/fs/splice.c
233+++ b/fs/splice.c
7eafdf33 234@@ -1108,6 +1108,7 @@ long do_splice_from(struct pipe_inode_info *pipe, struct file *out,
7f207e10
AM
235
236 return splice_write(pipe, out, ppos, len, flags);
237 }
238+EXPORT_SYMBOL(do_splice_from);
239
240 /*
241 * Attempt to initiate a splice from a file to a pipe.
7eafdf33 242@@ -1134,6 +1135,7 @@ long do_splice_to(struct file *in, loff_t *ppos,
7f207e10
AM
243
244 return splice_read(in, ppos, pipe, len, flags);
245 }
246+EXPORT_SYMBOL(do_splice_to);
247
248 /**
249 * splice_direct_to_actor - splices data directly between two non-pipes
250diff --git a/security/commoncap.c b/security/commoncap.c
92d182d2 251index 71a166a..5d63aac 100644
7f207e10
AM
252--- a/security/commoncap.c
253+++ b/security/commoncap.c
92d182d2 254@@ -972,3 +972,4 @@ int cap_file_mmap(struct file *file, unsigned long reqprot,
94337f0d 255 }
7f207e10
AM
256 return ret;
257 }
258+EXPORT_SYMBOL(cap_file_mmap);
259diff --git a/security/device_cgroup.c b/security/device_cgroup.c
92d182d2 260index c43a332..0c37289 100644
7f207e10
AM
261--- a/security/device_cgroup.c
262+++ b/security/device_cgroup.c
f6c5ef8b
AM
263@@ -7,6 +7,7 @@
264 #include <linux/device_cgroup.h>
265 #include <linux/cgroup.h>
266 #include <linux/ctype.h>
267+#include <linux/export.h>
268 #include <linux/list.h>
269 #include <linux/uaccess.h>
270 #include <linux/seq_file.h>
92d182d2 271@@ -499,6 +500,7 @@ found:
7f207e10
AM
272
273 return -EPERM;
274 }
2cbb1c4b 275+EXPORT_SYMBOL(__devcgroup_inode_permission);
7f207e10
AM
276
277 int devcgroup_inode_mknod(int mode, dev_t dev)
278 {
279diff --git a/security/security.c b/security/security.c
92d182d2 280index bf619ff..60b996a 100644
7f207e10
AM
281--- a/security/security.c
282+++ b/security/security.c
92d182d2 283@@ -380,6 +380,7 @@ int security_path_rmdir(struct path *dir, struct dentry *dentry)
7f207e10
AM
284 return 0;
285 return security_ops->path_rmdir(dir, dentry);
286 }
287+EXPORT_SYMBOL(security_path_rmdir);
288
289 int security_path_unlink(struct path *dir, struct dentry *dentry)
290 {
92d182d2 291@@ -396,6 +397,7 @@ int security_path_symlink(struct path *dir, struct dentry *dentry,
7f207e10
AM
292 return 0;
293 return security_ops->path_symlink(dir, dentry, old_name);
294 }
295+EXPORT_SYMBOL(security_path_symlink);
296
297 int security_path_link(struct dentry *old_dentry, struct path *new_dir,
298 struct dentry *new_dentry)
92d182d2 299@@ -404,6 +406,7 @@ int security_path_link(struct dentry *old_dentry, struct path *new_dir,
7f207e10
AM
300 return 0;
301 return security_ops->path_link(old_dentry, new_dir, new_dentry);
302 }
303+EXPORT_SYMBOL(security_path_link);
304
305 int security_path_rename(struct path *old_dir, struct dentry *old_dentry,
306 struct path *new_dir, struct dentry *new_dentry)
92d182d2 307@@ -422,6 +425,7 @@ int security_path_truncate(struct path *path)
7f207e10
AM
308 return 0;
309 return security_ops->path_truncate(path);
310 }
311+EXPORT_SYMBOL(security_path_truncate);
312
7eafdf33
AM
313 int security_path_chmod(struct path *path, umode_t mode)
314 {
92d182d2 315@@ -429,6 +433,7 @@ int security_path_chmod(struct path *path, umode_t mode)
7f207e10 316 return 0;
7eafdf33 317 return security_ops->path_chmod(path, mode);
7f207e10
AM
318 }
319+EXPORT_SYMBOL(security_path_chmod);
320
321 int security_path_chown(struct path *path, uid_t uid, gid_t gid)
322 {
92d182d2 323@@ -436,6 +441,7 @@ int security_path_chown(struct path *path, uid_t uid, gid_t gid)
7f207e10
AM
324 return 0;
325 return security_ops->path_chown(path, uid, gid);
326 }
327+EXPORT_SYMBOL(security_path_chown);
328
329 int security_path_chroot(struct path *path)
330 {
92d182d2 331@@ -512,6 +518,7 @@ int security_inode_readlink(struct dentry *dentry)
7f207e10
AM
332 return 0;
333 return security_ops->inode_readlink(dentry);
334 }
335+EXPORT_SYMBOL(security_inode_readlink);
336
337 int security_inode_follow_link(struct dentry *dentry, struct nameidata *nd)
338 {
92d182d2 339@@ -526,6 +533,7 @@ int security_inode_permission(struct inode *inode, int mask)
7f207e10 340 return 0;
1e00d052 341 return security_ops->inode_permission(inode, mask);
7f207e10
AM
342 }
343+EXPORT_SYMBOL(security_inode_permission);
344
1e00d052 345 int security_inode_setattr(struct dentry *dentry, struct iattr *attr)
7f207e10 346 {
92d182d2 347@@ -641,6 +649,7 @@ int security_file_permission(struct file *file, int mask)
7f207e10
AM
348
349 return fsnotify_perm(file, mask);
350 }
351+EXPORT_SYMBOL(security_file_permission);
352
353 int security_file_alloc(struct file *file)
354 {
92d182d2 355@@ -668,6 +677,7 @@ int security_file_mmap(struct file *file, unsigned long reqprot,
7f207e10
AM
356 return ret;
357 return ima_file_mmap(file, prot);
358 }
359+EXPORT_SYMBOL(security_file_mmap);
360
361 int security_file_mprotect(struct vm_area_struct *vma, unsigned long reqprot,
362 unsigned long prot)
363diff -urN /usr/share/empty/Documentation/ABI/testing/debugfs-aufs linux/Documentation/ABI/testing/debugfs-aufs
364--- /usr/share/empty/Documentation/ABI/testing/debugfs-aufs 1970-01-01 01:00:00.000000000 +0100
7ce627cf 365+++ linux/Documentation/ABI/testing/debugfs-aufs 2012-05-22 09:06:08.864125478 +0200
7f207e10
AM
366@@ -0,0 +1,37 @@
367+What: /debug/aufs/si_<id>/
368+Date: March 2009
369+Contact: J. R. Okajima <hooanon05@yahoo.co.jp>
370+Description:
371+ Under /debug/aufs, a directory named si_<id> is created
372+ per aufs mount, where <id> is a unique id generated
373+ internally.
1facf9fc 374+
7f207e10
AM
375+What: /debug/aufs/si_<id>/xib
376+Date: March 2009
377+Contact: J. R. Okajima <hooanon05@yahoo.co.jp>
378+Description:
379+ It shows the consumed blocks by xib (External Inode Number
380+ Bitmap), its block size and file size.
381+ When the aufs mount option 'noxino' is specified, it
382+ will be empty. About XINO files, see the aufs manual.
383+
384+What: /debug/aufs/si_<id>/xino0, xino1 ... xinoN
385+Date: March 2009
386+Contact: J. R. Okajima <hooanon05@yahoo.co.jp>
387+Description:
388+ It shows the consumed blocks by xino (External Inode Number
389+ Translation Table), its link count, block size and file
390+ size.
391+ When the aufs mount option 'noxino' is specified, it
392+ will be empty. About XINO files, see the aufs manual.
393+
394+What: /debug/aufs/si_<id>/xigen
395+Date: March 2009
396+Contact: J. R. Okajima <hooanon05@yahoo.co.jp>
397+Description:
398+ It shows the consumed blocks by xigen (External Inode
399+ Generation Table), its block size and file size.
400+ If CONFIG_AUFS_EXPORT is disabled, this entry will not
401+ be created.
402+ When the aufs mount option 'noxino' is specified, it
403+ will be empty. About XINO files, see the aufs manual.
404diff -urN /usr/share/empty/Documentation/ABI/testing/sysfs-aufs linux/Documentation/ABI/testing/sysfs-aufs
405--- /usr/share/empty/Documentation/ABI/testing/sysfs-aufs 1970-01-01 01:00:00.000000000 +0100
7ce627cf 406+++ linux/Documentation/ABI/testing/sysfs-aufs 2012-05-22 09:06:08.864125478 +0200
7f207e10
AM
407@@ -0,0 +1,24 @@
408+What: /sys/fs/aufs/si_<id>/
409+Date: March 2009
410+Contact: J. R. Okajima <hooanon05@yahoo.co.jp>
411+Description:
412+ Under /sys/fs/aufs, a directory named si_<id> is created
413+ per aufs mount, where <id> is a unique id generated
414+ internally.
415+
416+What: /sys/fs/aufs/si_<id>/br0, br1 ... brN
417+Date: March 2009
418+Contact: J. R. Okajima <hooanon05@yahoo.co.jp>
419+Description:
420+ It shows the abolute path of a member directory (which
421+ is called branch) in aufs, and its permission.
422+
423+What: /sys/fs/aufs/si_<id>/xi_path
424+Date: March 2009
425+Contact: J. R. Okajima <hooanon05@yahoo.co.jp>
426+Description:
427+ It shows the abolute path of XINO (External Inode Number
428+ Bitmap, Translation Table and Generation Table) file
429+ even if it is the default path.
430+ When the aufs mount option 'noxino' is specified, it
431+ will be empty. About XINO files, see the aufs manual.
53392da6
AM
432diff -urN /usr/share/empty/Documentation/filesystems/aufs/design/01intro.txt linux/Documentation/filesystems/aufs/design/01intro.txt
433--- /usr/share/empty/Documentation/filesystems/aufs/design/01intro.txt 1970-01-01 01:00:00.000000000 +0100
7ce627cf 434+++ linux/Documentation/filesystems/aufs/design/01intro.txt 2012-05-22 09:06:08.864125478 +0200
53392da6
AM
435@@ -0,0 +1,162 @@
436+
437+# Copyright (C) 2005-2011 Junjiro R. Okajima
438+#
439+# This program is free software; you can redistribute it and/or modify
440+# it under the terms of the GNU General Public License as published by
441+# the Free Software Foundation; either version 2 of the License, or
442+# (at your option) any later version.
443+#
444+# This program is distributed in the hope that it will be useful,
445+# but WITHOUT ANY WARRANTY; without even the implied warranty of
446+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
447+# GNU General Public License for more details.
448+#
449+# You should have received a copy of the GNU General Public License
450+# along with this program; if not, write to the Free Software
451+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
452+
453+Introduction
454+----------------------------------------
455+
456+aufs [ei ju: ef es] | [a u f s]
457+1. abbrev. for "advanced multi-layered unification filesystem".
458+2. abbrev. for "another unionfs".
459+3. abbrev. for "auf das" in German which means "on the" in English.
460+ Ex. "Butter aufs Brot"(G) means "butter onto bread"(E).
461+ But "Filesystem aufs Filesystem" is hard to understand.
462+
463+AUFS is a filesystem with features:
464+- multi layered stackable unification filesystem, the member directory
465+ is called as a branch.
466+- branch permission and attribute, 'readonly', 'real-readonly',
467+ 'readwrite', 'whiteout-able', 'link-able whiteout' and their
468+ combination.
469+- internal "file copy-on-write".
470+- logical deletion, whiteout.
471+- dynamic branch manipulation, adding, deleting and changing permission.
472+- allow bypassing aufs, user's direct branch access.
473+- external inode number translation table and bitmap which maintains the
474+ persistent aufs inode number.
475+- seekable directory, including NFS readdir.
476+- file mapping, mmap and sharing pages.
477+- pseudo-link, hardlink over branches.
478+- loopback mounted filesystem as a branch.
479+- several policies to select one among multiple writable branches.
480+- revert a single systemcall when an error occurs in aufs.
481+- and more...
482+
483+
484+Multi Layered Stackable Unification Filesystem
485+----------------------------------------------------------------------
486+Most people already knows what it is.
487+It is a filesystem which unifies several directories and provides a
488+merged single directory. When users access a file, the access will be
489+passed/re-directed/converted (sorry, I am not sure which English word is
490+correct) to the real file on the member filesystem. The member
491+filesystem is called 'lower filesystem' or 'branch' and has a mode
492+'readonly' and 'readwrite.' And the deletion for a file on the lower
493+readonly branch is handled by creating 'whiteout' on the upper writable
494+branch.
495+
496+On LKML, there have been discussions about UnionMount (Jan Blunck,
497+Bharata B Rao and Valerie Aurora) and Unionfs (Erez Zadok). They took
498+different approaches to implement the merged-view.
499+The former tries putting it into VFS, and the latter implements as a
500+separate filesystem.
501+(If I misunderstand about these implementations, please let me know and
502+I shall correct it. Because it is a long time ago when I read their
503+source files last time).
504+
505+UnionMount's approach will be able to small, but may be hard to share
506+branches between several UnionMount since the whiteout in it is
507+implemented in the inode on branch filesystem and always
508+shared. According to Bharata's post, readdir does not seems to be
509+finished yet.
510+There are several missing features known in this implementations such as
511+- for users, the inode number may change silently. eg. copy-up.
512+- link(2) may break by copy-up.
513+- read(2) may get an obsoleted filedata (fstat(2) too).
514+- fcntl(F_SETLK) may be broken by copy-up.
515+- unnecessary copy-up may happen, for example mmap(MAP_PRIVATE) after
516+ open(O_RDWR).
517+
518+Unionfs has a longer history. When I started implementing a stacking filesystem
519+(Aug 2005), it already existed. It has virtual super_block, inode,
520+dentry and file objects and they have an array pointing lower same kind
521+objects. After contributing many patches for Unionfs, I re-started my
522+project AUFS (Jun 2006).
523+
524+In AUFS, the structure of filesystem resembles to Unionfs, but I
525+implemented my own ideas, approaches and enhancements and it became
526+totally different one.
527+
528+Comparing DM snapshot and fs based implementation
529+- the number of bytes to be copied between devices is much smaller.
530+- the type of filesystem must be one and only.
531+- the fs must be writable, no readonly fs, even for the lower original
532+ device. so the compression fs will not be usable. but if we use
533+ loopback mount, we may address this issue.
534+ for instance,
535+ mount /cdrom/squashfs.img /sq
536+ losetup /sq/ext2.img
537+ losetup /somewhere/cow
538+ dmsetup "snapshot /dev/loop0 /dev/loop1 ..."
539+- it will be difficult (or needs more operations) to extract the
540+ difference between the original device and COW.
541+- DM snapshot-merge may help a lot when users try merging. in the
542+ fs-layer union, users will use rsync(1).
543+
544+
545+Several characters/aspects of aufs
546+----------------------------------------------------------------------
547+
548+Aufs has several characters or aspects.
549+1. a filesystem, callee of VFS helper
550+2. sub-VFS, caller of VFS helper for branches
551+3. a virtual filesystem which maintains persistent inode number
552+4. reader/writer of files on branches such like an application
553+
554+1. Callee of VFS Helper
555+As an ordinary linux filesystem, aufs is a callee of VFS. For instance,
556+unlink(2) from an application reaches sys_unlink() kernel function and
557+then vfs_unlink() is called. vfs_unlink() is one of VFS helper and it
558+calls filesystem specific unlink operation. Actually aufs implements the
559+unlink operation but it behaves like a redirector.
560+
561+2. Caller of VFS Helper for Branches
562+aufs_unlink() passes the unlink request to the branch filesystem as if
563+it were called from VFS. So the called unlink operation of the branch
564+filesystem acts as usual. As a caller of VFS helper, aufs should handle
565+every necessary pre/post operation for the branch filesystem.
566+- acquire the lock for the parent dir on a branch
567+- lookup in a branch
568+- revalidate dentry on a branch
569+- mnt_want_write() for a branch
570+- vfs_unlink() for a branch
571+- mnt_drop_write() for a branch
572+- release the lock on a branch
573+
574+3. Persistent Inode Number
575+One of the most important issue for a filesystem is to maintain inode
576+numbers. This is particularly important to support exporting a
577+filesystem via NFS. Aufs is a virtual filesystem which doesn't have a
578+backend block device for its own. But some storage is necessary to
579+maintain inode number. It may be a large space and may not suit to keep
580+in memory. Aufs rents some space from its first writable branch
581+filesystem (by default) and creates file(s) on it. These files are
582+created by aufs internally and removed soon (currently) keeping opened.
583+Note: Because these files are removed, they are totally gone after
584+ unmounting aufs. It means the inode numbers are not persistent
585+ across unmount or reboot. I have a plan to make them really
586+ persistent which will be important for aufs on NFS server.
587+
588+4. Read/Write Files Internally (copy-on-write)
589+Because a branch can be readonly, when you write a file on it, aufs will
590+"copy-up" it to the upper writable branch internally. And then write the
591+originally requested thing to the file. Generally kernel doesn't
592+open/read/write file actively. In aufs, even a single write may cause a
593+internal "file copy". This behaviour is very similar to cp(1) command.
594+
595+Some people may think it is better to pass such work to user space
596+helper, instead of doing in kernel space. Actually I am still thinking
597+about it. But currently I have implemented it in kernel space.
598diff -urN /usr/share/empty/Documentation/filesystems/aufs/design/02struct.txt linux/Documentation/filesystems/aufs/design/02struct.txt
599--- /usr/share/empty/Documentation/filesystems/aufs/design/02struct.txt 1970-01-01 01:00:00.000000000 +0100
7ce627cf 600+++ linux/Documentation/filesystems/aufs/design/02struct.txt 2012-05-22 09:06:08.864125478 +0200
53392da6
AM
601@@ -0,0 +1,226 @@
602+
603+# Copyright (C) 2005-2011 Junjiro R. Okajima
604+#
605+# This program is free software; you can redistribute it and/or modify
606+# it under the terms of the GNU General Public License as published by
607+# the Free Software Foundation; either version 2 of the License, or
608+# (at your option) any later version.
609+#
610+# This program is distributed in the hope that it will be useful,
611+# but WITHOUT ANY WARRANTY; without even the implied warranty of
612+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
613+# GNU General Public License for more details.
614+#
615+# You should have received a copy of the GNU General Public License
616+# along with this program; if not, write to the Free Software
617+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
618+
619+Basic Aufs Internal Structure
620+
621+Superblock/Inode/Dentry/File Objects
622+----------------------------------------------------------------------
623+As like an ordinary filesystem, aufs has its own
624+superblock/inode/dentry/file objects. All these objects have a
625+dynamically allocated array and store the same kind of pointers to the
626+lower filesystem, branch.
627+For example, when you build a union with one readwrite branch and one
628+readonly, mounted /au, /rw and /ro respectively.
629+- /au = /rw + /ro
630+- /ro/fileA exists but /rw/fileA
631+
632+Aufs lookup operation finds /ro/fileA and gets dentry for that. These
633+pointers are stored in a aufs dentry. The array in aufs dentry will be,
634+- [0] = NULL
635+- [1] = /ro/fileA
636+
637+This style of an array is essentially same to the aufs
638+superblock/inode/dentry/file objects.
639+
640+Because aufs supports manipulating branches, ie. add/delete/change
641+dynamically, these objects has its own generation. When branches are
642+changed, the generation in aufs superblock is incremented. And a
643+generation in other object are compared when it is accessed.
644+When a generation in other objects are obsoleted, aufs refreshes the
645+internal array.
646+
647+
648+Superblock
649+----------------------------------------------------------------------
650+Additionally aufs superblock has some data for policies to select one
651+among multiple writable branches, XIB files, pseudo-links and kobject.
652+See below in detail.
653+About the policies which supports copy-down a directory, see policy.txt
654+too.
655+
656+
657+Branch and XINO(External Inode Number Translation Table)
658+----------------------------------------------------------------------
659+Every branch has its own xino (external inode number translation table)
660+file. The xino file is created and unlinked by aufs internally. When two
661+members of a union exist on the same filesystem, they share the single
662+xino file.
663+The struct of a xino file is simple, just a sequence of aufs inode
664+numbers which is indexed by the lower inode number.
665+In the above sample, assume the inode number of /ro/fileA is i111 and
666+aufs assigns the inode number i999 for fileA. Then aufs writes 999 as
667+4(8) bytes at 111 * 4(8) bytes offset in the xino file.
668+
669+When the inode numbers are not contiguous, the xino file will be sparse
670+which has a hole in it and doesn't consume as much disk space as it
671+might appear. If your branch filesystem consumes disk space for such
672+holes, then you should specify 'xino=' option at mounting aufs.
673+
674+Also a writable branch has three kinds of "whiteout bases". All these
675+are existed when the branch is joined to aufs and the names are
676+whiteout-ed doubly, so that users will never see their names in aufs
677+hierarchy.
678+1. a regular file which will be linked to all whiteouts.
679+2. a directory to store a pseudo-link.
680+3. a directory to store an "orphan-ed" file temporary.
681+
682+1. Whiteout Base
683+ When you remove a file on a readonly branch, aufs handles it as a
684+ logical deletion and creates a whiteout on the upper writable branch
685+ as a hardlink of this file in order not to consume inode on the
686+ writable branch.
687+2. Pseudo-link Dir
688+ See below, Pseudo-link.
689+3. Step-Parent Dir
690+ When "fileC" exists on the lower readonly branch only and it is
691+ opened and removed with its parent dir, and then user writes
692+ something into it, then aufs copies-up fileC to this
693+ directory. Because there is no other dir to store fileC. After
694+ creating a file under this dir, the file is unlinked.
695+
696+Because aufs supports manipulating branches, ie. add/delete/change
697+dynamically, a branch has its own id. When the branch order changes, aufs
698+finds the new index by searching the branch id.
699+
700+
701+Pseudo-link
702+----------------------------------------------------------------------
703+Assume "fileA" exists on the lower readonly branch only and it is
704+hardlinked to "fileB" on the branch. When you write something to fileA,
705+aufs copies-up it to the upper writable branch. Additionally aufs
706+creates a hardlink under the Pseudo-link Directory of the writable
707+branch. The inode of a pseudo-link is kept in aufs super_block as a
708+simple list. If fileB is read after unlinking fileA, aufs returns
709+filedata from the pseudo-link instead of the lower readonly
710+branch. Because the pseudo-link is based upon the inode, to keep the
711+inode number by xino (see above) is important.
712+
713+All the hardlinks under the Pseudo-link Directory of the writable branch
714+should be restored in a proper location later. Aufs provides a utility
715+to do this. The userspace helpers executed at remounting and unmounting
716+aufs by default.
717+During this utility is running, it puts aufs into the pseudo-link
718+maintenance mode. In this mode, only the process which began the
719+maintenance mode (and its child processes) is allowed to operate in
720+aufs. Some other processes which are not related to the pseudo-link will
721+be allowed to run too, but the rest have to return an error or wait
722+until the maintenance mode ends. If a process already acquires an inode
723+mutex (in VFS), it has to return an error.
724+
725+
726+XIB(external inode number bitmap)
727+----------------------------------------------------------------------
728+Addition to the xino file per a branch, aufs has an external inode number
729+bitmap in a superblock object. It is also a file such like a xino file.
730+It is a simple bitmap to mark whether the aufs inode number is in-use or
731+not.
732+To reduce the file I/O, aufs prepares a single memory page to cache xib.
733+
734+Aufs implements a feature to truncate/refresh both of xino and xib to
735+reduce the number of consumed disk blocks for these files.
736+
737+
738+Virtual or Vertical Dir, and Readdir in Userspace
739+----------------------------------------------------------------------
740+In order to support multiple layers (branches), aufs readdir operation
741+constructs a virtual dir block on memory. For readdir, aufs calls
742+vfs_readdir() internally for each dir on branches, merges their entries
743+with eliminating the whiteout-ed ones, and sets it to file (dir)
744+object. So the file object has its entry list until it is closed. The
745+entry list will be updated when the file position is zero and becomes
746+old. This decision is made in aufs automatically.
747+
748+The dynamically allocated memory block for the name of entries has a
749+unit of 512 bytes (by default) and stores the names contiguously (no
750+padding). Another block for each entry is handled by kmem_cache too.
751+During building dir blocks, aufs creates hash list and judging whether
752+the entry is whiteouted by its upper branch or already listed.
753+The merged result is cached in the corresponding inode object and
754+maintained by a customizable life-time option.
755+
756+Some people may call it can be a security hole or invite DoS attack
757+since the opened and once readdir-ed dir (file object) holds its entry
758+list and becomes a pressure for system memory. But I'd say it is similar
759+to files under /proc or /sys. The virtual files in them also holds a
760+memory page (generally) while they are opened. When an idea to reduce
761+memory for them is introduced, it will be applied to aufs too.
762+For those who really hate this situation, I've developed readdir(3)
763+library which operates this merging in userspace. You just need to set
764+LD_PRELOAD environment variable, and aufs will not consume no memory in
765+kernel space for readdir(3).
766+
767+
768+Workqueue
769+----------------------------------------------------------------------
770+Aufs sometimes requires privilege access to a branch. For instance,
771+in copy-up/down operation. When a user process is going to make changes
772+to a file which exists in the lower readonly branch only, and the mode
773+of one of ancestor directories may not be writable by a user
774+process. Here aufs copy-up the file with its ancestors and they may
775+require privilege to set its owner/group/mode/etc.
776+This is a typical case of a application character of aufs (see
777+Introduction).
778+
779+Aufs uses workqueue synchronously for this case. It creates its own
780+workqueue. The workqueue is a kernel thread and has privilege. Aufs
781+passes the request to call mkdir or write (for example), and wait for
782+its completion. This approach solves a problem of a signal handler
783+simply.
784+If aufs didn't adopt the workqueue and changed the privilege of the
785+process, and if the mkdir/write call arises SIGXFSZ or other signal,
786+then the user process might gain a privilege or the generated core file
787+was owned by a superuser.
788+
789+Also aufs uses the system global workqueue ("events" kernel thread) too
790+for asynchronous tasks, such like handling inotify/fsnotify, re-creating a
791+whiteout base and etc. This is unrelated to a privilege.
792+Most of aufs operation tries acquiring a rw_semaphore for aufs
793+superblock at the beginning, at the same time waits for the completion
794+of all queued asynchronous tasks.
795+
796+
797+Whiteout
798+----------------------------------------------------------------------
799+The whiteout in aufs is very similar to Unionfs's. That is represented
800+by its filename. UnionMount takes an approach of a file mode, but I am
801+afraid several utilities (find(1) or something) will have to support it.
802+
803+Basically the whiteout represents "logical deletion" which stops aufs to
804+lookup further, but also it represents "dir is opaque" which also stop
805+lookup.
806+
807+In aufs, rmdir(2) and rename(2) for dir uses whiteout alternatively.
808+In order to make several functions in a single systemcall to be
809+revertible, aufs adopts an approach to rename a directory to a temporary
810+unique whiteouted name.
811+For example, in rename(2) dir where the target dir already existed, aufs
812+renames the target dir to a temporary unique whiteouted name before the
813+actual rename on a branch and then handles other actions (make it opaque,
814+update the attributes, etc). If an error happens in these actions, aufs
815+simply renames the whiteouted name back and returns an error. If all are
816+succeeded, aufs registers a function to remove the whiteouted unique
817+temporary name completely and asynchronously to the system global
818+workqueue.
819+
820+
821+Copy-up
822+----------------------------------------------------------------------
823+It is a well-known feature or concept.
824+When user modifies a file on a readonly branch, aufs operate "copy-up"
825+internally and makes change to the new file on the upper writable branch.
826+When the trigger systemcall does not update the timestamps of the parent
827+dir, aufs reverts it after copy-up.
828diff -urN /usr/share/empty/Documentation/filesystems/aufs/design/03lookup.txt linux/Documentation/filesystems/aufs/design/03lookup.txt
829--- /usr/share/empty/Documentation/filesystems/aufs/design/03lookup.txt 1970-01-01 01:00:00.000000000 +0100
7ce627cf 830+++ linux/Documentation/filesystems/aufs/design/03lookup.txt 2012-05-22 09:06:08.864125478 +0200
53392da6
AM
831@@ -0,0 +1,106 @@
832+
833+# Copyright (C) 2005-2011 Junjiro R. Okajima
834+#
835+# This program is free software; you can redistribute it and/or modify
836+# it under the terms of the GNU General Public License as published by
837+# the Free Software Foundation; either version 2 of the License, or
838+# (at your option) any later version.
839+#
840+# This program is distributed in the hope that it will be useful,
841+# but WITHOUT ANY WARRANTY; without even the implied warranty of
842+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
843+# GNU General Public License for more details.
844+#
845+# You should have received a copy of the GNU General Public License
846+# along with this program; if not, write to the Free Software
847+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
848+
849+Lookup in a Branch
850+----------------------------------------------------------------------
851+Since aufs has a character of sub-VFS (see Introduction), it operates
852+lookup for branches as VFS does. It may be a heavy work. Generally
853+speaking struct nameidata is a bigger structure and includes many
854+information. But almost all lookup operation in aufs is the simplest
855+case, ie. lookup only an entry directly connected to its parent. Digging
856+down the directory hierarchy is unnecessary.
857+
858+VFS has a function lookup_one_len() for that use, but it is not usable
859+for a branch filesystem which requires struct nameidata. So aufs
860+implements a simple lookup wrapper function. When a branch filesystem
861+allows NULL as nameidata, it calls lookup_one_len(). Otherwise it builds
862+a simplest nameidata and calls lookup_hash().
863+Here aufs applies "a principle in NFSD", ie. if the filesystem supports
864+NFS-export, then it has to support NULL as a nameidata parameter for
865+->create(), ->lookup() and ->d_revalidate(). So the lookup wrapper in
866+aufs tests if ->s_export_op in the branch is NULL or not.
867+
868+When a branch is a remote filesystem, aufs basically trusts its
869+->d_revalidate(), also aufs forces the hardest revalidate tests for
870+them.
871+For d_revalidate, aufs implements three levels of revalidate tests. See
872+"Revalidate Dentry and UDBA" in detail.
873+
874+
875+Loopback Mount
876+----------------------------------------------------------------------
877+Basically aufs supports any type of filesystem and block device for a
878+branch (actually there are some exceptions). But it is prohibited to add
879+a loopback mounted one whose backend file exists in a filesystem which is
880+already added to aufs. The reason is to protect aufs from a recursive
881+lookup. If it was allowed, the aufs lookup operation might re-enter a
882+lookup for the loopback mounted branch in the same context, and will
883+cause a deadlock.
884+
885+
886+Revalidate Dentry and UDBA (User's Direct Branch Access)
887+----------------------------------------------------------------------
888+Generally VFS helpers re-validate a dentry as a part of lookup.
889+0. digging down the directory hierarchy.
890+1. lock the parent dir by its i_mutex.
891+2. lookup the final (child) entry.
892+3. revalidate it.
893+4. call the actual operation (create, unlink, etc.)
894+5. unlock the parent dir
895+
896+If the filesystem implements its ->d_revalidate() (step 3), then it is
897+called. Actually aufs implements it and checks the dentry on a branch is
898+still valid.
899+But it is not enough. Because aufs has to release the lock for the
900+parent dir on a branch at the end of ->lookup() (step 2) and
901+->d_revalidate() (step 3) while the i_mutex of the aufs dir is still
902+held by VFS.
903+If the file on a branch is changed directly, eg. bypassing aufs, after
904+aufs released the lock, then the subsequent operation may cause
905+something unpleasant result.
906+
907+This situation is a result of VFS architecture, ->lookup() and
908+->d_revalidate() is separated. But I never say it is wrong. It is a good
909+design from VFS's point of view. It is just not suitable for sub-VFS
910+character in aufs.
911+
912+Aufs supports such case by three level of revalidation which is
913+selectable by user.
914+1. Simple Revalidate
915+ Addition to the native flow in VFS's, confirm the child-parent
916+ relationship on the branch just after locking the parent dir on the
917+ branch in the "actual operation" (step 4). When this validation
918+ fails, aufs returns EBUSY. ->d_revalidate() (step 3) in aufs still
919+ checks the validation of the dentry on branches.
920+2. Monitor Changes Internally by Inotify/Fsnotify
921+ Addition to above, in the "actual operation" (step 4) aufs re-lookup
922+ the dentry on the branch, and returns EBUSY if it finds different
923+ dentry.
924+ Additionally, aufs sets the inotify/fsnotify watch for every dir on branches
925+ during it is in cache. When the event is notified, aufs registers a
926+ function to kernel 'events' thread by schedule_work(). And the
927+ function sets some special status to the cached aufs dentry and inode
928+ private data. If they are not cached, then aufs has nothing to
929+ do. When the same file is accessed through aufs (step 0-3) later,
930+ aufs will detect the status and refresh all necessary data.
931+ In this mode, aufs has to ignore the event which is fired by aufs
932+ itself.
933+3. No Extra Validation
934+ This is the simplest test and doesn't add any additional revalidation
935+ test, and skip therevalidatin in step 4. It is useful and improves
936+ aufs performance when system surely hide the aufs branches from user,
937+ by over-mounting something (or another method).
938diff -urN /usr/share/empty/Documentation/filesystems/aufs/design/04branch.txt linux/Documentation/filesystems/aufs/design/04branch.txt
939--- /usr/share/empty/Documentation/filesystems/aufs/design/04branch.txt 1970-01-01 01:00:00.000000000 +0100
7ce627cf 940+++ linux/Documentation/filesystems/aufs/design/04branch.txt 2012-05-22 09:06:08.864125478 +0200
53392da6
AM
941@@ -0,0 +1,76 @@
942+
943+# Copyright (C) 2005-2011 Junjiro R. Okajima
944+#
945+# This program is free software; you can redistribute it and/or modify
946+# it under the terms of the GNU General Public License as published by
947+# the Free Software Foundation; either version 2 of the License, or
948+# (at your option) any later version.
949+#
950+# This program is distributed in the hope that it will be useful,
951+# but WITHOUT ANY WARRANTY; without even the implied warranty of
952+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
953+# GNU General Public License for more details.
954+#
955+# You should have received a copy of the GNU General Public License
956+# along with this program; if not, write to the Free Software
957+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
958+
959+Branch Manipulation
960+
961+Since aufs supports dynamic branch manipulation, ie. add/remove a branch
962+and changing its permission/attribute, there are a lot of works to do.
963+
964+
965+Add a Branch
966+----------------------------------------------------------------------
967+o Confirm the adding dir exists outside of aufs, including loopback
968+ mount.
969+- and other various attributes...
970+o Initialize the xino file and whiteout bases if necessary.
971+ See struct.txt.
972+
973+o Check the owner/group/mode of the directory
974+ When the owner/group/mode of the adding directory differs from the
975+ existing branch, aufs issues a warning because it may impose a
976+ security risk.
977+ For example, when a upper writable branch has a world writable empty
978+ top directory, a malicious user can create any files on the writable
979+ branch directly, like copy-up and modify manually. If something like
980+ /etc/{passwd,shadow} exists on the lower readonly branch but the upper
981+ writable branch, and the writable branch is world-writable, then a
982+ malicious guy may create /etc/passwd on the writable branch directly
983+ and the infected file will be valid in aufs.
984+ I am afraid it can be a security issue, but nothing to do except
985+ producing a warning.
986+
987+
988+Delete a Branch
989+----------------------------------------------------------------------
990+o Confirm the deleting branch is not busy
991+ To be general, there is one merit to adopt "remount" interface to
992+ manipulate branches. It is to discard caches. At deleting a branch,
993+ aufs checks the still cached (and connected) dentries and inodes. If
994+ there are any, then they are all in-use. An inode without its
995+ corresponding dentry can be alive alone (for example, inotify/fsnotify case).
996+
997+ For the cached one, aufs checks whether the same named entry exists on
998+ other branches.
999+ If the cached one is a directory, because aufs provides a merged view
1000+ to users, as long as one dir is left on any branch aufs can show the
1001+ dir to users. In this case, the branch can be removed from aufs.
1002+ Otherwise aufs rejects deleting the branch.
1003+
1004+ If any file on the deleting branch is opened by aufs, then aufs
1005+ rejects deleting.
1006+
1007+
1008+Modify the Permission of a Branch
1009+----------------------------------------------------------------------
1010+o Re-initialize or remove the xino file and whiteout bases if necessary.
1011+ See struct.txt.
1012+
1013+o rw --> ro: Confirm the modifying branch is not busy
1014+ Aufs rejects the request if any of these conditions are true.
1015+ - a file on the branch is mmap-ed.
1016+ - a regular file on the branch is opened for write and there is no
1017+ same named entry on the upper branch.
1018diff -urN /usr/share/empty/Documentation/filesystems/aufs/design/05wbr_policy.txt linux/Documentation/filesystems/aufs/design/05wbr_policy.txt
1019--- /usr/share/empty/Documentation/filesystems/aufs/design/05wbr_policy.txt 1970-01-01 01:00:00.000000000 +0100
7ce627cf 1020+++ linux/Documentation/filesystems/aufs/design/05wbr_policy.txt 2012-05-22 09:06:08.864125478 +0200
53392da6
AM
1021@@ -0,0 +1,65 @@
1022+
1023+# Copyright (C) 2005-2011 Junjiro R. Okajima
1024+#
1025+# This program is free software; you can redistribute it and/or modify
1026+# it under the terms of the GNU General Public License as published by
1027+# the Free Software Foundation; either version 2 of the License, or
1028+# (at your option) any later version.
1029+#
1030+# This program is distributed in the hope that it will be useful,
1031+# but WITHOUT ANY WARRANTY; without even the implied warranty of
1032+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1033+# GNU General Public License for more details.
1034+#
1035+# You should have received a copy of the GNU General Public License
1036+# along with this program; if not, write to the Free Software
1037+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1038+
1039+Policies to Select One among Multiple Writable Branches
1040+----------------------------------------------------------------------
1041+When the number of writable branch is more than one, aufs has to decide
1042+the target branch for file creation or copy-up. By default, the highest
1043+writable branch which has the parent (or ancestor) dir of the target
1044+file is chosen (top-down-parent policy).
1045+By user's request, aufs implements some other policies to select the
1046+writable branch, for file creation two policies, round-robin and
1047+most-free-space policies. For copy-up three policies, top-down-parent,
1048+bottom-up-parent and bottom-up policies.
1049+
1050+As expected, the round-robin policy selects the branch in circular. When
1051+you have two writable branches and creates 10 new files, 5 files will be
1052+created for each branch. mkdir(2) systemcall is an exception. When you
1053+create 10 new directories, all will be created on the same branch.
1054+And the most-free-space policy selects the one which has most free
1055+space among the writable branches. The amount of free space will be
1056+checked by aufs internally, and users can specify its time interval.
1057+
1058+The policies for copy-up is more simple,
1059+top-down-parent is equivalent to the same named on in create policy,
1060+bottom-up-parent selects the writable branch where the parent dir
1061+exists and the nearest upper one from the copyup-source,
1062+bottom-up selects the nearest upper writable branch from the
1063+copyup-source, regardless the existence of the parent dir.
1064+
1065+There are some rules or exceptions to apply these policies.
1066+- If there is a readonly branch above the policy-selected branch and
1067+ the parent dir is marked as opaque (a variation of whiteout), or the
1068+ target (creating) file is whiteout-ed on the upper readonly branch,
1069+ then the result of the policy is ignored and the target file will be
1070+ created on the nearest upper writable branch than the readonly branch.
1071+- If there is a writable branch above the policy-selected branch and
1072+ the parent dir is marked as opaque or the target file is whiteouted
1073+ on the branch, then the result of the policy is ignored and the target
1074+ file will be created on the highest one among the upper writable
1075+ branches who has diropq or whiteout. In case of whiteout, aufs removes
1076+ it as usual.
1077+- link(2) and rename(2) systemcalls are exceptions in every policy.
1078+ They try selecting the branch where the source exists as possible
1079+ since copyup a large file will take long time. If it can't be,
1080+ ie. the branch where the source exists is readonly, then they will
1081+ follow the copyup policy.
1082+- There is an exception for rename(2) when the target exists.
1083+ If the rename target exists, aufs compares the index of the branches
1084+ where the source and the target exists and selects the higher
1085+ one. If the selected branch is readonly, then aufs follows the
1086+ copyup policy.
1087diff -urN /usr/share/empty/Documentation/filesystems/aufs/design/06mmap.txt linux/Documentation/filesystems/aufs/design/06mmap.txt
1088--- /usr/share/empty/Documentation/filesystems/aufs/design/06mmap.txt 1970-01-01 01:00:00.000000000 +0100
7ce627cf 1089+++ linux/Documentation/filesystems/aufs/design/06mmap.txt 2012-05-22 09:06:08.864125478 +0200
53392da6
AM
1090@@ -0,0 +1,47 @@
1091+
1092+# Copyright (C) 2005-2011 Junjiro R. Okajima
1093+#
1094+# This program is free software; you can redistribute it and/or modify
1095+# it under the terms of the GNU General Public License as published by
1096+# the Free Software Foundation; either version 2 of the License, or
1097+# (at your option) any later version.
1098+#
1099+# This program is distributed in the hope that it will be useful,
1100+# but WITHOUT ANY WARRANTY; without even the implied warranty of
1101+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1102+# GNU General Public License for more details.
1103+#
1104+# You should have received a copy of the GNU General Public License
1105+# along with this program; if not, write to the Free Software
1106+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1107+
1108+mmap(2) -- File Memory Mapping
1109+----------------------------------------------------------------------
1110+In aufs, the file-mapped pages are handled by a branch fs directly, no
1111+interaction with aufs. It means aufs_mmap() calls the branch fs's
1112+->mmap().
1113+This approach is simple and good, but there is one problem.
1114+Under /proc, several entries show the mmap-ped files by its path (with
1115+device and inode number), and the printed path will be the path on the
1116+branch fs's instead of virtual aufs's.
1117+This is not a problem in most cases, but some utilities lsof(1) (and its
1118+user) may expect the path on aufs.
1119+
1120+To address this issue, aufs adds a new member called vm_prfile in struct
1121+vm_area_struct (and struct vm_region). The original vm_file points to
1122+the file on the branch fs in order to handle everything correctly as
1123+usual. The new vm_prfile points to a virtual file in aufs, and the
1124+show-functions in procfs refers to vm_prfile if it is set.
1125+Also we need to maintain several other places where touching vm_file
1126+such like
1127+- fork()/clone() copies vma and the reference count of vm_file is
1128+ incremented.
1129+- merging vma maintains the ref count too.
1130+
1131+This is not a good approach. It just faking the printed path. But it
1132+leaves all behaviour around f_mapping unchanged. This is surely an
1133+advantage.
1134+Actually aufs had adopted another complicated approach which calls
1135+generic_file_mmap() and handles struct vm_operations_struct. In this
1136+approach, aufs met a hard problem and I could not solve it without
1137+switching the approach.
1138diff -urN /usr/share/empty/Documentation/filesystems/aufs/design/07export.txt linux/Documentation/filesystems/aufs/design/07export.txt
1139--- /usr/share/empty/Documentation/filesystems/aufs/design/07export.txt 1970-01-01 01:00:00.000000000 +0100
7ce627cf 1140+++ linux/Documentation/filesystems/aufs/design/07export.txt 2012-05-22 09:06:08.864125478 +0200
53392da6
AM
1141@@ -0,0 +1,59 @@
1142+
1143+# Copyright (C) 2005-2011 Junjiro R. Okajima
1144+#
1145+# This program is free software; you can redistribute it and/or modify
1146+# it under the terms of the GNU General Public License as published by
1147+# the Free Software Foundation; either version 2 of the License, or
1148+# (at your option) any later version.
1149+#
1150+# This program is distributed in the hope that it will be useful,
1151+# but WITHOUT ANY WARRANTY; without even the implied warranty of
1152+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1153+# GNU General Public License for more details.
1154+#
1155+# You should have received a copy of the GNU General Public License
1156+# along with this program; if not, write to the Free Software
1157+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1158+
1159+Export Aufs via NFS
1160+----------------------------------------------------------------------
1161+Here is an approach.
1162+- like xino/xib, add a new file 'xigen' which stores aufs inode
1163+ generation.
1164+- iget_locked(): initialize aufs inode generation for a new inode, and
1165+ store it in xigen file.
1166+- destroy_inode(): increment aufs inode generation and store it in xigen
1167+ file. it is necessary even if it is not unlinked, because any data of
1168+ inode may be changed by UDBA.
1169+- encode_fh(): for a root dir, simply return FILEID_ROOT. otherwise
1170+ build file handle by
1171+ + branch id (4 bytes)
1172+ + superblock generation (4 bytes)
1173+ + inode number (4 or 8 bytes)
1174+ + parent dir inode number (4 or 8 bytes)
1175+ + inode generation (4 bytes))
1176+ + return value of exportfs_encode_fh() for the parent on a branch (4
1177+ bytes)
1178+ + file handle for a branch (by exportfs_encode_fh())
1179+- fh_to_dentry():
1180+ + find the index of a branch from its id in handle, and check it is
1181+ still exist in aufs.
1182+ + 1st level: get the inode number from handle and search it in cache.
1183+ + 2nd level: if not found, get the parent inode number from handle and
1184+ search it in cache. and then open the parent dir, find the matching
1185+ inode number by vfs_readdir() and get its name, and call
1186+ lookup_one_len() for the target dentry.
1187+ + 3rd level: if the parent dir is not cached, call
1188+ exportfs_decode_fh() for a branch and get the parent on a branch,
1189+ build a pathname of it, convert it a pathname in aufs, call
1190+ path_lookup(). now aufs gets a parent dir dentry, then handle it as
1191+ the 2nd level.
1192+ + to open the dir, aufs needs struct vfsmount. aufs keeps vfsmount
1193+ for every branch, but not itself. to get this, (currently) aufs
1194+ searches in current->nsproxy->mnt_ns list. it may not be a good
1195+ idea, but I didn't get other approach.
1196+ + test the generation of the gotten inode.
1197+- every inode operation: they may get EBUSY due to UDBA. in this case,
1198+ convert it into ESTALE for NFSD.
1199+- readdir(): call lockdep_on/off() because filldir in NFSD calls
1200+ lookup_one_len(), vfs_getattr(), encode_fh() and others.
1201diff -urN /usr/share/empty/Documentation/filesystems/aufs/design/08shwh.txt linux/Documentation/filesystems/aufs/design/08shwh.txt
1202--- /usr/share/empty/Documentation/filesystems/aufs/design/08shwh.txt 1970-01-01 01:00:00.000000000 +0100
7ce627cf 1203+++ linux/Documentation/filesystems/aufs/design/08shwh.txt 2012-05-22 09:06:08.864125478 +0200
53392da6
AM
1204@@ -0,0 +1,53 @@
1205+
1206+# Copyright (C) 2005-2011 Junjiro R. Okajima
1207+#
1208+# This program is free software; you can redistribute it and/or modify
1209+# it under the terms of the GNU General Public License as published by
1210+# the Free Software Foundation; either version 2 of the License, or
1211+# (at your option) any later version.
1212+#
1213+# This program is distributed in the hope that it will be useful,
1214+# but WITHOUT ANY WARRANTY; without even the implied warranty of
1215+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1216+# GNU General Public License for more details.
1217+#
1218+# You should have received a copy of the GNU General Public License
1219+# along with this program; if not, write to the Free Software
1220+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1221+
1222+Show Whiteout Mode (shwh)
1223+----------------------------------------------------------------------
1224+Generally aufs hides the name of whiteouts. But in some cases, to show
1225+them is very useful for users. For instance, creating a new middle layer
1226+(branch) by merging existing layers.
1227+
1228+(borrowing aufs1 HOW-TO from a user, Michael Towers)
1229+When you have three branches,
1230+- Bottom: 'system', squashfs (underlying base system), read-only
1231+- Middle: 'mods', squashfs, read-only
1232+- Top: 'overlay', ram (tmpfs), read-write
1233+
1234+The top layer is loaded at boot time and saved at shutdown, to preserve
1235+the changes made to the system during the session.
1236+When larger changes have been made, or smaller changes have accumulated,
1237+the size of the saved top layer data grows. At this point, it would be
1238+nice to be able to merge the two overlay branches ('mods' and 'overlay')
1239+and rewrite the 'mods' squashfs, clearing the top layer and thus
1240+restoring save and load speed.
1241+
1242+This merging is simplified by the use of another aufs mount, of just the
1243+two overlay branches using the 'shwh' option.
1244+# mount -t aufs -o ro,shwh,br:/livesys/overlay=ro+wh:/livesys/mods=rr+wh \
1245+ aufs /livesys/merge_union
1246+
1247+A merged view of these two branches is then available at
1248+/livesys/merge_union, and the new feature is that the whiteouts are
1249+visible!
1250+Note that in 'shwh' mode the aufs mount must be 'ro', which will disable
1251+writing to all branches. Also the default mode for all branches is 'ro'.
1252+It is now possible to save the combined contents of the two overlay
1253+branches to a new squashfs, e.g.:
1254+# mksquashfs /livesys/merge_union /path/to/newmods.squash
1255+
1256+This new squashfs archive can be stored on the boot device and the
1257+initramfs will use it to replace the old one at the next boot.
1258diff -urN /usr/share/empty/Documentation/filesystems/aufs/design/10dynop.txt linux/Documentation/filesystems/aufs/design/10dynop.txt
1259--- /usr/share/empty/Documentation/filesystems/aufs/design/10dynop.txt 1970-01-01 01:00:00.000000000 +0100
7ce627cf 1260+++ linux/Documentation/filesystems/aufs/design/10dynop.txt 2012-05-22 09:06:08.864125478 +0200
53392da6
AM
1261@@ -0,0 +1,47 @@
1262+
1263+# Copyright (C) 2010-2011 Junjiro R. Okajima
1264+#
1265+# This program is free software; you can redistribute it and/or modify
1266+# it under the terms of the GNU General Public License as published by
1267+# the Free Software Foundation; either version 2 of the License, or
1268+# (at your option) any later version.
1269+#
1270+# This program is distributed in the hope that it will be useful,
1271+# but WITHOUT ANY WARRANTY; without even the implied warranty of
1272+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1273+# GNU General Public License for more details.
1274+#
1275+# You should have received a copy of the GNU General Public License
1276+# along with this program; if not, write to the Free Software
1277+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1278+
1279+Dynamically customizable FS operations
1280+----------------------------------------------------------------------
1281+Generally FS operations (struct inode_operations, struct
1282+address_space_operations, struct file_operations, etc.) are defined as
1283+"static const", but it never means that FS have only one set of
1284+operation. Some FS have multiple sets of them. For instance, ext2 has
1285+three sets, one for XIP, for NOBH, and for normal.
1286+Since aufs overrides and redirects these operations, sometimes aufs has
1287+to change its behaviour according to the branch FS type. More imporantly
1288+VFS acts differently if a function (member in the struct) is set or
1289+not. It means aufs should have several sets of operations and select one
1290+among them according to the branch FS definition.
1291+
1292+In order to solve this problem and not to affect the behavour of VFS,
1293+aufs defines these operations dynamically. For instance, aufs defines
1294+aio_read function for struct file_operations, but it may not be set to
1295+the file_operations. When the branch FS doesn't have it, aufs doesn't
1296+set it to its file_operations while the function definition itself is
1297+still alive. So the behaviour of io_submit(2) will not change, and it
1298+will return an error when aio_read is not defined.
1299+
1300+The lifetime of these dynamically generated operation object is
1301+maintained by aufs branch object. When the branch is removed from aufs,
1302+the reference counter of the object is decremented. When it reaches
1303+zero, the dynamically generated operation object will be freed.
1304+
1305+This approach is designed to support AIO (io_submit), Direcit I/O and
1306+XIP mainly.
1307+Currently this approach is applied to file_operations and
1308+vm_operations_struct for regular files only.
1309diff -urN /usr/share/empty/Documentation/filesystems/aufs/design/99plan.txt linux/Documentation/filesystems/aufs/design/99plan.txt
1310--- /usr/share/empty/Documentation/filesystems/aufs/design/99plan.txt 1970-01-01 01:00:00.000000000 +0100
7ce627cf 1311+++ linux/Documentation/filesystems/aufs/design/99plan.txt 2012-05-22 09:06:08.864125478 +0200
53392da6
AM
1312@@ -0,0 +1,96 @@
1313+
1314+# Copyright (C) 2005-2011 Junjiro R. Okajima
1315+#
1316+# This program is free software; you can redistribute it and/or modify
1317+# it under the terms of the GNU General Public License as published by
1318+# the Free Software Foundation; either version 2 of the License, or
1319+# (at your option) any later version.
1320+#
1321+# This program is distributed in the hope that it will be useful,
1322+# but WITHOUT ANY WARRANTY; without even the implied warranty of
1323+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1324+# GNU General Public License for more details.
1325+#
1326+# You should have received a copy of the GNU General Public License
1327+# along with this program; if not, write to the Free Software
1328+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1329+
1330+Plan
1331+
1332+Restoring some features which was implemented in aufs1.
1333+They were dropped in aufs2 in order to make source files simpler and
1334+easier to be reviewed.
1335+
1336+
1337+Test Only the Highest One for the Directory Permission (dirperm1 option)
1338+----------------------------------------------------------------------
1339+Let's try case study.
1340+- aufs has two branches, upper readwrite and lower readonly.
1341+ /au = /rw + /ro
1342+- "dirA" exists under /ro, but /rw. and its mode is 0700.
1343+- user invoked "chmod a+rx /au/dirA"
1344+- then "dirA" becomes world readable?
1345+
1346+In this case, /ro/dirA is still 0700 since it exists in readonly branch,
1347+or it may be a natively readonly filesystem. If aufs respects the lower
1348+branch, it should not respond readdir request from other users. But user
1349+allowed it by chmod. Should really aufs rejects showing the entries
1350+under /ro/dirA?
1351+
1352+To be honest, I don't have a best solution for this case. So I
1353+implemented 'dirperm1' and 'nodirperm1' option in aufs1, and leave it to
1354+users.
1355+When dirperm1 is specified, aufs checks only the highest one for the
1356+directory permission, and shows the entries. Otherwise, as usual, checks
1357+every dir existing on all branches and rejects the request.
1358+
1359+As a side effect, dirperm1 option improves the performance of aufs
1360+because the number of permission check is reduced.
1361+
1362+
1363+Being Another Aufs's Readonly Branch (robr)
1364+----------------------------------------------------------------------
1365+Aufs1 allows aufs to be another aufs's readonly branch.
1366+This feature was developed by a user's request. But it may not be used
1367+currecnly.
1368+
1369+
1370+Copy-up on Open (coo=)
1371+----------------------------------------------------------------------
1372+By default the internal copy-up is executed when it is really necessary.
1373+It is not done when a file is opened for writing, but when write(2) is
1374+done. Users who have many (over 100) branches want to know and analyse
1375+when and what file is copied-up. To insert a new upper branch which
1376+contains such files only may improve the performance of aufs.
1377+
1378+Aufs1 implemented "coo=none | leaf | all" option.
1379+
1380+
1381+Refresh the Opened File (refrof)
1382+----------------------------------------------------------------------
1383+This option is implemented in aufs1 but incomplete.
1384+
1385+When user reads from a file, he expects to get its latest filedata
1386+generally. If the file is removed and a new same named file is created,
1387+the content he gets is unchanged, ie. the unlinked filedata.
1388+
1389+Let's try case study again.
1390+- aufs has two branches.
1391+ /au = /rw + /ro
1392+- "fileA" exists under /ro, but /rw.
1393+- user opened "/au/fileA".
1394+- he or someone else inserts a branch (/new) between /rw and /ro.
1395+ /au = /rw + /new + /ro
1396+- the new branch has "fileA".
1397+- user reads from the opened "fileA"
1398+- which filedata should aufs return, from /ro or /new?
1399+
1400+Some people says it has to be "from /ro" and it is a semantics of Unix.
1401+The others say it should be "from /new" because the file is not removed
1402+and it is equivalent to the case of someone else modifies the file.
1403+
1404+Here again I don't have a best and final answer. I got an idea to
1405+implement 'refrof' and 'norefrof' option. When 'refrof' (REFResh the
1406+Opened File) is specified (by default), aufs returns the filedata from
1407+/new.
1408+Otherwise from /new.
1409diff -urN /usr/share/empty/Documentation/filesystems/aufs/README linux/Documentation/filesystems/aufs/README
1410--- /usr/share/empty/Documentation/filesystems/aufs/README 1970-01-01 01:00:00.000000000 +0100
7ce627cf 1411+++ linux/Documentation/filesystems/aufs/README 2012-05-22 09:06:08.864125478 +0200
7eafdf33 1412@@ -0,0 +1,330 @@
53392da6
AM
1413+
1414+Aufs3 -- advanced multi layered unification filesystem version 3.x
1415+http://aufs.sf.net
1416+Junjiro R. Okajima
1417+
1418+
1419+0. Introduction
1420+----------------------------------------
1421+In the early days, aufs was entirely re-designed and re-implemented
1422+Unionfs Version 1.x series. After many original ideas, approaches,
1423+improvements and implementations, it becomes totally different from
1424+Unionfs while keeping the basic features.
1425+Recently, Unionfs Version 2.x series begin taking some of the same
1426+approaches to aufs1's.
1427+Unionfs is being developed by Professor Erez Zadok at Stony Brook
1428+University and his team.
1429+
1430+Aufs3 supports linux-3.0 and later.
1431+If you want older kernel version support, try aufs2-2.6.git or
1432+aufs2-standalone.git repository, aufs1 from CVS on SourceForge.
1433+
1434+Note: it becomes clear that "Aufs was rejected. Let's give it up."
1435+According to Christoph Hellwig, linux rejects all union-type filesystems
1436+but UnionMount.
1437+<http://marc.info/?l=linux-kernel&m=123938533724484&w=2>
1438+
1439+
1440+1. Features
1441+----------------------------------------
1442+- unite several directories into a single virtual filesystem. The member
1443+ directory is called as a branch.
1444+- you can specify the permission flags to the branch, which are 'readonly',
1445+ 'readwrite' and 'whiteout-able.'
1446+- by upper writable branch, internal copyup and whiteout, files/dirs on
1447+ readonly branch are modifiable logically.
1448+- dynamic branch manipulation, add, del.
1449+- etc...
1450+
1451+Also there are many enhancements in aufs1, such as:
1452+- readdir(3) in userspace.
1453+- keep inode number by external inode number table
1454+- keep the timestamps of file/dir in internal copyup operation
1455+- seekable directory, supporting NFS readdir.
1456+- whiteout is hardlinked in order to reduce the consumption of inodes
1457+ on branch
1458+- do not copyup, nor create a whiteout when it is unnecessary
1459+- revert a single systemcall when an error occurs in aufs
1460+- remount interface instead of ioctl
1461+- maintain /etc/mtab by an external command, /sbin/mount.aufs.
1462+- loopback mounted filesystem as a branch
1463+- kernel thread for removing the dir who has a plenty of whiteouts
1464+- support copyup sparse file (a file which has a 'hole' in it)
1465+- default permission flags for branches
1466+- selectable permission flags for ro branch, whether whiteout can
1467+ exist or not
1468+- export via NFS.
1469+- support <sysfs>/fs/aufs and <debugfs>/aufs.
1470+- support multiple writable branches, some policies to select one
1471+ among multiple writable branches.
1472+- a new semantics for link(2) and rename(2) to support multiple
1473+ writable branches.
1474+- no glibc changes are required.
1475+- pseudo hardlink (hardlink over branches)
1476+- allow a direct access manually to a file on branch, e.g. bypassing aufs.
1477+ including NFS or remote filesystem branch.
1478+- userspace wrapper for pathconf(3)/fpathconf(3) with _PC_LINK_MAX.
1479+- and more...
1480+
1481+Currently these features are dropped temporary from aufs3.
1482+See design/08plan.txt in detail.
1483+- test only the highest one for the directory permission (dirperm1)
1484+- copyup on open (coo=)
1485+- nested mount, i.e. aufs as readonly no-whiteout branch of another aufs
1486+ (robr)
1487+- statistics of aufs thread (/sys/fs/aufs/stat)
1488+- delegation mode (dlgt)
1489+ a delegation of the internal branch access to support task I/O
1490+ accounting, which also supports Linux Security Modules (LSM) mainly
1491+ for Suse AppArmor.
1492+- intent.open/create (file open in a single lookup)
1493+
1494+Features or just an idea in the future (see also design/*.txt),
1495+- reorder the branch index without del/re-add.
1496+- permanent xino files for NFSD
1497+- an option for refreshing the opened files after add/del branches
1498+- 'move' policy for copy-up between two writable branches, after
1499+ checking free space.
1500+- light version, without branch manipulation. (unnecessary?)
1501+- copyup in userspace
1502+- inotify in userspace
1503+- readv/writev
1504+- xattr, acl
1505+
1506+
1507+2. Download
1508+----------------------------------------
1e00d052
AM
1509+There were three GIT trees for aufs3, aufs3-linux.git,
1510+aufs3-standalone.git, and aufs-util.git. Note that there is no "3" in
1511+"aufs-util.git."
1512+While the aufs-util is always necessary, you need either of aufs3-linux
1513+or aufs3-standalone.
1514+
1515+The aufs3-linux tree includes the whole linux mainline GIT tree,
1516+git://git.kernel.org/.../torvalds/linux.git.
1517+And you cannot select CONFIG_AUFS_FS=m for this version, eg. you cannot
1518+build aufs3 as an externel kernel module.
1519+
1520+On the other hand, the aufs3-standalone tree has only aufs source files
53392da6
AM
1521+and necessary patches, and you can select CONFIG_AUFS_FS=m.
1522+
1523+You will find GIT branches whose name is in form of "aufs3.x" where "x"
1524+represents the linux kernel version, "linux-3.x". For instance,
1e00d052
AM
1525+"aufs3.0" is for linux-3.0. For latest "linux-3.x-rcN", use
1526+"aufs3.x-rcN" branch.
1527+
1528+o aufs3-linux tree
1529+$ git clone --reference /your/linux/git/tree \
1530+ git://aufs.git.sourceforge.net/gitroot/aufs/aufs3-linux.git \
1531+ aufs3-linux.git
1532+- if you don't have linux GIT tree, then remove "--reference ..."
1533+$ cd aufs3-linux.git
1534+$ git checkout origin/aufs3.0
53392da6
AM
1535+
1536+o aufs3-standalone tree
1537+$ git clone git://aufs.git.sourceforge.net/gitroot/aufs/aufs3-standalone.git \
1538+ aufs3-standalone.git
1539+$ cd aufs3-standalone.git
1540+$ git checkout origin/aufs3.0
1541+
1542+o aufs-util tree
1543+$ git clone git://aufs.git.sourceforge.net/gitroot/aufs/aufs-util.git \
1544+ aufs-util.git
1545+$ cd aufs-util.git
1546+$ git checkout origin/aufs3.0
1547+
9dbd164d
AM
1548+Note: The 3.x-rcN branch is to be used with `rc' kernel versions ONLY.
1549+The minor version number, 'x' in '3.x', of aufs may not always
1550+follow the minor version number of the kernel.
1551+Because changes in the kernel that cause the use of a new
1552+minor version number do not always require changes to aufs-util.
1553+
1554+Since aufs-util has its own minor version number, you may not be
1555+able to find a GIT branch in aufs-util for your kernel's
1556+exact minor version number.
1557+In this case, you should git-checkout the branch for the
53392da6 1558+nearest lower number.
9dbd164d
AM
1559+
1560+For (an unreleased) example:
1561+If you are using "linux-3.10" and the "aufs3.10" branch
7eafdf33 1562+does not exist in aufs-util repository, then "aufs3.9", "aufs3.8"
9dbd164d
AM
1563+or something numerically smaller is the branch for your kernel.
1564+
53392da6
AM
1565+Also you can view all branches by
1566+ $ git branch -a
1567+
1568+
1569+3. Configuration and Compilation
1570+----------------------------------------
1571+Make sure you have git-checkout'ed the correct branch.
1572+
1e00d052
AM
1573+For aufs3-linux tree,
1574+- enable CONFIG_EXPERIMENTAL and CONFIG_AUFS_FS.
1575+- set other aufs configurations if necessary.
1576+
53392da6
AM
1577+For aufs3-standalone tree,
1578+There are several ways to build.
1579+
1580+1.
1581+- apply ./aufs3-kbuild.patch to your kernel source files.
1582+- apply ./aufs3-base.patch too.
1583+- apply ./aufs3-proc_map.patch too, if you want to make /proc/PID/maps (and
1584+ others including lsof(1)) show the file path on aufs instead of the
1585+ path on the branch fs.
1586+- apply ./aufs3-standalone.patch too, if you have a plan to set
1587+ CONFIG_AUFS_FS=m. otherwise you don't need ./aufs3-standalone.patch.
1588+- copy ./{Documentation,fs,include/linux/aufs_type.h} files to your
1589+ kernel source tree. Never copy ./include/linux/Kbuild.
1590+- enable CONFIG_EXPERIMENTAL and CONFIG_AUFS_FS, you can select either
1591+ =m or =y.
1592+- and build your kernel as usual.
1593+- install the built kernel.
7eafdf33
AM
1594+- install the header files too by "make headers_install" to the
1595+ directory where you specify. By default, it is $PWD/usr.
53392da6
AM
1596+- and reboot your system.
1597+
1598+2.
1599+- module only (CONFIG_AUFS_FS=m).
1600+- apply ./aufs3-base.patch to your kernel source files.
1601+- apply ./aufs3-proc_map.patch too to your kernel source files,
1602+ if you want to make /proc/PID/maps (and others including lsof(1)) show
1603+ the file path on aufs instead of the path on the branch fs.
1604+- apply ./aufs3-standalone.patch too.
1605+- build your kernel, don't forget "make headers_install", and reboot.
1606+- edit ./config.mk and set other aufs configurations if necessary.
1607+ Note: You should read ./fs/aufs/Kconfig carefully which describes
1608+ every aufs configurations.
1609+- build the module by simple "make".
1610+- you can specify ${KDIR} make variable which points to your kernel
1611+ source tree.
1612+- install the files
1613+ + run "make install" to install the aufs module, or copy the built
1614+ ./aufs.ko to /lib/modules/... and run depmod -a (or reboot simply).
1615+ + run "make headers_install" to install the aufs header file (you can
1616+ specify DESTDIR), or copty ./usr/include/linux/aufs_type.h to
7eafdf33
AM
1617+ /usr/include/linux or wherever you like. By default, the target
1618+ directory is $PWD/usr.
53392da6
AM
1619+- no need to apply aufs3-kbuild.patch, nor copying source files to your
1620+ kernel source tree.
1621+
1622+Note: The haeder file aufs_type.h is necessary to build aufs-util
1623+ as well as "make headers_install" in the kernel source tree.
1624+ headers_install is subject to be forgotten, but it is essentially
1625+ necessary, not only for building aufs-util.
1626+ You may not meet problems without headers_install in some older
1627+ version though.
1628+
1629+And then,
1630+- read README in aufs-util, build and install it
9dbd164d
AM
1631+- note that your distribution may contain an obsoleted version of
1632+ aufs_type.h in /usr/include/linux or something. When you build aufs
1633+ utilities, make sure that your compiler refers the correct aufs header
1634+ file which is built by "make headers_install."
53392da6
AM
1635+- if you want to use readdir(3) in userspace or pathconf(3) wrapper,
1636+ then run "make install_ulib" too. And refer to the aufs manual in
1637+ detail.
1638+
1639+
1640+4. Usage
1641+----------------------------------------
1642+At first, make sure aufs-util are installed, and please read the aufs
1643+manual, aufs.5 in aufs-util.git tree.
1644+$ man -l aufs.5
1645+
1646+And then,
1647+$ mkdir /tmp/rw /tmp/aufs
1648+# mount -t aufs -o br=/tmp/rw:${HOME} none /tmp/aufs
1649+
1650+Here is another example. The result is equivalent.
1651+# mount -t aufs -o br=/tmp/rw=rw:${HOME}=ro none /tmp/aufs
1652+ Or
1653+# mount -t aufs -o br:/tmp/rw none /tmp/aufs
1654+# mount -o remount,append:${HOME} /tmp/aufs
1655+
1656+Then, you can see whole tree of your home dir through /tmp/aufs. If
1657+you modify a file under /tmp/aufs, the one on your home directory is
1658+not affected, instead the same named file will be newly created under
1659+/tmp/rw. And all of your modification to a file will be applied to
1660+the one under /tmp/rw. This is called the file based Copy on Write
1661+(COW) method.
1662+Aufs mount options are described in aufs.5.
1663+If you run chroot or something and make your aufs as a root directory,
1664+then you need to customize the shutdown script. See the aufs manual in
1665+detail.
1666+
1667+Additionally, there are some sample usages of aufs which are a
1668+diskless system with network booting, and LiveCD over NFS.
1669+See sample dir in CVS tree on SourceForge.
1670+
1671+
1672+5. Contact
1673+----------------------------------------
1674+When you have any problems or strange behaviour in aufs, please let me
1675+know with:
1676+- /proc/mounts (instead of the output of mount(8))
1677+- /sys/module/aufs/*
1678+- /sys/fs/aufs/* (if you have them)
1679+- /debug/aufs/* (if you have them)
1680+- linux kernel version
1681+ if your kernel is not plain, for example modified by distributor,
1682+ the url where i can download its source is necessary too.
1683+- aufs version which was printed at loading the module or booting the
1684+ system, instead of the date you downloaded.
1685+- configuration (define/undefine CONFIG_AUFS_xxx)
1686+- kernel configuration or /proc/config.gz (if you have it)
1687+- behaviour which you think to be incorrect
1688+- actual operation, reproducible one is better
1689+- mailto: aufs-users at lists.sourceforge.net
1690+
1691+Usually, I don't watch the Public Areas(Bugs, Support Requests, Patches,
1692+and Feature Requests) on SourceForge. Please join and write to
1693+aufs-users ML.
1694+
1695+
1696+6. Acknowledgements
1697+----------------------------------------
1698+Thanks to everyone who have tried and are using aufs, whoever
1699+have reported a bug or any feedback.
1700+
1701+Especially donators:
1702+Tomas Matejicek(slax.org) made a donation (much more than once).
1703+ Since Apr 2010, Tomas M (the author of Slax and Linux Live
1704+ scripts) is making "doubling" donations.
1705+ Unfortunately I cannot list all of the donators, but I really
1706+ appriciate.
1707+ It ends Aug 2010, but the ordinary donation URL is still available.
1708+ <http://sourceforge.net/donate/index.php?group_id=167503>
1709+Dai Itasaka made a donation (2007/8).
1710+Chuck Smith made a donation (2008/4, 10 and 12).
1711+Henk Schoneveld made a donation (2008/9).
1712+Chih-Wei Huang, ASUS, CTC donated Eee PC 4G (2008/10).
1713+Francois Dupoux made a donation (2008/11).
1714+Bruno Cesar Ribas and Luis Carlos Erpen de Bona, C3SL serves public
1715+ aufs2 GIT tree (2009/2).
1716+William Grant made a donation (2009/3).
1717+Patrick Lane made a donation (2009/4).
1718+The Mail Archive (mail-archive.com) made donations (2009/5).
1719+Nippy Networks (Ed Wildgoose) made a donation (2009/7).
1720+New Dream Network, LLC (www.dreamhost.com) made a donation (2009/11).
1721+Pavel Pronskiy made a donation (2011/2).
1722+Iridium and Inmarsat satellite phone retailer (www.mailasail.com), Nippy
1723+ Networks (Ed Wildgoose) made a donation for hardware (2011/3).
92d182d2 1724+Max Lekomcev (DOM-TV project) made a donation (2011/7, 12 and 2012/3).
1e00d052 1725+Sam Liddicott made a donation (2011/9).
53392da6
AM
1726+
1727+Thank you very much.
1728+Donations are always, including future donations, very important and
1729+helpful for me to keep on developing aufs.
1730+
1731+
1732+7.
1733+----------------------------------------
1734+If you are an experienced user, no explanation is needed. Aufs is
1735+just a linux filesystem.
1736+
1737+
1738+Enjoy!
1739+
1740+# Local variables: ;
1741+# mode: text;
1742+# End: ;
7f207e10
AM
1743diff -urN /usr/share/empty/fs/aufs/aufs.h linux/fs/aufs/aufs.h
1744--- /usr/share/empty/fs/aufs/aufs.h 1970-01-01 01:00:00.000000000 +0100
7ce627cf 1745+++ linux/fs/aufs/aufs.h 2012-05-22 09:06:08.864125478 +0200
2cbb1c4b 1746@@ -0,0 +1,60 @@
7f207e10 1747+/*
f6c5ef8b 1748+ * Copyright (C) 2005-2012 Junjiro R. Okajima
7f207e10
AM
1749+ *
1750+ * This program, aufs is free software; you can redistribute it and/or modify
1751+ * it under the terms of the GNU General Public License as published by
1752+ * the Free Software Foundation; either version 2 of the License, or
1753+ * (at your option) any later version.
1754+ *
1755+ * This program is distributed in the hope that it will be useful,
1756+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1757+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1758+ * GNU General Public License for more details.
1759+ *
1760+ * You should have received a copy of the GNU General Public License
1761+ * along with this program; if not, write to the Free Software
1762+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1763+ */
1764+
1765+/*
1766+ * all header files
1767+ */
1768+
1769+#ifndef __AUFS_H__
1770+#define __AUFS_H__
1771+
1772+#ifdef __KERNEL__
1773+
1774+#define AuStub(type, name, body, ...) \
1775+ static inline type name(__VA_ARGS__) { body; }
1776+
1777+#define AuStubVoid(name, ...) \
1778+ AuStub(void, name, , __VA_ARGS__)
1779+#define AuStubInt0(name, ...) \
1780+ AuStub(int, name, return 0, __VA_ARGS__)
1781+
1782+#include "debug.h"
1783+
1784+#include "branch.h"
1785+#include "cpup.h"
1786+#include "dcsub.h"
1787+#include "dbgaufs.h"
1788+#include "dentry.h"
1789+#include "dir.h"
1790+#include "dynop.h"
1791+#include "file.h"
1792+#include "fstype.h"
1793+#include "inode.h"
1794+#include "loop.h"
1795+#include "module.h"
7f207e10
AM
1796+#include "opts.h"
1797+#include "rwsem.h"
1798+#include "spl.h"
1799+#include "super.h"
1800+#include "sysaufs.h"
1801+#include "vfsub.h"
1802+#include "whout.h"
1803+#include "wkq.h"
1804+
1805+#endif /* __KERNEL__ */
1806+#endif /* __AUFS_H__ */
1807diff -urN /usr/share/empty/fs/aufs/branch.c linux/fs/aufs/branch.c
1808--- /usr/share/empty/fs/aufs/branch.c 1970-01-01 01:00:00.000000000 +0100
7ce627cf 1809+++ linux/fs/aufs/branch.c 2012-05-22 09:06:08.864125478 +0200
f6c5ef8b 1810@@ -0,0 +1,1169 @@
7f207e10 1811+/*
f6c5ef8b 1812+ * Copyright (C) 2005-2012 Junjiro R. Okajima
7f207e10
AM
1813+ *
1814+ * This program, aufs is free software; you can redistribute it and/or modify
1815+ * it under the terms of the GNU General Public License as published by
1816+ * the Free Software Foundation; either version 2 of the License, or
1817+ * (at your option) any later version.
1818+ *
1819+ * This program is distributed in the hope that it will be useful,
1820+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1821+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1822+ * GNU General Public License for more details.
1823+ *
1824+ * You should have received a copy of the GNU General Public License
1825+ * along with this program; if not, write to the Free Software
1826+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1827+ */
1828+
1829+/*
1830+ * branch management
1831+ */
1832+
027c5e7a 1833+#include <linux/compat.h>
7f207e10
AM
1834+#include <linux/statfs.h>
1835+#include "aufs.h"
1836+
1837+/*
1838+ * free a single branch
1facf9fc 1839+ */
1840+static void au_br_do_free(struct au_branch *br)
1841+{
1842+ int i;
1843+ struct au_wbr *wbr;
4a4d8108 1844+ struct au_dykey **key;
1facf9fc 1845+
027c5e7a
AM
1846+ au_hnotify_fin_br(br);
1847+
1facf9fc 1848+ if (br->br_xino.xi_file)
1849+ fput(br->br_xino.xi_file);
1850+ mutex_destroy(&br->br_xino.xi_nondir_mtx);
1851+
1852+ AuDebugOn(atomic_read(&br->br_count));
1853+
1854+ wbr = br->br_wbr;
1855+ if (wbr) {
1856+ for (i = 0; i < AuBrWh_Last; i++)
1857+ dput(wbr->wbr_wh[i]);
1858+ AuDebugOn(atomic_read(&wbr->wbr_wh_running));
dece6358 1859+ AuRwDestroy(&wbr->wbr_wh_rwsem);
1facf9fc 1860+ }
1861+
4a4d8108
AM
1862+ key = br->br_dykey;
1863+ for (i = 0; i < AuBrDynOp; i++, key++)
1864+ if (*key)
1865+ au_dy_put(*key);
1866+ else
1867+ break;
1868+
1facf9fc 1869+ mntput(br->br_mnt);
1facf9fc 1870+ kfree(wbr);
1871+ kfree(br);
1872+}
1873+
1874+/*
1875+ * frees all branches
1876+ */
1877+void au_br_free(struct au_sbinfo *sbinfo)
1878+{
1879+ aufs_bindex_t bmax;
1880+ struct au_branch **br;
1881+
dece6358
AM
1882+ AuRwMustWriteLock(&sbinfo->si_rwsem);
1883+
1facf9fc 1884+ bmax = sbinfo->si_bend + 1;
1885+ br = sbinfo->si_branch;
1886+ while (bmax--)
1887+ au_br_do_free(*br++);
1888+}
1889+
1890+/*
1891+ * find the index of a branch which is specified by @br_id.
1892+ */
1893+int au_br_index(struct super_block *sb, aufs_bindex_t br_id)
1894+{
1895+ aufs_bindex_t bindex, bend;
1896+
1897+ bend = au_sbend(sb);
1898+ for (bindex = 0; bindex <= bend; bindex++)
1899+ if (au_sbr_id(sb, bindex) == br_id)
1900+ return bindex;
1901+ return -1;
1902+}
1903+
1904+/* ---------------------------------------------------------------------- */
1905+
1906+/*
1907+ * add a branch
1908+ */
1909+
b752ccd1
AM
1910+static int test_overlap(struct super_block *sb, struct dentry *h_adding,
1911+ struct dentry *h_root)
1facf9fc 1912+{
b752ccd1
AM
1913+ if (unlikely(h_adding == h_root
1914+ || au_test_loopback_overlap(sb, h_adding)))
1facf9fc 1915+ return 1;
b752ccd1
AM
1916+ if (h_adding->d_sb != h_root->d_sb)
1917+ return 0;
1918+ return au_test_subdir(h_adding, h_root)
1919+ || au_test_subdir(h_root, h_adding);
1facf9fc 1920+}
1921+
1922+/*
1923+ * returns a newly allocated branch. @new_nbranch is a number of branches
1924+ * after adding a branch.
1925+ */
1926+static struct au_branch *au_br_alloc(struct super_block *sb, int new_nbranch,
1927+ int perm)
1928+{
1929+ struct au_branch *add_branch;
1930+ struct dentry *root;
4a4d8108 1931+ int err;
1facf9fc 1932+
4a4d8108 1933+ err = -ENOMEM;
1facf9fc 1934+ root = sb->s_root;
1935+ add_branch = kmalloc(sizeof(*add_branch), GFP_NOFS);
1936+ if (unlikely(!add_branch))
1937+ goto out;
1938+
027c5e7a
AM
1939+ err = au_hnotify_init_br(add_branch, perm);
1940+ if (unlikely(err))
1941+ goto out_br;
1942+
1facf9fc 1943+ add_branch->br_wbr = NULL;
1944+ if (au_br_writable(perm)) {
1945+ /* may be freed separately at changing the branch permission */
1946+ add_branch->br_wbr = kmalloc(sizeof(*add_branch->br_wbr),
1947+ GFP_NOFS);
1948+ if (unlikely(!add_branch->br_wbr))
027c5e7a 1949+ goto out_hnotify;
1facf9fc 1950+ }
1951+
4a4d8108
AM
1952+ err = au_sbr_realloc(au_sbi(sb), new_nbranch);
1953+ if (!err)
1954+ err = au_di_realloc(au_di(root), new_nbranch);
1955+ if (!err)
1956+ err = au_ii_realloc(au_ii(root->d_inode), new_nbranch);
1957+ if (!err)
1958+ return add_branch; /* success */
1facf9fc 1959+
1facf9fc 1960+ kfree(add_branch->br_wbr);
4a4d8108 1961+
027c5e7a
AM
1962+out_hnotify:
1963+ au_hnotify_fin_br(add_branch);
4f0767ce 1964+out_br:
1facf9fc 1965+ kfree(add_branch);
4f0767ce 1966+out:
4a4d8108 1967+ return ERR_PTR(err);
1facf9fc 1968+}
1969+
1970+/*
1971+ * test if the branch permission is legal or not.
1972+ */
1973+static int test_br(struct inode *inode, int brperm, char *path)
1974+{
1975+ int err;
1976+
4a4d8108
AM
1977+ err = (au_br_writable(brperm) && IS_RDONLY(inode));
1978+ if (!err)
1979+ goto out;
1facf9fc 1980+
4a4d8108
AM
1981+ err = -EINVAL;
1982+ pr_err("write permission for readonly mount or inode, %s\n", path);
1983+
4f0767ce 1984+out:
1facf9fc 1985+ return err;
1986+}
1987+
1988+/*
1989+ * returns:
1990+ * 0: success, the caller will add it
1991+ * plus: success, it is already unified, the caller should ignore it
1992+ * minus: error
1993+ */
1994+static int test_add(struct super_block *sb, struct au_opt_add *add, int remount)
1995+{
1996+ int err;
1997+ aufs_bindex_t bend, bindex;
1998+ struct dentry *root;
1999+ struct inode *inode, *h_inode;
2000+
2001+ root = sb->s_root;
2002+ bend = au_sbend(sb);
2003+ if (unlikely(bend >= 0
2004+ && au_find_dbindex(root, add->path.dentry) >= 0)) {
2005+ err = 1;
2006+ if (!remount) {
2007+ err = -EINVAL;
4a4d8108 2008+ pr_err("%s duplicated\n", add->pathname);
1facf9fc 2009+ }
2010+ goto out;
2011+ }
2012+
2013+ err = -ENOSPC; /* -E2BIG; */
2014+ if (unlikely(AUFS_BRANCH_MAX <= add->bindex
2015+ || AUFS_BRANCH_MAX - 1 <= bend)) {
4a4d8108 2016+ pr_err("number of branches exceeded %s\n", add->pathname);
1facf9fc 2017+ goto out;
2018+ }
2019+
2020+ err = -EDOM;
2021+ if (unlikely(add->bindex < 0 || bend + 1 < add->bindex)) {
4a4d8108 2022+ pr_err("bad index %d\n", add->bindex);
1facf9fc 2023+ goto out;
2024+ }
2025+
2026+ inode = add->path.dentry->d_inode;
2027+ err = -ENOENT;
2028+ if (unlikely(!inode->i_nlink)) {
4a4d8108 2029+ pr_err("no existence %s\n", add->pathname);
1facf9fc 2030+ goto out;
2031+ }
2032+
2033+ err = -EINVAL;
2034+ if (unlikely(inode->i_sb == sb)) {
4a4d8108 2035+ pr_err("%s must be outside\n", add->pathname);
1facf9fc 2036+ goto out;
2037+ }
2038+
2039+ if (unlikely(au_test_fs_unsuppoted(inode->i_sb))) {
4a4d8108
AM
2040+ pr_err("unsupported filesystem, %s (%s)\n",
2041+ add->pathname, au_sbtype(inode->i_sb));
1facf9fc 2042+ goto out;
2043+ }
2044+
2045+ err = test_br(add->path.dentry->d_inode, add->perm, add->pathname);
2046+ if (unlikely(err))
2047+ goto out;
2048+
2049+ if (bend < 0)
2050+ return 0; /* success */
2051+
2052+ err = -EINVAL;
2053+ for (bindex = 0; bindex <= bend; bindex++)
2054+ if (unlikely(test_overlap(sb, add->path.dentry,
2055+ au_h_dptr(root, bindex)))) {
4a4d8108 2056+ pr_err("%s is overlapped\n", add->pathname);
1facf9fc 2057+ goto out;
2058+ }
2059+
2060+ err = 0;
2061+ if (au_opt_test(au_mntflags(sb), WARN_PERM)) {
2062+ h_inode = au_h_dptr(root, 0)->d_inode;
2063+ if ((h_inode->i_mode & S_IALLUGO) != (inode->i_mode & S_IALLUGO)
2064+ || h_inode->i_uid != inode->i_uid
2065+ || h_inode->i_gid != inode->i_gid)
4a4d8108
AM
2066+ pr_warning("uid/gid/perm %s %u/%u/0%o, %u/%u/0%o\n",
2067+ add->pathname,
2068+ inode->i_uid, inode->i_gid,
2069+ (inode->i_mode & S_IALLUGO),
2070+ h_inode->i_uid, h_inode->i_gid,
2071+ (h_inode->i_mode & S_IALLUGO));
1facf9fc 2072+ }
2073+
4f0767ce 2074+out:
1facf9fc 2075+ return err;
2076+}
2077+
2078+/*
2079+ * initialize or clean the whiteouts for an adding branch
2080+ */
2081+static int au_br_init_wh(struct super_block *sb, struct au_branch *br,
2082+ int new_perm, struct dentry *h_root)
2083+{
2084+ int err, old_perm;
2085+ aufs_bindex_t bindex;
2086+ struct mutex *h_mtx;
2087+ struct au_wbr *wbr;
2088+ struct au_hinode *hdir;
2089+
2090+ wbr = br->br_wbr;
2091+ old_perm = br->br_perm;
2092+ br->br_perm = new_perm;
2093+ hdir = NULL;
2094+ h_mtx = NULL;
2095+ bindex = au_br_index(sb, br->br_id);
2096+ if (0 <= bindex) {
2097+ hdir = au_hi(sb->s_root->d_inode, bindex);
4a4d8108 2098+ au_hn_imtx_lock_nested(hdir, AuLsc_I_PARENT);
1facf9fc 2099+ } else {
2100+ h_mtx = &h_root->d_inode->i_mutex;
2101+ mutex_lock_nested(h_mtx, AuLsc_I_PARENT);
2102+ }
2103+ if (!wbr)
2104+ err = au_wh_init(h_root, br, sb);
2105+ else {
2106+ wbr_wh_write_lock(wbr);
2107+ err = au_wh_init(h_root, br, sb);
2108+ wbr_wh_write_unlock(wbr);
2109+ }
2110+ if (hdir)
4a4d8108 2111+ au_hn_imtx_unlock(hdir);
1facf9fc 2112+ else
2113+ mutex_unlock(h_mtx);
2114+ br->br_perm = old_perm;
2115+
2116+ if (!err && wbr && !au_br_writable(new_perm)) {
2117+ kfree(wbr);
2118+ br->br_wbr = NULL;
2119+ }
2120+
2121+ return err;
2122+}
2123+
2124+static int au_wbr_init(struct au_branch *br, struct super_block *sb,
2125+ int perm, struct path *path)
2126+{
2127+ int err;
4a4d8108 2128+ struct kstatfs kst;
1facf9fc 2129+ struct au_wbr *wbr;
4a4d8108 2130+ struct dentry *h_dentry;
1facf9fc 2131+
2132+ wbr = br->br_wbr;
dece6358 2133+ au_rw_init(&wbr->wbr_wh_rwsem);
1facf9fc 2134+ memset(wbr->wbr_wh, 0, sizeof(wbr->wbr_wh));
2135+ atomic_set(&wbr->wbr_wh_running, 0);
2136+ wbr->wbr_bytes = 0;
2137+
4a4d8108
AM
2138+ /*
2139+ * a limit for rmdir/rename a dir
2140+ * cf. AUFS_MAX_NAMELEN in include/linux/aufs_type.h
2141+ */
7f207e10 2142+ err = vfs_statfs(path, &kst);
4a4d8108
AM
2143+ if (unlikely(err))
2144+ goto out;
2145+ err = -EINVAL;
7f207e10 2146+ h_dentry = path->dentry;
4a4d8108
AM
2147+ if (kst.f_namelen >= NAME_MAX)
2148+ err = au_br_init_wh(sb, br, perm, h_dentry);
2149+ else
2150+ pr_err("%.*s(%s), unsupported namelen %ld\n",
2151+ AuDLNPair(h_dentry), au_sbtype(h_dentry->d_sb),
2152+ kst.f_namelen);
1facf9fc 2153+
4f0767ce 2154+out:
1facf9fc 2155+ return err;
2156+}
2157+
2158+/* intialize a new branch */
2159+static int au_br_init(struct au_branch *br, struct super_block *sb,
2160+ struct au_opt_add *add)
2161+{
2162+ int err;
2163+
2164+ err = 0;
2165+ memset(&br->br_xino, 0, sizeof(br->br_xino));
2166+ mutex_init(&br->br_xino.xi_nondir_mtx);
2167+ br->br_perm = add->perm;
2168+ br->br_mnt = add->path.mnt; /* set first, mntget() later */
4a4d8108
AM
2169+ spin_lock_init(&br->br_dykey_lock);
2170+ memset(br->br_dykey, 0, sizeof(br->br_dykey));
1facf9fc 2171+ atomic_set(&br->br_count, 0);
2172+ br->br_xino_upper = AUFS_XINO_TRUNC_INIT;
2173+ atomic_set(&br->br_xino_running, 0);
2174+ br->br_id = au_new_br_id(sb);
7f207e10 2175+ AuDebugOn(br->br_id < 0);
1facf9fc 2176+
2177+ if (au_br_writable(add->perm)) {
2178+ err = au_wbr_init(br, sb, add->perm, &add->path);
2179+ if (unlikely(err))
b752ccd1 2180+ goto out_err;
1facf9fc 2181+ }
2182+
2183+ if (au_opt_test(au_mntflags(sb), XINO)) {
2184+ err = au_xino_br(sb, br, add->path.dentry->d_inode->i_ino,
2185+ au_sbr(sb, 0)->br_xino.xi_file, /*do_test*/1);
2186+ if (unlikely(err)) {
2187+ AuDebugOn(br->br_xino.xi_file);
b752ccd1 2188+ goto out_err;
1facf9fc 2189+ }
2190+ }
2191+
2192+ sysaufs_br_init(br);
2193+ mntget(add->path.mnt);
b752ccd1 2194+ goto out; /* success */
1facf9fc 2195+
4f0767ce 2196+out_err:
b752ccd1 2197+ br->br_mnt = NULL;
4f0767ce 2198+out:
1facf9fc 2199+ return err;
2200+}
2201+
2202+static void au_br_do_add_brp(struct au_sbinfo *sbinfo, aufs_bindex_t bindex,
2203+ struct au_branch *br, aufs_bindex_t bend,
2204+ aufs_bindex_t amount)
2205+{
2206+ struct au_branch **brp;
2207+
dece6358
AM
2208+ AuRwMustWriteLock(&sbinfo->si_rwsem);
2209+
1facf9fc 2210+ brp = sbinfo->si_branch + bindex;
2211+ memmove(brp + 1, brp, sizeof(*brp) * amount);
2212+ *brp = br;
2213+ sbinfo->si_bend++;
2214+ if (unlikely(bend < 0))
2215+ sbinfo->si_bend = 0;
2216+}
2217+
2218+static void au_br_do_add_hdp(struct au_dinfo *dinfo, aufs_bindex_t bindex,
2219+ aufs_bindex_t bend, aufs_bindex_t amount)
2220+{
2221+ struct au_hdentry *hdp;
2222+
1308ab2a 2223+ AuRwMustWriteLock(&dinfo->di_rwsem);
2224+
1facf9fc 2225+ hdp = dinfo->di_hdentry + bindex;
2226+ memmove(hdp + 1, hdp, sizeof(*hdp) * amount);
2227+ au_h_dentry_init(hdp);
2228+ dinfo->di_bend++;
2229+ if (unlikely(bend < 0))
2230+ dinfo->di_bstart = 0;
2231+}
2232+
2233+static void au_br_do_add_hip(struct au_iinfo *iinfo, aufs_bindex_t bindex,
2234+ aufs_bindex_t bend, aufs_bindex_t amount)
2235+{
2236+ struct au_hinode *hip;
2237+
1308ab2a 2238+ AuRwMustWriteLock(&iinfo->ii_rwsem);
2239+
1facf9fc 2240+ hip = iinfo->ii_hinode + bindex;
2241+ memmove(hip + 1, hip, sizeof(*hip) * amount);
2242+ hip->hi_inode = NULL;
4a4d8108 2243+ au_hn_init(hip);
1facf9fc 2244+ iinfo->ii_bend++;
2245+ if (unlikely(bend < 0))
2246+ iinfo->ii_bstart = 0;
2247+}
2248+
2249+static void au_br_do_add(struct super_block *sb, struct dentry *h_dentry,
2250+ struct au_branch *br, aufs_bindex_t bindex)
2251+{
2252+ struct dentry *root;
2253+ struct inode *root_inode;
2254+ aufs_bindex_t bend, amount;
2255+
2256+ root = sb->s_root;
2257+ root_inode = root->d_inode;
1facf9fc 2258+ bend = au_sbend(sb);
2259+ amount = bend + 1 - bindex;
53392da6 2260+ au_sbilist_lock();
1facf9fc 2261+ au_br_do_add_brp(au_sbi(sb), bindex, br, bend, amount);
2262+ au_br_do_add_hdp(au_di(root), bindex, bend, amount);
2263+ au_br_do_add_hip(au_ii(root_inode), bindex, bend, amount);
2264+ au_set_h_dptr(root, bindex, dget(h_dentry));
2265+ au_set_h_iptr(root_inode, bindex, au_igrab(h_dentry->d_inode),
2266+ /*flags*/0);
53392da6 2267+ au_sbilist_unlock();
1facf9fc 2268+}
2269+
2270+int au_br_add(struct super_block *sb, struct au_opt_add *add, int remount)
2271+{
2272+ int err;
1facf9fc 2273+ aufs_bindex_t bend, add_bindex;
2274+ struct dentry *root, *h_dentry;
2275+ struct inode *root_inode;
2276+ struct au_branch *add_branch;
2277+
2278+ root = sb->s_root;
2279+ root_inode = root->d_inode;
2280+ IMustLock(root_inode);
2281+ err = test_add(sb, add, remount);
2282+ if (unlikely(err < 0))
2283+ goto out;
2284+ if (err) {
2285+ err = 0;
2286+ goto out; /* success */
2287+ }
2288+
2289+ bend = au_sbend(sb);
2290+ add_branch = au_br_alloc(sb, bend + 2, add->perm);
2291+ err = PTR_ERR(add_branch);
2292+ if (IS_ERR(add_branch))
2293+ goto out;
2294+
2295+ err = au_br_init(add_branch, sb, add);
2296+ if (unlikely(err)) {
2297+ au_br_do_free(add_branch);
2298+ goto out;
2299+ }
2300+
2301+ add_bindex = add->bindex;
2302+ h_dentry = add->path.dentry;
2303+ if (!remount)
2304+ au_br_do_add(sb, h_dentry, add_branch, add_bindex);
2305+ else {
2306+ sysaufs_brs_del(sb, add_bindex);
2307+ au_br_do_add(sb, h_dentry, add_branch, add_bindex);
2308+ sysaufs_brs_add(sb, add_bindex);
2309+ }
2310+
1308ab2a 2311+ if (!add_bindex) {
1facf9fc 2312+ au_cpup_attr_all(root_inode, /*force*/1);
1308ab2a 2313+ sb->s_maxbytes = h_dentry->d_sb->s_maxbytes;
2314+ } else
1facf9fc 2315+ au_add_nlink(root_inode, h_dentry->d_inode);
1facf9fc 2316+
2317+ /*
4a4d8108 2318+ * this test/set prevents aufs from handling unnecesary notify events
027c5e7a 2319+ * of xino files, in case of re-adding a writable branch which was
1facf9fc 2320+ * once detached from aufs.
2321+ */
2322+ if (au_xino_brid(sb) < 0
2323+ && au_br_writable(add_branch->br_perm)
2324+ && !au_test_fs_bad_xino(h_dentry->d_sb)
2325+ && add_branch->br_xino.xi_file
2326+ && add_branch->br_xino.xi_file->f_dentry->d_parent == h_dentry)
2327+ au_xino_brid_set(sb, add_branch->br_id);
2328+
4f0767ce 2329+out:
1facf9fc 2330+ return err;
2331+}
2332+
2333+/* ---------------------------------------------------------------------- */
2334+
2335+/*
2336+ * delete a branch
2337+ */
2338+
2339+/* to show the line number, do not make it inlined function */
4a4d8108 2340+#define AuVerbose(do_info, fmt, ...) do { \
1facf9fc 2341+ if (do_info) \
4a4d8108 2342+ pr_info(fmt, ##__VA_ARGS__); \
1facf9fc 2343+} while (0)
2344+
027c5e7a
AM
2345+static int au_test_ibusy(struct inode *inode, aufs_bindex_t bstart,
2346+ aufs_bindex_t bend)
2347+{
2348+ return (inode && !S_ISDIR(inode->i_mode)) || bstart == bend;
2349+}
2350+
2351+static int au_test_dbusy(struct dentry *dentry, aufs_bindex_t bstart,
2352+ aufs_bindex_t bend)
2353+{
2354+ return au_test_ibusy(dentry->d_inode, bstart, bend);
2355+}
2356+
1facf9fc 2357+/*
2358+ * test if the branch is deletable or not.
2359+ */
2360+static int test_dentry_busy(struct dentry *root, aufs_bindex_t bindex,
b752ccd1 2361+ unsigned int sigen, const unsigned int verbose)
1facf9fc 2362+{
2363+ int err, i, j, ndentry;
2364+ aufs_bindex_t bstart, bend;
1facf9fc 2365+ struct au_dcsub_pages dpages;
2366+ struct au_dpage *dpage;
2367+ struct dentry *d;
1facf9fc 2368+
2369+ err = au_dpages_init(&dpages, GFP_NOFS);
2370+ if (unlikely(err))
2371+ goto out;
2372+ err = au_dcsub_pages(&dpages, root, NULL, NULL);
2373+ if (unlikely(err))
2374+ goto out_dpages;
2375+
1facf9fc 2376+ for (i = 0; !err && i < dpages.ndpage; i++) {
2377+ dpage = dpages.dpages + i;
2378+ ndentry = dpage->ndentry;
2379+ for (j = 0; !err && j < ndentry; j++) {
2380+ d = dpage->dentries[j];
027c5e7a
AM
2381+ AuDebugOn(!d->d_count);
2382+ if (!au_digen_test(d, sigen)) {
1facf9fc 2383+ di_read_lock_child(d, AuLock_IR);
027c5e7a
AM
2384+ if (unlikely(au_dbrange_test(d))) {
2385+ di_read_unlock(d, AuLock_IR);
2386+ continue;
2387+ }
2388+ } else {
1facf9fc 2389+ di_write_lock_child(d);
027c5e7a
AM
2390+ if (unlikely(au_dbrange_test(d))) {
2391+ di_write_unlock(d);
2392+ continue;
2393+ }
1facf9fc 2394+ err = au_reval_dpath(d, sigen);
2395+ if (!err)
2396+ di_downgrade_lock(d, AuLock_IR);
2397+ else {
2398+ di_write_unlock(d);
2399+ break;
2400+ }
2401+ }
2402+
027c5e7a 2403+ /* AuDbgDentry(d); */
1facf9fc 2404+ bstart = au_dbstart(d);
2405+ bend = au_dbend(d);
2406+ if (bstart <= bindex
2407+ && bindex <= bend
2408+ && au_h_dptr(d, bindex)
027c5e7a 2409+ && au_test_dbusy(d, bstart, bend)) {
1facf9fc 2410+ err = -EBUSY;
2411+ AuVerbose(verbose, "busy %.*s\n", AuDLNPair(d));
027c5e7a 2412+ AuDbgDentry(d);
1facf9fc 2413+ }
2414+ di_read_unlock(d, AuLock_IR);
2415+ }
2416+ }
2417+
4f0767ce 2418+out_dpages:
1facf9fc 2419+ au_dpages_free(&dpages);
4f0767ce 2420+out:
1facf9fc 2421+ return err;
2422+}
2423+
2424+static int test_inode_busy(struct super_block *sb, aufs_bindex_t bindex,
b752ccd1 2425+ unsigned int sigen, const unsigned int verbose)
1facf9fc 2426+{
2427+ int err;
7f207e10
AM
2428+ unsigned long long max, ull;
2429+ struct inode *i, **array;
1facf9fc 2430+ aufs_bindex_t bstart, bend;
1facf9fc 2431+
7f207e10
AM
2432+ array = au_iarray_alloc(sb, &max);
2433+ err = PTR_ERR(array);
2434+ if (IS_ERR(array))
2435+ goto out;
2436+
1facf9fc 2437+ err = 0;
7f207e10
AM
2438+ AuDbg("b%d\n", bindex);
2439+ for (ull = 0; !err && ull < max; ull++) {
2440+ i = array[ull];
2441+ if (i->i_ino == AUFS_ROOT_INO)
1facf9fc 2442+ continue;
2443+
7f207e10 2444+ /* AuDbgInode(i); */
1facf9fc 2445+ if (au_iigen(i) == sigen)
2446+ ii_read_lock_child(i);
2447+ else {
2448+ ii_write_lock_child(i);
027c5e7a
AM
2449+ err = au_refresh_hinode_self(i);
2450+ au_iigen_dec(i);
1facf9fc 2451+ if (!err)
2452+ ii_downgrade_lock(i);
2453+ else {
2454+ ii_write_unlock(i);
2455+ break;
2456+ }
2457+ }
2458+
2459+ bstart = au_ibstart(i);
2460+ bend = au_ibend(i);
2461+ if (bstart <= bindex
2462+ && bindex <= bend
2463+ && au_h_iptr(i, bindex)
027c5e7a 2464+ && au_test_ibusy(i, bstart, bend)) {
1facf9fc 2465+ err = -EBUSY;
2466+ AuVerbose(verbose, "busy i%lu\n", i->i_ino);
7f207e10 2467+ AuDbgInode(i);
1facf9fc 2468+ }
2469+ ii_read_unlock(i);
2470+ }
7f207e10 2471+ au_iarray_free(array, max);
1facf9fc 2472+
7f207e10 2473+out:
1facf9fc 2474+ return err;
2475+}
2476+
b752ccd1
AM
2477+static int test_children_busy(struct dentry *root, aufs_bindex_t bindex,
2478+ const unsigned int verbose)
1facf9fc 2479+{
2480+ int err;
2481+ unsigned int sigen;
2482+
2483+ sigen = au_sigen(root->d_sb);
2484+ DiMustNoWaiters(root);
2485+ IiMustNoWaiters(root->d_inode);
2486+ di_write_unlock(root);
b752ccd1 2487+ err = test_dentry_busy(root, bindex, sigen, verbose);
1facf9fc 2488+ if (!err)
b752ccd1 2489+ err = test_inode_busy(root->d_sb, bindex, sigen, verbose);
1facf9fc 2490+ di_write_lock_child(root); /* aufs_write_lock() calls ..._child() */
2491+
2492+ return err;
2493+}
2494+
2495+static void au_br_do_del_brp(struct au_sbinfo *sbinfo,
2496+ const aufs_bindex_t bindex,
2497+ const aufs_bindex_t bend)
2498+{
2499+ struct au_branch **brp, **p;
2500+
dece6358
AM
2501+ AuRwMustWriteLock(&sbinfo->si_rwsem);
2502+
1facf9fc 2503+ brp = sbinfo->si_branch + bindex;
2504+ if (bindex < bend)
2505+ memmove(brp, brp + 1, sizeof(*brp) * (bend - bindex));
2506+ sbinfo->si_branch[0 + bend] = NULL;
2507+ sbinfo->si_bend--;
2508+
53392da6 2509+ p = krealloc(sbinfo->si_branch, sizeof(*p) * bend, AuGFP_SBILIST);
1facf9fc 2510+ if (p)
2511+ sbinfo->si_branch = p;
4a4d8108 2512+ /* harmless error */
1facf9fc 2513+}
2514+
2515+static void au_br_do_del_hdp(struct au_dinfo *dinfo, const aufs_bindex_t bindex,
2516+ const aufs_bindex_t bend)
2517+{
2518+ struct au_hdentry *hdp, *p;
2519+
1308ab2a 2520+ AuRwMustWriteLock(&dinfo->di_rwsem);
2521+
4a4d8108 2522+ hdp = dinfo->di_hdentry;
1facf9fc 2523+ if (bindex < bend)
4a4d8108
AM
2524+ memmove(hdp + bindex, hdp + bindex + 1,
2525+ sizeof(*hdp) * (bend - bindex));
2526+ hdp[0 + bend].hd_dentry = NULL;
1facf9fc 2527+ dinfo->di_bend--;
2528+
53392da6 2529+ p = krealloc(hdp, sizeof(*p) * bend, AuGFP_SBILIST);
1facf9fc 2530+ if (p)
2531+ dinfo->di_hdentry = p;
4a4d8108 2532+ /* harmless error */
1facf9fc 2533+}
2534+
2535+static void au_br_do_del_hip(struct au_iinfo *iinfo, const aufs_bindex_t bindex,
2536+ const aufs_bindex_t bend)
2537+{
2538+ struct au_hinode *hip, *p;
2539+
1308ab2a 2540+ AuRwMustWriteLock(&iinfo->ii_rwsem);
2541+
1facf9fc 2542+ hip = iinfo->ii_hinode + bindex;
2543+ if (bindex < bend)
2544+ memmove(hip, hip + 1, sizeof(*hip) * (bend - bindex));
2545+ iinfo->ii_hinode[0 + bend].hi_inode = NULL;
4a4d8108 2546+ au_hn_init(iinfo->ii_hinode + bend);
1facf9fc 2547+ iinfo->ii_bend--;
2548+
53392da6 2549+ p = krealloc(iinfo->ii_hinode, sizeof(*p) * bend, AuGFP_SBILIST);
1facf9fc 2550+ if (p)
2551+ iinfo->ii_hinode = p;
4a4d8108 2552+ /* harmless error */
1facf9fc 2553+}
2554+
2555+static void au_br_do_del(struct super_block *sb, aufs_bindex_t bindex,
2556+ struct au_branch *br)
2557+{
2558+ aufs_bindex_t bend;
2559+ struct au_sbinfo *sbinfo;
53392da6
AM
2560+ struct dentry *root, *h_root;
2561+ struct inode *inode, *h_inode;
2562+ struct au_hinode *hinode;
1facf9fc 2563+
dece6358
AM
2564+ SiMustWriteLock(sb);
2565+
1facf9fc 2566+ root = sb->s_root;
2567+ inode = root->d_inode;
1facf9fc 2568+ sbinfo = au_sbi(sb);
2569+ bend = sbinfo->si_bend;
2570+
53392da6
AM
2571+ h_root = au_h_dptr(root, bindex);
2572+ hinode = au_hi(inode, bindex);
2573+ h_inode = au_igrab(hinode->hi_inode);
2574+ au_hiput(hinode);
1facf9fc 2575+
53392da6 2576+ au_sbilist_lock();
1facf9fc 2577+ au_br_do_del_brp(sbinfo, bindex, bend);
2578+ au_br_do_del_hdp(au_di(root), bindex, bend);
2579+ au_br_do_del_hip(au_ii(inode), bindex, bend);
53392da6
AM
2580+ au_sbilist_unlock();
2581+
2582+ dput(h_root);
2583+ iput(h_inode);
2584+ au_br_do_free(br);
1facf9fc 2585+}
2586+
2587+int au_br_del(struct super_block *sb, struct au_opt_del *del, int remount)
2588+{
2589+ int err, rerr, i;
2590+ unsigned int mnt_flags;
2591+ aufs_bindex_t bindex, bend, br_id;
2592+ unsigned char do_wh, verbose;
2593+ struct au_branch *br;
2594+ struct au_wbr *wbr;
2595+
2596+ err = 0;
2597+ bindex = au_find_dbindex(sb->s_root, del->h_path.dentry);
2598+ if (bindex < 0) {
2599+ if (remount)
2600+ goto out; /* success */
2601+ err = -ENOENT;
4a4d8108 2602+ pr_err("%s no such branch\n", del->pathname);
1facf9fc 2603+ goto out;
2604+ }
2605+ AuDbg("bindex b%d\n", bindex);
2606+
2607+ err = -EBUSY;
2608+ mnt_flags = au_mntflags(sb);
2609+ verbose = !!au_opt_test(mnt_flags, VERBOSE);
2610+ bend = au_sbend(sb);
2611+ if (unlikely(!bend)) {
2612+ AuVerbose(verbose, "no more branches left\n");
2613+ goto out;
2614+ }
2615+ br = au_sbr(sb, bindex);
2616+ i = atomic_read(&br->br_count);
2617+ if (unlikely(i)) {
2618+ AuVerbose(verbose, "%d file(s) opened\n", i);
e49829fe 2619+ goto out;
1facf9fc 2620+ }
2621+
2622+ wbr = br->br_wbr;
2623+ do_wh = wbr && (wbr->wbr_whbase || wbr->wbr_plink || wbr->wbr_orph);
2624+ if (do_wh) {
1308ab2a 2625+ /* instead of WbrWhMustWriteLock(wbr) */
2626+ SiMustWriteLock(sb);
1facf9fc 2627+ for (i = 0; i < AuBrWh_Last; i++) {
2628+ dput(wbr->wbr_wh[i]);
2629+ wbr->wbr_wh[i] = NULL;
2630+ }
2631+ }
2632+
b752ccd1 2633+ err = test_children_busy(sb->s_root, bindex, verbose);
1facf9fc 2634+ if (unlikely(err)) {
2635+ if (do_wh)
2636+ goto out_wh;
2637+ goto out;
2638+ }
2639+
2640+ err = 0;
2641+ br_id = br->br_id;
2642+ if (!remount)
2643+ au_br_do_del(sb, bindex, br);
2644+ else {
2645+ sysaufs_brs_del(sb, bindex);
2646+ au_br_do_del(sb, bindex, br);
2647+ sysaufs_brs_add(sb, bindex);
2648+ }
2649+
1308ab2a 2650+ if (!bindex) {
1facf9fc 2651+ au_cpup_attr_all(sb->s_root->d_inode, /*force*/1);
1308ab2a 2652+ sb->s_maxbytes = au_sbr_sb(sb, 0)->s_maxbytes;
2653+ } else
1facf9fc 2654+ au_sub_nlink(sb->s_root->d_inode, del->h_path.dentry->d_inode);
2655+ if (au_opt_test(mnt_flags, PLINK))
2656+ au_plink_half_refresh(sb, br_id);
2657+
b752ccd1 2658+ if (au_xino_brid(sb) == br_id)
1facf9fc 2659+ au_xino_brid_set(sb, -1);
2660+ goto out; /* success */
2661+
4f0767ce 2662+out_wh:
1facf9fc 2663+ /* revert */
2664+ rerr = au_br_init_wh(sb, br, br->br_perm, del->h_path.dentry);
2665+ if (rerr)
4a4d8108
AM
2666+ pr_warning("failed re-creating base whiteout, %s. (%d)\n",
2667+ del->pathname, rerr);
4f0767ce 2668+out:
1facf9fc 2669+ return err;
2670+}
2671+
2672+/* ---------------------------------------------------------------------- */
2673+
027c5e7a
AM
2674+static int au_ibusy(struct super_block *sb, struct aufs_ibusy __user *arg)
2675+{
2676+ int err;
2677+ aufs_bindex_t bstart, bend;
2678+ struct aufs_ibusy ibusy;
2679+ struct inode *inode, *h_inode;
2680+
2681+ err = -EPERM;
2682+ if (unlikely(!capable(CAP_SYS_ADMIN)))
2683+ goto out;
2684+
2685+ err = copy_from_user(&ibusy, arg, sizeof(ibusy));
2686+ if (!err)
2687+ err = !access_ok(VERIFY_WRITE, &arg->h_ino, sizeof(arg->h_ino));
2688+ if (unlikely(err)) {
2689+ err = -EFAULT;
2690+ AuTraceErr(err);
2691+ goto out;
2692+ }
2693+
2694+ err = -EINVAL;
2695+ si_read_lock(sb, AuLock_FLUSH);
2696+ if (unlikely(ibusy.bindex < 0 || ibusy.bindex > au_sbend(sb)))
2697+ goto out_unlock;
2698+
2699+ err = 0;
2700+ ibusy.h_ino = 0; /* invalid */
2701+ inode = ilookup(sb, ibusy.ino);
2702+ if (!inode
2703+ || inode->i_ino == AUFS_ROOT_INO
2704+ || is_bad_inode(inode))
2705+ goto out_unlock;
2706+
2707+ ii_read_lock_child(inode);
2708+ bstart = au_ibstart(inode);
2709+ bend = au_ibend(inode);
2710+ if (bstart <= ibusy.bindex && ibusy.bindex <= bend) {
2711+ h_inode = au_h_iptr(inode, ibusy.bindex);
2712+ if (h_inode && au_test_ibusy(inode, bstart, bend))
2713+ ibusy.h_ino = h_inode->i_ino;
2714+ }
2715+ ii_read_unlock(inode);
2716+ iput(inode);
2717+
2718+out_unlock:
2719+ si_read_unlock(sb);
2720+ if (!err) {
2721+ err = __put_user(ibusy.h_ino, &arg->h_ino);
2722+ if (unlikely(err)) {
2723+ err = -EFAULT;
2724+ AuTraceErr(err);
2725+ }
2726+ }
2727+out:
2728+ return err;
2729+}
2730+
2731+long au_ibusy_ioctl(struct file *file, unsigned long arg)
2732+{
2733+ return au_ibusy(file->f_dentry->d_sb, (void __user *)arg);
2734+}
2735+
2736+#ifdef CONFIG_COMPAT
2737+long au_ibusy_compat_ioctl(struct file *file, unsigned long arg)
2738+{
2739+ return au_ibusy(file->f_dentry->d_sb, compat_ptr(arg));
2740+}
2741+#endif
2742+
2743+/* ---------------------------------------------------------------------- */
2744+
1facf9fc 2745+/*
2746+ * change a branch permission
2747+ */
2748+
dece6358
AM
2749+static void au_warn_ima(void)
2750+{
2751+#ifdef CONFIG_IMA
1308ab2a 2752+ /* since it doesn't support mark_files_ro() */
027c5e7a 2753+ AuWarn1("RW -> RO makes IMA to produce wrong message\n");
dece6358
AM
2754+#endif
2755+}
2756+
1facf9fc 2757+static int do_need_sigen_inc(int a, int b)
2758+{
2759+ return au_br_whable(a) && !au_br_whable(b);
2760+}
2761+
2762+static int need_sigen_inc(int old, int new)
2763+{
2764+ return do_need_sigen_inc(old, new)
2765+ || do_need_sigen_inc(new, old);
2766+}
2767+
7f207e10
AM
2768+static unsigned long long au_farray_cb(void *a,
2769+ unsigned long long max __maybe_unused,
2770+ void *arg)
2771+{
2772+ unsigned long long n;
2773+ struct file **p, *f;
2774+ struct super_block *sb = arg;
2775+
2776+ n = 0;
2777+ p = a;
2778+ lg_global_lock(files_lglock);
2779+ do_file_list_for_each_entry(sb, f) {
2780+ if (au_fi(f)
027c5e7a 2781+ && file_count(f)
7f207e10
AM
2782+ && !special_file(f->f_dentry->d_inode->i_mode)) {
2783+ get_file(f);
2784+ *p++ = f;
2785+ n++;
2786+ AuDebugOn(n > max);
2787+ }
2788+ } while_file_list_for_each_entry;
2789+ lg_global_unlock(files_lglock);
2790+
2791+ return n;
2792+}
2793+
2794+static struct file **au_farray_alloc(struct super_block *sb,
2795+ unsigned long long *max)
2796+{
2797+ *max = atomic_long_read(&au_sbi(sb)->si_nfiles);
2798+ return au_array_alloc(max, au_farray_cb, sb);
2799+}
2800+
2801+static void au_farray_free(struct file **a, unsigned long long max)
2802+{
2803+ unsigned long long ull;
2804+
2805+ for (ull = 0; ull < max; ull++)
2806+ if (a[ull])
2807+ fput(a[ull]);
2808+ au_array_free(a);
2809+}
2810+
1facf9fc 2811+static int au_br_mod_files_ro(struct super_block *sb, aufs_bindex_t bindex)
2812+{
7f207e10 2813+ int err, do_warn;
027c5e7a 2814+ unsigned int mnt_flags;
7f207e10 2815+ unsigned long long ull, max;
e49829fe 2816+ aufs_bindex_t br_id;
027c5e7a 2817+ unsigned char verbose;
7f207e10 2818+ struct file *file, *hf, **array;
e49829fe
JR
2819+ struct inode *inode;
2820+ struct au_hfile *hfile;
1facf9fc 2821+
027c5e7a
AM
2822+ mnt_flags = au_mntflags(sb);
2823+ verbose = !!au_opt_test(mnt_flags, VERBOSE);
2824+
7f207e10
AM
2825+ array = au_farray_alloc(sb, &max);
2826+ err = PTR_ERR(array);
2827+ if (IS_ERR(array))
1facf9fc 2828+ goto out;
2829+
7f207e10 2830+ do_warn = 0;
e49829fe 2831+ br_id = au_sbr_id(sb, bindex);
7f207e10
AM
2832+ for (ull = 0; ull < max; ull++) {
2833+ file = array[ull];
1facf9fc 2834+
7f207e10 2835+ /* AuDbg("%.*s\n", AuDLNPair(file->f_dentry)); */
1facf9fc 2836+ fi_read_lock(file);
2837+ if (unlikely(au_test_mmapped(file))) {
2838+ err = -EBUSY;
027c5e7a
AM
2839+ AuVerbose(verbose, "mmapped %.*s\n",
2840+ AuDLNPair(file->f_dentry));
7f207e10 2841+ AuDbgFile(file);
1facf9fc 2842+ FiMustNoWaiters(file);
2843+ fi_read_unlock(file);
7f207e10 2844+ goto out_array;
1facf9fc 2845+ }
2846+
027c5e7a 2847+ inode = file->f_dentry->d_inode;
e49829fe
JR
2848+ hfile = &au_fi(file)->fi_htop;
2849+ hf = hfile->hf_file;
2850+ if (!S_ISREG(inode->i_mode)
1facf9fc 2851+ || !(file->f_mode & FMODE_WRITE)
e49829fe 2852+ || hfile->hf_br->br_id != br_id
7f207e10
AM
2853+ || !(hf->f_mode & FMODE_WRITE))
2854+ array[ull] = NULL;
2855+ else {
2856+ do_warn = 1;
2857+ get_file(file);
1facf9fc 2858+ }
2859+
1facf9fc 2860+ FiMustNoWaiters(file);
2861+ fi_read_unlock(file);
7f207e10
AM
2862+ fput(file);
2863+ }
1facf9fc 2864+
2865+ err = 0;
7f207e10 2866+ if (do_warn)
dece6358 2867+ au_warn_ima();
7f207e10
AM
2868+
2869+ for (ull = 0; ull < max; ull++) {
2870+ file = array[ull];
2871+ if (!file)
2872+ continue;
2873+
1facf9fc 2874+ /* todo: already flushed? */
2875+ /* cf. fs/super.c:mark_files_ro() */
7f207e10
AM
2876+ /* fi_read_lock(file); */
2877+ hfile = &au_fi(file)->fi_htop;
2878+ hf = hfile->hf_file;
2879+ /* fi_read_unlock(file); */
027c5e7a 2880+ spin_lock(&hf->f_lock);
1facf9fc 2881+ hf->f_mode &= ~FMODE_WRITE;
027c5e7a 2882+ spin_unlock(&hf->f_lock);
1facf9fc 2883+ if (!file_check_writeable(hf)) {
2884+ file_release_write(hf);
2885+ mnt_drop_write(hf->f_vfsmnt);
2886+ }
2887+ }
2888+
7f207e10
AM
2889+out_array:
2890+ au_farray_free(array, max);
4f0767ce 2891+out:
7f207e10 2892+ AuTraceErr(err);
1facf9fc 2893+ return err;
2894+}
2895+
2896+int au_br_mod(struct super_block *sb, struct au_opt_mod *mod, int remount,
7f207e10 2897+ int *do_refresh)
1facf9fc 2898+{
2899+ int err, rerr;
2900+ aufs_bindex_t bindex;
1308ab2a 2901+ struct path path;
1facf9fc 2902+ struct dentry *root;
2903+ struct au_branch *br;
2904+
2905+ root = sb->s_root;
1facf9fc 2906+ bindex = au_find_dbindex(root, mod->h_root);
2907+ if (bindex < 0) {
2908+ if (remount)
2909+ return 0; /* success */
2910+ err = -ENOENT;
4a4d8108 2911+ pr_err("%s no such branch\n", mod->path);
1facf9fc 2912+ goto out;
2913+ }
2914+ AuDbg("bindex b%d\n", bindex);
2915+
2916+ err = test_br(mod->h_root->d_inode, mod->perm, mod->path);
2917+ if (unlikely(err))
2918+ goto out;
2919+
2920+ br = au_sbr(sb, bindex);
2921+ if (br->br_perm == mod->perm)
2922+ return 0; /* success */
2923+
2924+ if (au_br_writable(br->br_perm)) {
2925+ /* remove whiteout base */
2926+ err = au_br_init_wh(sb, br, mod->perm, mod->h_root);
2927+ if (unlikely(err))
2928+ goto out;
2929+
2930+ if (!au_br_writable(mod->perm)) {
2931+ /* rw --> ro, file might be mmapped */
2932+ DiMustNoWaiters(root);
2933+ IiMustNoWaiters(root->d_inode);
2934+ di_write_unlock(root);
2935+ err = au_br_mod_files_ro(sb, bindex);
2936+ /* aufs_write_lock() calls ..._child() */
2937+ di_write_lock_child(root);
2938+
2939+ if (unlikely(err)) {
2940+ rerr = -ENOMEM;
2941+ br->br_wbr = kmalloc(sizeof(*br->br_wbr),
2942+ GFP_NOFS);
1308ab2a 2943+ if (br->br_wbr) {
2944+ path.mnt = br->br_mnt;
2945+ path.dentry = mod->h_root;
2946+ rerr = au_wbr_init(br, sb, br->br_perm,
2947+ &path);
2948+ }
1facf9fc 2949+ if (unlikely(rerr)) {
2950+ AuIOErr("nested error %d (%d)\n",
2951+ rerr, err);
2952+ br->br_perm = mod->perm;
2953+ }
2954+ }
2955+ }
2956+ } else if (au_br_writable(mod->perm)) {
2957+ /* ro --> rw */
2958+ err = -ENOMEM;
2959+ br->br_wbr = kmalloc(sizeof(*br->br_wbr), GFP_NOFS);
2960+ if (br->br_wbr) {
1308ab2a 2961+ path.mnt = br->br_mnt;
2962+ path.dentry = mod->h_root;
1facf9fc 2963+ err = au_wbr_init(br, sb, mod->perm, &path);
2964+ if (unlikely(err)) {
2965+ kfree(br->br_wbr);
2966+ br->br_wbr = NULL;
2967+ }
2968+ }
2969+ }
2970+
2971+ if (!err) {
7f207e10 2972+ *do_refresh |= need_sigen_inc(br->br_perm, mod->perm);
1facf9fc 2973+ br->br_perm = mod->perm;
2974+ }
2975+
4f0767ce 2976+out:
7f207e10 2977+ AuTraceErr(err);
1facf9fc 2978+ return err;
2979+}
7f207e10
AM
2980diff -urN /usr/share/empty/fs/aufs/branch.h linux/fs/aufs/branch.h
2981--- /usr/share/empty/fs/aufs/branch.h 1970-01-01 01:00:00.000000000 +0100
7ce627cf 2982+++ linux/fs/aufs/branch.h 2012-05-22 09:06:08.864125478 +0200
f6c5ef8b 2983@@ -0,0 +1,230 @@
1facf9fc 2984+/*
f6c5ef8b 2985+ * Copyright (C) 2005-2012 Junjiro R. Okajima
1facf9fc 2986+ *
2987+ * This program, aufs is free software; you can redistribute it and/or modify
2988+ * it under the terms of the GNU General Public License as published by
2989+ * the Free Software Foundation; either version 2 of the License, or
2990+ * (at your option) any later version.
dece6358
AM
2991+ *
2992+ * This program is distributed in the hope that it will be useful,
2993+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
2994+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2995+ * GNU General Public License for more details.
2996+ *
2997+ * You should have received a copy of the GNU General Public License
2998+ * along with this program; if not, write to the Free Software
2999+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 3000+ */
3001+
3002+/*
3003+ * branch filesystems and xino for them
3004+ */
3005+
3006+#ifndef __AUFS_BRANCH_H__
3007+#define __AUFS_BRANCH_H__
3008+
3009+#ifdef __KERNEL__
3010+
1facf9fc 3011+#include <linux/mount.h>
4a4d8108 3012+#include "dynop.h"
1facf9fc 3013+#include "rwsem.h"
3014+#include "super.h"
3015+
3016+/* ---------------------------------------------------------------------- */
3017+
3018+/* a xino file */
3019+struct au_xino_file {
3020+ struct file *xi_file;
3021+ struct mutex xi_nondir_mtx;
3022+
3023+ /* todo: make xino files an array to support huge inode number */
3024+
3025+#ifdef CONFIG_DEBUG_FS
3026+ struct dentry *xi_dbgaufs;
3027+#endif
3028+};
3029+
3030+/* members for writable branch only */
3031+enum {AuBrWh_BASE, AuBrWh_PLINK, AuBrWh_ORPH, AuBrWh_Last};
3032+struct au_wbr {
dece6358 3033+ struct au_rwsem wbr_wh_rwsem;
1facf9fc 3034+ struct dentry *wbr_wh[AuBrWh_Last];
4a4d8108 3035+ atomic_t wbr_wh_running;
1facf9fc 3036+#define wbr_whbase wbr_wh[AuBrWh_BASE] /* whiteout base */
3037+#define wbr_plink wbr_wh[AuBrWh_PLINK] /* pseudo-link dir */
3038+#define wbr_orph wbr_wh[AuBrWh_ORPH] /* dir for orphans */
3039+
3040+ /* mfs mode */
3041+ unsigned long long wbr_bytes;
3042+};
3043+
4a4d8108
AM
3044+/* ext2 has 3 types of operations at least, ext3 has 4 */
3045+#define AuBrDynOp (AuDyLast * 4)
3046+
1facf9fc 3047+/* protected by superblock rwsem */
3048+struct au_branch {
3049+ struct au_xino_file br_xino;
3050+
3051+ aufs_bindex_t br_id;
3052+
3053+ int br_perm;
3054+ struct vfsmount *br_mnt;
4a4d8108
AM
3055+ spinlock_t br_dykey_lock;
3056+ struct au_dykey *br_dykey[AuBrDynOp];
1facf9fc 3057+ atomic_t br_count;
3058+
3059+ struct au_wbr *br_wbr;
3060+
3061+ /* xino truncation */
3062+ blkcnt_t br_xino_upper; /* watermark in blocks */
3063+ atomic_t br_xino_running;
3064+
027c5e7a
AM
3065+#ifdef CONFIG_AUFS_HFSNOTIFY
3066+ struct fsnotify_group *br_hfsn_group;
3067+ struct fsnotify_ops br_hfsn_ops;
3068+#endif
3069+
1facf9fc 3070+#ifdef CONFIG_SYSFS
3071+ /* an entry under sysfs per mount-point */
3072+ char br_name[8];
3073+ struct attribute br_attr;
3074+#endif
3075+};
3076+
3077+/* ---------------------------------------------------------------------- */
3078+
1e00d052
AM
3079+/* branch permissions and attributes */
3080+#define AuBrPerm_RW 1 /* writable, hardlinkable wh */
3081+#define AuBrPerm_RO (1 << 1) /* readonly */
3082+#define AuBrPerm_RR (1 << 2) /* natively readonly */
3083+#define AuBrPerm_Mask (AuBrPerm_RW | AuBrPerm_RO | AuBrPerm_RR)
1facf9fc 3084+
1e00d052 3085+#define AuBrRAttr_WH (1 << 3) /* whiteout-able */
1facf9fc 3086+
1e00d052 3087+#define AuBrWAttr_NoLinkWH (1 << 4) /* un-hardlinkable whiteouts */
1facf9fc 3088+
3089+static inline int au_br_writable(int brperm)
3090+{
1e00d052 3091+ return brperm & AuBrPerm_RW;
1facf9fc 3092+}
3093+
3094+static inline int au_br_whable(int brperm)
3095+{
1e00d052
AM
3096+ return brperm & (AuBrPerm_RW | AuBrRAttr_WH);
3097+}
3098+
3099+static inline int au_br_wh_linkable(int brperm)
3100+{
3101+ return !(brperm & AuBrWAttr_NoLinkWH);
1facf9fc 3102+}
3103+
3104+static inline int au_br_rdonly(struct au_branch *br)
3105+{
3106+ return ((br->br_mnt->mnt_sb->s_flags & MS_RDONLY)
3107+ || !au_br_writable(br->br_perm))
3108+ ? -EROFS : 0;
3109+}
3110+
4a4d8108 3111+static inline int au_br_hnotifyable(int brperm __maybe_unused)
1facf9fc 3112+{
4a4d8108 3113+#ifdef CONFIG_AUFS_HNOTIFY
1e00d052 3114+ return !(brperm & AuBrPerm_RR);
1facf9fc 3115+#else
3116+ return 0;
3117+#endif
3118+}
3119+
3120+/* ---------------------------------------------------------------------- */
3121+
3122+/* branch.c */
3123+struct au_sbinfo;
3124+void au_br_free(struct au_sbinfo *sinfo);
3125+int au_br_index(struct super_block *sb, aufs_bindex_t br_id);
3126+struct au_opt_add;
3127+int au_br_add(struct super_block *sb, struct au_opt_add *add, int remount);
3128+struct au_opt_del;
3129+int au_br_del(struct super_block *sb, struct au_opt_del *del, int remount);
027c5e7a
AM
3130+long au_ibusy_ioctl(struct file *file, unsigned long arg);
3131+#ifdef CONFIG_COMPAT
3132+long au_ibusy_compat_ioctl(struct file *file, unsigned long arg);
3133+#endif
1facf9fc 3134+struct au_opt_mod;
3135+int au_br_mod(struct super_block *sb, struct au_opt_mod *mod, int remount,
7f207e10 3136+ int *do_refresh);
1facf9fc 3137+
3138+/* xino.c */
3139+static const loff_t au_loff_max = LLONG_MAX;
3140+
3141+int au_xib_trunc(struct super_block *sb);
3142+ssize_t xino_fread(au_readf_t func, struct file *file, void *buf, size_t size,
3143+ loff_t *pos);
3144+ssize_t xino_fwrite(au_writef_t func, struct file *file, void *buf, size_t size,
3145+ loff_t *pos);
3146+struct file *au_xino_create2(struct file *base_file, struct file *copy_src);
3147+struct file *au_xino_create(struct super_block *sb, char *fname, int silent);
3148+ino_t au_xino_new_ino(struct super_block *sb);
b752ccd1 3149+void au_xino_delete_inode(struct inode *inode, const int unlinked);
1facf9fc 3150+int au_xino_write(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino,
3151+ ino_t ino);
3152+int au_xino_read(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino,
3153+ ino_t *ino);
3154+int au_xino_br(struct super_block *sb, struct au_branch *br, ino_t hino,
3155+ struct file *base_file, int do_test);
3156+int au_xino_trunc(struct super_block *sb, aufs_bindex_t bindex);
3157+
3158+struct au_opt_xino;
3159+int au_xino_set(struct super_block *sb, struct au_opt_xino *xino, int remount);
3160+void au_xino_clr(struct super_block *sb);
3161+struct file *au_xino_def(struct super_block *sb);
3162+int au_xino_path(struct seq_file *seq, struct file *file);
3163+
3164+/* ---------------------------------------------------------------------- */
3165+
3166+/* Superblock to branch */
3167+static inline
3168+aufs_bindex_t au_sbr_id(struct super_block *sb, aufs_bindex_t bindex)
3169+{
3170+ return au_sbr(sb, bindex)->br_id;
3171+}
3172+
3173+static inline
3174+struct vfsmount *au_sbr_mnt(struct super_block *sb, aufs_bindex_t bindex)
3175+{
3176+ return au_sbr(sb, bindex)->br_mnt;
3177+}
3178+
3179+static inline
3180+struct super_block *au_sbr_sb(struct super_block *sb, aufs_bindex_t bindex)
3181+{
3182+ return au_sbr_mnt(sb, bindex)->mnt_sb;
3183+}
3184+
3185+static inline void au_sbr_put(struct super_block *sb, aufs_bindex_t bindex)
3186+{
e49829fe 3187+ atomic_dec(&au_sbr(sb, bindex)->br_count);
1facf9fc 3188+}
3189+
3190+static inline int au_sbr_perm(struct super_block *sb, aufs_bindex_t bindex)
3191+{
3192+ return au_sbr(sb, bindex)->br_perm;
3193+}
3194+
3195+static inline int au_sbr_whable(struct super_block *sb, aufs_bindex_t bindex)
3196+{
3197+ return au_br_whable(au_sbr_perm(sb, bindex));
3198+}
3199+
3200+/* ---------------------------------------------------------------------- */
3201+
3202+/*
3203+ * wbr_wh_read_lock, wbr_wh_write_lock
3204+ * wbr_wh_read_unlock, wbr_wh_write_unlock, wbr_wh_downgrade_lock
3205+ */
3206+AuSimpleRwsemFuncs(wbr_wh, struct au_wbr *wbr, &wbr->wbr_wh_rwsem);
3207+
dece6358
AM
3208+#define WbrWhMustNoWaiters(wbr) AuRwMustNoWaiters(&wbr->wbr_wh_rwsem)
3209+#define WbrWhMustAnyLock(wbr) AuRwMustAnyLock(&wbr->wbr_wh_rwsem)
3210+#define WbrWhMustWriteLock(wbr) AuRwMustWriteLock(&wbr->wbr_wh_rwsem)
3211+
1facf9fc 3212+#endif /* __KERNEL__ */
3213+#endif /* __AUFS_BRANCH_H__ */
7f207e10
AM
3214diff -urN /usr/share/empty/fs/aufs/conf.mk linux/fs/aufs/conf.mk
3215--- /usr/share/empty/fs/aufs/conf.mk 1970-01-01 01:00:00.000000000 +0100
7ce627cf 3216+++ linux/fs/aufs/conf.mk 2012-05-22 09:06:08.864125478 +0200
2cbb1c4b 3217@@ -0,0 +1,38 @@
4a4d8108
AM
3218+
3219+AuConfStr = CONFIG_AUFS_FS=${CONFIG_AUFS_FS}
3220+
3221+define AuConf
3222+ifdef ${1}
3223+AuConfStr += ${1}=${${1}}
3224+endif
3225+endef
3226+
b752ccd1 3227+AuConfAll = BRANCH_MAX_127 BRANCH_MAX_511 BRANCH_MAX_1023 BRANCH_MAX_32767 \
e49829fe 3228+ SBILIST \
7f207e10 3229+ HNOTIFY HFSNOTIFY \
4a4d8108
AM
3230+ EXPORT INO_T_64 \
3231+ RDU \
2cbb1c4b 3232+ PROC_MAP \
4a4d8108
AM
3233+ SP_IATTR \
3234+ SHWH \
3235+ BR_RAMFS \
3236+ BR_FUSE POLL \
3237+ BR_HFSPLUS \
3238+ BDEV_LOOP \
b752ccd1
AM
3239+ DEBUG MAGIC_SYSRQ
3240+$(foreach i, ${AuConfAll}, \
4a4d8108
AM
3241+ $(eval $(call AuConf,CONFIG_AUFS_${i})))
3242+
3243+AuConfName = ${obj}/conf.str
3244+${AuConfName}.tmp: FORCE
3245+ @echo ${AuConfStr} | tr ' ' '\n' | sed -e 's/^/"/' -e 's/$$/\\n"/' > $@
3246+${AuConfName}: ${AuConfName}.tmp
3247+ @diff -q $< $@ > /dev/null 2>&1 || { \
3248+ echo ' GEN ' $@; \
3249+ cp -p $< $@; \
3250+ }
3251+FORCE:
3252+clean-files += ${AuConfName} ${AuConfName}.tmp
3253+${obj}/sysfs.o: ${AuConfName}
b752ccd1
AM
3254+
3255+-include ${srctree}/${src}/conf_priv.mk
7f207e10
AM
3256diff -urN /usr/share/empty/fs/aufs/cpup.c linux/fs/aufs/cpup.c
3257--- /usr/share/empty/fs/aufs/cpup.c 1970-01-01 01:00:00.000000000 +0100
7ce627cf 3258+++ linux/fs/aufs/cpup.c 2012-05-22 09:06:08.864125478 +0200
7eafdf33 3259@@ -0,0 +1,1084 @@
1facf9fc 3260+/*
f6c5ef8b 3261+ * Copyright (C) 2005-2012 Junjiro R. Okajima
1facf9fc 3262+ *
3263+ * This program, aufs is free software; you can redistribute it and/or modify
3264+ * it under the terms of the GNU General Public License as published by
3265+ * the Free Software Foundation; either version 2 of the License, or
3266+ * (at your option) any later version.
dece6358
AM
3267+ *
3268+ * This program is distributed in the hope that it will be useful,
3269+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
3270+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
3271+ * GNU General Public License for more details.
3272+ *
3273+ * You should have received a copy of the GNU General Public License
3274+ * along with this program; if not, write to the Free Software
3275+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 3276+ */
3277+
3278+/*
3279+ * copy-up functions, see wbr_policy.c for copy-down
3280+ */
3281+
3282+#include <linux/fs_stack.h>
dece6358 3283+#include <linux/mm.h>
1facf9fc 3284+#include "aufs.h"
3285+
3286+void au_cpup_attr_flags(struct inode *dst, struct inode *src)
3287+{
3288+ const unsigned int mask = S_DEAD | S_SWAPFILE | S_PRIVATE
3289+ | S_NOATIME | S_NOCMTIME;
3290+
3291+ dst->i_flags |= src->i_flags & ~mask;
3292+ if (au_test_fs_notime(dst->i_sb))
3293+ dst->i_flags |= S_NOATIME | S_NOCMTIME;
3294+}
3295+
3296+void au_cpup_attr_timesizes(struct inode *inode)
3297+{
3298+ struct inode *h_inode;
3299+
3300+ h_inode = au_h_iptr(inode, au_ibstart(inode));
3301+ fsstack_copy_attr_times(inode, h_inode);
4a4d8108 3302+ fsstack_copy_inode_size(inode, h_inode);
1facf9fc 3303+}
3304+
3305+void au_cpup_attr_nlink(struct inode *inode, int force)
3306+{
3307+ struct inode *h_inode;
3308+ struct super_block *sb;
3309+ aufs_bindex_t bindex, bend;
3310+
3311+ sb = inode->i_sb;
3312+ bindex = au_ibstart(inode);
3313+ h_inode = au_h_iptr(inode, bindex);
3314+ if (!force
3315+ && !S_ISDIR(h_inode->i_mode)
3316+ && au_opt_test(au_mntflags(sb), PLINK)
3317+ && au_plink_test(inode))
3318+ return;
3319+
7eafdf33
AM
3320+ /*
3321+ * 0 can happen in revalidating.
3322+ * h_inode->i_mutex is not held, but it is harmless since once i_nlink
3323+ * reaches 0, it will never become positive.
3324+ */
92d182d2 3325+ set_nlink(inode, h_inode->i_nlink);
1facf9fc 3326+
3327+ /*
3328+ * fewer nlink makes find(1) noisy, but larger nlink doesn't.
3329+ * it may includes whplink directory.
3330+ */
3331+ if (S_ISDIR(h_inode->i_mode)) {
3332+ bend = au_ibend(inode);
3333+ for (bindex++; bindex <= bend; bindex++) {
3334+ h_inode = au_h_iptr(inode, bindex);
3335+ if (h_inode)
3336+ au_add_nlink(inode, h_inode);
3337+ }
3338+ }
3339+}
3340+
3341+void au_cpup_attr_changeable(struct inode *inode)
3342+{
3343+ struct inode *h_inode;
3344+
3345+ h_inode = au_h_iptr(inode, au_ibstart(inode));
3346+ inode->i_mode = h_inode->i_mode;
3347+ inode->i_uid = h_inode->i_uid;
3348+ inode->i_gid = h_inode->i_gid;
3349+ au_cpup_attr_timesizes(inode);
3350+ au_cpup_attr_flags(inode, h_inode);
3351+}
3352+
3353+void au_cpup_igen(struct inode *inode, struct inode *h_inode)
3354+{
3355+ struct au_iinfo *iinfo = au_ii(inode);
3356+
1308ab2a 3357+ IiMustWriteLock(inode);
3358+
1facf9fc 3359+ iinfo->ii_higen = h_inode->i_generation;
3360+ iinfo->ii_hsb1 = h_inode->i_sb;
3361+}
3362+
3363+void au_cpup_attr_all(struct inode *inode, int force)
3364+{
3365+ struct inode *h_inode;
3366+
3367+ h_inode = au_h_iptr(inode, au_ibstart(inode));
3368+ au_cpup_attr_changeable(inode);
3369+ if (inode->i_nlink > 0)
3370+ au_cpup_attr_nlink(inode, force);
3371+ inode->i_rdev = h_inode->i_rdev;
3372+ inode->i_blkbits = h_inode->i_blkbits;
3373+ au_cpup_igen(inode, h_inode);
3374+}
3375+
3376+/* ---------------------------------------------------------------------- */
3377+
3378+/* Note: dt_dentry and dt_h_dentry are not dget/dput-ed */
3379+
3380+/* keep the timestamps of the parent dir when cpup */
3381+void au_dtime_store(struct au_dtime *dt, struct dentry *dentry,
3382+ struct path *h_path)
3383+{
3384+ struct inode *h_inode;
3385+
3386+ dt->dt_dentry = dentry;
3387+ dt->dt_h_path = *h_path;
3388+ h_inode = h_path->dentry->d_inode;
3389+ dt->dt_atime = h_inode->i_atime;
3390+ dt->dt_mtime = h_inode->i_mtime;
3391+ /* smp_mb(); */
3392+}
3393+
3394+void au_dtime_revert(struct au_dtime *dt)
3395+{
3396+ struct iattr attr;
3397+ int err;
3398+
3399+ attr.ia_atime = dt->dt_atime;
3400+ attr.ia_mtime = dt->dt_mtime;
3401+ attr.ia_valid = ATTR_FORCE | ATTR_MTIME | ATTR_MTIME_SET
3402+ | ATTR_ATIME | ATTR_ATIME_SET;
3403+
3404+ err = vfsub_notify_change(&dt->dt_h_path, &attr);
3405+ if (unlikely(err))
4a4d8108 3406+ pr_warning("restoring timestamps failed(%d). ignored\n", err);
1facf9fc 3407+}
3408+
3409+/* ---------------------------------------------------------------------- */
3410+
3411+static noinline_for_stack
3412+int cpup_iattr(struct dentry *dst, aufs_bindex_t bindex, struct dentry *h_src)
3413+{
3414+ int err, sbits;
3415+ struct iattr ia;
3416+ struct path h_path;
1308ab2a 3417+ struct inode *h_isrc, *h_idst;
1facf9fc 3418+
3419+ h_path.dentry = au_h_dptr(dst, bindex);
1308ab2a 3420+ h_idst = h_path.dentry->d_inode;
1facf9fc 3421+ h_path.mnt = au_sbr_mnt(dst->d_sb, bindex);
3422+ h_isrc = h_src->d_inode;
1308ab2a 3423+ ia.ia_valid = ATTR_FORCE | ATTR_UID | ATTR_GID
1facf9fc 3424+ | ATTR_ATIME | ATTR_MTIME
3425+ | ATTR_ATIME_SET | ATTR_MTIME_SET;
1facf9fc 3426+ ia.ia_uid = h_isrc->i_uid;
3427+ ia.ia_gid = h_isrc->i_gid;
3428+ ia.ia_atime = h_isrc->i_atime;
3429+ ia.ia_mtime = h_isrc->i_mtime;
1308ab2a 3430+ if (h_idst->i_mode != h_isrc->i_mode
3431+ && !S_ISLNK(h_idst->i_mode)) {
3432+ ia.ia_valid |= ATTR_MODE;
3433+ ia.ia_mode = h_isrc->i_mode;
3434+ }
3435+ sbits = !!(h_isrc->i_mode & (S_ISUID | S_ISGID));
3436+ au_cpup_attr_flags(h_idst, h_isrc);
1facf9fc 3437+ err = vfsub_notify_change(&h_path, &ia);
3438+
3439+ /* is this nfs only? */
3440+ if (!err && sbits && au_test_nfs(h_path.dentry->d_sb)) {
3441+ ia.ia_valid = ATTR_FORCE | ATTR_MODE;
3442+ ia.ia_mode = h_isrc->i_mode;
3443+ err = vfsub_notify_change(&h_path, &ia);
3444+ }
3445+
3446+ return err;
3447+}
3448+
3449+/* ---------------------------------------------------------------------- */
3450+
3451+static int au_do_copy_file(struct file *dst, struct file *src, loff_t len,
3452+ char *buf, unsigned long blksize)
3453+{
3454+ int err;
3455+ size_t sz, rbytes, wbytes;
3456+ unsigned char all_zero;
3457+ char *p, *zp;
3458+ struct mutex *h_mtx;
3459+ /* reduce stack usage */
3460+ struct iattr *ia;
3461+
3462+ zp = page_address(ZERO_PAGE(0));
3463+ if (unlikely(!zp))
3464+ return -ENOMEM; /* possible? */
3465+
3466+ err = 0;
3467+ all_zero = 0;
3468+ while (len) {
3469+ AuDbg("len %lld\n", len);
3470+ sz = blksize;
3471+ if (len < blksize)
3472+ sz = len;
3473+
3474+ rbytes = 0;
3475+ /* todo: signal_pending? */
3476+ while (!rbytes || err == -EAGAIN || err == -EINTR) {
3477+ rbytes = vfsub_read_k(src, buf, sz, &src->f_pos);
3478+ err = rbytes;
3479+ }
3480+ if (unlikely(err < 0))
3481+ break;
3482+
3483+ all_zero = 0;
3484+ if (len >= rbytes && rbytes == blksize)
3485+ all_zero = !memcmp(buf, zp, rbytes);
3486+ if (!all_zero) {
3487+ wbytes = rbytes;
3488+ p = buf;
3489+ while (wbytes) {
3490+ size_t b;
3491+
3492+ b = vfsub_write_k(dst, p, wbytes, &dst->f_pos);
3493+ err = b;
3494+ /* todo: signal_pending? */
3495+ if (unlikely(err == -EAGAIN || err == -EINTR))
3496+ continue;
3497+ if (unlikely(err < 0))
3498+ break;
3499+ wbytes -= b;
3500+ p += b;
3501+ }
3502+ } else {
3503+ loff_t res;
3504+
3505+ AuLabel(hole);
3506+ res = vfsub_llseek(dst, rbytes, SEEK_CUR);
3507+ err = res;
3508+ if (unlikely(res < 0))
3509+ break;
3510+ }
3511+ len -= rbytes;
3512+ err = 0;
3513+ }
3514+
3515+ /* the last block may be a hole */
3516+ if (!err && all_zero) {
3517+ AuLabel(last hole);
3518+
3519+ err = 1;
3520+ if (au_test_nfs(dst->f_dentry->d_sb)) {
3521+ /* nfs requires this step to make last hole */
3522+ /* is this only nfs? */
3523+ do {
3524+ /* todo: signal_pending? */
3525+ err = vfsub_write_k(dst, "\0", 1, &dst->f_pos);
3526+ } while (err == -EAGAIN || err == -EINTR);
3527+ if (err == 1)
3528+ dst->f_pos--;
3529+ }
3530+
3531+ if (err == 1) {
3532+ ia = (void *)buf;
3533+ ia->ia_size = dst->f_pos;
3534+ ia->ia_valid = ATTR_SIZE | ATTR_FILE;
3535+ ia->ia_file = dst;
3536+ h_mtx = &dst->f_dentry->d_inode->i_mutex;
3537+ mutex_lock_nested(h_mtx, AuLsc_I_CHILD2);
3538+ err = vfsub_notify_change(&dst->f_path, ia);
3539+ mutex_unlock(h_mtx);
3540+ }
3541+ }
3542+
3543+ return err;
3544+}
3545+
3546+int au_copy_file(struct file *dst, struct file *src, loff_t len)
3547+{
3548+ int err;
3549+ unsigned long blksize;
3550+ unsigned char do_kfree;
3551+ char *buf;
3552+
3553+ err = -ENOMEM;
3554+ blksize = dst->f_dentry->d_sb->s_blocksize;
3555+ if (!blksize || PAGE_SIZE < blksize)
3556+ blksize = PAGE_SIZE;
3557+ AuDbg("blksize %lu\n", blksize);
3558+ do_kfree = (blksize != PAGE_SIZE && blksize >= sizeof(struct iattr *));
3559+ if (do_kfree)
3560+ buf = kmalloc(blksize, GFP_NOFS);
3561+ else
3562+ buf = (void *)__get_free_page(GFP_NOFS);
3563+ if (unlikely(!buf))
3564+ goto out;
3565+
3566+ if (len > (1 << 22))
3567+ AuDbg("copying a large file %lld\n", (long long)len);
3568+
3569+ src->f_pos = 0;
3570+ dst->f_pos = 0;
3571+ err = au_do_copy_file(dst, src, len, buf, blksize);
3572+ if (do_kfree)
3573+ kfree(buf);
3574+ else
3575+ free_page((unsigned long)buf);
3576+
4f0767ce 3577+out:
1facf9fc 3578+ return err;
3579+}
3580+
3581+/*
3582+ * to support a sparse file which is opened with O_APPEND,
3583+ * we need to close the file.
3584+ */
3585+static int au_cp_regular(struct dentry *dentry, aufs_bindex_t bdst,
4a4d8108 3586+ aufs_bindex_t bsrc, loff_t len)
1facf9fc 3587+{
3588+ int err, i;
3589+ enum { SRC, DST };
3590+ struct {
3591+ aufs_bindex_t bindex;
3592+ unsigned int flags;
3593+ struct dentry *dentry;
3594+ struct file *file;
3595+ void *label, *label_file;
3596+ } *f, file[] = {
3597+ {
3598+ .bindex = bsrc,
3599+ .flags = O_RDONLY | O_NOATIME | O_LARGEFILE,
3600+ .file = NULL,
3601+ .label = &&out,
3602+ .label_file = &&out_src
3603+ },
3604+ {
3605+ .bindex = bdst,
3606+ .flags = O_WRONLY | O_NOATIME | O_LARGEFILE,
3607+ .file = NULL,
3608+ .label = &&out_src,
3609+ .label_file = &&out_dst
3610+ }
3611+ };
3612+ struct super_block *sb;
3613+
3614+ /* bsrc branch can be ro/rw. */
3615+ sb = dentry->d_sb;
3616+ f = file;
3617+ for (i = 0; i < 2; i++, f++) {
3618+ f->dentry = au_h_dptr(dentry, f->bindex);
3619+ f->file = au_h_open(dentry, f->bindex, f->flags, /*file*/NULL);
3620+ err = PTR_ERR(f->file);
3621+ if (IS_ERR(f->file))
3622+ goto *f->label;
3623+ err = -EINVAL;
3624+ if (unlikely(!f->file->f_op))
3625+ goto *f->label_file;
3626+ }
3627+
3628+ /* try stopping to update while we copyup */
3629+ IMustLock(file[SRC].dentry->d_inode);
3630+ err = au_copy_file(file[DST].file, file[SRC].file, len);
3631+
4f0767ce 3632+out_dst:
1facf9fc 3633+ fput(file[DST].file);
3634+ au_sbr_put(sb, file[DST].bindex);
4f0767ce 3635+out_src:
1facf9fc 3636+ fput(file[SRC].file);
3637+ au_sbr_put(sb, file[SRC].bindex);
4f0767ce 3638+out:
1facf9fc 3639+ return err;
3640+}
3641+
3642+static int au_do_cpup_regular(struct dentry *dentry, aufs_bindex_t bdst,
3643+ aufs_bindex_t bsrc, loff_t len,
3644+ struct inode *h_dir, struct path *h_path)
3645+{
3646+ int err, rerr;
3647+ loff_t l;
3648+
3649+ err = 0;
3650+ l = i_size_read(au_h_iptr(dentry->d_inode, bsrc));
3651+ if (len == -1 || l < len)
3652+ len = l;
3653+ if (len)
3654+ err = au_cp_regular(dentry, bdst, bsrc, len);
3655+ if (!err)
3656+ goto out; /* success */
3657+
3658+ rerr = vfsub_unlink(h_dir, h_path, /*force*/0);
3659+ if (rerr) {
3660+ AuIOErr("failed unlinking cpup-ed %.*s(%d, %d)\n",
3661+ AuDLNPair(h_path->dentry), err, rerr);
3662+ err = -EIO;
3663+ }
3664+
4f0767ce 3665+out:
1facf9fc 3666+ return err;
3667+}
3668+
3669+static int au_do_cpup_symlink(struct path *h_path, struct dentry *h_src,
3670+ struct inode *h_dir)
3671+{
3672+ int err, symlen;
3673+ mm_segment_t old_fs;
b752ccd1
AM
3674+ union {
3675+ char *k;
3676+ char __user *u;
3677+ } sym;
1facf9fc 3678+
3679+ err = -ENOSYS;
3680+ if (unlikely(!h_src->d_inode->i_op->readlink))
3681+ goto out;
3682+
3683+ err = -ENOMEM;
b752ccd1
AM
3684+ sym.k = __getname_gfp(GFP_NOFS);
3685+ if (unlikely(!sym.k))
1facf9fc 3686+ goto out;
3687+
9dbd164d 3688+ /* unnecessary to support mmap_sem since symlink is not mmap-able */
1facf9fc 3689+ old_fs = get_fs();
3690+ set_fs(KERNEL_DS);
b752ccd1 3691+ symlen = h_src->d_inode->i_op->readlink(h_src, sym.u, PATH_MAX);
1facf9fc 3692+ err = symlen;
3693+ set_fs(old_fs);
3694+
3695+ if (symlen > 0) {
b752ccd1
AM
3696+ sym.k[symlen] = 0;
3697+ err = vfsub_symlink(h_dir, h_path, sym.k);
1facf9fc 3698+ }
b752ccd1 3699+ __putname(sym.k);
1facf9fc 3700+
4f0767ce 3701+out:
1facf9fc 3702+ return err;
3703+}
3704+
3705+/* return with the lower dst inode is locked */
3706+static noinline_for_stack
3707+int cpup_entry(struct dentry *dentry, aufs_bindex_t bdst,
3708+ aufs_bindex_t bsrc, loff_t len, unsigned int flags,
3709+ struct dentry *dst_parent)
3710+{
3711+ int err;
3712+ umode_t mode;
3713+ unsigned int mnt_flags;
3714+ unsigned char isdir;
3715+ const unsigned char do_dt = !!au_ftest_cpup(flags, DTIME);
3716+ struct au_dtime dt;
3717+ struct path h_path;
3718+ struct dentry *h_src, *h_dst, *h_parent;
3719+ struct inode *h_inode, *h_dir;
3720+ struct super_block *sb;
3721+
3722+ /* bsrc branch can be ro/rw. */
3723+ h_src = au_h_dptr(dentry, bsrc);
3724+ h_inode = h_src->d_inode;
3725+ AuDebugOn(h_inode != au_h_iptr(dentry->d_inode, bsrc));
3726+
3727+ /* try stopping to be referenced while we are creating */
3728+ h_dst = au_h_dptr(dentry, bdst);
3729+ h_parent = h_dst->d_parent; /* dir inode is locked */
3730+ h_dir = h_parent->d_inode;
3731+ IMustLock(h_dir);
3732+ AuDebugOn(h_parent != h_dst->d_parent);
3733+
3734+ sb = dentry->d_sb;
3735+ h_path.mnt = au_sbr_mnt(sb, bdst);
3736+ if (do_dt) {
3737+ h_path.dentry = h_parent;
3738+ au_dtime_store(&dt, dst_parent, &h_path);
3739+ }
3740+ h_path.dentry = h_dst;
3741+
3742+ isdir = 0;
3743+ mode = h_inode->i_mode;
3744+ switch (mode & S_IFMT) {
3745+ case S_IFREG:
3746+ /* try stopping to update while we are referencing */
3747+ IMustLock(h_inode);
3748+ err = vfsub_create(h_dir, &h_path, mode | S_IWUSR);
3749+ if (!err)
3750+ err = au_do_cpup_regular
3751+ (dentry, bdst, bsrc, len,
3752+ au_h_iptr(dst_parent->d_inode, bdst), &h_path);
3753+ break;
3754+ case S_IFDIR:
3755+ isdir = 1;
3756+ err = vfsub_mkdir(h_dir, &h_path, mode);
3757+ if (!err) {
3758+ /*
3759+ * strange behaviour from the users view,
3760+ * particularry setattr case
3761+ */
3762+ if (au_ibstart(dst_parent->d_inode) == bdst)
3763+ au_cpup_attr_nlink(dst_parent->d_inode,
3764+ /*force*/1);
3765+ au_cpup_attr_nlink(dentry->d_inode, /*force*/1);
3766+ }
3767+ break;
3768+ case S_IFLNK:
3769+ err = au_do_cpup_symlink(&h_path, h_src, h_dir);
3770+ break;
3771+ case S_IFCHR:
3772+ case S_IFBLK:
3773+ AuDebugOn(!capable(CAP_MKNOD));
3774+ /*FALLTHROUGH*/
3775+ case S_IFIFO:
3776+ case S_IFSOCK:
3777+ err = vfsub_mknod(h_dir, &h_path, mode, h_inode->i_rdev);
3778+ break;
3779+ default:
3780+ AuIOErr("Unknown inode type 0%o\n", mode);
3781+ err = -EIO;
3782+ }
3783+
3784+ mnt_flags = au_mntflags(sb);
3785+ if (!au_opt_test(mnt_flags, UDBA_NONE)
3786+ && !isdir
3787+ && au_opt_test(mnt_flags, XINO)
3788+ && h_inode->i_nlink == 1
3789+ /* todo: unnecessary? */
3790+ /* && dentry->d_inode->i_nlink == 1 */
3791+ && bdst < bsrc
3792+ && !au_ftest_cpup(flags, KEEPLINO))
1308ab2a 3793+ au_xino_write(sb, bsrc, h_inode->i_ino, /*ino*/0);
1facf9fc 3794+ /* ignore this error */
3795+
3796+ if (do_dt)
3797+ au_dtime_revert(&dt);
3798+ return err;
3799+}
3800+
3801+/*
3802+ * copyup the @dentry from @bsrc to @bdst.
3803+ * the caller must set the both of lower dentries.
3804+ * @len is for truncating when it is -1 copyup the entire file.
3805+ * in link/rename cases, @dst_parent may be different from the real one.
3806+ */
3807+static int au_cpup_single(struct dentry *dentry, aufs_bindex_t bdst,
3808+ aufs_bindex_t bsrc, loff_t len, unsigned int flags,
3809+ struct dentry *dst_parent)
3810+{
3811+ int err, rerr;
3812+ aufs_bindex_t old_ibstart;
3813+ unsigned char isdir, plink;
3814+ struct au_dtime dt;
3815+ struct path h_path;
3816+ struct dentry *h_src, *h_dst, *h_parent;
3817+ struct inode *dst_inode, *h_dir, *inode;
3818+ struct super_block *sb;
3819+
3820+ AuDebugOn(bsrc <= bdst);
3821+
3822+ sb = dentry->d_sb;
3823+ h_path.mnt = au_sbr_mnt(sb, bdst);
3824+ h_dst = au_h_dptr(dentry, bdst);
3825+ h_parent = h_dst->d_parent; /* dir inode is locked */
3826+ h_dir = h_parent->d_inode;
3827+ IMustLock(h_dir);
3828+
3829+ h_src = au_h_dptr(dentry, bsrc);
3830+ inode = dentry->d_inode;
3831+
3832+ if (!dst_parent)
3833+ dst_parent = dget_parent(dentry);
3834+ else
3835+ dget(dst_parent);
3836+
3837+ plink = !!au_opt_test(au_mntflags(sb), PLINK);
3838+ dst_inode = au_h_iptr(inode, bdst);
3839+ if (dst_inode) {
3840+ if (unlikely(!plink)) {
3841+ err = -EIO;
027c5e7a
AM
3842+ AuIOErr("hi%lu(i%lu) exists on b%d "
3843+ "but plink is disabled\n",
3844+ dst_inode->i_ino, inode->i_ino, bdst);
1facf9fc 3845+ goto out;
3846+ }
3847+
3848+ if (dst_inode->i_nlink) {
3849+ const int do_dt = au_ftest_cpup(flags, DTIME);
3850+
3851+ h_src = au_plink_lkup(inode, bdst);
3852+ err = PTR_ERR(h_src);
3853+ if (IS_ERR(h_src))
3854+ goto out;
3855+ if (unlikely(!h_src->d_inode)) {
3856+ err = -EIO;
3857+ AuIOErr("i%lu exists on a upper branch "
027c5e7a
AM
3858+ "but not pseudo-linked\n",
3859+ inode->i_ino);
1facf9fc 3860+ dput(h_src);
3861+ goto out;
3862+ }
3863+
3864+ if (do_dt) {
3865+ h_path.dentry = h_parent;
3866+ au_dtime_store(&dt, dst_parent, &h_path);
3867+ }
3868+ h_path.dentry = h_dst;
3869+ err = vfsub_link(h_src, h_dir, &h_path);
3870+ if (do_dt)
3871+ au_dtime_revert(&dt);
3872+ dput(h_src);
3873+ goto out;
3874+ } else
3875+ /* todo: cpup_wh_file? */
3876+ /* udba work */
4a4d8108 3877+ au_update_ibrange(inode, /*do_put_zero*/1);
1facf9fc 3878+ }
3879+
3880+ old_ibstart = au_ibstart(inode);
3881+ err = cpup_entry(dentry, bdst, bsrc, len, flags, dst_parent);
3882+ if (unlikely(err))
3883+ goto out;
3884+ dst_inode = h_dst->d_inode;
3885+ mutex_lock_nested(&dst_inode->i_mutex, AuLsc_I_CHILD2);
3886+
3887+ err = cpup_iattr(dentry, bdst, h_src);
3888+ isdir = S_ISDIR(dst_inode->i_mode);
3889+ if (!err) {
4a4d8108
AM
3890+ if (bdst < old_ibstart) {
3891+ if (S_ISREG(inode->i_mode)) {
3892+ err = au_dy_iaop(inode, bdst, dst_inode);
3893+ if (unlikely(err))
3894+ goto out_rev;
3895+ }
1facf9fc 3896+ au_set_ibstart(inode, bdst);
4a4d8108 3897+ }
1facf9fc 3898+ au_set_h_iptr(inode, bdst, au_igrab(dst_inode),
3899+ au_hi_flags(inode, isdir));
3900+ mutex_unlock(&dst_inode->i_mutex);
3901+ if (!isdir
3902+ && h_src->d_inode->i_nlink > 1
3903+ && plink)
3904+ au_plink_append(inode, bdst, h_dst);
3905+ goto out; /* success */
3906+ }
3907+
3908+ /* revert */
4a4d8108 3909+out_rev:
1facf9fc 3910+ h_path.dentry = h_parent;
3911+ mutex_unlock(&dst_inode->i_mutex);
3912+ au_dtime_store(&dt, dst_parent, &h_path);
3913+ h_path.dentry = h_dst;
3914+ if (!isdir)
3915+ rerr = vfsub_unlink(h_dir, &h_path, /*force*/0);
3916+ else
3917+ rerr = vfsub_rmdir(h_dir, &h_path);
3918+ au_dtime_revert(&dt);
3919+ if (rerr) {
3920+ AuIOErr("failed removing broken entry(%d, %d)\n", err, rerr);
3921+ err = -EIO;
3922+ }
3923+
4f0767ce 3924+out:
1facf9fc 3925+ dput(dst_parent);
3926+ return err;
3927+}
3928+
3929+struct au_cpup_single_args {
3930+ int *errp;
3931+ struct dentry *dentry;
3932+ aufs_bindex_t bdst, bsrc;
3933+ loff_t len;
3934+ unsigned int flags;
3935+ struct dentry *dst_parent;
3936+};
3937+
3938+static void au_call_cpup_single(void *args)
3939+{
3940+ struct au_cpup_single_args *a = args;
3941+ *a->errp = au_cpup_single(a->dentry, a->bdst, a->bsrc, a->len,
3942+ a->flags, a->dst_parent);
3943+}
3944+
53392da6
AM
3945+/*
3946+ * prevent SIGXFSZ in copy-up.
3947+ * testing CAP_MKNOD is for generic fs,
3948+ * but CAP_FSETID is for xfs only, currently.
3949+ */
3950+static int au_cpup_sio_test(struct super_block *sb, umode_t mode)
3951+{
3952+ int do_sio;
3953+
3954+ do_sio = 0;
3955+ if (!au_wkq_test()
3956+ && (!au_sbi(sb)->si_plink_maint_pid
3957+ || au_plink_maint(sb, AuLock_NOPLM))) {
3958+ switch (mode & S_IFMT) {
3959+ case S_IFREG:
3960+ /* no condition about RLIMIT_FSIZE and the file size */
3961+ do_sio = 1;
3962+ break;
3963+ case S_IFCHR:
3964+ case S_IFBLK:
3965+ do_sio = !capable(CAP_MKNOD);
3966+ break;
3967+ }
3968+ if (!do_sio)
3969+ do_sio = ((mode & (S_ISUID | S_ISGID))
3970+ && !capable(CAP_FSETID));
3971+ }
3972+
3973+ return do_sio;
3974+}
3975+
1facf9fc 3976+int au_sio_cpup_single(struct dentry *dentry, aufs_bindex_t bdst,
3977+ aufs_bindex_t bsrc, loff_t len, unsigned int flags,
3978+ struct dentry *dst_parent)
3979+{
3980+ int err, wkq_err;
1facf9fc 3981+ struct dentry *h_dentry;
3982+
3983+ h_dentry = au_h_dptr(dentry, bsrc);
53392da6 3984+ if (!au_cpup_sio_test(dentry->d_sb, h_dentry->d_inode->i_mode))
1facf9fc 3985+ err = au_cpup_single(dentry, bdst, bsrc, len, flags,
3986+ dst_parent);
3987+ else {
3988+ struct au_cpup_single_args args = {
3989+ .errp = &err,
3990+ .dentry = dentry,
3991+ .bdst = bdst,
3992+ .bsrc = bsrc,
3993+ .len = len,
3994+ .flags = flags,
3995+ .dst_parent = dst_parent
3996+ };
3997+ wkq_err = au_wkq_wait(au_call_cpup_single, &args);
3998+ if (unlikely(wkq_err))
3999+ err = wkq_err;
4000+ }
4001+
4002+ return err;
4003+}
4004+
4005+/*
4006+ * copyup the @dentry from the first active lower branch to @bdst,
4007+ * using au_cpup_single().
4008+ */
4009+static int au_cpup_simple(struct dentry *dentry, aufs_bindex_t bdst, loff_t len,
4010+ unsigned int flags)
4011+{
4012+ int err;
4013+ aufs_bindex_t bsrc, bend;
4014+
4015+ bend = au_dbend(dentry);
4016+ for (bsrc = bdst + 1; bsrc <= bend; bsrc++)
4017+ if (au_h_dptr(dentry, bsrc))
4018+ break;
4019+
4020+ err = au_lkup_neg(dentry, bdst);
4021+ if (!err) {
4022+ err = au_cpup_single(dentry, bdst, bsrc, len, flags, NULL);
4023+ if (!err)
4024+ return 0; /* success */
4025+
4026+ /* revert */
4027+ au_set_h_dptr(dentry, bdst, NULL);
4028+ au_set_dbstart(dentry, bsrc);
4029+ }
4030+
4031+ return err;
4032+}
4033+
4034+struct au_cpup_simple_args {
4035+ int *errp;
4036+ struct dentry *dentry;
4037+ aufs_bindex_t bdst;
4038+ loff_t len;
4039+ unsigned int flags;
4040+};
4041+
4042+static void au_call_cpup_simple(void *args)
4043+{
4044+ struct au_cpup_simple_args *a = args;
4045+ *a->errp = au_cpup_simple(a->dentry, a->bdst, a->len, a->flags);
4046+}
4047+
4048+int au_sio_cpup_simple(struct dentry *dentry, aufs_bindex_t bdst, loff_t len,
4049+ unsigned int flags)
4050+{
4051+ int err, wkq_err;
1facf9fc 4052+ struct dentry *parent;
4053+ struct inode *h_dir;
4054+
4055+ parent = dget_parent(dentry);
4056+ h_dir = au_h_iptr(parent->d_inode, bdst);
53392da6
AM
4057+ if (!au_test_h_perm_sio(h_dir, MAY_EXEC | MAY_WRITE)
4058+ && !au_cpup_sio_test(dentry->d_sb, dentry->d_inode->i_mode))
1facf9fc 4059+ err = au_cpup_simple(dentry, bdst, len, flags);
4060+ else {
4061+ struct au_cpup_simple_args args = {
4062+ .errp = &err,
4063+ .dentry = dentry,
4064+ .bdst = bdst,
4065+ .len = len,
4066+ .flags = flags
4067+ };
4068+ wkq_err = au_wkq_wait(au_call_cpup_simple, &args);
4069+ if (unlikely(wkq_err))
4070+ err = wkq_err;
4071+ }
4072+
4073+ dput(parent);
4074+ return err;
4075+}
4076+
4077+/* ---------------------------------------------------------------------- */
4078+
4079+/*
4080+ * copyup the deleted file for writing.
4081+ */
4082+static int au_do_cpup_wh(struct dentry *dentry, aufs_bindex_t bdst,
4083+ struct dentry *wh_dentry, struct file *file,
4084+ loff_t len)
4085+{
4086+ int err;
4087+ aufs_bindex_t bstart;
4088+ struct au_dinfo *dinfo;
4089+ struct dentry *h_d_dst, *h_d_start;
4a4d8108 4090+ struct au_hdentry *hdp;
1facf9fc 4091+
4092+ dinfo = au_di(dentry);
1308ab2a 4093+ AuRwMustWriteLock(&dinfo->di_rwsem);
4094+
1facf9fc 4095+ bstart = dinfo->di_bstart;
4a4d8108
AM
4096+ hdp = dinfo->di_hdentry;
4097+ h_d_dst = hdp[0 + bdst].hd_dentry;
1facf9fc 4098+ dinfo->di_bstart = bdst;
4a4d8108 4099+ hdp[0 + bdst].hd_dentry = wh_dentry;
027c5e7a
AM
4100+ if (file) {
4101+ h_d_start = hdp[0 + bstart].hd_dentry;
4a4d8108 4102+ hdp[0 + bstart].hd_dentry = au_hf_top(file)->f_dentry;
027c5e7a 4103+ }
1facf9fc 4104+ err = au_cpup_single(dentry, bdst, bstart, len, !AuCpup_DTIME,
4105+ /*h_parent*/NULL);
027c5e7a
AM
4106+ if (file) {
4107+ if (!err)
4108+ err = au_reopen_nondir(file);
4a4d8108 4109+ hdp[0 + bstart].hd_dentry = h_d_start;
1facf9fc 4110+ }
4a4d8108 4111+ hdp[0 + bdst].hd_dentry = h_d_dst;
1facf9fc 4112+ dinfo->di_bstart = bstart;
4113+
4114+ return err;
4115+}
4116+
4117+static int au_cpup_wh(struct dentry *dentry, aufs_bindex_t bdst, loff_t len,
4118+ struct file *file)
4119+{
4120+ int err;
4121+ struct au_dtime dt;
4122+ struct dentry *parent, *h_parent, *wh_dentry;
4123+ struct au_branch *br;
4124+ struct path h_path;
4125+
4126+ br = au_sbr(dentry->d_sb, bdst);
4127+ parent = dget_parent(dentry);
4128+ h_parent = au_h_dptr(parent, bdst);
4129+ wh_dentry = au_whtmp_lkup(h_parent, br, &dentry->d_name);
4130+ err = PTR_ERR(wh_dentry);
4131+ if (IS_ERR(wh_dentry))
4132+ goto out;
4133+
4134+ h_path.dentry = h_parent;
4135+ h_path.mnt = br->br_mnt;
4136+ au_dtime_store(&dt, parent, &h_path);
4137+ err = au_do_cpup_wh(dentry, bdst, wh_dentry, file, len);
4138+ if (unlikely(err))
4139+ goto out_wh;
4140+
4141+ dget(wh_dentry);
4142+ h_path.dentry = wh_dentry;
4a4d8108
AM
4143+ if (!S_ISDIR(wh_dentry->d_inode->i_mode))
4144+ err = vfsub_unlink(h_parent->d_inode, &h_path, /*force*/0);
4145+ else
4146+ err = vfsub_rmdir(h_parent->d_inode, &h_path);
1facf9fc 4147+ if (unlikely(err)) {
4148+ AuIOErr("failed remove copied-up tmp file %.*s(%d)\n",
4149+ AuDLNPair(wh_dentry), err);
4150+ err = -EIO;
4151+ }
4152+ au_dtime_revert(&dt);
4153+ au_set_hi_wh(dentry->d_inode, bdst, wh_dentry);
4154+
4f0767ce 4155+out_wh:
1facf9fc 4156+ dput(wh_dentry);
4f0767ce 4157+out:
1facf9fc 4158+ dput(parent);
4159+ return err;
4160+}
4161+
4162+struct au_cpup_wh_args {
4163+ int *errp;
4164+ struct dentry *dentry;
4165+ aufs_bindex_t bdst;
4166+ loff_t len;
4167+ struct file *file;
4168+};
4169+
4170+static void au_call_cpup_wh(void *args)
4171+{
4172+ struct au_cpup_wh_args *a = args;
4173+ *a->errp = au_cpup_wh(a->dentry, a->bdst, a->len, a->file);
4174+}
4175+
4176+int au_sio_cpup_wh(struct dentry *dentry, aufs_bindex_t bdst, loff_t len,
4177+ struct file *file)
4178+{
4179+ int err, wkq_err;
4180+ struct dentry *parent, *h_orph, *h_parent, *h_dentry;
4181+ struct inode *dir, *h_dir, *h_tmpdir, *h_inode;
4182+ struct au_wbr *wbr;
4183+
4184+ parent = dget_parent(dentry);
4185+ dir = parent->d_inode;
4186+ h_orph = NULL;
4187+ h_parent = NULL;
4188+ h_dir = au_igrab(au_h_iptr(dir, bdst));
4189+ h_tmpdir = h_dir;
4190+ if (!h_dir->i_nlink) {
4191+ wbr = au_sbr(dentry->d_sb, bdst)->br_wbr;
4192+ h_orph = wbr->wbr_orph;
4193+
4194+ h_parent = dget(au_h_dptr(parent, bdst));
1facf9fc 4195+ au_set_h_dptr(parent, bdst, dget(h_orph));
4196+ h_tmpdir = h_orph->d_inode;
1facf9fc 4197+ au_set_h_iptr(dir, bdst, au_igrab(h_tmpdir), /*flags*/0);
4198+
4199+ /* this temporary unlock is safe */
4200+ if (file)
4a4d8108 4201+ h_dentry = au_hf_top(file)->f_dentry;
1facf9fc 4202+ else
4203+ h_dentry = au_h_dptr(dentry, au_dbstart(dentry));
4204+ h_inode = h_dentry->d_inode;
4205+ IMustLock(h_inode);
4206+ mutex_unlock(&h_inode->i_mutex);
dece6358 4207+ mutex_lock_nested(&h_tmpdir->i_mutex, AuLsc_I_PARENT3);
1facf9fc 4208+ mutex_lock_nested(&h_inode->i_mutex, AuLsc_I_CHILD);
4a4d8108 4209+ /* todo: au_h_open_pre()? */
1facf9fc 4210+ }
4211+
53392da6
AM
4212+ if (!au_test_h_perm_sio(h_tmpdir, MAY_EXEC | MAY_WRITE)
4213+ && !au_cpup_sio_test(dentry->d_sb, dentry->d_inode->i_mode))
1facf9fc 4214+ err = au_cpup_wh(dentry, bdst, len, file);
4215+ else {
4216+ struct au_cpup_wh_args args = {
4217+ .errp = &err,
4218+ .dentry = dentry,
4219+ .bdst = bdst,
4220+ .len = len,
4221+ .file = file
4222+ };
4223+ wkq_err = au_wkq_wait(au_call_cpup_wh, &args);
4224+ if (unlikely(wkq_err))
4225+ err = wkq_err;
4226+ }
4227+
4228+ if (h_orph) {
4229+ mutex_unlock(&h_tmpdir->i_mutex);
4a4d8108 4230+ /* todo: au_h_open_post()? */
1facf9fc 4231+ au_set_h_iptr(dir, bdst, au_igrab(h_dir), /*flags*/0);
1facf9fc 4232+ au_set_h_dptr(parent, bdst, h_parent);
4233+ }
4234+ iput(h_dir);
4235+ dput(parent);
4236+
4237+ return err;
4238+}
4239+
4240+/* ---------------------------------------------------------------------- */
4241+
4242+/*
4243+ * generic routine for both of copy-up and copy-down.
4244+ */
4245+/* cf. revalidate function in file.c */
4246+int au_cp_dirs(struct dentry *dentry, aufs_bindex_t bdst,
4247+ int (*cp)(struct dentry *dentry, aufs_bindex_t bdst,
4248+ struct dentry *h_parent, void *arg),
4249+ void *arg)
4250+{
4251+ int err;
4252+ struct au_pin pin;
4253+ struct dentry *d, *parent, *h_parent, *real_parent;
4254+
4255+ err = 0;
4256+ parent = dget_parent(dentry);
4257+ if (IS_ROOT(parent))
4258+ goto out;
4259+
4260+ au_pin_init(&pin, dentry, bdst, AuLsc_DI_PARENT2, AuLsc_I_PARENT2,
4261+ au_opt_udba(dentry->d_sb), AuPin_MNT_WRITE);
4262+
4263+ /* do not use au_dpage */
4264+ real_parent = parent;
4265+ while (1) {
4266+ dput(parent);
4267+ parent = dget_parent(dentry);
4268+ h_parent = au_h_dptr(parent, bdst);
4269+ if (h_parent)
4270+ goto out; /* success */
4271+
4272+ /* find top dir which is necessary to cpup */
4273+ do {
4274+ d = parent;
4275+ dput(parent);
4276+ parent = dget_parent(d);
4277+ di_read_lock_parent3(parent, !AuLock_IR);
4278+ h_parent = au_h_dptr(parent, bdst);
4279+ di_read_unlock(parent, !AuLock_IR);
4280+ } while (!h_parent);
4281+
4282+ if (d != real_parent)
4283+ di_write_lock_child3(d);
4284+
4285+ /* somebody else might create while we were sleeping */
4286+ if (!au_h_dptr(d, bdst) || !au_h_dptr(d, bdst)->d_inode) {
4287+ if (au_h_dptr(d, bdst))
4288+ au_update_dbstart(d);
4289+
4290+ au_pin_set_dentry(&pin, d);
4291+ err = au_do_pin(&pin);
4292+ if (!err) {
4293+ err = cp(d, bdst, h_parent, arg);
4294+ au_unpin(&pin);
4295+ }
4296+ }
4297+
4298+ if (d != real_parent)
4299+ di_write_unlock(d);
4300+ if (unlikely(err))
4301+ break;
4302+ }
4303+
4f0767ce 4304+out:
1facf9fc 4305+ dput(parent);
4306+ return err;
4307+}
4308+
4309+static int au_cpup_dir(struct dentry *dentry, aufs_bindex_t bdst,
4310+ struct dentry *h_parent __maybe_unused ,
4311+ void *arg __maybe_unused)
4312+{
4313+ return au_sio_cpup_simple(dentry, bdst, -1, AuCpup_DTIME);
4314+}
4315+
4316+int au_cpup_dirs(struct dentry *dentry, aufs_bindex_t bdst)
4317+{
4318+ return au_cp_dirs(dentry, bdst, au_cpup_dir, NULL);
4319+}
4320+
4321+int au_test_and_cpup_dirs(struct dentry *dentry, aufs_bindex_t bdst)
4322+{
4323+ int err;
4324+ struct dentry *parent;
4325+ struct inode *dir;
4326+
4327+ parent = dget_parent(dentry);
4328+ dir = parent->d_inode;
4329+ err = 0;
4330+ if (au_h_iptr(dir, bdst))
4331+ goto out;
4332+
4333+ di_read_unlock(parent, AuLock_IR);
4334+ di_write_lock_parent(parent);
4335+ /* someone else might change our inode while we were sleeping */
4336+ if (!au_h_iptr(dir, bdst))
4337+ err = au_cpup_dirs(dentry, bdst);
4338+ di_downgrade_lock(parent, AuLock_IR);
4339+
4f0767ce 4340+out:
1facf9fc 4341+ dput(parent);
4342+ return err;
4343+}
7f207e10
AM
4344diff -urN /usr/share/empty/fs/aufs/cpup.h linux/fs/aufs/cpup.h
4345--- /usr/share/empty/fs/aufs/cpup.h 1970-01-01 01:00:00.000000000 +0100
7ce627cf 4346+++ linux/fs/aufs/cpup.h 2012-05-22 09:06:08.867458905 +0200
f6c5ef8b 4347@@ -0,0 +1,81 @@
1facf9fc 4348+/*
f6c5ef8b 4349+ * Copyright (C) 2005-2012 Junjiro R. Okajima
1facf9fc 4350+ *
4351+ * This program, aufs is free software; you can redistribute it and/or modify
4352+ * it under the terms of the GNU General Public License as published by
4353+ * the Free Software Foundation; either version 2 of the License, or
4354+ * (at your option) any later version.
dece6358
AM
4355+ *
4356+ * This program is distributed in the hope that it will be useful,
4357+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
4358+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
4359+ * GNU General Public License for more details.
4360+ *
4361+ * You should have received a copy of the GNU General Public License
4362+ * along with this program; if not, write to the Free Software
4363+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 4364+ */
4365+
4366+/*
4367+ * copy-up/down functions
4368+ */
4369+
4370+#ifndef __AUFS_CPUP_H__
4371+#define __AUFS_CPUP_H__
4372+
4373+#ifdef __KERNEL__
4374+
dece6358 4375+#include <linux/path.h>
1facf9fc 4376+
dece6358
AM
4377+struct inode;
4378+struct file;
4379+
1facf9fc 4380+void au_cpup_attr_flags(struct inode *dst, struct inode *src);
4381+void au_cpup_attr_timesizes(struct inode *inode);
4382+void au_cpup_attr_nlink(struct inode *inode, int force);
4383+void au_cpup_attr_changeable(struct inode *inode);
4384+void au_cpup_igen(struct inode *inode, struct inode *h_inode);
4385+void au_cpup_attr_all(struct inode *inode, int force);
4386+
4387+/* ---------------------------------------------------------------------- */
4388+
4389+/* cpup flags */
4390+#define AuCpup_DTIME 1 /* do dtime_store/revert */
4391+#define AuCpup_KEEPLINO (1 << 1) /* do not clear the lower xino,
4392+ for link(2) */
4393+#define au_ftest_cpup(flags, name) ((flags) & AuCpup_##name)
7f207e10
AM
4394+#define au_fset_cpup(flags, name) \
4395+ do { (flags) |= AuCpup_##name; } while (0)
4396+#define au_fclr_cpup(flags, name) \
4397+ do { (flags) &= ~AuCpup_##name; } while (0)
1facf9fc 4398+
4399+int au_copy_file(struct file *dst, struct file *src, loff_t len);
4400+int au_sio_cpup_single(struct dentry *dentry, aufs_bindex_t bdst,
4401+ aufs_bindex_t bsrc, loff_t len, unsigned int flags,
4402+ struct dentry *dst_parent);
4403+int au_sio_cpup_simple(struct dentry *dentry, aufs_bindex_t bdst, loff_t len,
4404+ unsigned int flags);
4405+int au_sio_cpup_wh(struct dentry *dentry, aufs_bindex_t bdst, loff_t len,
4406+ struct file *file);
4407+
4408+int au_cp_dirs(struct dentry *dentry, aufs_bindex_t bdst,
4409+ int (*cp)(struct dentry *dentry, aufs_bindex_t bdst,
4410+ struct dentry *h_parent, void *arg),
4411+ void *arg);
4412+int au_cpup_dirs(struct dentry *dentry, aufs_bindex_t bdst);
4413+int au_test_and_cpup_dirs(struct dentry *dentry, aufs_bindex_t bdst);
4414+
4415+/* ---------------------------------------------------------------------- */
4416+
4417+/* keep timestamps when copyup */
4418+struct au_dtime {
4419+ struct dentry *dt_dentry;
4420+ struct path dt_h_path;
4421+ struct timespec dt_atime, dt_mtime;
4422+};
4423+void au_dtime_store(struct au_dtime *dt, struct dentry *dentry,
4424+ struct path *h_path);
4425+void au_dtime_revert(struct au_dtime *dt);
4426+
4427+#endif /* __KERNEL__ */
4428+#endif /* __AUFS_CPUP_H__ */
7f207e10
AM
4429diff -urN /usr/share/empty/fs/aufs/dbgaufs.c linux/fs/aufs/dbgaufs.c
4430--- /usr/share/empty/fs/aufs/dbgaufs.c 1970-01-01 01:00:00.000000000 +0100
7ce627cf 4431+++ linux/fs/aufs/dbgaufs.c 2012-05-22 09:06:08.867458905 +0200
4a4d8108 4432@@ -0,0 +1,334 @@
1facf9fc 4433+/*
f6c5ef8b 4434+ * Copyright (C) 2005-2012 Junjiro R. Okajima
1facf9fc 4435+ *
4436+ * This program, aufs is free software; you can redistribute it and/or modify
4437+ * it under the terms of the GNU General Public License as published by
4438+ * the Free Software Foundation; either version 2 of the License, or
4439+ * (at your option) any later version.
dece6358
AM
4440+ *
4441+ * This program is distributed in the hope that it will be useful,
4442+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
4443+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
4444+ * GNU General Public License for more details.
4445+ *
4446+ * You should have received a copy of the GNU General Public License
4447+ * along with this program; if not, write to the Free Software
4448+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 4449+ */
4450+
4451+/*
4452+ * debugfs interface
4453+ */
4454+
4455+#include <linux/debugfs.h>
4456+#include "aufs.h"
4457+
4458+#ifndef CONFIG_SYSFS
4459+#error DEBUG_FS depends upon SYSFS
4460+#endif
4461+
4462+static struct dentry *dbgaufs;
4463+static const mode_t dbgaufs_mode = S_IRUSR | S_IRGRP | S_IROTH;
4464+
4465+/* 20 is max digits length of ulong 64 */
4466+struct dbgaufs_arg {
4467+ int n;
4468+ char a[20 * 4];
4469+};
4470+
4471+/*
4472+ * common function for all XINO files
4473+ */
4474+static int dbgaufs_xi_release(struct inode *inode __maybe_unused,
4475+ struct file *file)
4476+{
4477+ kfree(file->private_data);
4478+ return 0;
4479+}
4480+
4481+static int dbgaufs_xi_open(struct file *xf, struct file *file, int do_fcnt)
4482+{
4483+ int err;
4484+ struct kstat st;
4485+ struct dbgaufs_arg *p;
4486+
4487+ err = -ENOMEM;
4488+ p = kmalloc(sizeof(*p), GFP_NOFS);
4489+ if (unlikely(!p))
4490+ goto out;
4491+
4492+ err = 0;
4493+ p->n = 0;
4494+ file->private_data = p;
4495+ if (!xf)
4496+ goto out;
4497+
4498+ err = vfs_getattr(xf->f_vfsmnt, xf->f_dentry, &st);
4499+ if (!err) {
4500+ if (do_fcnt)
4501+ p->n = snprintf
4502+ (p->a, sizeof(p->a), "%ld, %llux%lu %lld\n",
4503+ (long)file_count(xf), st.blocks, st.blksize,
4504+ (long long)st.size);
4505+ else
4506+ p->n = snprintf(p->a, sizeof(p->a), "%llux%lu %lld\n",
4507+ st.blocks, st.blksize,
4508+ (long long)st.size);
4509+ AuDebugOn(p->n >= sizeof(p->a));
4510+ } else {
4511+ p->n = snprintf(p->a, sizeof(p->a), "err %d\n", err);
4512+ err = 0;
4513+ }
4514+
4f0767ce 4515+out:
1facf9fc 4516+ return err;
4517+
4518+}
4519+
4520+static ssize_t dbgaufs_xi_read(struct file *file, char __user *buf,
4521+ size_t count, loff_t *ppos)
4522+{
4523+ struct dbgaufs_arg *p;
4524+
4525+ p = file->private_data;
4526+ return simple_read_from_buffer(buf, count, ppos, p->a, p->n);
4527+}
4528+
4529+/* ---------------------------------------------------------------------- */
4530+
4531+static int dbgaufs_xib_open(struct inode *inode, struct file *file)
4532+{
4533+ int err;
4534+ struct au_sbinfo *sbinfo;
4535+ struct super_block *sb;
4536+
4537+ sbinfo = inode->i_private;
4538+ sb = sbinfo->si_sb;
4539+ si_noflush_read_lock(sb);
4540+ err = dbgaufs_xi_open(sbinfo->si_xib, file, /*do_fcnt*/0);
4541+ si_read_unlock(sb);
4542+ return err;
4543+}
4544+
4545+static const struct file_operations dbgaufs_xib_fop = {
4a4d8108 4546+ .owner = THIS_MODULE,
1facf9fc 4547+ .open = dbgaufs_xib_open,
4548+ .release = dbgaufs_xi_release,
4549+ .read = dbgaufs_xi_read
4550+};
4551+
4552+/* ---------------------------------------------------------------------- */
4553+
4554+#define DbgaufsXi_PREFIX "xi"
4555+
4556+static int dbgaufs_xino_open(struct inode *inode, struct file *file)
4557+{
4558+ int err;
4559+ long l;
4560+ struct au_sbinfo *sbinfo;
4561+ struct super_block *sb;
4562+ struct file *xf;
4563+ struct qstr *name;
4564+
4565+ err = -ENOENT;
4566+ xf = NULL;
4567+ name = &file->f_dentry->d_name;
4568+ if (unlikely(name->len < sizeof(DbgaufsXi_PREFIX)
4569+ || memcmp(name->name, DbgaufsXi_PREFIX,
4570+ sizeof(DbgaufsXi_PREFIX) - 1)))
4571+ goto out;
9dbd164d 4572+ err = kstrtol(name->name + sizeof(DbgaufsXi_PREFIX) - 1, 10, &l);
1facf9fc 4573+ if (unlikely(err))
4574+ goto out;
4575+
4576+ sbinfo = inode->i_private;
4577+ sb = sbinfo->si_sb;
4578+ si_noflush_read_lock(sb);
4579+ if (l <= au_sbend(sb)) {
4580+ xf = au_sbr(sb, (aufs_bindex_t)l)->br_xino.xi_file;
4581+ err = dbgaufs_xi_open(xf, file, /*do_fcnt*/1);
4582+ } else
4583+ err = -ENOENT;
4584+ si_read_unlock(sb);
4585+
4f0767ce 4586+out:
1facf9fc 4587+ return err;
4588+}
4589+
4590+static const struct file_operations dbgaufs_xino_fop = {
4a4d8108 4591+ .owner = THIS_MODULE,
1facf9fc 4592+ .open = dbgaufs_xino_open,
4593+ .release = dbgaufs_xi_release,
4594+ .read = dbgaufs_xi_read
4595+};
4596+
4597+void dbgaufs_brs_del(struct super_block *sb, aufs_bindex_t bindex)
4598+{
4599+ aufs_bindex_t bend;
4600+ struct au_branch *br;
4601+ struct au_xino_file *xi;
4602+
4603+ if (!au_sbi(sb)->si_dbgaufs)
4604+ return;
4605+
4606+ bend = au_sbend(sb);
4607+ for (; bindex <= bend; bindex++) {
4608+ br = au_sbr(sb, bindex);
4609+ xi = &br->br_xino;
4610+ if (xi->xi_dbgaufs) {
4611+ debugfs_remove(xi->xi_dbgaufs);
4612+ xi->xi_dbgaufs = NULL;
4613+ }
4614+ }
4615+}
4616+
4617+void dbgaufs_brs_add(struct super_block *sb, aufs_bindex_t bindex)
4618+{
4619+ struct au_sbinfo *sbinfo;
4620+ struct dentry *parent;
4621+ struct au_branch *br;
4622+ struct au_xino_file *xi;
4623+ aufs_bindex_t bend;
4624+ char name[sizeof(DbgaufsXi_PREFIX) + 5]; /* "xi" bindex NULL */
4625+
4626+ sbinfo = au_sbi(sb);
4627+ parent = sbinfo->si_dbgaufs;
4628+ if (!parent)
4629+ return;
4630+
4631+ bend = au_sbend(sb);
4632+ for (; bindex <= bend; bindex++) {
4633+ snprintf(name, sizeof(name), DbgaufsXi_PREFIX "%d", bindex);
4634+ br = au_sbr(sb, bindex);
4635+ xi = &br->br_xino;
4636+ AuDebugOn(xi->xi_dbgaufs);
4637+ xi->xi_dbgaufs = debugfs_create_file(name, dbgaufs_mode, parent,
4638+ sbinfo, &dbgaufs_xino_fop);
4639+ /* ignore an error */
4640+ if (unlikely(!xi->xi_dbgaufs))
4641+ AuWarn1("failed %s under debugfs\n", name);
4642+ }
4643+}
4644+
4645+/* ---------------------------------------------------------------------- */
4646+
4647+#ifdef CONFIG_AUFS_EXPORT
4648+static int dbgaufs_xigen_open(struct inode *inode, struct file *file)
4649+{
4650+ int err;
4651+ struct au_sbinfo *sbinfo;
4652+ struct super_block *sb;
4653+
4654+ sbinfo = inode->i_private;
4655+ sb = sbinfo->si_sb;
4656+ si_noflush_read_lock(sb);
4657+ err = dbgaufs_xi_open(sbinfo->si_xigen, file, /*do_fcnt*/0);
4658+ si_read_unlock(sb);
4659+ return err;
4660+}
4661+
4662+static const struct file_operations dbgaufs_xigen_fop = {
4a4d8108 4663+ .owner = THIS_MODULE,
1facf9fc 4664+ .open = dbgaufs_xigen_open,
4665+ .release = dbgaufs_xi_release,
4666+ .read = dbgaufs_xi_read
4667+};
4668+
4669+static int dbgaufs_xigen_init(struct au_sbinfo *sbinfo)
4670+{
4671+ int err;
4672+
dece6358
AM
4673+ /*
4674+ * This function is a dynamic '__init' fucntion actually,
4675+ * so the tiny check for si_rwsem is unnecessary.
4676+ */
4677+ /* AuRwMustWriteLock(&sbinfo->si_rwsem); */
4678+
1facf9fc 4679+ err = -EIO;
4680+ sbinfo->si_dbgaufs_xigen = debugfs_create_file
4681+ ("xigen", dbgaufs_mode, sbinfo->si_dbgaufs, sbinfo,
4682+ &dbgaufs_xigen_fop);
4683+ if (sbinfo->si_dbgaufs_xigen)
4684+ err = 0;
4685+
4686+ return err;
4687+}
4688+#else
4689+static int dbgaufs_xigen_init(struct au_sbinfo *sbinfo)
4690+{
4691+ return 0;
4692+}
4693+#endif /* CONFIG_AUFS_EXPORT */
4694+
4695+/* ---------------------------------------------------------------------- */
4696+
4697+void dbgaufs_si_fin(struct au_sbinfo *sbinfo)
4698+{
dece6358
AM
4699+ /*
4700+ * This function is a dynamic '__init' fucntion actually,
4701+ * so the tiny check for si_rwsem is unnecessary.
4702+ */
4703+ /* AuRwMustWriteLock(&sbinfo->si_rwsem); */
4704+
1facf9fc 4705+ debugfs_remove_recursive(sbinfo->si_dbgaufs);
4706+ sbinfo->si_dbgaufs = NULL;
4707+ kobject_put(&sbinfo->si_kobj);
4708+}
4709+
4710+int dbgaufs_si_init(struct au_sbinfo *sbinfo)
4711+{
4712+ int err;
4713+ char name[SysaufsSiNameLen];
4714+
dece6358
AM
4715+ /*
4716+ * This function is a dynamic '__init' fucntion actually,
4717+ * so the tiny check for si_rwsem is unnecessary.
4718+ */
4719+ /* AuRwMustWriteLock(&sbinfo->si_rwsem); */
4720+
1facf9fc 4721+ err = -ENOENT;
4722+ if (!dbgaufs) {
4723+ AuErr1("/debug/aufs is uninitialized\n");
4724+ goto out;
4725+ }
4726+
4727+ err = -EIO;
4728+ sysaufs_name(sbinfo, name);
4729+ sbinfo->si_dbgaufs = debugfs_create_dir(name, dbgaufs);
4730+ if (unlikely(!sbinfo->si_dbgaufs))
4731+ goto out;
4732+ kobject_get(&sbinfo->si_kobj);
4733+
4734+ sbinfo->si_dbgaufs_xib = debugfs_create_file
4735+ ("xib", dbgaufs_mode, sbinfo->si_dbgaufs, sbinfo,
4736+ &dbgaufs_xib_fop);
4737+ if (unlikely(!sbinfo->si_dbgaufs_xib))
4738+ goto out_dir;
4739+
4740+ err = dbgaufs_xigen_init(sbinfo);
4741+ if (!err)
4742+ goto out; /* success */
4743+
4f0767ce 4744+out_dir:
1facf9fc 4745+ dbgaufs_si_fin(sbinfo);
4f0767ce 4746+out:
1facf9fc 4747+ return err;
4748+}
4749+
4750+/* ---------------------------------------------------------------------- */
4751+
4752+void dbgaufs_fin(void)
4753+{
4754+ debugfs_remove(dbgaufs);
4755+}
4756+
4757+int __init dbgaufs_init(void)
4758+{
4759+ int err;
4760+
4761+ err = -EIO;
4762+ dbgaufs = debugfs_create_dir(AUFS_NAME, NULL);
4763+ if (dbgaufs)
4764+ err = 0;
4765+ return err;
4766+}
7f207e10
AM
4767diff -urN /usr/share/empty/fs/aufs/dbgaufs.h linux/fs/aufs/dbgaufs.h
4768--- /usr/share/empty/fs/aufs/dbgaufs.h 1970-01-01 01:00:00.000000000 +0100
7ce627cf 4769+++ linux/fs/aufs/dbgaufs.h 2012-05-22 09:06:08.867458905 +0200
f6c5ef8b 4770@@ -0,0 +1,49 @@
1facf9fc 4771+/*
f6c5ef8b 4772+ * Copyright (C) 2005-2012 Junjiro R. Okajima
1facf9fc 4773+ *
4774+ * This program, aufs is free software; you can redistribute it and/or modify
4775+ * it under the terms of the GNU General Public License as published by
4776+ * the Free Software Foundation; either version 2 of the License, or
4777+ * (at your option) any later version.
dece6358
AM
4778+ *
4779+ * This program is distributed in the hope that it will be useful,
4780+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
4781+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
4782+ * GNU General Public License for more details.
4783+ *
4784+ * You should have received a copy of the GNU General Public License
4785+ * along with this program; if not, write to the Free Software
4786+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 4787+ */
4788+
4789+/*
4790+ * debugfs interface
4791+ */
4792+
4793+#ifndef __DBGAUFS_H__
4794+#define __DBGAUFS_H__
4795+
4796+#ifdef __KERNEL__
4797+
dece6358 4798+struct super_block;
1facf9fc 4799+struct au_sbinfo;
dece6358 4800+
1facf9fc 4801+#ifdef CONFIG_DEBUG_FS
4802+/* dbgaufs.c */
4803+void dbgaufs_brs_del(struct super_block *sb, aufs_bindex_t bindex);
4804+void dbgaufs_brs_add(struct super_block *sb, aufs_bindex_t bindex);
4805+void dbgaufs_si_fin(struct au_sbinfo *sbinfo);
4806+int dbgaufs_si_init(struct au_sbinfo *sbinfo);
4807+void dbgaufs_fin(void);
4808+int __init dbgaufs_init(void);
1facf9fc 4809+#else
4a4d8108
AM
4810+AuStubVoid(dbgaufs_brs_del, struct super_block *sb, aufs_bindex_t bindex)
4811+AuStubVoid(dbgaufs_brs_add, struct super_block *sb, aufs_bindex_t bindex)
4812+AuStubVoid(dbgaufs_si_fin, struct au_sbinfo *sbinfo)
4813+AuStubInt0(dbgaufs_si_init, struct au_sbinfo *sbinfo)
4814+AuStubVoid(dbgaufs_fin, void)
4815+AuStubInt0(__init dbgaufs_init, void)
1facf9fc 4816+#endif /* CONFIG_DEBUG_FS */
4817+
4818+#endif /* __KERNEL__ */
4819+#endif /* __DBGAUFS_H__ */
7f207e10
AM
4820diff -urN /usr/share/empty/fs/aufs/dcsub.c linux/fs/aufs/dcsub.c
4821--- /usr/share/empty/fs/aufs/dcsub.c 1970-01-01 01:00:00.000000000 +0100
7ce627cf 4822+++ linux/fs/aufs/dcsub.c 2012-05-22 09:06:08.867458905 +0200
027c5e7a 4823@@ -0,0 +1,243 @@
1facf9fc 4824+/*
f6c5ef8b 4825+ * Copyright (C) 2005-2012 Junjiro R. Okajima
1facf9fc 4826+ *
4827+ * This program, aufs is free software; you can redistribute it and/or modify
4828+ * it under the terms of the GNU General Public License as published by
4829+ * the Free Software Foundation; either version 2 of the License, or
4830+ * (at your option) any later version.
dece6358
AM
4831+ *
4832+ * This program is distributed in the hope that it will be useful,
4833+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
4834+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
4835+ * GNU General Public License for more details.
4836+ *
4837+ * You should have received a copy of the GNU General Public License
4838+ * along with this program; if not, write to the Free Software
4839+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 4840+ */
4841+
4842+/*
4843+ * sub-routines for dentry cache
4844+ */
4845+
4846+#include "aufs.h"
4847+
4848+static void au_dpage_free(struct au_dpage *dpage)
4849+{
4850+ int i;
4851+ struct dentry **p;
4852+
4853+ p = dpage->dentries;
4854+ for (i = 0; i < dpage->ndentry; i++)
4855+ dput(*p++);
4856+ free_page((unsigned long)dpage->dentries);
4857+}
4858+
4859+int au_dpages_init(struct au_dcsub_pages *dpages, gfp_t gfp)
4860+{
4861+ int err;
4862+ void *p;
4863+
4864+ err = -ENOMEM;
4865+ dpages->dpages = kmalloc(sizeof(*dpages->dpages), gfp);
4866+ if (unlikely(!dpages->dpages))
4867+ goto out;
4868+
4869+ p = (void *)__get_free_page(gfp);
4870+ if (unlikely(!p))
4871+ goto out_dpages;
4872+
4873+ dpages->dpages[0].ndentry = 0;
4874+ dpages->dpages[0].dentries = p;
4875+ dpages->ndpage = 1;
4876+ return 0; /* success */
4877+
4f0767ce 4878+out_dpages:
1facf9fc 4879+ kfree(dpages->dpages);
4f0767ce 4880+out:
1facf9fc 4881+ return err;
4882+}
4883+
4884+void au_dpages_free(struct au_dcsub_pages *dpages)
4885+{
4886+ int i;
4887+ struct au_dpage *p;
4888+
4889+ p = dpages->dpages;
4890+ for (i = 0; i < dpages->ndpage; i++)
4891+ au_dpage_free(p++);
4892+ kfree(dpages->dpages);
4893+}
4894+
4895+static int au_dpages_append(struct au_dcsub_pages *dpages,
4896+ struct dentry *dentry, gfp_t gfp)
4897+{
4898+ int err, sz;
4899+ struct au_dpage *dpage;
4900+ void *p;
4901+
4902+ dpage = dpages->dpages + dpages->ndpage - 1;
4903+ sz = PAGE_SIZE / sizeof(dentry);
4904+ if (unlikely(dpage->ndentry >= sz)) {
4905+ AuLabel(new dpage);
4906+ err = -ENOMEM;
4907+ sz = dpages->ndpage * sizeof(*dpages->dpages);
4908+ p = au_kzrealloc(dpages->dpages, sz,
4909+ sz + sizeof(*dpages->dpages), gfp);
4910+ if (unlikely(!p))
4911+ goto out;
4912+
4913+ dpages->dpages = p;
4914+ dpage = dpages->dpages + dpages->ndpage;
4915+ p = (void *)__get_free_page(gfp);
4916+ if (unlikely(!p))
4917+ goto out;
4918+
4919+ dpage->ndentry = 0;
4920+ dpage->dentries = p;
4921+ dpages->ndpage++;
4922+ }
4923+
027c5e7a
AM
4924+ AuDebugOn(!dentry->d_count);
4925+ dpage->dentries[dpage->ndentry++] = dget_dlock(dentry);
1facf9fc 4926+ return 0; /* success */
4927+
4f0767ce 4928+out:
1facf9fc 4929+ return err;
4930+}
4931+
4932+int au_dcsub_pages(struct au_dcsub_pages *dpages, struct dentry *root,
4933+ au_dpages_test test, void *arg)
4934+{
4935+ int err;
027c5e7a 4936+ struct dentry *this_parent;
1facf9fc 4937+ struct list_head *next;
4938+ struct super_block *sb = root->d_sb;
4939+
4940+ err = 0;
027c5e7a
AM
4941+ write_seqlock(&rename_lock);
4942+ this_parent = root;
4943+ spin_lock(&this_parent->d_lock);
4f0767ce 4944+repeat:
1facf9fc 4945+ next = this_parent->d_subdirs.next;
4f0767ce 4946+resume:
1facf9fc 4947+ if (this_parent->d_sb == sb
4948+ && !IS_ROOT(this_parent)
027c5e7a
AM
4949+ && au_di(this_parent)
4950+ && this_parent->d_count
1facf9fc 4951+ && (!test || test(this_parent, arg))) {
4952+ err = au_dpages_append(dpages, this_parent, GFP_ATOMIC);
4953+ if (unlikely(err))
4954+ goto out;
4955+ }
4956+
4957+ while (next != &this_parent->d_subdirs) {
4958+ struct list_head *tmp = next;
4959+ struct dentry *dentry = list_entry(tmp, struct dentry,
4960+ d_u.d_child);
027c5e7a 4961+
1facf9fc 4962+ next = tmp->next;
027c5e7a
AM
4963+ spin_lock_nested(&dentry->d_lock, DENTRY_D_LOCK_NESTED);
4964+ if (dentry->d_count) {
4965+ if (!list_empty(&dentry->d_subdirs)) {
4966+ spin_unlock(&this_parent->d_lock);
4967+ spin_release(&dentry->d_lock.dep_map, 1,
4968+ _RET_IP_);
4969+ this_parent = dentry;
4970+ spin_acquire(&this_parent->d_lock.dep_map, 0, 1,
4971+ _RET_IP_);
4972+ goto repeat;
4973+ }
4974+ if (dentry->d_sb == sb
4975+ && au_di(dentry)
4976+ && (!test || test(dentry, arg)))
4977+ err = au_dpages_append(dpages, dentry,
4978+ GFP_ATOMIC);
1facf9fc 4979+ }
027c5e7a
AM
4980+ spin_unlock(&dentry->d_lock);
4981+ if (unlikely(err))
4982+ goto out;
1facf9fc 4983+ }
4984+
4985+ if (this_parent != root) {
027c5e7a
AM
4986+ struct dentry *tmp;
4987+ struct dentry *child;
4988+
4989+ tmp = this_parent->d_parent;
4990+ rcu_read_lock();
4991+ spin_unlock(&this_parent->d_lock);
4992+ child = this_parent;
4993+ this_parent = tmp;
4994+ spin_lock(&this_parent->d_lock);
4995+ rcu_read_unlock();
4996+ next = child->d_u.d_child.next;
1facf9fc 4997+ goto resume;
4998+ }
027c5e7a 4999+
4f0767ce 5000+out:
027c5e7a
AM
5001+ spin_unlock(&this_parent->d_lock);
5002+ write_sequnlock(&rename_lock);
1facf9fc 5003+ return err;
5004+}
5005+
5006+int au_dcsub_pages_rev(struct au_dcsub_pages *dpages, struct dentry *dentry,
5007+ int do_include, au_dpages_test test, void *arg)
5008+{
5009+ int err;
5010+
5011+ err = 0;
027c5e7a
AM
5012+ write_seqlock(&rename_lock);
5013+ spin_lock(&dentry->d_lock);
5014+ if (do_include
5015+ && dentry->d_count
5016+ && (!test || test(dentry, arg)))
1facf9fc 5017+ err = au_dpages_append(dpages, dentry, GFP_ATOMIC);
027c5e7a
AM
5018+ spin_unlock(&dentry->d_lock);
5019+ if (unlikely(err))
5020+ goto out;
5021+
5022+ /*
5023+ * vfsmount_lock is unnecessary since this is a traverse in a single
5024+ * mount
5025+ */
1facf9fc 5026+ while (!IS_ROOT(dentry)) {
027c5e7a
AM
5027+ dentry = dentry->d_parent; /* rename_lock is locked */
5028+ spin_lock(&dentry->d_lock);
5029+ if (dentry->d_count
5030+ && (!test || test(dentry, arg)))
1facf9fc 5031+ err = au_dpages_append(dpages, dentry, GFP_ATOMIC);
027c5e7a
AM
5032+ spin_unlock(&dentry->d_lock);
5033+ if (unlikely(err))
5034+ break;
1facf9fc 5035+ }
5036+
4f0767ce 5037+out:
027c5e7a 5038+ write_sequnlock(&rename_lock);
1facf9fc 5039+ return err;
5040+}
5041+
027c5e7a
AM
5042+static inline int au_dcsub_dpages_aufs(struct dentry *dentry, void *arg)
5043+{
5044+ return au_di(dentry) && dentry->d_sb == arg;
5045+}
5046+
5047+int au_dcsub_pages_rev_aufs(struct au_dcsub_pages *dpages,
5048+ struct dentry *dentry, int do_include)
5049+{
5050+ return au_dcsub_pages_rev(dpages, dentry, do_include,
5051+ au_dcsub_dpages_aufs, dentry->d_sb);
5052+}
5053+
4a4d8108 5054+int au_test_subdir(struct dentry *d1, struct dentry *d2)
1facf9fc 5055+{
4a4d8108
AM
5056+ struct path path[2] = {
5057+ {
5058+ .dentry = d1
5059+ },
5060+ {
5061+ .dentry = d2
5062+ }
5063+ };
1facf9fc 5064+
4a4d8108 5065+ return path_is_under(path + 0, path + 1);
1facf9fc 5066+}
7f207e10
AM
5067diff -urN /usr/share/empty/fs/aufs/dcsub.h linux/fs/aufs/dcsub.h
5068--- /usr/share/empty/fs/aufs/dcsub.h 1970-01-01 01:00:00.000000000 +0100
7ce627cf 5069+++ linux/fs/aufs/dcsub.h 2012-05-22 09:06:08.867458905 +0200
f6c5ef8b 5070@@ -0,0 +1,94 @@
1facf9fc 5071+/*
f6c5ef8b 5072+ * Copyright (C) 2005-2012 Junjiro R. Okajima
1facf9fc 5073+ *
5074+ * This program, aufs is free software; you can redistribute it and/or modify
5075+ * it under the terms of the GNU General Public License as published by
5076+ * the Free Software Foundation; either version 2 of the License, or
5077+ * (at your option) any later version.
dece6358
AM
5078+ *
5079+ * This program is distributed in the hope that it will be useful,
5080+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
5081+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
5082+ * GNU General Public License for more details.
5083+ *
5084+ * You should have received a copy of the GNU General Public License
5085+ * along with this program; if not, write to the Free Software
5086+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 5087+ */
5088+
5089+/*
5090+ * sub-routines for dentry cache
5091+ */
5092+
5093+#ifndef __AUFS_DCSUB_H__
5094+#define __AUFS_DCSUB_H__
5095+
5096+#ifdef __KERNEL__
5097+
7f207e10 5098+#include <linux/dcache.h>
027c5e7a 5099+#include <linux/fs.h>
dece6358
AM
5100+
5101+struct dentry;
1facf9fc 5102+
5103+struct au_dpage {
5104+ int ndentry;
5105+ struct dentry **dentries;
5106+};
5107+
5108+struct au_dcsub_pages {
5109+ int ndpage;
5110+ struct au_dpage *dpages;
5111+};
5112+
5113+/* ---------------------------------------------------------------------- */
5114+
7f207e10 5115+/* dcsub.c */
1facf9fc 5116+int au_dpages_init(struct au_dcsub_pages *dpages, gfp_t gfp);
5117+void au_dpages_free(struct au_dcsub_pages *dpages);
5118+typedef int (*au_dpages_test)(struct dentry *dentry, void *arg);
5119+int au_dcsub_pages(struct au_dcsub_pages *dpages, struct dentry *root,
5120+ au_dpages_test test, void *arg);
5121+int au_dcsub_pages_rev(struct au_dcsub_pages *dpages, struct dentry *dentry,
5122+ int do_include, au_dpages_test test, void *arg);
027c5e7a
AM
5123+int au_dcsub_pages_rev_aufs(struct au_dcsub_pages *dpages,
5124+ struct dentry *dentry, int do_include);
4a4d8108 5125+int au_test_subdir(struct dentry *d1, struct dentry *d2);
1facf9fc 5126+
7f207e10
AM
5127+/* ---------------------------------------------------------------------- */
5128+
027c5e7a
AM
5129+static inline int au_d_hashed_positive(struct dentry *d)
5130+{
5131+ int err;
5132+ struct inode *inode = d->d_inode;
5133+ err = 0;
5134+ if (unlikely(d_unhashed(d) || !inode || !inode->i_nlink))
5135+ err = -ENOENT;
5136+ return err;
5137+}
5138+
5139+static inline int au_d_alive(struct dentry *d)
5140+{
5141+ int err;
5142+ struct inode *inode;
5143+ err = 0;
5144+ if (!IS_ROOT(d))
5145+ err = au_d_hashed_positive(d);
5146+ else {
5147+ inode = d->d_inode;
5148+ if (unlikely(d_unlinked(d) || !inode || !inode->i_nlink))
5149+ err = -ENOENT;
5150+ }
5151+ return err;
5152+}
5153+
5154+static inline int au_alive_dir(struct dentry *d)
7f207e10 5155+{
027c5e7a
AM
5156+ int err;
5157+ err = au_d_alive(d);
5158+ if (unlikely(err || IS_DEADDIR(d->d_inode)))
5159+ err = -ENOENT;
5160+ return err;
7f207e10
AM
5161+}
5162+
1facf9fc 5163+#endif /* __KERNEL__ */
5164+#endif /* __AUFS_DCSUB_H__ */
7f207e10
AM
5165diff -urN /usr/share/empty/fs/aufs/debug.c linux/fs/aufs/debug.c
5166--- /usr/share/empty/fs/aufs/debug.c 1970-01-01 01:00:00.000000000 +0100
7ce627cf 5167+++ linux/fs/aufs/debug.c 2012-05-22 09:06:08.867458905 +0200
f6c5ef8b 5168@@ -0,0 +1,489 @@
1facf9fc 5169+/*
f6c5ef8b 5170+ * Copyright (C) 2005-2012 Junjiro R. Okajima
1facf9fc 5171+ *
5172+ * This program, aufs is free software; you can redistribute it and/or modify
5173+ * it under the terms of the GNU General Public License as published by
5174+ * the Free Software Foundation; either version 2 of the License, or
5175+ * (at your option) any later version.
dece6358
AM
5176+ *
5177+ * This program is distributed in the hope that it will be useful,
5178+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
5179+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
5180+ * GNU General Public License for more details.
5181+ *
5182+ * You should have received a copy of the GNU General Public License
5183+ * along with this program; if not, write to the Free Software
5184+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 5185+ */
5186+
5187+/*
5188+ * debug print functions
5189+ */
5190+
7f207e10 5191+#include <linux/vt_kern.h>
1facf9fc 5192+#include "aufs.h"
5193+
5194+int aufs_debug;
5195+MODULE_PARM_DESC(debug, "debug print");
5196+module_param_named(debug, aufs_debug, int, S_IRUGO | S_IWUSR | S_IWGRP);
5197+
5198+char *au_plevel = KERN_DEBUG;
e49829fe
JR
5199+#define dpri(fmt, ...) do { \
5200+ if ((au_plevel \
5201+ && strcmp(au_plevel, KERN_DEBUG)) \
5202+ || au_debug_test()) \
5203+ printk("%s" fmt, au_plevel, ##__VA_ARGS__); \
1facf9fc 5204+} while (0)
5205+
5206+/* ---------------------------------------------------------------------- */
5207+
5208+void au_dpri_whlist(struct au_nhash *whlist)
5209+{
5210+ unsigned long ul, n;
5211+ struct hlist_head *head;
5212+ struct au_vdir_wh *tpos;
5213+ struct hlist_node *pos;
5214+
5215+ n = whlist->nh_num;
5216+ head = whlist->nh_head;
5217+ for (ul = 0; ul < n; ul++) {
5218+ hlist_for_each_entry(tpos, pos, head, wh_hash)
5219+ dpri("b%d, %.*s, %d\n",
5220+ tpos->wh_bindex,
5221+ tpos->wh_str.len, tpos->wh_str.name,
5222+ tpos->wh_str.len);
5223+ head++;
5224+ }
5225+}
5226+
5227+void au_dpri_vdir(struct au_vdir *vdir)
5228+{
5229+ unsigned long ul;
5230+ union au_vdir_deblk_p p;
5231+ unsigned char *o;
5232+
5233+ if (!vdir || IS_ERR(vdir)) {
5234+ dpri("err %ld\n", PTR_ERR(vdir));
5235+ return;
5236+ }
5237+
5238+ dpri("deblk %u, nblk %lu, deblk %p, last{%lu, %p}, ver %lu\n",
5239+ vdir->vd_deblk_sz, vdir->vd_nblk, vdir->vd_deblk,
5240+ vdir->vd_last.ul, vdir->vd_last.p.deblk, vdir->vd_version);
5241+ for (ul = 0; ul < vdir->vd_nblk; ul++) {
5242+ p.deblk = vdir->vd_deblk[ul];
5243+ o = p.deblk;
5244+ dpri("[%lu]: %p\n", ul, o);
5245+ }
5246+}
5247+
53392da6 5248+static int do_pri_inode(aufs_bindex_t bindex, struct inode *inode, int hn,
1facf9fc 5249+ struct dentry *wh)
5250+{
5251+ char *n = NULL;
5252+ int l = 0;
5253+
5254+ if (!inode || IS_ERR(inode)) {
5255+ dpri("i%d: err %ld\n", bindex, PTR_ERR(inode));
5256+ return -1;
5257+ }
5258+
5259+ /* the type of i_blocks depends upon CONFIG_LSF */
5260+ BUILD_BUG_ON(sizeof(inode->i_blocks) != sizeof(unsigned long)
5261+ && sizeof(inode->i_blocks) != sizeof(u64));
5262+ if (wh) {
5263+ n = (void *)wh->d_name.name;
5264+ l = wh->d_name.len;
5265+ }
5266+
53392da6
AM
5267+ dpri("i%d: %p, i%lu, %s, cnt %d, nl %u, 0%o, sz %llu, blk %llu,"
5268+ " hn %d, ct %lld, np %lu, st 0x%lx, f 0x%x, v %llu, g %x%s%.*s\n",
5269+ bindex, inode,
1facf9fc 5270+ inode->i_ino, inode->i_sb ? au_sbtype(inode->i_sb) : "??",
5271+ atomic_read(&inode->i_count), inode->i_nlink, inode->i_mode,
5272+ i_size_read(inode), (unsigned long long)inode->i_blocks,
53392da6 5273+ hn, (long long)timespec_to_ns(&inode->i_ctime) & 0x0ffff,
1facf9fc 5274+ inode->i_mapping ? inode->i_mapping->nrpages : 0,
b752ccd1
AM
5275+ inode->i_state, inode->i_flags, inode->i_version,
5276+ inode->i_generation,
1facf9fc 5277+ l ? ", wh " : "", l, n);
5278+ return 0;
5279+}
5280+
5281+void au_dpri_inode(struct inode *inode)
5282+{
5283+ struct au_iinfo *iinfo;
5284+ aufs_bindex_t bindex;
53392da6 5285+ int err, hn;
1facf9fc 5286+
53392da6 5287+ err = do_pri_inode(-1, inode, -1, NULL);
1facf9fc 5288+ if (err || !au_test_aufs(inode->i_sb))
5289+ return;
5290+
5291+ iinfo = au_ii(inode);
5292+ if (!iinfo)
5293+ return;
5294+ dpri("i-1: bstart %d, bend %d, gen %d\n",
5295+ iinfo->ii_bstart, iinfo->ii_bend, au_iigen(inode));
5296+ if (iinfo->ii_bstart < 0)
5297+ return;
53392da6
AM
5298+ hn = 0;
5299+ for (bindex = iinfo->ii_bstart; bindex <= iinfo->ii_bend; bindex++) {
5300+ hn = !!au_hn(iinfo->ii_hinode + bindex);
5301+ do_pri_inode(bindex, iinfo->ii_hinode[0 + bindex].hi_inode, hn,
1facf9fc 5302+ iinfo->ii_hinode[0 + bindex].hi_whdentry);
53392da6 5303+ }
1facf9fc 5304+}
5305+
2cbb1c4b
JR
5306+void au_dpri_dalias(struct inode *inode)
5307+{
5308+ struct dentry *d;
5309+
5310+ spin_lock(&inode->i_lock);
5311+ list_for_each_entry(d, &inode->i_dentry, d_alias)
5312+ au_dpri_dentry(d);
5313+ spin_unlock(&inode->i_lock);
5314+}
5315+
1facf9fc 5316+static int do_pri_dentry(aufs_bindex_t bindex, struct dentry *dentry)
5317+{
5318+ struct dentry *wh = NULL;
53392da6 5319+ int hn;
1facf9fc 5320+
5321+ if (!dentry || IS_ERR(dentry)) {
5322+ dpri("d%d: err %ld\n", bindex, PTR_ERR(dentry));
5323+ return -1;
5324+ }
5325+ /* do not call dget_parent() here */
027c5e7a 5326+ /* note: access d_xxx without d_lock */
1facf9fc 5327+ dpri("d%d: %.*s?/%.*s, %s, cnt %d, flags 0x%x\n",
5328+ bindex,
5329+ AuDLNPair(dentry->d_parent), AuDLNPair(dentry),
5330+ dentry->d_sb ? au_sbtype(dentry->d_sb) : "??",
027c5e7a 5331+ dentry->d_count, dentry->d_flags);
53392da6 5332+ hn = -1;
1facf9fc 5333+ if (bindex >= 0 && dentry->d_inode && au_test_aufs(dentry->d_sb)) {
5334+ struct au_iinfo *iinfo = au_ii(dentry->d_inode);
53392da6
AM
5335+ if (iinfo) {
5336+ hn = !!au_hn(iinfo->ii_hinode + bindex);
1facf9fc 5337+ wh = iinfo->ii_hinode[0 + bindex].hi_whdentry;
53392da6 5338+ }
1facf9fc 5339+ }
53392da6 5340+ do_pri_inode(bindex, dentry->d_inode, hn, wh);
1facf9fc 5341+ return 0;
5342+}
5343+
5344+void au_dpri_dentry(struct dentry *dentry)
5345+{
5346+ struct au_dinfo *dinfo;
5347+ aufs_bindex_t bindex;
5348+ int err;
4a4d8108 5349+ struct au_hdentry *hdp;
1facf9fc 5350+
5351+ err = do_pri_dentry(-1, dentry);
5352+ if (err || !au_test_aufs(dentry->d_sb))
5353+ return;
5354+
5355+ dinfo = au_di(dentry);
5356+ if (!dinfo)
5357+ return;
5358+ dpri("d-1: bstart %d, bend %d, bwh %d, bdiropq %d, gen %d\n",
5359+ dinfo->di_bstart, dinfo->di_bend,
5360+ dinfo->di_bwh, dinfo->di_bdiropq, au_digen(dentry));
5361+ if (dinfo->di_bstart < 0)
5362+ return;
4a4d8108 5363+ hdp = dinfo->di_hdentry;
1facf9fc 5364+ for (bindex = dinfo->di_bstart; bindex <= dinfo->di_bend; bindex++)
4a4d8108 5365+ do_pri_dentry(bindex, hdp[0 + bindex].hd_dentry);
1facf9fc 5366+}
5367+
5368+static int do_pri_file(aufs_bindex_t bindex, struct file *file)
5369+{
5370+ char a[32];
5371+
5372+ if (!file || IS_ERR(file)) {
5373+ dpri("f%d: err %ld\n", bindex, PTR_ERR(file));
5374+ return -1;
5375+ }
5376+ a[0] = 0;
5377+ if (bindex < 0
5378+ && file->f_dentry
5379+ && au_test_aufs(file->f_dentry->d_sb)
5380+ && au_fi(file))
e49829fe 5381+ snprintf(a, sizeof(a), ", gen %d, mmapped %d",
2cbb1c4b 5382+ au_figen(file), atomic_read(&au_fi(file)->fi_mmapped));
b752ccd1 5383+ dpri("f%d: mode 0x%x, flags 0%o, cnt %ld, v %llu, pos %llu%s\n",
1facf9fc 5384+ bindex, file->f_mode, file->f_flags, (long)file_count(file),
b752ccd1 5385+ file->f_version, file->f_pos, a);
1facf9fc 5386+ if (file->f_dentry)
5387+ do_pri_dentry(bindex, file->f_dentry);
5388+ return 0;
5389+}
5390+
5391+void au_dpri_file(struct file *file)
5392+{
5393+ struct au_finfo *finfo;
4a4d8108
AM
5394+ struct au_fidir *fidir;
5395+ struct au_hfile *hfile;
1facf9fc 5396+ aufs_bindex_t bindex;
5397+ int err;
5398+
5399+ err = do_pri_file(-1, file);
5400+ if (err || !file->f_dentry || !au_test_aufs(file->f_dentry->d_sb))
5401+ return;
5402+
5403+ finfo = au_fi(file);
5404+ if (!finfo)
5405+ return;
4a4d8108 5406+ if (finfo->fi_btop < 0)
1facf9fc 5407+ return;
4a4d8108
AM
5408+ fidir = finfo->fi_hdir;
5409+ if (!fidir)
5410+ do_pri_file(finfo->fi_btop, finfo->fi_htop.hf_file);
5411+ else
e49829fe
JR
5412+ for (bindex = finfo->fi_btop;
5413+ bindex >= 0 && bindex <= fidir->fd_bbot;
4a4d8108
AM
5414+ bindex++) {
5415+ hfile = fidir->fd_hfile + bindex;
5416+ do_pri_file(bindex, hfile ? hfile->hf_file : NULL);
5417+ }
1facf9fc 5418+}
5419+
5420+static int do_pri_br(aufs_bindex_t bindex, struct au_branch *br)
5421+{
5422+ struct vfsmount *mnt;
5423+ struct super_block *sb;
5424+
5425+ if (!br || IS_ERR(br))
5426+ goto out;
5427+ mnt = br->br_mnt;
5428+ if (!mnt || IS_ERR(mnt))
5429+ goto out;
5430+ sb = mnt->mnt_sb;
5431+ if (!sb || IS_ERR(sb))
5432+ goto out;
5433+
1e00d052 5434+ dpri("s%d: {perm 0x%x, id %d, cnt %d, wbr %p}, "
b752ccd1 5435+ "%s, dev 0x%02x%02x, flags 0x%lx, cnt %d, active %d, "
1facf9fc 5436+ "xino %d\n",
1e00d052
AM
5437+ bindex, br->br_perm, br->br_id, atomic_read(&br->br_count),
5438+ br->br_wbr, au_sbtype(sb), MAJOR(sb->s_dev), MINOR(sb->s_dev),
b752ccd1 5439+ sb->s_flags, sb->s_count,
1facf9fc 5440+ atomic_read(&sb->s_active), !!br->br_xino.xi_file);
5441+ return 0;
5442+
4f0767ce 5443+out:
1facf9fc 5444+ dpri("s%d: err %ld\n", bindex, PTR_ERR(br));
5445+ return -1;
5446+}
5447+
5448+void au_dpri_sb(struct super_block *sb)
5449+{
5450+ struct au_sbinfo *sbinfo;
5451+ aufs_bindex_t bindex;
5452+ int err;
5453+ /* to reuduce stack size */
5454+ struct {
5455+ struct vfsmount mnt;
5456+ struct au_branch fake;
5457+ } *a;
5458+
5459+ /* this function can be called from magic sysrq */
5460+ a = kzalloc(sizeof(*a), GFP_ATOMIC);
5461+ if (unlikely(!a)) {
5462+ dpri("no memory\n");
5463+ return;
5464+ }
5465+
5466+ a->mnt.mnt_sb = sb;
5467+ a->fake.br_perm = 0;
5468+ a->fake.br_mnt = &a->mnt;
5469+ a->fake.br_xino.xi_file = NULL;
5470+ atomic_set(&a->fake.br_count, 0);
5471+ smp_mb(); /* atomic_set */
5472+ err = do_pri_br(-1, &a->fake);
5473+ kfree(a);
5474+ dpri("dev 0x%x\n", sb->s_dev);
5475+ if (err || !au_test_aufs(sb))
5476+ return;
5477+
5478+ sbinfo = au_sbi(sb);
5479+ if (!sbinfo)
5480+ return;
5481+ dpri("nw %d, gen %u, kobj %d\n",
5482+ atomic_read(&sbinfo->si_nowait.nw_len), sbinfo->si_generation,
5483+ atomic_read(&sbinfo->si_kobj.kref.refcount));
5484+ for (bindex = 0; bindex <= sbinfo->si_bend; bindex++)
5485+ do_pri_br(bindex, sbinfo->si_branch[0 + bindex]);
5486+}
5487+
5488+/* ---------------------------------------------------------------------- */
5489+
5490+void au_dbg_sleep_jiffy(int jiffy)
5491+{
5492+ while (jiffy)
5493+ jiffy = schedule_timeout_uninterruptible(jiffy);
5494+}
5495+
5496+void au_dbg_iattr(struct iattr *ia)
5497+{
5498+#define AuBit(name) if (ia->ia_valid & ATTR_ ## name) \
5499+ dpri(#name "\n")
5500+ AuBit(MODE);
5501+ AuBit(UID);
5502+ AuBit(GID);
5503+ AuBit(SIZE);
5504+ AuBit(ATIME);
5505+ AuBit(MTIME);
5506+ AuBit(CTIME);
5507+ AuBit(ATIME_SET);
5508+ AuBit(MTIME_SET);
5509+ AuBit(FORCE);
5510+ AuBit(ATTR_FLAG);
5511+ AuBit(KILL_SUID);
5512+ AuBit(KILL_SGID);
5513+ AuBit(FILE);
5514+ AuBit(KILL_PRIV);
5515+ AuBit(OPEN);
5516+ AuBit(TIMES_SET);
5517+#undef AuBit
5518+ dpri("ia_file %p\n", ia->ia_file);
5519+}
5520+
5521+/* ---------------------------------------------------------------------- */
5522+
027c5e7a
AM
5523+void __au_dbg_verify_dinode(struct dentry *dentry, const char *func, int line)
5524+{
5525+ struct inode *h_inode, *inode = dentry->d_inode;
5526+ struct dentry *h_dentry;
5527+ aufs_bindex_t bindex, bend, bi;
5528+
5529+ if (!inode /* || au_di(dentry)->di_lsc == AuLsc_DI_TMP */)
5530+ return;
5531+
5532+ bend = au_dbend(dentry);
5533+ bi = au_ibend(inode);
5534+ if (bi < bend)
5535+ bend = bi;
5536+ bindex = au_dbstart(dentry);
5537+ bi = au_ibstart(inode);
5538+ if (bi > bindex)
5539+ bindex = bi;
5540+
5541+ for (; bindex <= bend; bindex++) {
5542+ h_dentry = au_h_dptr(dentry, bindex);
5543+ if (!h_dentry)
5544+ continue;
5545+ h_inode = au_h_iptr(inode, bindex);
5546+ if (unlikely(h_inode != h_dentry->d_inode)) {
5547+ int old = au_debug_test();
5548+ if (!old)
5549+ au_debug(1);
5550+ AuDbg("b%d, %s:%d\n", bindex, func, line);
5551+ AuDbgDentry(dentry);
5552+ AuDbgInode(inode);
5553+ if (!old)
5554+ au_debug(0);
5555+ BUG();
5556+ }
5557+ }
5558+}
5559+
1facf9fc 5560+void au_dbg_verify_dir_parent(struct dentry *dentry, unsigned int sigen)
5561+{
5562+ struct dentry *parent;
5563+
5564+ parent = dget_parent(dentry);
027c5e7a
AM
5565+ AuDebugOn(!S_ISDIR(dentry->d_inode->i_mode));
5566+ AuDebugOn(IS_ROOT(dentry));
5567+ AuDebugOn(au_digen_test(parent, sigen));
1facf9fc 5568+ dput(parent);
5569+}
5570+
5571+void au_dbg_verify_nondir_parent(struct dentry *dentry, unsigned int sigen)
5572+{
5573+ struct dentry *parent;
027c5e7a 5574+ struct inode *inode;
1facf9fc 5575+
5576+ parent = dget_parent(dentry);
027c5e7a
AM
5577+ inode = dentry->d_inode;
5578+ AuDebugOn(inode && S_ISDIR(dentry->d_inode->i_mode));
5579+ AuDebugOn(au_digen_test(parent, sigen));
1facf9fc 5580+ dput(parent);
5581+}
5582+
5583+void au_dbg_verify_gen(struct dentry *parent, unsigned int sigen)
5584+{
5585+ int err, i, j;
5586+ struct au_dcsub_pages dpages;
5587+ struct au_dpage *dpage;
5588+ struct dentry **dentries;
5589+
5590+ err = au_dpages_init(&dpages, GFP_NOFS);
5591+ AuDebugOn(err);
027c5e7a 5592+ err = au_dcsub_pages_rev_aufs(&dpages, parent, /*do_include*/1);
1facf9fc 5593+ AuDebugOn(err);
5594+ for (i = dpages.ndpage - 1; !err && i >= 0; i--) {
5595+ dpage = dpages.dpages + i;
5596+ dentries = dpage->dentries;
5597+ for (j = dpage->ndentry - 1; !err && j >= 0; j--)
027c5e7a 5598+ AuDebugOn(au_digen_test(dentries[j], sigen));
1facf9fc 5599+ }
5600+ au_dpages_free(&dpages);
5601+}
5602+
1facf9fc 5603+void au_dbg_verify_kthread(void)
5604+{
53392da6 5605+ if (au_wkq_test()) {
1facf9fc 5606+ au_dbg_blocked();
1e00d052
AM
5607+ /*
5608+ * It may be recursive, but udba=notify between two aufs mounts,
5609+ * where a single ro branch is shared, is not a problem.
5610+ */
5611+ /* WARN_ON(1); */
1facf9fc 5612+ }
5613+}
5614+
5615+/* ---------------------------------------------------------------------- */
5616+
5617+void au_debug_sbinfo_init(struct au_sbinfo *sbinfo __maybe_unused)
5618+{
5619+#ifdef AuForceNoPlink
5620+ au_opt_clr(sbinfo->si_mntflags, PLINK);
5621+#endif
5622+#ifdef AuForceNoXino
5623+ au_opt_clr(sbinfo->si_mntflags, XINO);
5624+#endif
5625+#ifdef AuForceNoRefrof
5626+ au_opt_clr(sbinfo->si_mntflags, REFROF);
5627+#endif
4a4d8108
AM
5628+#ifdef AuForceHnotify
5629+ au_opt_set_udba(sbinfo->si_mntflags, UDBA_HNOTIFY);
1facf9fc 5630+#endif
1308ab2a 5631+#ifdef AuForceRd0
5632+ sbinfo->si_rdblk = 0;
5633+ sbinfo->si_rdhash = 0;
5634+#endif
1facf9fc 5635+}
5636+
5637+int __init au_debug_init(void)
5638+{
5639+ aufs_bindex_t bindex;
5640+ struct au_vdir_destr destr;
5641+
5642+ bindex = -1;
5643+ AuDebugOn(bindex >= 0);
5644+
5645+ destr.len = -1;
5646+ AuDebugOn(destr.len < NAME_MAX);
5647+
5648+#ifdef CONFIG_4KSTACKS
4a4d8108 5649+ pr_warning("CONFIG_4KSTACKS is defined.\n");
1facf9fc 5650+#endif
5651+
5652+#ifdef AuForceNoBrs
5653+ sysaufs_brs = 0;
5654+#endif
5655+
5656+ return 0;
5657+}
7f207e10
AM
5658diff -urN /usr/share/empty/fs/aufs/debug.h linux/fs/aufs/debug.h
5659--- /usr/share/empty/fs/aufs/debug.h 1970-01-01 01:00:00.000000000 +0100
7ce627cf 5660+++ linux/fs/aufs/debug.h 2012-05-22 09:06:08.867458905 +0200
92d182d2 5661@@ -0,0 +1,242 @@
1facf9fc 5662+/*
f6c5ef8b 5663+ * Copyright (C) 2005-2012 Junjiro R. Okajima
1facf9fc 5664+ *
5665+ * This program, aufs is free software; you can redistribute it and/or modify
5666+ * it under the terms of the GNU General Public License as published by
5667+ * the Free Software Foundation; either version 2 of the License, or
5668+ * (at your option) any later version.
dece6358
AM
5669+ *
5670+ * This program is distributed in the hope that it will be useful,
5671+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
5672+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
5673+ * GNU General Public License for more details.
5674+ *
5675+ * You should have received a copy of the GNU General Public License
5676+ * along with this program; if not, write to the Free Software
5677+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 5678+ */
5679+
5680+/*
5681+ * debug print functions
5682+ */
5683+
5684+#ifndef __AUFS_DEBUG_H__
5685+#define __AUFS_DEBUG_H__
5686+
5687+#ifdef __KERNEL__
5688+
4a4d8108
AM
5689+#include <linux/module.h>
5690+#include <linux/kallsyms.h>
1facf9fc 5691+#include <linux/sysrq.h>
4a4d8108 5692+
1facf9fc 5693+#ifdef CONFIG_AUFS_DEBUG
5694+#define AuDebugOn(a) BUG_ON(a)
5695+
5696+/* module parameter */
5697+extern int aufs_debug;
5698+static inline void au_debug(int n)
5699+{
5700+ aufs_debug = n;
5701+ smp_mb();
5702+}
5703+
5704+static inline int au_debug_test(void)
5705+{
5706+ return aufs_debug;
5707+}
5708+#else
5709+#define AuDebugOn(a) do {} while (0)
4a4d8108
AM
5710+AuStubVoid(au_debug, int n)
5711+AuStubInt0(au_debug_test, void)
1facf9fc 5712+#endif /* CONFIG_AUFS_DEBUG */
5713+
5714+/* ---------------------------------------------------------------------- */
5715+
5716+/* debug print */
5717+
4a4d8108 5718+#define AuDbg(fmt, ...) do { \
1facf9fc 5719+ if (au_debug_test()) \
4a4d8108 5720+ pr_debug("DEBUG: " fmt, ##__VA_ARGS__); \
1facf9fc 5721+} while (0)
4a4d8108
AM
5722+#define AuLabel(l) AuDbg(#l "\n")
5723+#define AuIOErr(fmt, ...) pr_err("I/O Error, " fmt, ##__VA_ARGS__)
5724+#define AuWarn1(fmt, ...) do { \
1facf9fc 5725+ static unsigned char _c; \
5726+ if (!_c++) \
4a4d8108 5727+ pr_warning(fmt, ##__VA_ARGS__); \
1facf9fc 5728+} while (0)
5729+
4a4d8108 5730+#define AuErr1(fmt, ...) do { \
1facf9fc 5731+ static unsigned char _c; \
5732+ if (!_c++) \
4a4d8108 5733+ pr_err(fmt, ##__VA_ARGS__); \
1facf9fc 5734+} while (0)
5735+
4a4d8108 5736+#define AuIOErr1(fmt, ...) do { \
1facf9fc 5737+ static unsigned char _c; \
5738+ if (!_c++) \
4a4d8108 5739+ AuIOErr(fmt, ##__VA_ARGS__); \
1facf9fc 5740+} while (0)
5741+
5742+#define AuUnsupportMsg "This operation is not supported." \
5743+ " Please report this application to aufs-users ML."
4a4d8108
AM
5744+#define AuUnsupport(fmt, ...) do { \
5745+ pr_err(AuUnsupportMsg "\n" fmt, ##__VA_ARGS__); \
1facf9fc 5746+ dump_stack(); \
5747+} while (0)
5748+
5749+#define AuTraceErr(e) do { \
5750+ if (unlikely((e) < 0)) \
5751+ AuDbg("err %d\n", (int)(e)); \
5752+} while (0)
5753+
5754+#define AuTraceErrPtr(p) do { \
5755+ if (IS_ERR(p)) \
5756+ AuDbg("err %ld\n", PTR_ERR(p)); \
5757+} while (0)
5758+
5759+/* dirty macros for debug print, use with "%.*s" and caution */
5760+#define AuLNPair(qstr) (qstr)->len, (qstr)->name
5761+#define AuDLNPair(d) AuLNPair(&(d)->d_name)
5762+
5763+/* ---------------------------------------------------------------------- */
5764+
5765+struct au_sbinfo;
5766+struct au_finfo;
dece6358 5767+struct dentry;
1facf9fc 5768+#ifdef CONFIG_AUFS_DEBUG
5769+extern char *au_plevel;
5770+struct au_nhash;
5771+void au_dpri_whlist(struct au_nhash *whlist);
5772+struct au_vdir;
5773+void au_dpri_vdir(struct au_vdir *vdir);
dece6358 5774+struct inode;
1facf9fc 5775+void au_dpri_inode(struct inode *inode);
2cbb1c4b 5776+void au_dpri_dalias(struct inode *inode);
1facf9fc 5777+void au_dpri_dentry(struct dentry *dentry);
dece6358 5778+struct file;
1facf9fc 5779+void au_dpri_file(struct file *filp);
dece6358 5780+struct super_block;
1facf9fc 5781+void au_dpri_sb(struct super_block *sb);
5782+
5783+void au_dbg_sleep_jiffy(int jiffy);
dece6358 5784+struct iattr;
1facf9fc 5785+void au_dbg_iattr(struct iattr *ia);
5786+
027c5e7a
AM
5787+#define au_dbg_verify_dinode(d) __au_dbg_verify_dinode(d, __func__, __LINE__)
5788+void __au_dbg_verify_dinode(struct dentry *dentry, const char *func, int line);
1facf9fc 5789+void au_dbg_verify_dir_parent(struct dentry *dentry, unsigned int sigen);
5790+void au_dbg_verify_nondir_parent(struct dentry *dentry, unsigned int sigen);
5791+void au_dbg_verify_gen(struct dentry *parent, unsigned int sigen);
1facf9fc 5792+void au_dbg_verify_kthread(void);
5793+
5794+int __init au_debug_init(void);
5795+void au_debug_sbinfo_init(struct au_sbinfo *sbinfo);
5796+#define AuDbgWhlist(w) do { \
5797+ AuDbg(#w "\n"); \
5798+ au_dpri_whlist(w); \
5799+} while (0)
5800+
5801+#define AuDbgVdir(v) do { \
5802+ AuDbg(#v "\n"); \
5803+ au_dpri_vdir(v); \
5804+} while (0)
5805+
5806+#define AuDbgInode(i) do { \
5807+ AuDbg(#i "\n"); \
5808+ au_dpri_inode(i); \
5809+} while (0)
5810+
2cbb1c4b
JR
5811+#define AuDbgDAlias(i) do { \
5812+ AuDbg(#i "\n"); \
5813+ au_dpri_dalias(i); \
5814+} while (0)
5815+
1facf9fc 5816+#define AuDbgDentry(d) do { \
5817+ AuDbg(#d "\n"); \
5818+ au_dpri_dentry(d); \
5819+} while (0)
5820+
5821+#define AuDbgFile(f) do { \
5822+ AuDbg(#f "\n"); \
5823+ au_dpri_file(f); \
5824+} while (0)
5825+
5826+#define AuDbgSb(sb) do { \
5827+ AuDbg(#sb "\n"); \
5828+ au_dpri_sb(sb); \
5829+} while (0)
5830+
5831+#define AuDbgSleep(sec) do { \
5832+ AuDbg("sleep %d sec\n", sec); \
5833+ ssleep(sec); \
5834+} while (0)
5835+
5836+#define AuDbgSleepJiffy(jiffy) do { \
5837+ AuDbg("sleep %d jiffies\n", jiffy); \
5838+ au_dbg_sleep_jiffy(jiffy); \
5839+} while (0)
5840+
5841+#define AuDbgIAttr(ia) do { \
5842+ AuDbg("ia_valid 0x%x\n", (ia)->ia_valid); \
5843+ au_dbg_iattr(ia); \
5844+} while (0)
4a4d8108
AM
5845+
5846+#define AuDbgSym(addr) do { \
5847+ char sym[KSYM_SYMBOL_LEN]; \
5848+ sprint_symbol(sym, (unsigned long)addr); \
5849+ AuDbg("%s\n", sym); \
5850+} while (0)
5851+
5852+#define AuInfoSym(addr) do { \
5853+ char sym[KSYM_SYMBOL_LEN]; \
5854+ sprint_symbol(sym, (unsigned long)addr); \
5855+ AuInfo("%s\n", sym); \
5856+} while (0)
1facf9fc 5857+#else
027c5e7a 5858+AuStubVoid(au_dbg_verify_dinode, struct dentry *dentry)
4a4d8108
AM
5859+AuStubVoid(au_dbg_verify_dir_parent, struct dentry *dentry, unsigned int sigen)
5860+AuStubVoid(au_dbg_verify_nondir_parent, struct dentry *dentry,
5861+ unsigned int sigen)
5862+AuStubVoid(au_dbg_verify_gen, struct dentry *parent, unsigned int sigen)
5863+AuStubVoid(au_dbg_verify_kthread, void)
5864+AuStubInt0(__init au_debug_init, void)
5865+AuStubVoid(au_debug_sbinfo_init, struct au_sbinfo *sbinfo)
1facf9fc 5866+
1facf9fc 5867+#define AuDbgWhlist(w) do {} while (0)
5868+#define AuDbgVdir(v) do {} while (0)
5869+#define AuDbgInode(i) do {} while (0)
2cbb1c4b 5870+#define AuDbgDAlias(i) do {} while (0)
1facf9fc 5871+#define AuDbgDentry(d) do {} while (0)
5872+#define AuDbgFile(f) do {} while (0)
5873+#define AuDbgSb(sb) do {} while (0)
5874+#define AuDbgSleep(sec) do {} while (0)
5875+#define AuDbgSleepJiffy(jiffy) do {} while (0)
5876+#define AuDbgIAttr(ia) do {} while (0)
4a4d8108
AM
5877+#define AuDbgSym(addr) do {} while (0)
5878+#define AuInfoSym(addr) do {} while (0)
1facf9fc 5879+#endif /* CONFIG_AUFS_DEBUG */
5880+
5881+/* ---------------------------------------------------------------------- */
5882+
5883+#ifdef CONFIG_AUFS_MAGIC_SYSRQ
5884+int __init au_sysrq_init(void);
5885+void au_sysrq_fin(void);
5886+
5887+#ifdef CONFIG_HW_CONSOLE
5888+#define au_dbg_blocked() do { \
5889+ WARN_ON(1); \
0c5527e5 5890+ handle_sysrq('w'); \
1facf9fc 5891+} while (0)
5892+#else
4a4d8108 5893+AuStubVoid(au_dbg_blocked, void)
1facf9fc 5894+#endif
5895+
5896+#else
4a4d8108
AM
5897+AuStubInt0(__init au_sysrq_init, void)
5898+AuStubVoid(au_sysrq_fin, void)
5899+AuStubVoid(au_dbg_blocked, void)
1facf9fc 5900+#endif /* CONFIG_AUFS_MAGIC_SYSRQ */
5901+
5902+#endif /* __KERNEL__ */
5903+#endif /* __AUFS_DEBUG_H__ */
7f207e10
AM
5904diff -urN /usr/share/empty/fs/aufs/dentry.c linux/fs/aufs/dentry.c
5905--- /usr/share/empty/fs/aufs/dentry.c 1970-01-01 01:00:00.000000000 +0100
7ce627cf 5906+++ linux/fs/aufs/dentry.c 2012-05-22 09:06:08.867458905 +0200
027c5e7a 5907@@ -0,0 +1,1140 @@
1facf9fc 5908+/*
f6c5ef8b 5909+ * Copyright (C) 2005-2012 Junjiro R. Okajima
1facf9fc 5910+ *
5911+ * This program, aufs is free software; you can redistribute it and/or modify
5912+ * it under the terms of the GNU General Public License as published by
5913+ * the Free Software Foundation; either version 2 of the License, or
5914+ * (at your option) any later version.
dece6358
AM
5915+ *
5916+ * This program is distributed in the hope that it will be useful,
5917+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
5918+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
5919+ * GNU General Public License for more details.
5920+ *
5921+ * You should have received a copy of the GNU General Public License
5922+ * along with this program; if not, write to the Free Software
5923+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 5924+ */
5925+
5926+/*
5927+ * lookup and dentry operations
5928+ */
5929+
dece6358 5930+#include <linux/namei.h>
1facf9fc 5931+#include "aufs.h"
5932+
5933+static void au_h_nd(struct nameidata *h_nd, struct nameidata *nd)
5934+{
5935+ if (nd) {
5936+ *h_nd = *nd;
5937+
5938+ /*
5939+ * gave up supporting LOOKUP_CREATE/OPEN for lower fs,
5940+ * due to whiteout and branch permission.
5941+ */
5942+ h_nd->flags &= ~(/*LOOKUP_PARENT |*/ LOOKUP_OPEN | LOOKUP_CREATE
b752ccd1 5943+ | LOOKUP_FOLLOW | LOOKUP_EXCL);
1facf9fc 5944+ /* unnecessary? */
5945+ h_nd->intent.open.file = NULL;
5946+ } else
5947+ memset(h_nd, 0, sizeof(*h_nd));
5948+}
5949+
5950+struct au_lkup_one_args {
5951+ struct dentry **errp;
5952+ struct qstr *name;
5953+ struct dentry *h_parent;
5954+ struct au_branch *br;
5955+ struct nameidata *nd;
5956+};
5957+
5958+struct dentry *au_lkup_one(struct qstr *name, struct dentry *h_parent,
5959+ struct au_branch *br, struct nameidata *nd)
5960+{
5961+ struct dentry *h_dentry;
5962+ int err;
5963+ struct nameidata h_nd;
5964+
5965+ if (au_test_fs_null_nd(h_parent->d_sb))
5966+ return vfsub_lookup_one_len(name->name, h_parent, name->len);
5967+
5968+ au_h_nd(&h_nd, nd);
5969+ h_nd.path.dentry = h_parent;
5970+ h_nd.path.mnt = br->br_mnt;
5971+
2cbb1c4b 5972+ err = vfsub_name_hash(name->name, &h_nd.last, name->len);
1facf9fc 5973+ h_dentry = ERR_PTR(err);
5974+ if (!err) {
5975+ path_get(&h_nd.path);
5976+ h_dentry = vfsub_lookup_hash(&h_nd);
5977+ path_put(&h_nd.path);
5978+ }
5979+
4a4d8108 5980+ AuTraceErrPtr(h_dentry);
1facf9fc 5981+ return h_dentry;
5982+}
5983+
5984+static void au_call_lkup_one(void *args)
5985+{
5986+ struct au_lkup_one_args *a = args;
5987+ *a->errp = au_lkup_one(a->name, a->h_parent, a->br, a->nd);
5988+}
5989+
5990+#define AuLkup_ALLOW_NEG 1
5991+#define au_ftest_lkup(flags, name) ((flags) & AuLkup_##name)
7f207e10
AM
5992+#define au_fset_lkup(flags, name) \
5993+ do { (flags) |= AuLkup_##name; } while (0)
5994+#define au_fclr_lkup(flags, name) \
5995+ do { (flags) &= ~AuLkup_##name; } while (0)
1facf9fc 5996+
5997+struct au_do_lookup_args {
5998+ unsigned int flags;
5999+ mode_t type;
6000+ struct nameidata *nd;
6001+};
6002+
6003+/*
6004+ * returns positive/negative dentry, NULL or an error.
6005+ * NULL means whiteout-ed or not-found.
6006+ */
6007+static struct dentry*
6008+au_do_lookup(struct dentry *h_parent, struct dentry *dentry,
6009+ aufs_bindex_t bindex, struct qstr *wh_name,
6010+ struct au_do_lookup_args *args)
6011+{
6012+ struct dentry *h_dentry;
6013+ struct inode *h_inode, *inode;
1facf9fc 6014+ struct au_branch *br;
6015+ int wh_found, opq;
6016+ unsigned char wh_able;
6017+ const unsigned char allow_neg = !!au_ftest_lkup(args->flags, ALLOW_NEG);
6018+
1facf9fc 6019+ wh_found = 0;
6020+ br = au_sbr(dentry->d_sb, bindex);
6021+ wh_able = !!au_br_whable(br->br_perm);
6022+ if (wh_able)
6023+ wh_found = au_wh_test(h_parent, wh_name, br, /*try_sio*/0);
6024+ h_dentry = ERR_PTR(wh_found);
6025+ if (!wh_found)
6026+ goto real_lookup;
6027+ if (unlikely(wh_found < 0))
6028+ goto out;
6029+
6030+ /* We found a whiteout */
6031+ /* au_set_dbend(dentry, bindex); */
6032+ au_set_dbwh(dentry, bindex);
6033+ if (!allow_neg)
6034+ return NULL; /* success */
6035+
4f0767ce 6036+real_lookup:
4a4d8108 6037+ h_dentry = au_lkup_one(&dentry->d_name, h_parent, br, args->nd);
1facf9fc 6038+ if (IS_ERR(h_dentry))
6039+ goto out;
6040+
6041+ h_inode = h_dentry->d_inode;
6042+ if (!h_inode) {
6043+ if (!allow_neg)
6044+ goto out_neg;
6045+ } else if (wh_found
6046+ || (args->type && args->type != (h_inode->i_mode & S_IFMT)))
6047+ goto out_neg;
6048+
6049+ if (au_dbend(dentry) <= bindex)
6050+ au_set_dbend(dentry, bindex);
6051+ if (au_dbstart(dentry) < 0 || bindex < au_dbstart(dentry))
6052+ au_set_dbstart(dentry, bindex);
6053+ au_set_h_dptr(dentry, bindex, h_dentry);
6054+
6055+ inode = dentry->d_inode;
6056+ if (!h_inode || !S_ISDIR(h_inode->i_mode) || !wh_able
6057+ || (inode && !S_ISDIR(inode->i_mode)))
6058+ goto out; /* success */
6059+
6060+ mutex_lock_nested(&h_inode->i_mutex, AuLsc_I_CHILD);
6061+ opq = au_diropq_test(h_dentry, br);
6062+ mutex_unlock(&h_inode->i_mutex);
6063+ if (opq > 0)
6064+ au_set_dbdiropq(dentry, bindex);
6065+ else if (unlikely(opq < 0)) {
6066+ au_set_h_dptr(dentry, bindex, NULL);
6067+ h_dentry = ERR_PTR(opq);
6068+ }
6069+ goto out;
6070+
4f0767ce 6071+out_neg:
1facf9fc 6072+ dput(h_dentry);
6073+ h_dentry = NULL;
4f0767ce 6074+out:
1facf9fc 6075+ return h_dentry;
6076+}
6077+
dece6358
AM
6078+static int au_test_shwh(struct super_block *sb, const struct qstr *name)
6079+{
6080+ if (unlikely(!au_opt_test(au_mntflags(sb), SHWH)
6081+ && !strncmp(name->name, AUFS_WH_PFX, AUFS_WH_PFX_LEN)))
6082+ return -EPERM;
6083+ return 0;
6084+}
6085+
1facf9fc 6086+/*
6087+ * returns the number of lower positive dentries,
6088+ * otherwise an error.
6089+ * can be called at unlinking with @type is zero.
6090+ */
6091+int au_lkup_dentry(struct dentry *dentry, aufs_bindex_t bstart, mode_t type,
6092+ struct nameidata *nd)
6093+{
6094+ int npositive, err;
6095+ aufs_bindex_t bindex, btail, bdiropq;
6096+ unsigned char isdir;
6097+ struct qstr whname;
6098+ struct au_do_lookup_args args = {
6099+ .flags = 0,
6100+ .type = type,
6101+ .nd = nd
6102+ };
6103+ const struct qstr *name = &dentry->d_name;
6104+ struct dentry *parent;
6105+ struct inode *inode;
6106+
dece6358
AM
6107+ err = au_test_shwh(dentry->d_sb, name);
6108+ if (unlikely(err))
1facf9fc 6109+ goto out;
6110+
6111+ err = au_wh_name_alloc(&whname, name);
6112+ if (unlikely(err))
6113+ goto out;
6114+
6115+ inode = dentry->d_inode;
6116+ isdir = !!(inode && S_ISDIR(inode->i_mode));
6117+ if (!type)
6118+ au_fset_lkup(args.flags, ALLOW_NEG);
6119+
6120+ npositive = 0;
4a4d8108 6121+ parent = dget_parent(dentry);
1facf9fc 6122+ btail = au_dbtaildir(parent);
6123+ for (bindex = bstart; bindex <= btail; bindex++) {
6124+ struct dentry *h_parent, *h_dentry;
6125+ struct inode *h_inode, *h_dir;
6126+
6127+ h_dentry = au_h_dptr(dentry, bindex);
6128+ if (h_dentry) {
6129+ if (h_dentry->d_inode)
6130+ npositive++;
6131+ if (type != S_IFDIR)
6132+ break;
6133+ continue;
6134+ }
6135+ h_parent = au_h_dptr(parent, bindex);
6136+ if (!h_parent)
6137+ continue;
6138+ h_dir = h_parent->d_inode;
6139+ if (!h_dir || !S_ISDIR(h_dir->i_mode))
6140+ continue;
6141+
6142+ mutex_lock_nested(&h_dir->i_mutex, AuLsc_I_PARENT);
6143+ h_dentry = au_do_lookup(h_parent, dentry, bindex, &whname,
6144+ &args);
6145+ mutex_unlock(&h_dir->i_mutex);
6146+ err = PTR_ERR(h_dentry);
6147+ if (IS_ERR(h_dentry))
4a4d8108 6148+ goto out_parent;
1facf9fc 6149+ au_fclr_lkup(args.flags, ALLOW_NEG);
6150+
6151+ if (au_dbwh(dentry) >= 0)
6152+ break;
6153+ if (!h_dentry)
6154+ continue;
6155+ h_inode = h_dentry->d_inode;
6156+ if (!h_inode)
6157+ continue;
6158+ npositive++;
6159+ if (!args.type)
6160+ args.type = h_inode->i_mode & S_IFMT;
6161+ if (args.type != S_IFDIR)
6162+ break;
6163+ else if (isdir) {
6164+ /* the type of lower may be different */
6165+ bdiropq = au_dbdiropq(dentry);
6166+ if (bdiropq >= 0 && bdiropq <= bindex)
6167+ break;
6168+ }
6169+ }
6170+
6171+ if (npositive) {
6172+ AuLabel(positive);
6173+ au_update_dbstart(dentry);
6174+ }
6175+ err = npositive;
6176+ if (unlikely(!au_opt_test(au_mntflags(dentry->d_sb), UDBA_NONE)
027c5e7a 6177+ && au_dbstart(dentry) < 0)) {
1facf9fc 6178+ err = -EIO;
027c5e7a
AM
6179+ AuIOErr("both of real entry and whiteout found, %.*s, err %d\n",
6180+ AuDLNPair(dentry), err);
6181+ }
1facf9fc 6182+
4f0767ce 6183+out_parent:
4a4d8108 6184+ dput(parent);
1facf9fc 6185+ kfree(whname.name);
4f0767ce 6186+out:
1facf9fc 6187+ return err;
6188+}
6189+
6190+struct dentry *au_sio_lkup_one(struct qstr *name, struct dentry *parent,
6191+ struct au_branch *br)
6192+{
6193+ struct dentry *dentry;
6194+ int wkq_err;
6195+
6196+ if (!au_test_h_perm_sio(parent->d_inode, MAY_EXEC))
6197+ dentry = au_lkup_one(name, parent, br, /*nd*/NULL);
6198+ else {
6199+ struct au_lkup_one_args args = {
6200+ .errp = &dentry,
6201+ .name = name,
6202+ .h_parent = parent,
6203+ .br = br,
6204+ .nd = NULL
6205+ };
6206+
6207+ wkq_err = au_wkq_wait(au_call_lkup_one, &args);
6208+ if (unlikely(wkq_err))
6209+ dentry = ERR_PTR(wkq_err);
6210+ }
6211+
6212+ return dentry;
6213+}
6214+
6215+/*
6216+ * lookup @dentry on @bindex which should be negative.
6217+ */
6218+int au_lkup_neg(struct dentry *dentry, aufs_bindex_t bindex)
6219+{
6220+ int err;
6221+ struct dentry *parent, *h_parent, *h_dentry;
1facf9fc 6222+
1facf9fc 6223+ parent = dget_parent(dentry);
6224+ h_parent = au_h_dptr(parent, bindex);
4a4d8108 6225+ h_dentry = au_sio_lkup_one(&dentry->d_name, h_parent,
1facf9fc 6226+ au_sbr(dentry->d_sb, bindex));
6227+ err = PTR_ERR(h_dentry);
6228+ if (IS_ERR(h_dentry))
6229+ goto out;
6230+ if (unlikely(h_dentry->d_inode)) {
6231+ err = -EIO;
027c5e7a
AM
6232+ AuIOErr("%.*s should be negative on b%d.\n",
6233+ AuDLNPair(h_dentry), bindex);
1facf9fc 6234+ dput(h_dentry);
6235+ goto out;
6236+ }
6237+
4a4d8108 6238+ err = 0;
1facf9fc 6239+ if (bindex < au_dbstart(dentry))
6240+ au_set_dbstart(dentry, bindex);
6241+ if (au_dbend(dentry) < bindex)
6242+ au_set_dbend(dentry, bindex);
6243+ au_set_h_dptr(dentry, bindex, h_dentry);
1facf9fc 6244+
4f0767ce 6245+out:
1facf9fc 6246+ dput(parent);
6247+ return err;
6248+}
6249+
6250+/* ---------------------------------------------------------------------- */
6251+
6252+/* subset of struct inode */
6253+struct au_iattr {
6254+ unsigned long i_ino;
6255+ /* unsigned int i_nlink; */
6256+ uid_t i_uid;
6257+ gid_t i_gid;
6258+ u64 i_version;
6259+/*
6260+ loff_t i_size;
6261+ blkcnt_t i_blocks;
6262+*/
6263+ umode_t i_mode;
6264+};
6265+
6266+static void au_iattr_save(struct au_iattr *ia, struct inode *h_inode)
6267+{
6268+ ia->i_ino = h_inode->i_ino;
6269+ /* ia->i_nlink = h_inode->i_nlink; */
6270+ ia->i_uid = h_inode->i_uid;
6271+ ia->i_gid = h_inode->i_gid;
6272+ ia->i_version = h_inode->i_version;
6273+/*
6274+ ia->i_size = h_inode->i_size;
6275+ ia->i_blocks = h_inode->i_blocks;
6276+*/
6277+ ia->i_mode = (h_inode->i_mode & S_IFMT);
6278+}
6279+
6280+static int au_iattr_test(struct au_iattr *ia, struct inode *h_inode)
6281+{
6282+ return ia->i_ino != h_inode->i_ino
6283+ /* || ia->i_nlink != h_inode->i_nlink */
6284+ || ia->i_uid != h_inode->i_uid
6285+ || ia->i_gid != h_inode->i_gid
6286+ || ia->i_version != h_inode->i_version
6287+/*
6288+ || ia->i_size != h_inode->i_size
6289+ || ia->i_blocks != h_inode->i_blocks
6290+*/
6291+ || ia->i_mode != (h_inode->i_mode & S_IFMT);
6292+}
6293+
6294+static int au_h_verify_dentry(struct dentry *h_dentry, struct dentry *h_parent,
6295+ struct au_branch *br)
6296+{
6297+ int err;
6298+ struct au_iattr ia;
6299+ struct inode *h_inode;
6300+ struct dentry *h_d;
6301+ struct super_block *h_sb;
6302+
6303+ err = 0;
6304+ memset(&ia, -1, sizeof(ia));
6305+ h_sb = h_dentry->d_sb;
6306+ h_inode = h_dentry->d_inode;
6307+ if (h_inode)
6308+ au_iattr_save(&ia, h_inode);
6309+ else if (au_test_nfs(h_sb) || au_test_fuse(h_sb))
6310+ /* nfs d_revalidate may return 0 for negative dentry */
6311+ /* fuse d_revalidate always return 0 for negative dentry */
6312+ goto out;
6313+
6314+ /* main purpose is namei.c:cached_lookup() and d_revalidate */
6315+ h_d = au_lkup_one(&h_dentry->d_name, h_parent, br, /*nd*/NULL);
6316+ err = PTR_ERR(h_d);
6317+ if (IS_ERR(h_d))
6318+ goto out;
6319+
6320+ err = 0;
6321+ if (unlikely(h_d != h_dentry
6322+ || h_d->d_inode != h_inode
6323+ || (h_inode && au_iattr_test(&ia, h_inode))))
6324+ err = au_busy_or_stale();
6325+ dput(h_d);
6326+
4f0767ce 6327+out:
1facf9fc 6328+ AuTraceErr(err);
6329+ return err;
6330+}
6331+
6332+int au_h_verify(struct dentry *h_dentry, unsigned int udba, struct inode *h_dir,
6333+ struct dentry *h_parent, struct au_branch *br)
6334+{
6335+ int err;
6336+
6337+ err = 0;
027c5e7a
AM
6338+ if (udba == AuOpt_UDBA_REVAL
6339+ && !au_test_fs_remote(h_dentry->d_sb)) {
1facf9fc 6340+ IMustLock(h_dir);
6341+ err = (h_dentry->d_parent->d_inode != h_dir);
027c5e7a 6342+ } else if (udba != AuOpt_UDBA_NONE)
1facf9fc 6343+ err = au_h_verify_dentry(h_dentry, h_parent, br);
6344+
6345+ return err;
6346+}
6347+
6348+/* ---------------------------------------------------------------------- */
6349+
027c5e7a 6350+static int au_do_refresh_hdentry(struct dentry *dentry, struct dentry *parent)
1facf9fc 6351+{
027c5e7a 6352+ int err;
1facf9fc 6353+ aufs_bindex_t new_bindex, bindex, bend, bwh, bdiropq;
027c5e7a
AM
6354+ struct au_hdentry tmp, *p, *q;
6355+ struct au_dinfo *dinfo;
6356+ struct super_block *sb;
1facf9fc 6357+
027c5e7a 6358+ DiMustWriteLock(dentry);
1308ab2a 6359+
027c5e7a
AM
6360+ sb = dentry->d_sb;
6361+ dinfo = au_di(dentry);
1facf9fc 6362+ bend = dinfo->di_bend;
6363+ bwh = dinfo->di_bwh;
6364+ bdiropq = dinfo->di_bdiropq;
027c5e7a 6365+ p = dinfo->di_hdentry + dinfo->di_bstart;
1facf9fc 6366+ for (bindex = dinfo->di_bstart; bindex <= bend; bindex++, p++) {
027c5e7a 6367+ if (!p->hd_dentry)
1facf9fc 6368+ continue;
6369+
027c5e7a
AM
6370+ new_bindex = au_br_index(sb, p->hd_id);
6371+ if (new_bindex == bindex)
1facf9fc 6372+ continue;
1facf9fc 6373+
1facf9fc 6374+ if (dinfo->di_bwh == bindex)
6375+ bwh = new_bindex;
6376+ if (dinfo->di_bdiropq == bindex)
6377+ bdiropq = new_bindex;
6378+ if (new_bindex < 0) {
6379+ au_hdput(p);
6380+ p->hd_dentry = NULL;
6381+ continue;
6382+ }
6383+
6384+ /* swap two lower dentries, and loop again */
6385+ q = dinfo->di_hdentry + new_bindex;
6386+ tmp = *q;
6387+ *q = *p;
6388+ *p = tmp;
6389+ if (tmp.hd_dentry) {
6390+ bindex--;
6391+ p--;
6392+ }
6393+ }
6394+
1facf9fc 6395+ dinfo->di_bwh = -1;
6396+ if (bwh >= 0 && bwh <= au_sbend(sb) && au_sbr_whable(sb, bwh))
6397+ dinfo->di_bwh = bwh;
6398+
6399+ dinfo->di_bdiropq = -1;
6400+ if (bdiropq >= 0
6401+ && bdiropq <= au_sbend(sb)
6402+ && au_sbr_whable(sb, bdiropq))
6403+ dinfo->di_bdiropq = bdiropq;
6404+
027c5e7a
AM
6405+ err = -EIO;
6406+ dinfo->di_bstart = -1;
6407+ dinfo->di_bend = -1;
1facf9fc 6408+ bend = au_dbend(parent);
6409+ p = dinfo->di_hdentry;
6410+ for (bindex = 0; bindex <= bend; bindex++, p++)
6411+ if (p->hd_dentry) {
6412+ dinfo->di_bstart = bindex;
6413+ break;
6414+ }
6415+
027c5e7a
AM
6416+ if (dinfo->di_bstart >= 0) {
6417+ p = dinfo->di_hdentry + bend;
6418+ for (bindex = bend; bindex >= 0; bindex--, p--)
6419+ if (p->hd_dentry) {
6420+ dinfo->di_bend = bindex;
6421+ err = 0;
6422+ break;
6423+ }
6424+ }
6425+
6426+ return err;
1facf9fc 6427+}
6428+
027c5e7a 6429+static void au_do_hide(struct dentry *dentry)
1facf9fc 6430+{
027c5e7a 6431+ struct inode *inode;
1facf9fc 6432+
027c5e7a
AM
6433+ inode = dentry->d_inode;
6434+ if (inode) {
6435+ if (!S_ISDIR(inode->i_mode)) {
6436+ if (inode->i_nlink && !d_unhashed(dentry))
6437+ drop_nlink(inode);
6438+ } else {
6439+ clear_nlink(inode);
6440+ /* stop next lookup */
6441+ inode->i_flags |= S_DEAD;
6442+ }
6443+ smp_mb(); /* necessary? */
6444+ }
6445+ d_drop(dentry);
6446+}
1308ab2a 6447+
027c5e7a
AM
6448+static int au_hide_children(struct dentry *parent)
6449+{
6450+ int err, i, j, ndentry;
6451+ struct au_dcsub_pages dpages;
6452+ struct au_dpage *dpage;
6453+ struct dentry *dentry;
1facf9fc 6454+
027c5e7a 6455+ err = au_dpages_init(&dpages, GFP_NOFS);
1facf9fc 6456+ if (unlikely(err))
6457+ goto out;
027c5e7a
AM
6458+ err = au_dcsub_pages(&dpages, parent, NULL, NULL);
6459+ if (unlikely(err))
6460+ goto out_dpages;
1facf9fc 6461+
027c5e7a
AM
6462+ /* in reverse order */
6463+ for (i = dpages.ndpage - 1; i >= 0; i--) {
6464+ dpage = dpages.dpages + i;
6465+ ndentry = dpage->ndentry;
6466+ for (j = ndentry - 1; j >= 0; j--) {
6467+ dentry = dpage->dentries[j];
6468+ if (dentry != parent)
6469+ au_do_hide(dentry);
6470+ }
6471+ }
1facf9fc 6472+
027c5e7a
AM
6473+out_dpages:
6474+ au_dpages_free(&dpages);
4f0767ce 6475+out:
027c5e7a 6476+ return err;
1facf9fc 6477+}
6478+
027c5e7a 6479+static void au_hide(struct dentry *dentry)
1facf9fc 6480+{
027c5e7a
AM
6481+ int err;
6482+ struct inode *inode;
1facf9fc 6483+
027c5e7a
AM
6484+ AuDbgDentry(dentry);
6485+ inode = dentry->d_inode;
6486+ if (inode && S_ISDIR(inode->i_mode)) {
6487+ /* shrink_dcache_parent(dentry); */
6488+ err = au_hide_children(dentry);
6489+ if (unlikely(err))
6490+ AuIOErr("%.*s, failed hiding children, ignored %d\n",
6491+ AuDLNPair(dentry), err);
6492+ }
6493+ au_do_hide(dentry);
6494+}
1facf9fc 6495+
027c5e7a
AM
6496+/*
6497+ * By adding a dirty branch, a cached dentry may be affected in various ways.
6498+ *
6499+ * a dirty branch is added
6500+ * - on the top of layers
6501+ * - in the middle of layers
6502+ * - to the bottom of layers
6503+ *
6504+ * on the added branch there exists
6505+ * - a whiteout
6506+ * - a diropq
6507+ * - a same named entry
6508+ * + exist
6509+ * * negative --> positive
6510+ * * positive --> positive
6511+ * - type is unchanged
6512+ * - type is changed
6513+ * + doesn't exist
6514+ * * negative --> negative
6515+ * * positive --> negative (rejected by au_br_del() for non-dir case)
6516+ * - none
6517+ */
6518+static int au_refresh_by_dinfo(struct dentry *dentry, struct au_dinfo *dinfo,
6519+ struct au_dinfo *tmp)
6520+{
6521+ int err;
6522+ aufs_bindex_t bindex, bend;
6523+ struct {
6524+ struct dentry *dentry;
6525+ struct inode *inode;
6526+ mode_t mode;
6527+ } orig_h, tmp_h;
6528+ struct au_hdentry *hd;
6529+ struct inode *inode, *h_inode;
6530+ struct dentry *h_dentry;
6531+
6532+ err = 0;
6533+ AuDebugOn(dinfo->di_bstart < 0);
6534+ orig_h.dentry = dinfo->di_hdentry[dinfo->di_bstart].hd_dentry;
6535+ orig_h.inode = orig_h.dentry->d_inode;
6536+ orig_h.mode = 0;
6537+ if (orig_h.inode)
6538+ orig_h.mode = orig_h.inode->i_mode & S_IFMT;
6539+ memset(&tmp_h, 0, sizeof(tmp_h));
6540+ if (tmp->di_bstart >= 0) {
6541+ tmp_h.dentry = tmp->di_hdentry[tmp->di_bstart].hd_dentry;
6542+ tmp_h.inode = tmp_h.dentry->d_inode;
6543+ if (tmp_h.inode)
6544+ tmp_h.mode = tmp_h.inode->i_mode & S_IFMT;
6545+ }
6546+
6547+ inode = dentry->d_inode;
6548+ if (!orig_h.inode) {
6549+ AuDbg("nagative originally\n");
6550+ if (inode) {
6551+ au_hide(dentry);
6552+ goto out;
6553+ }
6554+ AuDebugOn(inode);
6555+ AuDebugOn(dinfo->di_bstart != dinfo->di_bend);
6556+ AuDebugOn(dinfo->di_bdiropq != -1);
6557+
6558+ if (!tmp_h.inode) {
6559+ AuDbg("negative --> negative\n");
6560+ /* should have only one negative lower */
6561+ if (tmp->di_bstart >= 0
6562+ && tmp->di_bstart < dinfo->di_bstart) {
6563+ AuDebugOn(tmp->di_bstart != tmp->di_bend);
6564+ AuDebugOn(dinfo->di_bstart != dinfo->di_bend);
6565+ au_set_h_dptr(dentry, dinfo->di_bstart, NULL);
6566+ au_di_cp(dinfo, tmp);
6567+ hd = tmp->di_hdentry + tmp->di_bstart;
6568+ au_set_h_dptr(dentry, tmp->di_bstart,
6569+ dget(hd->hd_dentry));
6570+ }
6571+ au_dbg_verify_dinode(dentry);
6572+ } else {
6573+ AuDbg("negative --> positive\n");
6574+ /*
6575+ * similar to the behaviour of creating with bypassing
6576+ * aufs.
6577+ * unhash it in order to force an error in the
6578+ * succeeding create operation.
6579+ * we should not set S_DEAD here.
6580+ */
6581+ d_drop(dentry);
6582+ /* au_di_swap(tmp, dinfo); */
6583+ au_dbg_verify_dinode(dentry);
6584+ }
6585+ } else {
6586+ AuDbg("positive originally\n");
6587+ /* inode may be NULL */
6588+ AuDebugOn(inode && (inode->i_mode & S_IFMT) != orig_h.mode);
6589+ if (!tmp_h.inode) {
6590+ AuDbg("positive --> negative\n");
6591+ /* or bypassing aufs */
6592+ au_hide(dentry);
6593+ if (tmp->di_bwh >= 0 && tmp->di_bwh <= dinfo->di_bstart)
6594+ dinfo->di_bwh = tmp->di_bwh;
6595+ if (inode)
6596+ err = au_refresh_hinode_self(inode);
6597+ au_dbg_verify_dinode(dentry);
6598+ } else if (orig_h.mode == tmp_h.mode) {
6599+ AuDbg("positive --> positive, same type\n");
6600+ if (!S_ISDIR(orig_h.mode)
6601+ && dinfo->di_bstart > tmp->di_bstart) {
6602+ /*
6603+ * similar to the behaviour of removing and
6604+ * creating.
6605+ */
6606+ au_hide(dentry);
6607+ if (inode)
6608+ err = au_refresh_hinode_self(inode);
6609+ au_dbg_verify_dinode(dentry);
6610+ } else {
6611+ /* fill empty slots */
6612+ if (dinfo->di_bstart > tmp->di_bstart)
6613+ dinfo->di_bstart = tmp->di_bstart;
6614+ if (dinfo->di_bend < tmp->di_bend)
6615+ dinfo->di_bend = tmp->di_bend;
6616+ dinfo->di_bwh = tmp->di_bwh;
6617+ dinfo->di_bdiropq = tmp->di_bdiropq;
6618+ hd = tmp->di_hdentry;
6619+ bend = dinfo->di_bend;
6620+ for (bindex = tmp->di_bstart; bindex <= bend;
6621+ bindex++) {
6622+ if (au_h_dptr(dentry, bindex))
6623+ continue;
6624+ h_dentry = hd[bindex].hd_dentry;
6625+ if (!h_dentry)
6626+ continue;
6627+ h_inode = h_dentry->d_inode;
6628+ AuDebugOn(!h_inode);
6629+ AuDebugOn(orig_h.mode
6630+ != (h_inode->i_mode
6631+ & S_IFMT));
6632+ au_set_h_dptr(dentry, bindex,
6633+ dget(h_dentry));
6634+ }
6635+ err = au_refresh_hinode(inode, dentry);
6636+ au_dbg_verify_dinode(dentry);
6637+ }
6638+ } else {
6639+ AuDbg("positive --> positive, different type\n");
6640+ /* similar to the behaviour of removing and creating */
6641+ au_hide(dentry);
6642+ if (inode)
6643+ err = au_refresh_hinode_self(inode);
6644+ au_dbg_verify_dinode(dentry);
6645+ }
6646+ }
6647+
6648+out:
6649+ return err;
6650+}
6651+
6652+int au_refresh_dentry(struct dentry *dentry, struct dentry *parent)
6653+{
6654+ int err, ebrange;
6655+ unsigned int sigen;
6656+ struct au_dinfo *dinfo, *tmp;
6657+ struct super_block *sb;
6658+ struct inode *inode;
6659+
6660+ DiMustWriteLock(dentry);
6661+ AuDebugOn(IS_ROOT(dentry));
6662+ AuDebugOn(!parent->d_inode);
6663+
6664+ sb = dentry->d_sb;
6665+ inode = dentry->d_inode;
6666+ sigen = au_sigen(sb);
6667+ err = au_digen_test(parent, sigen);
6668+ if (unlikely(err))
6669+ goto out;
6670+
6671+ dinfo = au_di(dentry);
6672+ err = au_di_realloc(dinfo, au_sbend(sb) + 1);
6673+ if (unlikely(err))
6674+ goto out;
6675+ ebrange = au_dbrange_test(dentry);
6676+ if (!ebrange)
6677+ ebrange = au_do_refresh_hdentry(dentry, parent);
6678+
6679+ if (d_unhashed(dentry) || ebrange) {
6680+ AuDebugOn(au_dbstart(dentry) < 0 && au_dbend(dentry) >= 0);
6681+ if (inode)
6682+ err = au_refresh_hinode_self(inode);
6683+ au_dbg_verify_dinode(dentry);
6684+ if (!err)
6685+ goto out_dgen; /* success */
6686+ goto out;
6687+ }
6688+
6689+ /* temporary dinfo */
6690+ AuDbgDentry(dentry);
6691+ err = -ENOMEM;
6692+ tmp = au_di_alloc(sb, AuLsc_DI_TMP);
6693+ if (unlikely(!tmp))
6694+ goto out;
6695+ au_di_swap(tmp, dinfo);
6696+ /* returns the number of positive dentries */
6697+ /*
6698+ * if current working dir is removed, it returns an error.
6699+ * but the dentry is legal.
6700+ */
6701+ err = au_lkup_dentry(dentry, /*bstart*/0, /*type*/0, /*nd*/NULL);
6702+ AuDbgDentry(dentry);
6703+ au_di_swap(tmp, dinfo);
6704+ if (err == -ENOENT)
6705+ err = 0;
6706+ if (err >= 0) {
6707+ /* compare/refresh by dinfo */
6708+ AuDbgDentry(dentry);
6709+ err = au_refresh_by_dinfo(dentry, dinfo, tmp);
6710+ au_dbg_verify_dinode(dentry);
6711+ AuTraceErr(err);
6712+ }
6713+ au_rw_write_unlock(&tmp->di_rwsem);
6714+ au_di_free(tmp);
6715+ if (unlikely(err))
6716+ goto out;
6717+
6718+out_dgen:
6719+ au_update_digen(dentry);
6720+out:
6721+ if (unlikely(err && !(dentry->d_flags & DCACHE_NFSFS_RENAMED))) {
6722+ AuIOErr("failed refreshing %.*s, %d\n",
6723+ AuDLNPair(dentry), err);
6724+ AuDbgDentry(dentry);
6725+ }
6726+ AuTraceErr(err);
6727+ return err;
6728+}
6729+
6730+static noinline_for_stack
6731+int au_do_h_d_reval(struct dentry *h_dentry, struct nameidata *nd,
6732+ struct dentry *dentry, aufs_bindex_t bindex)
6733+{
6734+ int err, valid;
6735+ int (*reval)(struct dentry *, struct nameidata *);
6736+
6737+ err = 0;
6738+ if (!(h_dentry->d_flags & DCACHE_OP_REVALIDATE))
6739+ goto out;
6740+ reval = h_dentry->d_op->d_revalidate;
6741+
6742+ AuDbg("b%d\n", bindex);
6743+ if (au_test_fs_null_nd(h_dentry->d_sb))
6744+ /* it may return tri-state */
6745+ valid = reval(h_dentry, NULL);
6746+ else {
6747+ struct nameidata h_nd;
6748+ int locked;
1facf9fc 6749+ struct dentry *parent;
6750+
6751+ au_h_nd(&h_nd, nd);
6752+ parent = nd->path.dentry;
6753+ locked = (nd && nd->path.dentry != dentry);
6754+ if (locked)
6755+ di_read_lock_parent(parent, AuLock_IR);
6756+ BUG_ON(bindex > au_dbend(parent));
6757+ h_nd.path.dentry = au_h_dptr(parent, bindex);
6758+ BUG_ON(!h_nd.path.dentry);
6759+ h_nd.path.mnt = au_sbr(parent->d_sb, bindex)->br_mnt;
6760+ path_get(&h_nd.path);
6761+ valid = reval(h_dentry, &h_nd);
6762+ path_put(&h_nd.path);
6763+ if (locked)
6764+ di_read_unlock(parent, AuLock_IR);
6765+ }
6766+
6767+ if (unlikely(valid < 0))
6768+ err = valid;
6769+ else if (!valid)
6770+ err = -EINVAL;
6771+
4f0767ce 6772+out:
1facf9fc 6773+ AuTraceErr(err);
6774+ return err;
6775+}
6776+
6777+/* todo: remove this */
6778+static int h_d_revalidate(struct dentry *dentry, struct inode *inode,
6779+ struct nameidata *nd, int do_udba)
6780+{
6781+ int err;
6782+ umode_t mode, h_mode;
6783+ aufs_bindex_t bindex, btail, bstart, ibs, ibe;
6784+ unsigned char plus, unhashed, is_root, h_plus;
4a4d8108 6785+ struct inode *h_inode, *h_cached_inode;
1facf9fc 6786+ struct dentry *h_dentry;
6787+ struct qstr *name, *h_name;
6788+
6789+ err = 0;
6790+ plus = 0;
6791+ mode = 0;
1facf9fc 6792+ ibs = -1;
6793+ ibe = -1;
6794+ unhashed = !!d_unhashed(dentry);
6795+ is_root = !!IS_ROOT(dentry);
6796+ name = &dentry->d_name;
6797+
6798+ /*
7f207e10
AM
6799+ * Theoretically, REVAL test should be unnecessary in case of
6800+ * {FS,I}NOTIFY.
6801+ * But {fs,i}notify doesn't fire some necessary events,
1facf9fc 6802+ * IN_ATTRIB for atime/nlink/pageio
6803+ * IN_DELETE for NFS dentry
6804+ * Let's do REVAL test too.
6805+ */
6806+ if (do_udba && inode) {
6807+ mode = (inode->i_mode & S_IFMT);
6808+ plus = (inode->i_nlink > 0);
1facf9fc 6809+ ibs = au_ibstart(inode);
6810+ ibe = au_ibend(inode);
6811+ }
6812+
6813+ bstart = au_dbstart(dentry);
6814+ btail = bstart;
6815+ if (inode && S_ISDIR(inode->i_mode))
6816+ btail = au_dbtaildir(dentry);
6817+ for (bindex = bstart; bindex <= btail; bindex++) {
6818+ h_dentry = au_h_dptr(dentry, bindex);
6819+ if (!h_dentry)
6820+ continue;
6821+
6822+ AuDbg("b%d, %.*s\n", bindex, AuDLNPair(h_dentry));
027c5e7a 6823+ spin_lock(&h_dentry->d_lock);
1facf9fc 6824+ h_name = &h_dentry->d_name;
6825+ if (unlikely(do_udba
6826+ && !is_root
6827+ && (unhashed != !!d_unhashed(h_dentry)
6828+ || name->len != h_name->len
6829+ || memcmp(name->name, h_name->name, name->len))
6830+ )) {
6831+ AuDbg("unhash 0x%x 0x%x, %.*s %.*s\n",
6832+ unhashed, d_unhashed(h_dentry),
6833+ AuDLNPair(dentry), AuDLNPair(h_dentry));
027c5e7a 6834+ spin_unlock(&h_dentry->d_lock);
1facf9fc 6835+ goto err;
6836+ }
027c5e7a 6837+ spin_unlock(&h_dentry->d_lock);
1facf9fc 6838+
6839+ err = au_do_h_d_reval(h_dentry, nd, dentry, bindex);
6840+ if (unlikely(err))
6841+ /* do not goto err, to keep the errno */
6842+ break;
6843+
6844+ /* todo: plink too? */
6845+ if (!do_udba)
6846+ continue;
6847+
6848+ /* UDBA tests */
6849+ h_inode = h_dentry->d_inode;
6850+ if (unlikely(!!inode != !!h_inode))
6851+ goto err;
6852+
6853+ h_plus = plus;
6854+ h_mode = mode;
6855+ h_cached_inode = h_inode;
6856+ if (h_inode) {
6857+ h_mode = (h_inode->i_mode & S_IFMT);
6858+ h_plus = (h_inode->i_nlink > 0);
6859+ }
6860+ if (inode && ibs <= bindex && bindex <= ibe)
6861+ h_cached_inode = au_h_iptr(inode, bindex);
6862+
6863+ if (unlikely(plus != h_plus
6864+ || mode != h_mode
6865+ || h_cached_inode != h_inode))
6866+ goto err;
6867+ continue;
6868+
6869+ err:
6870+ err = -EINVAL;
6871+ break;
6872+ }
6873+
6874+ return err;
6875+}
6876+
027c5e7a 6877+/* todo: consolidate with do_refresh() and au_reval_for_attr() */
1facf9fc 6878+static int simple_reval_dpath(struct dentry *dentry, unsigned int sigen)
6879+{
6880+ int err;
6881+ struct dentry *parent;
1facf9fc 6882+
027c5e7a 6883+ if (!au_digen_test(dentry, sigen))
1facf9fc 6884+ return 0;
6885+
6886+ parent = dget_parent(dentry);
6887+ di_read_lock_parent(parent, AuLock_IR);
027c5e7a 6888+ AuDebugOn(au_digen_test(parent, sigen));
1facf9fc 6889+ au_dbg_verify_gen(parent, sigen);
027c5e7a 6890+ err = au_refresh_dentry(dentry, parent);
1facf9fc 6891+ di_read_unlock(parent, AuLock_IR);
6892+ dput(parent);
027c5e7a 6893+ AuTraceErr(err);
1facf9fc 6894+ return err;
6895+}
6896+
6897+int au_reval_dpath(struct dentry *dentry, unsigned int sigen)
6898+{
6899+ int err;
6900+ struct dentry *d, *parent;
6901+ struct inode *inode;
6902+
027c5e7a 6903+ if (!au_ftest_si(au_sbi(dentry->d_sb), FAILED_REFRESH_DIR))
1facf9fc 6904+ return simple_reval_dpath(dentry, sigen);
6905+
6906+ /* slow loop, keep it simple and stupid */
6907+ /* cf: au_cpup_dirs() */
6908+ err = 0;
6909+ parent = NULL;
027c5e7a 6910+ while (au_digen_test(dentry, sigen)) {
1facf9fc 6911+ d = dentry;
6912+ while (1) {
6913+ dput(parent);
6914+ parent = dget_parent(d);
027c5e7a 6915+ if (!au_digen_test(parent, sigen))
1facf9fc 6916+ break;
6917+ d = parent;
6918+ }
6919+
6920+ inode = d->d_inode;
6921+ if (d != dentry)
027c5e7a 6922+ di_write_lock_child2(d);
1facf9fc 6923+
6924+ /* someone might update our dentry while we were sleeping */
027c5e7a
AM
6925+ if (au_digen_test(d, sigen)) {
6926+ /*
6927+ * todo: consolidate with simple_reval_dpath(),
6928+ * do_refresh() and au_reval_for_attr().
6929+ */
1facf9fc 6930+ di_read_lock_parent(parent, AuLock_IR);
027c5e7a 6931+ err = au_refresh_dentry(d, parent);
1facf9fc 6932+ di_read_unlock(parent, AuLock_IR);
6933+ }
6934+
6935+ if (d != dentry)
6936+ di_write_unlock(d);
6937+ dput(parent);
6938+ if (unlikely(err))
6939+ break;
6940+ }
6941+
6942+ return err;
6943+}
6944+
6945+/*
6946+ * if valid returns 1, otherwise 0.
6947+ */
6948+static int aufs_d_revalidate(struct dentry *dentry, struct nameidata *nd)
6949+{
6950+ int valid, err;
6951+ unsigned int sigen;
6952+ unsigned char do_udba;
6953+ struct super_block *sb;
6954+ struct inode *inode;
6955+
027c5e7a
AM
6956+ /* todo: support rcu-walk? */
6957+ if (nd && (nd->flags & LOOKUP_RCU))
6958+ return -ECHILD;
6959+
6960+ valid = 0;
6961+ if (unlikely(!au_di(dentry)))
6962+ goto out;
6963+
6964+ inode = dentry->d_inode;
6965+ if (inode && is_bad_inode(inode))
6966+ goto out;
6967+
e49829fe 6968+ valid = 1;
1facf9fc 6969+ sb = dentry->d_sb;
e49829fe
JR
6970+ /*
6971+ * todo: very ugly
6972+ * i_mutex of parent dir may be held,
6973+ * but we should not return 'invalid' due to busy.
6974+ */
6975+ err = aufs_read_lock(dentry, AuLock_FLUSH | AuLock_DW | AuLock_NOPLM);
6976+ if (unlikely(err)) {
6977+ valid = err;
027c5e7a 6978+ AuTraceErr(err);
e49829fe
JR
6979+ goto out;
6980+ }
027c5e7a
AM
6981+ if (unlikely(au_dbrange_test(dentry))) {
6982+ err = -EINVAL;
6983+ AuTraceErr(err);
6984+ goto out_dgrade;
1facf9fc 6985+ }
027c5e7a
AM
6986+
6987+ sigen = au_sigen(sb);
6988+ if (au_digen_test(dentry, sigen)) {
1facf9fc 6989+ AuDebugOn(IS_ROOT(dentry));
027c5e7a
AM
6990+ err = au_reval_dpath(dentry, sigen);
6991+ if (unlikely(err)) {
6992+ AuTraceErr(err);
1facf9fc 6993+ goto out_dgrade;
027c5e7a 6994+ }
1facf9fc 6995+ }
6996+ di_downgrade_lock(dentry, AuLock_IR);
6997+
1facf9fc 6998+ err = -EINVAL;
027c5e7a
AM
6999+ if (inode && (IS_DEADDIR(inode) || !inode->i_nlink))
7000+ goto out_inval;
7001+
1facf9fc 7002+ do_udba = !au_opt_test(au_mntflags(sb), UDBA_NONE);
7003+ if (do_udba && inode) {
7004+ aufs_bindex_t bstart = au_ibstart(inode);
027c5e7a 7005+ struct inode *h_inode;
1facf9fc 7006+
027c5e7a
AM
7007+ if (bstart >= 0) {
7008+ h_inode = au_h_iptr(inode, bstart);
7009+ if (h_inode && au_test_higen(inode, h_inode))
7010+ goto out_inval;
7011+ }
1facf9fc 7012+ }
7013+
7014+ err = h_d_revalidate(dentry, inode, nd, do_udba);
027c5e7a 7015+ if (unlikely(!err && do_udba && au_dbstart(dentry) < 0)) {
1facf9fc 7016+ err = -EIO;
027c5e7a
AM
7017+ AuDbg("both of real entry and whiteout found, %.*s, err %d\n",
7018+ AuDLNPair(dentry), err);
7019+ }
e49829fe 7020+ goto out_inval;
1facf9fc 7021+
4f0767ce 7022+out_dgrade:
1facf9fc 7023+ di_downgrade_lock(dentry, AuLock_IR);
e49829fe 7024+out_inval:
1facf9fc 7025+ aufs_read_unlock(dentry, AuLock_IR);
7026+ AuTraceErr(err);
7027+ valid = !err;
e49829fe 7028+out:
027c5e7a 7029+ if (!valid) {
e49829fe 7030+ AuDbg("%.*s invalid, %d\n", AuDLNPair(dentry), valid);
027c5e7a
AM
7031+ d_drop(dentry);
7032+ }
1facf9fc 7033+ return valid;
7034+}
7035+
7036+static void aufs_d_release(struct dentry *dentry)
7037+{
027c5e7a 7038+ if (au_di(dentry)) {
4a4d8108
AM
7039+ au_di_fin(dentry);
7040+ au_hn_di_reinit(dentry);
1facf9fc 7041+ }
1facf9fc 7042+}
7043+
4a4d8108 7044+const struct dentry_operations aufs_dop = {
1facf9fc 7045+ .d_revalidate = aufs_d_revalidate,
7046+ .d_release = aufs_d_release
7047+};
7f207e10
AM
7048diff -urN /usr/share/empty/fs/aufs/dentry.h linux/fs/aufs/dentry.h
7049--- /usr/share/empty/fs/aufs/dentry.h 1970-01-01 01:00:00.000000000 +0100
7ce627cf 7050+++ linux/fs/aufs/dentry.h 2012-05-22 09:06:08.867458905 +0200
f6c5ef8b 7051@@ -0,0 +1,237 @@
1facf9fc 7052+/*
f6c5ef8b 7053+ * Copyright (C) 2005-2012 Junjiro R. Okajima
1facf9fc 7054+ *
7055+ * This program, aufs is free software; you can redistribute it and/or modify
7056+ * it under the terms of the GNU General Public License as published by
7057+ * the Free Software Foundation; either version 2 of the License, or
7058+ * (at your option) any later version.
dece6358
AM
7059+ *
7060+ * This program is distributed in the hope that it will be useful,
7061+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
7062+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
7063+ * GNU General Public License for more details.
7064+ *
7065+ * You should have received a copy of the GNU General Public License
7066+ * along with this program; if not, write to the Free Software
7067+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 7068+ */
7069+
7070+/*
7071+ * lookup and dentry operations
7072+ */
7073+
7074+#ifndef __AUFS_DENTRY_H__
7075+#define __AUFS_DENTRY_H__
7076+
7077+#ifdef __KERNEL__
7078+
dece6358 7079+#include <linux/dcache.h>
1facf9fc 7080+#include "rwsem.h"
7081+
1facf9fc 7082+struct au_hdentry {
7083+ struct dentry *hd_dentry;
027c5e7a 7084+ aufs_bindex_t hd_id;
1facf9fc 7085+};
7086+
7087+struct au_dinfo {
7088+ atomic_t di_generation;
7089+
dece6358 7090+ struct au_rwsem di_rwsem;
1facf9fc 7091+ aufs_bindex_t di_bstart, di_bend, di_bwh, di_bdiropq;
7092+ struct au_hdentry *di_hdentry;
4a4d8108 7093+} ____cacheline_aligned_in_smp;
1facf9fc 7094+
7095+/* ---------------------------------------------------------------------- */
7096+
7097+/* dentry.c */
4a4d8108 7098+extern const struct dentry_operations aufs_dop;
1facf9fc 7099+struct au_branch;
7100+struct dentry *au_lkup_one(struct qstr *name, struct dentry *h_parent,
7101+ struct au_branch *br, struct nameidata *nd);
7102+struct dentry *au_sio_lkup_one(struct qstr *name, struct dentry *parent,
7103+ struct au_branch *br);
7104+int au_h_verify(struct dentry *h_dentry, unsigned int udba, struct inode *h_dir,
7105+ struct dentry *h_parent, struct au_branch *br);
7106+
7107+int au_lkup_dentry(struct dentry *dentry, aufs_bindex_t bstart, mode_t type,
7108+ struct nameidata *nd);
7109+int au_lkup_neg(struct dentry *dentry, aufs_bindex_t bindex);
027c5e7a 7110+int au_refresh_dentry(struct dentry *dentry, struct dentry *parent);
1facf9fc 7111+int au_reval_dpath(struct dentry *dentry, unsigned int sigen);
7112+
7113+/* dinfo.c */
4a4d8108 7114+void au_di_init_once(void *_di);
027c5e7a
AM
7115+struct au_dinfo *au_di_alloc(struct super_block *sb, unsigned int lsc);
7116+void au_di_free(struct au_dinfo *dinfo);
7117+void au_di_swap(struct au_dinfo *a, struct au_dinfo *b);
7118+void au_di_cp(struct au_dinfo *dst, struct au_dinfo *src);
4a4d8108
AM
7119+int au_di_init(struct dentry *dentry);
7120+void au_di_fin(struct dentry *dentry);
1facf9fc 7121+int au_di_realloc(struct au_dinfo *dinfo, int nbr);
7122+
7123+void di_read_lock(struct dentry *d, int flags, unsigned int lsc);
7124+void di_read_unlock(struct dentry *d, int flags);
7125+void di_downgrade_lock(struct dentry *d, int flags);
7126+void di_write_lock(struct dentry *d, unsigned int lsc);
7127+void di_write_unlock(struct dentry *d);
7128+void di_write_lock2_child(struct dentry *d1, struct dentry *d2, int isdir);
7129+void di_write_lock2_parent(struct dentry *d1, struct dentry *d2, int isdir);
7130+void di_write_unlock2(struct dentry *d1, struct dentry *d2);
7131+
7132+struct dentry *au_h_dptr(struct dentry *dentry, aufs_bindex_t bindex);
2cbb1c4b 7133+struct dentry *au_h_d_alias(struct dentry *dentry, aufs_bindex_t bindex);
1facf9fc 7134+aufs_bindex_t au_dbtail(struct dentry *dentry);
7135+aufs_bindex_t au_dbtaildir(struct dentry *dentry);
7136+
7137+void au_set_h_dptr(struct dentry *dentry, aufs_bindex_t bindex,
7138+ struct dentry *h_dentry);
027c5e7a
AM
7139+int au_digen_test(struct dentry *dentry, unsigned int sigen);
7140+int au_dbrange_test(struct dentry *dentry);
1facf9fc 7141+void au_update_digen(struct dentry *dentry);
7142+void au_update_dbrange(struct dentry *dentry, int do_put_zero);
7143+void au_update_dbstart(struct dentry *dentry);
7144+void au_update_dbend(struct dentry *dentry);
7145+int au_find_dbindex(struct dentry *dentry, struct dentry *h_dentry);
7146+
7147+/* ---------------------------------------------------------------------- */
7148+
7149+static inline struct au_dinfo *au_di(struct dentry *dentry)
7150+{
7151+ return dentry->d_fsdata;
7152+}
7153+
7154+/* ---------------------------------------------------------------------- */
7155+
7156+/* lock subclass for dinfo */
7157+enum {
7158+ AuLsc_DI_CHILD, /* child first */
4a4d8108 7159+ AuLsc_DI_CHILD2, /* rename(2), link(2), and cpup at hnotify */
1facf9fc 7160+ AuLsc_DI_CHILD3, /* copyup dirs */
7161+ AuLsc_DI_PARENT,
7162+ AuLsc_DI_PARENT2,
027c5e7a
AM
7163+ AuLsc_DI_PARENT3,
7164+ AuLsc_DI_TMP /* temp for replacing dinfo */
1facf9fc 7165+};
7166+
7167+/*
7168+ * di_read_lock_child, di_write_lock_child,
7169+ * di_read_lock_child2, di_write_lock_child2,
7170+ * di_read_lock_child3, di_write_lock_child3,
7171+ * di_read_lock_parent, di_write_lock_parent,
7172+ * di_read_lock_parent2, di_write_lock_parent2,
7173+ * di_read_lock_parent3, di_write_lock_parent3,
7174+ */
7175+#define AuReadLockFunc(name, lsc) \
7176+static inline void di_read_lock_##name(struct dentry *d, int flags) \
7177+{ di_read_lock(d, flags, AuLsc_DI_##lsc); }
7178+
7179+#define AuWriteLockFunc(name, lsc) \
7180+static inline void di_write_lock_##name(struct dentry *d) \
7181+{ di_write_lock(d, AuLsc_DI_##lsc); }
7182+
7183+#define AuRWLockFuncs(name, lsc) \
7184+ AuReadLockFunc(name, lsc) \
7185+ AuWriteLockFunc(name, lsc)
7186+
7187+AuRWLockFuncs(child, CHILD);
7188+AuRWLockFuncs(child2, CHILD2);
7189+AuRWLockFuncs(child3, CHILD3);
7190+AuRWLockFuncs(parent, PARENT);
7191+AuRWLockFuncs(parent2, PARENT2);
7192+AuRWLockFuncs(parent3, PARENT3);
7193+
7194+#undef AuReadLockFunc
7195+#undef AuWriteLockFunc
7196+#undef AuRWLockFuncs
7197+
7198+#define DiMustNoWaiters(d) AuRwMustNoWaiters(&au_di(d)->di_rwsem)
dece6358
AM
7199+#define DiMustAnyLock(d) AuRwMustAnyLock(&au_di(d)->di_rwsem)
7200+#define DiMustWriteLock(d) AuRwMustWriteLock(&au_di(d)->di_rwsem)
1facf9fc 7201+
7202+/* ---------------------------------------------------------------------- */
7203+
7204+/* todo: memory barrier? */
7205+static inline unsigned int au_digen(struct dentry *d)
7206+{
7207+ return atomic_read(&au_di(d)->di_generation);
7208+}
7209+
7210+static inline void au_h_dentry_init(struct au_hdentry *hdentry)
7211+{
7212+ hdentry->hd_dentry = NULL;
7213+}
7214+
7215+static inline void au_hdput(struct au_hdentry *hd)
7216+{
4a4d8108
AM
7217+ if (hd)
7218+ dput(hd->hd_dentry);
1facf9fc 7219+}
7220+
7221+static inline aufs_bindex_t au_dbstart(struct dentry *dentry)
7222+{
1308ab2a 7223+ DiMustAnyLock(dentry);
1facf9fc 7224+ return au_di(dentry)->di_bstart;
7225+}
7226+
7227+static inline aufs_bindex_t au_dbend(struct dentry *dentry)
7228+{
1308ab2a 7229+ DiMustAnyLock(dentry);
1facf9fc 7230+ return au_di(dentry)->di_bend;
7231+}
7232+
7233+static inline aufs_bindex_t au_dbwh(struct dentry *dentry)
7234+{
1308ab2a 7235+ DiMustAnyLock(dentry);
1facf9fc 7236+ return au_di(dentry)->di_bwh;
7237+}
7238+
7239+static inline aufs_bindex_t au_dbdiropq(struct dentry *dentry)
7240+{
1308ab2a 7241+ DiMustAnyLock(dentry);
1facf9fc 7242+ return au_di(dentry)->di_bdiropq;
7243+}
7244+
7245+/* todo: hard/soft set? */
7246+static inline void au_set_dbstart(struct dentry *dentry, aufs_bindex_t bindex)
7247+{
1308ab2a 7248+ DiMustWriteLock(dentry);
1facf9fc 7249+ au_di(dentry)->di_bstart = bindex;
7250+}
7251+
7252+static inline void au_set_dbend(struct dentry *dentry, aufs_bindex_t bindex)
7253+{
1308ab2a 7254+ DiMustWriteLock(dentry);
1facf9fc 7255+ au_di(dentry)->di_bend = bindex;
7256+}
7257+
7258+static inline void au_set_dbwh(struct dentry *dentry, aufs_bindex_t bindex)
7259+{
1308ab2a 7260+ DiMustWriteLock(dentry);
1facf9fc 7261+ /* dbwh can be outside of bstart - bend range */
7262+ au_di(dentry)->di_bwh = bindex;
7263+}
7264+
7265+static inline void au_set_dbdiropq(struct dentry *dentry, aufs_bindex_t bindex)
7266+{
1308ab2a 7267+ DiMustWriteLock(dentry);
1facf9fc 7268+ au_di(dentry)->di_bdiropq = bindex;
7269+}
7270+
7271+/* ---------------------------------------------------------------------- */
7272+
4a4d8108 7273+#ifdef CONFIG_AUFS_HNOTIFY
1facf9fc 7274+static inline void au_digen_dec(struct dentry *d)
7275+{
e49829fe 7276+ atomic_dec(&au_di(d)->di_generation);
1facf9fc 7277+}
7278+
4a4d8108 7279+static inline void au_hn_di_reinit(struct dentry *dentry)
1facf9fc 7280+{
7281+ dentry->d_fsdata = NULL;
7282+}
7283+#else
4a4d8108
AM
7284+AuStubVoid(au_hn_di_reinit, struct dentry *dentry __maybe_unused)
7285+#endif /* CONFIG_AUFS_HNOTIFY */
1facf9fc 7286+
7287+#endif /* __KERNEL__ */
7288+#endif /* __AUFS_DENTRY_H__ */
7f207e10
AM
7289diff -urN /usr/share/empty/fs/aufs/dinfo.c linux/fs/aufs/dinfo.c
7290--- /usr/share/empty/fs/aufs/dinfo.c 1970-01-01 01:00:00.000000000 +0100
7ce627cf 7291+++ linux/fs/aufs/dinfo.c 2012-05-22 09:06:08.867458905 +0200
2cbb1c4b 7292@@ -0,0 +1,543 @@
1facf9fc 7293+/*
f6c5ef8b 7294+ * Copyright (C) 2005-2012 Junjiro R. Okajima
1facf9fc 7295+ *
7296+ * This program, aufs is free software; you can redistribute it and/or modify
7297+ * it under the terms of the GNU General Public License as published by
7298+ * the Free Software Foundation; either version 2 of the License, or
7299+ * (at your option) any later version.
dece6358
AM
7300+ *
7301+ * This program is distributed in the hope that it will be useful,
7302+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
7303+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
7304+ * GNU General Public License for more details.
7305+ *
7306+ * You should have received a copy of the GNU General Public License
7307+ * along with this program; if not, write to the Free Software
7308+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 7309+ */
7310+
7311+/*
7312+ * dentry private data
7313+ */
7314+
7315+#include "aufs.h"
7316+
e49829fe 7317+void au_di_init_once(void *_dinfo)
4a4d8108 7318+{
e49829fe
JR
7319+ struct au_dinfo *dinfo = _dinfo;
7320+ static struct lock_class_key aufs_di;
4a4d8108 7321+
e49829fe
JR
7322+ au_rw_init(&dinfo->di_rwsem);
7323+ au_rw_class(&dinfo->di_rwsem, &aufs_di);
4a4d8108
AM
7324+}
7325+
027c5e7a 7326+struct au_dinfo *au_di_alloc(struct super_block *sb, unsigned int lsc)
1facf9fc 7327+{
7328+ struct au_dinfo *dinfo;
027c5e7a 7329+ int nbr, i;
1facf9fc 7330+
7331+ dinfo = au_cache_alloc_dinfo();
7332+ if (unlikely(!dinfo))
7333+ goto out;
7334+
1facf9fc 7335+ nbr = au_sbend(sb) + 1;
7336+ if (nbr <= 0)
7337+ nbr = 1;
7338+ dinfo->di_hdentry = kcalloc(nbr, sizeof(*dinfo->di_hdentry), GFP_NOFS);
027c5e7a
AM
7339+ if (dinfo->di_hdentry) {
7340+ au_rw_write_lock_nested(&dinfo->di_rwsem, lsc);
7341+ dinfo->di_bstart = -1;
7342+ dinfo->di_bend = -1;
7343+ dinfo->di_bwh = -1;
7344+ dinfo->di_bdiropq = -1;
7345+ for (i = 0; i < nbr; i++)
7346+ dinfo->di_hdentry[i].hd_id = -1;
7347+ goto out;
7348+ }
1facf9fc 7349+
1facf9fc 7350+ au_cache_free_dinfo(dinfo);
027c5e7a
AM
7351+ dinfo = NULL;
7352+
4f0767ce 7353+out:
027c5e7a 7354+ return dinfo;
1facf9fc 7355+}
7356+
027c5e7a 7357+void au_di_free(struct au_dinfo *dinfo)
4a4d8108 7358+{
4a4d8108
AM
7359+ struct au_hdentry *p;
7360+ aufs_bindex_t bend, bindex;
7361+
7362+ /* dentry may not be revalidated */
027c5e7a 7363+ bindex = dinfo->di_bstart;
4a4d8108 7364+ if (bindex >= 0) {
027c5e7a
AM
7365+ bend = dinfo->di_bend;
7366+ p = dinfo->di_hdentry + bindex;
4a4d8108
AM
7367+ while (bindex++ <= bend)
7368+ au_hdput(p++);
7369+ }
027c5e7a
AM
7370+ kfree(dinfo->di_hdentry);
7371+ au_cache_free_dinfo(dinfo);
7372+}
7373+
7374+void au_di_swap(struct au_dinfo *a, struct au_dinfo *b)
7375+{
7376+ struct au_hdentry *p;
7377+ aufs_bindex_t bi;
7378+
7379+ AuRwMustWriteLock(&a->di_rwsem);
7380+ AuRwMustWriteLock(&b->di_rwsem);
7381+
7382+#define DiSwap(v, name) \
7383+ do { \
7384+ v = a->di_##name; \
7385+ a->di_##name = b->di_##name; \
7386+ b->di_##name = v; \
7387+ } while (0)
7388+
7389+ DiSwap(p, hdentry);
7390+ DiSwap(bi, bstart);
7391+ DiSwap(bi, bend);
7392+ DiSwap(bi, bwh);
7393+ DiSwap(bi, bdiropq);
7394+ /* smp_mb(); */
7395+
7396+#undef DiSwap
7397+}
7398+
7399+void au_di_cp(struct au_dinfo *dst, struct au_dinfo *src)
7400+{
7401+ AuRwMustWriteLock(&dst->di_rwsem);
7402+ AuRwMustWriteLock(&src->di_rwsem);
7403+
7404+ dst->di_bstart = src->di_bstart;
7405+ dst->di_bend = src->di_bend;
7406+ dst->di_bwh = src->di_bwh;
7407+ dst->di_bdiropq = src->di_bdiropq;
7408+ /* smp_mb(); */
7409+}
7410+
7411+int au_di_init(struct dentry *dentry)
7412+{
7413+ int err;
7414+ struct super_block *sb;
7415+ struct au_dinfo *dinfo;
7416+
7417+ err = 0;
7418+ sb = dentry->d_sb;
7419+ dinfo = au_di_alloc(sb, AuLsc_DI_CHILD);
7420+ if (dinfo) {
7421+ atomic_set(&dinfo->di_generation, au_sigen(sb));
7422+ /* smp_mb(); */ /* atomic_set */
7423+ dentry->d_fsdata = dinfo;
7424+ } else
7425+ err = -ENOMEM;
7426+
7427+ return err;
7428+}
7429+
7430+void au_di_fin(struct dentry *dentry)
7431+{
7432+ struct au_dinfo *dinfo;
7433+
7434+ dinfo = au_di(dentry);
7435+ AuRwDestroy(&dinfo->di_rwsem);
7436+ au_di_free(dinfo);
4a4d8108
AM
7437+}
7438+
1facf9fc 7439+int au_di_realloc(struct au_dinfo *dinfo, int nbr)
7440+{
7441+ int err, sz;
7442+ struct au_hdentry *hdp;
7443+
1308ab2a 7444+ AuRwMustWriteLock(&dinfo->di_rwsem);
7445+
1facf9fc 7446+ err = -ENOMEM;
7447+ sz = sizeof(*hdp) * (dinfo->di_bend + 1);
7448+ if (!sz)
7449+ sz = sizeof(*hdp);
7450+ hdp = au_kzrealloc(dinfo->di_hdentry, sz, sizeof(*hdp) * nbr, GFP_NOFS);
7451+ if (hdp) {
7452+ dinfo->di_hdentry = hdp;
7453+ err = 0;
7454+ }
7455+
7456+ return err;
7457+}
7458+
7459+/* ---------------------------------------------------------------------- */
7460+
7461+static void do_ii_write_lock(struct inode *inode, unsigned int lsc)
7462+{
7463+ switch (lsc) {
7464+ case AuLsc_DI_CHILD:
7465+ ii_write_lock_child(inode);
7466+ break;
7467+ case AuLsc_DI_CHILD2:
7468+ ii_write_lock_child2(inode);
7469+ break;
7470+ case AuLsc_DI_CHILD3:
7471+ ii_write_lock_child3(inode);
7472+ break;
7473+ case AuLsc_DI_PARENT:
7474+ ii_write_lock_parent(inode);
7475+ break;
7476+ case AuLsc_DI_PARENT2:
7477+ ii_write_lock_parent2(inode);
7478+ break;
7479+ case AuLsc_DI_PARENT3:
7480+ ii_write_lock_parent3(inode);
7481+ break;
7482+ default:
7483+ BUG();
7484+ }
7485+}
7486+
7487+static void do_ii_read_lock(struct inode *inode, unsigned int lsc)
7488+{
7489+ switch (lsc) {
7490+ case AuLsc_DI_CHILD:
7491+ ii_read_lock_child(inode);
7492+ break;
7493+ case AuLsc_DI_CHILD2:
7494+ ii_read_lock_child2(inode);
7495+ break;
7496+ case AuLsc_DI_CHILD3:
7497+ ii_read_lock_child3(inode);
7498+ break;
7499+ case AuLsc_DI_PARENT:
7500+ ii_read_lock_parent(inode);
7501+ break;
7502+ case AuLsc_DI_PARENT2:
7503+ ii_read_lock_parent2(inode);
7504+ break;
7505+ case AuLsc_DI_PARENT3:
7506+ ii_read_lock_parent3(inode);
7507+ break;
7508+ default:
7509+ BUG();
7510+ }
7511+}
7512+
7513+void di_read_lock(struct dentry *d, int flags, unsigned int lsc)
7514+{
dece6358 7515+ au_rw_read_lock_nested(&au_di(d)->di_rwsem, lsc);
1facf9fc 7516+ if (d->d_inode) {
7517+ if (au_ftest_lock(flags, IW))
7518+ do_ii_write_lock(d->d_inode, lsc);
7519+ else if (au_ftest_lock(flags, IR))
7520+ do_ii_read_lock(d->d_inode, lsc);
7521+ }
7522+}
7523+
7524+void di_read_unlock(struct dentry *d, int flags)
7525+{
7526+ if (d->d_inode) {
027c5e7a
AM
7527+ if (au_ftest_lock(flags, IW)) {
7528+ au_dbg_verify_dinode(d);
1facf9fc 7529+ ii_write_unlock(d->d_inode);
027c5e7a
AM
7530+ } else if (au_ftest_lock(flags, IR)) {
7531+ au_dbg_verify_dinode(d);
1facf9fc 7532+ ii_read_unlock(d->d_inode);
027c5e7a 7533+ }
1facf9fc 7534+ }
dece6358 7535+ au_rw_read_unlock(&au_di(d)->di_rwsem);
1facf9fc 7536+}
7537+
7538+void di_downgrade_lock(struct dentry *d, int flags)
7539+{
1facf9fc 7540+ if (d->d_inode && au_ftest_lock(flags, IR))
7541+ ii_downgrade_lock(d->d_inode);
dece6358 7542+ au_rw_dgrade_lock(&au_di(d)->di_rwsem);
1facf9fc 7543+}
7544+
7545+void di_write_lock(struct dentry *d, unsigned int lsc)
7546+{
dece6358 7547+ au_rw_write_lock_nested(&au_di(d)->di_rwsem, lsc);
1facf9fc 7548+ if (d->d_inode)
7549+ do_ii_write_lock(d->d_inode, lsc);
7550+}
7551+
7552+void di_write_unlock(struct dentry *d)
7553+{
027c5e7a 7554+ au_dbg_verify_dinode(d);
1facf9fc 7555+ if (d->d_inode)
7556+ ii_write_unlock(d->d_inode);
dece6358 7557+ au_rw_write_unlock(&au_di(d)->di_rwsem);
1facf9fc 7558+}
7559+
7560+void di_write_lock2_child(struct dentry *d1, struct dentry *d2, int isdir)
7561+{
7562+ AuDebugOn(d1 == d2
7563+ || d1->d_inode == d2->d_inode
7564+ || d1->d_sb != d2->d_sb);
7565+
7566+ if (isdir && au_test_subdir(d1, d2)) {
7567+ di_write_lock_child(d1);
7568+ di_write_lock_child2(d2);
7569+ } else {
7570+ /* there should be no races */
7571+ di_write_lock_child(d2);
7572+ di_write_lock_child2(d1);
7573+ }
7574+}
7575+
7576+void di_write_lock2_parent(struct dentry *d1, struct dentry *d2, int isdir)
7577+{
7578+ AuDebugOn(d1 == d2
7579+ || d1->d_inode == d2->d_inode
7580+ || d1->d_sb != d2->d_sb);
7581+
7582+ if (isdir && au_test_subdir(d1, d2)) {
7583+ di_write_lock_parent(d1);
7584+ di_write_lock_parent2(d2);
7585+ } else {
7586+ /* there should be no races */
7587+ di_write_lock_parent(d2);
7588+ di_write_lock_parent2(d1);
7589+ }
7590+}
7591+
7592+void di_write_unlock2(struct dentry *d1, struct dentry *d2)
7593+{
7594+ di_write_unlock(d1);
7595+ if (d1->d_inode == d2->d_inode)
dece6358 7596+ au_rw_write_unlock(&au_di(d2)->di_rwsem);
1facf9fc 7597+ else
7598+ di_write_unlock(d2);
7599+}
7600+
7601+/* ---------------------------------------------------------------------- */
7602+
7603+struct dentry *au_h_dptr(struct dentry *dentry, aufs_bindex_t bindex)
7604+{
7605+ struct dentry *d;
7606+
1308ab2a 7607+ DiMustAnyLock(dentry);
7608+
1facf9fc 7609+ if (au_dbstart(dentry) < 0 || bindex < au_dbstart(dentry))
7610+ return NULL;
7611+ AuDebugOn(bindex < 0);
7612+ d = au_di(dentry)->di_hdentry[0 + bindex].hd_dentry;
027c5e7a 7613+ AuDebugOn(d && d->d_count <= 0);
1facf9fc 7614+ return d;
7615+}
7616+
2cbb1c4b
JR
7617+/*
7618+ * extended version of au_h_dptr().
7619+ * returns a hashed and positive h_dentry in bindex, NULL, or error.
7620+ */
7621+struct dentry *au_h_d_alias(struct dentry *dentry, aufs_bindex_t bindex)
7622+{
7623+ struct dentry *h_dentry;
7624+ struct inode *inode, *h_inode;
7625+
7626+ inode = dentry->d_inode;
7627+ AuDebugOn(!inode);
7628+
7629+ h_dentry = NULL;
7630+ if (au_dbstart(dentry) <= bindex
7631+ && bindex <= au_dbend(dentry))
7632+ h_dentry = au_h_dptr(dentry, bindex);
7633+ if (h_dentry && !au_d_hashed_positive(h_dentry)) {
7634+ dget(h_dentry);
7635+ goto out; /* success */
7636+ }
7637+
7638+ AuDebugOn(bindex < au_ibstart(inode));
7639+ AuDebugOn(au_ibend(inode) < bindex);
7640+ h_inode = au_h_iptr(inode, bindex);
7641+ h_dentry = d_find_alias(h_inode);
7642+ if (h_dentry) {
7643+ if (!IS_ERR(h_dentry)) {
7644+ if (!au_d_hashed_positive(h_dentry))
7645+ goto out; /* success */
7646+ dput(h_dentry);
7647+ } else
7648+ goto out;
7649+ }
7650+
7651+ if (au_opt_test(au_mntflags(dentry->d_sb), PLINK)) {
7652+ h_dentry = au_plink_lkup(inode, bindex);
7653+ AuDebugOn(!h_dentry);
7654+ if (!IS_ERR(h_dentry)) {
7655+ if (!au_d_hashed_positive(h_dentry))
7656+ goto out; /* success */
7657+ dput(h_dentry);
7658+ h_dentry = NULL;
7659+ }
7660+ }
7661+
7662+out:
7663+ AuDbgDentry(h_dentry);
7664+ return h_dentry;
7665+}
7666+
1facf9fc 7667+aufs_bindex_t au_dbtail(struct dentry *dentry)
7668+{
7669+ aufs_bindex_t bend, bwh;
7670+
7671+ bend = au_dbend(dentry);
7672+ if (0 <= bend) {
7673+ bwh = au_dbwh(dentry);
7674+ if (!bwh)
7675+ return bwh;
7676+ if (0 < bwh && bwh < bend)
7677+ return bwh - 1;
7678+ }
7679+ return bend;
7680+}
7681+
7682+aufs_bindex_t au_dbtaildir(struct dentry *dentry)
7683+{
7684+ aufs_bindex_t bend, bopq;
7685+
7686+ bend = au_dbtail(dentry);
7687+ if (0 <= bend) {
7688+ bopq = au_dbdiropq(dentry);
7689+ if (0 <= bopq && bopq < bend)
7690+ bend = bopq;
7691+ }
7692+ return bend;
7693+}
7694+
7695+/* ---------------------------------------------------------------------- */
7696+
7697+void au_set_h_dptr(struct dentry *dentry, aufs_bindex_t bindex,
7698+ struct dentry *h_dentry)
7699+{
7700+ struct au_hdentry *hd = au_di(dentry)->di_hdentry + bindex;
027c5e7a 7701+ struct au_branch *br;
1facf9fc 7702+
1308ab2a 7703+ DiMustWriteLock(dentry);
7704+
4a4d8108 7705+ au_hdput(hd);
1facf9fc 7706+ hd->hd_dentry = h_dentry;
027c5e7a
AM
7707+ if (h_dentry) {
7708+ br = au_sbr(dentry->d_sb, bindex);
7709+ hd->hd_id = br->br_id;
7710+ }
7711+}
7712+
7713+int au_dbrange_test(struct dentry *dentry)
7714+{
7715+ int err;
7716+ aufs_bindex_t bstart, bend;
7717+
7718+ err = 0;
7719+ bstart = au_dbstart(dentry);
7720+ bend = au_dbend(dentry);
7721+ if (bstart >= 0)
7722+ AuDebugOn(bend < 0 && bstart > bend);
7723+ else {
7724+ err = -EIO;
7725+ AuDebugOn(bend >= 0);
7726+ }
7727+
7728+ return err;
7729+}
7730+
7731+int au_digen_test(struct dentry *dentry, unsigned int sigen)
7732+{
7733+ int err;
7734+
7735+ err = 0;
7736+ if (unlikely(au_digen(dentry) != sigen
7737+ || au_iigen_test(dentry->d_inode, sigen)))
7738+ err = -EIO;
7739+
7740+ return err;
1facf9fc 7741+}
7742+
7743+void au_update_digen(struct dentry *dentry)
7744+{
7745+ atomic_set(&au_di(dentry)->di_generation, au_sigen(dentry->d_sb));
7746+ /* smp_mb(); */ /* atomic_set */
7747+}
7748+
7749+void au_update_dbrange(struct dentry *dentry, int do_put_zero)
7750+{
7751+ struct au_dinfo *dinfo;
7752+ struct dentry *h_d;
4a4d8108 7753+ struct au_hdentry *hdp;
1facf9fc 7754+
1308ab2a 7755+ DiMustWriteLock(dentry);
7756+
1facf9fc 7757+ dinfo = au_di(dentry);
7758+ if (!dinfo || dinfo->di_bstart < 0)
7759+ return;
7760+
4a4d8108 7761+ hdp = dinfo->di_hdentry;
1facf9fc 7762+ if (do_put_zero) {
7763+ aufs_bindex_t bindex, bend;
7764+
7765+ bend = dinfo->di_bend;
7766+ for (bindex = dinfo->di_bstart; bindex <= bend; bindex++) {
4a4d8108 7767+ h_d = hdp[0 + bindex].hd_dentry;
1facf9fc 7768+ if (h_d && !h_d->d_inode)
7769+ au_set_h_dptr(dentry, bindex, NULL);
7770+ }
7771+ }
7772+
7773+ dinfo->di_bstart = -1;
7774+ while (++dinfo->di_bstart <= dinfo->di_bend)
4a4d8108 7775+ if (hdp[0 + dinfo->di_bstart].hd_dentry)
1facf9fc 7776+ break;
7777+ if (dinfo->di_bstart > dinfo->di_bend) {
7778+ dinfo->di_bstart = -1;
7779+ dinfo->di_bend = -1;
7780+ return;
7781+ }
7782+
7783+ dinfo->di_bend++;
7784+ while (0 <= --dinfo->di_bend)
4a4d8108 7785+ if (hdp[0 + dinfo->di_bend].hd_dentry)
1facf9fc 7786+ break;
7787+ AuDebugOn(dinfo->di_bstart > dinfo->di_bend || dinfo->di_bend < 0);
7788+}
7789+
7790+void au_update_dbstart(struct dentry *dentry)
7791+{
7792+ aufs_bindex_t bindex, bend;
7793+ struct dentry *h_dentry;
7794+
7795+ bend = au_dbend(dentry);
7796+ for (bindex = au_dbstart(dentry); bindex <= bend; bindex++) {
7797+ h_dentry = au_h_dptr(dentry, bindex);
7798+ if (!h_dentry)
7799+ continue;
7800+ if (h_dentry->d_inode) {
7801+ au_set_dbstart(dentry, bindex);
7802+ return;
7803+ }
7804+ au_set_h_dptr(dentry, bindex, NULL);
7805+ }
7806+}
7807+
7808+void au_update_dbend(struct dentry *dentry)
7809+{
7810+ aufs_bindex_t bindex, bstart;
7811+ struct dentry *h_dentry;
7812+
7813+ bstart = au_dbstart(dentry);
7f207e10 7814+ for (bindex = au_dbend(dentry); bindex >= bstart; bindex--) {
1facf9fc 7815+ h_dentry = au_h_dptr(dentry, bindex);
7816+ if (!h_dentry)
7817+ continue;
7818+ if (h_dentry->d_inode) {
7819+ au_set_dbend(dentry, bindex);
7820+ return;
7821+ }
7822+ au_set_h_dptr(dentry, bindex, NULL);
7823+ }
7824+}
7825+
7826+int au_find_dbindex(struct dentry *dentry, struct dentry *h_dentry)
7827+{
7828+ aufs_bindex_t bindex, bend;
7829+
7830+ bend = au_dbend(dentry);
7831+ for (bindex = au_dbstart(dentry); bindex <= bend; bindex++)
7832+ if (au_h_dptr(dentry, bindex) == h_dentry)
7833+ return bindex;
7834+ return -1;
7835+}
7f207e10
AM
7836diff -urN /usr/share/empty/fs/aufs/dir.c linux/fs/aufs/dir.c
7837--- /usr/share/empty/fs/aufs/dir.c 1970-01-01 01:00:00.000000000 +0100
7ce627cf 7838+++ linux/fs/aufs/dir.c 2012-05-22 09:06:08.867458905 +0200
7eafdf33 7839@@ -0,0 +1,636 @@
1facf9fc 7840+/*
f6c5ef8b 7841+ * Copyright (C) 2005-2012 Junjiro R. Okajima
1facf9fc 7842+ *
7843+ * This program, aufs is free software; you can redistribute it and/or modify
7844+ * it under the terms of the GNU General Public License as published by
7845+ * the Free Software Foundation; either version 2 of the License, or
7846+ * (at your option) any later version.
dece6358
AM
7847+ *
7848+ * This program is distributed in the hope that it will be useful,
7849+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
7850+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
7851+ * GNU General Public License for more details.
7852+ *
7853+ * You should have received a copy of the GNU General Public License
7854+ * along with this program; if not, write to the Free Software
7855+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 7856+ */
7857+
7858+/*
7859+ * directory operations
7860+ */
7861+
7862+#include <linux/fs_stack.h>
7863+#include "aufs.h"
7864+
7865+void au_add_nlink(struct inode *dir, struct inode *h_dir)
7866+{
9dbd164d
AM
7867+ unsigned int nlink;
7868+
1facf9fc 7869+ AuDebugOn(!S_ISDIR(dir->i_mode) || !S_ISDIR(h_dir->i_mode));
7870+
9dbd164d
AM
7871+ nlink = dir->i_nlink;
7872+ nlink += h_dir->i_nlink - 2;
1facf9fc 7873+ if (h_dir->i_nlink < 2)
9dbd164d 7874+ nlink += 2;
7eafdf33 7875+ /* 0 can happen in revaliding */
92d182d2 7876+ set_nlink(dir, nlink);
1facf9fc 7877+}
7878+
7879+void au_sub_nlink(struct inode *dir, struct inode *h_dir)
7880+{
9dbd164d
AM
7881+ unsigned int nlink;
7882+
1facf9fc 7883+ AuDebugOn(!S_ISDIR(dir->i_mode) || !S_ISDIR(h_dir->i_mode));
7884+
9dbd164d
AM
7885+ nlink = dir->i_nlink;
7886+ nlink -= h_dir->i_nlink - 2;
1facf9fc 7887+ if (h_dir->i_nlink < 2)
9dbd164d 7888+ nlink -= 2;
92d182d2 7889+ /* nlink == 0 means the branch-fs is broken */
9dbd164d 7890+ set_nlink(dir, nlink);
1facf9fc 7891+}
7892+
1308ab2a 7893+loff_t au_dir_size(struct file *file, struct dentry *dentry)
7894+{
7895+ loff_t sz;
7896+ aufs_bindex_t bindex, bend;
7897+ struct file *h_file;
7898+ struct dentry *h_dentry;
7899+
7900+ sz = 0;
7901+ if (file) {
7902+ AuDebugOn(!file->f_dentry);
7903+ AuDebugOn(!file->f_dentry->d_inode);
7904+ AuDebugOn(!S_ISDIR(file->f_dentry->d_inode->i_mode));
7905+
4a4d8108 7906+ bend = au_fbend_dir(file);
1308ab2a 7907+ for (bindex = au_fbstart(file);
7908+ bindex <= bend && sz < KMALLOC_MAX_SIZE;
7909+ bindex++) {
4a4d8108 7910+ h_file = au_hf_dir(file, bindex);
1308ab2a 7911+ if (h_file
7912+ && h_file->f_dentry
7913+ && h_file->f_dentry->d_inode)
7914+ sz += i_size_read(h_file->f_dentry->d_inode);
7915+ }
7916+ } else {
7917+ AuDebugOn(!dentry);
7918+ AuDebugOn(!dentry->d_inode);
7919+ AuDebugOn(!S_ISDIR(dentry->d_inode->i_mode));
7920+
7921+ bend = au_dbtaildir(dentry);
7922+ for (bindex = au_dbstart(dentry);
7923+ bindex <= bend && sz < KMALLOC_MAX_SIZE;
7924+ bindex++) {
7925+ h_dentry = au_h_dptr(dentry, bindex);
7926+ if (h_dentry && h_dentry->d_inode)
7927+ sz += i_size_read(h_dentry->d_inode);
7928+ }
7929+ }
7930+ if (sz < KMALLOC_MAX_SIZE)
7931+ sz = roundup_pow_of_two(sz);
7932+ if (sz > KMALLOC_MAX_SIZE)
7933+ sz = KMALLOC_MAX_SIZE;
7934+ else if (sz < NAME_MAX) {
7935+ BUILD_BUG_ON(AUFS_RDBLK_DEF < NAME_MAX);
7936+ sz = AUFS_RDBLK_DEF;
7937+ }
7938+ return sz;
7939+}
7940+
1facf9fc 7941+/* ---------------------------------------------------------------------- */
7942+
7943+static int reopen_dir(struct file *file)
7944+{
7945+ int err;
7946+ unsigned int flags;
7947+ aufs_bindex_t bindex, btail, bstart;
7948+ struct dentry *dentry, *h_dentry;
7949+ struct file *h_file;
7950+
7951+ /* open all lower dirs */
7952+ dentry = file->f_dentry;
7953+ bstart = au_dbstart(dentry);
7954+ for (bindex = au_fbstart(file); bindex < bstart; bindex++)
7955+ au_set_h_fptr(file, bindex, NULL);
7956+ au_set_fbstart(file, bstart);
7957+
7958+ btail = au_dbtaildir(dentry);
4a4d8108 7959+ for (bindex = au_fbend_dir(file); btail < bindex; bindex--)
1facf9fc 7960+ au_set_h_fptr(file, bindex, NULL);
4a4d8108 7961+ au_set_fbend_dir(file, btail);
1facf9fc 7962+
4a4d8108 7963+ flags = vfsub_file_flags(file);
1facf9fc 7964+ for (bindex = bstart; bindex <= btail; bindex++) {
7965+ h_dentry = au_h_dptr(dentry, bindex);
7966+ if (!h_dentry)
7967+ continue;
4a4d8108 7968+ h_file = au_hf_dir(file, bindex);
1facf9fc 7969+ if (h_file)
7970+ continue;
7971+
7972+ h_file = au_h_open(dentry, bindex, flags, file);
7973+ err = PTR_ERR(h_file);
7974+ if (IS_ERR(h_file))
7975+ goto out; /* close all? */
7976+ au_set_h_fptr(file, bindex, h_file);
7977+ }
7978+ au_update_figen(file);
7979+ /* todo: necessary? */
7980+ /* file->f_ra = h_file->f_ra; */
7981+ err = 0;
7982+
4f0767ce 7983+out:
1facf9fc 7984+ return err;
7985+}
7986+
7987+static int do_open_dir(struct file *file, int flags)
7988+{
7989+ int err;
7990+ aufs_bindex_t bindex, btail;
7991+ struct dentry *dentry, *h_dentry;
7992+ struct file *h_file;
7993+
1308ab2a 7994+ FiMustWriteLock(file);
7995+
1facf9fc 7996+ dentry = file->f_dentry;
027c5e7a
AM
7997+ err = au_alive_dir(dentry);
7998+ if (unlikely(err))
7999+ goto out;
8000+
1facf9fc 8001+ file->f_version = dentry->d_inode->i_version;
8002+ bindex = au_dbstart(dentry);
8003+ au_set_fbstart(file, bindex);
8004+ btail = au_dbtaildir(dentry);
4a4d8108 8005+ au_set_fbend_dir(file, btail);
1facf9fc 8006+ for (; !err && bindex <= btail; bindex++) {
8007+ h_dentry = au_h_dptr(dentry, bindex);
8008+ if (!h_dentry)
8009+ continue;
8010+
8011+ h_file = au_h_open(dentry, bindex, flags, file);
8012+ if (IS_ERR(h_file)) {
8013+ err = PTR_ERR(h_file);
8014+ break;
8015+ }
8016+ au_set_h_fptr(file, bindex, h_file);
8017+ }
8018+ au_update_figen(file);
8019+ /* todo: necessary? */
8020+ /* file->f_ra = h_file->f_ra; */
8021+ if (!err)
8022+ return 0; /* success */
8023+
8024+ /* close all */
8025+ for (bindex = au_fbstart(file); bindex <= btail; bindex++)
8026+ au_set_h_fptr(file, bindex, NULL);
8027+ au_set_fbstart(file, -1);
4a4d8108
AM
8028+ au_set_fbend_dir(file, -1);
8029+
027c5e7a 8030+out:
1facf9fc 8031+ return err;
8032+}
8033+
8034+static int aufs_open_dir(struct inode *inode __maybe_unused,
8035+ struct file *file)
8036+{
4a4d8108
AM
8037+ int err;
8038+ struct super_block *sb;
8039+ struct au_fidir *fidir;
8040+
8041+ err = -ENOMEM;
8042+ sb = file->f_dentry->d_sb;
8043+ si_read_lock(sb, AuLock_FLUSH);
e49829fe 8044+ fidir = au_fidir_alloc(sb);
4a4d8108
AM
8045+ if (fidir) {
8046+ err = au_do_open(file, do_open_dir, fidir);
8047+ if (unlikely(err))
8048+ kfree(fidir);
8049+ }
8050+ si_read_unlock(sb);
8051+ return err;
1facf9fc 8052+}
8053+
8054+static int aufs_release_dir(struct inode *inode __maybe_unused,
8055+ struct file *file)
8056+{
8057+ struct au_vdir *vdir_cache;
4a4d8108
AM
8058+ struct au_finfo *finfo;
8059+ struct au_fidir *fidir;
8060+ aufs_bindex_t bindex, bend;
1facf9fc 8061+
4a4d8108
AM
8062+ finfo = au_fi(file);
8063+ fidir = finfo->fi_hdir;
8064+ if (fidir) {
0c5527e5
AM
8065+ /* remove me from sb->s_files */
8066+ file_sb_list_del(file);
8067+
4a4d8108
AM
8068+ vdir_cache = fidir->fd_vdir_cache; /* lock-free */
8069+ if (vdir_cache)
8070+ au_vdir_free(vdir_cache);
8071+
8072+ bindex = finfo->fi_btop;
8073+ if (bindex >= 0) {
8074+ /*
8075+ * calls fput() instead of filp_close(),
8076+ * since no dnotify or lock for the lower file.
8077+ */
8078+ bend = fidir->fd_bbot;
8079+ for (; bindex <= bend; bindex++)
8080+ au_set_h_fptr(file, bindex, NULL);
8081+ }
8082+ kfree(fidir);
8083+ finfo->fi_hdir = NULL;
1facf9fc 8084+ }
1facf9fc 8085+ au_finfo_fin(file);
1facf9fc 8086+ return 0;
8087+}
8088+
8089+/* ---------------------------------------------------------------------- */
8090+
4a4d8108
AM
8091+static int au_do_flush_dir(struct file *file, fl_owner_t id)
8092+{
8093+ int err;
8094+ aufs_bindex_t bindex, bend;
8095+ struct file *h_file;
8096+
8097+ err = 0;
8098+ bend = au_fbend_dir(file);
8099+ for (bindex = au_fbstart(file); !err && bindex <= bend; bindex++) {
8100+ h_file = au_hf_dir(file, bindex);
8101+ if (h_file)
8102+ err = vfsub_flush(h_file, id);
8103+ }
8104+ return err;
8105+}
8106+
8107+static int aufs_flush_dir(struct file *file, fl_owner_t id)
8108+{
8109+ return au_do_flush(file, id, au_do_flush_dir);
8110+}
8111+
8112+/* ---------------------------------------------------------------------- */
8113+
1facf9fc 8114+static int au_do_fsync_dir_no_file(struct dentry *dentry, int datasync)
8115+{
8116+ int err;
8117+ aufs_bindex_t bend, bindex;
8118+ struct inode *inode;
8119+ struct super_block *sb;
8120+
8121+ err = 0;
8122+ sb = dentry->d_sb;
8123+ inode = dentry->d_inode;
8124+ IMustLock(inode);
8125+ bend = au_dbend(dentry);
8126+ for (bindex = au_dbstart(dentry); !err && bindex <= bend; bindex++) {
8127+ struct path h_path;
1facf9fc 8128+
8129+ if (au_test_ro(sb, bindex, inode))
8130+ continue;
8131+ h_path.dentry = au_h_dptr(dentry, bindex);
8132+ if (!h_path.dentry)
8133+ continue;
1facf9fc 8134+
1facf9fc 8135+ h_path.mnt = au_sbr_mnt(sb, bindex);
53392da6 8136+ err = vfsub_fsync(NULL, &h_path, datasync);
1facf9fc 8137+ }
8138+
8139+ return err;
8140+}
8141+
8142+static int au_do_fsync_dir(struct file *file, int datasync)
8143+{
8144+ int err;
8145+ aufs_bindex_t bend, bindex;
8146+ struct file *h_file;
8147+ struct super_block *sb;
8148+ struct inode *inode;
1facf9fc 8149+
8150+ err = au_reval_and_lock_fdi(file, reopen_dir, /*wlock*/1);
8151+ if (unlikely(err))
8152+ goto out;
8153+
8154+ sb = file->f_dentry->d_sb;
8155+ inode = file->f_dentry->d_inode;
4a4d8108 8156+ bend = au_fbend_dir(file);
1facf9fc 8157+ for (bindex = au_fbstart(file); !err && bindex <= bend; bindex++) {
4a4d8108 8158+ h_file = au_hf_dir(file, bindex);
1facf9fc 8159+ if (!h_file || au_test_ro(sb, bindex, inode))
8160+ continue;
8161+
53392da6 8162+ err = vfsub_fsync(h_file, &h_file->f_path, datasync);
1facf9fc 8163+ }
8164+
4f0767ce 8165+out:
1facf9fc 8166+ return err;
8167+}
8168+
8169+/*
8170+ * @file may be NULL
8171+ */
1e00d052
AM
8172+static int aufs_fsync_dir(struct file *file, loff_t start, loff_t end,
8173+ int datasync)
1facf9fc 8174+{
8175+ int err;
b752ccd1 8176+ struct dentry *dentry;
1facf9fc 8177+ struct super_block *sb;
1e00d052 8178+ struct mutex *mtx;
1facf9fc 8179+
8180+ err = 0;
1e00d052
AM
8181+ dentry = file->f_dentry;
8182+ mtx = &dentry->d_inode->i_mutex;
8183+ mutex_lock(mtx);
1facf9fc 8184+ sb = dentry->d_sb;
8185+ si_noflush_read_lock(sb);
8186+ if (file)
8187+ err = au_do_fsync_dir(file, datasync);
8188+ else {
8189+ di_write_lock_child(dentry);
8190+ err = au_do_fsync_dir_no_file(dentry, datasync);
8191+ }
8192+ au_cpup_attr_timesizes(dentry->d_inode);
8193+ di_write_unlock(dentry);
8194+ if (file)
8195+ fi_write_unlock(file);
8196+
8197+ si_read_unlock(sb);
1e00d052 8198+ mutex_unlock(mtx);
1facf9fc 8199+ return err;
8200+}
8201+
8202+/* ---------------------------------------------------------------------- */
8203+
8204+static int aufs_readdir(struct file *file, void *dirent, filldir_t filldir)
8205+{
8206+ int err;
8207+ struct dentry *dentry;
9dbd164d 8208+ struct inode *inode, *h_inode;
1facf9fc 8209+ struct super_block *sb;
8210+
8211+ dentry = file->f_dentry;
8212+ inode = dentry->d_inode;
8213+ IMustLock(inode);
8214+
8215+ sb = dentry->d_sb;
8216+ si_read_lock(sb, AuLock_FLUSH);
8217+ err = au_reval_and_lock_fdi(file, reopen_dir, /*wlock*/1);
8218+ if (unlikely(err))
8219+ goto out;
027c5e7a
AM
8220+ err = au_alive_dir(dentry);
8221+ if (!err)
8222+ err = au_vdir_init(file);
1facf9fc 8223+ di_downgrade_lock(dentry, AuLock_IR);
8224+ if (unlikely(err))
8225+ goto out_unlock;
8226+
9dbd164d 8227+ h_inode = au_h_iptr(inode, au_ibstart(inode));
b752ccd1 8228+ if (!au_test_nfsd()) {
1facf9fc 8229+ err = au_vdir_fill_de(file, dirent, filldir);
9dbd164d 8230+ fsstack_copy_attr_atime(inode, h_inode);
1facf9fc 8231+ } else {
8232+ /*
8233+ * nfsd filldir may call lookup_one_len(), vfs_getattr(),
8234+ * encode_fh() and others.
8235+ */
9dbd164d 8236+ atomic_inc(&h_inode->i_count);
1facf9fc 8237+ di_read_unlock(dentry, AuLock_IR);
8238+ si_read_unlock(sb);
1facf9fc 8239+ err = au_vdir_fill_de(file, dirent, filldir);
1facf9fc 8240+ fsstack_copy_attr_atime(inode, h_inode);
8241+ fi_write_unlock(file);
9dbd164d 8242+ iput(h_inode);
1facf9fc 8243+
8244+ AuTraceErr(err);
8245+ return err;
8246+ }
8247+
4f0767ce 8248+out_unlock:
1facf9fc 8249+ di_read_unlock(dentry, AuLock_IR);
8250+ fi_write_unlock(file);
4f0767ce 8251+out:
1facf9fc 8252+ si_read_unlock(sb);
8253+ return err;
8254+}
8255+
8256+/* ---------------------------------------------------------------------- */
8257+
8258+#define AuTestEmpty_WHONLY 1
dece6358
AM
8259+#define AuTestEmpty_CALLED (1 << 1)
8260+#define AuTestEmpty_SHWH (1 << 2)
1facf9fc 8261+#define au_ftest_testempty(flags, name) ((flags) & AuTestEmpty_##name)
7f207e10
AM
8262+#define au_fset_testempty(flags, name) \
8263+ do { (flags) |= AuTestEmpty_##name; } while (0)
8264+#define au_fclr_testempty(flags, name) \
8265+ do { (flags) &= ~AuTestEmpty_##name; } while (0)
1facf9fc 8266+
dece6358
AM
8267+#ifndef CONFIG_AUFS_SHWH
8268+#undef AuTestEmpty_SHWH
8269+#define AuTestEmpty_SHWH 0
8270+#endif
8271+
1facf9fc 8272+struct test_empty_arg {
1308ab2a 8273+ struct au_nhash *whlist;
1facf9fc 8274+ unsigned int flags;
8275+ int err;
8276+ aufs_bindex_t bindex;
8277+};
8278+
8279+static int test_empty_cb(void *__arg, const char *__name, int namelen,
dece6358
AM
8280+ loff_t offset __maybe_unused, u64 ino,
8281+ unsigned int d_type)
1facf9fc 8282+{
8283+ struct test_empty_arg *arg = __arg;
8284+ char *name = (void *)__name;
8285+
8286+ arg->err = 0;
8287+ au_fset_testempty(arg->flags, CALLED);
8288+ /* smp_mb(); */
8289+ if (name[0] == '.'
8290+ && (namelen == 1 || (name[1] == '.' && namelen == 2)))
8291+ goto out; /* success */
8292+
8293+ if (namelen <= AUFS_WH_PFX_LEN
8294+ || memcmp(name, AUFS_WH_PFX, AUFS_WH_PFX_LEN)) {
8295+ if (au_ftest_testempty(arg->flags, WHONLY)
1308ab2a 8296+ && !au_nhash_test_known_wh(arg->whlist, name, namelen))
1facf9fc 8297+ arg->err = -ENOTEMPTY;
8298+ goto out;
8299+ }
8300+
8301+ name += AUFS_WH_PFX_LEN;
8302+ namelen -= AUFS_WH_PFX_LEN;
1308ab2a 8303+ if (!au_nhash_test_known_wh(arg->whlist, name, namelen))
1facf9fc 8304+ arg->err = au_nhash_append_wh
1308ab2a 8305+ (arg->whlist, name, namelen, ino, d_type, arg->bindex,
dece6358 8306+ au_ftest_testempty(arg->flags, SHWH));
1facf9fc 8307+
4f0767ce 8308+out:
1facf9fc 8309+ /* smp_mb(); */
8310+ AuTraceErr(arg->err);
8311+ return arg->err;
8312+}
8313+
8314+static int do_test_empty(struct dentry *dentry, struct test_empty_arg *arg)
8315+{
8316+ int err;
8317+ struct file *h_file;
8318+
8319+ h_file = au_h_open(dentry, arg->bindex,
8320+ O_RDONLY | O_NONBLOCK | O_DIRECTORY | O_LARGEFILE,
8321+ /*file*/NULL);
8322+ err = PTR_ERR(h_file);
8323+ if (IS_ERR(h_file))
8324+ goto out;
8325+
8326+ err = 0;
8327+ if (!au_opt_test(au_mntflags(dentry->d_sb), UDBA_NONE)
8328+ && !h_file->f_dentry->d_inode->i_nlink)
8329+ goto out_put;
8330+
8331+ do {
8332+ arg->err = 0;
8333+ au_fclr_testempty(arg->flags, CALLED);
8334+ /* smp_mb(); */
8335+ err = vfsub_readdir(h_file, test_empty_cb, arg);
8336+ if (err >= 0)
8337+ err = arg->err;
8338+ } while (!err && au_ftest_testempty(arg->flags, CALLED));
8339+
4f0767ce 8340+out_put:
1facf9fc 8341+ fput(h_file);
8342+ au_sbr_put(dentry->d_sb, arg->bindex);
4f0767ce 8343+out:
1facf9fc 8344+ return err;
8345+}
8346+
8347+struct do_test_empty_args {
8348+ int *errp;
8349+ struct dentry *dentry;
8350+ struct test_empty_arg *arg;
8351+};
8352+
8353+static void call_do_test_empty(void *args)
8354+{
8355+ struct do_test_empty_args *a = args;
8356+ *a->errp = do_test_empty(a->dentry, a->arg);
8357+}
8358+
8359+static int sio_test_empty(struct dentry *dentry, struct test_empty_arg *arg)
8360+{
8361+ int err, wkq_err;
8362+ struct dentry *h_dentry;
8363+ struct inode *h_inode;
8364+
8365+ h_dentry = au_h_dptr(dentry, arg->bindex);
8366+ h_inode = h_dentry->d_inode;
53392da6 8367+ /* todo: i_mode changes anytime? */
1facf9fc 8368+ mutex_lock_nested(&h_inode->i_mutex, AuLsc_I_CHILD);
8369+ err = au_test_h_perm_sio(h_inode, MAY_EXEC | MAY_READ);
8370+ mutex_unlock(&h_inode->i_mutex);
8371+ if (!err)
8372+ err = do_test_empty(dentry, arg);
8373+ else {
8374+ struct do_test_empty_args args = {
8375+ .errp = &err,
8376+ .dentry = dentry,
8377+ .arg = arg
8378+ };
8379+ unsigned int flags = arg->flags;
8380+
8381+ wkq_err = au_wkq_wait(call_do_test_empty, &args);
8382+ if (unlikely(wkq_err))
8383+ err = wkq_err;
8384+ arg->flags = flags;
8385+ }
8386+
8387+ return err;
8388+}
8389+
8390+int au_test_empty_lower(struct dentry *dentry)
8391+{
8392+ int err;
1308ab2a 8393+ unsigned int rdhash;
1facf9fc 8394+ aufs_bindex_t bindex, bstart, btail;
1308ab2a 8395+ struct au_nhash whlist;
1facf9fc 8396+ struct test_empty_arg arg;
1facf9fc 8397+
dece6358
AM
8398+ SiMustAnyLock(dentry->d_sb);
8399+
1308ab2a 8400+ rdhash = au_sbi(dentry->d_sb)->si_rdhash;
8401+ if (!rdhash)
8402+ rdhash = au_rdhash_est(au_dir_size(/*file*/NULL, dentry));
8403+ err = au_nhash_alloc(&whlist, rdhash, GFP_NOFS);
dece6358 8404+ if (unlikely(err))
1facf9fc 8405+ goto out;
8406+
1facf9fc 8407+ arg.flags = 0;
1308ab2a 8408+ arg.whlist = &whlist;
8409+ bstart = au_dbstart(dentry);
dece6358
AM
8410+ if (au_opt_test(au_mntflags(dentry->d_sb), SHWH))
8411+ au_fset_testempty(arg.flags, SHWH);
1facf9fc 8412+ arg.bindex = bstart;
8413+ err = do_test_empty(dentry, &arg);
8414+ if (unlikely(err))
8415+ goto out_whlist;
8416+
8417+ au_fset_testempty(arg.flags, WHONLY);
8418+ btail = au_dbtaildir(dentry);
8419+ for (bindex = bstart + 1; !err && bindex <= btail; bindex++) {
8420+ struct dentry *h_dentry;
8421+
8422+ h_dentry = au_h_dptr(dentry, bindex);
8423+ if (h_dentry && h_dentry->d_inode) {
8424+ arg.bindex = bindex;
8425+ err = do_test_empty(dentry, &arg);
8426+ }
8427+ }
8428+
4f0767ce 8429+out_whlist:
1308ab2a 8430+ au_nhash_wh_free(&whlist);
4f0767ce 8431+out:
1facf9fc 8432+ return err;
8433+}
8434+
8435+int au_test_empty(struct dentry *dentry, struct au_nhash *whlist)
8436+{
8437+ int err;
8438+ struct test_empty_arg arg;
8439+ aufs_bindex_t bindex, btail;
8440+
8441+ err = 0;
1308ab2a 8442+ arg.whlist = whlist;
1facf9fc 8443+ arg.flags = AuTestEmpty_WHONLY;
dece6358
AM
8444+ if (au_opt_test(au_mntflags(dentry->d_sb), SHWH))
8445+ au_fset_testempty(arg.flags, SHWH);
1facf9fc 8446+ btail = au_dbtaildir(dentry);
8447+ for (bindex = au_dbstart(dentry); !err && bindex <= btail; bindex++) {
8448+ struct dentry *h_dentry;
8449+
8450+ h_dentry = au_h_dptr(dentry, bindex);
8451+ if (h_dentry && h_dentry->d_inode) {
8452+ arg.bindex = bindex;
8453+ err = sio_test_empty(dentry, &arg);
8454+ }
8455+ }
8456+
8457+ return err;
8458+}
8459+
8460+/* ---------------------------------------------------------------------- */
8461+
8462+const struct file_operations aufs_dir_fop = {
4a4d8108 8463+ .owner = THIS_MODULE,
027c5e7a 8464+ .llseek = default_llseek,
1facf9fc 8465+ .read = generic_read_dir,
8466+ .readdir = aufs_readdir,
8467+ .unlocked_ioctl = aufs_ioctl_dir,
b752ccd1
AM
8468+#ifdef CONFIG_COMPAT
8469+ .compat_ioctl = aufs_compat_ioctl_dir,
8470+#endif
1facf9fc 8471+ .open = aufs_open_dir,
8472+ .release = aufs_release_dir,
4a4d8108 8473+ .flush = aufs_flush_dir,
1facf9fc 8474+ .fsync = aufs_fsync_dir
8475+};
7f207e10
AM
8476diff -urN /usr/share/empty/fs/aufs/dir.h linux/fs/aufs/dir.h
8477--- /usr/share/empty/fs/aufs/dir.h 1970-01-01 01:00:00.000000000 +0100
7ce627cf 8478+++ linux/fs/aufs/dir.h 2012-05-22 09:06:08.867458905 +0200
f6c5ef8b 8479@@ -0,0 +1,137 @@
1facf9fc 8480+/*
f6c5ef8b 8481+ * Copyright (C) 2005-2012 Junjiro R. Okajima
1facf9fc 8482+ *
8483+ * This program, aufs is free software; you can redistribute it and/or modify
8484+ * it under the terms of the GNU General Public License as published by
8485+ * the Free Software Foundation; either version 2 of the License, or
8486+ * (at your option) any later version.
dece6358
AM
8487+ *
8488+ * This program is distributed in the hope that it will be useful,
8489+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
8490+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
8491+ * GNU General Public License for more details.
8492+ *
8493+ * You should have received a copy of the GNU General Public License
8494+ * along with this program; if not, write to the Free Software
8495+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 8496+ */
8497+
8498+/*
8499+ * directory operations
8500+ */
8501+
8502+#ifndef __AUFS_DIR_H__
8503+#define __AUFS_DIR_H__
8504+
8505+#ifdef __KERNEL__
8506+
8507+#include <linux/fs.h>
1facf9fc 8508+
8509+/* ---------------------------------------------------------------------- */
8510+
8511+/* need to be faster and smaller */
8512+
8513+struct au_nhash {
dece6358
AM
8514+ unsigned int nh_num;
8515+ struct hlist_head *nh_head;
1facf9fc 8516+};
8517+
8518+struct au_vdir_destr {
8519+ unsigned char len;
8520+ unsigned char name[0];
8521+} __packed;
8522+
8523+struct au_vdir_dehstr {
8524+ struct hlist_node hash;
8525+ struct au_vdir_destr *str;
4a4d8108 8526+} ____cacheline_aligned_in_smp;
1facf9fc 8527+
8528+struct au_vdir_de {
8529+ ino_t de_ino;
8530+ unsigned char de_type;
8531+ /* caution: packed */
8532+ struct au_vdir_destr de_str;
8533+} __packed;
8534+
8535+struct au_vdir_wh {
8536+ struct hlist_node wh_hash;
dece6358
AM
8537+#ifdef CONFIG_AUFS_SHWH
8538+ ino_t wh_ino;
1facf9fc 8539+ aufs_bindex_t wh_bindex;
dece6358
AM
8540+ unsigned char wh_type;
8541+#else
8542+ aufs_bindex_t wh_bindex;
8543+#endif
8544+ /* caution: packed */
1facf9fc 8545+ struct au_vdir_destr wh_str;
8546+} __packed;
8547+
8548+union au_vdir_deblk_p {
8549+ unsigned char *deblk;
8550+ struct au_vdir_de *de;
8551+};
8552+
8553+struct au_vdir {
8554+ unsigned char **vd_deblk;
8555+ unsigned long vd_nblk;
1facf9fc 8556+ struct {
8557+ unsigned long ul;
8558+ union au_vdir_deblk_p p;
8559+ } vd_last;
8560+
8561+ unsigned long vd_version;
dece6358 8562+ unsigned int vd_deblk_sz;
1facf9fc 8563+ unsigned long vd_jiffy;
4a4d8108 8564+} ____cacheline_aligned_in_smp;
1facf9fc 8565+
8566+/* ---------------------------------------------------------------------- */
8567+
8568+/* dir.c */
8569+extern const struct file_operations aufs_dir_fop;
8570+void au_add_nlink(struct inode *dir, struct inode *h_dir);
8571+void au_sub_nlink(struct inode *dir, struct inode *h_dir);
1308ab2a 8572+loff_t au_dir_size(struct file *file, struct dentry *dentry);
1facf9fc 8573+int au_test_empty_lower(struct dentry *dentry);
8574+int au_test_empty(struct dentry *dentry, struct au_nhash *whlist);
8575+
8576+/* vdir.c */
1308ab2a 8577+unsigned int au_rdhash_est(loff_t sz);
dece6358
AM
8578+int au_nhash_alloc(struct au_nhash *nhash, unsigned int num_hash, gfp_t gfp);
8579+void au_nhash_wh_free(struct au_nhash *whlist);
1facf9fc 8580+int au_nhash_test_longer_wh(struct au_nhash *whlist, aufs_bindex_t btgt,
8581+ int limit);
dece6358
AM
8582+int au_nhash_test_known_wh(struct au_nhash *whlist, char *name, int nlen);
8583+int au_nhash_append_wh(struct au_nhash *whlist, char *name, int nlen, ino_t ino,
8584+ unsigned int d_type, aufs_bindex_t bindex,
8585+ unsigned char shwh);
1facf9fc 8586+void au_vdir_free(struct au_vdir *vdir);
8587+int au_vdir_init(struct file *file);
8588+int au_vdir_fill_de(struct file *file, void *dirent, filldir_t filldir);
8589+
8590+/* ioctl.c */
8591+long aufs_ioctl_dir(struct file *file, unsigned int cmd, unsigned long arg);
8592+
1308ab2a 8593+#ifdef CONFIG_AUFS_RDU
8594+/* rdu.c */
8595+long au_rdu_ioctl(struct file *file, unsigned int cmd, unsigned long arg);
b752ccd1
AM
8596+#ifdef CONFIG_COMPAT
8597+long au_rdu_compat_ioctl(struct file *file, unsigned int cmd,
8598+ unsigned long arg);
8599+#endif
1308ab2a 8600+#else
8601+static inline long au_rdu_ioctl(struct file *file, unsigned int cmd,
8602+ unsigned long arg)
8603+{
8604+ return -EINVAL;
8605+}
b752ccd1
AM
8606+#ifdef CONFIG_COMPAT
8607+static inline long au_rdu_compat_ioctl(struct file *file, unsigned int cmd,
8608+ unsigned long arg)
8609+{
8610+ return -EINVAL;
8611+}
8612+#endif
1308ab2a 8613+#endif
8614+
1facf9fc 8615+#endif /* __KERNEL__ */
8616+#endif /* __AUFS_DIR_H__ */
7f207e10
AM
8617diff -urN /usr/share/empty/fs/aufs/dynop.c linux/fs/aufs/dynop.c
8618--- /usr/share/empty/fs/aufs/dynop.c 1970-01-01 01:00:00.000000000 +0100
7ce627cf 8619+++ linux/fs/aufs/dynop.c 2012-05-22 09:06:08.867458905 +0200
2cbb1c4b 8620@@ -0,0 +1,377 @@
1facf9fc 8621+/*
f6c5ef8b 8622+ * Copyright (C) 2010-2012 Junjiro R. Okajima
1facf9fc 8623+ *
8624+ * This program, aufs is free software; you can redistribute it and/or modify
8625+ * it under the terms of the GNU General Public License as published by
8626+ * the Free Software Foundation; either version 2 of the License, or
8627+ * (at your option) any later version.
dece6358
AM
8628+ *
8629+ * This program is distributed in the hope that it will be useful,
8630+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
8631+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
8632+ * GNU General Public License for more details.
8633+ *
8634+ * You should have received a copy of the GNU General Public License
8635+ * along with this program; if not, write to the Free Software
8636+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 8637+ */
8638+
8639+/*
4a4d8108 8640+ * dynamically customizable operations for regular files
1facf9fc 8641+ */
8642+
1facf9fc 8643+#include "aufs.h"
8644+
4a4d8108 8645+#define DyPrSym(key) AuDbgSym(key->dk_op.dy_hop)
1facf9fc 8646+
4a4d8108
AM
8647+/*
8648+ * How large will these lists be?
8649+ * Usually just a few elements, 20-30 at most for each, I guess.
8650+ */
8651+static struct au_splhead dynop[AuDyLast];
8652+
8653+static struct au_dykey *dy_gfind_get(struct au_splhead *spl, const void *h_op)
1facf9fc 8654+{
4a4d8108
AM
8655+ struct au_dykey *key, *tmp;
8656+ struct list_head *head;
1facf9fc 8657+
4a4d8108
AM
8658+ key = NULL;
8659+ head = &spl->head;
8660+ rcu_read_lock();
8661+ list_for_each_entry_rcu(tmp, head, dk_list)
8662+ if (tmp->dk_op.dy_hop == h_op) {
8663+ key = tmp;
8664+ kref_get(&key->dk_kref);
8665+ break;
8666+ }
8667+ rcu_read_unlock();
8668+
8669+ return key;
1facf9fc 8670+}
8671+
4a4d8108 8672+static struct au_dykey *dy_bradd(struct au_branch *br, struct au_dykey *key)
1facf9fc 8673+{
4a4d8108
AM
8674+ struct au_dykey **k, *found;
8675+ const void *h_op = key->dk_op.dy_hop;
8676+ int i;
1facf9fc 8677+
4a4d8108
AM
8678+ found = NULL;
8679+ k = br->br_dykey;
8680+ for (i = 0; i < AuBrDynOp; i++)
8681+ if (k[i]) {
8682+ if (k[i]->dk_op.dy_hop == h_op) {
8683+ found = k[i];
8684+ break;
8685+ }
8686+ } else
8687+ break;
8688+ if (!found) {
8689+ spin_lock(&br->br_dykey_lock);
8690+ for (; i < AuBrDynOp; i++)
8691+ if (k[i]) {
8692+ if (k[i]->dk_op.dy_hop == h_op) {
8693+ found = k[i];
8694+ break;
8695+ }
8696+ } else {
8697+ k[i] = key;
8698+ break;
8699+ }
8700+ spin_unlock(&br->br_dykey_lock);
8701+ BUG_ON(i == AuBrDynOp); /* expand the array */
8702+ }
8703+
8704+ return found;
1facf9fc 8705+}
8706+
4a4d8108
AM
8707+/* kref_get() if @key is already added */
8708+static struct au_dykey *dy_gadd(struct au_splhead *spl, struct au_dykey *key)
8709+{
8710+ struct au_dykey *tmp, *found;
8711+ struct list_head *head;
8712+ const void *h_op = key->dk_op.dy_hop;
1facf9fc 8713+
4a4d8108
AM
8714+ found = NULL;
8715+ head = &spl->head;
8716+ spin_lock(&spl->spin);
8717+ list_for_each_entry(tmp, head, dk_list)
8718+ if (tmp->dk_op.dy_hop == h_op) {
8719+ kref_get(&tmp->dk_kref);
8720+ found = tmp;
8721+ break;
8722+ }
8723+ if (!found)
8724+ list_add_rcu(&key->dk_list, head);
8725+ spin_unlock(&spl->spin);
1facf9fc 8726+
4a4d8108
AM
8727+ if (!found)
8728+ DyPrSym(key);
8729+ return found;
8730+}
8731+
8732+static void dy_free_rcu(struct rcu_head *rcu)
1facf9fc 8733+{
4a4d8108
AM
8734+ struct au_dykey *key;
8735+
8736+ key = container_of(rcu, struct au_dykey, dk_rcu);
8737+ DyPrSym(key);
8738+ kfree(key);
1facf9fc 8739+}
8740+
4a4d8108
AM
8741+static void dy_free(struct kref *kref)
8742+{
8743+ struct au_dykey *key;
8744+ struct au_splhead *spl;
1facf9fc 8745+
4a4d8108
AM
8746+ key = container_of(kref, struct au_dykey, dk_kref);
8747+ spl = dynop + key->dk_op.dy_type;
8748+ au_spl_del_rcu(&key->dk_list, spl);
8749+ call_rcu(&key->dk_rcu, dy_free_rcu);
8750+}
8751+
8752+void au_dy_put(struct au_dykey *key)
1facf9fc 8753+{
4a4d8108
AM
8754+ kref_put(&key->dk_kref, dy_free);
8755+}
1facf9fc 8756+
4a4d8108
AM
8757+/* ---------------------------------------------------------------------- */
8758+
8759+#define DyDbgSize(cnt, op) AuDebugOn(cnt != sizeof(op)/sizeof(void *))
8760+
8761+#ifdef CONFIG_AUFS_DEBUG
8762+#define DyDbgDeclare(cnt) unsigned int cnt = 0
4f0767ce 8763+#define DyDbgInc(cnt) do { cnt++; } while (0)
4a4d8108
AM
8764+#else
8765+#define DyDbgDeclare(cnt) do {} while (0)
8766+#define DyDbgInc(cnt) do {} while (0)
8767+#endif
8768+
8769+#define DySet(func, dst, src, h_op, h_sb) do { \
8770+ DyDbgInc(cnt); \
8771+ if (h_op->func) { \
8772+ if (src.func) \
8773+ dst.func = src.func; \
8774+ else \
8775+ AuDbg("%s %s\n", au_sbtype(h_sb), #func); \
8776+ } \
8777+} while (0)
8778+
8779+#define DySetForce(func, dst, src) do { \
8780+ AuDebugOn(!src.func); \
8781+ DyDbgInc(cnt); \
8782+ dst.func = src.func; \
8783+} while (0)
8784+
8785+#define DySetAop(func) \
8786+ DySet(func, dyaop->da_op, aufs_aop, h_aop, h_sb)
8787+#define DySetAopForce(func) \
8788+ DySetForce(func, dyaop->da_op, aufs_aop)
8789+
8790+static void dy_aop(struct au_dykey *key, const void *h_op,
8791+ struct super_block *h_sb __maybe_unused)
8792+{
8793+ struct au_dyaop *dyaop = (void *)key;
8794+ const struct address_space_operations *h_aop = h_op;
8795+ DyDbgDeclare(cnt);
8796+
8797+ AuDbg("%s\n", au_sbtype(h_sb));
8798+
8799+ DySetAop(writepage);
8800+ DySetAopForce(readpage); /* force */
4a4d8108
AM
8801+ DySetAop(writepages);
8802+ DySetAop(set_page_dirty);
8803+ DySetAop(readpages);
8804+ DySetAop(write_begin);
8805+ DySetAop(write_end);
8806+ DySetAop(bmap);
8807+ DySetAop(invalidatepage);
8808+ DySetAop(releasepage);
027c5e7a 8809+ DySetAop(freepage);
4a4d8108
AM
8810+ /* these two will be changed according to an aufs mount option */
8811+ DySetAop(direct_IO);
8812+ DySetAop(get_xip_mem);
8813+ DySetAop(migratepage);
8814+ DySetAop(launder_page);
8815+ DySetAop(is_partially_uptodate);
8816+ DySetAop(error_remove_page);
8817+
8818+ DyDbgSize(cnt, *h_aop);
8819+ dyaop->da_get_xip_mem = h_aop->get_xip_mem;
8820+}
8821+
4a4d8108
AM
8822+/* ---------------------------------------------------------------------- */
8823+
8824+static void dy_bug(struct kref *kref)
8825+{
8826+ BUG();
8827+}
8828+
8829+static struct au_dykey *dy_get(struct au_dynop *op, struct au_branch *br)
8830+{
8831+ struct au_dykey *key, *old;
8832+ struct au_splhead *spl;
b752ccd1 8833+ struct op {
4a4d8108 8834+ unsigned int sz;
b752ccd1
AM
8835+ void (*set)(struct au_dykey *key, const void *h_op,
8836+ struct super_block *h_sb __maybe_unused);
8837+ };
8838+ static const struct op a[] = {
4a4d8108
AM
8839+ [AuDy_AOP] = {
8840+ .sz = sizeof(struct au_dyaop),
b752ccd1 8841+ .set = dy_aop
4a4d8108 8842+ }
b752ccd1
AM
8843+ };
8844+ const struct op *p;
4a4d8108
AM
8845+
8846+ spl = dynop + op->dy_type;
8847+ key = dy_gfind_get(spl, op->dy_hop);
8848+ if (key)
8849+ goto out_add; /* success */
8850+
8851+ p = a + op->dy_type;
8852+ key = kzalloc(p->sz, GFP_NOFS);
8853+ if (unlikely(!key)) {
8854+ key = ERR_PTR(-ENOMEM);
8855+ goto out;
8856+ }
8857+
8858+ key->dk_op.dy_hop = op->dy_hop;
8859+ kref_init(&key->dk_kref);
b752ccd1 8860+ p->set(key, op->dy_hop, br->br_mnt->mnt_sb);
4a4d8108
AM
8861+ old = dy_gadd(spl, key);
8862+ if (old) {
8863+ kfree(key);
8864+ key = old;
8865+ }
8866+
8867+out_add:
8868+ old = dy_bradd(br, key);
8869+ if (old)
8870+ /* its ref-count should never be zero here */
8871+ kref_put(&key->dk_kref, dy_bug);
8872+out:
8873+ return key;
8874+}
8875+
8876+/* ---------------------------------------------------------------------- */
8877+/*
8878+ * Aufs prohibits O_DIRECT by defaut even if the branch supports it.
8879+ * This behaviour is neccessary to return an error from open(O_DIRECT) instead
8880+ * of the succeeding I/O. The dio mount option enables O_DIRECT and makes
8881+ * open(O_DIRECT) always succeed, but the succeeding I/O may return an error.
8882+ * See the aufs manual in detail.
8883+ *
8884+ * To keep this behaviour, aufs has to set NULL to ->get_xip_mem too, and the
8885+ * performance of fadvise() and madvise() may be affected.
8886+ */
8887+static void dy_adx(struct au_dyaop *dyaop, int do_dx)
8888+{
8889+ if (!do_dx) {
8890+ dyaop->da_op.direct_IO = NULL;
8891+ dyaop->da_op.get_xip_mem = NULL;
8892+ } else {
8893+ dyaop->da_op.direct_IO = aufs_aop.direct_IO;
8894+ dyaop->da_op.get_xip_mem = aufs_aop.get_xip_mem;
8895+ if (!dyaop->da_get_xip_mem)
8896+ dyaop->da_op.get_xip_mem = NULL;
8897+ }
8898+}
8899+
8900+static struct au_dyaop *dy_aget(struct au_branch *br,
8901+ const struct address_space_operations *h_aop,
8902+ int do_dx)
8903+{
8904+ struct au_dyaop *dyaop;
8905+ struct au_dynop op;
8906+
8907+ op.dy_type = AuDy_AOP;
8908+ op.dy_haop = h_aop;
8909+ dyaop = (void *)dy_get(&op, br);
8910+ if (IS_ERR(dyaop))
8911+ goto out;
8912+ dy_adx(dyaop, do_dx);
8913+
8914+out:
8915+ return dyaop;
8916+}
8917+
8918+int au_dy_iaop(struct inode *inode, aufs_bindex_t bindex,
8919+ struct inode *h_inode)
8920+{
8921+ int err, do_dx;
8922+ struct super_block *sb;
8923+ struct au_branch *br;
8924+ struct au_dyaop *dyaop;
8925+
8926+ AuDebugOn(!S_ISREG(h_inode->i_mode));
8927+ IiMustWriteLock(inode);
8928+
8929+ sb = inode->i_sb;
8930+ br = au_sbr(sb, bindex);
8931+ do_dx = !!au_opt_test(au_mntflags(sb), DIO);
8932+ dyaop = dy_aget(br, h_inode->i_mapping->a_ops, do_dx);
8933+ err = PTR_ERR(dyaop);
8934+ if (IS_ERR(dyaop))
8935+ /* unnecessary to call dy_fput() */
8936+ goto out;
8937+
8938+ err = 0;
8939+ inode->i_mapping->a_ops = &dyaop->da_op;
8940+
8941+out:
8942+ return err;
8943+}
8944+
b752ccd1
AM
8945+/*
8946+ * Is it safe to replace a_ops during the inode/file is in operation?
8947+ * Yes, I hope so.
8948+ */
8949+int au_dy_irefresh(struct inode *inode)
8950+{
8951+ int err;
8952+ aufs_bindex_t bstart;
8953+ struct inode *h_inode;
8954+
8955+ err = 0;
8956+ if (S_ISREG(inode->i_mode)) {
8957+ bstart = au_ibstart(inode);
8958+ h_inode = au_h_iptr(inode, bstart);
8959+ err = au_dy_iaop(inode, bstart, h_inode);
8960+ }
8961+ return err;
8962+}
8963+
4a4d8108
AM
8964+void au_dy_arefresh(int do_dx)
8965+{
8966+ struct au_splhead *spl;
8967+ struct list_head *head;
8968+ struct au_dykey *key;
8969+
8970+ spl = dynop + AuDy_AOP;
8971+ head = &spl->head;
8972+ spin_lock(&spl->spin);
8973+ list_for_each_entry(key, head, dk_list)
8974+ dy_adx((void *)key, do_dx);
8975+ spin_unlock(&spl->spin);
8976+}
8977+
4a4d8108
AM
8978+/* ---------------------------------------------------------------------- */
8979+
8980+void __init au_dy_init(void)
8981+{
8982+ int i;
8983+
8984+ /* make sure that 'struct au_dykey *' can be any type */
8985+ BUILD_BUG_ON(offsetof(struct au_dyaop, da_key));
4a4d8108
AM
8986+
8987+ for (i = 0; i < AuDyLast; i++)
8988+ au_spl_init(dynop + i);
8989+}
8990+
8991+void au_dy_fin(void)
8992+{
8993+ int i;
8994+
8995+ for (i = 0; i < AuDyLast; i++)
8996+ WARN_ON(!list_empty(&dynop[i].head));
8997+}
7f207e10
AM
8998diff -urN /usr/share/empty/fs/aufs/dynop.h linux/fs/aufs/dynop.h
8999--- /usr/share/empty/fs/aufs/dynop.h 1970-01-01 01:00:00.000000000 +0100
7ce627cf 9000+++ linux/fs/aufs/dynop.h 2012-05-22 09:06:08.867458905 +0200
f6c5ef8b 9001@@ -0,0 +1,76 @@
4a4d8108 9002+/*
f6c5ef8b 9003+ * Copyright (C) 2010-2012 Junjiro R. Okajima
4a4d8108
AM
9004+ *
9005+ * This program, aufs is free software; you can redistribute it and/or modify
9006+ * it under the terms of the GNU General Public License as published by
9007+ * the Free Software Foundation; either version 2 of the License, or
9008+ * (at your option) any later version.
9009+ *
9010+ * This program is distributed in the hope that it will be useful,
9011+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
9012+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
9013+ * GNU General Public License for more details.
9014+ *
9015+ * You should have received a copy of the GNU General Public License
9016+ * along with this program; if not, write to the Free Software
9017+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
9018+ */
9019+
9020+/*
9021+ * dynamically customizable operations (for regular files only)
9022+ */
9023+
9024+#ifndef __AUFS_DYNOP_H__
9025+#define __AUFS_DYNOP_H__
9026+
9027+#ifdef __KERNEL__
9028+
4a4d8108
AM
9029+#include "inode.h"
9030+
2cbb1c4b 9031+enum {AuDy_AOP, AuDyLast};
4a4d8108
AM
9032+
9033+struct au_dynop {
9034+ int dy_type;
9035+ union {
9036+ const void *dy_hop;
9037+ const struct address_space_operations *dy_haop;
4a4d8108
AM
9038+ };
9039+};
9040+
9041+struct au_dykey {
9042+ union {
9043+ struct list_head dk_list;
9044+ struct rcu_head dk_rcu;
9045+ };
9046+ struct au_dynop dk_op;
9047+
9048+ /*
9049+ * during I am in the branch local array, kref is gotten. when the
9050+ * branch is removed, kref is put.
9051+ */
9052+ struct kref dk_kref;
9053+};
9054+
9055+/* stop unioning since their sizes are very different from each other */
9056+struct au_dyaop {
9057+ struct au_dykey da_key;
9058+ struct address_space_operations da_op; /* not const */
9059+ int (*da_get_xip_mem)(struct address_space *, pgoff_t, int,
9060+ void **, unsigned long *);
9061+};
9062+
4a4d8108
AM
9063+/* ---------------------------------------------------------------------- */
9064+
9065+/* dynop.c */
9066+struct au_branch;
9067+void au_dy_put(struct au_dykey *key);
9068+int au_dy_iaop(struct inode *inode, aufs_bindex_t bindex,
9069+ struct inode *h_inode);
b752ccd1 9070+int au_dy_irefresh(struct inode *inode);
4a4d8108 9071+void au_dy_arefresh(int do_dio);
4a4d8108
AM
9072+
9073+void __init au_dy_init(void);
9074+void au_dy_fin(void);
9075+
4a4d8108
AM
9076+#endif /* __KERNEL__ */
9077+#endif /* __AUFS_DYNOP_H__ */
7f207e10
AM
9078diff -urN /usr/share/empty/fs/aufs/export.c linux/fs/aufs/export.c
9079--- /usr/share/empty/fs/aufs/export.c 1970-01-01 01:00:00.000000000 +0100
7ce627cf 9080+++ linux/fs/aufs/export.c 2012-05-22 09:06:08.867458905 +0200
7eafdf33 9081@@ -0,0 +1,803 @@
4a4d8108 9082+/*
f6c5ef8b 9083+ * Copyright (C) 2005-2012 Junjiro R. Okajima
4a4d8108
AM
9084+ *
9085+ * This program, aufs is free software; you can redistribute it and/or modify
9086+ * it under the terms of the GNU General Public License as published by
9087+ * the Free Software Foundation; either version 2 of the License, or
9088+ * (at your option) any later version.
9089+ *
9090+ * This program is distributed in the hope that it will be useful,
9091+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
9092+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
9093+ * GNU General Public License for more details.
9094+ *
9095+ * You should have received a copy of the GNU General Public License
9096+ * along with this program; if not, write to the Free Software
9097+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
9098+ */
9099+
9100+/*
9101+ * export via nfs
9102+ */
9103+
9104+#include <linux/exportfs.h>
7eafdf33 9105+#include <linux/fs_struct.h>
4a4d8108
AM
9106+#include <linux/namei.h>
9107+#include <linux/nsproxy.h>
9108+#include <linux/random.h>
9109+#include <linux/writeback.h>
7eafdf33 9110+#include "../fs/mount.h"
4a4d8108
AM
9111+#include "aufs.h"
9112+
9113+union conv {
9114+#ifdef CONFIG_AUFS_INO_T_64
9115+ __u32 a[2];
9116+#else
9117+ __u32 a[1];
9118+#endif
9119+ ino_t ino;
9120+};
9121+
9122+static ino_t decode_ino(__u32 *a)
9123+{
9124+ union conv u;
9125+
9126+ BUILD_BUG_ON(sizeof(u.ino) != sizeof(u.a));
9127+ u.a[0] = a[0];
9128+#ifdef CONFIG_AUFS_INO_T_64
9129+ u.a[1] = a[1];
9130+#endif
9131+ return u.ino;
9132+}
9133+
9134+static void encode_ino(__u32 *a, ino_t ino)
9135+{
9136+ union conv u;
9137+
9138+ u.ino = ino;
9139+ a[0] = u.a[0];
9140+#ifdef CONFIG_AUFS_INO_T_64
9141+ a[1] = u.a[1];
9142+#endif
9143+}
9144+
9145+/* NFS file handle */
9146+enum {
9147+ Fh_br_id,
9148+ Fh_sigen,
9149+#ifdef CONFIG_AUFS_INO_T_64
9150+ /* support 64bit inode number */
9151+ Fh_ino1,
9152+ Fh_ino2,
9153+ Fh_dir_ino1,
9154+ Fh_dir_ino2,
9155+#else
9156+ Fh_ino1,
9157+ Fh_dir_ino1,
9158+#endif
9159+ Fh_igen,
9160+ Fh_h_type,
9161+ Fh_tail,
9162+
9163+ Fh_ino = Fh_ino1,
9164+ Fh_dir_ino = Fh_dir_ino1
9165+};
9166+
9167+static int au_test_anon(struct dentry *dentry)
9168+{
027c5e7a 9169+ /* note: read d_flags without d_lock */
4a4d8108
AM
9170+ return !!(dentry->d_flags & DCACHE_DISCONNECTED);
9171+}
9172+
9173+/* ---------------------------------------------------------------------- */
9174+/* inode generation external table */
9175+
b752ccd1 9176+void au_xigen_inc(struct inode *inode)
4a4d8108 9177+{
4a4d8108
AM
9178+ loff_t pos;
9179+ ssize_t sz;
9180+ __u32 igen;
9181+ struct super_block *sb;
9182+ struct au_sbinfo *sbinfo;
9183+
4a4d8108 9184+ sb = inode->i_sb;
b752ccd1 9185+ AuDebugOn(!au_opt_test(au_mntflags(sb), XINO));
1facf9fc 9186+
b752ccd1 9187+ sbinfo = au_sbi(sb);
1facf9fc 9188+ pos = inode->i_ino;
9189+ pos *= sizeof(igen);
9190+ igen = inode->i_generation + 1;
1facf9fc 9191+ sz = xino_fwrite(sbinfo->si_xwrite, sbinfo->si_xigen, &igen,
9192+ sizeof(igen), &pos);
9193+ if (sz == sizeof(igen))
b752ccd1 9194+ return; /* success */
1facf9fc 9195+
b752ccd1 9196+ if (unlikely(sz >= 0))
1facf9fc 9197+ AuIOErr("xigen error (%zd)\n", sz);
1facf9fc 9198+}
9199+
9200+int au_xigen_new(struct inode *inode)
9201+{
9202+ int err;
9203+ loff_t pos;
9204+ ssize_t sz;
9205+ struct super_block *sb;
9206+ struct au_sbinfo *sbinfo;
9207+ struct file *file;
9208+
9209+ err = 0;
9210+ /* todo: dirty, at mount time */
9211+ if (inode->i_ino == AUFS_ROOT_INO)
9212+ goto out;
9213+ sb = inode->i_sb;
dece6358 9214+ SiMustAnyLock(sb);
1facf9fc 9215+ if (unlikely(!au_opt_test(au_mntflags(sb), XINO)))
9216+ goto out;
9217+
9218+ err = -EFBIG;
9219+ pos = inode->i_ino;
9220+ if (unlikely(au_loff_max / sizeof(inode->i_generation) - 1 < pos)) {
9221+ AuIOErr1("too large i%lld\n", pos);
9222+ goto out;
9223+ }
9224+ pos *= sizeof(inode->i_generation);
9225+
9226+ err = 0;
9227+ sbinfo = au_sbi(sb);
9228+ file = sbinfo->si_xigen;
9229+ BUG_ON(!file);
9230+
9231+ if (i_size_read(file->f_dentry->d_inode)
9232+ < pos + sizeof(inode->i_generation)) {
9233+ inode->i_generation = atomic_inc_return(&sbinfo->si_xigen_next);
9234+ sz = xino_fwrite(sbinfo->si_xwrite, file, &inode->i_generation,
9235+ sizeof(inode->i_generation), &pos);
9236+ } else
9237+ sz = xino_fread(sbinfo->si_xread, file, &inode->i_generation,
9238+ sizeof(inode->i_generation), &pos);
9239+ if (sz == sizeof(inode->i_generation))
9240+ goto out; /* success */
9241+
9242+ err = sz;
9243+ if (unlikely(sz >= 0)) {
9244+ err = -EIO;
9245+ AuIOErr("xigen error (%zd)\n", sz);
9246+ }
9247+
4f0767ce 9248+out:
1facf9fc 9249+ return err;
9250+}
9251+
9252+int au_xigen_set(struct super_block *sb, struct file *base)
9253+{
9254+ int err;
9255+ struct au_sbinfo *sbinfo;
9256+ struct file *file;
9257+
dece6358
AM
9258+ SiMustWriteLock(sb);
9259+
1facf9fc 9260+ sbinfo = au_sbi(sb);
9261+ file = au_xino_create2(base, sbinfo->si_xigen);
9262+ err = PTR_ERR(file);
9263+ if (IS_ERR(file))
9264+ goto out;
9265+ err = 0;
9266+ if (sbinfo->si_xigen)
9267+ fput(sbinfo->si_xigen);
9268+ sbinfo->si_xigen = file;
9269+
4f0767ce 9270+out:
1facf9fc 9271+ return err;
9272+}
9273+
9274+void au_xigen_clr(struct super_block *sb)
9275+{
9276+ struct au_sbinfo *sbinfo;
9277+
dece6358
AM
9278+ SiMustWriteLock(sb);
9279+
1facf9fc 9280+ sbinfo = au_sbi(sb);
9281+ if (sbinfo->si_xigen) {
9282+ fput(sbinfo->si_xigen);
9283+ sbinfo->si_xigen = NULL;
9284+ }
9285+}
9286+
9287+/* ---------------------------------------------------------------------- */
9288+
9289+static struct dentry *decode_by_ino(struct super_block *sb, ino_t ino,
9290+ ino_t dir_ino)
9291+{
9292+ struct dentry *dentry, *d;
9293+ struct inode *inode;
9294+ unsigned int sigen;
9295+
9296+ dentry = NULL;
9297+ inode = ilookup(sb, ino);
9298+ if (!inode)
9299+ goto out;
9300+
9301+ dentry = ERR_PTR(-ESTALE);
9302+ sigen = au_sigen(sb);
9303+ if (unlikely(is_bad_inode(inode)
9304+ || IS_DEADDIR(inode)
9305+ || sigen != au_iigen(inode)))
9306+ goto out_iput;
9307+
9308+ dentry = NULL;
9309+ if (!dir_ino || S_ISDIR(inode->i_mode))
9310+ dentry = d_find_alias(inode);
9311+ else {
027c5e7a
AM
9312+ spin_lock(&inode->i_lock);
9313+ list_for_each_entry(d, &inode->i_dentry, d_alias) {
9314+ spin_lock(&d->d_lock);
1facf9fc 9315+ if (!au_test_anon(d)
9316+ && d->d_parent->d_inode->i_ino == dir_ino) {
027c5e7a
AM
9317+ dentry = dget_dlock(d);
9318+ spin_unlock(&d->d_lock);
1facf9fc 9319+ break;
9320+ }
027c5e7a
AM
9321+ spin_unlock(&d->d_lock);
9322+ }
9323+ spin_unlock(&inode->i_lock);
1facf9fc 9324+ }
027c5e7a 9325+ if (unlikely(dentry && au_digen_test(dentry, sigen))) {
2cbb1c4b 9326+ /* need to refresh */
1facf9fc 9327+ dput(dentry);
2cbb1c4b 9328+ dentry = NULL;
1facf9fc 9329+ }
9330+
4f0767ce 9331+out_iput:
1facf9fc 9332+ iput(inode);
4f0767ce 9333+out:
2cbb1c4b 9334+ AuTraceErrPtr(dentry);
1facf9fc 9335+ return dentry;
9336+}
9337+
9338+/* ---------------------------------------------------------------------- */
9339+
9340+/* todo: dirty? */
9341+/* if exportfs_decode_fh() passed vfsmount*, we could be happy */
4a4d8108
AM
9342+
9343+struct au_compare_mnt_args {
9344+ /* input */
9345+ struct super_block *sb;
9346+
9347+ /* output */
9348+ struct vfsmount *mnt;
9349+};
9350+
9351+static int au_compare_mnt(struct vfsmount *mnt, void *arg)
9352+{
9353+ struct au_compare_mnt_args *a = arg;
9354+
9355+ if (mnt->mnt_sb != a->sb)
9356+ return 0;
9357+ a->mnt = mntget(mnt);
9358+ return 1;
9359+}
9360+
1facf9fc 9361+static struct vfsmount *au_mnt_get(struct super_block *sb)
9362+{
4a4d8108 9363+ int err;
7eafdf33 9364+ struct path root;
4a4d8108
AM
9365+ struct au_compare_mnt_args args = {
9366+ .sb = sb
9367+ };
1facf9fc 9368+
7eafdf33 9369+ get_fs_root(current->fs, &root);
0c5527e5 9370+ br_read_lock(vfsmount_lock);
7eafdf33 9371+ err = iterate_mounts(au_compare_mnt, &args, root.mnt);
0c5527e5 9372+ br_read_unlock(vfsmount_lock);
7eafdf33 9373+ path_put(&root);
4a4d8108
AM
9374+ AuDebugOn(!err);
9375+ AuDebugOn(!args.mnt);
9376+ return args.mnt;
1facf9fc 9377+}
9378+
9379+struct au_nfsd_si_lock {
4a4d8108 9380+ unsigned int sigen;
027c5e7a 9381+ aufs_bindex_t bindex, br_id;
1facf9fc 9382+ unsigned char force_lock;
9383+};
9384+
027c5e7a
AM
9385+static int si_nfsd_read_lock(struct super_block *sb,
9386+ struct au_nfsd_si_lock *nsi_lock)
1facf9fc 9387+{
027c5e7a 9388+ int err;
1facf9fc 9389+ aufs_bindex_t bindex;
9390+
9391+ si_read_lock(sb, AuLock_FLUSH);
9392+
9393+ /* branch id may be wrapped around */
027c5e7a 9394+ err = 0;
1facf9fc 9395+ bindex = au_br_index(sb, nsi_lock->br_id);
9396+ if (bindex >= 0 && nsi_lock->sigen + AUFS_BRANCH_MAX > au_sigen(sb))
9397+ goto out; /* success */
9398+
027c5e7a
AM
9399+ err = -ESTALE;
9400+ bindex = -1;
1facf9fc 9401+ if (!nsi_lock->force_lock)
9402+ si_read_unlock(sb);
1facf9fc 9403+
4f0767ce 9404+out:
027c5e7a
AM
9405+ nsi_lock->bindex = bindex;
9406+ return err;
1facf9fc 9407+}
9408+
9409+struct find_name_by_ino {
9410+ int called, found;
9411+ ino_t ino;
9412+ char *name;
9413+ int namelen;
9414+};
9415+
9416+static int
9417+find_name_by_ino(void *arg, const char *name, int namelen, loff_t offset,
9418+ u64 ino, unsigned int d_type)
9419+{
9420+ struct find_name_by_ino *a = arg;
9421+
9422+ a->called++;
9423+ if (a->ino != ino)
9424+ return 0;
9425+
9426+ memcpy(a->name, name, namelen);
9427+ a->namelen = namelen;
9428+ a->found = 1;
9429+ return 1;
9430+}
9431+
9432+static struct dentry *au_lkup_by_ino(struct path *path, ino_t ino,
9433+ struct au_nfsd_si_lock *nsi_lock)
9434+{
9435+ struct dentry *dentry, *parent;
9436+ struct file *file;
9437+ struct inode *dir;
9438+ struct find_name_by_ino arg;
9439+ int err;
9440+
9441+ parent = path->dentry;
9442+ if (nsi_lock)
9443+ si_read_unlock(parent->d_sb);
4a4d8108 9444+ file = vfsub_dentry_open(path, au_dir_roflags);
1facf9fc 9445+ dentry = (void *)file;
9446+ if (IS_ERR(file))
9447+ goto out;
9448+
9449+ dentry = ERR_PTR(-ENOMEM);
4a4d8108 9450+ arg.name = __getname_gfp(GFP_NOFS);
1facf9fc 9451+ if (unlikely(!arg.name))
9452+ goto out_file;
9453+ arg.ino = ino;
9454+ arg.found = 0;
9455+ do {
9456+ arg.called = 0;
9457+ /* smp_mb(); */
9458+ err = vfsub_readdir(file, find_name_by_ino, &arg);
9459+ } while (!err && !arg.found && arg.called);
9460+ dentry = ERR_PTR(err);
9461+ if (unlikely(err))
9462+ goto out_name;
9463+ dentry = ERR_PTR(-ENOENT);
9464+ if (!arg.found)
9465+ goto out_name;
9466+
9467+ /* do not call au_lkup_one() */
9468+ dir = parent->d_inode;
9469+ mutex_lock(&dir->i_mutex);
9470+ dentry = vfsub_lookup_one_len(arg.name, parent, arg.namelen);
9471+ mutex_unlock(&dir->i_mutex);
9472+ AuTraceErrPtr(dentry);
9473+ if (IS_ERR(dentry))
9474+ goto out_name;
9475+ AuDebugOn(au_test_anon(dentry));
9476+ if (unlikely(!dentry->d_inode)) {
9477+ dput(dentry);
9478+ dentry = ERR_PTR(-ENOENT);
9479+ }
9480+
4f0767ce 9481+out_name:
1facf9fc 9482+ __putname(arg.name);
4f0767ce 9483+out_file:
1facf9fc 9484+ fput(file);
4f0767ce 9485+out:
1facf9fc 9486+ if (unlikely(nsi_lock
9487+ && si_nfsd_read_lock(parent->d_sb, nsi_lock) < 0))
9488+ if (!IS_ERR(dentry)) {
9489+ dput(dentry);
9490+ dentry = ERR_PTR(-ESTALE);
9491+ }
9492+ AuTraceErrPtr(dentry);
9493+ return dentry;
9494+}
9495+
9496+static struct dentry *decode_by_dir_ino(struct super_block *sb, ino_t ino,
9497+ ino_t dir_ino,
9498+ struct au_nfsd_si_lock *nsi_lock)
9499+{
9500+ struct dentry *dentry;
9501+ struct path path;
9502+
9503+ if (dir_ino != AUFS_ROOT_INO) {
9504+ path.dentry = decode_by_ino(sb, dir_ino, 0);
9505+ dentry = path.dentry;
9506+ if (!path.dentry || IS_ERR(path.dentry))
9507+ goto out;
9508+ AuDebugOn(au_test_anon(path.dentry));
9509+ } else
9510+ path.dentry = dget(sb->s_root);
9511+
9512+ path.mnt = au_mnt_get(sb);
9513+ dentry = au_lkup_by_ino(&path, ino, nsi_lock);
9514+ path_put(&path);
9515+
4f0767ce 9516+out:
1facf9fc 9517+ AuTraceErrPtr(dentry);
9518+ return dentry;
9519+}
9520+
9521+/* ---------------------------------------------------------------------- */
9522+
9523+static int h_acceptable(void *expv, struct dentry *dentry)
9524+{
9525+ return 1;
9526+}
9527+
9528+static char *au_build_path(struct dentry *h_parent, struct path *h_rootpath,
9529+ char *buf, int len, struct super_block *sb)
9530+{
9531+ char *p;
9532+ int n;
9533+ struct path path;
9534+
9535+ p = d_path(h_rootpath, buf, len);
9536+ if (IS_ERR(p))
9537+ goto out;
9538+ n = strlen(p);
9539+
9540+ path.mnt = h_rootpath->mnt;
9541+ path.dentry = h_parent;
9542+ p = d_path(&path, buf, len);
9543+ if (IS_ERR(p))
9544+ goto out;
9545+ if (n != 1)
9546+ p += n;
9547+
9548+ path.mnt = au_mnt_get(sb);
9549+ path.dentry = sb->s_root;
9550+ p = d_path(&path, buf, len - strlen(p));
9551+ mntput(path.mnt);
9552+ if (IS_ERR(p))
9553+ goto out;
9554+ if (n != 1)
9555+ p[strlen(p)] = '/';
9556+
4f0767ce 9557+out:
1facf9fc 9558+ AuTraceErrPtr(p);
9559+ return p;
9560+}
9561+
9562+static
027c5e7a
AM
9563+struct dentry *decode_by_path(struct super_block *sb, ino_t ino, __u32 *fh,
9564+ int fh_len, struct au_nfsd_si_lock *nsi_lock)
1facf9fc 9565+{
9566+ struct dentry *dentry, *h_parent, *root;
9567+ struct super_block *h_sb;
9568+ char *pathname, *p;
9569+ struct vfsmount *h_mnt;
9570+ struct au_branch *br;
9571+ int err;
9572+ struct path path;
9573+
027c5e7a 9574+ br = au_sbr(sb, nsi_lock->bindex);
1facf9fc 9575+ h_mnt = br->br_mnt;
9576+ h_sb = h_mnt->mnt_sb;
9577+ /* todo: call lower fh_to_dentry()? fh_to_parent()? */
9578+ h_parent = exportfs_decode_fh(h_mnt, (void *)(fh + Fh_tail),
9579+ fh_len - Fh_tail, fh[Fh_h_type],
9580+ h_acceptable, /*context*/NULL);
9581+ dentry = h_parent;
9582+ if (unlikely(!h_parent || IS_ERR(h_parent))) {
9583+ AuWarn1("%s decode_fh failed, %ld\n",
9584+ au_sbtype(h_sb), PTR_ERR(h_parent));
9585+ goto out;
9586+ }
9587+ dentry = NULL;
9588+ if (unlikely(au_test_anon(h_parent))) {
9589+ AuWarn1("%s decode_fh returned a disconnected dentry\n",
9590+ au_sbtype(h_sb));
9591+ goto out_h_parent;
9592+ }
9593+
9594+ dentry = ERR_PTR(-ENOMEM);
9595+ pathname = (void *)__get_free_page(GFP_NOFS);
9596+ if (unlikely(!pathname))
9597+ goto out_h_parent;
9598+
9599+ root = sb->s_root;
9600+ path.mnt = h_mnt;
9601+ di_read_lock_parent(root, !AuLock_IR);
027c5e7a 9602+ path.dentry = au_h_dptr(root, nsi_lock->bindex);
1facf9fc 9603+ di_read_unlock(root, !AuLock_IR);
9604+ p = au_build_path(h_parent, &path, pathname, PAGE_SIZE, sb);
9605+ dentry = (void *)p;
9606+ if (IS_ERR(p))
9607+ goto out_pathname;
9608+
9609+ si_read_unlock(sb);
9610+ err = vfsub_kern_path(p, LOOKUP_FOLLOW | LOOKUP_DIRECTORY, &path);
9611+ dentry = ERR_PTR(err);
9612+ if (unlikely(err))
9613+ goto out_relock;
9614+
9615+ dentry = ERR_PTR(-ENOENT);
9616+ AuDebugOn(au_test_anon(path.dentry));
9617+ if (unlikely(!path.dentry->d_inode))
9618+ goto out_path;
9619+
9620+ if (ino != path.dentry->d_inode->i_ino)
9621+ dentry = au_lkup_by_ino(&path, ino, /*nsi_lock*/NULL);
9622+ else
9623+ dentry = dget(path.dentry);
9624+
4f0767ce 9625+out_path:
1facf9fc 9626+ path_put(&path);
4f0767ce 9627+out_relock:
1facf9fc 9628+ if (unlikely(si_nfsd_read_lock(sb, nsi_lock) < 0))
9629+ if (!IS_ERR(dentry)) {
9630+ dput(dentry);
9631+ dentry = ERR_PTR(-ESTALE);
9632+ }
4f0767ce 9633+out_pathname:
1facf9fc 9634+ free_page((unsigned long)pathname);
4f0767ce 9635+out_h_parent:
1facf9fc 9636+ dput(h_parent);
4f0767ce 9637+out:
1facf9fc 9638+ AuTraceErrPtr(dentry);
9639+ return dentry;
9640+}
9641+
9642+/* ---------------------------------------------------------------------- */
9643+
9644+static struct dentry *
9645+aufs_fh_to_dentry(struct super_block *sb, struct fid *fid, int fh_len,
9646+ int fh_type)
9647+{
9648+ struct dentry *dentry;
9649+ __u32 *fh = fid->raw;
027c5e7a 9650+ struct au_branch *br;
1facf9fc 9651+ ino_t ino, dir_ino;
1facf9fc 9652+ struct au_nfsd_si_lock nsi_lock = {
1facf9fc 9653+ .force_lock = 0
9654+ };
9655+
1facf9fc 9656+ dentry = ERR_PTR(-ESTALE);
4a4d8108
AM
9657+ /* it should never happen, but the file handle is unreliable */
9658+ if (unlikely(fh_len < Fh_tail))
9659+ goto out;
9660+ nsi_lock.sigen = fh[Fh_sigen];
9661+ nsi_lock.br_id = fh[Fh_br_id];
9662+
1facf9fc 9663+ /* branch id may be wrapped around */
027c5e7a
AM
9664+ br = NULL;
9665+ if (unlikely(si_nfsd_read_lock(sb, &nsi_lock)))
1facf9fc 9666+ goto out;
9667+ nsi_lock.force_lock = 1;
9668+
9669+ /* is this inode still cached? */
9670+ ino = decode_ino(fh + Fh_ino);
4a4d8108
AM
9671+ /* it should never happen */
9672+ if (unlikely(ino == AUFS_ROOT_INO))
9673+ goto out;
9674+
1facf9fc 9675+ dir_ino = decode_ino(fh + Fh_dir_ino);
9676+ dentry = decode_by_ino(sb, ino, dir_ino);
9677+ if (IS_ERR(dentry))
9678+ goto out_unlock;
9679+ if (dentry)
9680+ goto accept;
9681+
9682+ /* is the parent dir cached? */
027c5e7a
AM
9683+ br = au_sbr(sb, nsi_lock.bindex);
9684+ atomic_inc(&br->br_count);
1facf9fc 9685+ dentry = decode_by_dir_ino(sb, ino, dir_ino, &nsi_lock);
9686+ if (IS_ERR(dentry))
9687+ goto out_unlock;
9688+ if (dentry)
9689+ goto accept;
9690+
9691+ /* lookup path */
027c5e7a 9692+ dentry = decode_by_path(sb, ino, fh, fh_len, &nsi_lock);
1facf9fc 9693+ if (IS_ERR(dentry))
9694+ goto out_unlock;
9695+ if (unlikely(!dentry))
9696+ /* todo?: make it ESTALE */
9697+ goto out_unlock;
9698+
4f0767ce 9699+accept:
027c5e7a
AM
9700+ if (!au_digen_test(dentry, au_sigen(sb))
9701+ && dentry->d_inode->i_generation == fh[Fh_igen])
1facf9fc 9702+ goto out_unlock; /* success */
9703+
9704+ dput(dentry);
9705+ dentry = ERR_PTR(-ESTALE);
4f0767ce 9706+out_unlock:
027c5e7a
AM
9707+ if (br)
9708+ atomic_dec(&br->br_count);
1facf9fc 9709+ si_read_unlock(sb);
4f0767ce 9710+out:
1facf9fc 9711+ AuTraceErrPtr(dentry);
9712+ return dentry;
9713+}
9714+
9715+#if 0 /* reserved for future use */
9716+/* support subtreecheck option */
9717+static struct dentry *aufs_fh_to_parent(struct super_block *sb, struct fid *fid,
9718+ int fh_len, int fh_type)
9719+{
9720+ struct dentry *parent;
9721+ __u32 *fh = fid->raw;
9722+ ino_t dir_ino;
9723+
9724+ dir_ino = decode_ino(fh + Fh_dir_ino);
9725+ parent = decode_by_ino(sb, dir_ino, 0);
9726+ if (IS_ERR(parent))
9727+ goto out;
9728+ if (!parent)
9729+ parent = decode_by_path(sb, au_br_index(sb, fh[Fh_br_id]),
9730+ dir_ino, fh, fh_len);
9731+
4f0767ce 9732+out:
1facf9fc 9733+ AuTraceErrPtr(parent);
9734+ return parent;
9735+}
9736+#endif
9737+
9738+/* ---------------------------------------------------------------------- */
9739+
9740+static int aufs_encode_fh(struct dentry *dentry, __u32 *fh, int *max_len,
9741+ int connectable)
9742+{
9743+ int err;
9744+ aufs_bindex_t bindex, bend;
9745+ struct super_block *sb, *h_sb;
9746+ struct inode *inode;
9747+ struct dentry *parent, *h_parent;
9748+ struct au_branch *br;
9749+
9750+ AuDebugOn(au_test_anon(dentry));
9751+
9752+ parent = NULL;
9753+ err = -ENOSPC;
9754+ if (unlikely(*max_len <= Fh_tail)) {
9755+ AuWarn1("NFSv2 client (max_len %d)?\n", *max_len);
9756+ goto out;
9757+ }
9758+
9759+ err = FILEID_ROOT;
9760+ if (IS_ROOT(dentry)) {
9761+ AuDebugOn(dentry->d_inode->i_ino != AUFS_ROOT_INO);
9762+ goto out;
9763+ }
9764+
1facf9fc 9765+ h_parent = NULL;
027c5e7a
AM
9766+ err = aufs_read_lock(dentry, AuLock_FLUSH | AuLock_IR | AuLock_GEN);
9767+ if (unlikely(err))
9768+ goto out;
9769+
1facf9fc 9770+ inode = dentry->d_inode;
9771+ AuDebugOn(!inode);
027c5e7a 9772+ sb = dentry->d_sb;
1facf9fc 9773+#ifdef CONFIG_AUFS_DEBUG
9774+ if (unlikely(!au_opt_test(au_mntflags(sb), XINO)))
9775+ AuWarn1("NFS-exporting requires xino\n");
9776+#endif
027c5e7a
AM
9777+ err = -EIO;
9778+ parent = dget_parent(dentry);
9779+ di_read_lock_parent(parent, !AuLock_IR);
1facf9fc 9780+ bend = au_dbtaildir(parent);
9781+ for (bindex = au_dbstart(parent); bindex <= bend; bindex++) {
9782+ h_parent = au_h_dptr(parent, bindex);
9783+ if (h_parent) {
9784+ dget(h_parent);
9785+ break;
9786+ }
9787+ }
9788+ if (unlikely(!h_parent))
9789+ goto out_unlock;
9790+
9791+ err = -EPERM;
9792+ br = au_sbr(sb, bindex);
9793+ h_sb = br->br_mnt->mnt_sb;
9794+ if (unlikely(!h_sb->s_export_op)) {
9795+ AuErr1("%s branch is not exportable\n", au_sbtype(h_sb));
9796+ goto out_dput;
9797+ }
9798+
9799+ fh[Fh_br_id] = br->br_id;
9800+ fh[Fh_sigen] = au_sigen(sb);
9801+ encode_ino(fh + Fh_ino, inode->i_ino);
9802+ encode_ino(fh + Fh_dir_ino, parent->d_inode->i_ino);
9803+ fh[Fh_igen] = inode->i_generation;
9804+
9805+ *max_len -= Fh_tail;
9806+ fh[Fh_h_type] = exportfs_encode_fh(h_parent, (void *)(fh + Fh_tail),
9807+ max_len,
9808+ /*connectable or subtreecheck*/0);
9809+ err = fh[Fh_h_type];
9810+ *max_len += Fh_tail;
9811+ /* todo: macros? */
9812+ if (err != 255)
9813+ err = 99;
9814+ else
9815+ AuWarn1("%s encode_fh failed\n", au_sbtype(h_sb));
9816+
4f0767ce 9817+out_dput:
1facf9fc 9818+ dput(h_parent);
4f0767ce 9819+out_unlock:
1facf9fc 9820+ di_read_unlock(parent, !AuLock_IR);
9821+ dput(parent);
9822+ aufs_read_unlock(dentry, AuLock_IR);
4f0767ce 9823+out:
1facf9fc 9824+ if (unlikely(err < 0))
9825+ err = 255;
9826+ return err;
9827+}
9828+
9829+/* ---------------------------------------------------------------------- */
9830+
4a4d8108
AM
9831+static int aufs_commit_metadata(struct inode *inode)
9832+{
9833+ int err;
9834+ aufs_bindex_t bindex;
9835+ struct super_block *sb;
9836+ struct inode *h_inode;
9837+ int (*f)(struct inode *inode);
9838+
9839+ sb = inode->i_sb;
e49829fe 9840+ si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLMW);
4a4d8108
AM
9841+ ii_write_lock_child(inode);
9842+ bindex = au_ibstart(inode);
9843+ AuDebugOn(bindex < 0);
9844+ h_inode = au_h_iptr(inode, bindex);
9845+
9846+ f = h_inode->i_sb->s_export_op->commit_metadata;
9847+ if (f)
9848+ err = f(h_inode);
9849+ else {
9850+ struct writeback_control wbc = {
9851+ .sync_mode = WB_SYNC_ALL,
9852+ .nr_to_write = 0 /* metadata only */
9853+ };
9854+
9855+ err = sync_inode(h_inode, &wbc);
9856+ }
9857+
9858+ au_cpup_attr_timesizes(inode);
9859+ ii_write_unlock(inode);
9860+ si_read_unlock(sb);
9861+ return err;
9862+}
9863+
9864+/* ---------------------------------------------------------------------- */
9865+
1facf9fc 9866+static struct export_operations aufs_export_op = {
4a4d8108 9867+ .fh_to_dentry = aufs_fh_to_dentry,
1facf9fc 9868+ /* .fh_to_parent = aufs_fh_to_parent, */
4a4d8108
AM
9869+ .encode_fh = aufs_encode_fh,
9870+ .commit_metadata = aufs_commit_metadata
1facf9fc 9871+};
9872+
9873+void au_export_init(struct super_block *sb)
9874+{
9875+ struct au_sbinfo *sbinfo;
9876+ __u32 u;
9877+
9878+ sb->s_export_op = &aufs_export_op;
9879+ sbinfo = au_sbi(sb);
9880+ sbinfo->si_xigen = NULL;
9881+ get_random_bytes(&u, sizeof(u));
9882+ BUILD_BUG_ON(sizeof(u) != sizeof(int));
9883+ atomic_set(&sbinfo->si_xigen_next, u);
9884+}
7f207e10
AM
9885diff -urN /usr/share/empty/fs/aufs/file.c linux/fs/aufs/file.c
9886--- /usr/share/empty/fs/aufs/file.c 1970-01-01 01:00:00.000000000 +0100
7ce627cf 9887+++ linux/fs/aufs/file.c 2012-05-22 09:06:08.867458905 +0200
7eafdf33 9888@@ -0,0 +1,676 @@
1facf9fc 9889+/*
f6c5ef8b 9890+ * Copyright (C) 2005-2012 Junjiro R. Okajima
1facf9fc 9891+ *
9892+ * This program, aufs is free software; you can redistribute it and/or modify
9893+ * it under the terms of the GNU General Public License as published by
9894+ * the Free Software Foundation; either version 2 of the License, or
9895+ * (at your option) any later version.
dece6358
AM
9896+ *
9897+ * This program is distributed in the hope that it will be useful,
9898+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
9899+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
9900+ * GNU General Public License for more details.
9901+ *
9902+ * You should have received a copy of the GNU General Public License
9903+ * along with this program; if not, write to the Free Software
9904+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 9905+ */
9906+
9907+/*
4a4d8108 9908+ * handling file/dir, and address_space operation
1facf9fc 9909+ */
9910+
7eafdf33
AM
9911+#ifdef CONFIG_AUFS_DEBUG
9912+#include <linux/migrate.h>
9913+#endif
4a4d8108 9914+#include <linux/pagemap.h>
1facf9fc 9915+#include "aufs.h"
9916+
4a4d8108
AM
9917+/* drop flags for writing */
9918+unsigned int au_file_roflags(unsigned int flags)
9919+{
9920+ flags &= ~(O_WRONLY | O_RDWR | O_APPEND | O_CREAT | O_TRUNC);
9921+ flags |= O_RDONLY | O_NOATIME;
9922+ return flags;
9923+}
9924+
9925+/* common functions to regular file and dir */
9926+struct file *au_h_open(struct dentry *dentry, aufs_bindex_t bindex, int flags,
9927+ struct file *file)
1facf9fc 9928+{
1308ab2a 9929+ struct file *h_file;
4a4d8108
AM
9930+ struct dentry *h_dentry;
9931+ struct inode *h_inode;
9932+ struct super_block *sb;
9933+ struct au_branch *br;
9934+ struct path h_path;
9935+ int err, exec_flag;
1facf9fc 9936+
4a4d8108
AM
9937+ /* a race condition can happen between open and unlink/rmdir */
9938+ h_file = ERR_PTR(-ENOENT);
9939+ h_dentry = au_h_dptr(dentry, bindex);
b752ccd1 9940+ if (au_test_nfsd() && !h_dentry)
4a4d8108
AM
9941+ goto out;
9942+ h_inode = h_dentry->d_inode;
b752ccd1 9943+ if (au_test_nfsd() && !h_inode)
4a4d8108 9944+ goto out;
027c5e7a
AM
9945+ spin_lock(&h_dentry->d_lock);
9946+ err = (!d_unhashed(dentry) && d_unlinked(h_dentry))
9947+ || !h_inode
9948+ /* || !dentry->d_inode->i_nlink */
9949+ ;
9950+ spin_unlock(&h_dentry->d_lock);
9951+ if (unlikely(err))
4a4d8108 9952+ goto out;
1facf9fc 9953+
4a4d8108
AM
9954+ sb = dentry->d_sb;
9955+ br = au_sbr(sb, bindex);
9956+ h_file = ERR_PTR(-EACCES);
2cbb1c4b 9957+ exec_flag = flags & __FMODE_EXEC;
4a4d8108 9958+ if (exec_flag && (br->br_mnt->mnt_flags & MNT_NOEXEC))
027c5e7a 9959+ goto out;
1facf9fc 9960+
4a4d8108
AM
9961+ /* drop flags for writing */
9962+ if (au_test_ro(sb, bindex, dentry->d_inode))
9963+ flags = au_file_roflags(flags);
9964+ flags &= ~O_CREAT;
9965+ atomic_inc(&br->br_count);
9966+ h_path.dentry = h_dentry;
9967+ h_path.mnt = br->br_mnt;
9968+ if (!au_special_file(h_inode->i_mode))
9969+ h_file = vfsub_dentry_open(&h_path, flags);
9970+ else {
9971+ /* this block depends upon the configuration */
9972+ di_read_unlock(dentry, AuLock_IR);
9973+ fi_write_unlock(file);
9974+ si_read_unlock(sb);
9975+ h_file = vfsub_dentry_open(&h_path, flags);
9976+ si_noflush_read_lock(sb);
9977+ fi_write_lock(file);
9978+ di_read_lock_child(dentry, AuLock_IR);
dece6358 9979+ }
4a4d8108
AM
9980+ if (IS_ERR(h_file))
9981+ goto out_br;
dece6358 9982+
4a4d8108
AM
9983+ if (exec_flag) {
9984+ err = deny_write_access(h_file);
9985+ if (unlikely(err)) {
9986+ fput(h_file);
9987+ h_file = ERR_PTR(err);
9988+ goto out_br;
9989+ }
9990+ }
953406b4 9991+ fsnotify_open(h_file);
4a4d8108 9992+ goto out; /* success */
1facf9fc 9993+
4f0767ce 9994+out_br:
4a4d8108 9995+ atomic_dec(&br->br_count);
4f0767ce 9996+out:
4a4d8108
AM
9997+ return h_file;
9998+}
1308ab2a 9999+
4a4d8108
AM
10000+int au_do_open(struct file *file, int (*open)(struct file *file, int flags),
10001+ struct au_fidir *fidir)
1facf9fc 10002+{
dece6358 10003+ int err;
1facf9fc 10004+ struct dentry *dentry;
1308ab2a 10005+
4a4d8108
AM
10006+ err = au_finfo_init(file, fidir);
10007+ if (unlikely(err))
10008+ goto out;
1facf9fc 10009+
10010+ dentry = file->f_dentry;
4a4d8108
AM
10011+ di_read_lock_child(dentry, AuLock_IR);
10012+ err = open(file, vfsub_file_flags(file));
10013+ di_read_unlock(dentry, AuLock_IR);
1facf9fc 10014+
4a4d8108
AM
10015+ fi_write_unlock(file);
10016+ if (unlikely(err)) {
10017+ au_fi(file)->fi_hdir = NULL;
10018+ au_finfo_fin(file);
1308ab2a 10019+ }
4a4d8108 10020+
4f0767ce 10021+out:
1308ab2a 10022+ return err;
10023+}
dece6358 10024+
4a4d8108 10025+int au_reopen_nondir(struct file *file)
1308ab2a 10026+{
4a4d8108
AM
10027+ int err;
10028+ aufs_bindex_t bstart;
10029+ struct dentry *dentry;
10030+ struct file *h_file, *h_file_tmp;
1308ab2a 10031+
4a4d8108
AM
10032+ dentry = file->f_dentry;
10033+ AuDebugOn(au_special_file(dentry->d_inode->i_mode));
10034+ bstart = au_dbstart(dentry);
10035+ h_file_tmp = NULL;
10036+ if (au_fbstart(file) == bstart) {
10037+ h_file = au_hf_top(file);
10038+ if (file->f_mode == h_file->f_mode)
10039+ return 0; /* success */
10040+ h_file_tmp = h_file;
10041+ get_file(h_file_tmp);
10042+ au_set_h_fptr(file, bstart, NULL);
10043+ }
10044+ AuDebugOn(au_fi(file)->fi_hdir);
10045+ AuDebugOn(au_fbstart(file) < bstart);
1308ab2a 10046+
4a4d8108
AM
10047+ h_file = au_h_open(dentry, bstart, vfsub_file_flags(file) & ~O_TRUNC,
10048+ file);
10049+ err = PTR_ERR(h_file);
10050+ if (IS_ERR(h_file))
10051+ goto out; /* todo: close all? */
10052+
10053+ err = 0;
10054+ au_set_fbstart(file, bstart);
10055+ au_set_h_fptr(file, bstart, h_file);
10056+ au_update_figen(file);
10057+ /* todo: necessary? */
10058+ /* file->f_ra = h_file->f_ra; */
10059+
4f0767ce 10060+out:
4a4d8108
AM
10061+ if (h_file_tmp)
10062+ fput(h_file_tmp);
10063+ return err;
1facf9fc 10064+}
10065+
1308ab2a 10066+/* ---------------------------------------------------------------------- */
10067+
4a4d8108
AM
10068+static int au_reopen_wh(struct file *file, aufs_bindex_t btgt,
10069+ struct dentry *hi_wh)
1facf9fc 10070+{
4a4d8108
AM
10071+ int err;
10072+ aufs_bindex_t bstart;
10073+ struct au_dinfo *dinfo;
10074+ struct dentry *h_dentry;
10075+ struct au_hdentry *hdp;
1facf9fc 10076+
4a4d8108
AM
10077+ dinfo = au_di(file->f_dentry);
10078+ AuRwMustWriteLock(&dinfo->di_rwsem);
dece6358 10079+
4a4d8108
AM
10080+ bstart = dinfo->di_bstart;
10081+ dinfo->di_bstart = btgt;
10082+ hdp = dinfo->di_hdentry;
10083+ h_dentry = hdp[0 + btgt].hd_dentry;
10084+ hdp[0 + btgt].hd_dentry = hi_wh;
10085+ err = au_reopen_nondir(file);
10086+ hdp[0 + btgt].hd_dentry = h_dentry;
10087+ dinfo->di_bstart = bstart;
1facf9fc 10088+
1facf9fc 10089+ return err;
10090+}
10091+
4a4d8108
AM
10092+static int au_ready_to_write_wh(struct file *file, loff_t len,
10093+ aufs_bindex_t bcpup)
1facf9fc 10094+{
4a4d8108 10095+ int err;
027c5e7a
AM
10096+ struct inode *inode, *h_inode;
10097+ struct dentry *dentry, *h_dentry, *hi_wh;
1facf9fc 10098+
dece6358 10099+ dentry = file->f_dentry;
4a4d8108 10100+ au_update_dbstart(dentry);
dece6358 10101+ inode = dentry->d_inode;
027c5e7a
AM
10102+ h_inode = NULL;
10103+ if (au_dbstart(dentry) <= bcpup && au_dbend(dentry) >= bcpup) {
10104+ h_dentry = au_h_dptr(dentry, bcpup);
10105+ if (h_dentry)
10106+ h_inode = h_dentry->d_inode;
10107+ }
4a4d8108 10108+ hi_wh = au_hi_wh(inode, bcpup);
027c5e7a 10109+ if (!hi_wh && !h_inode)
4a4d8108
AM
10110+ err = au_sio_cpup_wh(dentry, bcpup, len, file);
10111+ else
10112+ /* already copied-up after unlink */
10113+ err = au_reopen_wh(file, bcpup, hi_wh);
1facf9fc 10114+
4a4d8108
AM
10115+ if (!err
10116+ && inode->i_nlink > 1
10117+ && au_opt_test(au_mntflags(dentry->d_sb), PLINK))
10118+ au_plink_append(inode, bcpup, au_h_dptr(dentry, bcpup));
1308ab2a 10119+
dece6358 10120+ return err;
1facf9fc 10121+}
10122+
4a4d8108
AM
10123+/*
10124+ * prepare the @file for writing.
10125+ */
10126+int au_ready_to_write(struct file *file, loff_t len, struct au_pin *pin)
1facf9fc 10127+{
4a4d8108 10128+ int err;
027c5e7a 10129+ aufs_bindex_t bstart, bcpup, dbstart;
4a4d8108
AM
10130+ struct dentry *dentry, *parent, *h_dentry;
10131+ struct inode *h_inode, *inode;
1facf9fc 10132+ struct super_block *sb;
4a4d8108 10133+ struct file *h_file;
1facf9fc 10134+
10135+ dentry = file->f_dentry;
1facf9fc 10136+ sb = dentry->d_sb;
4a4d8108
AM
10137+ inode = dentry->d_inode;
10138+ AuDebugOn(au_special_file(inode->i_mode));
10139+ bstart = au_fbstart(file);
10140+ err = au_test_ro(sb, bstart, inode);
10141+ if (!err && (au_hf_top(file)->f_mode & FMODE_WRITE)) {
10142+ err = au_pin(pin, dentry, bstart, AuOpt_UDBA_NONE, /*flags*/0);
1facf9fc 10143+ goto out;
4a4d8108 10144+ }
1facf9fc 10145+
027c5e7a 10146+ /* need to cpup or reopen */
4a4d8108
AM
10147+ parent = dget_parent(dentry);
10148+ di_write_lock_parent(parent);
10149+ err = AuWbrCopyup(au_sbi(sb), dentry);
10150+ bcpup = err;
10151+ if (unlikely(err < 0))
10152+ goto out_dgrade;
10153+ err = 0;
10154+
027c5e7a 10155+ if (!d_unhashed(dentry) && !au_h_dptr(parent, bcpup)) {
4a4d8108 10156+ err = au_cpup_dirs(dentry, bcpup);
1facf9fc 10157+ if (unlikely(err))
4a4d8108
AM
10158+ goto out_dgrade;
10159+ }
10160+
10161+ err = au_pin(pin, dentry, bcpup, AuOpt_UDBA_NONE,
10162+ AuPin_DI_LOCKED | AuPin_MNT_WRITE);
10163+ if (unlikely(err))
10164+ goto out_dgrade;
10165+
10166+ h_dentry = au_hf_top(file)->f_dentry;
10167+ h_inode = h_dentry->d_inode;
027c5e7a
AM
10168+ dbstart = au_dbstart(dentry);
10169+ if (dbstart <= bcpup) {
10170+ h_dentry = au_h_dptr(dentry, bcpup);
10171+ AuDebugOn(!h_dentry);
10172+ h_inode = h_dentry->d_inode;
10173+ AuDebugOn(!h_inode);
10174+ bstart = bcpup;
10175+ }
10176+
10177+ if (dbstart <= bcpup /* just reopen */
10178+ || !d_unhashed(dentry) /* copyup and reopen */
10179+ ) {
10180+ mutex_lock_nested(&h_inode->i_mutex, AuLsc_I_CHILD);
10181+ h_file = au_h_open_pre(dentry, bstart);
10182+ if (IS_ERR(h_file)) {
10183+ err = PTR_ERR(h_file);
10184+ h_file = NULL;
10185+ } else {
10186+ di_downgrade_lock(parent, AuLock_IR);
10187+ if (dbstart > bcpup)
10188+ err = au_sio_cpup_simple(dentry, bcpup, len,
10189+ AuCpup_DTIME);
10190+ if (!err)
10191+ err = au_reopen_nondir(file);
10192+ }
10193+ mutex_unlock(&h_inode->i_mutex);
10194+ au_h_open_post(dentry, bstart, h_file);
10195+ } else { /* copyup as wh and reopen */
10196+ /*
10197+ * since writable hfsplus branch is not supported,
10198+ * h_open_pre/post() are unnecessary.
10199+ */
10200+ mutex_lock_nested(&h_inode->i_mutex, AuLsc_I_CHILD);
4a4d8108
AM
10201+ err = au_ready_to_write_wh(file, len, bcpup);
10202+ di_downgrade_lock(parent, AuLock_IR);
027c5e7a 10203+ mutex_unlock(&h_inode->i_mutex);
4a4d8108 10204+ }
4a4d8108
AM
10205+
10206+ if (!err) {
10207+ au_pin_set_parent_lflag(pin, /*lflag*/0);
10208+ goto out_dput; /* success */
10209+ }
10210+ au_unpin(pin);
10211+ goto out_unlock;
1facf9fc 10212+
4f0767ce 10213+out_dgrade:
4a4d8108 10214+ di_downgrade_lock(parent, AuLock_IR);
4f0767ce 10215+out_unlock:
4a4d8108 10216+ di_read_unlock(parent, AuLock_IR);
4f0767ce 10217+out_dput:
4a4d8108 10218+ dput(parent);
4f0767ce 10219+out:
1facf9fc 10220+ return err;
10221+}
10222+
4a4d8108
AM
10223+/* ---------------------------------------------------------------------- */
10224+
10225+int au_do_flush(struct file *file, fl_owner_t id,
10226+ int (*flush)(struct file *file, fl_owner_t id))
1facf9fc 10227+{
4a4d8108 10228+ int err;
1308ab2a 10229+ struct dentry *dentry;
1facf9fc 10230+ struct super_block *sb;
4a4d8108 10231+ struct inode *inode;
1facf9fc 10232+
1facf9fc 10233+ dentry = file->f_dentry;
10234+ sb = dentry->d_sb;
dece6358 10235+ inode = dentry->d_inode;
4a4d8108
AM
10236+ si_noflush_read_lock(sb);
10237+ fi_read_lock(file);
b752ccd1 10238+ ii_read_lock_child(inode);
1facf9fc 10239+
4a4d8108
AM
10240+ err = flush(file, id);
10241+ au_cpup_attr_timesizes(inode);
1facf9fc 10242+
b752ccd1 10243+ ii_read_unlock(inode);
4a4d8108 10244+ fi_read_unlock(file);
1308ab2a 10245+ si_read_unlock(sb);
dece6358 10246+ return err;
1facf9fc 10247+}
10248+
4a4d8108
AM
10249+/* ---------------------------------------------------------------------- */
10250+
10251+static int au_file_refresh_by_inode(struct file *file, int *need_reopen)
1facf9fc 10252+{
4a4d8108
AM
10253+ int err;
10254+ aufs_bindex_t bstart;
10255+ struct au_pin pin;
10256+ struct au_finfo *finfo;
10257+ struct dentry *dentry, *parent, *hi_wh;
10258+ struct inode *inode;
1facf9fc 10259+ struct super_block *sb;
10260+
4a4d8108
AM
10261+ FiMustWriteLock(file);
10262+
10263+ err = 0;
10264+ finfo = au_fi(file);
1308ab2a 10265+ dentry = file->f_dentry;
10266+ sb = dentry->d_sb;
4a4d8108
AM
10267+ inode = dentry->d_inode;
10268+ bstart = au_ibstart(inode);
027c5e7a 10269+ if (bstart == finfo->fi_btop || IS_ROOT(dentry))
1308ab2a 10270+ goto out;
dece6358 10271+
4a4d8108
AM
10272+ parent = dget_parent(dentry);
10273+ if (au_test_ro(sb, bstart, inode)) {
10274+ di_read_lock_parent(parent, !AuLock_IR);
10275+ err = AuWbrCopyup(au_sbi(sb), dentry);
10276+ bstart = err;
10277+ di_read_unlock(parent, !AuLock_IR);
10278+ if (unlikely(err < 0))
10279+ goto out_parent;
10280+ err = 0;
1facf9fc 10281+ }
1facf9fc 10282+
4a4d8108
AM
10283+ di_read_lock_parent(parent, AuLock_IR);
10284+ hi_wh = au_hi_wh(inode, bstart);
7f207e10
AM
10285+ if (!S_ISDIR(inode->i_mode)
10286+ && au_opt_test(au_mntflags(sb), PLINK)
4a4d8108
AM
10287+ && au_plink_test(inode)
10288+ && !d_unhashed(dentry)) {
10289+ err = au_test_and_cpup_dirs(dentry, bstart);
10290+ if (unlikely(err))
10291+ goto out_unlock;
10292+
10293+ /* always superio. */
10294+ err = au_pin(&pin, dentry, bstart, AuOpt_UDBA_NONE,
10295+ AuPin_DI_LOCKED | AuPin_MNT_WRITE);
10296+ if (!err)
10297+ err = au_sio_cpup_simple(dentry, bstart, -1,
10298+ AuCpup_DTIME);
10299+ au_unpin(&pin);
10300+ } else if (hi_wh) {
10301+ /* already copied-up after unlink */
10302+ err = au_reopen_wh(file, bstart, hi_wh);
10303+ *need_reopen = 0;
10304+ }
1facf9fc 10305+
4f0767ce 10306+out_unlock:
4a4d8108 10307+ di_read_unlock(parent, AuLock_IR);
4f0767ce 10308+out_parent:
4a4d8108 10309+ dput(parent);
4f0767ce 10310+out:
1308ab2a 10311+ return err;
dece6358 10312+}
1facf9fc 10313+
4a4d8108 10314+static void au_do_refresh_dir(struct file *file)
dece6358 10315+{
4a4d8108
AM
10316+ aufs_bindex_t bindex, bend, new_bindex, brid;
10317+ struct au_hfile *p, tmp, *q;
10318+ struct au_finfo *finfo;
1308ab2a 10319+ struct super_block *sb;
4a4d8108 10320+ struct au_fidir *fidir;
1facf9fc 10321+
4a4d8108 10322+ FiMustWriteLock(file);
1facf9fc 10323+
4a4d8108
AM
10324+ sb = file->f_dentry->d_sb;
10325+ finfo = au_fi(file);
10326+ fidir = finfo->fi_hdir;
10327+ AuDebugOn(!fidir);
10328+ p = fidir->fd_hfile + finfo->fi_btop;
10329+ brid = p->hf_br->br_id;
10330+ bend = fidir->fd_bbot;
10331+ for (bindex = finfo->fi_btop; bindex <= bend; bindex++, p++) {
10332+ if (!p->hf_file)
10333+ continue;
1308ab2a 10334+
4a4d8108
AM
10335+ new_bindex = au_br_index(sb, p->hf_br->br_id);
10336+ if (new_bindex == bindex)
10337+ continue;
10338+ if (new_bindex < 0) {
10339+ au_set_h_fptr(file, bindex, NULL);
10340+ continue;
10341+ }
1308ab2a 10342+
4a4d8108
AM
10343+ /* swap two lower inode, and loop again */
10344+ q = fidir->fd_hfile + new_bindex;
10345+ tmp = *q;
10346+ *q = *p;
10347+ *p = tmp;
10348+ if (tmp.hf_file) {
10349+ bindex--;
10350+ p--;
10351+ }
10352+ }
1308ab2a 10353+
4a4d8108 10354+ p = fidir->fd_hfile;
027c5e7a 10355+ if (!au_test_mmapped(file) && !d_unlinked(file->f_dentry)) {
4a4d8108
AM
10356+ bend = au_sbend(sb);
10357+ for (finfo->fi_btop = 0; finfo->fi_btop <= bend;
10358+ finfo->fi_btop++, p++)
10359+ if (p->hf_file) {
10360+ if (p->hf_file->f_dentry
10361+ && p->hf_file->f_dentry->d_inode)
10362+ break;
10363+ else
10364+ au_hfput(p, file);
10365+ }
10366+ } else {
10367+ bend = au_br_index(sb, brid);
10368+ for (finfo->fi_btop = 0; finfo->fi_btop < bend;
10369+ finfo->fi_btop++, p++)
10370+ if (p->hf_file)
10371+ au_hfput(p, file);
10372+ bend = au_sbend(sb);
10373+ }
1308ab2a 10374+
4a4d8108
AM
10375+ p = fidir->fd_hfile + bend;
10376+ for (fidir->fd_bbot = bend; fidir->fd_bbot >= finfo->fi_btop;
10377+ fidir->fd_bbot--, p--)
10378+ if (p->hf_file) {
10379+ if (p->hf_file->f_dentry
10380+ && p->hf_file->f_dentry->d_inode)
10381+ break;
10382+ else
10383+ au_hfput(p, file);
10384+ }
10385+ AuDebugOn(fidir->fd_bbot < finfo->fi_btop);
1308ab2a 10386+}
10387+
4a4d8108
AM
10388+/*
10389+ * after branch manipulating, refresh the file.
10390+ */
10391+static int refresh_file(struct file *file, int (*reopen)(struct file *file))
1facf9fc 10392+{
4a4d8108
AM
10393+ int err, need_reopen;
10394+ aufs_bindex_t bend, bindex;
10395+ struct dentry *dentry;
1308ab2a 10396+ struct au_finfo *finfo;
4a4d8108 10397+ struct au_hfile *hfile;
1facf9fc 10398+
4a4d8108 10399+ dentry = file->f_dentry;
1308ab2a 10400+ finfo = au_fi(file);
4a4d8108
AM
10401+ if (!finfo->fi_hdir) {
10402+ hfile = &finfo->fi_htop;
10403+ AuDebugOn(!hfile->hf_file);
10404+ bindex = au_br_index(dentry->d_sb, hfile->hf_br->br_id);
10405+ AuDebugOn(bindex < 0);
10406+ if (bindex != finfo->fi_btop)
10407+ au_set_fbstart(file, bindex);
10408+ } else {
10409+ err = au_fidir_realloc(finfo, au_sbend(dentry->d_sb) + 1);
10410+ if (unlikely(err))
10411+ goto out;
10412+ au_do_refresh_dir(file);
10413+ }
1facf9fc 10414+
4a4d8108
AM
10415+ err = 0;
10416+ need_reopen = 1;
10417+ if (!au_test_mmapped(file))
10418+ err = au_file_refresh_by_inode(file, &need_reopen);
027c5e7a 10419+ if (!err && need_reopen && !d_unlinked(dentry))
4a4d8108
AM
10420+ err = reopen(file);
10421+ if (!err) {
10422+ au_update_figen(file);
10423+ goto out; /* success */
10424+ }
10425+
10426+ /* error, close all lower files */
10427+ if (finfo->fi_hdir) {
10428+ bend = au_fbend_dir(file);
10429+ for (bindex = au_fbstart(file); bindex <= bend; bindex++)
10430+ au_set_h_fptr(file, bindex, NULL);
10431+ }
1facf9fc 10432+
4f0767ce 10433+out:
1facf9fc 10434+ return err;
10435+}
10436+
4a4d8108
AM
10437+/* common function to regular file and dir */
10438+int au_reval_and_lock_fdi(struct file *file, int (*reopen)(struct file *file),
10439+ int wlock)
dece6358 10440+{
1308ab2a 10441+ int err;
4a4d8108
AM
10442+ unsigned int sigen, figen;
10443+ aufs_bindex_t bstart;
10444+ unsigned char pseudo_link;
10445+ struct dentry *dentry;
10446+ struct inode *inode;
1facf9fc 10447+
4a4d8108
AM
10448+ err = 0;
10449+ dentry = file->f_dentry;
10450+ inode = dentry->d_inode;
10451+ AuDebugOn(au_special_file(inode->i_mode));
10452+ sigen = au_sigen(dentry->d_sb);
10453+ fi_write_lock(file);
10454+ figen = au_figen(file);
10455+ di_write_lock_child(dentry);
10456+ bstart = au_dbstart(dentry);
10457+ pseudo_link = (bstart != au_ibstart(inode));
10458+ if (sigen == figen && !pseudo_link && au_fbstart(file) == bstart) {
10459+ if (!wlock) {
10460+ di_downgrade_lock(dentry, AuLock_IR);
10461+ fi_downgrade_lock(file);
10462+ }
10463+ goto out; /* success */
10464+ }
dece6358 10465+
4a4d8108 10466+ AuDbg("sigen %d, figen %d\n", sigen, figen);
027c5e7a 10467+ if (au_digen_test(dentry, sigen)) {
4a4d8108 10468+ err = au_reval_dpath(dentry, sigen);
027c5e7a 10469+ AuDebugOn(!err && au_digen_test(dentry, sigen));
4a4d8108 10470+ }
dece6358 10471+
027c5e7a
AM
10472+ if (!err)
10473+ err = refresh_file(file, reopen);
4a4d8108
AM
10474+ if (!err) {
10475+ if (!wlock) {
10476+ di_downgrade_lock(dentry, AuLock_IR);
10477+ fi_downgrade_lock(file);
10478+ }
10479+ } else {
10480+ di_write_unlock(dentry);
10481+ fi_write_unlock(file);
10482+ }
1facf9fc 10483+
4f0767ce 10484+out:
1308ab2a 10485+ return err;
10486+}
1facf9fc 10487+
4a4d8108
AM
10488+/* ---------------------------------------------------------------------- */
10489+
10490+/* cf. aufs_nopage() */
10491+/* for madvise(2) */
10492+static int aufs_readpage(struct file *file __maybe_unused, struct page *page)
1308ab2a 10493+{
4a4d8108
AM
10494+ unlock_page(page);
10495+ return 0;
10496+}
1facf9fc 10497+
4a4d8108
AM
10498+/* it will never be called, but necessary to support O_DIRECT */
10499+static ssize_t aufs_direct_IO(int rw, struct kiocb *iocb,
10500+ const struct iovec *iov, loff_t offset,
10501+ unsigned long nr_segs)
10502+{ BUG(); return 0; }
1facf9fc 10503+
4a4d8108
AM
10504+/*
10505+ * it will never be called, but madvise and fadvise behaves differently
10506+ * when get_xip_mem is defined
10507+ */
10508+static int aufs_get_xip_mem(struct address_space *mapping, pgoff_t pgoff,
10509+ int create, void **kmem, unsigned long *pfn)
10510+{ BUG(); return 0; }
1facf9fc 10511+
4a4d8108
AM
10512+/* they will never be called. */
10513+#ifdef CONFIG_AUFS_DEBUG
10514+static int aufs_write_begin(struct file *file, struct address_space *mapping,
10515+ loff_t pos, unsigned len, unsigned flags,
10516+ struct page **pagep, void **fsdata)
10517+{ AuUnsupport(); return 0; }
10518+static int aufs_write_end(struct file *file, struct address_space *mapping,
10519+ loff_t pos, unsigned len, unsigned copied,
10520+ struct page *page, void *fsdata)
10521+{ AuUnsupport(); return 0; }
10522+static int aufs_writepage(struct page *page, struct writeback_control *wbc)
10523+{ AuUnsupport(); return 0; }
1308ab2a 10524+
4a4d8108
AM
10525+static int aufs_set_page_dirty(struct page *page)
10526+{ AuUnsupport(); return 0; }
10527+static void aufs_invalidatepage(struct page *page, unsigned long offset)
10528+{ AuUnsupport(); }
10529+static int aufs_releasepage(struct page *page, gfp_t gfp)
10530+{ AuUnsupport(); return 0; }
10531+static int aufs_migratepage(struct address_space *mapping, struct page *newpage,
7eafdf33 10532+ struct page *page, enum migrate_mode mode)
4a4d8108
AM
10533+{ AuUnsupport(); return 0; }
10534+static int aufs_launder_page(struct page *page)
10535+{ AuUnsupport(); return 0; }
10536+static int aufs_is_partially_uptodate(struct page *page,
10537+ read_descriptor_t *desc,
10538+ unsigned long from)
10539+{ AuUnsupport(); return 0; }
10540+static int aufs_error_remove_page(struct address_space *mapping,
10541+ struct page *page)
10542+{ AuUnsupport(); return 0; }
10543+#endif /* CONFIG_AUFS_DEBUG */
10544+
10545+const struct address_space_operations aufs_aop = {
10546+ .readpage = aufs_readpage,
10547+ .direct_IO = aufs_direct_IO,
10548+ .get_xip_mem = aufs_get_xip_mem,
10549+#ifdef CONFIG_AUFS_DEBUG
10550+ .writepage = aufs_writepage,
4a4d8108
AM
10551+ /* no writepages, because of writepage */
10552+ .set_page_dirty = aufs_set_page_dirty,
10553+ /* no readpages, because of readpage */
10554+ .write_begin = aufs_write_begin,
10555+ .write_end = aufs_write_end,
10556+ /* no bmap, no block device */
10557+ .invalidatepage = aufs_invalidatepage,
10558+ .releasepage = aufs_releasepage,
10559+ .migratepage = aufs_migratepage,
10560+ .launder_page = aufs_launder_page,
10561+ .is_partially_uptodate = aufs_is_partially_uptodate,
10562+ .error_remove_page = aufs_error_remove_page
10563+#endif /* CONFIG_AUFS_DEBUG */
dece6358 10564+};
7f207e10
AM
10565diff -urN /usr/share/empty/fs/aufs/file.h linux/fs/aufs/file.h
10566--- /usr/share/empty/fs/aufs/file.h 1970-01-01 01:00:00.000000000 +0100
7ce627cf 10567+++ linux/fs/aufs/file.h 2012-05-22 09:06:08.867458905 +0200
f6c5ef8b 10568@@ -0,0 +1,298 @@
4a4d8108 10569+/*
f6c5ef8b 10570+ * Copyright (C) 2005-2012 Junjiro R. Okajima
4a4d8108
AM
10571+ *
10572+ * This program, aufs is free software; you can redistribute it and/or modify
10573+ * it under the terms of the GNU General Public License as published by
10574+ * the Free Software Foundation; either version 2 of the License, or
10575+ * (at your option) any later version.
10576+ *
10577+ * This program is distributed in the hope that it will be useful,
10578+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
10579+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10580+ * GNU General Public License for more details.
10581+ *
10582+ * You should have received a copy of the GNU General Public License
10583+ * along with this program; if not, write to the Free Software
10584+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
10585+ */
1facf9fc 10586+
4a4d8108
AM
10587+/*
10588+ * file operations
10589+ */
1facf9fc 10590+
4a4d8108
AM
10591+#ifndef __AUFS_FILE_H__
10592+#define __AUFS_FILE_H__
1facf9fc 10593+
4a4d8108 10594+#ifdef __KERNEL__
1facf9fc 10595+
2cbb1c4b 10596+#include <linux/file.h>
4a4d8108
AM
10597+#include <linux/fs.h>
10598+#include <linux/poll.h>
4a4d8108 10599+#include "rwsem.h"
1facf9fc 10600+
4a4d8108
AM
10601+struct au_branch;
10602+struct au_hfile {
10603+ struct file *hf_file;
10604+ struct au_branch *hf_br;
10605+};
1facf9fc 10606+
4a4d8108
AM
10607+struct au_vdir;
10608+struct au_fidir {
10609+ aufs_bindex_t fd_bbot;
10610+ aufs_bindex_t fd_nent;
10611+ struct au_vdir *fd_vdir_cache;
10612+ struct au_hfile fd_hfile[];
10613+};
1facf9fc 10614+
4a4d8108 10615+static inline int au_fidir_sz(int nent)
dece6358 10616+{
4f0767ce
JR
10617+ AuDebugOn(nent < 0);
10618+ return sizeof(struct au_fidir) + sizeof(struct au_hfile) * nent;
4a4d8108 10619+}
1facf9fc 10620+
4a4d8108
AM
10621+struct au_finfo {
10622+ atomic_t fi_generation;
dece6358 10623+
4a4d8108
AM
10624+ struct au_rwsem fi_rwsem;
10625+ aufs_bindex_t fi_btop;
10626+
10627+ /* do not union them */
10628+ struct { /* for non-dir */
10629+ struct au_hfile fi_htop;
2cbb1c4b 10630+ atomic_t fi_mmapped;
4a4d8108
AM
10631+ };
10632+ struct au_fidir *fi_hdir; /* for dir only */
10633+} ____cacheline_aligned_in_smp;
1facf9fc 10634+
4a4d8108 10635+/* ---------------------------------------------------------------------- */
1facf9fc 10636+
4a4d8108
AM
10637+/* file.c */
10638+extern const struct address_space_operations aufs_aop;
10639+unsigned int au_file_roflags(unsigned int flags);
10640+struct file *au_h_open(struct dentry *dentry, aufs_bindex_t bindex, int flags,
10641+ struct file *file);
10642+int au_do_open(struct file *file, int (*open)(struct file *file, int flags),
10643+ struct au_fidir *fidir);
10644+int au_reopen_nondir(struct file *file);
10645+struct au_pin;
10646+int au_ready_to_write(struct file *file, loff_t len, struct au_pin *pin);
10647+int au_reval_and_lock_fdi(struct file *file, int (*reopen)(struct file *file),
10648+ int wlock);
10649+int au_do_flush(struct file *file, fl_owner_t id,
10650+ int (*flush)(struct file *file, fl_owner_t id));
1facf9fc 10651+
4a4d8108
AM
10652+/* poll.c */
10653+#ifdef CONFIG_AUFS_POLL
10654+unsigned int aufs_poll(struct file *file, poll_table *wait);
10655+#endif
1facf9fc 10656+
4a4d8108
AM
10657+#ifdef CONFIG_AUFS_BR_HFSPLUS
10658+/* hfsplus.c */
10659+struct file *au_h_open_pre(struct dentry *dentry, aufs_bindex_t bindex);
10660+void au_h_open_post(struct dentry *dentry, aufs_bindex_t bindex,
10661+ struct file *h_file);
10662+#else
10663+static inline
10664+struct file *au_h_open_pre(struct dentry *dentry, aufs_bindex_t bindex)
dece6358 10665+{
4a4d8108
AM
10666+ return NULL;
10667+}
1facf9fc 10668+
4a4d8108
AM
10669+AuStubVoid(au_h_open_post, struct dentry *dentry, aufs_bindex_t bindex,
10670+ struct file *h_file);
10671+#endif
1facf9fc 10672+
4a4d8108
AM
10673+/* f_op.c */
10674+extern const struct file_operations aufs_file_fop;
4a4d8108
AM
10675+int au_do_open_nondir(struct file *file, int flags);
10676+int aufs_release_nondir(struct inode *inode __maybe_unused, struct file *file);
10677+
10678+#ifdef CONFIG_AUFS_SP_IATTR
10679+/* f_op_sp.c */
10680+int au_special_file(umode_t mode);
10681+void au_init_special_fop(struct inode *inode, umode_t mode, dev_t rdev);
10682+#else
10683+AuStubInt0(au_special_file, umode_t mode)
10684+static inline void au_init_special_fop(struct inode *inode, umode_t mode,
10685+ dev_t rdev)
10686+{
10687+ init_special_inode(inode, mode, rdev);
10688+}
10689+#endif
1facf9fc 10690+
4a4d8108
AM
10691+/* finfo.c */
10692+void au_hfput(struct au_hfile *hf, struct file *file);
10693+void au_set_h_fptr(struct file *file, aufs_bindex_t bindex,
10694+ struct file *h_file);
1facf9fc 10695+
4a4d8108 10696+void au_update_figen(struct file *file);
4a4d8108
AM
10697+struct au_fidir *au_fidir_alloc(struct super_block *sb);
10698+int au_fidir_realloc(struct au_finfo *finfo, int nbr);
1facf9fc 10699+
4a4d8108
AM
10700+void au_fi_init_once(void *_fi);
10701+void au_finfo_fin(struct file *file);
10702+int au_finfo_init(struct file *file, struct au_fidir *fidir);
1facf9fc 10703+
4a4d8108
AM
10704+/* ioctl.c */
10705+long aufs_ioctl_nondir(struct file *file, unsigned int cmd, unsigned long arg);
b752ccd1
AM
10706+#ifdef CONFIG_COMPAT
10707+long aufs_compat_ioctl_dir(struct file *file, unsigned int cmd,
10708+ unsigned long arg);
10709+#endif
1facf9fc 10710+
4a4d8108 10711+/* ---------------------------------------------------------------------- */
1facf9fc 10712+
4a4d8108
AM
10713+static inline struct au_finfo *au_fi(struct file *file)
10714+{
10715+ return file->private_data;
10716+}
1facf9fc 10717+
4a4d8108 10718+/* ---------------------------------------------------------------------- */
1facf9fc 10719+
4a4d8108
AM
10720+/*
10721+ * fi_read_lock, fi_write_lock,
10722+ * fi_read_unlock, fi_write_unlock, fi_downgrade_lock
10723+ */
10724+AuSimpleRwsemFuncs(fi, struct file *f, &au_fi(f)->fi_rwsem);
1308ab2a 10725+
4a4d8108
AM
10726+#define FiMustNoWaiters(f) AuRwMustNoWaiters(&au_fi(f)->fi_rwsem)
10727+#define FiMustAnyLock(f) AuRwMustAnyLock(&au_fi(f)->fi_rwsem)
10728+#define FiMustWriteLock(f) AuRwMustWriteLock(&au_fi(f)->fi_rwsem)
1facf9fc 10729+
1308ab2a 10730+/* ---------------------------------------------------------------------- */
10731+
4a4d8108
AM
10732+/* todo: hard/soft set? */
10733+static inline aufs_bindex_t au_fbstart(struct file *file)
dece6358 10734+{
4a4d8108
AM
10735+ FiMustAnyLock(file);
10736+ return au_fi(file)->fi_btop;
10737+}
dece6358 10738+
4a4d8108
AM
10739+static inline aufs_bindex_t au_fbend_dir(struct file *file)
10740+{
10741+ FiMustAnyLock(file);
10742+ AuDebugOn(!au_fi(file)->fi_hdir);
10743+ return au_fi(file)->fi_hdir->fd_bbot;
10744+}
1facf9fc 10745+
4a4d8108
AM
10746+static inline struct au_vdir *au_fvdir_cache(struct file *file)
10747+{
10748+ FiMustAnyLock(file);
10749+ AuDebugOn(!au_fi(file)->fi_hdir);
10750+ return au_fi(file)->fi_hdir->fd_vdir_cache;
10751+}
1facf9fc 10752+
4a4d8108
AM
10753+static inline void au_set_fbstart(struct file *file, aufs_bindex_t bindex)
10754+{
10755+ FiMustWriteLock(file);
10756+ au_fi(file)->fi_btop = bindex;
10757+}
1facf9fc 10758+
4a4d8108
AM
10759+static inline void au_set_fbend_dir(struct file *file, aufs_bindex_t bindex)
10760+{
10761+ FiMustWriteLock(file);
10762+ AuDebugOn(!au_fi(file)->fi_hdir);
10763+ au_fi(file)->fi_hdir->fd_bbot = bindex;
10764+}
1308ab2a 10765+
4a4d8108
AM
10766+static inline void au_set_fvdir_cache(struct file *file,
10767+ struct au_vdir *vdir_cache)
10768+{
10769+ FiMustWriteLock(file);
10770+ AuDebugOn(!au_fi(file)->fi_hdir);
10771+ au_fi(file)->fi_hdir->fd_vdir_cache = vdir_cache;
10772+}
dece6358 10773+
4a4d8108
AM
10774+static inline struct file *au_hf_top(struct file *file)
10775+{
10776+ FiMustAnyLock(file);
10777+ AuDebugOn(au_fi(file)->fi_hdir);
10778+ return au_fi(file)->fi_htop.hf_file;
10779+}
1facf9fc 10780+
4a4d8108
AM
10781+static inline struct file *au_hf_dir(struct file *file, aufs_bindex_t bindex)
10782+{
10783+ FiMustAnyLock(file);
10784+ AuDebugOn(!au_fi(file)->fi_hdir);
10785+ return au_fi(file)->fi_hdir->fd_hfile[0 + bindex].hf_file;
dece6358
AM
10786+}
10787+
4a4d8108
AM
10788+/* todo: memory barrier? */
10789+static inline unsigned int au_figen(struct file *f)
dece6358 10790+{
4a4d8108
AM
10791+ return atomic_read(&au_fi(f)->fi_generation);
10792+}
dece6358 10793+
2cbb1c4b
JR
10794+static inline void au_set_mmapped(struct file *f)
10795+{
10796+ if (atomic_inc_return(&au_fi(f)->fi_mmapped))
10797+ return;
10798+ pr_warning("fi_mmapped wrapped around\n");
10799+ while (!atomic_inc_return(&au_fi(f)->fi_mmapped))
10800+ ;
10801+}
10802+
10803+static inline void au_unset_mmapped(struct file *f)
10804+{
10805+ atomic_dec(&au_fi(f)->fi_mmapped);
10806+}
10807+
4a4d8108
AM
10808+static inline int au_test_mmapped(struct file *f)
10809+{
2cbb1c4b
JR
10810+ return atomic_read(&au_fi(f)->fi_mmapped);
10811+}
10812+
10813+/* customize vma->vm_file */
10814+
10815+static inline void au_do_vm_file_reset(struct vm_area_struct *vma,
10816+ struct file *file)
10817+{
53392da6
AM
10818+ struct file *f;
10819+
10820+ f = vma->vm_file;
2cbb1c4b
JR
10821+ get_file(file);
10822+ vma->vm_file = file;
53392da6 10823+ fput(f);
2cbb1c4b
JR
10824+}
10825+
10826+#ifdef CONFIG_MMU
10827+#define AuDbgVmRegion(file, vma) do {} while (0)
10828+
10829+static inline void au_vm_file_reset(struct vm_area_struct *vma,
10830+ struct file *file)
10831+{
10832+ au_do_vm_file_reset(vma, file);
10833+}
10834+#else
10835+#define AuDbgVmRegion(file, vma) \
10836+ AuDebugOn((vma)->vm_region && (vma)->vm_region->vm_file != (file))
10837+
10838+static inline void au_vm_file_reset(struct vm_area_struct *vma,
10839+ struct file *file)
10840+{
53392da6
AM
10841+ struct file *f;
10842+
2cbb1c4b 10843+ au_do_vm_file_reset(vma, file);
53392da6 10844+ f = vma->vm_region->vm_file;
2cbb1c4b
JR
10845+ get_file(file);
10846+ vma->vm_region->vm_file = file;
53392da6 10847+ fput(f);
2cbb1c4b
JR
10848+}
10849+#endif /* CONFIG_MMU */
10850+
10851+/* handle vma->vm_prfile */
10852+static inline void au_vm_prfile_set(struct vm_area_struct *vma,
10853+ struct file *file)
10854+{
10855+#ifdef CONFIG_AUFS_PROC_MAP
10856+ get_file(file);
10857+ vma->vm_prfile = file;
10858+#ifndef CONFIG_MMU
10859+ get_file(file);
10860+ vma->vm_region->vm_prfile = file;
10861+#endif
10862+#endif
4a4d8108 10863+}
1308ab2a 10864+
4a4d8108
AM
10865+#endif /* __KERNEL__ */
10866+#endif /* __AUFS_FILE_H__ */
7f207e10
AM
10867diff -urN /usr/share/empty/fs/aufs/finfo.c linux/fs/aufs/finfo.c
10868--- /usr/share/empty/fs/aufs/finfo.c 1970-01-01 01:00:00.000000000 +0100
7ce627cf 10869+++ linux/fs/aufs/finfo.c 2012-05-22 09:06:08.867458905 +0200
f6c5ef8b 10870@@ -0,0 +1,156 @@
4a4d8108 10871+/*
f6c5ef8b 10872+ * Copyright (C) 2005-2012 Junjiro R. Okajima
4a4d8108
AM
10873+ *
10874+ * This program, aufs is free software; you can redistribute it and/or modify
10875+ * it under the terms of the GNU General Public License as published by
10876+ * the Free Software Foundation; either version 2 of the License, or
10877+ * (at your option) any later version.
10878+ *
10879+ * This program is distributed in the hope that it will be useful,
10880+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
10881+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10882+ * GNU General Public License for more details.
10883+ *
10884+ * You should have received a copy of the GNU General Public License
10885+ * along with this program; if not, write to the Free Software
10886+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
10887+ */
1308ab2a 10888+
4a4d8108
AM
10889+/*
10890+ * file private data
10891+ */
1facf9fc 10892+
4a4d8108 10893+#include "aufs.h"
1facf9fc 10894+
4a4d8108
AM
10895+void au_hfput(struct au_hfile *hf, struct file *file)
10896+{
10897+ /* todo: direct access f_flags */
2cbb1c4b 10898+ if (vfsub_file_flags(file) & __FMODE_EXEC)
4a4d8108
AM
10899+ allow_write_access(hf->hf_file);
10900+ fput(hf->hf_file);
10901+ hf->hf_file = NULL;
e49829fe 10902+ atomic_dec(&hf->hf_br->br_count);
4a4d8108
AM
10903+ hf->hf_br = NULL;
10904+}
1facf9fc 10905+
4a4d8108
AM
10906+void au_set_h_fptr(struct file *file, aufs_bindex_t bindex, struct file *val)
10907+{
10908+ struct au_finfo *finfo = au_fi(file);
10909+ struct au_hfile *hf;
10910+ struct au_fidir *fidir;
10911+
10912+ fidir = finfo->fi_hdir;
10913+ if (!fidir) {
10914+ AuDebugOn(finfo->fi_btop != bindex);
10915+ hf = &finfo->fi_htop;
10916+ } else
10917+ hf = fidir->fd_hfile + bindex;
10918+
10919+ if (hf && hf->hf_file)
10920+ au_hfput(hf, file);
10921+ if (val) {
10922+ FiMustWriteLock(file);
10923+ hf->hf_file = val;
10924+ hf->hf_br = au_sbr(file->f_dentry->d_sb, bindex);
1308ab2a 10925+ }
4a4d8108 10926+}
1facf9fc 10927+
4a4d8108
AM
10928+void au_update_figen(struct file *file)
10929+{
10930+ atomic_set(&au_fi(file)->fi_generation, au_digen(file->f_dentry));
10931+ /* smp_mb(); */ /* atomic_set */
1facf9fc 10932+}
10933+
4a4d8108
AM
10934+/* ---------------------------------------------------------------------- */
10935+
4a4d8108
AM
10936+struct au_fidir *au_fidir_alloc(struct super_block *sb)
10937+{
10938+ struct au_fidir *fidir;
10939+ int nbr;
10940+
10941+ nbr = au_sbend(sb) + 1;
10942+ if (nbr < 2)
10943+ nbr = 2; /* initial allocate for 2 branches */
10944+ fidir = kzalloc(au_fidir_sz(nbr), GFP_NOFS);
10945+ if (fidir) {
10946+ fidir->fd_bbot = -1;
10947+ fidir->fd_nent = nbr;
10948+ fidir->fd_vdir_cache = NULL;
10949+ }
10950+
10951+ return fidir;
10952+}
10953+
10954+int au_fidir_realloc(struct au_finfo *finfo, int nbr)
10955+{
10956+ int err;
10957+ struct au_fidir *fidir, *p;
10958+
10959+ AuRwMustWriteLock(&finfo->fi_rwsem);
10960+ fidir = finfo->fi_hdir;
10961+ AuDebugOn(!fidir);
10962+
10963+ err = -ENOMEM;
10964+ p = au_kzrealloc(fidir, au_fidir_sz(fidir->fd_nent), au_fidir_sz(nbr),
10965+ GFP_NOFS);
10966+ if (p) {
10967+ p->fd_nent = nbr;
10968+ finfo->fi_hdir = p;
10969+ err = 0;
10970+ }
1facf9fc 10971+
dece6358 10972+ return err;
1facf9fc 10973+}
1308ab2a 10974+
10975+/* ---------------------------------------------------------------------- */
10976+
4a4d8108 10977+void au_finfo_fin(struct file *file)
1308ab2a 10978+{
4a4d8108
AM
10979+ struct au_finfo *finfo;
10980+
7f207e10
AM
10981+ au_nfiles_dec(file->f_dentry->d_sb);
10982+
4a4d8108
AM
10983+ finfo = au_fi(file);
10984+ AuDebugOn(finfo->fi_hdir);
10985+ AuRwDestroy(&finfo->fi_rwsem);
10986+ au_cache_free_finfo(finfo);
1308ab2a 10987+}
1308ab2a 10988+
e49829fe 10989+void au_fi_init_once(void *_finfo)
4a4d8108 10990+{
e49829fe 10991+ struct au_finfo *finfo = _finfo;
2cbb1c4b 10992+ static struct lock_class_key aufs_fi;
1308ab2a 10993+
e49829fe
JR
10994+ au_rw_init(&finfo->fi_rwsem);
10995+ au_rw_class(&finfo->fi_rwsem, &aufs_fi);
4a4d8108 10996+}
1308ab2a 10997+
4a4d8108
AM
10998+int au_finfo_init(struct file *file, struct au_fidir *fidir)
10999+{
9dbd164d 11000+ int err, lc_idx;
4a4d8108
AM
11001+ struct au_finfo *finfo;
11002+ struct dentry *dentry;
11003+
11004+ err = -ENOMEM;
11005+ dentry = file->f_dentry;
11006+ finfo = au_cache_alloc_finfo();
11007+ if (unlikely(!finfo))
11008+ goto out;
11009+
11010+ err = 0;
7f207e10 11011+ au_nfiles_inc(dentry->d_sb);
9dbd164d
AM
11012+ lc_idx = AuLcNonDir_FIINFO;
11013+ if (fidir)
11014+ lc_idx = AuLcDir_FIINFO;
11015+ au_rw_class(&finfo->fi_rwsem, au_lc_key + lc_idx);
4a4d8108
AM
11016+ au_rw_write_lock(&finfo->fi_rwsem);
11017+ finfo->fi_btop = -1;
11018+ finfo->fi_hdir = fidir;
11019+ atomic_set(&finfo->fi_generation, au_digen(dentry));
11020+ /* smp_mb(); */ /* atomic_set */
11021+
11022+ file->private_data = finfo;
11023+
11024+out:
11025+ return err;
11026+}
7f207e10
AM
11027diff -urN /usr/share/empty/fs/aufs/f_op.c linux/fs/aufs/f_op.c
11028--- /usr/share/empty/fs/aufs/f_op.c 1970-01-01 01:00:00.000000000 +0100
7ce627cf 11029+++ linux/fs/aufs/f_op.c 2012-05-22 09:06:08.867458905 +0200
f6c5ef8b 11030@@ -0,0 +1,729 @@
dece6358 11031+/*
f6c5ef8b 11032+ * Copyright (C) 2005-2012 Junjiro R. Okajima
dece6358
AM
11033+ *
11034+ * This program, aufs is free software; you can redistribute it and/or modify
11035+ * it under the terms of the GNU General Public License as published by
11036+ * the Free Software Foundation; either version 2 of the License, or
11037+ * (at your option) any later version.
11038+ *
11039+ * This program is distributed in the hope that it will be useful,
11040+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
11041+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11042+ * GNU General Public License for more details.
11043+ *
11044+ * You should have received a copy of the GNU General Public License
11045+ * along with this program; if not, write to the Free Software
11046+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
11047+ */
1facf9fc 11048+
11049+/*
4a4d8108 11050+ * file and vm operations
1facf9fc 11051+ */
dece6358 11052+
4a4d8108
AM
11053+#include <linux/fs_stack.h>
11054+#include <linux/mman.h>
4a4d8108 11055+#include <linux/security.h>
dece6358
AM
11056+#include "aufs.h"
11057+
4a4d8108 11058+int au_do_open_nondir(struct file *file, int flags)
1facf9fc 11059+{
4a4d8108
AM
11060+ int err;
11061+ aufs_bindex_t bindex;
11062+ struct file *h_file;
11063+ struct dentry *dentry;
11064+ struct au_finfo *finfo;
11065+
11066+ FiMustWriteLock(file);
11067+
4a4d8108 11068+ dentry = file->f_dentry;
027c5e7a
AM
11069+ err = au_d_alive(dentry);
11070+ if (unlikely(err))
11071+ goto out;
11072+
4a4d8108
AM
11073+ finfo = au_fi(file);
11074+ memset(&finfo->fi_htop, 0, sizeof(finfo->fi_htop));
2cbb1c4b 11075+ atomic_set(&finfo->fi_mmapped, 0);
4a4d8108
AM
11076+ bindex = au_dbstart(dentry);
11077+ h_file = au_h_open(dentry, bindex, flags, file);
11078+ if (IS_ERR(h_file))
11079+ err = PTR_ERR(h_file);
11080+ else {
11081+ au_set_fbstart(file, bindex);
11082+ au_set_h_fptr(file, bindex, h_file);
11083+ au_update_figen(file);
11084+ /* todo: necessary? */
11085+ /* file->f_ra = h_file->f_ra; */
11086+ }
027c5e7a
AM
11087+
11088+out:
4a4d8108 11089+ return err;
1facf9fc 11090+}
11091+
4a4d8108
AM
11092+static int aufs_open_nondir(struct inode *inode __maybe_unused,
11093+ struct file *file)
1facf9fc 11094+{
4a4d8108 11095+ int err;
1308ab2a 11096+ struct super_block *sb;
1facf9fc 11097+
2cbb1c4b 11098+ AuDbg("%.*s, f_flags 0x%x, f_mode 0x%x\n",
4a4d8108
AM
11099+ AuDLNPair(file->f_dentry), vfsub_file_flags(file),
11100+ file->f_mode);
1facf9fc 11101+
4a4d8108
AM
11102+ sb = file->f_dentry->d_sb;
11103+ si_read_lock(sb, AuLock_FLUSH);
11104+ err = au_do_open(file, au_do_open_nondir, /*fidir*/NULL);
11105+ si_read_unlock(sb);
11106+ return err;
11107+}
1facf9fc 11108+
4a4d8108
AM
11109+int aufs_release_nondir(struct inode *inode __maybe_unused, struct file *file)
11110+{
11111+ struct au_finfo *finfo;
11112+ aufs_bindex_t bindex;
1facf9fc 11113+
4a4d8108
AM
11114+ finfo = au_fi(file);
11115+ bindex = finfo->fi_btop;
0c5527e5
AM
11116+ if (bindex >= 0) {
11117+ /* remove me from sb->s_files */
11118+ file_sb_list_del(file);
4a4d8108 11119+ au_set_h_fptr(file, bindex, NULL);
0c5527e5 11120+ }
7f207e10 11121+
4a4d8108
AM
11122+ au_finfo_fin(file);
11123+ return 0;
1facf9fc 11124+}
11125+
4a4d8108
AM
11126+/* ---------------------------------------------------------------------- */
11127+
11128+static int au_do_flush_nondir(struct file *file, fl_owner_t id)
dece6358 11129+{
1308ab2a 11130+ int err;
4a4d8108
AM
11131+ struct file *h_file;
11132+
11133+ err = 0;
11134+ h_file = au_hf_top(file);
11135+ if (h_file)
11136+ err = vfsub_flush(h_file, id);
11137+ return err;
11138+}
11139+
11140+static int aufs_flush_nondir(struct file *file, fl_owner_t id)
11141+{
11142+ return au_do_flush(file, id, au_do_flush_nondir);
11143+}
11144+
11145+/* ---------------------------------------------------------------------- */
9dbd164d
AM
11146+/*
11147+ * read and write functions acquire [fdi]_rwsem once, but release before
11148+ * mmap_sem. This is because to stop a race condition between mmap(2).
11149+ * Releasing these aufs-rwsem should be safe, no branch-mamagement (by keeping
11150+ * si_rwsem), no harmful copy-up should happen. Actually copy-up may happen in
11151+ * read functions after [fdi]_rwsem are released, but it should be harmless.
11152+ */
4a4d8108
AM
11153+
11154+static ssize_t aufs_read(struct file *file, char __user *buf, size_t count,
11155+ loff_t *ppos)
11156+{
11157+ ssize_t err;
dece6358 11158+ struct dentry *dentry;
4a4d8108 11159+ struct file *h_file;
dece6358 11160+ struct super_block *sb;
1facf9fc 11161+
dece6358
AM
11162+ dentry = file->f_dentry;
11163+ sb = dentry->d_sb;
e49829fe 11164+ si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLMW);
4a4d8108 11165+ err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/0);
dece6358
AM
11166+ if (unlikely(err))
11167+ goto out;
1facf9fc 11168+
4a4d8108 11169+ h_file = au_hf_top(file);
9dbd164d
AM
11170+ get_file(h_file);
11171+ di_read_unlock(dentry, AuLock_IR);
11172+ fi_read_unlock(file);
11173+
11174+ /* filedata may be obsoleted by concurrent copyup, but no problem */
4a4d8108
AM
11175+ err = vfsub_read_u(h_file, buf, count, ppos);
11176+ /* todo: necessary? */
11177+ /* file->f_ra = h_file->f_ra; */
9dbd164d 11178+ /* update without lock, I don't think it a problem */
4a4d8108 11179+ fsstack_copy_attr_atime(dentry->d_inode, h_file->f_dentry->d_inode);
9dbd164d 11180+ fput(h_file);
1308ab2a 11181+
4f0767ce 11182+out:
dece6358
AM
11183+ si_read_unlock(sb);
11184+ return err;
11185+}
1facf9fc 11186+
e49829fe
JR
11187+/*
11188+ * todo: very ugly
11189+ * it locks both of i_mutex and si_rwsem for read in safe.
11190+ * if the plink maintenance mode continues forever (that is the problem),
11191+ * may loop forever.
11192+ */
11193+static void au_mtx_and_read_lock(struct inode *inode)
11194+{
11195+ int err;
11196+ struct super_block *sb = inode->i_sb;
11197+
11198+ while (1) {
11199+ mutex_lock(&inode->i_mutex);
11200+ err = si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLM);
11201+ if (!err)
11202+ break;
11203+ mutex_unlock(&inode->i_mutex);
11204+ si_read_lock(sb, AuLock_NOPLMW);
11205+ si_read_unlock(sb);
11206+ }
11207+}
11208+
4a4d8108
AM
11209+static ssize_t aufs_write(struct file *file, const char __user *ubuf,
11210+ size_t count, loff_t *ppos)
dece6358 11211+{
4a4d8108
AM
11212+ ssize_t err;
11213+ struct au_pin pin;
dece6358 11214+ struct dentry *dentry;
9dbd164d 11215+ struct super_block *sb;
4a4d8108 11216+ struct inode *inode;
4a4d8108
AM
11217+ struct file *h_file;
11218+ char __user *buf = (char __user *)ubuf;
1facf9fc 11219+
dece6358 11220+ dentry = file->f_dentry;
9dbd164d 11221+ sb = dentry->d_sb;
4a4d8108 11222+ inode = dentry->d_inode;
e49829fe 11223+ au_mtx_and_read_lock(inode);
1facf9fc 11224+
4a4d8108
AM
11225+ err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/1);
11226+ if (unlikely(err))
11227+ goto out;
1facf9fc 11228+
4a4d8108
AM
11229+ err = au_ready_to_write(file, -1, &pin);
11230+ di_downgrade_lock(dentry, AuLock_IR);
9dbd164d
AM
11231+ if (unlikely(err)) {
11232+ di_read_unlock(dentry, AuLock_IR);
11233+ fi_write_unlock(file);
11234+ goto out;
11235+ }
1facf9fc 11236+
4a4d8108 11237+ h_file = au_hf_top(file);
9dbd164d 11238+ get_file(h_file);
4a4d8108 11239+ au_unpin(&pin);
9dbd164d
AM
11240+ di_read_unlock(dentry, AuLock_IR);
11241+ fi_write_unlock(file);
11242+
4a4d8108 11243+ err = vfsub_write_u(h_file, buf, count, ppos);
9dbd164d 11244+ ii_write_lock_child(inode);
4a4d8108
AM
11245+ au_cpup_attr_timesizes(inode);
11246+ inode->i_mode = h_file->f_dentry->d_inode->i_mode;
9dbd164d
AM
11247+ ii_write_unlock(inode);
11248+ fput(h_file);
1facf9fc 11249+
4f0767ce 11250+out:
9dbd164d 11251+ si_read_unlock(sb);
4a4d8108 11252+ mutex_unlock(&inode->i_mutex);
dece6358
AM
11253+ return err;
11254+}
1facf9fc 11255+
4a4d8108
AM
11256+static ssize_t au_do_aio(struct file *h_file, int rw, struct kiocb *kio,
11257+ const struct iovec *iov, unsigned long nv, loff_t pos)
dece6358 11258+{
4a4d8108
AM
11259+ ssize_t err;
11260+ struct file *file;
11261+ ssize_t (*func)(struct kiocb *, const struct iovec *, unsigned long,
11262+ loff_t);
1facf9fc 11263+
4a4d8108
AM
11264+ err = security_file_permission(h_file, rw);
11265+ if (unlikely(err))
11266+ goto out;
1facf9fc 11267+
4a4d8108
AM
11268+ err = -ENOSYS;
11269+ func = NULL;
11270+ if (rw == MAY_READ)
11271+ func = h_file->f_op->aio_read;
11272+ else if (rw == MAY_WRITE)
11273+ func = h_file->f_op->aio_write;
11274+ if (func) {
11275+ file = kio->ki_filp;
11276+ kio->ki_filp = h_file;
2cbb1c4b 11277+ lockdep_off();
4a4d8108 11278+ err = func(kio, iov, nv, pos);
2cbb1c4b 11279+ lockdep_on();
4a4d8108
AM
11280+ kio->ki_filp = file;
11281+ } else
11282+ /* currently there is no such fs */
11283+ WARN_ON_ONCE(1);
1facf9fc 11284+
4f0767ce 11285+out:
dece6358
AM
11286+ return err;
11287+}
1facf9fc 11288+
4a4d8108
AM
11289+static ssize_t aufs_aio_read(struct kiocb *kio, const struct iovec *iov,
11290+ unsigned long nv, loff_t pos)
1facf9fc 11291+{
4a4d8108
AM
11292+ ssize_t err;
11293+ struct file *file, *h_file;
11294+ struct dentry *dentry;
dece6358 11295+ struct super_block *sb;
1facf9fc 11296+
4a4d8108 11297+ file = kio->ki_filp;
dece6358 11298+ dentry = file->f_dentry;
1308ab2a 11299+ sb = dentry->d_sb;
e49829fe 11300+ si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLMW);
4a4d8108
AM
11301+ err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/0);
11302+ if (unlikely(err))
11303+ goto out;
11304+
11305+ h_file = au_hf_top(file);
9dbd164d
AM
11306+ get_file(h_file);
11307+ di_read_unlock(dentry, AuLock_IR);
11308+ fi_read_unlock(file);
11309+
4a4d8108
AM
11310+ err = au_do_aio(h_file, MAY_READ, kio, iov, nv, pos);
11311+ /* todo: necessary? */
11312+ /* file->f_ra = h_file->f_ra; */
9dbd164d 11313+ /* update without lock, I don't think it a problem */
4a4d8108 11314+ fsstack_copy_attr_atime(dentry->d_inode, h_file->f_dentry->d_inode);
9dbd164d 11315+ fput(h_file);
1facf9fc 11316+
4f0767ce 11317+out:
4a4d8108 11318+ si_read_unlock(sb);
1308ab2a 11319+ return err;
11320+}
1facf9fc 11321+
4a4d8108
AM
11322+static ssize_t aufs_aio_write(struct kiocb *kio, const struct iovec *iov,
11323+ unsigned long nv, loff_t pos)
1308ab2a 11324+{
4a4d8108
AM
11325+ ssize_t err;
11326+ struct au_pin pin;
11327+ struct dentry *dentry;
11328+ struct inode *inode;
4a4d8108 11329+ struct file *file, *h_file;
9dbd164d 11330+ struct super_block *sb;
1308ab2a 11331+
4a4d8108 11332+ file = kio->ki_filp;
1308ab2a 11333+ dentry = file->f_dentry;
9dbd164d 11334+ sb = dentry->d_sb;
1308ab2a 11335+ inode = dentry->d_inode;
e49829fe
JR
11336+ au_mtx_and_read_lock(inode);
11337+
4a4d8108
AM
11338+ err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/1);
11339+ if (unlikely(err))
1308ab2a 11340+ goto out;
1facf9fc 11341+
4a4d8108
AM
11342+ err = au_ready_to_write(file, -1, &pin);
11343+ di_downgrade_lock(dentry, AuLock_IR);
9dbd164d
AM
11344+ if (unlikely(err)) {
11345+ di_read_unlock(dentry, AuLock_IR);
11346+ fi_write_unlock(file);
11347+ goto out;
11348+ }
1facf9fc 11349+
4a4d8108 11350+ h_file = au_hf_top(file);
9dbd164d
AM
11351+ get_file(h_file);
11352+ au_unpin(&pin);
11353+ di_read_unlock(dentry, AuLock_IR);
11354+ fi_write_unlock(file);
11355+
4a4d8108 11356+ err = au_do_aio(h_file, MAY_WRITE, kio, iov, nv, pos);
9dbd164d 11357+ ii_write_lock_child(inode);
4a4d8108
AM
11358+ au_cpup_attr_timesizes(inode);
11359+ inode->i_mode = h_file->f_dentry->d_inode->i_mode;
9dbd164d
AM
11360+ ii_write_unlock(inode);
11361+ fput(h_file);
1facf9fc 11362+
4f0767ce 11363+out:
9dbd164d 11364+ si_read_unlock(sb);
4a4d8108 11365+ mutex_unlock(&inode->i_mutex);
dece6358 11366+ return err;
1facf9fc 11367+}
11368+
4a4d8108
AM
11369+static ssize_t aufs_splice_read(struct file *file, loff_t *ppos,
11370+ struct pipe_inode_info *pipe, size_t len,
11371+ unsigned int flags)
1facf9fc 11372+{
4a4d8108
AM
11373+ ssize_t err;
11374+ struct file *h_file;
11375+ struct dentry *dentry;
dece6358 11376+ struct super_block *sb;
1facf9fc 11377+
dece6358 11378+ dentry = file->f_dentry;
dece6358 11379+ sb = dentry->d_sb;
e49829fe 11380+ si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLMW);
4a4d8108
AM
11381+ err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/0);
11382+ if (unlikely(err))
dece6358 11383+ goto out;
1facf9fc 11384+
4a4d8108
AM
11385+ err = -EINVAL;
11386+ h_file = au_hf_top(file);
9dbd164d 11387+ get_file(h_file);
4a4d8108 11388+ if (au_test_loopback_kthread()) {
87a755f4
AM
11389+ au_warn_loopback(h_file->f_dentry->d_sb);
11390+ if (file->f_mapping != h_file->f_mapping) {
11391+ file->f_mapping = h_file->f_mapping;
11392+ smp_mb(); /* unnecessary? */
11393+ }
1308ab2a 11394+ }
9dbd164d
AM
11395+ di_read_unlock(dentry, AuLock_IR);
11396+ fi_read_unlock(file);
11397+
4a4d8108
AM
11398+ err = vfsub_splice_to(h_file, ppos, pipe, len, flags);
11399+ /* todo: necessasry? */
11400+ /* file->f_ra = h_file->f_ra; */
9dbd164d 11401+ /* update without lock, I don't think it a problem */
4a4d8108 11402+ fsstack_copy_attr_atime(dentry->d_inode, h_file->f_dentry->d_inode);
9dbd164d 11403+ fput(h_file);
1facf9fc 11404+
4f0767ce 11405+out:
4a4d8108 11406+ si_read_unlock(sb);
dece6358 11407+ return err;
1facf9fc 11408+}
11409+
4a4d8108
AM
11410+static ssize_t
11411+aufs_splice_write(struct pipe_inode_info *pipe, struct file *file, loff_t *ppos,
11412+ size_t len, unsigned int flags)
1facf9fc 11413+{
4a4d8108
AM
11414+ ssize_t err;
11415+ struct au_pin pin;
11416+ struct dentry *dentry;
11417+ struct inode *inode;
4a4d8108 11418+ struct file *h_file;
9dbd164d 11419+ struct super_block *sb;
1facf9fc 11420+
4a4d8108 11421+ dentry = file->f_dentry;
9dbd164d 11422+ sb = dentry->d_sb;
4a4d8108 11423+ inode = dentry->d_inode;
e49829fe 11424+ au_mtx_and_read_lock(inode);
9dbd164d 11425+
4a4d8108
AM
11426+ err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/1);
11427+ if (unlikely(err))
11428+ goto out;
1facf9fc 11429+
4a4d8108
AM
11430+ err = au_ready_to_write(file, -1, &pin);
11431+ di_downgrade_lock(dentry, AuLock_IR);
9dbd164d
AM
11432+ if (unlikely(err)) {
11433+ di_read_unlock(dentry, AuLock_IR);
11434+ fi_write_unlock(file);
11435+ goto out;
11436+ }
1facf9fc 11437+
4a4d8108 11438+ h_file = au_hf_top(file);
9dbd164d 11439+ get_file(h_file);
4a4d8108 11440+ au_unpin(&pin);
9dbd164d
AM
11441+ di_read_unlock(dentry, AuLock_IR);
11442+ fi_write_unlock(file);
11443+
4a4d8108 11444+ err = vfsub_splice_from(pipe, h_file, ppos, len, flags);
9dbd164d 11445+ ii_write_lock_child(inode);
4a4d8108
AM
11446+ au_cpup_attr_timesizes(inode);
11447+ inode->i_mode = h_file->f_dentry->d_inode->i_mode;
9dbd164d
AM
11448+ ii_write_unlock(inode);
11449+ fput(h_file);
1facf9fc 11450+
4f0767ce 11451+out:
9dbd164d 11452+ si_read_unlock(sb);
4a4d8108
AM
11453+ mutex_unlock(&inode->i_mutex);
11454+ return err;
11455+}
1facf9fc 11456+
4a4d8108
AM
11457+/* ---------------------------------------------------------------------- */
11458+
9dbd164d
AM
11459+/*
11460+ * The locking order around current->mmap_sem.
11461+ * - in most and regular cases
11462+ * file I/O syscall -- aufs_read() or something
11463+ * -- si_rwsem for read -- mmap_sem
11464+ * (Note that [fdi]i_rwsem are released before mmap_sem).
11465+ * - in mmap case
11466+ * mmap(2) -- mmap_sem -- aufs_mmap() -- si_rwsem for read -- [fdi]i_rwsem
11467+ * This AB-BA order is definitly bad, but is not a problem since "si_rwsem for
11468+ * read" allows muliple processes to acquire it and [fdi]i_rwsem are not held in
11469+ * file I/O. Aufs needs to stop lockdep in aufs_mmap() though.
11470+ * It means that when aufs acquires si_rwsem for write, the process should never
11471+ * acquire mmap_sem.
11472+ *
11473+ * Actually aufs_readdir() holds [fdi]i_rwsem before mmap_sem, but this is not a
11474+ * problem either since any directory is not able to be mmap-ed.
11475+ * The similar scenario is applied to aufs_readlink() too.
11476+ */
11477+
4a4d8108
AM
11478+/* cf. linux/include/linux/mman.h: calc_vm_prot_bits() */
11479+#define AuConv_VM_PROT(f, b) _calc_vm_trans(f, VM_##b, PROT_##b)
1308ab2a 11480+
4a4d8108 11481+static unsigned long au_arch_prot_conv(unsigned long flags)
dece6358 11482+{
4a4d8108
AM
11483+ /* currently ppc64 only */
11484+#ifdef CONFIG_PPC64
11485+ /* cf. linux/arch/powerpc/include/asm/mman.h */
11486+ AuDebugOn(arch_calc_vm_prot_bits(-1) != VM_SAO);
11487+ return AuConv_VM_PROT(flags, SAO);
11488+#else
11489+ AuDebugOn(arch_calc_vm_prot_bits(-1));
11490+ return 0;
11491+#endif
dece6358
AM
11492+}
11493+
4a4d8108 11494+static unsigned long au_prot_conv(unsigned long flags)
dece6358 11495+{
4a4d8108
AM
11496+ return AuConv_VM_PROT(flags, READ)
11497+ | AuConv_VM_PROT(flags, WRITE)
11498+ | AuConv_VM_PROT(flags, EXEC)
11499+ | au_arch_prot_conv(flags);
dece6358
AM
11500+}
11501+
4a4d8108
AM
11502+/* cf. linux/include/linux/mman.h: calc_vm_flag_bits() */
11503+#define AuConv_VM_MAP(f, b) _calc_vm_trans(f, VM_##b, MAP_##b)
dece6358 11504+
4a4d8108 11505+static unsigned long au_flag_conv(unsigned long flags)
dece6358 11506+{
4a4d8108
AM
11507+ return AuConv_VM_MAP(flags, GROWSDOWN)
11508+ | AuConv_VM_MAP(flags, DENYWRITE)
11509+ | AuConv_VM_MAP(flags, EXECUTABLE)
11510+ | AuConv_VM_MAP(flags, LOCKED);
dece6358 11511+}
1308ab2a 11512+
9dbd164d 11513+static int aufs_mmap(struct file *file, struct vm_area_struct *vma)
dece6358 11514+{
4a4d8108 11515+ int err;
9dbd164d 11516+ unsigned long prot;
4a4d8108
AM
11517+ aufs_bindex_t bstart;
11518+ const unsigned char wlock
9dbd164d 11519+ = (file->f_mode & FMODE_WRITE) && (vma->vm_flags & VM_SHARED);
4a4d8108
AM
11520+ struct dentry *dentry;
11521+ struct super_block *sb;
9dbd164d
AM
11522+ struct file *h_file;
11523+ struct au_branch *br;
11524+ struct au_pin pin;
11525+
11526+ AuDbgVmRegion(file, vma);
1308ab2a 11527+
4a4d8108
AM
11528+ dentry = file->f_dentry;
11529+ sb = dentry->d_sb;
9dbd164d 11530+ lockdep_off();
e49829fe 11531+ si_read_lock(sb, AuLock_NOPLMW);
4a4d8108
AM
11532+ err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/1);
11533+ if (unlikely(err))
11534+ goto out;
11535+
4a4d8108 11536+ if (wlock) {
4a4d8108
AM
11537+ err = au_ready_to_write(file, -1, &pin);
11538+ di_write_unlock(dentry);
9dbd164d
AM
11539+ if (unlikely(err)) {
11540+ fi_write_unlock(file);
11541+ goto out;
11542+ }
4a4d8108
AM
11543+ au_unpin(&pin);
11544+ } else
11545+ di_write_unlock(dentry);
9dbd164d 11546+
4a4d8108 11547+ bstart = au_fbstart(file);
9dbd164d
AM
11548+ br = au_sbr(sb, bstart);
11549+ h_file = au_hf_top(file);
11550+ get_file(h_file);
2cbb1c4b 11551+ au_set_mmapped(file);
4a4d8108 11552+ fi_write_unlock(file);
9dbd164d 11553+ lockdep_on();
1308ab2a 11554+
9dbd164d 11555+ au_vm_file_reset(vma, h_file);
2cbb1c4b 11556+ prot = au_prot_conv(vma->vm_flags);
9dbd164d 11557+ err = security_file_mmap(h_file, /*reqprot*/prot, prot,
2cbb1c4b 11558+ au_flag_conv(vma->vm_flags), vma->vm_start, 0);
9dbd164d
AM
11559+ if (!err)
11560+ err = h_file->f_op->mmap(h_file, vma);
2cbb1c4b
JR
11561+ if (unlikely(err))
11562+ goto out_reset;
4a4d8108 11563+
2cbb1c4b 11564+ au_vm_prfile_set(vma, file);
4a4d8108 11565+ /* update without lock, I don't think it a problem */
2cbb1c4b 11566+ fsstack_copy_attr_atime(file->f_dentry->d_inode,
9dbd164d 11567+ h_file->f_dentry->d_inode);
2cbb1c4b 11568+ goto out_fput; /* success */
4a4d8108 11569+
2cbb1c4b
JR
11570+out_reset:
11571+ au_unset_mmapped(file);
11572+ au_vm_file_reset(vma, file);
11573+out_fput:
9dbd164d
AM
11574+ fput(h_file);
11575+ lockdep_off();
4f0767ce 11576+out:
9dbd164d
AM
11577+ si_read_unlock(sb);
11578+ lockdep_on();
11579+ AuTraceErr(err);
4a4d8108
AM
11580+ return err;
11581+}
11582+
11583+/* ---------------------------------------------------------------------- */
11584+
1e00d052
AM
11585+static int aufs_fsync_nondir(struct file *file, loff_t start, loff_t end,
11586+ int datasync)
4a4d8108
AM
11587+{
11588+ int err;
11589+ struct au_pin pin;
b752ccd1 11590+ struct dentry *dentry;
4a4d8108
AM
11591+ struct inode *inode;
11592+ struct file *h_file;
11593+ struct super_block *sb;
11594+
b752ccd1 11595+ dentry = file->f_dentry;
4a4d8108 11596+ inode = dentry->d_inode;
4a4d8108 11597+ sb = dentry->d_sb;
1e00d052 11598+ mutex_lock(&inode->i_mutex);
e49829fe
JR
11599+ err = si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLM);
11600+ if (unlikely(err))
11601+ goto out;
4a4d8108
AM
11602+
11603+ err = 0; /* -EBADF; */ /* posix? */
11604+ if (unlikely(!(file->f_mode & FMODE_WRITE)))
e49829fe 11605+ goto out_si;
4a4d8108
AM
11606+ err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/1);
11607+ if (unlikely(err))
e49829fe 11608+ goto out_si;
4a4d8108
AM
11609+
11610+ err = au_ready_to_write(file, -1, &pin);
11611+ di_downgrade_lock(dentry, AuLock_IR);
11612+ if (unlikely(err))
11613+ goto out_unlock;
11614+ au_unpin(&pin);
11615+
11616+ err = -EINVAL;
11617+ h_file = au_hf_top(file);
53392da6
AM
11618+ err = vfsub_fsync(h_file, &h_file->f_path, datasync);
11619+ au_cpup_attr_timesizes(inode);
4a4d8108 11620+
4f0767ce 11621+out_unlock:
4a4d8108 11622+ di_read_unlock(dentry, AuLock_IR);
1308ab2a 11623+ fi_write_unlock(file);
e49829fe 11624+out_si:
953406b4 11625+ si_read_unlock(sb);
e49829fe 11626+out:
1e00d052 11627+ mutex_unlock(&inode->i_mutex);
4a4d8108 11628+ return err;
dece6358
AM
11629+}
11630+
4a4d8108
AM
11631+/* no one supports this operation, currently */
11632+#if 0
11633+static int aufs_aio_fsync_nondir(struct kiocb *kio, int datasync)
dece6358 11634+{
4a4d8108
AM
11635+ int err;
11636+ struct au_pin pin;
1308ab2a 11637+ struct dentry *dentry;
4a4d8108
AM
11638+ struct inode *inode;
11639+ struct file *file, *h_file;
1308ab2a 11640+
4a4d8108 11641+ file = kio->ki_filp;
1308ab2a 11642+ dentry = file->f_dentry;
4a4d8108 11643+ inode = dentry->d_inode;
e49829fe 11644+ au_mtx_and_read_lock(inode);
4a4d8108
AM
11645+
11646+ err = 0; /* -EBADF; */ /* posix? */
11647+ if (unlikely(!(file->f_mode & FMODE_WRITE)))
11648+ goto out;
11649+ err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/1);
11650+ if (unlikely(err))
1308ab2a 11651+ goto out;
11652+
4a4d8108
AM
11653+ err = au_ready_to_write(file, -1, &pin);
11654+ di_downgrade_lock(dentry, AuLock_IR);
11655+ if (unlikely(err))
11656+ goto out_unlock;
11657+ au_unpin(&pin);
1308ab2a 11658+
4a4d8108
AM
11659+ err = -ENOSYS;
11660+ h_file = au_hf_top(file);
11661+ if (h_file->f_op && h_file->f_op->aio_fsync) {
11662+ struct dentry *h_d;
11663+ struct mutex *h_mtx;
1308ab2a 11664+
4a4d8108
AM
11665+ h_d = h_file->f_dentry;
11666+ h_mtx = &h_d->d_inode->i_mutex;
11667+ if (!is_sync_kiocb(kio)) {
11668+ get_file(h_file);
11669+ fput(file);
11670+ }
11671+ kio->ki_filp = h_file;
11672+ err = h_file->f_op->aio_fsync(kio, datasync);
11673+ mutex_lock_nested(h_mtx, AuLsc_I_CHILD);
11674+ if (!err)
11675+ vfsub_update_h_iattr(&h_file->f_path, /*did*/NULL);
11676+ /*ignore*/
11677+ au_cpup_attr_timesizes(inode);
11678+ mutex_unlock(h_mtx);
11679+ }
1308ab2a 11680+
4f0767ce 11681+out_unlock:
4a4d8108
AM
11682+ di_read_unlock(dentry, AuLock_IR);
11683+ fi_write_unlock(file);
4f0767ce 11684+out:
e49829fe 11685+ si_read_unlock(inode->sb);
4a4d8108
AM
11686+ mutex_unlock(&inode->i_mutex);
11687+ return err;
dece6358 11688+}
4a4d8108 11689+#endif
dece6358 11690+
4a4d8108 11691+static int aufs_fasync(int fd, struct file *file, int flag)
dece6358 11692+{
4a4d8108
AM
11693+ int err;
11694+ struct file *h_file;
11695+ struct dentry *dentry;
11696+ struct super_block *sb;
1308ab2a 11697+
4a4d8108
AM
11698+ dentry = file->f_dentry;
11699+ sb = dentry->d_sb;
e49829fe 11700+ si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLMW);
4a4d8108
AM
11701+ err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/0);
11702+ if (unlikely(err))
11703+ goto out;
11704+
11705+ h_file = au_hf_top(file);
11706+ if (h_file->f_op && h_file->f_op->fasync)
11707+ err = h_file->f_op->fasync(fd, h_file, flag);
11708+
11709+ di_read_unlock(dentry, AuLock_IR);
11710+ fi_read_unlock(file);
1308ab2a 11711+
4f0767ce 11712+out:
4a4d8108 11713+ si_read_unlock(sb);
1308ab2a 11714+ return err;
dece6358 11715+}
4a4d8108
AM
11716+
11717+/* ---------------------------------------------------------------------- */
11718+
11719+/* no one supports this operation, currently */
11720+#if 0
11721+static ssize_t aufs_sendpage(struct file *file, struct page *page, int offset,
11722+ size_t len, loff_t *pos , int more)
11723+{
11724+}
11725+#endif
11726+
11727+/* ---------------------------------------------------------------------- */
11728+
11729+const struct file_operations aufs_file_fop = {
11730+ .owner = THIS_MODULE,
2cbb1c4b 11731+
027c5e7a 11732+ .llseek = default_llseek,
4a4d8108
AM
11733+
11734+ .read = aufs_read,
11735+ .write = aufs_write,
11736+ .aio_read = aufs_aio_read,
11737+ .aio_write = aufs_aio_write,
11738+#ifdef CONFIG_AUFS_POLL
11739+ .poll = aufs_poll,
11740+#endif
11741+ .unlocked_ioctl = aufs_ioctl_nondir,
b752ccd1
AM
11742+#ifdef CONFIG_COMPAT
11743+ .compat_ioctl = aufs_ioctl_nondir, /* same */
11744+#endif
4a4d8108
AM
11745+ .mmap = aufs_mmap,
11746+ .open = aufs_open_nondir,
11747+ .flush = aufs_flush_nondir,
11748+ .release = aufs_release_nondir,
11749+ .fsync = aufs_fsync_nondir,
11750+ /* .aio_fsync = aufs_aio_fsync_nondir, */
11751+ .fasync = aufs_fasync,
11752+ /* .sendpage = aufs_sendpage, */
11753+ .splice_write = aufs_splice_write,
11754+ .splice_read = aufs_splice_read,
11755+#if 0
11756+ .aio_splice_write = aufs_aio_splice_write,
11757+ .aio_splice_read = aufs_aio_splice_read
11758+#endif
11759+};
7f207e10
AM
11760diff -urN /usr/share/empty/fs/aufs/f_op_sp.c linux/fs/aufs/f_op_sp.c
11761--- /usr/share/empty/fs/aufs/f_op_sp.c 1970-01-01 01:00:00.000000000 +0100
7ce627cf 11762+++ linux/fs/aufs/f_op_sp.c 2012-05-22 09:06:08.867458905 +0200
f6c5ef8b 11763@@ -0,0 +1,298 @@
1308ab2a 11764+/*
f6c5ef8b 11765+ * Copyright (C) 2005-2012 Junjiro R. Okajima
1308ab2a 11766+ *
11767+ * This program, aufs is free software; you can redistribute it and/or modify
11768+ * it under the terms of the GNU General Public License as published by
11769+ * the Free Software Foundation; either version 2 of the License, or
11770+ * (at your option) any later version.
11771+ *
11772+ * This program is distributed in the hope that it will be useful,
11773+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
11774+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11775+ * GNU General Public License for more details.
11776+ *
11777+ * You should have received a copy of the GNU General Public License
11778+ * along with this program; if not, write to the Free Software
11779+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
11780+ */
dece6358 11781+
1308ab2a 11782+/*
4a4d8108
AM
11783+ * file operations for special files.
11784+ * while they exist in aufs virtually,
11785+ * their file I/O is handled out of aufs.
1308ab2a 11786+ */
11787+
4a4d8108 11788+#include "aufs.h"
1308ab2a 11789+
4a4d8108
AM
11790+static ssize_t aufs_aio_read_sp(struct kiocb *kio, const struct iovec *iov,
11791+ unsigned long nv, loff_t pos)
dece6358 11792+{
4a4d8108
AM
11793+ ssize_t err;
11794+ aufs_bindex_t bstart;
11795+ unsigned char wbr;
11796+ struct file *file, *h_file;
11797+ struct super_block *sb;
1308ab2a 11798+
4a4d8108
AM
11799+ file = kio->ki_filp;
11800+ sb = file->f_dentry->d_sb;
11801+ si_read_lock(sb, AuLock_FLUSH);
11802+ fi_read_lock(file);
11803+ bstart = au_fbstart(file);
11804+ h_file = au_hf_top(file);
11805+ fi_read_unlock(file);
11806+ wbr = !!au_br_writable(au_sbr(sb, bstart)->br_perm);
11807+ si_read_unlock(sb);
11808+
11809+ /* do not change the file in kio */
11810+ AuDebugOn(!h_file->f_op || !h_file->f_op->aio_read);
11811+ err = h_file->f_op->aio_read(kio, iov, nv, pos);
11812+ if (err > 0 && wbr)
11813+ file_accessed(h_file);
11814+
11815+ return err;
11816+}
11817+
11818+static ssize_t aufs_aio_write_sp(struct kiocb *kio, const struct iovec *iov,
11819+ unsigned long nv, loff_t pos)
11820+{
11821+ ssize_t err;
11822+ aufs_bindex_t bstart;
11823+ unsigned char wbr;
11824+ struct super_block *sb;
11825+ struct file *file, *h_file;
11826+
11827+ file = kio->ki_filp;
11828+ sb = file->f_dentry->d_sb;
11829+ si_read_lock(sb, AuLock_FLUSH);
11830+ fi_read_lock(file);
11831+ bstart = au_fbstart(file);
11832+ h_file = au_hf_top(file);
11833+ fi_read_unlock(file);
11834+ wbr = !!au_br_writable(au_sbr(sb, bstart)->br_perm);
11835+ si_read_unlock(sb);
11836+
11837+ /* do not change the file in kio */
11838+ AuDebugOn(!h_file->f_op || !h_file->f_op->aio_write);
11839+ err = h_file->f_op->aio_write(kio, iov, nv, pos);
11840+ if (err > 0 && wbr)
11841+ file_update_time(h_file);
11842+
11843+ return err;
11844+}
11845+
11846+/* ---------------------------------------------------------------------- */
11847+
11848+static int aufs_release_sp(struct inode *inode, struct file *file)
11849+{
11850+ int err;
11851+ struct file *h_file;
11852+
11853+ fi_read_lock(file);
11854+ h_file = au_hf_top(file);
11855+ fi_read_unlock(file);
11856+ /* close this fifo in aufs */
11857+ err = h_file->f_op->release(inode, file); /* ignore */
11858+ aufs_release_nondir(inode, file); /* ignore */
11859+ return err;
11860+}
11861+
11862+/* ---------------------------------------------------------------------- */
11863+
11864+/* currently, support only FIFO */
4f0767ce
JR
11865+enum {
11866+ AuSp_FIFO, AuSp_FIFO_R, AuSp_FIFO_W, AuSp_FIFO_RW,
11867+ /* AuSp_SOCK, AuSp_CHR, AuSp_BLK, */
11868+ AuSp_Last
11869+};
4a4d8108
AM
11870+static int aufs_open_sp(struct inode *inode, struct file *file);
11871+static struct au_sp_fop {
11872+ int done;
11873+ struct file_operations fop; /* not 'const' */
11874+ spinlock_t spin;
11875+} au_sp_fop[AuSp_Last] = {
11876+ [AuSp_FIFO] = {
11877+ .fop = {
11878+ .owner = THIS_MODULE,
11879+ .open = aufs_open_sp
11880+ }
11881+ }
11882+};
11883+
11884+static void au_init_fop_sp(struct file *file)
11885+{
11886+ struct au_sp_fop *p;
11887+ int i;
11888+ struct file *h_file;
11889+
11890+ p = au_sp_fop;
11891+ if (unlikely(!p->done)) {
11892+ /* initialize first time only */
11893+ static DEFINE_SPINLOCK(spin);
11894+
11895+ spin_lock(&spin);
11896+ if (!p->done) {
11897+ BUILD_BUG_ON(sizeof(au_sp_fop)/sizeof(*au_sp_fop)
11898+ != AuSp_Last);
11899+ for (i = 0; i < AuSp_Last; i++)
11900+ spin_lock_init(&p[i].spin);
11901+ p->done = 1;
11902+ }
11903+ spin_unlock(&spin);
11904+ }
11905+
11906+ switch (file->f_mode & (FMODE_READ | FMODE_WRITE)) {
11907+ case FMODE_READ:
11908+ i = AuSp_FIFO_R;
11909+ break;
11910+ case FMODE_WRITE:
11911+ i = AuSp_FIFO_W;
11912+ break;
11913+ case FMODE_READ | FMODE_WRITE:
11914+ i = AuSp_FIFO_RW;
11915+ break;
11916+ default:
11917+ BUG();
11918+ }
11919+
11920+ p += i;
11921+ if (unlikely(!p->done)) {
11922+ /* initialize first time only */
11923+ h_file = au_hf_top(file);
11924+ spin_lock(&p->spin);
11925+ if (!p->done) {
11926+ p->fop = *h_file->f_op;
11927+ p->fop.owner = THIS_MODULE;
11928+ if (p->fop.aio_read)
11929+ p->fop.aio_read = aufs_aio_read_sp;
11930+ if (p->fop.aio_write)
11931+ p->fop.aio_write = aufs_aio_write_sp;
11932+ p->fop.release = aufs_release_sp;
11933+ p->done = 1;
11934+ }
11935+ spin_unlock(&p->spin);
11936+ }
11937+ file->f_op = &p->fop;
11938+}
11939+
11940+static int au_cpup_sp(struct dentry *dentry)
11941+{
11942+ int err;
11943+ aufs_bindex_t bcpup;
11944+ struct au_pin pin;
11945+ struct au_wr_dir_args wr_dir_args = {
11946+ .force_btgt = -1,
11947+ .flags = 0
11948+ };
11949+
11950+ AuDbg("%.*s\n", AuDLNPair(dentry));
11951+
11952+ di_read_unlock(dentry, AuLock_IR);
11953+ di_write_lock_child(dentry);
11954+ err = au_wr_dir(dentry, /*src_dentry*/NULL, &wr_dir_args);
11955+ if (unlikely(err < 0))
11956+ goto out;
11957+ bcpup = err;
11958+ err = 0;
11959+ if (bcpup == au_dbstart(dentry))
11960+ goto out; /* success */
11961+
11962+ err = au_pin(&pin, dentry, bcpup, au_opt_udba(dentry->d_sb),
11963+ AuPin_MNT_WRITE);
11964+ if (!err) {
11965+ err = au_sio_cpup_simple(dentry, bcpup, -1, AuCpup_DTIME);
11966+ au_unpin(&pin);
11967+ }
11968+
4f0767ce 11969+out:
4a4d8108
AM
11970+ di_downgrade_lock(dentry, AuLock_IR);
11971+ return err;
11972+}
11973+
11974+static int au_do_open_sp(struct file *file, int flags)
11975+{
11976+ int err;
11977+ struct dentry *dentry;
11978+ struct super_block *sb;
11979+ struct file *h_file;
11980+ struct inode *h_inode;
11981+
11982+ dentry = file->f_dentry;
11983+ AuDbg("%.*s\n", AuDLNPair(dentry));
11984+
11985+ /*
11986+ * try copying-up.
11987+ * operate on the ro branch is not an error.
11988+ */
11989+ au_cpup_sp(dentry); /* ignore */
11990+
11991+ /* prepare h_file */
11992+ err = au_do_open_nondir(file, vfsub_file_flags(file));
11993+ if (unlikely(err))
11994+ goto out;
11995+
11996+ sb = dentry->d_sb;
11997+ h_file = au_hf_top(file);
11998+ h_inode = h_file->f_dentry->d_inode;
11999+ di_read_unlock(dentry, AuLock_IR);
12000+ fi_write_unlock(file);
12001+ si_read_unlock(sb);
12002+ /* open this fifo in aufs */
12003+ err = h_inode->i_fop->open(file->f_dentry->d_inode, file);
12004+ si_noflush_read_lock(sb);
12005+ fi_write_lock(file);
12006+ di_read_lock_child(dentry, AuLock_IR);
12007+ if (!err)
12008+ au_init_fop_sp(file);
4a4d8108 12009+
4f0767ce 12010+out:
4a4d8108
AM
12011+ return err;
12012+}
12013+
12014+static int aufs_open_sp(struct inode *inode, struct file *file)
12015+{
12016+ int err;
12017+ struct super_block *sb;
12018+
12019+ sb = file->f_dentry->d_sb;
12020+ si_read_lock(sb, AuLock_FLUSH);
12021+ err = au_do_open(file, au_do_open_sp, /*fidir*/NULL);
12022+ si_read_unlock(sb);
12023+ return err;
12024+}
12025+
12026+/* ---------------------------------------------------------------------- */
12027+
12028+void au_init_special_fop(struct inode *inode, umode_t mode, dev_t rdev)
12029+{
12030+ init_special_inode(inode, mode, rdev);
12031+
12032+ switch (mode & S_IFMT) {
12033+ case S_IFIFO:
12034+ inode->i_fop = &au_sp_fop[AuSp_FIFO].fop;
12035+ /*FALLTHROUGH*/
12036+ case S_IFCHR:
12037+ case S_IFBLK:
12038+ case S_IFSOCK:
12039+ break;
12040+ default:
12041+ AuDebugOn(1);
12042+ }
12043+}
12044+
12045+int au_special_file(umode_t mode)
12046+{
12047+ int ret;
12048+
12049+ ret = 0;
12050+ switch (mode & S_IFMT) {
12051+ case S_IFIFO:
12052+#if 0
12053+ case S_IFCHR:
12054+ case S_IFBLK:
12055+ case S_IFSOCK:
12056+#endif
12057+ ret = 1;
12058+ }
12059+
12060+ return ret;
12061+}
7f207e10
AM
12062diff -urN /usr/share/empty/fs/aufs/fstype.h linux/fs/aufs/fstype.h
12063--- /usr/share/empty/fs/aufs/fstype.h 1970-01-01 01:00:00.000000000 +0100
7ce627cf 12064+++ linux/fs/aufs/fstype.h 2012-05-22 09:06:08.867458905 +0200
f6c5ef8b 12065@@ -0,0 +1,496 @@
4a4d8108 12066+/*
f6c5ef8b 12067+ * Copyright (C) 2005-2012 Junjiro R. Okajima
4a4d8108
AM
12068+ *
12069+ * This program, aufs is free software; you can redistribute it and/or modify
12070+ * it under the terms of the GNU General Public License as published by
12071+ * the Free Software Foundation; either version 2 of the License, or
12072+ * (at your option) any later version.
12073+ *
12074+ * This program is distributed in the hope that it will be useful,
12075+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
12076+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12077+ * GNU General Public License for more details.
12078+ *
12079+ * You should have received a copy of the GNU General Public License
12080+ * along with this program; if not, write to the Free Software
12081+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
12082+ */
12083+
12084+/*
12085+ * judging filesystem type
12086+ */
12087+
12088+#ifndef __AUFS_FSTYPE_H__
12089+#define __AUFS_FSTYPE_H__
12090+
12091+#ifdef __KERNEL__
12092+
12093+#include <linux/fs.h>
12094+#include <linux/magic.h>
12095+#include <linux/romfs_fs.h>
4a4d8108
AM
12096+
12097+static inline int au_test_aufs(struct super_block *sb)
12098+{
12099+ return sb->s_magic == AUFS_SUPER_MAGIC;
12100+}
12101+
12102+static inline const char *au_sbtype(struct super_block *sb)
12103+{
12104+ return sb->s_type->name;
12105+}
1308ab2a 12106+
12107+static inline int au_test_iso9660(struct super_block *sb __maybe_unused)
12108+{
12109+#if defined(CONFIG_ROMFS_FS) || defined(CONFIG_ROMFS_FS_MODULE)
12110+ return sb->s_magic == ROMFS_MAGIC;
dece6358
AM
12111+#else
12112+ return 0;
12113+#endif
12114+}
12115+
1308ab2a 12116+static inline int au_test_romfs(struct super_block *sb __maybe_unused)
dece6358 12117+{
1308ab2a 12118+#if defined(CONFIG_ISO9660_FS) || defined(CONFIG_ISO9660_FS_MODULE)
12119+ return sb->s_magic == ISOFS_SUPER_MAGIC;
dece6358
AM
12120+#else
12121+ return 0;
12122+#endif
12123+}
12124+
1308ab2a 12125+static inline int au_test_cramfs(struct super_block *sb __maybe_unused)
dece6358 12126+{
1308ab2a 12127+#if defined(CONFIG_CRAMFS) || defined(CONFIG_CRAMFS_MODULE)
12128+ return sb->s_magic == CRAMFS_MAGIC;
12129+#endif
12130+ return 0;
12131+}
12132+
12133+static inline int au_test_nfs(struct super_block *sb __maybe_unused)
12134+{
12135+#if defined(CONFIG_NFS_FS) || defined(CONFIG_NFS_FS_MODULE)
12136+ return sb->s_magic == NFS_SUPER_MAGIC;
dece6358
AM
12137+#else
12138+ return 0;
12139+#endif
12140+}
12141+
1308ab2a 12142+static inline int au_test_fuse(struct super_block *sb __maybe_unused)
dece6358 12143+{
1308ab2a 12144+#if defined(CONFIG_FUSE_FS) || defined(CONFIG_FUSE_FS_MODULE)
12145+ return sb->s_magic == FUSE_SUPER_MAGIC;
dece6358
AM
12146+#else
12147+ return 0;
12148+#endif
12149+}
12150+
1308ab2a 12151+static inline int au_test_xfs(struct super_block *sb __maybe_unused)
dece6358 12152+{
1308ab2a 12153+#if defined(CONFIG_XFS_FS) || defined(CONFIG_XFS_FS_MODULE)
12154+ return sb->s_magic == XFS_SB_MAGIC;
dece6358
AM
12155+#else
12156+ return 0;
12157+#endif
12158+}
12159+
1308ab2a 12160+static inline int au_test_tmpfs(struct super_block *sb __maybe_unused)
dece6358 12161+{
1308ab2a 12162+#ifdef CONFIG_TMPFS
12163+ return sb->s_magic == TMPFS_MAGIC;
12164+#else
12165+ return 0;
dece6358 12166+#endif
dece6358
AM
12167+}
12168+
1308ab2a 12169+static inline int au_test_ecryptfs(struct super_block *sb __maybe_unused)
1facf9fc 12170+{
1308ab2a 12171+#if defined(CONFIG_ECRYPT_FS) || defined(CONFIG_ECRYPT_FS_MODULE)
12172+ return !strcmp(au_sbtype(sb), "ecryptfs");
12173+#else
12174+ return 0;
12175+#endif
1facf9fc 12176+}
12177+
1308ab2a 12178+static inline int au_test_smbfs(struct super_block *sb __maybe_unused)
1facf9fc 12179+{
1308ab2a 12180+#if defined(CONFIG_SMB_FS) || defined(CONFIG_SMB_FS_MODULE)
12181+ return sb->s_magic == SMB_SUPER_MAGIC;
12182+#else
12183+ return 0;
1facf9fc 12184+#endif
1facf9fc 12185+}
12186+
1308ab2a 12187+static inline int au_test_ocfs2(struct super_block *sb __maybe_unused)
1facf9fc 12188+{
1308ab2a 12189+#if defined(CONFIG_OCFS2_FS) || defined(CONFIG_OCFS2_FS_MODULE)
12190+ return sb->s_magic == OCFS2_SUPER_MAGIC;
12191+#else
12192+ return 0;
12193+#endif
1facf9fc 12194+}
12195+
1308ab2a 12196+static inline int au_test_ocfs2_dlmfs(struct super_block *sb __maybe_unused)
1facf9fc 12197+{
1308ab2a 12198+#if defined(CONFIG_OCFS2_FS_O2CB) || defined(CONFIG_OCFS2_FS_O2CB_MODULE)
12199+ return sb->s_magic == DLMFS_MAGIC;
12200+#else
12201+ return 0;
12202+#endif
1facf9fc 12203+}
12204+
1308ab2a 12205+static inline int au_test_coda(struct super_block *sb __maybe_unused)
1facf9fc 12206+{
1308ab2a 12207+#if defined(CONFIG_CODA_FS) || defined(CONFIG_CODA_FS_MODULE)
12208+ return sb->s_magic == CODA_SUPER_MAGIC;
12209+#else
12210+ return 0;
12211+#endif
12212+}
12213+
12214+static inline int au_test_v9fs(struct super_block *sb __maybe_unused)
12215+{
12216+#if defined(CONFIG_9P_FS) || defined(CONFIG_9P_FS_MODULE)
12217+ return sb->s_magic == V9FS_MAGIC;
12218+#else
12219+ return 0;
12220+#endif
12221+}
12222+
12223+static inline int au_test_ext4(struct super_block *sb __maybe_unused)
12224+{
12225+#if defined(CONFIG_EXT4DEV_FS) || defined(CONFIG_EXT4DEV_FS_MODULE)
12226+ return sb->s_magic == EXT4_SUPER_MAGIC;
12227+#else
12228+ return 0;
12229+#endif
12230+}
12231+
12232+static inline int au_test_sysv(struct super_block *sb __maybe_unused)
12233+{
12234+#if defined(CONFIG_SYSV_FS) || defined(CONFIG_SYSV_FS_MODULE)
12235+ return !strcmp(au_sbtype(sb), "sysv");
12236+#else
12237+ return 0;
12238+#endif
12239+}
12240+
12241+static inline int au_test_ramfs(struct super_block *sb)
12242+{
12243+ return sb->s_magic == RAMFS_MAGIC;
12244+}
12245+
12246+static inline int au_test_ubifs(struct super_block *sb __maybe_unused)
12247+{
12248+#if defined(CONFIG_UBIFS_FS) || defined(CONFIG_UBIFS_FS_MODULE)
12249+ return sb->s_magic == UBIFS_SUPER_MAGIC;
12250+#else
12251+ return 0;
12252+#endif
12253+}
12254+
12255+static inline int au_test_procfs(struct super_block *sb __maybe_unused)
12256+{
12257+#ifdef CONFIG_PROC_FS
12258+ return sb->s_magic == PROC_SUPER_MAGIC;
12259+#else
12260+ return 0;
12261+#endif
12262+}
12263+
12264+static inline int au_test_sysfs(struct super_block *sb __maybe_unused)
12265+{
12266+#ifdef CONFIG_SYSFS
12267+ return sb->s_magic == SYSFS_MAGIC;
12268+#else
12269+ return 0;
12270+#endif
12271+}
12272+
12273+static inline int au_test_configfs(struct super_block *sb __maybe_unused)
12274+{
12275+#if defined(CONFIG_CONFIGFS_FS) || defined(CONFIG_CONFIGFS_FS_MODULE)
12276+ return sb->s_magic == CONFIGFS_MAGIC;
12277+#else
12278+ return 0;
12279+#endif
12280+}
12281+
12282+static inline int au_test_minix(struct super_block *sb __maybe_unused)
12283+{
12284+#if defined(CONFIG_MINIX_FS) || defined(CONFIG_MINIX_FS_MODULE)
12285+ return sb->s_magic == MINIX3_SUPER_MAGIC
12286+ || sb->s_magic == MINIX2_SUPER_MAGIC
12287+ || sb->s_magic == MINIX2_SUPER_MAGIC2
12288+ || sb->s_magic == MINIX_SUPER_MAGIC
12289+ || sb->s_magic == MINIX_SUPER_MAGIC2;
12290+#else
12291+ return 0;
12292+#endif
12293+}
12294+
12295+static inline int au_test_cifs(struct super_block *sb __maybe_unused)
12296+{
12297+#if defined(CONFIG_CIFS_FS) || defined(CONFIGCIFS_FS_MODULE)
12298+ return sb->s_magic == CIFS_MAGIC_NUMBER;
12299+#else
12300+ return 0;
12301+#endif
12302+}
12303+
12304+static inline int au_test_fat(struct super_block *sb __maybe_unused)
12305+{
12306+#if defined(CONFIG_FAT_FS) || defined(CONFIG_FAT_FS_MODULE)
12307+ return sb->s_magic == MSDOS_SUPER_MAGIC;
12308+#else
12309+ return 0;
12310+#endif
12311+}
12312+
12313+static inline int au_test_msdos(struct super_block *sb)
12314+{
12315+ return au_test_fat(sb);
12316+}
12317+
12318+static inline int au_test_vfat(struct super_block *sb)
12319+{
12320+ return au_test_fat(sb);
12321+}
12322+
12323+static inline int au_test_securityfs(struct super_block *sb __maybe_unused)
12324+{
12325+#ifdef CONFIG_SECURITYFS
12326+ return sb->s_magic == SECURITYFS_MAGIC;
12327+#else
12328+ return 0;
12329+#endif
12330+}
12331+
12332+static inline int au_test_squashfs(struct super_block *sb __maybe_unused)
12333+{
12334+#if defined(CONFIG_SQUASHFS) || defined(CONFIG_SQUASHFS_MODULE)
12335+ return sb->s_magic == SQUASHFS_MAGIC;
12336+#else
12337+ return 0;
12338+#endif
12339+}
12340+
12341+static inline int au_test_btrfs(struct super_block *sb __maybe_unused)
12342+{
12343+#if defined(CONFIG_BTRFS_FS) || defined(CONFIG_BTRFS_FS_MODULE)
12344+ return sb->s_magic == BTRFS_SUPER_MAGIC;
12345+#else
12346+ return 0;
12347+#endif
12348+}
12349+
12350+static inline int au_test_xenfs(struct super_block *sb __maybe_unused)
12351+{
12352+#if defined(CONFIG_XENFS) || defined(CONFIG_XENFS_MODULE)
12353+ return sb->s_magic == XENFS_SUPER_MAGIC;
12354+#else
12355+ return 0;
12356+#endif
12357+}
12358+
12359+static inline int au_test_debugfs(struct super_block *sb __maybe_unused)
12360+{
12361+#ifdef CONFIG_DEBUG_FS
12362+ return sb->s_magic == DEBUGFS_MAGIC;
12363+#else
12364+ return 0;
12365+#endif
12366+}
12367+
12368+static inline int au_test_nilfs(struct super_block *sb __maybe_unused)
12369+{
12370+#if defined(CONFIG_NILFS) || defined(CONFIG_NILFS_MODULE)
12371+ return sb->s_magic == NILFS_SUPER_MAGIC;
12372+#else
12373+ return 0;
12374+#endif
12375+}
12376+
4a4d8108
AM
12377+static inline int au_test_hfsplus(struct super_block *sb __maybe_unused)
12378+{
12379+#if defined(CONFIG_HFSPLUS_FS) || defined(CONFIG_HFSPLUS_FS_MODULE)
12380+ return sb->s_magic == HFSPLUS_SUPER_MAGIC;
12381+#else
12382+ return 0;
12383+#endif
12384+}
12385+
1308ab2a 12386+/* ---------------------------------------------------------------------- */
12387+/*
12388+ * they can't be an aufs branch.
12389+ */
12390+static inline int au_test_fs_unsuppoted(struct super_block *sb)
12391+{
12392+ return
12393+#ifndef CONFIG_AUFS_BR_RAMFS
12394+ au_test_ramfs(sb) ||
12395+#endif
12396+ au_test_procfs(sb)
12397+ || au_test_sysfs(sb)
12398+ || au_test_configfs(sb)
12399+ || au_test_debugfs(sb)
12400+ || au_test_securityfs(sb)
12401+ || au_test_xenfs(sb)
12402+ || au_test_ecryptfs(sb)
12403+ /* || !strcmp(au_sbtype(sb), "unionfs") */
12404+ || au_test_aufs(sb); /* will be supported in next version */
12405+}
12406+
12407+/*
12408+ * If the filesystem supports NFS-export, then it has to support NULL as
12409+ * a nameidata parameter for ->create(), ->lookup() and ->d_revalidate().
12410+ * We can apply this principle when we handle a lower filesystem.
12411+ */
12412+static inline int au_test_fs_null_nd(struct super_block *sb)
12413+{
12414+ return !!sb->s_export_op;
12415+}
12416+
12417+static inline int au_test_fs_remote(struct super_block *sb)
12418+{
12419+ return !au_test_tmpfs(sb)
12420+#ifdef CONFIG_AUFS_BR_RAMFS
12421+ && !au_test_ramfs(sb)
12422+#endif
12423+ && !(sb->s_type->fs_flags & FS_REQUIRES_DEV);
12424+}
12425+
12426+/* ---------------------------------------------------------------------- */
12427+
12428+/*
12429+ * Note: these functions (below) are created after reading ->getattr() in all
12430+ * filesystems under linux/fs. it means we have to do so in every update...
12431+ */
12432+
12433+/*
12434+ * some filesystems require getattr to refresh the inode attributes before
12435+ * referencing.
12436+ * in most cases, we can rely on the inode attribute in NFS (or every remote fs)
12437+ * and leave the work for d_revalidate()
12438+ */
12439+static inline int au_test_fs_refresh_iattr(struct super_block *sb)
12440+{
12441+ return au_test_nfs(sb)
12442+ || au_test_fuse(sb)
12443+ /* || au_test_smbfs(sb) */ /* untested */
12444+ /* || au_test_ocfs2(sb) */ /* untested */
12445+ /* || au_test_btrfs(sb) */ /* untested */
12446+ /* || au_test_coda(sb) */ /* untested */
12447+ /* || au_test_v9fs(sb) */ /* untested */
12448+ ;
12449+}
12450+
12451+/*
12452+ * filesystems which don't maintain i_size or i_blocks.
12453+ */
12454+static inline int au_test_fs_bad_iattr_size(struct super_block *sb)
12455+{
12456+ return au_test_xfs(sb)
4a4d8108
AM
12457+ || au_test_btrfs(sb)
12458+ || au_test_ubifs(sb)
12459+ || au_test_hfsplus(sb) /* maintained, but incorrect */
1308ab2a 12460+ /* || au_test_ext4(sb) */ /* untested */
12461+ /* || au_test_ocfs2(sb) */ /* untested */
12462+ /* || au_test_ocfs2_dlmfs(sb) */ /* untested */
12463+ /* || au_test_sysv(sb) */ /* untested */
1308ab2a 12464+ /* || au_test_minix(sb) */ /* untested */
12465+ ;
12466+}
12467+
12468+/*
12469+ * filesystems which don't store the correct value in some of their inode
12470+ * attributes.
12471+ */
12472+static inline int au_test_fs_bad_iattr(struct super_block *sb)
12473+{
12474+ return au_test_fs_bad_iattr_size(sb)
12475+ /* || au_test_cifs(sb) */ /* untested */
12476+ || au_test_fat(sb)
12477+ || au_test_msdos(sb)
12478+ || au_test_vfat(sb);
1facf9fc 12479+}
12480+
12481+/* they don't check i_nlink in link(2) */
12482+static inline int au_test_fs_no_limit_nlink(struct super_block *sb)
12483+{
12484+ return au_test_tmpfs(sb)
12485+#ifdef CONFIG_AUFS_BR_RAMFS
12486+ || au_test_ramfs(sb)
12487+#endif
4a4d8108
AM
12488+ || au_test_ubifs(sb)
12489+ || au_test_btrfs(sb)
12490+ || au_test_hfsplus(sb);
1facf9fc 12491+}
12492+
12493+/*
12494+ * filesystems which sets S_NOATIME and S_NOCMTIME.
12495+ */
12496+static inline int au_test_fs_notime(struct super_block *sb)
12497+{
12498+ return au_test_nfs(sb)
12499+ || au_test_fuse(sb)
dece6358 12500+ || au_test_ubifs(sb)
1facf9fc 12501+ /* || au_test_cifs(sb) */ /* untested */
1facf9fc 12502+ ;
12503+}
12504+
12505+/*
12506+ * filesystems which requires replacing i_mapping.
12507+ */
12508+static inline int au_test_fs_bad_mapping(struct super_block *sb)
12509+{
dece6358
AM
12510+ return au_test_fuse(sb)
12511+ || au_test_ubifs(sb);
1facf9fc 12512+}
12513+
12514+/* temporary support for i#1 in cramfs */
12515+static inline int au_test_fs_unique_ino(struct inode *inode)
12516+{
12517+ if (au_test_cramfs(inode->i_sb))
12518+ return inode->i_ino != 1;
12519+ return 1;
12520+}
12521+
12522+/* ---------------------------------------------------------------------- */
12523+
12524+/*
12525+ * the filesystem where the xino files placed must support i/o after unlink and
12526+ * maintain i_size and i_blocks.
12527+ */
12528+static inline int au_test_fs_bad_xino(struct super_block *sb)
12529+{
12530+ return au_test_fs_remote(sb)
12531+ || au_test_fs_bad_iattr_size(sb)
12532+#ifdef CONFIG_AUFS_BR_RAMFS
12533+ || !(au_test_ramfs(sb) || au_test_fs_null_nd(sb))
12534+#else
12535+ || !au_test_fs_null_nd(sb) /* to keep xino code simple */
12536+#endif
12537+ /* don't want unnecessary work for xino */
12538+ || au_test_aufs(sb)
1308ab2a 12539+ || au_test_ecryptfs(sb)
12540+ || au_test_nilfs(sb);
1facf9fc 12541+}
12542+
12543+static inline int au_test_fs_trunc_xino(struct super_block *sb)
12544+{
12545+ return au_test_tmpfs(sb)
12546+ || au_test_ramfs(sb);
12547+}
12548+
12549+/*
12550+ * test if the @sb is real-readonly.
12551+ */
12552+static inline int au_test_fs_rr(struct super_block *sb)
12553+{
12554+ return au_test_squashfs(sb)
12555+ || au_test_iso9660(sb)
12556+ || au_test_cramfs(sb)
12557+ || au_test_romfs(sb);
12558+}
12559+
12560+#endif /* __KERNEL__ */
12561+#endif /* __AUFS_FSTYPE_H__ */
7f207e10
AM
12562diff -urN /usr/share/empty/fs/aufs/hfsnotify.c linux/fs/aufs/hfsnotify.c
12563--- /usr/share/empty/fs/aufs/hfsnotify.c 1970-01-01 01:00:00.000000000 +0100
7ce627cf 12564+++ linux/fs/aufs/hfsnotify.c 2012-05-22 09:06:08.867458905 +0200
7eafdf33 12565@@ -0,0 +1,260 @@
1facf9fc 12566+/*
f6c5ef8b 12567+ * Copyright (C) 2005-2012 Junjiro R. Okajima
1facf9fc 12568+ *
12569+ * This program, aufs is free software; you can redistribute it and/or modify
12570+ * it under the terms of the GNU General Public License as published by
12571+ * the Free Software Foundation; either version 2 of the License, or
12572+ * (at your option) any later version.
dece6358
AM
12573+ *
12574+ * This program is distributed in the hope that it will be useful,
12575+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
12576+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12577+ * GNU General Public License for more details.
12578+ *
12579+ * You should have received a copy of the GNU General Public License
12580+ * along with this program; if not, write to the Free Software
12581+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 12582+ */
12583+
12584+/*
4a4d8108 12585+ * fsnotify for the lower directories
1facf9fc 12586+ */
12587+
12588+#include "aufs.h"
12589+
4a4d8108
AM
12590+/* FS_IN_IGNORED is unnecessary */
12591+static const __u32 AuHfsnMask = (FS_MOVED_TO | FS_MOVED_FROM | FS_DELETE
12592+ | FS_CREATE | FS_EVENT_ON_CHILD);
7f207e10 12593+static DECLARE_WAIT_QUEUE_HEAD(au_hfsn_wq);
7eafdf33 12594+static __cacheline_aligned_in_smp atomic64_t au_hfsn_ifree = ATOMIC64_INIT(0);
1facf9fc 12595+
0c5527e5 12596+static void au_hfsn_free_mark(struct fsnotify_mark *mark)
1facf9fc 12597+{
0c5527e5
AM
12598+ struct au_hnotify *hn = container_of(mark, struct au_hnotify,
12599+ hn_mark);
4a4d8108 12600+ AuDbg("here\n");
7eafdf33
AM
12601+ au_cache_free_hnotify(hn);
12602+ smp_mb__before_atomic_dec();
12603+ atomic64_dec(&au_hfsn_ifree);
12604+ wake_up(&au_hfsn_wq);
4a4d8108 12605+}
1facf9fc 12606+
027c5e7a 12607+static int au_hfsn_alloc(struct au_hinode *hinode)
4a4d8108 12608+{
027c5e7a
AM
12609+ struct au_hnotify *hn;
12610+ struct super_block *sb;
12611+ struct au_branch *br;
0c5527e5 12612+ struct fsnotify_mark *mark;
027c5e7a 12613+ aufs_bindex_t bindex;
1facf9fc 12614+
027c5e7a
AM
12615+ hn = hinode->hi_notify;
12616+ sb = hn->hn_aufs_inode->i_sb;
12617+ bindex = au_br_index(sb, hinode->hi_id);
12618+ br = au_sbr(sb, bindex);
0c5527e5
AM
12619+ mark = &hn->hn_mark;
12620+ fsnotify_init_mark(mark, au_hfsn_free_mark);
12621+ mark->mask = AuHfsnMask;
7f207e10
AM
12622+ /*
12623+ * by udba rename or rmdir, aufs assign a new inode to the known
12624+ * h_inode, so specify 1 to allow dups.
12625+ */
027c5e7a
AM
12626+ return fsnotify_add_mark(mark, br->br_hfsn_group, hinode->hi_inode,
12627+ /*mnt*/NULL, /*allow_dups*/1);
1facf9fc 12628+}
12629+
7eafdf33 12630+static int au_hfsn_free(struct au_hinode *hinode, struct au_hnotify *hn)
1facf9fc 12631+{
0c5527e5 12632+ struct fsnotify_mark *mark;
7eafdf33
AM
12633+ unsigned long long ull;
12634+
12635+ ull = atomic64_inc_return(&au_hfsn_ifree);
12636+ BUG_ON(!ull);
953406b4 12637+
0c5527e5
AM
12638+ mark = &hn->hn_mark;
12639+ fsnotify_destroy_mark(mark);
12640+ fsnotify_put_mark(mark);
7f207e10 12641+
7eafdf33
AM
12642+ /* free hn by myself */
12643+ return 0;
1facf9fc 12644+}
12645+
12646+/* ---------------------------------------------------------------------- */
12647+
4a4d8108 12648+static void au_hfsn_ctl(struct au_hinode *hinode, int do_set)
1facf9fc 12649+{
0c5527e5 12650+ struct fsnotify_mark *mark;
1facf9fc 12651+
0c5527e5
AM
12652+ mark = &hinode->hi_notify->hn_mark;
12653+ spin_lock(&mark->lock);
1facf9fc 12654+ if (do_set) {
0c5527e5
AM
12655+ AuDebugOn(mark->mask & AuHfsnMask);
12656+ mark->mask |= AuHfsnMask;
1facf9fc 12657+ } else {
0c5527e5
AM
12658+ AuDebugOn(!(mark->mask & AuHfsnMask));
12659+ mark->mask &= ~AuHfsnMask;
1facf9fc 12660+ }
0c5527e5 12661+ spin_unlock(&mark->lock);
4a4d8108 12662+ /* fsnotify_recalc_inode_mask(hinode->hi_inode); */
1facf9fc 12663+}
12664+
4a4d8108 12665+/* ---------------------------------------------------------------------- */
1facf9fc 12666+
4a4d8108
AM
12667+/* #define AuDbgHnotify */
12668+#ifdef AuDbgHnotify
12669+static char *au_hfsn_name(u32 mask)
12670+{
12671+#ifdef CONFIG_AUFS_DEBUG
12672+#define test_ret(flag) if (mask & flag) \
12673+ return #flag;
12674+ test_ret(FS_ACCESS);
12675+ test_ret(FS_MODIFY);
12676+ test_ret(FS_ATTRIB);
12677+ test_ret(FS_CLOSE_WRITE);
12678+ test_ret(FS_CLOSE_NOWRITE);
12679+ test_ret(FS_OPEN);
12680+ test_ret(FS_MOVED_FROM);
12681+ test_ret(FS_MOVED_TO);
12682+ test_ret(FS_CREATE);
12683+ test_ret(FS_DELETE);
12684+ test_ret(FS_DELETE_SELF);
12685+ test_ret(FS_MOVE_SELF);
12686+ test_ret(FS_UNMOUNT);
12687+ test_ret(FS_Q_OVERFLOW);
12688+ test_ret(FS_IN_IGNORED);
12689+ test_ret(FS_IN_ISDIR);
12690+ test_ret(FS_IN_ONESHOT);
12691+ test_ret(FS_EVENT_ON_CHILD);
12692+ return "";
12693+#undef test_ret
12694+#else
12695+ return "??";
12696+#endif
1facf9fc 12697+}
4a4d8108 12698+#endif
1facf9fc 12699+
12700+/* ---------------------------------------------------------------------- */
12701+
4a4d8108 12702+static int au_hfsn_handle_event(struct fsnotify_group *group,
0c5527e5
AM
12703+ struct fsnotify_mark *inode_mark,
12704+ struct fsnotify_mark *vfsmount_mark,
4a4d8108 12705+ struct fsnotify_event *event)
1facf9fc 12706+{
12707+ int err;
4a4d8108
AM
12708+ struct au_hnotify *hnotify;
12709+ struct inode *h_dir, *h_inode;
12710+ __u32 mask;
4a4d8108
AM
12711+ struct qstr h_child_qstr = {
12712+ .name = event->file_name,
12713+ .len = event->name_len
12714+ };
12715+
12716+ AuDebugOn(event->data_type != FSNOTIFY_EVENT_INODE);
1facf9fc 12717+
12718+ err = 0;
0c5527e5 12719+ /* if FS_UNMOUNT happens, there must be another bug */
4a4d8108
AM
12720+ mask = event->mask;
12721+ AuDebugOn(mask & FS_UNMOUNT);
0c5527e5 12722+ if (mask & (FS_IN_IGNORED | FS_UNMOUNT))
1facf9fc 12723+ goto out;
1facf9fc 12724+
4a4d8108
AM
12725+ h_dir = event->to_tell;
12726+ h_inode = event->inode;
12727+#ifdef AuDbgHnotify
12728+ au_debug(1);
12729+ if (1 || h_child_qstr.len != sizeof(AUFS_XINO_FNAME) - 1
12730+ || strncmp(h_child_qstr.name, AUFS_XINO_FNAME, h_child_qstr.len)) {
12731+ AuDbg("i%lu, mask 0x%x %s, hcname %.*s, hi%lu\n",
12732+ h_dir->i_ino, mask, au_hfsn_name(mask),
12733+ AuLNPair(&h_child_qstr), h_inode ? h_inode->i_ino : 0);
12734+ /* WARN_ON(1); */
1facf9fc 12735+ }
4a4d8108 12736+ au_debug(0);
1facf9fc 12737+#endif
4a4d8108 12738+
0c5527e5
AM
12739+ AuDebugOn(!inode_mark);
12740+ hnotify = container_of(inode_mark, struct au_hnotify, hn_mark);
12741+ err = au_hnotify(h_dir, hnotify, mask, &h_child_qstr, h_inode);
1facf9fc 12742+
4a4d8108
AM
12743+out:
12744+ return err;
12745+}
1facf9fc 12746+
027c5e7a 12747+/* isn't it waste to ask every registered 'group'? */
7f207e10 12748+/* copied from linux/fs/notify/inotify/inotify_fsnotiry.c */
4a4d8108 12749+/* it should be exported to modules */
7f207e10
AM
12750+static bool au_hfsn_should_send_event(struct fsnotify_group *group,
12751+ struct inode *h_inode,
0c5527e5
AM
12752+ struct fsnotify_mark *inode_mark,
12753+ struct fsnotify_mark *vfsmount_mark,
12754+ __u32 mask, void *data, int data_type)
4a4d8108 12755+{
4a4d8108 12756+ mask = (mask & ~FS_EVENT_ON_CHILD);
7f207e10 12757+ return inode_mark->mask & mask;
4a4d8108
AM
12758+}
12759+
12760+static struct fsnotify_ops au_hfsn_ops = {
12761+ .should_send_event = au_hfsn_should_send_event,
12762+ .handle_event = au_hfsn_handle_event
12763+};
12764+
12765+/* ---------------------------------------------------------------------- */
12766+
027c5e7a
AM
12767+static void au_hfsn_fin_br(struct au_branch *br)
12768+{
12769+ if (br->br_hfsn_group)
12770+ fsnotify_put_group(br->br_hfsn_group);
12771+}
12772+
12773+static int au_hfsn_init_br(struct au_branch *br, int perm)
12774+{
12775+ br->br_hfsn_group = NULL;
12776+ br->br_hfsn_ops = au_hfsn_ops;
12777+ return 0;
12778+}
12779+
12780+static int au_hfsn_reset_br(unsigned int udba, struct au_branch *br, int perm)
4a4d8108
AM
12781+{
12782+ int err;
1facf9fc 12783+
4a4d8108 12784+ err = 0;
027c5e7a
AM
12785+ if (udba != AuOpt_UDBA_HNOTIFY
12786+ || !au_br_hnotifyable(perm)) {
12787+ au_hfsn_fin_br(br);
12788+ br->br_hfsn_group = NULL;
12789+ goto out;
12790+ }
12791+
12792+ if (br->br_hfsn_group)
12793+ goto out;
12794+
12795+ br->br_hfsn_group = fsnotify_alloc_group(&br->br_hfsn_ops);
12796+ if (IS_ERR(br->br_hfsn_group)) {
12797+ err = PTR_ERR(br->br_hfsn_group);
0c5527e5 12798+ pr_err("fsnotify_alloc_group() failed, %d\n", err);
027c5e7a 12799+ br->br_hfsn_group = NULL;
4a4d8108 12800+ }
1facf9fc 12801+
027c5e7a 12802+out:
1facf9fc 12803+ AuTraceErr(err);
12804+ return err;
12805+}
12806+
7eafdf33
AM
12807+/* ---------------------------------------------------------------------- */
12808+
12809+static void au_hfsn_fin(void)
12810+{
12811+ AuDbg("au_hfsn_ifree %lld\n", (long long)atomic64_read(&au_hfsn_ifree));
12812+ wait_event(au_hfsn_wq, !atomic64_read(&au_hfsn_ifree));
12813+}
12814+
4a4d8108
AM
12815+const struct au_hnotify_op au_hnotify_op = {
12816+ .ctl = au_hfsn_ctl,
12817+ .alloc = au_hfsn_alloc,
12818+ .free = au_hfsn_free,
1facf9fc 12819+
7eafdf33
AM
12820+ .fin = au_hfsn_fin,
12821+
027c5e7a
AM
12822+ .reset_br = au_hfsn_reset_br,
12823+ .fin_br = au_hfsn_fin_br,
12824+ .init_br = au_hfsn_init_br
4a4d8108 12825+};
7f207e10
AM
12826diff -urN /usr/share/empty/fs/aufs/hfsplus.c linux/fs/aufs/hfsplus.c
12827--- /usr/share/empty/fs/aufs/hfsplus.c 1970-01-01 01:00:00.000000000 +0100
7ce627cf 12828+++ linux/fs/aufs/hfsplus.c 2012-05-22 09:06:08.867458905 +0200
f6c5ef8b 12829@@ -0,0 +1,57 @@
4a4d8108 12830+/*
f6c5ef8b 12831+ * Copyright (C) 2010-2012 Junjiro R. Okajima
4a4d8108
AM
12832+ *
12833+ * This program, aufs is free software; you can redistribute it and/or modify
12834+ * it under the terms of the GNU General Public License as published by
12835+ * the Free Software Foundation; either version 2 of the License, or
12836+ * (at your option) any later version.
12837+ *
12838+ * This program is distributed in the hope that it will be useful,
12839+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
12840+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12841+ * GNU General Public License for more details.
12842+ *
12843+ * You should have received a copy of the GNU General Public License
12844+ * along with this program; if not, write to the Free Software
12845+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
12846+ */
1facf9fc 12847+
4a4d8108
AM
12848+/*
12849+ * special support for filesystems which aqucires an inode mutex
12850+ * at final closing a file, eg, hfsplus.
12851+ *
12852+ * This trick is very simple and stupid, just to open the file before really
12853+ * neceeary open to tell hfsplus that this is not the final closing.
12854+ * The caller should call au_h_open_pre() after acquiring the inode mutex,
12855+ * and au_h_open_post() after releasing it.
12856+ */
1facf9fc 12857+
4a4d8108 12858+#include "aufs.h"
1facf9fc 12859+
4a4d8108
AM
12860+struct file *au_h_open_pre(struct dentry *dentry, aufs_bindex_t bindex)
12861+{
12862+ struct file *h_file;
12863+ struct dentry *h_dentry;
1facf9fc 12864+
4a4d8108
AM
12865+ h_dentry = au_h_dptr(dentry, bindex);
12866+ AuDebugOn(!h_dentry);
12867+ AuDebugOn(!h_dentry->d_inode);
12868+ IMustLock(h_dentry->d_inode);
12869+
12870+ h_file = NULL;
12871+ if (au_test_hfsplus(h_dentry->d_sb)
12872+ && S_ISREG(h_dentry->d_inode->i_mode))
12873+ h_file = au_h_open(dentry, bindex,
12874+ O_RDONLY | O_NOATIME | O_LARGEFILE,
12875+ /*file*/NULL);
12876+ return h_file;
1facf9fc 12877+}
12878+
4a4d8108
AM
12879+void au_h_open_post(struct dentry *dentry, aufs_bindex_t bindex,
12880+ struct file *h_file)
12881+{
12882+ if (h_file) {
12883+ fput(h_file);
12884+ au_sbr_put(dentry->d_sb, bindex);
12885+ }
12886+}
7f207e10
AM
12887diff -urN /usr/share/empty/fs/aufs/hnotify.c linux/fs/aufs/hnotify.c
12888--- /usr/share/empty/fs/aufs/hnotify.c 1970-01-01 01:00:00.000000000 +0100
7ce627cf 12889+++ linux/fs/aufs/hnotify.c 2012-05-22 09:06:08.867458905 +0200
53392da6 12890@@ -0,0 +1,712 @@
e49829fe 12891+/*
f6c5ef8b 12892+ * Copyright (C) 2005-2012 Junjiro R. Okajima
e49829fe
JR
12893+ *
12894+ * This program, aufs is free software; you can redistribute it and/or modify
12895+ * it under the terms of the GNU General Public License as published by
12896+ * the Free Software Foundation; either version 2 of the License, or
12897+ * (at your option) any later version.
12898+ *
12899+ * This program is distributed in the hope that it will be useful,
12900+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
12901+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12902+ * GNU General Public License for more details.
12903+ *
12904+ * You should have received a copy of the GNU General Public License
12905+ * along with this program; if not, write to the Free Software
12906+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
12907+ */
12908+
12909+/*
7f207e10 12910+ * abstraction to notify the direct changes on lower directories
e49829fe
JR
12911+ */
12912+
12913+#include "aufs.h"
12914+
027c5e7a 12915+int au_hn_alloc(struct au_hinode *hinode, struct inode *inode)
e49829fe
JR
12916+{
12917+ int err;
7f207e10 12918+ struct au_hnotify *hn;
1facf9fc 12919+
4a4d8108
AM
12920+ err = -ENOMEM;
12921+ hn = au_cache_alloc_hnotify();
12922+ if (hn) {
12923+ hn->hn_aufs_inode = inode;
027c5e7a
AM
12924+ hinode->hi_notify = hn;
12925+ err = au_hnotify_op.alloc(hinode);
12926+ AuTraceErr(err);
12927+ if (unlikely(err)) {
12928+ hinode->hi_notify = NULL;
4a4d8108
AM
12929+ au_cache_free_hnotify(hn);
12930+ /*
12931+ * The upper dir was removed by udba, but the same named
12932+ * dir left. In this case, aufs assignes a new inode
12933+ * number and set the monitor again.
12934+ * For the lower dir, the old monitnor is still left.
12935+ */
12936+ if (err == -EEXIST)
12937+ err = 0;
12938+ }
1308ab2a 12939+ }
1308ab2a 12940+
027c5e7a 12941+ AuTraceErr(err);
1308ab2a 12942+ return err;
dece6358 12943+}
1facf9fc 12944+
4a4d8108 12945+void au_hn_free(struct au_hinode *hinode)
dece6358 12946+{
4a4d8108 12947+ struct au_hnotify *hn;
1facf9fc 12948+
4a4d8108
AM
12949+ hn = hinode->hi_notify;
12950+ if (hn) {
4a4d8108 12951+ hinode->hi_notify = NULL;
7eafdf33
AM
12952+ if (au_hnotify_op.free(hinode, hn))
12953+ au_cache_free_hnotify(hn);
4a4d8108
AM
12954+ }
12955+}
dece6358 12956+
4a4d8108 12957+/* ---------------------------------------------------------------------- */
dece6358 12958+
4a4d8108
AM
12959+void au_hn_ctl(struct au_hinode *hinode, int do_set)
12960+{
12961+ if (hinode->hi_notify)
12962+ au_hnotify_op.ctl(hinode, do_set);
12963+}
12964+
12965+void au_hn_reset(struct inode *inode, unsigned int flags)
12966+{
12967+ aufs_bindex_t bindex, bend;
12968+ struct inode *hi;
12969+ struct dentry *iwhdentry;
1facf9fc 12970+
1308ab2a 12971+ bend = au_ibend(inode);
4a4d8108
AM
12972+ for (bindex = au_ibstart(inode); bindex <= bend; bindex++) {
12973+ hi = au_h_iptr(inode, bindex);
12974+ if (!hi)
12975+ continue;
1308ab2a 12976+
4a4d8108
AM
12977+ /* mutex_lock_nested(&hi->i_mutex, AuLsc_I_CHILD); */
12978+ iwhdentry = au_hi_wh(inode, bindex);
12979+ if (iwhdentry)
12980+ dget(iwhdentry);
12981+ au_igrab(hi);
12982+ au_set_h_iptr(inode, bindex, NULL, 0);
12983+ au_set_h_iptr(inode, bindex, au_igrab(hi),
12984+ flags & ~AuHi_XINO);
12985+ iput(hi);
12986+ dput(iwhdentry);
12987+ /* mutex_unlock(&hi->i_mutex); */
1facf9fc 12988+ }
1facf9fc 12989+}
12990+
1308ab2a 12991+/* ---------------------------------------------------------------------- */
1facf9fc 12992+
4a4d8108 12993+static int hn_xino(struct inode *inode, struct inode *h_inode)
1facf9fc 12994+{
4a4d8108
AM
12995+ int err;
12996+ aufs_bindex_t bindex, bend, bfound, bstart;
12997+ struct inode *h_i;
1facf9fc 12998+
4a4d8108
AM
12999+ err = 0;
13000+ if (unlikely(inode->i_ino == AUFS_ROOT_INO)) {
13001+ pr_warning("branch root dir was changed\n");
13002+ goto out;
13003+ }
1facf9fc 13004+
4a4d8108
AM
13005+ bfound = -1;
13006+ bend = au_ibend(inode);
13007+ bstart = au_ibstart(inode);
13008+#if 0 /* reserved for future use */
13009+ if (bindex == bend) {
13010+ /* keep this ino in rename case */
13011+ goto out;
13012+ }
13013+#endif
13014+ for (bindex = bstart; bindex <= bend; bindex++)
13015+ if (au_h_iptr(inode, bindex) == h_inode) {
13016+ bfound = bindex;
13017+ break;
13018+ }
13019+ if (bfound < 0)
1308ab2a 13020+ goto out;
1facf9fc 13021+
4a4d8108
AM
13022+ for (bindex = bstart; bindex <= bend; bindex++) {
13023+ h_i = au_h_iptr(inode, bindex);
13024+ if (!h_i)
13025+ continue;
1facf9fc 13026+
4a4d8108
AM
13027+ err = au_xino_write(inode->i_sb, bindex, h_i->i_ino, /*ino*/0);
13028+ /* ignore this error */
13029+ /* bad action? */
1facf9fc 13030+ }
1facf9fc 13031+
4a4d8108 13032+ /* children inode number will be broken */
1facf9fc 13033+
4f0767ce 13034+out:
4a4d8108
AM
13035+ AuTraceErr(err);
13036+ return err;
1facf9fc 13037+}
13038+
4a4d8108 13039+static int hn_gen_tree(struct dentry *dentry)
1facf9fc 13040+{
4a4d8108
AM
13041+ int err, i, j, ndentry;
13042+ struct au_dcsub_pages dpages;
13043+ struct au_dpage *dpage;
13044+ struct dentry **dentries;
1facf9fc 13045+
4a4d8108
AM
13046+ err = au_dpages_init(&dpages, GFP_NOFS);
13047+ if (unlikely(err))
13048+ goto out;
13049+ err = au_dcsub_pages(&dpages, dentry, NULL, NULL);
13050+ if (unlikely(err))
13051+ goto out_dpages;
1facf9fc 13052+
4a4d8108
AM
13053+ for (i = 0; i < dpages.ndpage; i++) {
13054+ dpage = dpages.dpages + i;
13055+ dentries = dpage->dentries;
13056+ ndentry = dpage->ndentry;
13057+ for (j = 0; j < ndentry; j++) {
13058+ struct dentry *d;
13059+
13060+ d = dentries[j];
13061+ if (IS_ROOT(d))
13062+ continue;
13063+
4a4d8108
AM
13064+ au_digen_dec(d);
13065+ if (d->d_inode)
13066+ /* todo: reset children xino?
13067+ cached children only? */
13068+ au_iigen_dec(d->d_inode);
1308ab2a 13069+ }
dece6358 13070+ }
1facf9fc 13071+
4f0767ce 13072+out_dpages:
4a4d8108 13073+ au_dpages_free(&dpages);
dece6358 13074+
027c5e7a 13075+#if 0
4a4d8108
AM
13076+ /* discard children */
13077+ dentry_unhash(dentry);
13078+ dput(dentry);
027c5e7a 13079+#endif
4f0767ce 13080+out:
dece6358
AM
13081+ return err;
13082+}
13083+
1308ab2a 13084+/*
4a4d8108 13085+ * return 0 if processed.
1308ab2a 13086+ */
4a4d8108
AM
13087+static int hn_gen_by_inode(char *name, unsigned int nlen, struct inode *inode,
13088+ const unsigned int isdir)
dece6358 13089+{
1308ab2a 13090+ int err;
4a4d8108
AM
13091+ struct dentry *d;
13092+ struct qstr *dname;
1facf9fc 13093+
4a4d8108
AM
13094+ err = 1;
13095+ if (unlikely(inode->i_ino == AUFS_ROOT_INO)) {
13096+ pr_warning("branch root dir was changed\n");
13097+ err = 0;
13098+ goto out;
13099+ }
dece6358 13100+
4a4d8108
AM
13101+ if (!isdir) {
13102+ AuDebugOn(!name);
13103+ au_iigen_dec(inode);
027c5e7a 13104+ spin_lock(&inode->i_lock);
4a4d8108 13105+ list_for_each_entry(d, &inode->i_dentry, d_alias) {
027c5e7a 13106+ spin_lock(&d->d_lock);
4a4d8108
AM
13107+ dname = &d->d_name;
13108+ if (dname->len != nlen
027c5e7a
AM
13109+ && memcmp(dname->name, name, nlen)) {
13110+ spin_unlock(&d->d_lock);
4a4d8108 13111+ continue;
027c5e7a 13112+ }
4a4d8108 13113+ err = 0;
4a4d8108
AM
13114+ au_digen_dec(d);
13115+ spin_unlock(&d->d_lock);
13116+ break;
1facf9fc 13117+ }
027c5e7a 13118+ spin_unlock(&inode->i_lock);
1308ab2a 13119+ } else {
027c5e7a 13120+ au_fset_si(au_sbi(inode->i_sb), FAILED_REFRESH_DIR);
4a4d8108
AM
13121+ d = d_find_alias(inode);
13122+ if (!d) {
13123+ au_iigen_dec(inode);
13124+ goto out;
13125+ }
1facf9fc 13126+
027c5e7a 13127+ spin_lock(&d->d_lock);
4a4d8108 13128+ dname = &d->d_name;
027c5e7a
AM
13129+ if (dname->len == nlen && !memcmp(dname->name, name, nlen)) {
13130+ spin_unlock(&d->d_lock);
4a4d8108 13131+ err = hn_gen_tree(d);
027c5e7a
AM
13132+ spin_lock(&d->d_lock);
13133+ }
13134+ spin_unlock(&d->d_lock);
4a4d8108
AM
13135+ dput(d);
13136+ }
1facf9fc 13137+
4f0767ce 13138+out:
4a4d8108 13139+ AuTraceErr(err);
1308ab2a 13140+ return err;
13141+}
dece6358 13142+
4a4d8108 13143+static int hn_gen_by_name(struct dentry *dentry, const unsigned int isdir)
1facf9fc 13144+{
4a4d8108
AM
13145+ int err;
13146+ struct inode *inode;
1facf9fc 13147+
4a4d8108
AM
13148+ inode = dentry->d_inode;
13149+ if (IS_ROOT(dentry)
13150+ /* || (inode && inode->i_ino == AUFS_ROOT_INO) */
13151+ ) {
13152+ pr_warning("branch root dir was changed\n");
13153+ return 0;
13154+ }
1308ab2a 13155+
4a4d8108
AM
13156+ err = 0;
13157+ if (!isdir) {
4a4d8108
AM
13158+ au_digen_dec(dentry);
13159+ if (inode)
13160+ au_iigen_dec(inode);
13161+ } else {
027c5e7a 13162+ au_fset_si(au_sbi(dentry->d_sb), FAILED_REFRESH_DIR);
4a4d8108
AM
13163+ if (inode)
13164+ err = hn_gen_tree(dentry);
13165+ }
13166+
13167+ AuTraceErr(err);
13168+ return err;
1facf9fc 13169+}
13170+
4a4d8108 13171+/* ---------------------------------------------------------------------- */
1facf9fc 13172+
4a4d8108
AM
13173+/* hnotify job flags */
13174+#define AuHnJob_XINO0 1
13175+#define AuHnJob_GEN (1 << 1)
13176+#define AuHnJob_DIRENT (1 << 2)
13177+#define AuHnJob_ISDIR (1 << 3)
13178+#define AuHnJob_TRYXINO0 (1 << 4)
13179+#define AuHnJob_MNTPNT (1 << 5)
13180+#define au_ftest_hnjob(flags, name) ((flags) & AuHnJob_##name)
7f207e10
AM
13181+#define au_fset_hnjob(flags, name) \
13182+ do { (flags) |= AuHnJob_##name; } while (0)
13183+#define au_fclr_hnjob(flags, name) \
13184+ do { (flags) &= ~AuHnJob_##name; } while (0)
1facf9fc 13185+
4a4d8108
AM
13186+enum {
13187+ AuHn_CHILD,
13188+ AuHn_PARENT,
13189+ AuHnLast
13190+};
1facf9fc 13191+
4a4d8108
AM
13192+struct au_hnotify_args {
13193+ struct inode *h_dir, *dir, *h_child_inode;
13194+ u32 mask;
13195+ unsigned int flags[AuHnLast];
13196+ unsigned int h_child_nlen;
13197+ char h_child_name[];
13198+};
1facf9fc 13199+
4a4d8108
AM
13200+struct hn_job_args {
13201+ unsigned int flags;
13202+ struct inode *inode, *h_inode, *dir, *h_dir;
13203+ struct dentry *dentry;
13204+ char *h_name;
13205+ int h_nlen;
13206+};
1308ab2a 13207+
4a4d8108
AM
13208+static int hn_job(struct hn_job_args *a)
13209+{
13210+ const unsigned int isdir = au_ftest_hnjob(a->flags, ISDIR);
1308ab2a 13211+
4a4d8108
AM
13212+ /* reset xino */
13213+ if (au_ftest_hnjob(a->flags, XINO0) && a->inode)
13214+ hn_xino(a->inode, a->h_inode); /* ignore this error */
1308ab2a 13215+
4a4d8108
AM
13216+ if (au_ftest_hnjob(a->flags, TRYXINO0)
13217+ && a->inode
13218+ && a->h_inode) {
13219+ mutex_lock_nested(&a->h_inode->i_mutex, AuLsc_I_CHILD);
13220+ if (!a->h_inode->i_nlink)
13221+ hn_xino(a->inode, a->h_inode); /* ignore this error */
13222+ mutex_unlock(&a->h_inode->i_mutex);
1308ab2a 13223+ }
1facf9fc 13224+
4a4d8108
AM
13225+ /* make the generation obsolete */
13226+ if (au_ftest_hnjob(a->flags, GEN)) {
13227+ int err = -1;
13228+ if (a->inode)
13229+ err = hn_gen_by_inode(a->h_name, a->h_nlen, a->inode,
13230+ isdir);
13231+ if (err && a->dentry)
13232+ hn_gen_by_name(a->dentry, isdir);
13233+ /* ignore this error */
1facf9fc 13234+ }
1facf9fc 13235+
4a4d8108
AM
13236+ /* make dir entries obsolete */
13237+ if (au_ftest_hnjob(a->flags, DIRENT) && a->inode) {
13238+ struct au_vdir *vdir;
1facf9fc 13239+
4a4d8108
AM
13240+ vdir = au_ivdir(a->inode);
13241+ if (vdir)
13242+ vdir->vd_jiffy = 0;
13243+ /* IMustLock(a->inode); */
13244+ /* a->inode->i_version++; */
13245+ }
1facf9fc 13246+
4a4d8108
AM
13247+ /* can do nothing but warn */
13248+ if (au_ftest_hnjob(a->flags, MNTPNT)
13249+ && a->dentry
13250+ && d_mountpoint(a->dentry))
13251+ pr_warning("mount-point %.*s is removed or renamed\n",
13252+ AuDLNPair(a->dentry));
1facf9fc 13253+
4a4d8108 13254+ return 0;
1308ab2a 13255+}
1facf9fc 13256+
1308ab2a 13257+/* ---------------------------------------------------------------------- */
1facf9fc 13258+
4a4d8108
AM
13259+static struct dentry *lookup_wlock_by_name(char *name, unsigned int nlen,
13260+ struct inode *dir)
1308ab2a 13261+{
4a4d8108
AM
13262+ struct dentry *dentry, *d, *parent;
13263+ struct qstr *dname;
1308ab2a 13264+
4a4d8108
AM
13265+ parent = d_find_alias(dir);
13266+ if (!parent)
13267+ return NULL;
1308ab2a 13268+
4a4d8108 13269+ dentry = NULL;
027c5e7a 13270+ spin_lock(&parent->d_lock);
4a4d8108
AM
13271+ list_for_each_entry(d, &parent->d_subdirs, d_u.d_child) {
13272+ /* AuDbg("%.*s\n", AuDLNPair(d)); */
027c5e7a 13273+ spin_lock_nested(&d->d_lock, DENTRY_D_LOCK_NESTED);
4a4d8108
AM
13274+ dname = &d->d_name;
13275+ if (dname->len != nlen || memcmp(dname->name, name, nlen))
027c5e7a
AM
13276+ goto cont_unlock;
13277+ if (au_di(d))
13278+ au_digen_dec(d);
13279+ else
13280+ goto cont_unlock;
13281+ if (d->d_count) {
13282+ dentry = dget_dlock(d);
4a4d8108 13283+ spin_unlock(&d->d_lock);
027c5e7a 13284+ break;
dece6358 13285+ }
1facf9fc 13286+
027c5e7a
AM
13287+ cont_unlock:
13288+ spin_unlock(&d->d_lock);
1308ab2a 13289+ }
027c5e7a 13290+ spin_unlock(&parent->d_lock);
4a4d8108 13291+ dput(parent);
1facf9fc 13292+
4a4d8108
AM
13293+ if (dentry)
13294+ di_write_lock_child(dentry);
1308ab2a 13295+
4a4d8108
AM
13296+ return dentry;
13297+}
dece6358 13298+
4a4d8108
AM
13299+static struct inode *lookup_wlock_by_ino(struct super_block *sb,
13300+ aufs_bindex_t bindex, ino_t h_ino)
13301+{
13302+ struct inode *inode;
13303+ ino_t ino;
13304+ int err;
13305+
13306+ inode = NULL;
13307+ err = au_xino_read(sb, bindex, h_ino, &ino);
13308+ if (!err && ino)
13309+ inode = ilookup(sb, ino);
13310+ if (!inode)
13311+ goto out;
13312+
13313+ if (unlikely(inode->i_ino == AUFS_ROOT_INO)) {
13314+ pr_warning("wrong root branch\n");
13315+ iput(inode);
13316+ inode = NULL;
13317+ goto out;
1308ab2a 13318+ }
13319+
4a4d8108 13320+ ii_write_lock_child(inode);
1308ab2a 13321+
4f0767ce 13322+out:
4a4d8108 13323+ return inode;
dece6358
AM
13324+}
13325+
4a4d8108 13326+static void au_hn_bh(void *_args)
1facf9fc 13327+{
4a4d8108
AM
13328+ struct au_hnotify_args *a = _args;
13329+ struct super_block *sb;
13330+ aufs_bindex_t bindex, bend, bfound;
13331+ unsigned char xino, try_iput;
1facf9fc 13332+ int err;
1308ab2a 13333+ struct inode *inode;
4a4d8108
AM
13334+ ino_t h_ino;
13335+ struct hn_job_args args;
13336+ struct dentry *dentry;
13337+ struct au_sbinfo *sbinfo;
1facf9fc 13338+
4a4d8108
AM
13339+ AuDebugOn(!_args);
13340+ AuDebugOn(!a->h_dir);
13341+ AuDebugOn(!a->dir);
13342+ AuDebugOn(!a->mask);
13343+ AuDbg("mask 0x%x, i%lu, hi%lu, hci%lu\n",
13344+ a->mask, a->dir->i_ino, a->h_dir->i_ino,
13345+ a->h_child_inode ? a->h_child_inode->i_ino : 0);
1facf9fc 13346+
4a4d8108
AM
13347+ inode = NULL;
13348+ dentry = NULL;
13349+ /*
13350+ * do not lock a->dir->i_mutex here
13351+ * because of d_revalidate() may cause a deadlock.
13352+ */
13353+ sb = a->dir->i_sb;
13354+ AuDebugOn(!sb);
13355+ sbinfo = au_sbi(sb);
13356+ AuDebugOn(!sbinfo);
7f207e10 13357+ si_write_lock(sb, AuLock_NOPLMW);
1facf9fc 13358+
4a4d8108
AM
13359+ ii_read_lock_parent(a->dir);
13360+ bfound = -1;
13361+ bend = au_ibend(a->dir);
13362+ for (bindex = au_ibstart(a->dir); bindex <= bend; bindex++)
13363+ if (au_h_iptr(a->dir, bindex) == a->h_dir) {
13364+ bfound = bindex;
13365+ break;
13366+ }
13367+ ii_read_unlock(a->dir);
13368+ if (unlikely(bfound < 0))
13369+ goto out;
1facf9fc 13370+
4a4d8108
AM
13371+ xino = !!au_opt_test(au_mntflags(sb), XINO);
13372+ h_ino = 0;
13373+ if (a->h_child_inode)
13374+ h_ino = a->h_child_inode->i_ino;
1facf9fc 13375+
4a4d8108
AM
13376+ if (a->h_child_nlen
13377+ && (au_ftest_hnjob(a->flags[AuHn_CHILD], GEN)
13378+ || au_ftest_hnjob(a->flags[AuHn_CHILD], MNTPNT)))
13379+ dentry = lookup_wlock_by_name(a->h_child_name, a->h_child_nlen,
13380+ a->dir);
13381+ try_iput = 0;
13382+ if (dentry)
13383+ inode = dentry->d_inode;
13384+ if (xino && !inode && h_ino
13385+ && (au_ftest_hnjob(a->flags[AuHn_CHILD], XINO0)
13386+ || au_ftest_hnjob(a->flags[AuHn_CHILD], TRYXINO0)
13387+ || au_ftest_hnjob(a->flags[AuHn_CHILD], GEN))) {
13388+ inode = lookup_wlock_by_ino(sb, bfound, h_ino);
13389+ try_iput = 1;
13390+ }
1facf9fc 13391+
4a4d8108
AM
13392+ args.flags = a->flags[AuHn_CHILD];
13393+ args.dentry = dentry;
13394+ args.inode = inode;
13395+ args.h_inode = a->h_child_inode;
13396+ args.dir = a->dir;
13397+ args.h_dir = a->h_dir;
13398+ args.h_name = a->h_child_name;
13399+ args.h_nlen = a->h_child_nlen;
13400+ err = hn_job(&args);
13401+ if (dentry) {
027c5e7a 13402+ if (au_di(dentry))
4a4d8108
AM
13403+ di_write_unlock(dentry);
13404+ dput(dentry);
13405+ }
13406+ if (inode && try_iput) {
13407+ ii_write_unlock(inode);
13408+ iput(inode);
13409+ }
1facf9fc 13410+
4a4d8108
AM
13411+ ii_write_lock_parent(a->dir);
13412+ args.flags = a->flags[AuHn_PARENT];
13413+ args.dentry = NULL;
13414+ args.inode = a->dir;
13415+ args.h_inode = a->h_dir;
13416+ args.dir = NULL;
13417+ args.h_dir = NULL;
13418+ args.h_name = NULL;
13419+ args.h_nlen = 0;
13420+ err = hn_job(&args);
13421+ ii_write_unlock(a->dir);
1facf9fc 13422+
4f0767ce 13423+out:
4a4d8108
AM
13424+ iput(a->h_child_inode);
13425+ iput(a->h_dir);
13426+ iput(a->dir);
027c5e7a
AM
13427+ si_write_unlock(sb);
13428+ au_nwt_done(&sbinfo->si_nowait);
1308ab2a 13429+ kfree(a);
dece6358 13430+}
1facf9fc 13431+
4a4d8108
AM
13432+/* ---------------------------------------------------------------------- */
13433+
13434+int au_hnotify(struct inode *h_dir, struct au_hnotify *hnotify, u32 mask,
13435+ struct qstr *h_child_qstr, struct inode *h_child_inode)
dece6358 13436+{
4a4d8108 13437+ int err, len;
53392da6 13438+ unsigned int flags[AuHnLast], f;
4a4d8108
AM
13439+ unsigned char isdir, isroot, wh;
13440+ struct inode *dir;
13441+ struct au_hnotify_args *args;
13442+ char *p, *h_child_name;
dece6358 13443+
1308ab2a 13444+ err = 0;
4a4d8108
AM
13445+ AuDebugOn(!hnotify || !hnotify->hn_aufs_inode);
13446+ dir = igrab(hnotify->hn_aufs_inode);
13447+ if (!dir)
13448+ goto out;
1facf9fc 13449+
4a4d8108
AM
13450+ isroot = (dir->i_ino == AUFS_ROOT_INO);
13451+ wh = 0;
13452+ h_child_name = (void *)h_child_qstr->name;
13453+ len = h_child_qstr->len;
13454+ if (h_child_name) {
13455+ if (len > AUFS_WH_PFX_LEN
13456+ && !memcmp(h_child_name, AUFS_WH_PFX, AUFS_WH_PFX_LEN)) {
13457+ h_child_name += AUFS_WH_PFX_LEN;
13458+ len -= AUFS_WH_PFX_LEN;
13459+ wh = 1;
13460+ }
1facf9fc 13461+ }
dece6358 13462+
4a4d8108
AM
13463+ isdir = 0;
13464+ if (h_child_inode)
13465+ isdir = !!S_ISDIR(h_child_inode->i_mode);
13466+ flags[AuHn_PARENT] = AuHnJob_ISDIR;
13467+ flags[AuHn_CHILD] = 0;
13468+ if (isdir)
13469+ flags[AuHn_CHILD] = AuHnJob_ISDIR;
13470+ au_fset_hnjob(flags[AuHn_PARENT], DIRENT);
13471+ au_fset_hnjob(flags[AuHn_CHILD], GEN);
13472+ switch (mask & FS_EVENTS_POSS_ON_CHILD) {
13473+ case FS_MOVED_FROM:
13474+ case FS_MOVED_TO:
13475+ au_fset_hnjob(flags[AuHn_CHILD], XINO0);
13476+ au_fset_hnjob(flags[AuHn_CHILD], MNTPNT);
13477+ /*FALLTHROUGH*/
13478+ case FS_CREATE:
13479+ AuDebugOn(!h_child_name || !h_child_inode);
13480+ break;
1facf9fc 13481+
4a4d8108
AM
13482+ case FS_DELETE:
13483+ /*
13484+ * aufs never be able to get this child inode.
13485+ * revalidation should be in d_revalidate()
13486+ * by checking i_nlink, i_generation or d_unhashed().
13487+ */
13488+ AuDebugOn(!h_child_name);
13489+ au_fset_hnjob(flags[AuHn_CHILD], TRYXINO0);
13490+ au_fset_hnjob(flags[AuHn_CHILD], MNTPNT);
13491+ break;
dece6358 13492+
4a4d8108
AM
13493+ default:
13494+ AuDebugOn(1);
13495+ }
1308ab2a 13496+
4a4d8108
AM
13497+ if (wh)
13498+ h_child_inode = NULL;
1308ab2a 13499+
4a4d8108
AM
13500+ err = -ENOMEM;
13501+ /* iput() and kfree() will be called in au_hnotify() */
4a4d8108 13502+ args = kmalloc(sizeof(*args) + len + 1, GFP_NOFS);
4a4d8108
AM
13503+ if (unlikely(!args)) {
13504+ AuErr1("no memory\n");
13505+ iput(dir);
13506+ goto out;
13507+ }
13508+ args->flags[AuHn_PARENT] = flags[AuHn_PARENT];
13509+ args->flags[AuHn_CHILD] = flags[AuHn_CHILD];
13510+ args->mask = mask;
13511+ args->dir = dir;
13512+ args->h_dir = igrab(h_dir);
13513+ if (h_child_inode)
13514+ h_child_inode = igrab(h_child_inode); /* can be NULL */
13515+ args->h_child_inode = h_child_inode;
13516+ args->h_child_nlen = len;
13517+ if (len) {
13518+ p = (void *)args;
13519+ p += sizeof(*args);
13520+ memcpy(p, h_child_name, len);
13521+ p[len] = 0;
1308ab2a 13522+ }
1308ab2a 13523+
53392da6
AM
13524+ f = 0;
13525+ if (!dir->i_nlink)
13526+ f = AuWkq_NEST;
13527+ err = au_wkq_nowait(au_hn_bh, args, dir->i_sb, f);
4a4d8108
AM
13528+ if (unlikely(err)) {
13529+ pr_err("wkq %d\n", err);
13530+ iput(args->h_child_inode);
13531+ iput(args->h_dir);
13532+ iput(args->dir);
13533+ kfree(args);
1facf9fc 13534+ }
1facf9fc 13535+
4a4d8108 13536+out:
1facf9fc 13537+ return err;
13538+}
13539+
027c5e7a
AM
13540+/* ---------------------------------------------------------------------- */
13541+
13542+int au_hnotify_reset_br(unsigned int udba, struct au_branch *br, int perm)
13543+{
13544+ int err;
13545+
13546+ AuDebugOn(!(udba & AuOptMask_UDBA));
13547+
13548+ err = 0;
13549+ if (au_hnotify_op.reset_br)
13550+ err = au_hnotify_op.reset_br(udba, br, perm);
13551+
13552+ return err;
13553+}
13554+
13555+int au_hnotify_init_br(struct au_branch *br, int perm)
13556+{
13557+ int err;
13558+
13559+ err = 0;
13560+ if (au_hnotify_op.init_br)
13561+ err = au_hnotify_op.init_br(br, perm);
13562+
13563+ return err;
13564+}
13565+
13566+void au_hnotify_fin_br(struct au_branch *br)
13567+{
13568+ if (au_hnotify_op.fin_br)
13569+ au_hnotify_op.fin_br(br);
13570+}
13571+
4a4d8108
AM
13572+static void au_hn_destroy_cache(void)
13573+{
13574+ kmem_cache_destroy(au_cachep[AuCache_HNOTIFY]);
13575+ au_cachep[AuCache_HNOTIFY] = NULL;
13576+}
1308ab2a 13577+
4a4d8108 13578+int __init au_hnotify_init(void)
1facf9fc 13579+{
1308ab2a 13580+ int err;
1308ab2a 13581+
4a4d8108
AM
13582+ err = -ENOMEM;
13583+ au_cachep[AuCache_HNOTIFY] = AuCache(au_hnotify);
13584+ if (au_cachep[AuCache_HNOTIFY]) {
027c5e7a
AM
13585+ err = 0;
13586+ if (au_hnotify_op.init)
13587+ err = au_hnotify_op.init();
4a4d8108
AM
13588+ if (unlikely(err))
13589+ au_hn_destroy_cache();
1308ab2a 13590+ }
1308ab2a 13591+ AuTraceErr(err);
4a4d8108 13592+ return err;
1308ab2a 13593+}
13594+
4a4d8108 13595+void au_hnotify_fin(void)
1308ab2a 13596+{
027c5e7a
AM
13597+ if (au_hnotify_op.fin)
13598+ au_hnotify_op.fin();
4a4d8108
AM
13599+ /* cf. au_cache_fin() */
13600+ if (au_cachep[AuCache_HNOTIFY])
13601+ au_hn_destroy_cache();
dece6358 13602+}
7f207e10
AM
13603diff -urN /usr/share/empty/fs/aufs/iinfo.c linux/fs/aufs/iinfo.c
13604--- /usr/share/empty/fs/aufs/iinfo.c 1970-01-01 01:00:00.000000000 +0100
7ce627cf 13605+++ linux/fs/aufs/iinfo.c 2012-05-22 09:06:08.867458905 +0200
027c5e7a 13606@@ -0,0 +1,264 @@
dece6358 13607+/*
f6c5ef8b 13608+ * Copyright (C) 2005-2012 Junjiro R. Okajima
dece6358
AM
13609+ *
13610+ * This program, aufs is free software; you can redistribute it and/or modify
13611+ * it under the terms of the GNU General Public License as published by
13612+ * the Free Software Foundation; either version 2 of the License, or
13613+ * (at your option) any later version.
13614+ *
13615+ * This program is distributed in the hope that it will be useful,
13616+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
13617+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13618+ * GNU General Public License for more details.
13619+ *
13620+ * You should have received a copy of the GNU General Public License
13621+ * along with this program; if not, write to the Free Software
13622+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
13623+ */
1facf9fc 13624+
dece6358 13625+/*
4a4d8108 13626+ * inode private data
dece6358 13627+ */
1facf9fc 13628+
1308ab2a 13629+#include "aufs.h"
1facf9fc 13630+
4a4d8108 13631+struct inode *au_h_iptr(struct inode *inode, aufs_bindex_t bindex)
1308ab2a 13632+{
4a4d8108 13633+ struct inode *h_inode;
1facf9fc 13634+
4a4d8108 13635+ IiMustAnyLock(inode);
1facf9fc 13636+
4a4d8108
AM
13637+ h_inode = au_ii(inode)->ii_hinode[0 + bindex].hi_inode;
13638+ AuDebugOn(h_inode && atomic_read(&h_inode->i_count) <= 0);
13639+ return h_inode;
13640+}
1facf9fc 13641+
4a4d8108
AM
13642+/* todo: hard/soft set? */
13643+void au_hiput(struct au_hinode *hinode)
13644+{
13645+ au_hn_free(hinode);
13646+ dput(hinode->hi_whdentry);
13647+ iput(hinode->hi_inode);
13648+}
1facf9fc 13649+
4a4d8108
AM
13650+unsigned int au_hi_flags(struct inode *inode, int isdir)
13651+{
13652+ unsigned int flags;
13653+ const unsigned int mnt_flags = au_mntflags(inode->i_sb);
1facf9fc 13654+
4a4d8108
AM
13655+ flags = 0;
13656+ if (au_opt_test(mnt_flags, XINO))
13657+ au_fset_hi(flags, XINO);
13658+ if (isdir && au_opt_test(mnt_flags, UDBA_HNOTIFY))
13659+ au_fset_hi(flags, HNOTIFY);
13660+ return flags;
1facf9fc 13661+}
13662+
4a4d8108
AM
13663+void au_set_h_iptr(struct inode *inode, aufs_bindex_t bindex,
13664+ struct inode *h_inode, unsigned int flags)
1308ab2a 13665+{
4a4d8108
AM
13666+ struct au_hinode *hinode;
13667+ struct inode *hi;
13668+ struct au_iinfo *iinfo = au_ii(inode);
1facf9fc 13669+
4a4d8108 13670+ IiMustWriteLock(inode);
dece6358 13671+
4a4d8108
AM
13672+ hinode = iinfo->ii_hinode + bindex;
13673+ hi = hinode->hi_inode;
13674+ AuDebugOn(h_inode && atomic_read(&h_inode->i_count) <= 0);
13675+
13676+ if (hi)
13677+ au_hiput(hinode);
13678+ hinode->hi_inode = h_inode;
13679+ if (h_inode) {
13680+ int err;
13681+ struct super_block *sb = inode->i_sb;
13682+ struct au_branch *br;
13683+
027c5e7a
AM
13684+ AuDebugOn(inode->i_mode
13685+ && (h_inode->i_mode & S_IFMT)
13686+ != (inode->i_mode & S_IFMT));
4a4d8108
AM
13687+ if (bindex == iinfo->ii_bstart)
13688+ au_cpup_igen(inode, h_inode);
13689+ br = au_sbr(sb, bindex);
13690+ hinode->hi_id = br->br_id;
13691+ if (au_ftest_hi(flags, XINO)) {
13692+ err = au_xino_write(sb, bindex, h_inode->i_ino,
13693+ inode->i_ino);
13694+ if (unlikely(err))
13695+ AuIOErr1("failed au_xino_write() %d\n", err);
13696+ }
13697+
13698+ if (au_ftest_hi(flags, HNOTIFY)
13699+ && au_br_hnotifyable(br->br_perm)) {
027c5e7a 13700+ err = au_hn_alloc(hinode, inode);
4a4d8108
AM
13701+ if (unlikely(err))
13702+ AuIOErr1("au_hn_alloc() %d\n", err);
1308ab2a 13703+ }
13704+ }
4a4d8108 13705+}
dece6358 13706+
4a4d8108
AM
13707+void au_set_hi_wh(struct inode *inode, aufs_bindex_t bindex,
13708+ struct dentry *h_wh)
13709+{
13710+ struct au_hinode *hinode;
dece6358 13711+
4a4d8108
AM
13712+ IiMustWriteLock(inode);
13713+
13714+ hinode = au_ii(inode)->ii_hinode + bindex;
13715+ AuDebugOn(hinode->hi_whdentry);
13716+ hinode->hi_whdentry = h_wh;
1facf9fc 13717+}
13718+
4a4d8108 13719+void au_update_iigen(struct inode *inode)
1308ab2a 13720+{
4a4d8108
AM
13721+ atomic_set(&au_ii(inode)->ii_generation, au_sigen(inode->i_sb));
13722+ /* smp_mb(); */ /* atomic_set */
13723+}
1facf9fc 13724+
4a4d8108
AM
13725+/* it may be called at remount time, too */
13726+void au_update_ibrange(struct inode *inode, int do_put_zero)
13727+{
13728+ struct au_iinfo *iinfo;
027c5e7a 13729+ aufs_bindex_t bindex, bend;
1facf9fc 13730+
4a4d8108 13731+ iinfo = au_ii(inode);
027c5e7a 13732+ if (!iinfo)
4a4d8108 13733+ return;
1facf9fc 13734+
4a4d8108 13735+ IiMustWriteLock(inode);
1facf9fc 13736+
027c5e7a 13737+ if (do_put_zero && iinfo->ii_bstart >= 0) {
4a4d8108
AM
13738+ for (bindex = iinfo->ii_bstart; bindex <= iinfo->ii_bend;
13739+ bindex++) {
13740+ struct inode *h_i;
1facf9fc 13741+
4a4d8108 13742+ h_i = iinfo->ii_hinode[0 + bindex].hi_inode;
027c5e7a
AM
13743+ if (h_i && !h_i->i_nlink)
13744+ au_set_h_iptr(inode, bindex, NULL, 0);
13745+ }
4a4d8108
AM
13746+ }
13747+
027c5e7a
AM
13748+ iinfo->ii_bstart = -1;
13749+ iinfo->ii_bend = -1;
13750+ bend = au_sbend(inode->i_sb);
13751+ for (bindex = 0; bindex <= bend; bindex++)
13752+ if (iinfo->ii_hinode[0 + bindex].hi_inode) {
13753+ iinfo->ii_bstart = bindex;
4a4d8108 13754+ break;
027c5e7a
AM
13755+ }
13756+ if (iinfo->ii_bstart >= 0)
13757+ for (bindex = bend; bindex >= iinfo->ii_bstart; bindex--)
13758+ if (iinfo->ii_hinode[0 + bindex].hi_inode) {
13759+ iinfo->ii_bend = bindex;
13760+ break;
13761+ }
13762+ AuDebugOn(iinfo->ii_bstart > iinfo->ii_bend);
1308ab2a 13763+}
1facf9fc 13764+
dece6358 13765+/* ---------------------------------------------------------------------- */
1facf9fc 13766+
4a4d8108 13767+void au_icntnr_init_once(void *_c)
dece6358 13768+{
4a4d8108
AM
13769+ struct au_icntnr *c = _c;
13770+ struct au_iinfo *iinfo = &c->iinfo;
e49829fe 13771+ static struct lock_class_key aufs_ii;
1facf9fc 13772+
4a4d8108 13773+ au_rw_init(&iinfo->ii_rwsem);
e49829fe 13774+ au_rw_class(&iinfo->ii_rwsem, &aufs_ii);
4a4d8108
AM
13775+ inode_init_once(&c->vfs_inode);
13776+}
1facf9fc 13777+
4a4d8108
AM
13778+int au_iinfo_init(struct inode *inode)
13779+{
13780+ struct au_iinfo *iinfo;
13781+ struct super_block *sb;
13782+ int nbr, i;
1facf9fc 13783+
4a4d8108
AM
13784+ sb = inode->i_sb;
13785+ iinfo = &(container_of(inode, struct au_icntnr, vfs_inode)->iinfo);
13786+ nbr = au_sbend(sb) + 1;
13787+ if (unlikely(nbr <= 0))
13788+ nbr = 1;
13789+ iinfo->ii_hinode = kcalloc(nbr, sizeof(*iinfo->ii_hinode), GFP_NOFS);
13790+ if (iinfo->ii_hinode) {
7f207e10 13791+ au_ninodes_inc(sb);
4a4d8108
AM
13792+ for (i = 0; i < nbr; i++)
13793+ iinfo->ii_hinode[i].hi_id = -1;
1facf9fc 13794+
4a4d8108
AM
13795+ atomic_set(&iinfo->ii_generation, au_sigen(sb));
13796+ /* smp_mb(); */ /* atomic_set */
13797+ iinfo->ii_bstart = -1;
13798+ iinfo->ii_bend = -1;
13799+ iinfo->ii_vdir = NULL;
13800+ return 0;
1308ab2a 13801+ }
4a4d8108
AM
13802+ return -ENOMEM;
13803+}
1facf9fc 13804+
4a4d8108
AM
13805+int au_ii_realloc(struct au_iinfo *iinfo, int nbr)
13806+{
13807+ int err, sz;
13808+ struct au_hinode *hip;
1facf9fc 13809+
4a4d8108
AM
13810+ AuRwMustWriteLock(&iinfo->ii_rwsem);
13811+
13812+ err = -ENOMEM;
13813+ sz = sizeof(*hip) * (iinfo->ii_bend + 1);
13814+ if (!sz)
13815+ sz = sizeof(*hip);
13816+ hip = au_kzrealloc(iinfo->ii_hinode, sz, sizeof(*hip) * nbr, GFP_NOFS);
13817+ if (hip) {
13818+ iinfo->ii_hinode = hip;
13819+ err = 0;
1308ab2a 13820+ }
4a4d8108 13821+
1308ab2a 13822+ return err;
1facf9fc 13823+}
13824+
4a4d8108 13825+void au_iinfo_fin(struct inode *inode)
1facf9fc 13826+{
4a4d8108
AM
13827+ struct au_iinfo *iinfo;
13828+ struct au_hinode *hi;
13829+ struct super_block *sb;
b752ccd1
AM
13830+ aufs_bindex_t bindex, bend;
13831+ const unsigned char unlinked = !inode->i_nlink;
1308ab2a 13832+
4a4d8108
AM
13833+ iinfo = au_ii(inode);
13834+ /* bad_inode case */
13835+ if (!iinfo)
13836+ return;
1308ab2a 13837+
b752ccd1 13838+ sb = inode->i_sb;
7f207e10 13839+ au_ninodes_dec(sb);
b752ccd1
AM
13840+ if (si_pid_test(sb))
13841+ au_xino_delete_inode(inode, unlinked);
13842+ else {
13843+ /*
13844+ * it is safe to hide the dependency between sbinfo and
13845+ * sb->s_umount.
13846+ */
13847+ lockdep_off();
13848+ si_noflush_read_lock(sb);
13849+ au_xino_delete_inode(inode, unlinked);
13850+ si_read_unlock(sb);
13851+ lockdep_on();
13852+ }
13853+
4a4d8108
AM
13854+ if (iinfo->ii_vdir)
13855+ au_vdir_free(iinfo->ii_vdir);
1308ab2a 13856+
b752ccd1
AM
13857+ bindex = iinfo->ii_bstart;
13858+ if (bindex >= 0) {
13859+ hi = iinfo->ii_hinode + bindex;
4a4d8108 13860+ bend = iinfo->ii_bend;
b752ccd1
AM
13861+ while (bindex++ <= bend) {
13862+ if (hi->hi_inode)
4a4d8108 13863+ au_hiput(hi);
4a4d8108
AM
13864+ hi++;
13865+ }
13866+ }
4a4d8108 13867+ kfree(iinfo->ii_hinode);
027c5e7a 13868+ iinfo->ii_hinode = NULL;
4a4d8108 13869+ AuRwDestroy(&iinfo->ii_rwsem);
dece6358 13870+}
7f207e10
AM
13871diff -urN /usr/share/empty/fs/aufs/inode.c linux/fs/aufs/inode.c
13872--- /usr/share/empty/fs/aufs/inode.c 1970-01-01 01:00:00.000000000 +0100
7ce627cf 13873+++ linux/fs/aufs/inode.c 2012-05-22 09:06:08.870792417 +0200
027c5e7a 13874@@ -0,0 +1,471 @@
4a4d8108 13875+/*
f6c5ef8b 13876+ * Copyright (C) 2005-2012 Junjiro R. Okajima
4a4d8108
AM
13877+ *
13878+ * This program, aufs is free software; you can redistribute it and/or modify
13879+ * it under the terms of the GNU General Public License as published by
13880+ * the Free Software Foundation; either version 2 of the License, or
13881+ * (at your option) any later version.
13882+ *
13883+ * This program is distributed in the hope that it will be useful,
13884+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
13885+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13886+ * GNU General Public License for more details.
13887+ *
13888+ * You should have received a copy of the GNU General Public License
13889+ * along with this program; if not, write to the Free Software
13890+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
13891+ */
1facf9fc 13892+
4a4d8108
AM
13893+/*
13894+ * inode functions
13895+ */
1facf9fc 13896+
4a4d8108 13897+#include "aufs.h"
1308ab2a 13898+
4a4d8108
AM
13899+struct inode *au_igrab(struct inode *inode)
13900+{
13901+ if (inode) {
13902+ AuDebugOn(!atomic_read(&inode->i_count));
027c5e7a 13903+ ihold(inode);
1facf9fc 13904+ }
4a4d8108
AM
13905+ return inode;
13906+}
1facf9fc 13907+
4a4d8108
AM
13908+static void au_refresh_hinode_attr(struct inode *inode, int do_version)
13909+{
13910+ au_cpup_attr_all(inode, /*force*/0);
13911+ au_update_iigen(inode);
13912+ if (do_version)
13913+ inode->i_version++;
dece6358 13914+}
1facf9fc 13915+
027c5e7a 13916+static int au_ii_refresh(struct inode *inode, int *update)
dece6358 13917+{
4a4d8108 13918+ int err, e;
027c5e7a 13919+ umode_t type;
4a4d8108 13920+ aufs_bindex_t bindex, new_bindex;
1308ab2a 13921+ struct super_block *sb;
4a4d8108 13922+ struct au_iinfo *iinfo;
027c5e7a 13923+ struct au_hinode *p, *q, tmp;
1facf9fc 13924+
4a4d8108 13925+ IiMustWriteLock(inode);
1facf9fc 13926+
027c5e7a 13927+ *update = 0;
4a4d8108 13928+ sb = inode->i_sb;
027c5e7a 13929+ type = inode->i_mode & S_IFMT;
4a4d8108
AM
13930+ iinfo = au_ii(inode);
13931+ err = au_ii_realloc(iinfo, au_sbend(sb) + 1);
13932+ if (unlikely(err))
1308ab2a 13933+ goto out;
1facf9fc 13934+
027c5e7a 13935+ AuDebugOn(iinfo->ii_bstart < 0);
4a4d8108 13936+ p = iinfo->ii_hinode + iinfo->ii_bstart;
4a4d8108
AM
13937+ for (bindex = iinfo->ii_bstart; bindex <= iinfo->ii_bend;
13938+ bindex++, p++) {
13939+ if (!p->hi_inode)
13940+ continue;
1facf9fc 13941+
027c5e7a 13942+ AuDebugOn(type != (p->hi_inode->i_mode & S_IFMT));
4a4d8108
AM
13943+ new_bindex = au_br_index(sb, p->hi_id);
13944+ if (new_bindex == bindex)
13945+ continue;
1facf9fc 13946+
4a4d8108 13947+ if (new_bindex < 0) {
027c5e7a 13948+ *update = 1;
4a4d8108
AM
13949+ au_hiput(p);
13950+ p->hi_inode = NULL;
13951+ continue;
1308ab2a 13952+ }
4a4d8108
AM
13953+
13954+ if (new_bindex < iinfo->ii_bstart)
13955+ iinfo->ii_bstart = new_bindex;
13956+ if (iinfo->ii_bend < new_bindex)
13957+ iinfo->ii_bend = new_bindex;
13958+ /* swap two lower inode, and loop again */
13959+ q = iinfo->ii_hinode + new_bindex;
13960+ tmp = *q;
13961+ *q = *p;
13962+ *p = tmp;
13963+ if (tmp.hi_inode) {
13964+ bindex--;
13965+ p--;
1308ab2a 13966+ }
13967+ }
4a4d8108
AM
13968+ au_update_ibrange(inode, /*do_put_zero*/0);
13969+ e = au_dy_irefresh(inode);
13970+ if (unlikely(e && !err))
13971+ err = e;
1facf9fc 13972+
4f0767ce 13973+out:
027c5e7a
AM
13974+ AuTraceErr(err);
13975+ return err;
13976+}
13977+
13978+int au_refresh_hinode_self(struct inode *inode)
13979+{
13980+ int err, update;
13981+
13982+ err = au_ii_refresh(inode, &update);
13983+ if (!err)
13984+ au_refresh_hinode_attr(inode, update && S_ISDIR(inode->i_mode));
13985+
13986+ AuTraceErr(err);
4a4d8108
AM
13987+ return err;
13988+}
1facf9fc 13989+
4a4d8108
AM
13990+int au_refresh_hinode(struct inode *inode, struct dentry *dentry)
13991+{
027c5e7a 13992+ int err, e, update;
4a4d8108 13993+ unsigned int flags;
027c5e7a 13994+ umode_t mode;
4a4d8108 13995+ aufs_bindex_t bindex, bend;
027c5e7a 13996+ unsigned char isdir;
4a4d8108
AM
13997+ struct au_hinode *p;
13998+ struct au_iinfo *iinfo;
1facf9fc 13999+
027c5e7a 14000+ err = au_ii_refresh(inode, &update);
4a4d8108
AM
14001+ if (unlikely(err))
14002+ goto out;
14003+
14004+ update = 0;
14005+ iinfo = au_ii(inode);
14006+ p = iinfo->ii_hinode + iinfo->ii_bstart;
027c5e7a
AM
14007+ mode = (inode->i_mode & S_IFMT);
14008+ isdir = S_ISDIR(mode);
4a4d8108
AM
14009+ flags = au_hi_flags(inode, isdir);
14010+ bend = au_dbend(dentry);
14011+ for (bindex = au_dbstart(dentry); bindex <= bend; bindex++) {
14012+ struct inode *h_i;
14013+ struct dentry *h_d;
14014+
14015+ h_d = au_h_dptr(dentry, bindex);
14016+ if (!h_d || !h_d->d_inode)
14017+ continue;
14018+
027c5e7a 14019+ AuDebugOn(mode != (h_d->d_inode->i_mode & S_IFMT));
4a4d8108
AM
14020+ if (iinfo->ii_bstart <= bindex && bindex <= iinfo->ii_bend) {
14021+ h_i = au_h_iptr(inode, bindex);
14022+ if (h_i) {
14023+ if (h_i == h_d->d_inode)
14024+ continue;
14025+ err = -EIO;
14026+ break;
14027+ }
14028+ }
14029+ if (bindex < iinfo->ii_bstart)
14030+ iinfo->ii_bstart = bindex;
14031+ if (iinfo->ii_bend < bindex)
14032+ iinfo->ii_bend = bindex;
14033+ au_set_h_iptr(inode, bindex, au_igrab(h_d->d_inode), flags);
14034+ update = 1;
1308ab2a 14035+ }
4a4d8108
AM
14036+ au_update_ibrange(inode, /*do_put_zero*/0);
14037+ e = au_dy_irefresh(inode);
14038+ if (unlikely(e && !err))
14039+ err = e;
027c5e7a
AM
14040+ if (!err)
14041+ au_refresh_hinode_attr(inode, update && isdir);
4a4d8108 14042+
4f0767ce 14043+out:
4a4d8108 14044+ AuTraceErr(err);
1308ab2a 14045+ return err;
dece6358
AM
14046+}
14047+
4a4d8108 14048+static int set_inode(struct inode *inode, struct dentry *dentry)
dece6358 14049+{
4a4d8108
AM
14050+ int err;
14051+ unsigned int flags;
14052+ umode_t mode;
14053+ aufs_bindex_t bindex, bstart, btail;
14054+ unsigned char isdir;
14055+ struct dentry *h_dentry;
14056+ struct inode *h_inode;
14057+ struct au_iinfo *iinfo;
dece6358 14058+
4a4d8108 14059+ IiMustWriteLock(inode);
dece6358 14060+
4a4d8108
AM
14061+ err = 0;
14062+ isdir = 0;
14063+ bstart = au_dbstart(dentry);
14064+ h_inode = au_h_dptr(dentry, bstart)->d_inode;
14065+ mode = h_inode->i_mode;
14066+ switch (mode & S_IFMT) {
14067+ case S_IFREG:
14068+ btail = au_dbtail(dentry);
14069+ inode->i_op = &aufs_iop;
14070+ inode->i_fop = &aufs_file_fop;
14071+ err = au_dy_iaop(inode, bstart, h_inode);
14072+ if (unlikely(err))
14073+ goto out;
14074+ break;
14075+ case S_IFDIR:
14076+ isdir = 1;
14077+ btail = au_dbtaildir(dentry);
14078+ inode->i_op = &aufs_dir_iop;
14079+ inode->i_fop = &aufs_dir_fop;
14080+ break;
14081+ case S_IFLNK:
14082+ btail = au_dbtail(dentry);
14083+ inode->i_op = &aufs_symlink_iop;
14084+ break;
14085+ case S_IFBLK:
14086+ case S_IFCHR:
14087+ case S_IFIFO:
14088+ case S_IFSOCK:
14089+ btail = au_dbtail(dentry);
14090+ inode->i_op = &aufs_iop;
14091+ au_init_special_fop(inode, mode, h_inode->i_rdev);
14092+ break;
14093+ default:
14094+ AuIOErr("Unknown file type 0%o\n", mode);
14095+ err = -EIO;
1308ab2a 14096+ goto out;
4a4d8108 14097+ }
dece6358 14098+
4a4d8108
AM
14099+ /* do not set hnotify for whiteouted dirs (SHWH mode) */
14100+ flags = au_hi_flags(inode, isdir);
14101+ if (au_opt_test(au_mntflags(dentry->d_sb), SHWH)
14102+ && au_ftest_hi(flags, HNOTIFY)
14103+ && dentry->d_name.len > AUFS_WH_PFX_LEN
14104+ && !memcmp(dentry->d_name.name, AUFS_WH_PFX, AUFS_WH_PFX_LEN))
14105+ au_fclr_hi(flags, HNOTIFY);
14106+ iinfo = au_ii(inode);
14107+ iinfo->ii_bstart = bstart;
14108+ iinfo->ii_bend = btail;
14109+ for (bindex = bstart; bindex <= btail; bindex++) {
14110+ h_dentry = au_h_dptr(dentry, bindex);
14111+ if (h_dentry)
14112+ au_set_h_iptr(inode, bindex,
14113+ au_igrab(h_dentry->d_inode), flags);
14114+ }
14115+ au_cpup_attr_all(inode, /*force*/1);
dece6358 14116+
4f0767ce 14117+out:
4a4d8108
AM
14118+ return err;
14119+}
dece6358 14120+
027c5e7a
AM
14121+/*
14122+ * successful returns with iinfo write_locked
14123+ * minus: errno
14124+ * zero: success, matched
14125+ * plus: no error, but unmatched
14126+ */
14127+static int reval_inode(struct inode *inode, struct dentry *dentry)
4a4d8108
AM
14128+{
14129+ int err;
14130+ aufs_bindex_t bindex, bend;
14131+ struct inode *h_inode, *h_dinode;
dece6358 14132+
4a4d8108
AM
14133+ /*
14134+ * before this function, if aufs got any iinfo lock, it must be only
14135+ * one, the parent dir.
14136+ * it can happen by UDBA and the obsoleted inode number.
14137+ */
14138+ err = -EIO;
14139+ if (unlikely(inode->i_ino == parent_ino(dentry)))
14140+ goto out;
14141+
027c5e7a 14142+ err = 1;
4a4d8108
AM
14143+ ii_write_lock_new_child(inode);
14144+ h_dinode = au_h_dptr(dentry, au_dbstart(dentry))->d_inode;
14145+ bend = au_ibend(inode);
14146+ for (bindex = au_ibstart(inode); bindex <= bend; bindex++) {
14147+ h_inode = au_h_iptr(inode, bindex);
14148+ if (h_inode && h_inode == h_dinode) {
4a4d8108 14149+ err = 0;
027c5e7a 14150+ if (au_iigen_test(inode, au_digen(dentry)))
4a4d8108
AM
14151+ err = au_refresh_hinode(inode, dentry);
14152+ break;
1308ab2a 14153+ }
1facf9fc 14154+ }
dece6358 14155+
4a4d8108
AM
14156+ if (unlikely(err))
14157+ ii_write_unlock(inode);
4f0767ce 14158+out:
1facf9fc 14159+ return err;
14160+}
1facf9fc 14161+
4a4d8108
AM
14162+int au_ino(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino,
14163+ unsigned int d_type, ino_t *ino)
1facf9fc 14164+{
4a4d8108
AM
14165+ int err;
14166+ struct mutex *mtx;
1facf9fc 14167+
b752ccd1 14168+ /* prevent hardlinked inode number from race condition */
4a4d8108 14169+ mtx = NULL;
b752ccd1 14170+ if (d_type != DT_DIR) {
4a4d8108
AM
14171+ mtx = &au_sbr(sb, bindex)->br_xino.xi_nondir_mtx;
14172+ mutex_lock(mtx);
14173+ }
14174+ err = au_xino_read(sb, bindex, h_ino, ino);
14175+ if (unlikely(err))
14176+ goto out;
1308ab2a 14177+
4a4d8108
AM
14178+ if (!*ino) {
14179+ err = -EIO;
14180+ *ino = au_xino_new_ino(sb);
14181+ if (unlikely(!*ino))
1facf9fc 14182+ goto out;
4a4d8108
AM
14183+ err = au_xino_write(sb, bindex, h_ino, *ino);
14184+ if (unlikely(err))
1308ab2a 14185+ goto out;
1308ab2a 14186+ }
1facf9fc 14187+
4f0767ce 14188+out:
b752ccd1 14189+ if (mtx)
4a4d8108 14190+ mutex_unlock(mtx);
1facf9fc 14191+ return err;
14192+}
14193+
4a4d8108
AM
14194+/* successful returns with iinfo write_locked */
14195+/* todo: return with unlocked? */
14196+struct inode *au_new_inode(struct dentry *dentry, int must_new)
1facf9fc 14197+{
b752ccd1 14198+ struct inode *inode, *h_inode;
4a4d8108
AM
14199+ struct dentry *h_dentry;
14200+ struct super_block *sb;
b752ccd1 14201+ struct mutex *mtx;
4a4d8108 14202+ ino_t h_ino, ino;
027c5e7a 14203+ int err;
4a4d8108 14204+ aufs_bindex_t bstart;
1facf9fc 14205+
4a4d8108
AM
14206+ sb = dentry->d_sb;
14207+ bstart = au_dbstart(dentry);
14208+ h_dentry = au_h_dptr(dentry, bstart);
b752ccd1
AM
14209+ h_inode = h_dentry->d_inode;
14210+ h_ino = h_inode->i_ino;
14211+
14212+ /*
14213+ * stop 'race'-ing between hardlinks under different
14214+ * parents.
14215+ */
14216+ mtx = NULL;
14217+ if (!S_ISDIR(h_inode->i_mode))
14218+ mtx = &au_sbr(sb, bstart)->br_xino.xi_nondir_mtx;
14219+
4f0767ce 14220+new_ino:
b752ccd1
AM
14221+ if (mtx)
14222+ mutex_lock(mtx);
4a4d8108
AM
14223+ err = au_xino_read(sb, bstart, h_ino, &ino);
14224+ inode = ERR_PTR(err);
14225+ if (unlikely(err))
14226+ goto out;
b752ccd1 14227+
4a4d8108
AM
14228+ if (!ino) {
14229+ ino = au_xino_new_ino(sb);
14230+ if (unlikely(!ino)) {
14231+ inode = ERR_PTR(-EIO);
dece6358
AM
14232+ goto out;
14233+ }
14234+ }
1facf9fc 14235+
4a4d8108
AM
14236+ AuDbg("i%lu\n", (unsigned long)ino);
14237+ inode = au_iget_locked(sb, ino);
14238+ err = PTR_ERR(inode);
14239+ if (IS_ERR(inode))
1facf9fc 14240+ goto out;
1facf9fc 14241+
4a4d8108
AM
14242+ AuDbg("%lx, new %d\n", inode->i_state, !!(inode->i_state & I_NEW));
14243+ if (inode->i_state & I_NEW) {
14244+ ii_write_lock_new_child(inode);
14245+ err = set_inode(inode, dentry);
14246+ if (!err) {
14247+ unlock_new_inode(inode);
14248+ goto out; /* success */
14249+ }
1308ab2a 14250+
027c5e7a
AM
14251+ /*
14252+ * iget_failed() calls iput(), but we need to call
14253+ * ii_write_unlock() after iget_failed(). so dirty hack for
14254+ * i_count.
14255+ */
14256+ atomic_inc(&inode->i_count);
4a4d8108 14257+ iget_failed(inode);
027c5e7a
AM
14258+ ii_write_unlock(inode);
14259+ au_xino_write(sb, bstart, h_ino, /*ino*/0);
14260+ /* ignore this error */
14261+ goto out_iput;
14262+ } else if (!must_new && !IS_DEADDIR(inode) && inode->i_nlink) {
b752ccd1
AM
14263+ /*
14264+ * horrible race condition between lookup, readdir and copyup
14265+ * (or something).
14266+ */
14267+ if (mtx)
14268+ mutex_unlock(mtx);
027c5e7a
AM
14269+ err = reval_inode(inode, dentry);
14270+ if (unlikely(err < 0)) {
14271+ mtx = NULL;
14272+ goto out_iput;
14273+ }
14274+
b752ccd1
AM
14275+ if (!err) {
14276+ mtx = NULL;
4a4d8108 14277+ goto out; /* success */
b752ccd1
AM
14278+ } else if (mtx)
14279+ mutex_lock(mtx);
4a4d8108
AM
14280+ }
14281+
14282+ if (unlikely(au_test_fs_unique_ino(h_dentry->d_inode)))
14283+ AuWarn1("Warning: Un-notified UDBA or repeatedly renamed dir,"
14284+ " b%d, %s, %.*s, hi%lu, i%lu.\n",
14285+ bstart, au_sbtype(h_dentry->d_sb), AuDLNPair(dentry),
14286+ (unsigned long)h_ino, (unsigned long)ino);
14287+ ino = 0;
14288+ err = au_xino_write(sb, bstart, h_ino, /*ino*/0);
14289+ if (!err) {
14290+ iput(inode);
b752ccd1
AM
14291+ if (mtx)
14292+ mutex_unlock(mtx);
4a4d8108
AM
14293+ goto new_ino;
14294+ }
1308ab2a 14295+
4f0767ce 14296+out_iput:
4a4d8108 14297+ iput(inode);
4a4d8108 14298+ inode = ERR_PTR(err);
4f0767ce 14299+out:
b752ccd1
AM
14300+ if (mtx)
14301+ mutex_unlock(mtx);
4a4d8108 14302+ return inode;
1facf9fc 14303+}
14304+
4a4d8108 14305+/* ---------------------------------------------------------------------- */
1facf9fc 14306+
4a4d8108
AM
14307+int au_test_ro(struct super_block *sb, aufs_bindex_t bindex,
14308+ struct inode *inode)
14309+{
14310+ int err;
1facf9fc 14311+
4a4d8108 14312+ err = au_br_rdonly(au_sbr(sb, bindex));
1facf9fc 14313+
4a4d8108
AM
14314+ /* pseudo-link after flushed may happen out of bounds */
14315+ if (!err
14316+ && inode
14317+ && au_ibstart(inode) <= bindex
14318+ && bindex <= au_ibend(inode)) {
14319+ /*
14320+ * permission check is unnecessary since vfsub routine
14321+ * will be called later
14322+ */
14323+ struct inode *hi = au_h_iptr(inode, bindex);
14324+ if (hi)
14325+ err = IS_IMMUTABLE(hi) ? -EROFS : 0;
1facf9fc 14326+ }
14327+
4a4d8108
AM
14328+ return err;
14329+}
dece6358 14330+
4a4d8108
AM
14331+int au_test_h_perm(struct inode *h_inode, int mask)
14332+{
14333+ if (!current_fsuid())
14334+ return 0;
14335+ return inode_permission(h_inode, mask);
14336+}
1facf9fc 14337+
4a4d8108
AM
14338+int au_test_h_perm_sio(struct inode *h_inode, int mask)
14339+{
14340+ if (au_test_nfs(h_inode->i_sb)
14341+ && (mask & MAY_WRITE)
14342+ && S_ISDIR(h_inode->i_mode))
14343+ mask |= MAY_READ; /* force permission check */
14344+ return au_test_h_perm(h_inode, mask);
1facf9fc 14345+}
7f207e10
AM
14346diff -urN /usr/share/empty/fs/aufs/inode.h linux/fs/aufs/inode.h
14347--- /usr/share/empty/fs/aufs/inode.h 1970-01-01 01:00:00.000000000 +0100
7ce627cf 14348+++ linux/fs/aufs/inode.h 2012-05-22 09:06:08.870792417 +0200
7eafdf33 14349@@ -0,0 +1,560 @@
4a4d8108 14350+/*
f6c5ef8b 14351+ * Copyright (C) 2005-2012 Junjiro R. Okajima
4a4d8108
AM
14352+ *
14353+ * This program, aufs is free software; you can redistribute it and/or modify
14354+ * it under the terms of the GNU General Public License as published by
14355+ * the Free Software Foundation; either version 2 of the License, or
14356+ * (at your option) any later version.
14357+ *
14358+ * This program is distributed in the hope that it will be useful,
14359+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
14360+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14361+ * GNU General Public License for more details.
14362+ *
14363+ * You should have received a copy of the GNU General Public License
14364+ * along with this program; if not, write to the Free Software
14365+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
14366+ */
1facf9fc 14367+
1308ab2a 14368+/*
4a4d8108 14369+ * inode operations
1308ab2a 14370+ */
dece6358 14371+
4a4d8108
AM
14372+#ifndef __AUFS_INODE_H__
14373+#define __AUFS_INODE_H__
dece6358 14374+
4a4d8108 14375+#ifdef __KERNEL__
1308ab2a 14376+
4a4d8108 14377+#include <linux/fsnotify.h>
4a4d8108 14378+#include "rwsem.h"
1308ab2a 14379+
4a4d8108 14380+struct vfsmount;
1facf9fc 14381+
4a4d8108
AM
14382+struct au_hnotify {
14383+#ifdef CONFIG_AUFS_HNOTIFY
14384+#ifdef CONFIG_AUFS_HFSNOTIFY
7f207e10 14385+ /* never use fsnotify_add_vfsmount_mark() */
0c5527e5 14386+ struct fsnotify_mark hn_mark;
4a4d8108 14387+#endif
7f207e10 14388+ struct inode *hn_aufs_inode; /* no get/put */
4a4d8108
AM
14389+#endif
14390+} ____cacheline_aligned_in_smp;
1facf9fc 14391+
4a4d8108
AM
14392+struct au_hinode {
14393+ struct inode *hi_inode;
14394+ aufs_bindex_t hi_id;
14395+#ifdef CONFIG_AUFS_HNOTIFY
14396+ struct au_hnotify *hi_notify;
14397+#endif
dece6358 14398+
4a4d8108
AM
14399+ /* reference to the copied-up whiteout with get/put */
14400+ struct dentry *hi_whdentry;
14401+};
dece6358 14402+
4a4d8108
AM
14403+struct au_vdir;
14404+struct au_iinfo {
14405+ atomic_t ii_generation;
14406+ struct super_block *ii_hsb1; /* no get/put */
1facf9fc 14407+
4a4d8108
AM
14408+ struct au_rwsem ii_rwsem;
14409+ aufs_bindex_t ii_bstart, ii_bend;
14410+ __u32 ii_higen;
14411+ struct au_hinode *ii_hinode;
14412+ struct au_vdir *ii_vdir;
14413+};
1facf9fc 14414+
4a4d8108
AM
14415+struct au_icntnr {
14416+ struct au_iinfo iinfo;
14417+ struct inode vfs_inode;
14418+} ____cacheline_aligned_in_smp;
1308ab2a 14419+
4a4d8108
AM
14420+/* au_pin flags */
14421+#define AuPin_DI_LOCKED 1
14422+#define AuPin_MNT_WRITE (1 << 1)
14423+#define au_ftest_pin(flags, name) ((flags) & AuPin_##name)
7f207e10
AM
14424+#define au_fset_pin(flags, name) \
14425+ do { (flags) |= AuPin_##name; } while (0)
14426+#define au_fclr_pin(flags, name) \
14427+ do { (flags) &= ~AuPin_##name; } while (0)
4a4d8108
AM
14428+
14429+struct au_pin {
14430+ /* input */
14431+ struct dentry *dentry;
14432+ unsigned int udba;
14433+ unsigned char lsc_di, lsc_hi, flags;
14434+ aufs_bindex_t bindex;
14435+
14436+ /* output */
14437+ struct dentry *parent;
14438+ struct au_hinode *hdir;
14439+ struct vfsmount *h_mnt;
14440+};
1facf9fc 14441+
1308ab2a 14442+/* ---------------------------------------------------------------------- */
14443+
4a4d8108 14444+static inline struct au_iinfo *au_ii(struct inode *inode)
1facf9fc 14445+{
4a4d8108 14446+ struct au_iinfo *iinfo;
1facf9fc 14447+
4a4d8108
AM
14448+ iinfo = &(container_of(inode, struct au_icntnr, vfs_inode)->iinfo);
14449+ if (iinfo->ii_hinode)
14450+ return iinfo;
14451+ return NULL; /* debugging bad_inode case */
14452+}
1facf9fc 14453+
4a4d8108 14454+/* ---------------------------------------------------------------------- */
1facf9fc 14455+
4a4d8108
AM
14456+/* inode.c */
14457+struct inode *au_igrab(struct inode *inode);
027c5e7a 14458+int au_refresh_hinode_self(struct inode *inode);
4a4d8108
AM
14459+int au_refresh_hinode(struct inode *inode, struct dentry *dentry);
14460+int au_ino(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino,
14461+ unsigned int d_type, ino_t *ino);
14462+struct inode *au_new_inode(struct dentry *dentry, int must_new);
14463+int au_test_ro(struct super_block *sb, aufs_bindex_t bindex,
14464+ struct inode *inode);
14465+int au_test_h_perm(struct inode *h_inode, int mask);
14466+int au_test_h_perm_sio(struct inode *h_inode, int mask);
1facf9fc 14467+
4a4d8108
AM
14468+static inline int au_wh_ino(struct super_block *sb, aufs_bindex_t bindex,
14469+ ino_t h_ino, unsigned int d_type, ino_t *ino)
14470+{
14471+#ifdef CONFIG_AUFS_SHWH
14472+ return au_ino(sb, bindex, h_ino, d_type, ino);
14473+#else
14474+ return 0;
14475+#endif
14476+}
1facf9fc 14477+
4a4d8108
AM
14478+/* i_op.c */
14479+extern struct inode_operations aufs_iop, aufs_symlink_iop, aufs_dir_iop;
1308ab2a 14480+
4a4d8108
AM
14481+/* au_wr_dir flags */
14482+#define AuWrDir_ADD_ENTRY 1
14483+#define AuWrDir_ISDIR (1 << 1)
14484+#define au_ftest_wrdir(flags, name) ((flags) & AuWrDir_##name)
7f207e10
AM
14485+#define au_fset_wrdir(flags, name) \
14486+ do { (flags) |= AuWrDir_##name; } while (0)
14487+#define au_fclr_wrdir(flags, name) \
14488+ do { (flags) &= ~AuWrDir_##name; } while (0)
1facf9fc 14489+
4a4d8108
AM
14490+struct au_wr_dir_args {
14491+ aufs_bindex_t force_btgt;
14492+ unsigned char flags;
14493+};
14494+int au_wr_dir(struct dentry *dentry, struct dentry *src_dentry,
14495+ struct au_wr_dir_args *args);
dece6358 14496+
4a4d8108
AM
14497+struct dentry *au_pinned_h_parent(struct au_pin *pin);
14498+void au_pin_init(struct au_pin *pin, struct dentry *dentry,
14499+ aufs_bindex_t bindex, int lsc_di, int lsc_hi,
14500+ unsigned int udba, unsigned char flags);
14501+int au_pin(struct au_pin *pin, struct dentry *dentry, aufs_bindex_t bindex,
14502+ unsigned int udba, unsigned char flags) __must_check;
14503+int au_do_pin(struct au_pin *pin) __must_check;
14504+void au_unpin(struct au_pin *pin);
1facf9fc 14505+
4a4d8108
AM
14506+/* i_op_add.c */
14507+int au_may_add(struct dentry *dentry, aufs_bindex_t bindex,
14508+ struct dentry *h_parent, int isdir);
7eafdf33
AM
14509+int aufs_mknod(struct inode *dir, struct dentry *dentry, umode_t mode,
14510+ dev_t dev);
4a4d8108 14511+int aufs_symlink(struct inode *dir, struct dentry *dentry, const char *symname);
7eafdf33 14512+int aufs_create(struct inode *dir, struct dentry *dentry, umode_t mode,
4a4d8108
AM
14513+ struct nameidata *nd);
14514+int aufs_link(struct dentry *src_dentry, struct inode *dir,
14515+ struct dentry *dentry);
7eafdf33 14516+int aufs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode);
1facf9fc 14517+
4a4d8108
AM
14518+/* i_op_del.c */
14519+int au_wr_dir_need_wh(struct dentry *dentry, int isdir, aufs_bindex_t *bcpup);
14520+int au_may_del(struct dentry *dentry, aufs_bindex_t bindex,
14521+ struct dentry *h_parent, int isdir);
14522+int aufs_unlink(struct inode *dir, struct dentry *dentry);
14523+int aufs_rmdir(struct inode *dir, struct dentry *dentry);
1308ab2a 14524+
4a4d8108
AM
14525+/* i_op_ren.c */
14526+int au_wbr(struct dentry *dentry, aufs_bindex_t btgt);
14527+int aufs_rename(struct inode *src_dir, struct dentry *src_dentry,
14528+ struct inode *dir, struct dentry *dentry);
1facf9fc 14529+
4a4d8108
AM
14530+/* iinfo.c */
14531+struct inode *au_h_iptr(struct inode *inode, aufs_bindex_t bindex);
14532+void au_hiput(struct au_hinode *hinode);
14533+void au_set_hi_wh(struct inode *inode, aufs_bindex_t bindex,
14534+ struct dentry *h_wh);
14535+unsigned int au_hi_flags(struct inode *inode, int isdir);
1308ab2a 14536+
4a4d8108
AM
14537+/* hinode flags */
14538+#define AuHi_XINO 1
14539+#define AuHi_HNOTIFY (1 << 1)
14540+#define au_ftest_hi(flags, name) ((flags) & AuHi_##name)
7f207e10
AM
14541+#define au_fset_hi(flags, name) \
14542+ do { (flags) |= AuHi_##name; } while (0)
14543+#define au_fclr_hi(flags, name) \
14544+ do { (flags) &= ~AuHi_##name; } while (0)
1facf9fc 14545+
4a4d8108
AM
14546+#ifndef CONFIG_AUFS_HNOTIFY
14547+#undef AuHi_HNOTIFY
14548+#define AuHi_HNOTIFY 0
14549+#endif
1facf9fc 14550+
4a4d8108
AM
14551+void au_set_h_iptr(struct inode *inode, aufs_bindex_t bindex,
14552+ struct inode *h_inode, unsigned int flags);
1facf9fc 14553+
4a4d8108
AM
14554+void au_update_iigen(struct inode *inode);
14555+void au_update_ibrange(struct inode *inode, int do_put_zero);
1facf9fc 14556+
4a4d8108
AM
14557+void au_icntnr_init_once(void *_c);
14558+int au_iinfo_init(struct inode *inode);
14559+void au_iinfo_fin(struct inode *inode);
14560+int au_ii_realloc(struct au_iinfo *iinfo, int nbr);
1308ab2a 14561+
e49829fe 14562+#ifdef CONFIG_PROC_FS
4a4d8108 14563+/* plink.c */
e49829fe
JR
14564+int au_plink_maint(struct super_block *sb, int flags);
14565+void au_plink_maint_leave(struct au_sbinfo *sbinfo);
14566+int au_plink_maint_enter(struct super_block *sb);
4a4d8108
AM
14567+#ifdef CONFIG_AUFS_DEBUG
14568+void au_plink_list(struct super_block *sb);
14569+#else
14570+AuStubVoid(au_plink_list, struct super_block *sb)
14571+#endif
14572+int au_plink_test(struct inode *inode);
14573+struct dentry *au_plink_lkup(struct inode *inode, aufs_bindex_t bindex);
14574+void au_plink_append(struct inode *inode, aufs_bindex_t bindex,
14575+ struct dentry *h_dentry);
e49829fe
JR
14576+void au_plink_put(struct super_block *sb, int verbose);
14577+void au_plink_clean(struct super_block *sb, int verbose);
4a4d8108 14578+void au_plink_half_refresh(struct super_block *sb, aufs_bindex_t br_id);
e49829fe
JR
14579+#else
14580+AuStubInt0(au_plink_maint, struct super_block *sb, int flags);
14581+AuStubVoid(au_plink_maint_leave, struct au_sbinfo *sbinfo);
14582+AuStubInt0(au_plink_maint_enter, struct super_block *sb);
14583+AuStubVoid(au_plink_list, struct super_block *sb);
14584+AuStubInt0(au_plink_test, struct inode *inode);
14585+AuStub(struct dentry *, au_plink_lkup, return NULL,
14586+ struct inode *inode, aufs_bindex_t bindex);
14587+AuStubVoid(au_plink_append, struct inode *inode, aufs_bindex_t bindex,
14588+ struct dentry *h_dentry);
14589+AuStubVoid(au_plink_put, struct super_block *sb, int verbose);
14590+AuStubVoid(au_plink_clean, struct super_block *sb, int verbose);
14591+AuStubVoid(au_plink_half_refresh, struct super_block *sb, aufs_bindex_t br_id);
14592+#endif /* CONFIG_PROC_FS */
1facf9fc 14593+
4a4d8108 14594+/* ---------------------------------------------------------------------- */
1308ab2a 14595+
4a4d8108
AM
14596+/* lock subclass for iinfo */
14597+enum {
14598+ AuLsc_II_CHILD, /* child first */
14599+ AuLsc_II_CHILD2, /* rename(2), link(2), and cpup at hnotify */
14600+ AuLsc_II_CHILD3, /* copyup dirs */
14601+ AuLsc_II_PARENT, /* see AuLsc_I_PARENT in vfsub.h */
14602+ AuLsc_II_PARENT2,
14603+ AuLsc_II_PARENT3, /* copyup dirs */
14604+ AuLsc_II_NEW_CHILD
14605+};
1308ab2a 14606+
1facf9fc 14607+/*
4a4d8108
AM
14608+ * ii_read_lock_child, ii_write_lock_child,
14609+ * ii_read_lock_child2, ii_write_lock_child2,
14610+ * ii_read_lock_child3, ii_write_lock_child3,
14611+ * ii_read_lock_parent, ii_write_lock_parent,
14612+ * ii_read_lock_parent2, ii_write_lock_parent2,
14613+ * ii_read_lock_parent3, ii_write_lock_parent3,
14614+ * ii_read_lock_new_child, ii_write_lock_new_child,
1facf9fc 14615+ */
4a4d8108
AM
14616+#define AuReadLockFunc(name, lsc) \
14617+static inline void ii_read_lock_##name(struct inode *i) \
14618+{ \
14619+ au_rw_read_lock_nested(&au_ii(i)->ii_rwsem, AuLsc_II_##lsc); \
14620+}
14621+
14622+#define AuWriteLockFunc(name, lsc) \
14623+static inline void ii_write_lock_##name(struct inode *i) \
14624+{ \
14625+ au_rw_write_lock_nested(&au_ii(i)->ii_rwsem, AuLsc_II_##lsc); \
14626+}
14627+
14628+#define AuRWLockFuncs(name, lsc) \
14629+ AuReadLockFunc(name, lsc) \
14630+ AuWriteLockFunc(name, lsc)
14631+
14632+AuRWLockFuncs(child, CHILD);
14633+AuRWLockFuncs(child2, CHILD2);
14634+AuRWLockFuncs(child3, CHILD3);
14635+AuRWLockFuncs(parent, PARENT);
14636+AuRWLockFuncs(parent2, PARENT2);
14637+AuRWLockFuncs(parent3, PARENT3);
14638+AuRWLockFuncs(new_child, NEW_CHILD);
14639+
14640+#undef AuReadLockFunc
14641+#undef AuWriteLockFunc
14642+#undef AuRWLockFuncs
1facf9fc 14643+
14644+/*
4a4d8108 14645+ * ii_read_unlock, ii_write_unlock, ii_downgrade_lock
1facf9fc 14646+ */
4a4d8108 14647+AuSimpleUnlockRwsemFuncs(ii, struct inode *i, &au_ii(i)->ii_rwsem);
1facf9fc 14648+
4a4d8108
AM
14649+#define IiMustNoWaiters(i) AuRwMustNoWaiters(&au_ii(i)->ii_rwsem)
14650+#define IiMustAnyLock(i) AuRwMustAnyLock(&au_ii(i)->ii_rwsem)
14651+#define IiMustWriteLock(i) AuRwMustWriteLock(&au_ii(i)->ii_rwsem)
1facf9fc 14652+
4a4d8108 14653+/* ---------------------------------------------------------------------- */
1308ab2a 14654+
027c5e7a
AM
14655+static inline void au_icntnr_init(struct au_icntnr *c)
14656+{
14657+#ifdef CONFIG_AUFS_DEBUG
14658+ c->vfs_inode.i_mode = 0;
14659+#endif
14660+}
14661+
4a4d8108
AM
14662+static inline unsigned int au_iigen(struct inode *inode)
14663+{
14664+ return atomic_read(&au_ii(inode)->ii_generation);
14665+}
1308ab2a 14666+
4a4d8108
AM
14667+/* tiny test for inode number */
14668+/* tmpfs generation is too rough */
14669+static inline int au_test_higen(struct inode *inode, struct inode *h_inode)
14670+{
14671+ struct au_iinfo *iinfo;
1308ab2a 14672+
4a4d8108
AM
14673+ iinfo = au_ii(inode);
14674+ AuRwMustAnyLock(&iinfo->ii_rwsem);
14675+ return !(iinfo->ii_hsb1 == h_inode->i_sb
14676+ && iinfo->ii_higen == h_inode->i_generation);
14677+}
1308ab2a 14678+
4a4d8108
AM
14679+static inline void au_iigen_dec(struct inode *inode)
14680+{
e49829fe 14681+ atomic_dec(&au_ii(inode)->ii_generation);
027c5e7a
AM
14682+}
14683+
14684+static inline int au_iigen_test(struct inode *inode, unsigned int sigen)
14685+{
14686+ int err;
14687+
14688+ err = 0;
14689+ if (unlikely(inode && au_iigen(inode) != sigen))
14690+ err = -EIO;
14691+
14692+ return err;
4a4d8108 14693+}
1308ab2a 14694+
4a4d8108 14695+/* ---------------------------------------------------------------------- */
1308ab2a 14696+
4a4d8108
AM
14697+static inline aufs_bindex_t au_ii_br_id(struct inode *inode,
14698+ aufs_bindex_t bindex)
14699+{
14700+ IiMustAnyLock(inode);
14701+ return au_ii(inode)->ii_hinode[0 + bindex].hi_id;
14702+}
1308ab2a 14703+
4a4d8108
AM
14704+static inline aufs_bindex_t au_ibstart(struct inode *inode)
14705+{
14706+ IiMustAnyLock(inode);
14707+ return au_ii(inode)->ii_bstart;
14708+}
1308ab2a 14709+
4a4d8108
AM
14710+static inline aufs_bindex_t au_ibend(struct inode *inode)
14711+{
14712+ IiMustAnyLock(inode);
14713+ return au_ii(inode)->ii_bend;
14714+}
1308ab2a 14715+
4a4d8108
AM
14716+static inline struct au_vdir *au_ivdir(struct inode *inode)
14717+{
14718+ IiMustAnyLock(inode);
14719+ return au_ii(inode)->ii_vdir;
14720+}
1308ab2a 14721+
4a4d8108
AM
14722+static inline struct dentry *au_hi_wh(struct inode *inode, aufs_bindex_t bindex)
14723+{
14724+ IiMustAnyLock(inode);
14725+ return au_ii(inode)->ii_hinode[0 + bindex].hi_whdentry;
14726+}
1308ab2a 14727+
4a4d8108 14728+static inline void au_set_ibstart(struct inode *inode, aufs_bindex_t bindex)
1308ab2a 14729+{
4a4d8108
AM
14730+ IiMustWriteLock(inode);
14731+ au_ii(inode)->ii_bstart = bindex;
14732+}
1308ab2a 14733+
4a4d8108
AM
14734+static inline void au_set_ibend(struct inode *inode, aufs_bindex_t bindex)
14735+{
14736+ IiMustWriteLock(inode);
14737+ au_ii(inode)->ii_bend = bindex;
1308ab2a 14738+}
14739+
4a4d8108
AM
14740+static inline void au_set_ivdir(struct inode *inode, struct au_vdir *vdir)
14741+{
14742+ IiMustWriteLock(inode);
14743+ au_ii(inode)->ii_vdir = vdir;
14744+}
1facf9fc 14745+
4a4d8108 14746+static inline struct au_hinode *au_hi(struct inode *inode, aufs_bindex_t bindex)
1308ab2a 14747+{
4a4d8108
AM
14748+ IiMustAnyLock(inode);
14749+ return au_ii(inode)->ii_hinode + bindex;
14750+}
dece6358 14751+
4a4d8108 14752+/* ---------------------------------------------------------------------- */
1facf9fc 14753+
4a4d8108
AM
14754+static inline struct dentry *au_pinned_parent(struct au_pin *pin)
14755+{
14756+ if (pin)
14757+ return pin->parent;
14758+ return NULL;
1facf9fc 14759+}
14760+
4a4d8108 14761+static inline struct inode *au_pinned_h_dir(struct au_pin *pin)
1facf9fc 14762+{
4a4d8108
AM
14763+ if (pin && pin->hdir)
14764+ return pin->hdir->hi_inode;
14765+ return NULL;
1308ab2a 14766+}
1facf9fc 14767+
4a4d8108
AM
14768+static inline struct au_hinode *au_pinned_hdir(struct au_pin *pin)
14769+{
14770+ if (pin)
14771+ return pin->hdir;
14772+ return NULL;
14773+}
1facf9fc 14774+
4a4d8108 14775+static inline void au_pin_set_dentry(struct au_pin *pin, struct dentry *dentry)
1308ab2a 14776+{
4a4d8108
AM
14777+ if (pin)
14778+ pin->dentry = dentry;
14779+}
1308ab2a 14780+
4a4d8108
AM
14781+static inline void au_pin_set_parent_lflag(struct au_pin *pin,
14782+ unsigned char lflag)
14783+{
14784+ if (pin) {
7f207e10 14785+ if (lflag)
4a4d8108 14786+ au_fset_pin(pin->flags, DI_LOCKED);
7f207e10 14787+ else
4a4d8108 14788+ au_fclr_pin(pin->flags, DI_LOCKED);
1308ab2a 14789+ }
4a4d8108
AM
14790+}
14791+
14792+static inline void au_pin_set_parent(struct au_pin *pin, struct dentry *parent)
14793+{
14794+ if (pin) {
14795+ dput(pin->parent);
14796+ pin->parent = dget(parent);
1facf9fc 14797+ }
4a4d8108 14798+}
1facf9fc 14799+
4a4d8108
AM
14800+/* ---------------------------------------------------------------------- */
14801+
027c5e7a 14802+struct au_branch;
4a4d8108
AM
14803+#ifdef CONFIG_AUFS_HNOTIFY
14804+struct au_hnotify_op {
14805+ void (*ctl)(struct au_hinode *hinode, int do_set);
027c5e7a 14806+ int (*alloc)(struct au_hinode *hinode);
7eafdf33
AM
14807+
14808+ /*
14809+ * if it returns true, the the caller should free hinode->hi_notify,
14810+ * otherwise ->free() frees it.
14811+ */
14812+ int (*free)(struct au_hinode *hinode,
14813+ struct au_hnotify *hn) __must_check;
4a4d8108
AM
14814+
14815+ void (*fin)(void);
14816+ int (*init)(void);
027c5e7a
AM
14817+
14818+ int (*reset_br)(unsigned int udba, struct au_branch *br, int perm);
14819+ void (*fin_br)(struct au_branch *br);
14820+ int (*init_br)(struct au_branch *br, int perm);
4a4d8108
AM
14821+};
14822+
14823+/* hnotify.c */
027c5e7a 14824+int au_hn_alloc(struct au_hinode *hinode, struct inode *inode);
4a4d8108
AM
14825+void au_hn_free(struct au_hinode *hinode);
14826+void au_hn_ctl(struct au_hinode *hinode, int do_set);
14827+void au_hn_reset(struct inode *inode, unsigned int flags);
14828+int au_hnotify(struct inode *h_dir, struct au_hnotify *hnotify, u32 mask,
14829+ struct qstr *h_child_qstr, struct inode *h_child_inode);
027c5e7a
AM
14830+int au_hnotify_reset_br(unsigned int udba, struct au_branch *br, int perm);
14831+int au_hnotify_init_br(struct au_branch *br, int perm);
14832+void au_hnotify_fin_br(struct au_branch *br);
4a4d8108
AM
14833+int __init au_hnotify_init(void);
14834+void au_hnotify_fin(void);
14835+
7f207e10 14836+/* hfsnotify.c */
4a4d8108
AM
14837+extern const struct au_hnotify_op au_hnotify_op;
14838+
14839+static inline
14840+void au_hn_init(struct au_hinode *hinode)
14841+{
14842+ hinode->hi_notify = NULL;
1308ab2a 14843+}
14844+
53392da6
AM
14845+static inline struct au_hnotify *au_hn(struct au_hinode *hinode)
14846+{
14847+ return hinode->hi_notify;
14848+}
14849+
4a4d8108
AM
14850+#else
14851+static inline
14852+int au_hn_alloc(struct au_hinode *hinode __maybe_unused,
027c5e7a 14853+ struct inode *inode __maybe_unused)
1308ab2a 14854+{
4a4d8108
AM
14855+ return -EOPNOTSUPP;
14856+}
1308ab2a 14857+
53392da6
AM
14858+static inline struct au_hnotify *au_hn(struct au_hinode *hinode)
14859+{
14860+ return NULL;
14861+}
14862+
4a4d8108
AM
14863+AuStubVoid(au_hn_free, struct au_hinode *hinode __maybe_unused)
14864+AuStubVoid(au_hn_ctl, struct au_hinode *hinode __maybe_unused,
14865+ int do_set __maybe_unused)
14866+AuStubVoid(au_hn_reset, struct inode *inode __maybe_unused,
14867+ unsigned int flags __maybe_unused)
027c5e7a
AM
14868+AuStubInt0(au_hnotify_reset_br, unsigned int udba __maybe_unused,
14869+ struct au_branch *br __maybe_unused,
14870+ int perm __maybe_unused)
14871+AuStubInt0(au_hnotify_init_br, struct au_branch *br __maybe_unused,
14872+ int perm __maybe_unused)
14873+AuStubVoid(au_hnotify_fin_br, struct au_branch *br __maybe_unused)
4a4d8108
AM
14874+AuStubInt0(__init au_hnotify_init, void)
14875+AuStubVoid(au_hnotify_fin, void)
14876+AuStubVoid(au_hn_init, struct au_hinode *hinode __maybe_unused)
14877+#endif /* CONFIG_AUFS_HNOTIFY */
14878+
14879+static inline void au_hn_suspend(struct au_hinode *hdir)
14880+{
14881+ au_hn_ctl(hdir, /*do_set*/0);
1308ab2a 14882+}
14883+
4a4d8108 14884+static inline void au_hn_resume(struct au_hinode *hdir)
1308ab2a 14885+{
4a4d8108
AM
14886+ au_hn_ctl(hdir, /*do_set*/1);
14887+}
1308ab2a 14888+
4a4d8108
AM
14889+static inline void au_hn_imtx_lock(struct au_hinode *hdir)
14890+{
14891+ mutex_lock(&hdir->hi_inode->i_mutex);
14892+ au_hn_suspend(hdir);
14893+}
dece6358 14894+
4a4d8108
AM
14895+static inline void au_hn_imtx_lock_nested(struct au_hinode *hdir,
14896+ unsigned int sc __maybe_unused)
14897+{
14898+ mutex_lock_nested(&hdir->hi_inode->i_mutex, sc);
14899+ au_hn_suspend(hdir);
1facf9fc 14900+}
1facf9fc 14901+
4a4d8108
AM
14902+static inline void au_hn_imtx_unlock(struct au_hinode *hdir)
14903+{
14904+ au_hn_resume(hdir);
14905+ mutex_unlock(&hdir->hi_inode->i_mutex);
14906+}
14907+
14908+#endif /* __KERNEL__ */
14909+#endif /* __AUFS_INODE_H__ */
7f207e10
AM
14910diff -urN /usr/share/empty/fs/aufs/ioctl.c linux/fs/aufs/ioctl.c
14911--- /usr/share/empty/fs/aufs/ioctl.c 1970-01-01 01:00:00.000000000 +0100
7ce627cf 14912+++ linux/fs/aufs/ioctl.c 2012-05-22 09:06:08.870792417 +0200
f6c5ef8b 14913@@ -0,0 +1,196 @@
4a4d8108 14914+/*
f6c5ef8b 14915+ * Copyright (C) 2005-2012 Junjiro R. Okajima
4a4d8108
AM
14916+ *
14917+ * This program, aufs is free software; you can redistribute it and/or modify
14918+ * it under the terms of the GNU General Public License as published by
14919+ * the Free Software Foundation; either version 2 of the License, or
14920+ * (at your option) any later version.
14921+ *
14922+ * This program is distributed in the hope that it will be useful,
14923+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
14924+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14925+ * GNU General Public License for more details.
14926+ *
14927+ * You should have received a copy of the GNU General Public License
14928+ * along with this program; if not, write to the Free Software
14929+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
14930+ */
14931+
14932+/*
14933+ * ioctl
14934+ * plink-management and readdir in userspace.
14935+ * assist the pathconf(3) wrapper library.
14936+ */
14937+
4a4d8108
AM
14938+#include "aufs.h"
14939+
1e00d052 14940+static int au_wbr_fd(struct path *path, struct aufs_wbr_fd __user *arg)
4a4d8108
AM
14941+{
14942+ int err, fd;
14943+ aufs_bindex_t wbi, bindex, bend;
14944+ struct file *h_file;
14945+ struct super_block *sb;
14946+ struct dentry *root;
1e00d052
AM
14947+ struct au_branch *br;
14948+ struct aufs_wbr_fd wbrfd = {
14949+ .oflags = au_dir_roflags,
14950+ .brid = -1
14951+ };
14952+ const int valid = O_RDONLY | O_NONBLOCK | O_LARGEFILE | O_DIRECTORY
14953+ | O_NOATIME | O_CLOEXEC;
4a4d8108 14954+
1e00d052
AM
14955+ AuDebugOn(wbrfd.oflags & ~valid);
14956+
14957+ if (arg) {
14958+ err = copy_from_user(&wbrfd, arg, sizeof(wbrfd));
14959+ if (unlikely(err)) {
14960+ err = -EFAULT;
14961+ goto out;
14962+ }
14963+
14964+ err = -EINVAL;
14965+ AuDbg("wbrfd{0%o, %d}\n", wbrfd.oflags, wbrfd.brid);
14966+ wbrfd.oflags |= au_dir_roflags;
14967+ AuDbg("0%o\n", wbrfd.oflags);
14968+ if (unlikely(wbrfd.oflags & ~valid))
14969+ goto out;
14970+ }
14971+
14972+ fd = get_unused_fd();
14973+ err = fd;
14974+ if (unlikely(fd < 0))
4a4d8108 14975+ goto out;
4a4d8108 14976+
1e00d052 14977+ h_file = ERR_PTR(-EINVAL);
4a4d8108 14978+ wbi = 0;
1e00d052 14979+ br = NULL;
4a4d8108
AM
14980+ sb = path->dentry->d_sb;
14981+ root = sb->s_root;
14982+ aufs_read_lock(root, AuLock_IR);
1e00d052
AM
14983+ bend = au_sbend(sb);
14984+ if (wbrfd.brid >= 0) {
14985+ wbi = au_br_index(sb, wbrfd.brid);
14986+ if (unlikely(wbi < 0 || wbi > bend))
14987+ goto out_unlock;
14988+ }
14989+
14990+ h_file = ERR_PTR(-ENOENT);
14991+ br = au_sbr(sb, wbi);
14992+ if (!au_br_writable(br->br_perm)) {
14993+ if (arg)
14994+ goto out_unlock;
14995+
14996+ bindex = wbi + 1;
14997+ wbi = -1;
14998+ for (; bindex <= bend; bindex++) {
14999+ br = au_sbr(sb, bindex);
15000+ if (au_br_writable(br->br_perm)) {
4a4d8108 15001+ wbi = bindex;
1e00d052 15002+ br = au_sbr(sb, wbi);
4a4d8108
AM
15003+ break;
15004+ }
15005+ }
4a4d8108
AM
15006+ }
15007+ AuDbg("wbi %d\n", wbi);
1e00d052
AM
15008+ if (wbi >= 0)
15009+ h_file = au_h_open(root, wbi, wbrfd.oflags, NULL);
15010+
15011+out_unlock:
4a4d8108
AM
15012+ aufs_read_unlock(root, AuLock_IR);
15013+ err = PTR_ERR(h_file);
15014+ if (IS_ERR(h_file))
15015+ goto out_fd;
15016+
1e00d052 15017+ atomic_dec(&br->br_count); /* cf. au_h_open() */
4a4d8108
AM
15018+ fd_install(fd, h_file);
15019+ err = fd;
15020+ goto out; /* success */
15021+
4f0767ce 15022+out_fd:
4a4d8108 15023+ put_unused_fd(fd);
4f0767ce 15024+out:
1e00d052 15025+ AuTraceErr(err);
4a4d8108
AM
15026+ return err;
15027+}
15028+
15029+/* ---------------------------------------------------------------------- */
15030+
15031+long aufs_ioctl_dir(struct file *file, unsigned int cmd, unsigned long arg)
15032+{
15033+ long err;
15034+
15035+ switch (cmd) {
4a4d8108
AM
15036+ case AUFS_CTL_RDU:
15037+ case AUFS_CTL_RDU_INO:
15038+ err = au_rdu_ioctl(file, cmd, arg);
15039+ break;
15040+
15041+ case AUFS_CTL_WBR_FD:
1e00d052 15042+ err = au_wbr_fd(&file->f_path, (void __user *)arg);
4a4d8108
AM
15043+ break;
15044+
027c5e7a
AM
15045+ case AUFS_CTL_IBUSY:
15046+ err = au_ibusy_ioctl(file, arg);
15047+ break;
15048+
4a4d8108
AM
15049+ default:
15050+ /* do not call the lower */
15051+ AuDbg("0x%x\n", cmd);
15052+ err = -ENOTTY;
15053+ }
15054+
15055+ AuTraceErr(err);
15056+ return err;
15057+}
15058+
15059+long aufs_ioctl_nondir(struct file *file, unsigned int cmd, unsigned long arg)
15060+{
15061+ long err;
15062+
15063+ switch (cmd) {
15064+ case AUFS_CTL_WBR_FD:
1e00d052 15065+ err = au_wbr_fd(&file->f_path, (void __user *)arg);
4a4d8108
AM
15066+ break;
15067+
15068+ default:
15069+ /* do not call the lower */
15070+ AuDbg("0x%x\n", cmd);
15071+ err = -ENOTTY;
15072+ }
15073+
15074+ AuTraceErr(err);
15075+ return err;
15076+}
b752ccd1
AM
15077+
15078+#ifdef CONFIG_COMPAT
15079+long aufs_compat_ioctl_dir(struct file *file, unsigned int cmd,
15080+ unsigned long arg)
15081+{
15082+ long err;
15083+
15084+ switch (cmd) {
15085+ case AUFS_CTL_RDU:
15086+ case AUFS_CTL_RDU_INO:
15087+ err = au_rdu_compat_ioctl(file, cmd, arg);
15088+ break;
15089+
027c5e7a
AM
15090+ case AUFS_CTL_IBUSY:
15091+ err = au_ibusy_compat_ioctl(file, arg);
15092+ break;
15093+
b752ccd1
AM
15094+ default:
15095+ err = aufs_ioctl_dir(file, cmd, arg);
15096+ }
15097+
15098+ AuTraceErr(err);
15099+ return err;
15100+}
15101+
15102+#if 0 /* unused yet */
15103+long aufs_compat_ioctl_nondir(struct file *file, unsigned int cmd,
15104+ unsigned long arg)
15105+{
15106+ return aufs_ioctl_nondir(file, cmd, (unsigned long)compat_ptr(arg));
15107+}
15108+#endif
15109+#endif
7f207e10
AM
15110diff -urN /usr/share/empty/fs/aufs/i_op_add.c linux/fs/aufs/i_op_add.c
15111--- /usr/share/empty/fs/aufs/i_op_add.c 1970-01-01 01:00:00.000000000 +0100
7ce627cf 15112+++ linux/fs/aufs/i_op_add.c 2012-05-22 09:06:08.867458905 +0200
7eafdf33 15113@@ -0,0 +1,712 @@
4a4d8108 15114+/*
f6c5ef8b 15115+ * Copyright (C) 2005-2012 Junjiro R. Okajima
4a4d8108
AM
15116+ *
15117+ * This program, aufs is free software; you can redistribute it and/or modify
15118+ * it under the terms of the GNU General Public License as published by
15119+ * the Free Software Foundation; either version 2 of the License, or
15120+ * (at your option) any later version.
15121+ *
15122+ * This program is distributed in the hope that it will be useful,
15123+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
15124+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15125+ * GNU General Public License for more details.
15126+ *
15127+ * You should have received a copy of the GNU General Public License
15128+ * along with this program; if not, write to the Free Software
15129+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
15130+ */
15131+
15132+/*
15133+ * inode operations (add entry)
15134+ */
15135+
15136+#include "aufs.h"
15137+
15138+/*
15139+ * final procedure of adding a new entry, except link(2).
15140+ * remove whiteout, instantiate, copyup the parent dir's times and size
15141+ * and update version.
15142+ * if it failed, re-create the removed whiteout.
15143+ */
15144+static int epilog(struct inode *dir, aufs_bindex_t bindex,
15145+ struct dentry *wh_dentry, struct dentry *dentry)
15146+{
15147+ int err, rerr;
15148+ aufs_bindex_t bwh;
15149+ struct path h_path;
15150+ struct inode *inode, *h_dir;
15151+ struct dentry *wh;
15152+
15153+ bwh = -1;
15154+ if (wh_dentry) {
15155+ h_dir = wh_dentry->d_parent->d_inode; /* dir inode is locked */
15156+ IMustLock(h_dir);
15157+ AuDebugOn(au_h_iptr(dir, bindex) != h_dir);
15158+ bwh = au_dbwh(dentry);
15159+ h_path.dentry = wh_dentry;
15160+ h_path.mnt = au_sbr_mnt(dir->i_sb, bindex);
15161+ err = au_wh_unlink_dentry(au_h_iptr(dir, bindex), &h_path,
15162+ dentry);
15163+ if (unlikely(err))
15164+ goto out;
15165+ }
15166+
15167+ inode = au_new_inode(dentry, /*must_new*/1);
15168+ if (!IS_ERR(inode)) {
15169+ d_instantiate(dentry, inode);
15170+ dir = dentry->d_parent->d_inode; /* dir inode is locked */
15171+ IMustLock(dir);
15172+ if (au_ibstart(dir) == au_dbstart(dentry))
15173+ au_cpup_attr_timesizes(dir);
15174+ dir->i_version++;
15175+ return 0; /* success */
15176+ }
15177+
15178+ err = PTR_ERR(inode);
15179+ if (!wh_dentry)
15180+ goto out;
15181+
15182+ /* revert */
15183+ /* dir inode is locked */
15184+ wh = au_wh_create(dentry, bwh, wh_dentry->d_parent);
15185+ rerr = PTR_ERR(wh);
15186+ if (IS_ERR(wh)) {
15187+ AuIOErr("%.*s reverting whiteout failed(%d, %d)\n",
15188+ AuDLNPair(dentry), err, rerr);
15189+ err = -EIO;
15190+ } else
15191+ dput(wh);
15192+
4f0767ce 15193+out:
4a4d8108
AM
15194+ return err;
15195+}
15196+
027c5e7a
AM
15197+static int au_d_may_add(struct dentry *dentry)
15198+{
15199+ int err;
15200+
15201+ err = 0;
15202+ if (unlikely(d_unhashed(dentry)))
15203+ err = -ENOENT;
15204+ if (unlikely(dentry->d_inode))
15205+ err = -EEXIST;
15206+ return err;
15207+}
15208+
4a4d8108
AM
15209+/*
15210+ * simple tests for the adding inode operations.
15211+ * following the checks in vfs, plus the parent-child relationship.
15212+ */
15213+int au_may_add(struct dentry *dentry, aufs_bindex_t bindex,
15214+ struct dentry *h_parent, int isdir)
15215+{
15216+ int err;
15217+ umode_t h_mode;
15218+ struct dentry *h_dentry;
15219+ struct inode *h_inode;
15220+
15221+ err = -ENAMETOOLONG;
15222+ if (unlikely(dentry->d_name.len > AUFS_MAX_NAMELEN))
15223+ goto out;
15224+
15225+ h_dentry = au_h_dptr(dentry, bindex);
15226+ h_inode = h_dentry->d_inode;
15227+ if (!dentry->d_inode) {
15228+ err = -EEXIST;
15229+ if (unlikely(h_inode))
15230+ goto out;
15231+ } else {
15232+ /* rename(2) case */
15233+ err = -EIO;
15234+ if (unlikely(!h_inode || !h_inode->i_nlink))
15235+ goto out;
15236+
15237+ h_mode = h_inode->i_mode;
15238+ if (!isdir) {
15239+ err = -EISDIR;
15240+ if (unlikely(S_ISDIR(h_mode)))
15241+ goto out;
15242+ } else if (unlikely(!S_ISDIR(h_mode))) {
15243+ err = -ENOTDIR;
15244+ goto out;
15245+ }
15246+ }
15247+
15248+ err = 0;
15249+ /* expected parent dir is locked */
15250+ if (unlikely(h_parent != h_dentry->d_parent))
15251+ err = -EIO;
15252+
4f0767ce 15253+out:
4a4d8108
AM
15254+ AuTraceErr(err);
15255+ return err;
15256+}
15257+
15258+/*
15259+ * initial procedure of adding a new entry.
15260+ * prepare writable branch and the parent dir, lock it,
15261+ * and lookup whiteout for the new entry.
15262+ */
15263+static struct dentry*
15264+lock_hdir_lkup_wh(struct dentry *dentry, struct au_dtime *dt,
15265+ struct dentry *src_dentry, struct au_pin *pin,
15266+ struct au_wr_dir_args *wr_dir_args)
15267+{
15268+ struct dentry *wh_dentry, *h_parent;
15269+ struct super_block *sb;
15270+ struct au_branch *br;
15271+ int err;
15272+ unsigned int udba;
15273+ aufs_bindex_t bcpup;
15274+
15275+ AuDbg("%.*s\n", AuDLNPair(dentry));
15276+
15277+ err = au_wr_dir(dentry, src_dentry, wr_dir_args);
15278+ bcpup = err;
15279+ wh_dentry = ERR_PTR(err);
15280+ if (unlikely(err < 0))
15281+ goto out;
15282+
15283+ sb = dentry->d_sb;
15284+ udba = au_opt_udba(sb);
15285+ err = au_pin(pin, dentry, bcpup, udba,
15286+ AuPin_DI_LOCKED | AuPin_MNT_WRITE);
15287+ wh_dentry = ERR_PTR(err);
15288+ if (unlikely(err))
15289+ goto out;
15290+
15291+ h_parent = au_pinned_h_parent(pin);
15292+ if (udba != AuOpt_UDBA_NONE
15293+ && au_dbstart(dentry) == bcpup)
15294+ err = au_may_add(dentry, bcpup, h_parent,
15295+ au_ftest_wrdir(wr_dir_args->flags, ISDIR));
15296+ else if (unlikely(dentry->d_name.len > AUFS_MAX_NAMELEN))
15297+ err = -ENAMETOOLONG;
15298+ wh_dentry = ERR_PTR(err);
15299+ if (unlikely(err))
15300+ goto out_unpin;
15301+
15302+ br = au_sbr(sb, bcpup);
15303+ if (dt) {
15304+ struct path tmp = {
15305+ .dentry = h_parent,
15306+ .mnt = br->br_mnt
15307+ };
15308+ au_dtime_store(dt, au_pinned_parent(pin), &tmp);
15309+ }
15310+
15311+ wh_dentry = NULL;
15312+ if (bcpup != au_dbwh(dentry))
15313+ goto out; /* success */
15314+
15315+ wh_dentry = au_wh_lkup(h_parent, &dentry->d_name, br);
15316+
4f0767ce 15317+out_unpin:
4a4d8108
AM
15318+ if (IS_ERR(wh_dentry))
15319+ au_unpin(pin);
4f0767ce 15320+out:
4a4d8108
AM
15321+ return wh_dentry;
15322+}
15323+
15324+/* ---------------------------------------------------------------------- */
15325+
15326+enum { Mknod, Symlink, Creat };
15327+struct simple_arg {
15328+ int type;
15329+ union {
15330+ struct {
7eafdf33 15331+ umode_t mode;
4a4d8108
AM
15332+ struct nameidata *nd;
15333+ } c;
15334+ struct {
15335+ const char *symname;
15336+ } s;
15337+ struct {
7eafdf33 15338+ umode_t mode;
4a4d8108
AM
15339+ dev_t dev;
15340+ } m;
15341+ } u;
15342+};
15343+
15344+static int add_simple(struct inode *dir, struct dentry *dentry,
15345+ struct simple_arg *arg)
15346+{
15347+ int err;
15348+ aufs_bindex_t bstart;
15349+ unsigned char created;
15350+ struct au_dtime dt;
15351+ struct au_pin pin;
15352+ struct path h_path;
15353+ struct dentry *wh_dentry, *parent;
15354+ struct inode *h_dir;
15355+ struct au_wr_dir_args wr_dir_args = {
15356+ .force_btgt = -1,
15357+ .flags = AuWrDir_ADD_ENTRY
15358+ };
15359+
15360+ AuDbg("%.*s\n", AuDLNPair(dentry));
15361+ IMustLock(dir);
15362+
15363+ parent = dentry->d_parent; /* dir inode is locked */
027c5e7a
AM
15364+ err = aufs_read_lock(dentry, AuLock_DW | AuLock_GEN);
15365+ if (unlikely(err))
15366+ goto out;
15367+ err = au_d_may_add(dentry);
15368+ if (unlikely(err))
15369+ goto out_unlock;
4a4d8108
AM
15370+ di_write_lock_parent(parent);
15371+ wh_dentry = lock_hdir_lkup_wh(dentry, &dt, /*src_dentry*/NULL, &pin,
15372+ &wr_dir_args);
15373+ err = PTR_ERR(wh_dentry);
15374+ if (IS_ERR(wh_dentry))
027c5e7a 15375+ goto out_parent;
4a4d8108
AM
15376+
15377+ bstart = au_dbstart(dentry);
15378+ h_path.dentry = au_h_dptr(dentry, bstart);
15379+ h_path.mnt = au_sbr_mnt(dentry->d_sb, bstart);
15380+ h_dir = au_pinned_h_dir(&pin);
15381+ switch (arg->type) {
15382+ case Creat:
15383+ err = vfsub_create(h_dir, &h_path, arg->u.c.mode);
15384+ break;
15385+ case Symlink:
15386+ err = vfsub_symlink(h_dir, &h_path, arg->u.s.symname);
15387+ break;
15388+ case Mknod:
15389+ err = vfsub_mknod(h_dir, &h_path, arg->u.m.mode, arg->u.m.dev);
15390+ break;
15391+ default:
15392+ BUG();
15393+ }
15394+ created = !err;
15395+ if (!err)
15396+ err = epilog(dir, bstart, wh_dentry, dentry);
15397+
15398+ /* revert */
15399+ if (unlikely(created && err && h_path.dentry->d_inode)) {
15400+ int rerr;
15401+ rerr = vfsub_unlink(h_dir, &h_path, /*force*/0);
15402+ if (rerr) {
15403+ AuIOErr("%.*s revert failure(%d, %d)\n",
15404+ AuDLNPair(dentry), err, rerr);
15405+ err = -EIO;
15406+ }
15407+ au_dtime_revert(&dt);
4a4d8108
AM
15408+ }
15409+
15410+ au_unpin(&pin);
15411+ dput(wh_dentry);
15412+
027c5e7a
AM
15413+out_parent:
15414+ di_write_unlock(parent);
15415+out_unlock:
4a4d8108
AM
15416+ if (unlikely(err)) {
15417+ au_update_dbstart(dentry);
15418+ d_drop(dentry);
15419+ }
4a4d8108 15420+ aufs_read_unlock(dentry, AuLock_DW);
027c5e7a 15421+out:
4a4d8108
AM
15422+ return err;
15423+}
15424+
7eafdf33
AM
15425+int aufs_mknod(struct inode *dir, struct dentry *dentry, umode_t mode,
15426+ dev_t dev)
4a4d8108
AM
15427+{
15428+ struct simple_arg arg = {
15429+ .type = Mknod,
15430+ .u.m = {
15431+ .mode = mode,
15432+ .dev = dev
15433+ }
15434+ };
15435+ return add_simple(dir, dentry, &arg);
15436+}
15437+
15438+int aufs_symlink(struct inode *dir, struct dentry *dentry, const char *symname)
15439+{
15440+ struct simple_arg arg = {
15441+ .type = Symlink,
15442+ .u.s.symname = symname
15443+ };
15444+ return add_simple(dir, dentry, &arg);
15445+}
15446+
7eafdf33 15447+int aufs_create(struct inode *dir, struct dentry *dentry, umode_t mode,
4a4d8108
AM
15448+ struct nameidata *nd)
15449+{
15450+ struct simple_arg arg = {
15451+ .type = Creat,
15452+ .u.c = {
15453+ .mode = mode,
15454+ .nd = nd
15455+ }
15456+ };
15457+ return add_simple(dir, dentry, &arg);
15458+}
15459+
15460+/* ---------------------------------------------------------------------- */
15461+
15462+struct au_link_args {
15463+ aufs_bindex_t bdst, bsrc;
15464+ struct au_pin pin;
15465+ struct path h_path;
15466+ struct dentry *src_parent, *parent;
15467+};
15468+
15469+static int au_cpup_before_link(struct dentry *src_dentry,
15470+ struct au_link_args *a)
15471+{
15472+ int err;
15473+ struct dentry *h_src_dentry;
15474+ struct mutex *h_mtx;
15475+ struct file *h_file;
15476+
15477+ di_read_lock_parent(a->src_parent, AuLock_IR);
15478+ err = au_test_and_cpup_dirs(src_dentry, a->bdst);
15479+ if (unlikely(err))
15480+ goto out;
15481+
15482+ h_src_dentry = au_h_dptr(src_dentry, a->bsrc);
15483+ h_mtx = &h_src_dentry->d_inode->i_mutex;
15484+ err = au_pin(&a->pin, src_dentry, a->bdst,
15485+ au_opt_udba(src_dentry->d_sb),
15486+ AuPin_DI_LOCKED | AuPin_MNT_WRITE);
15487+ if (unlikely(err))
15488+ goto out;
15489+ mutex_lock_nested(h_mtx, AuLsc_I_CHILD);
15490+ h_file = au_h_open_pre(src_dentry, a->bsrc);
15491+ if (IS_ERR(h_file)) {
15492+ err = PTR_ERR(h_file);
15493+ h_file = NULL;
15494+ } else
1e00d052 15495+ err = au_sio_cpup_simple(src_dentry, a->bdst, -1,
4a4d8108
AM
15496+ AuCpup_DTIME /* | AuCpup_KEEPLINO */);
15497+ mutex_unlock(h_mtx);
15498+ au_h_open_post(src_dentry, a->bsrc, h_file);
15499+ au_unpin(&a->pin);
15500+
4f0767ce 15501+out:
4a4d8108
AM
15502+ di_read_unlock(a->src_parent, AuLock_IR);
15503+ return err;
15504+}
15505+
15506+static int au_cpup_or_link(struct dentry *src_dentry, struct au_link_args *a)
15507+{
15508+ int err;
15509+ unsigned char plink;
15510+ struct inode *h_inode, *inode;
15511+ struct dentry *h_src_dentry;
15512+ struct super_block *sb;
15513+ struct file *h_file;
15514+
15515+ plink = 0;
15516+ h_inode = NULL;
15517+ sb = src_dentry->d_sb;
15518+ inode = src_dentry->d_inode;
15519+ if (au_ibstart(inode) <= a->bdst)
15520+ h_inode = au_h_iptr(inode, a->bdst);
15521+ if (!h_inode || !h_inode->i_nlink) {
15522+ /* copyup src_dentry as the name of dentry. */
15523+ au_set_dbstart(src_dentry, a->bdst);
15524+ au_set_h_dptr(src_dentry, a->bdst, dget(a->h_path.dentry));
15525+ h_inode = au_h_dptr(src_dentry, a->bsrc)->d_inode;
15526+ mutex_lock_nested(&h_inode->i_mutex, AuLsc_I_CHILD);
15527+ h_file = au_h_open_pre(src_dentry, a->bsrc);
15528+ if (IS_ERR(h_file)) {
15529+ err = PTR_ERR(h_file);
15530+ h_file = NULL;
15531+ } else
15532+ err = au_sio_cpup_single(src_dentry, a->bdst, a->bsrc,
15533+ -1, AuCpup_KEEPLINO,
15534+ a->parent);
15535+ mutex_unlock(&h_inode->i_mutex);
15536+ au_h_open_post(src_dentry, a->bsrc, h_file);
15537+ au_set_h_dptr(src_dentry, a->bdst, NULL);
15538+ au_set_dbstart(src_dentry, a->bsrc);
15539+ } else {
15540+ /* the inode of src_dentry already exists on a.bdst branch */
15541+ h_src_dentry = d_find_alias(h_inode);
15542+ if (!h_src_dentry && au_plink_test(inode)) {
15543+ plink = 1;
15544+ h_src_dentry = au_plink_lkup(inode, a->bdst);
15545+ err = PTR_ERR(h_src_dentry);
15546+ if (IS_ERR(h_src_dentry))
15547+ goto out;
15548+
15549+ if (unlikely(!h_src_dentry->d_inode)) {
15550+ dput(h_src_dentry);
15551+ h_src_dentry = NULL;
15552+ }
15553+
15554+ }
15555+ if (h_src_dentry) {
15556+ err = vfsub_link(h_src_dentry, au_pinned_h_dir(&a->pin),
15557+ &a->h_path);
15558+ dput(h_src_dentry);
15559+ } else {
15560+ AuIOErr("no dentry found for hi%lu on b%d\n",
15561+ h_inode->i_ino, a->bdst);
15562+ err = -EIO;
15563+ }
15564+ }
15565+
15566+ if (!err && !plink)
15567+ au_plink_append(inode, a->bdst, a->h_path.dentry);
15568+
15569+out:
2cbb1c4b 15570+ AuTraceErr(err);
4a4d8108
AM
15571+ return err;
15572+}
15573+
15574+int aufs_link(struct dentry *src_dentry, struct inode *dir,
15575+ struct dentry *dentry)
15576+{
15577+ int err, rerr;
15578+ struct au_dtime dt;
15579+ struct au_link_args *a;
15580+ struct dentry *wh_dentry, *h_src_dentry;
15581+ struct inode *inode;
15582+ struct super_block *sb;
15583+ struct au_wr_dir_args wr_dir_args = {
15584+ /* .force_btgt = -1, */
15585+ .flags = AuWrDir_ADD_ENTRY
15586+ };
15587+
15588+ IMustLock(dir);
15589+ inode = src_dentry->d_inode;
15590+ IMustLock(inode);
15591+
4a4d8108
AM
15592+ err = -ENOMEM;
15593+ a = kzalloc(sizeof(*a), GFP_NOFS);
15594+ if (unlikely(!a))
15595+ goto out;
15596+
15597+ a->parent = dentry->d_parent; /* dir inode is locked */
027c5e7a
AM
15598+ err = aufs_read_and_write_lock2(dentry, src_dentry,
15599+ AuLock_NOPLM | AuLock_GEN);
e49829fe
JR
15600+ if (unlikely(err))
15601+ goto out_kfree;
027c5e7a
AM
15602+ err = au_d_hashed_positive(src_dentry);
15603+ if (unlikely(err))
15604+ goto out_unlock;
15605+ err = au_d_may_add(dentry);
15606+ if (unlikely(err))
15607+ goto out_unlock;
e49829fe 15608+
4a4d8108 15609+ a->src_parent = dget_parent(src_dentry);
2cbb1c4b 15610+ wr_dir_args.force_btgt = au_ibstart(inode);
4a4d8108
AM
15611+
15612+ di_write_lock_parent(a->parent);
15613+ wr_dir_args.force_btgt = au_wbr(dentry, wr_dir_args.force_btgt);
15614+ wh_dentry = lock_hdir_lkup_wh(dentry, &dt, src_dentry, &a->pin,
15615+ &wr_dir_args);
15616+ err = PTR_ERR(wh_dentry);
15617+ if (IS_ERR(wh_dentry))
027c5e7a 15618+ goto out_parent;
4a4d8108
AM
15619+
15620+ err = 0;
15621+ sb = dentry->d_sb;
15622+ a->bdst = au_dbstart(dentry);
15623+ a->h_path.dentry = au_h_dptr(dentry, a->bdst);
15624+ a->h_path.mnt = au_sbr_mnt(sb, a->bdst);
2cbb1c4b
JR
15625+ a->bsrc = au_ibstart(inode);
15626+ h_src_dentry = au_h_d_alias(src_dentry, a->bsrc);
15627+ if (!h_src_dentry) {
15628+ a->bsrc = au_dbstart(src_dentry);
15629+ h_src_dentry = au_h_d_alias(src_dentry, a->bsrc);
15630+ AuDebugOn(!h_src_dentry);
15631+ } else if (IS_ERR(h_src_dentry))
15632+ goto out_parent;
15633+
4a4d8108
AM
15634+ if (au_opt_test(au_mntflags(sb), PLINK)) {
15635+ if (a->bdst < a->bsrc
15636+ /* && h_src_dentry->d_sb != a->h_path.dentry->d_sb */)
15637+ err = au_cpup_or_link(src_dentry, a);
2cbb1c4b 15638+ else
4a4d8108
AM
15639+ err = vfsub_link(h_src_dentry, au_pinned_h_dir(&a->pin),
15640+ &a->h_path);
2cbb1c4b 15641+ dput(h_src_dentry);
4a4d8108
AM
15642+ } else {
15643+ /*
15644+ * copyup src_dentry to the branch we process,
15645+ * and then link(2) to it.
15646+ */
2cbb1c4b 15647+ dput(h_src_dentry);
4a4d8108
AM
15648+ if (a->bdst < a->bsrc
15649+ /* && h_src_dentry->d_sb != a->h_path.dentry->d_sb */) {
15650+ au_unpin(&a->pin);
15651+ di_write_unlock(a->parent);
15652+ err = au_cpup_before_link(src_dentry, a);
15653+ di_write_lock_parent(a->parent);
15654+ if (!err)
15655+ err = au_pin(&a->pin, dentry, a->bdst,
15656+ au_opt_udba(sb),
15657+ AuPin_DI_LOCKED | AuPin_MNT_WRITE);
15658+ if (unlikely(err))
15659+ goto out_wh;
15660+ }
15661+ if (!err) {
15662+ h_src_dentry = au_h_dptr(src_dentry, a->bdst);
15663+ err = -ENOENT;
15664+ if (h_src_dentry && h_src_dentry->d_inode)
15665+ err = vfsub_link(h_src_dentry,
15666+ au_pinned_h_dir(&a->pin),
15667+ &a->h_path);
15668+ }
15669+ }
15670+ if (unlikely(err))
15671+ goto out_unpin;
15672+
15673+ if (wh_dentry) {
15674+ a->h_path.dentry = wh_dentry;
15675+ err = au_wh_unlink_dentry(au_pinned_h_dir(&a->pin), &a->h_path,
15676+ dentry);
15677+ if (unlikely(err))
15678+ goto out_revert;
15679+ }
15680+
15681+ dir->i_version++;
15682+ if (au_ibstart(dir) == au_dbstart(dentry))
15683+ au_cpup_attr_timesizes(dir);
15684+ inc_nlink(inode);
15685+ inode->i_ctime = dir->i_ctime;
027c5e7a
AM
15686+ d_instantiate(dentry, au_igrab(inode));
15687+ if (d_unhashed(a->h_path.dentry))
4a4d8108
AM
15688+ /* some filesystem calls d_drop() */
15689+ d_drop(dentry);
15690+ goto out_unpin; /* success */
15691+
4f0767ce 15692+out_revert:
4a4d8108 15693+ rerr = vfsub_unlink(au_pinned_h_dir(&a->pin), &a->h_path, /*force*/0);
027c5e7a
AM
15694+ if (unlikely(rerr)) {
15695+ AuIOErr("%.*s reverting failed(%d, %d)\n",
15696+ AuDLNPair(dentry), err, rerr);
15697+ err = -EIO;
15698+ }
4a4d8108 15699+ au_dtime_revert(&dt);
4f0767ce 15700+out_unpin:
4a4d8108 15701+ au_unpin(&a->pin);
4f0767ce 15702+out_wh:
4a4d8108 15703+ dput(wh_dentry);
027c5e7a
AM
15704+out_parent:
15705+ di_write_unlock(a->parent);
15706+ dput(a->src_parent);
4f0767ce 15707+out_unlock:
4a4d8108
AM
15708+ if (unlikely(err)) {
15709+ au_update_dbstart(dentry);
15710+ d_drop(dentry);
15711+ }
4a4d8108 15712+ aufs_read_and_write_unlock2(dentry, src_dentry);
e49829fe 15713+out_kfree:
4a4d8108 15714+ kfree(a);
4f0767ce 15715+out:
4a4d8108
AM
15716+ return err;
15717+}
15718+
7eafdf33 15719+int aufs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
4a4d8108
AM
15720+{
15721+ int err, rerr;
15722+ aufs_bindex_t bindex;
15723+ unsigned char diropq;
15724+ struct path h_path;
15725+ struct dentry *wh_dentry, *parent, *opq_dentry;
15726+ struct mutex *h_mtx;
15727+ struct super_block *sb;
15728+ struct {
15729+ struct au_pin pin;
15730+ struct au_dtime dt;
15731+ } *a; /* reduce the stack usage */
15732+ struct au_wr_dir_args wr_dir_args = {
15733+ .force_btgt = -1,
15734+ .flags = AuWrDir_ADD_ENTRY | AuWrDir_ISDIR
15735+ };
15736+
15737+ IMustLock(dir);
15738+
15739+ err = -ENOMEM;
15740+ a = kmalloc(sizeof(*a), GFP_NOFS);
15741+ if (unlikely(!a))
15742+ goto out;
15743+
027c5e7a
AM
15744+ err = aufs_read_lock(dentry, AuLock_DW | AuLock_GEN);
15745+ if (unlikely(err))
15746+ goto out_free;
15747+ err = au_d_may_add(dentry);
15748+ if (unlikely(err))
15749+ goto out_unlock;
15750+
4a4d8108
AM
15751+ parent = dentry->d_parent; /* dir inode is locked */
15752+ di_write_lock_parent(parent);
15753+ wh_dentry = lock_hdir_lkup_wh(dentry, &a->dt, /*src_dentry*/NULL,
15754+ &a->pin, &wr_dir_args);
15755+ err = PTR_ERR(wh_dentry);
15756+ if (IS_ERR(wh_dentry))
027c5e7a 15757+ goto out_parent;
4a4d8108
AM
15758+
15759+ sb = dentry->d_sb;
15760+ bindex = au_dbstart(dentry);
15761+ h_path.dentry = au_h_dptr(dentry, bindex);
15762+ h_path.mnt = au_sbr_mnt(sb, bindex);
15763+ err = vfsub_mkdir(au_pinned_h_dir(&a->pin), &h_path, mode);
15764+ if (unlikely(err))
027c5e7a 15765+ goto out_unpin;
4a4d8108
AM
15766+
15767+ /* make the dir opaque */
15768+ diropq = 0;
15769+ h_mtx = &h_path.dentry->d_inode->i_mutex;
15770+ if (wh_dentry
15771+ || au_opt_test(au_mntflags(sb), ALWAYS_DIROPQ)) {
15772+ mutex_lock_nested(h_mtx, AuLsc_I_CHILD);
15773+ opq_dentry = au_diropq_create(dentry, bindex);
15774+ mutex_unlock(h_mtx);
15775+ err = PTR_ERR(opq_dentry);
15776+ if (IS_ERR(opq_dentry))
15777+ goto out_dir;
15778+ dput(opq_dentry);
15779+ diropq = 1;
15780+ }
15781+
15782+ err = epilog(dir, bindex, wh_dentry, dentry);
15783+ if (!err) {
15784+ inc_nlink(dir);
027c5e7a 15785+ goto out_unpin; /* success */
4a4d8108
AM
15786+ }
15787+
15788+ /* revert */
15789+ if (diropq) {
15790+ AuLabel(revert opq);
15791+ mutex_lock_nested(h_mtx, AuLsc_I_CHILD);
15792+ rerr = au_diropq_remove(dentry, bindex);
15793+ mutex_unlock(h_mtx);
15794+ if (rerr) {
15795+ AuIOErr("%.*s reverting diropq failed(%d, %d)\n",
15796+ AuDLNPair(dentry), err, rerr);
15797+ err = -EIO;
15798+ }
15799+ }
15800+
4f0767ce 15801+out_dir:
4a4d8108
AM
15802+ AuLabel(revert dir);
15803+ rerr = vfsub_rmdir(au_pinned_h_dir(&a->pin), &h_path);
15804+ if (rerr) {
15805+ AuIOErr("%.*s reverting dir failed(%d, %d)\n",
15806+ AuDLNPair(dentry), err, rerr);
15807+ err = -EIO;
15808+ }
4a4d8108 15809+ au_dtime_revert(&a->dt);
027c5e7a 15810+out_unpin:
4a4d8108
AM
15811+ au_unpin(&a->pin);
15812+ dput(wh_dentry);
027c5e7a
AM
15813+out_parent:
15814+ di_write_unlock(parent);
15815+out_unlock:
4a4d8108
AM
15816+ if (unlikely(err)) {
15817+ au_update_dbstart(dentry);
15818+ d_drop(dentry);
15819+ }
4a4d8108 15820+ aufs_read_unlock(dentry, AuLock_DW);
027c5e7a 15821+out_free:
4a4d8108 15822+ kfree(a);
4f0767ce 15823+out:
4a4d8108
AM
15824+ return err;
15825+}
7f207e10
AM
15826diff -urN /usr/share/empty/fs/aufs/i_op.c linux/fs/aufs/i_op.c
15827--- /usr/share/empty/fs/aufs/i_op.c 1970-01-01 01:00:00.000000000 +0100
7ce627cf 15828+++ linux/fs/aufs/i_op.c 2012-05-22 09:06:08.867458905 +0200
92d182d2 15829@@ -0,0 +1,993 @@
4a4d8108 15830+/*
f6c5ef8b 15831+ * Copyright (C) 2005-2012 Junjiro R. Okajima
4a4d8108
AM
15832+ *
15833+ * This program, aufs is free software; you can redistribute it and/or modify
15834+ * it under the terms of the GNU General Public License as published by
15835+ * the Free Software Foundation; either version 2 of the License, or
15836+ * (at your option) any later version.
15837+ *
15838+ * This program is distributed in the hope that it will be useful,
15839+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
15840+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15841+ * GNU General Public License for more details.
15842+ *
15843+ * You should have received a copy of the GNU General Public License
15844+ * along with this program; if not, write to the Free Software
15845+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
15846+ */
1facf9fc 15847+
1308ab2a 15848+/*
4a4d8108 15849+ * inode operations (except add/del/rename)
1308ab2a 15850+ */
4a4d8108
AM
15851+
15852+#include <linux/device_cgroup.h>
15853+#include <linux/fs_stack.h>
92d182d2 15854+#include <linux/mm.h>
4a4d8108
AM
15855+#include <linux/namei.h>
15856+#include <linux/security.h>
4a4d8108
AM
15857+#include "aufs.h"
15858+
1e00d052 15859+static int h_permission(struct inode *h_inode, int mask,
4a4d8108 15860+ struct vfsmount *h_mnt, int brperm)
1facf9fc 15861+{
1308ab2a 15862+ int err;
4a4d8108 15863+ const unsigned char write_mask = !!(mask & (MAY_WRITE | MAY_APPEND));
1facf9fc 15864+
4a4d8108
AM
15865+ err = -EACCES;
15866+ if ((write_mask && IS_IMMUTABLE(h_inode))
15867+ || ((mask & MAY_EXEC)
15868+ && S_ISREG(h_inode->i_mode)
15869+ && ((h_mnt->mnt_flags & MNT_NOEXEC)
15870+ || !(h_inode->i_mode & S_IXUGO))))
15871+ goto out;
15872+
15873+ /*
15874+ * - skip the lower fs test in the case of write to ro branch.
15875+ * - nfs dir permission write check is optimized, but a policy for
15876+ * link/rename requires a real check.
15877+ */
15878+ if ((write_mask && !au_br_writable(brperm))
15879+ || (au_test_nfs(h_inode->i_sb) && S_ISDIR(h_inode->i_mode)
15880+ && write_mask && !(mask & MAY_READ))
15881+ || !h_inode->i_op->permission) {
15882+ /* AuLabel(generic_permission); */
1e00d052 15883+ err = generic_permission(h_inode, mask);
1308ab2a 15884+ } else {
4a4d8108 15885+ /* AuLabel(h_inode->permission); */
1e00d052 15886+ err = h_inode->i_op->permission(h_inode, mask);
4a4d8108
AM
15887+ AuTraceErr(err);
15888+ }
1facf9fc 15889+
4a4d8108
AM
15890+ if (!err)
15891+ err = devcgroup_inode_permission(h_inode, mask);
7f207e10 15892+ if (!err)
4a4d8108 15893+ err = security_inode_permission(h_inode, mask);
4a4d8108
AM
15894+
15895+#if 0
15896+ if (!err) {
15897+ /* todo: do we need to call ima_path_check()? */
15898+ struct path h_path = {
15899+ .dentry =
15900+ .mnt = h_mnt
15901+ };
15902+ err = ima_path_check(&h_path,
15903+ mask & (MAY_READ | MAY_WRITE | MAY_EXEC),
15904+ IMA_COUNT_LEAVE);
1308ab2a 15905+ }
4a4d8108 15906+#endif
dece6358 15907+
4f0767ce 15908+out:
1308ab2a 15909+ return err;
15910+}
dece6358 15911+
1e00d052 15912+static int aufs_permission(struct inode *inode, int mask)
1308ab2a 15913+{
15914+ int err;
4a4d8108
AM
15915+ aufs_bindex_t bindex, bend;
15916+ const unsigned char isdir = !!S_ISDIR(inode->i_mode),
15917+ write_mask = !!(mask & (MAY_WRITE | MAY_APPEND));
15918+ struct inode *h_inode;
15919+ struct super_block *sb;
15920+ struct au_branch *br;
1facf9fc 15921+
027c5e7a 15922+ /* todo: support rcu-walk? */
1e00d052 15923+ if (mask & MAY_NOT_BLOCK)
027c5e7a
AM
15924+ return -ECHILD;
15925+
4a4d8108
AM
15926+ sb = inode->i_sb;
15927+ si_read_lock(sb, AuLock_FLUSH);
15928+ ii_read_lock_child(inode);
027c5e7a
AM
15929+#if 0
15930+ err = au_iigen_test(inode, au_sigen(sb));
15931+ if (unlikely(err))
15932+ goto out;
15933+#endif
dece6358 15934+
4a4d8108
AM
15935+ if (!isdir || write_mask) {
15936+ err = au_busy_or_stale();
15937+ h_inode = au_h_iptr(inode, au_ibstart(inode));
15938+ if (unlikely(!h_inode
15939+ || (h_inode->i_mode & S_IFMT)
15940+ != (inode->i_mode & S_IFMT)))
15941+ goto out;
1facf9fc 15942+
4a4d8108
AM
15943+ err = 0;
15944+ bindex = au_ibstart(inode);
15945+ br = au_sbr(sb, bindex);
1e00d052 15946+ err = h_permission(h_inode, mask, br->br_mnt, br->br_perm);
4a4d8108
AM
15947+ if (write_mask
15948+ && !err
15949+ && !special_file(h_inode->i_mode)) {
15950+ /* test whether the upper writable branch exists */
15951+ err = -EROFS;
15952+ for (; bindex >= 0; bindex--)
15953+ if (!au_br_rdonly(au_sbr(sb, bindex))) {
15954+ err = 0;
15955+ break;
15956+ }
15957+ }
15958+ goto out;
15959+ }
dece6358 15960+
4a4d8108 15961+ /* non-write to dir */
1308ab2a 15962+ err = 0;
4a4d8108
AM
15963+ bend = au_ibend(inode);
15964+ for (bindex = au_ibstart(inode); !err && bindex <= bend; bindex++) {
15965+ h_inode = au_h_iptr(inode, bindex);
15966+ if (h_inode) {
15967+ err = au_busy_or_stale();
15968+ if (unlikely(!S_ISDIR(h_inode->i_mode)))
15969+ break;
15970+
15971+ br = au_sbr(sb, bindex);
1e00d052 15972+ err = h_permission(h_inode, mask, br->br_mnt,
4a4d8108
AM
15973+ br->br_perm);
15974+ }
15975+ }
1308ab2a 15976+
4f0767ce 15977+out:
4a4d8108
AM
15978+ ii_read_unlock(inode);
15979+ si_read_unlock(sb);
1308ab2a 15980+ return err;
15981+}
15982+
4a4d8108 15983+/* ---------------------------------------------------------------------- */
1facf9fc 15984+
4a4d8108
AM
15985+static struct dentry *aufs_lookup(struct inode *dir, struct dentry *dentry,
15986+ struct nameidata *nd)
15987+{
15988+ struct dentry *ret, *parent;
b752ccd1 15989+ struct inode *inode;
4a4d8108 15990+ struct super_block *sb;
9dbd164d 15991+ int err, npositive, lc_idx;
dece6358 15992+
4a4d8108 15993+ IMustLock(dir);
1308ab2a 15994+
4a4d8108 15995+ sb = dir->i_sb;
7f207e10
AM
15996+ err = si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLM);
15997+ ret = ERR_PTR(err);
15998+ if (unlikely(err))
15999+ goto out;
16000+
4a4d8108
AM
16001+ ret = ERR_PTR(-ENAMETOOLONG);
16002+ if (unlikely(dentry->d_name.len > AUFS_MAX_NAMELEN))
7f207e10 16003+ goto out_si;
4a4d8108
AM
16004+ err = au_di_init(dentry);
16005+ ret = ERR_PTR(err);
16006+ if (unlikely(err))
7f207e10 16007+ goto out_si;
1308ab2a 16008+
9dbd164d 16009+ inode = NULL;
027c5e7a 16010+ npositive = 0; /* suppress a warning */
4a4d8108
AM
16011+ parent = dentry->d_parent; /* dir inode is locked */
16012+ di_read_lock_parent(parent, AuLock_IR);
027c5e7a
AM
16013+ err = au_alive_dir(parent);
16014+ if (!err)
16015+ err = au_digen_test(parent, au_sigen(sb));
16016+ if (!err) {
16017+ npositive = au_lkup_dentry(dentry, au_dbstart(parent),
16018+ /*type*/0, nd);
16019+ err = npositive;
16020+ }
4a4d8108 16021+ di_read_unlock(parent, AuLock_IR);
4a4d8108
AM
16022+ ret = ERR_PTR(err);
16023+ if (unlikely(err < 0))
16024+ goto out_unlock;
1308ab2a 16025+
4a4d8108 16026+ if (npositive) {
b752ccd1 16027+ inode = au_new_inode(dentry, /*must_new*/0);
4a4d8108 16028+ ret = (void *)inode;
1facf9fc 16029+ }
9dbd164d
AM
16030+ if (IS_ERR(inode)) {
16031+ inode = NULL;
4a4d8108 16032+ goto out_unlock;
9dbd164d 16033+ }
4a4d8108
AM
16034+
16035+ ret = d_splice_alias(inode, dentry);
7f207e10 16036+ if (unlikely(IS_ERR(ret) && inode)) {
4a4d8108 16037+ ii_write_unlock(inode);
9dbd164d
AM
16038+ lc_idx = AuLcNonDir_IIINFO;
16039+ if (S_ISLNK(inode->i_mode))
16040+ lc_idx = AuLcSymlink_IIINFO;
16041+ else if (S_ISDIR(inode->i_mode))
16042+ lc_idx = AuLcDir_IIINFO;
16043+ au_rw_class(&au_ii(inode)->ii_rwsem, au_lc_key + lc_idx);
7f207e10
AM
16044+ iput(inode);
16045+ }
1facf9fc 16046+
4f0767ce 16047+out_unlock:
4a4d8108 16048+ di_write_unlock(dentry);
9dbd164d
AM
16049+ if (unlikely(IS_ERR(ret) && inode)) {
16050+ lc_idx = AuLcNonDir_DIINFO;
16051+ if (S_ISLNK(inode->i_mode))
16052+ lc_idx = AuLcSymlink_DIINFO;
16053+ else if (S_ISDIR(inode->i_mode))
16054+ lc_idx = AuLcDir_DIINFO;
16055+ au_rw_class(&au_di(dentry)->di_rwsem, au_lc_key + lc_idx);
16056+ }
7f207e10 16057+out_si:
4a4d8108 16058+ si_read_unlock(sb);
7f207e10 16059+out:
4a4d8108
AM
16060+ return ret;
16061+}
1facf9fc 16062+
4a4d8108 16063+/* ---------------------------------------------------------------------- */
1facf9fc 16064+
4a4d8108
AM
16065+static int au_wr_dir_cpup(struct dentry *dentry, struct dentry *parent,
16066+ const unsigned char add_entry, aufs_bindex_t bcpup,
16067+ aufs_bindex_t bstart)
16068+{
16069+ int err;
16070+ struct dentry *h_parent;
16071+ struct inode *h_dir;
1facf9fc 16072+
027c5e7a 16073+ if (add_entry)
4a4d8108 16074+ IMustLock(parent->d_inode);
027c5e7a 16075+ else
4a4d8108
AM
16076+ di_write_lock_parent(parent);
16077+
16078+ err = 0;
16079+ if (!au_h_dptr(parent, bcpup)) {
16080+ if (bstart < bcpup)
16081+ err = au_cpdown_dirs(dentry, bcpup);
16082+ else
16083+ err = au_cpup_dirs(dentry, bcpup);
16084+ }
16085+ if (!err && add_entry) {
16086+ h_parent = au_h_dptr(parent, bcpup);
16087+ h_dir = h_parent->d_inode;
16088+ mutex_lock_nested(&h_dir->i_mutex, AuLsc_I_PARENT);
16089+ err = au_lkup_neg(dentry, bcpup);
16090+ /* todo: no unlock here */
16091+ mutex_unlock(&h_dir->i_mutex);
027c5e7a
AM
16092+
16093+ AuDbg("bcpup %d\n", bcpup);
16094+ if (!err) {
16095+ if (!dentry->d_inode)
16096+ au_set_h_dptr(dentry, bstart, NULL);
4a4d8108
AM
16097+ au_update_dbrange(dentry, /*do_put_zero*/0);
16098+ }
1308ab2a 16099+ }
1facf9fc 16100+
4a4d8108
AM
16101+ if (!add_entry)
16102+ di_write_unlock(parent);
16103+ if (!err)
16104+ err = bcpup; /* success */
1308ab2a 16105+
027c5e7a 16106+ AuTraceErr(err);
4a4d8108
AM
16107+ return err;
16108+}
1facf9fc 16109+
4a4d8108
AM
16110+/*
16111+ * decide the branch and the parent dir where we will create a new entry.
16112+ * returns new bindex or an error.
16113+ * copyup the parent dir if needed.
16114+ */
16115+int au_wr_dir(struct dentry *dentry, struct dentry *src_dentry,
16116+ struct au_wr_dir_args *args)
16117+{
16118+ int err;
16119+ aufs_bindex_t bcpup, bstart, src_bstart;
16120+ const unsigned char add_entry = !!au_ftest_wrdir(args->flags,
16121+ ADD_ENTRY);
16122+ struct super_block *sb;
16123+ struct dentry *parent;
16124+ struct au_sbinfo *sbinfo;
1facf9fc 16125+
4a4d8108
AM
16126+ sb = dentry->d_sb;
16127+ sbinfo = au_sbi(sb);
16128+ parent = dget_parent(dentry);
16129+ bstart = au_dbstart(dentry);
16130+ bcpup = bstart;
16131+ if (args->force_btgt < 0) {
16132+ if (src_dentry) {
16133+ src_bstart = au_dbstart(src_dentry);
16134+ if (src_bstart < bstart)
16135+ bcpup = src_bstart;
16136+ } else if (add_entry) {
16137+ err = AuWbrCreate(sbinfo, dentry,
16138+ au_ftest_wrdir(args->flags, ISDIR));
16139+ bcpup = err;
16140+ }
1facf9fc 16141+
4a4d8108
AM
16142+ if (bcpup < 0 || au_test_ro(sb, bcpup, dentry->d_inode)) {
16143+ if (add_entry)
16144+ err = AuWbrCopyup(sbinfo, dentry);
16145+ else {
16146+ if (!IS_ROOT(dentry)) {
16147+ di_read_lock_parent(parent, !AuLock_IR);
16148+ err = AuWbrCopyup(sbinfo, dentry);
16149+ di_read_unlock(parent, !AuLock_IR);
16150+ } else
16151+ err = AuWbrCopyup(sbinfo, dentry);
16152+ }
16153+ bcpup = err;
16154+ if (unlikely(err < 0))
16155+ goto out;
16156+ }
16157+ } else {
16158+ bcpup = args->force_btgt;
16159+ AuDebugOn(au_test_ro(sb, bcpup, dentry->d_inode));
1308ab2a 16160+ }
027c5e7a 16161+
4a4d8108
AM
16162+ AuDbg("bstart %d, bcpup %d\n", bstart, bcpup);
16163+ err = bcpup;
16164+ if (bcpup == bstart)
16165+ goto out; /* success */
4a4d8108
AM
16166+
16167+ /* copyup the new parent into the branch we process */
16168+ err = au_wr_dir_cpup(dentry, parent, add_entry, bcpup, bstart);
027c5e7a
AM
16169+ if (err >= 0) {
16170+ if (!dentry->d_inode) {
16171+ au_set_h_dptr(dentry, bstart, NULL);
16172+ au_set_dbstart(dentry, bcpup);
16173+ au_set_dbend(dentry, bcpup);
16174+ }
16175+ AuDebugOn(add_entry && !au_h_dptr(dentry, bcpup));
16176+ }
4a4d8108 16177+
4f0767ce 16178+out:
4a4d8108 16179+ dput(parent);
dece6358
AM
16180+ return err;
16181+}
1facf9fc 16182+
1308ab2a 16183+/* ---------------------------------------------------------------------- */
16184+
4a4d8108 16185+struct dentry *au_pinned_h_parent(struct au_pin *pin)
1308ab2a 16186+{
4a4d8108
AM
16187+ if (pin && pin->parent)
16188+ return au_h_dptr(pin->parent, pin->bindex);
16189+ return NULL;
dece6358 16190+}
1facf9fc 16191+
4a4d8108 16192+void au_unpin(struct au_pin *p)
dece6358 16193+{
e49829fe 16194+ if (p->h_mnt && au_ftest_pin(p->flags, MNT_WRITE))
4a4d8108
AM
16195+ mnt_drop_write(p->h_mnt);
16196+ if (!p->hdir)
16197+ return;
1facf9fc 16198+
4a4d8108
AM
16199+ au_hn_imtx_unlock(p->hdir);
16200+ if (!au_ftest_pin(p->flags, DI_LOCKED))
16201+ di_read_unlock(p->parent, AuLock_IR);
16202+ iput(p->hdir->hi_inode);
16203+ dput(p->parent);
16204+ p->parent = NULL;
16205+ p->hdir = NULL;
16206+ p->h_mnt = NULL;
16207+}
1308ab2a 16208+
4a4d8108
AM
16209+int au_do_pin(struct au_pin *p)
16210+{
16211+ int err;
16212+ struct super_block *sb;
16213+ struct dentry *h_dentry, *h_parent;
16214+ struct au_branch *br;
16215+ struct inode *h_dir;
16216+
16217+ err = 0;
16218+ sb = p->dentry->d_sb;
16219+ br = au_sbr(sb, p->bindex);
16220+ if (IS_ROOT(p->dentry)) {
16221+ if (au_ftest_pin(p->flags, MNT_WRITE)) {
16222+ p->h_mnt = br->br_mnt;
16223+ err = mnt_want_write(p->h_mnt);
16224+ if (unlikely(err)) {
16225+ au_fclr_pin(p->flags, MNT_WRITE);
16226+ goto out_err;
16227+ }
16228+ }
dece6358 16229+ goto out;
1facf9fc 16230+ }
16231+
4a4d8108
AM
16232+ h_dentry = NULL;
16233+ if (p->bindex <= au_dbend(p->dentry))
16234+ h_dentry = au_h_dptr(p->dentry, p->bindex);
dece6358 16235+
4a4d8108
AM
16236+ p->parent = dget_parent(p->dentry);
16237+ if (!au_ftest_pin(p->flags, DI_LOCKED))
16238+ di_read_lock(p->parent, AuLock_IR, p->lsc_di);
dece6358 16239+
4a4d8108
AM
16240+ h_dir = NULL;
16241+ h_parent = au_h_dptr(p->parent, p->bindex);
16242+ p->hdir = au_hi(p->parent->d_inode, p->bindex);
16243+ if (p->hdir)
16244+ h_dir = p->hdir->hi_inode;
dece6358 16245+
b752ccd1
AM
16246+ /*
16247+ * udba case, or
16248+ * if DI_LOCKED is not set, then p->parent may be different
16249+ * and h_parent can be NULL.
16250+ */
16251+ if (unlikely(!p->hdir || !h_dir || !h_parent)) {
e49829fe 16252+ err = -EBUSY;
4a4d8108
AM
16253+ if (!au_ftest_pin(p->flags, DI_LOCKED))
16254+ di_read_unlock(p->parent, AuLock_IR);
16255+ dput(p->parent);
16256+ p->parent = NULL;
16257+ goto out_err;
16258+ }
1308ab2a 16259+
4a4d8108
AM
16260+ au_igrab(h_dir);
16261+ au_hn_imtx_lock_nested(p->hdir, p->lsc_hi);
1308ab2a 16262+
4a4d8108
AM
16263+ if (unlikely(p->hdir->hi_inode != h_parent->d_inode)) {
16264+ err = -EBUSY;
16265+ goto out_unpin;
16266+ }
16267+ if (h_dentry) {
16268+ err = au_h_verify(h_dentry, p->udba, h_dir, h_parent, br);
16269+ if (unlikely(err)) {
16270+ au_fclr_pin(p->flags, MNT_WRITE);
16271+ goto out_unpin;
16272+ }
1facf9fc 16273+ }
dece6358 16274+
4a4d8108
AM
16275+ if (au_ftest_pin(p->flags, MNT_WRITE)) {
16276+ p->h_mnt = br->br_mnt;
16277+ err = mnt_want_write(p->h_mnt);
dece6358 16278+ if (unlikely(err)) {
4a4d8108
AM
16279+ au_fclr_pin(p->flags, MNT_WRITE);
16280+ goto out_unpin;
dece6358
AM
16281+ }
16282+ }
4a4d8108
AM
16283+ goto out; /* success */
16284+
4f0767ce 16285+out_unpin:
4a4d8108 16286+ au_unpin(p);
4f0767ce 16287+out_err:
4a4d8108
AM
16288+ pr_err("err %d\n", err);
16289+ err = au_busy_or_stale();
4f0767ce 16290+out:
1facf9fc 16291+ return err;
16292+}
16293+
4a4d8108
AM
16294+void au_pin_init(struct au_pin *p, struct dentry *dentry,
16295+ aufs_bindex_t bindex, int lsc_di, int lsc_hi,
16296+ unsigned int udba, unsigned char flags)
16297+{
16298+ p->dentry = dentry;
16299+ p->udba = udba;
16300+ p->lsc_di = lsc_di;
16301+ p->lsc_hi = lsc_hi;
16302+ p->flags = flags;
16303+ p->bindex = bindex;
16304+
16305+ p->parent = NULL;
16306+ p->hdir = NULL;
16307+ p->h_mnt = NULL;
16308+}
16309+
16310+int au_pin(struct au_pin *pin, struct dentry *dentry, aufs_bindex_t bindex,
16311+ unsigned int udba, unsigned char flags)
16312+{
16313+ au_pin_init(pin, dentry, bindex, AuLsc_DI_PARENT, AuLsc_I_PARENT2,
16314+ udba, flags);
16315+ return au_do_pin(pin);
16316+}
16317+
dece6358
AM
16318+/* ---------------------------------------------------------------------- */
16319+
1308ab2a 16320+/*
4a4d8108
AM
16321+ * ->setattr() and ->getattr() are called in various cases.
16322+ * chmod, stat: dentry is revalidated.
16323+ * fchmod, fstat: file and dentry are not revalidated, additionally they may be
16324+ * unhashed.
16325+ * for ->setattr(), ia->ia_file is passed from ftruncate only.
1308ab2a 16326+ */
027c5e7a 16327+/* todo: consolidate with do_refresh() and simple_reval_dpath() */
4a4d8108 16328+static int au_reval_for_attr(struct dentry *dentry, unsigned int sigen)
1facf9fc 16329+{
4a4d8108
AM
16330+ int err;
16331+ struct inode *inode;
16332+ struct dentry *parent;
1facf9fc 16333+
1308ab2a 16334+ err = 0;
4a4d8108 16335+ inode = dentry->d_inode;
027c5e7a 16336+ if (au_digen_test(dentry, sigen)) {
4a4d8108
AM
16337+ parent = dget_parent(dentry);
16338+ di_read_lock_parent(parent, AuLock_IR);
027c5e7a 16339+ err = au_refresh_dentry(dentry, parent);
4a4d8108
AM
16340+ di_read_unlock(parent, AuLock_IR);
16341+ dput(parent);
dece6358 16342+ }
1facf9fc 16343+
4a4d8108 16344+ AuTraceErr(err);
1308ab2a 16345+ return err;
16346+}
dece6358 16347+
4a4d8108
AM
16348+#define AuIcpup_DID_CPUP 1
16349+#define au_ftest_icpup(flags, name) ((flags) & AuIcpup_##name)
7f207e10
AM
16350+#define au_fset_icpup(flags, name) \
16351+ do { (flags) |= AuIcpup_##name; } while (0)
16352+#define au_fclr_icpup(flags, name) \
16353+ do { (flags) &= ~AuIcpup_##name; } while (0)
1308ab2a 16354+
4a4d8108
AM
16355+struct au_icpup_args {
16356+ unsigned char flags;
16357+ unsigned char pin_flags;
16358+ aufs_bindex_t btgt;
16359+ unsigned int udba;
16360+ struct au_pin pin;
16361+ struct path h_path;
16362+ struct inode *h_inode;
16363+};
1308ab2a 16364+
4a4d8108
AM
16365+static int au_pin_and_icpup(struct dentry *dentry, struct iattr *ia,
16366+ struct au_icpup_args *a)
1308ab2a 16367+{
16368+ int err;
4a4d8108 16369+ loff_t sz;
e49829fe 16370+ aufs_bindex_t bstart, ibstart;
4a4d8108
AM
16371+ struct dentry *hi_wh, *parent;
16372+ struct inode *inode;
16373+ struct file *h_file;
16374+ struct au_wr_dir_args wr_dir_args = {
16375+ .force_btgt = -1,
16376+ .flags = 0
16377+ };
16378+
16379+ bstart = au_dbstart(dentry);
16380+ inode = dentry->d_inode;
16381+ if (S_ISDIR(inode->i_mode))
16382+ au_fset_wrdir(wr_dir_args.flags, ISDIR);
16383+ /* plink or hi_wh() case */
e49829fe 16384+ ibstart = au_ibstart(inode);
027c5e7a 16385+ if (bstart != ibstart && !au_test_ro(inode->i_sb, ibstart, inode))
e49829fe 16386+ wr_dir_args.force_btgt = ibstart;
4a4d8108
AM
16387+ err = au_wr_dir(dentry, /*src_dentry*/NULL, &wr_dir_args);
16388+ if (unlikely(err < 0))
16389+ goto out;
16390+ a->btgt = err;
16391+ if (err != bstart)
16392+ au_fset_icpup(a->flags, DID_CPUP);
16393+
16394+ err = 0;
16395+ a->pin_flags = AuPin_MNT_WRITE;
16396+ parent = NULL;
16397+ if (!IS_ROOT(dentry)) {
16398+ au_fset_pin(a->pin_flags, DI_LOCKED);
16399+ parent = dget_parent(dentry);
16400+ di_write_lock_parent(parent);
16401+ }
16402+
16403+ err = au_pin(&a->pin, dentry, a->btgt, a->udba, a->pin_flags);
16404+ if (unlikely(err))
16405+ goto out_parent;
16406+
16407+ a->h_path.dentry = au_h_dptr(dentry, bstart);
16408+ a->h_inode = a->h_path.dentry->d_inode;
16409+ mutex_lock_nested(&a->h_inode->i_mutex, AuLsc_I_CHILD);
16410+ sz = -1;
16411+ if ((ia->ia_valid & ATTR_SIZE) && ia->ia_size < i_size_read(a->h_inode))
16412+ sz = ia->ia_size;
16413+
16414+ h_file = NULL;
16415+ hi_wh = NULL;
027c5e7a 16416+ if (au_ftest_icpup(a->flags, DID_CPUP) && d_unlinked(dentry)) {
4a4d8108
AM
16417+ hi_wh = au_hi_wh(inode, a->btgt);
16418+ if (!hi_wh) {
16419+ err = au_sio_cpup_wh(dentry, a->btgt, sz, /*file*/NULL);
16420+ if (unlikely(err))
16421+ goto out_unlock;
16422+ hi_wh = au_hi_wh(inode, a->btgt);
16423+ /* todo: revalidate hi_wh? */
16424+ }
16425+ }
16426+
16427+ if (parent) {
16428+ au_pin_set_parent_lflag(&a->pin, /*lflag*/0);
16429+ di_downgrade_lock(parent, AuLock_IR);
16430+ dput(parent);
16431+ parent = NULL;
16432+ }
16433+ if (!au_ftest_icpup(a->flags, DID_CPUP))
16434+ goto out; /* success */
16435+
16436+ if (!d_unhashed(dentry)) {
16437+ h_file = au_h_open_pre(dentry, bstart);
16438+ if (IS_ERR(h_file)) {
16439+ err = PTR_ERR(h_file);
16440+ h_file = NULL;
16441+ } else
16442+ err = au_sio_cpup_simple(dentry, a->btgt, sz,
16443+ AuCpup_DTIME);
16444+ if (!err)
16445+ a->h_path.dentry = au_h_dptr(dentry, a->btgt);
16446+ } else if (!hi_wh)
16447+ a->h_path.dentry = au_h_dptr(dentry, a->btgt);
16448+ else
16449+ a->h_path.dentry = hi_wh; /* do not dget here */
1308ab2a 16450+
4f0767ce 16451+out_unlock:
4a4d8108
AM
16452+ mutex_unlock(&a->h_inode->i_mutex);
16453+ au_h_open_post(dentry, bstart, h_file);
16454+ a->h_inode = a->h_path.dentry->d_inode;
dece6358 16455+ if (!err) {
4a4d8108 16456+ mutex_lock_nested(&a->h_inode->i_mutex, AuLsc_I_CHILD);
dece6358 16457+ goto out; /* success */
1facf9fc 16458+ }
dece6358 16459+
4a4d8108 16460+ au_unpin(&a->pin);
4f0767ce 16461+out_parent:
4a4d8108
AM
16462+ if (parent) {
16463+ di_write_unlock(parent);
16464+ dput(parent);
16465+ }
4f0767ce 16466+out:
1facf9fc 16467+ return err;
16468+}
16469+
4a4d8108 16470+static int aufs_setattr(struct dentry *dentry, struct iattr *ia)
1facf9fc 16471+{
4a4d8108
AM
16472+ int err;
16473+ struct inode *inode;
16474+ struct super_block *sb;
16475+ struct file *file;
16476+ struct au_icpup_args *a;
1facf9fc 16477+
4a4d8108
AM
16478+ inode = dentry->d_inode;
16479+ IMustLock(inode);
dece6358 16480+
4a4d8108
AM
16481+ err = -ENOMEM;
16482+ a = kzalloc(sizeof(*a), GFP_NOFS);
16483+ if (unlikely(!a))
16484+ goto out;
1facf9fc 16485+
4a4d8108
AM
16486+ if (ia->ia_valid & (ATTR_KILL_SUID | ATTR_KILL_SGID))
16487+ ia->ia_valid &= ~ATTR_MODE;
dece6358 16488+
4a4d8108
AM
16489+ file = NULL;
16490+ sb = dentry->d_sb;
e49829fe
JR
16491+ err = si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLM);
16492+ if (unlikely(err))
16493+ goto out_kfree;
16494+
4a4d8108
AM
16495+ if (ia->ia_valid & ATTR_FILE) {
16496+ /* currently ftruncate(2) only */
16497+ AuDebugOn(!S_ISREG(inode->i_mode));
16498+ file = ia->ia_file;
16499+ err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/1);
16500+ if (unlikely(err))
16501+ goto out_si;
16502+ ia->ia_file = au_hf_top(file);
16503+ a->udba = AuOpt_UDBA_NONE;
16504+ } else {
16505+ /* fchmod() doesn't pass ia_file */
16506+ a->udba = au_opt_udba(sb);
027c5e7a
AM
16507+ di_write_lock_child(dentry);
16508+ /* no d_unlinked(), to set UDBA_NONE for root */
4a4d8108
AM
16509+ if (d_unhashed(dentry))
16510+ a->udba = AuOpt_UDBA_NONE;
4a4d8108
AM
16511+ if (a->udba != AuOpt_UDBA_NONE) {
16512+ AuDebugOn(IS_ROOT(dentry));
16513+ err = au_reval_for_attr(dentry, au_sigen(sb));
16514+ if (unlikely(err))
16515+ goto out_dentry;
16516+ }
dece6358 16517+ }
dece6358 16518+
4a4d8108
AM
16519+ err = au_pin_and_icpup(dentry, ia, a);
16520+ if (unlikely(err < 0))
16521+ goto out_dentry;
16522+ if (au_ftest_icpup(a->flags, DID_CPUP)) {
16523+ ia->ia_file = NULL;
16524+ ia->ia_valid &= ~ATTR_FILE;
1308ab2a 16525+ }
dece6358 16526+
4a4d8108
AM
16527+ a->h_path.mnt = au_sbr_mnt(sb, a->btgt);
16528+ if ((ia->ia_valid & (ATTR_MODE | ATTR_CTIME))
16529+ == (ATTR_MODE | ATTR_CTIME)) {
7eafdf33 16530+ err = security_path_chmod(&a->h_path, ia->ia_mode);
4a4d8108
AM
16531+ if (unlikely(err))
16532+ goto out_unlock;
16533+ } else if ((ia->ia_valid & (ATTR_UID | ATTR_GID))
16534+ && (ia->ia_valid & ATTR_CTIME)) {
16535+ err = security_path_chown(&a->h_path, ia->ia_uid, ia->ia_gid);
16536+ if (unlikely(err))
16537+ goto out_unlock;
16538+ }
dece6358 16539+
4a4d8108
AM
16540+ if (ia->ia_valid & ATTR_SIZE) {
16541+ struct file *f;
1308ab2a 16542+
953406b4 16543+ if (ia->ia_size < i_size_read(inode))
4a4d8108 16544+ /* unmap only */
953406b4 16545+ truncate_setsize(inode, ia->ia_size);
1308ab2a 16546+
4a4d8108
AM
16547+ f = NULL;
16548+ if (ia->ia_valid & ATTR_FILE)
16549+ f = ia->ia_file;
16550+ mutex_unlock(&a->h_inode->i_mutex);
16551+ err = vfsub_trunc(&a->h_path, ia->ia_size, ia->ia_valid, f);
16552+ mutex_lock_nested(&a->h_inode->i_mutex, AuLsc_I_CHILD);
16553+ } else
16554+ err = vfsub_notify_change(&a->h_path, ia);
16555+ if (!err)
16556+ au_cpup_attr_changeable(inode);
1308ab2a 16557+
4f0767ce 16558+out_unlock:
4a4d8108
AM
16559+ mutex_unlock(&a->h_inode->i_mutex);
16560+ au_unpin(&a->pin);
027c5e7a
AM
16561+ if (unlikely(err))
16562+ au_update_dbstart(dentry);
4f0767ce 16563+out_dentry:
4a4d8108
AM
16564+ di_write_unlock(dentry);
16565+ if (file) {
16566+ fi_write_unlock(file);
16567+ ia->ia_file = file;
16568+ ia->ia_valid |= ATTR_FILE;
16569+ }
4f0767ce 16570+out_si:
4a4d8108 16571+ si_read_unlock(sb);
e49829fe 16572+out_kfree:
4a4d8108 16573+ kfree(a);
4f0767ce 16574+out:
4a4d8108
AM
16575+ AuTraceErr(err);
16576+ return err;
1facf9fc 16577+}
16578+
4a4d8108
AM
16579+static void au_refresh_iattr(struct inode *inode, struct kstat *st,
16580+ unsigned int nlink)
1facf9fc 16581+{
9dbd164d
AM
16582+ unsigned int n;
16583+
4a4d8108
AM
16584+ inode->i_mode = st->mode;
16585+ inode->i_uid = st->uid;
16586+ inode->i_gid = st->gid;
16587+ inode->i_atime = st->atime;
16588+ inode->i_mtime = st->mtime;
16589+ inode->i_ctime = st->ctime;
1facf9fc 16590+
4a4d8108
AM
16591+ au_cpup_attr_nlink(inode, /*force*/0);
16592+ if (S_ISDIR(inode->i_mode)) {
9dbd164d
AM
16593+ n = inode->i_nlink;
16594+ n -= nlink;
16595+ n += st->nlink;
7eafdf33 16596+ /* 0 can happen */
92d182d2 16597+ set_nlink(inode, n);
4a4d8108 16598+ }
1facf9fc 16599+
4a4d8108
AM
16600+ spin_lock(&inode->i_lock);
16601+ inode->i_blocks = st->blocks;
16602+ i_size_write(inode, st->size);
16603+ spin_unlock(&inode->i_lock);
1facf9fc 16604+}
16605+
4a4d8108
AM
16606+static int aufs_getattr(struct vfsmount *mnt __maybe_unused,
16607+ struct dentry *dentry, struct kstat *st)
1facf9fc 16608+{
4a4d8108
AM
16609+ int err;
16610+ unsigned int mnt_flags;
16611+ aufs_bindex_t bindex;
16612+ unsigned char udba_none, positive;
16613+ struct super_block *sb, *h_sb;
16614+ struct inode *inode;
16615+ struct vfsmount *h_mnt;
16616+ struct dentry *h_dentry;
1facf9fc 16617+
4a4d8108
AM
16618+ sb = dentry->d_sb;
16619+ inode = dentry->d_inode;
7f207e10
AM
16620+ err = si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLM);
16621+ if (unlikely(err))
16622+ goto out;
4a4d8108
AM
16623+ mnt_flags = au_mntflags(sb);
16624+ udba_none = !!au_opt_test(mnt_flags, UDBA_NONE);
1facf9fc 16625+
4a4d8108 16626+ /* support fstat(2) */
027c5e7a 16627+ if (!d_unlinked(dentry) && !udba_none) {
4a4d8108 16628+ unsigned int sigen = au_sigen(sb);
027c5e7a
AM
16629+ err = au_digen_test(dentry, sigen);
16630+ if (!err) {
4a4d8108 16631+ di_read_lock_child(dentry, AuLock_IR);
027c5e7a
AM
16632+ err = au_dbrange_test(dentry);
16633+ if (unlikely(err))
16634+ goto out_unlock;
16635+ } else {
4a4d8108
AM
16636+ AuDebugOn(IS_ROOT(dentry));
16637+ di_write_lock_child(dentry);
027c5e7a
AM
16638+ err = au_dbrange_test(dentry);
16639+ if (!err)
16640+ err = au_reval_for_attr(dentry, sigen);
4a4d8108
AM
16641+ di_downgrade_lock(dentry, AuLock_IR);
16642+ if (unlikely(err))
7f207e10 16643+ goto out_unlock;
4a4d8108
AM
16644+ }
16645+ } else
16646+ di_read_lock_child(dentry, AuLock_IR);
1facf9fc 16647+
4a4d8108
AM
16648+ bindex = au_ibstart(inode);
16649+ h_mnt = au_sbr_mnt(sb, bindex);
16650+ h_sb = h_mnt->mnt_sb;
16651+ if (!au_test_fs_bad_iattr(h_sb) && udba_none)
16652+ goto out_fill; /* success */
1facf9fc 16653+
4a4d8108
AM
16654+ h_dentry = NULL;
16655+ if (au_dbstart(dentry) == bindex)
16656+ h_dentry = dget(au_h_dptr(dentry, bindex));
16657+ else if (au_opt_test(mnt_flags, PLINK) && au_plink_test(inode)) {
16658+ h_dentry = au_plink_lkup(inode, bindex);
16659+ if (IS_ERR(h_dentry))
16660+ goto out_fill; /* pretending success */
16661+ }
16662+ /* illegally overlapped or something */
16663+ if (unlikely(!h_dentry))
16664+ goto out_fill; /* pretending success */
16665+
16666+ positive = !!h_dentry->d_inode;
16667+ if (positive)
16668+ err = vfs_getattr(h_mnt, h_dentry, st);
16669+ dput(h_dentry);
16670+ if (!err) {
16671+ if (positive)
16672+ au_refresh_iattr(inode, st, h_dentry->d_inode->i_nlink);
16673+ goto out_fill; /* success */
1facf9fc 16674+ }
7f207e10
AM
16675+ AuTraceErr(err);
16676+ goto out_unlock;
4a4d8108 16677+
4f0767ce 16678+out_fill:
4a4d8108 16679+ generic_fillattr(inode, st);
7f207e10 16680+out_unlock:
4a4d8108
AM
16681+ di_read_unlock(dentry, AuLock_IR);
16682+ si_read_unlock(sb);
7f207e10
AM
16683+out:
16684+ AuTraceErr(err);
4a4d8108 16685+ return err;
1facf9fc 16686+}
16687+
16688+/* ---------------------------------------------------------------------- */
16689+
4a4d8108
AM
16690+static int h_readlink(struct dentry *dentry, int bindex, char __user *buf,
16691+ int bufsiz)
1facf9fc 16692+{
16693+ int err;
4a4d8108
AM
16694+ struct super_block *sb;
16695+ struct dentry *h_dentry;
1facf9fc 16696+
4a4d8108
AM
16697+ err = -EINVAL;
16698+ h_dentry = au_h_dptr(dentry, bindex);
16699+ if (unlikely(!h_dentry->d_inode->i_op->readlink))
16700+ goto out;
1facf9fc 16701+
4a4d8108
AM
16702+ err = security_inode_readlink(h_dentry);
16703+ if (unlikely(err))
dece6358 16704+ goto out;
1facf9fc 16705+
4a4d8108
AM
16706+ sb = dentry->d_sb;
16707+ if (!au_test_ro(sb, bindex, dentry->d_inode)) {
16708+ vfsub_touch_atime(au_sbr_mnt(sb, bindex), h_dentry);
16709+ fsstack_copy_attr_atime(dentry->d_inode, h_dentry->d_inode);
1facf9fc 16710+ }
4a4d8108 16711+ err = h_dentry->d_inode->i_op->readlink(h_dentry, buf, bufsiz);
1facf9fc 16712+
4f0767ce 16713+out:
4a4d8108
AM
16714+ return err;
16715+}
1facf9fc 16716+
4a4d8108
AM
16717+static int aufs_readlink(struct dentry *dentry, char __user *buf, int bufsiz)
16718+{
16719+ int err;
1facf9fc 16720+
027c5e7a
AM
16721+ err = aufs_read_lock(dentry, AuLock_IR | AuLock_GEN);
16722+ if (unlikely(err))
16723+ goto out;
16724+ err = au_d_hashed_positive(dentry);
16725+ if (!err)
16726+ err = h_readlink(dentry, au_dbstart(dentry), buf, bufsiz);
4a4d8108 16727+ aufs_read_unlock(dentry, AuLock_IR);
1facf9fc 16728+
027c5e7a 16729+out:
4a4d8108
AM
16730+ return err;
16731+}
1facf9fc 16732+
4a4d8108
AM
16733+static void *aufs_follow_link(struct dentry *dentry, struct nameidata *nd)
16734+{
16735+ int err;
4a4d8108 16736+ mm_segment_t old_fs;
b752ccd1
AM
16737+ union {
16738+ char *k;
16739+ char __user *u;
16740+ } buf;
1facf9fc 16741+
4a4d8108 16742+ err = -ENOMEM;
b752ccd1
AM
16743+ buf.k = __getname_gfp(GFP_NOFS);
16744+ if (unlikely(!buf.k))
4a4d8108 16745+ goto out;
1facf9fc 16746+
027c5e7a
AM
16747+ err = aufs_read_lock(dentry, AuLock_IR | AuLock_GEN);
16748+ if (unlikely(err))
16749+ goto out_name;
16750+
16751+ err = au_d_hashed_positive(dentry);
16752+ if (!err) {
16753+ old_fs = get_fs();
16754+ set_fs(KERNEL_DS);
16755+ err = h_readlink(dentry, au_dbstart(dentry), buf.u, PATH_MAX);
16756+ set_fs(old_fs);
16757+ }
4a4d8108 16758+ aufs_read_unlock(dentry, AuLock_IR);
1facf9fc 16759+
4a4d8108 16760+ if (err >= 0) {
b752ccd1 16761+ buf.k[err] = 0;
4a4d8108 16762+ /* will be freed by put_link */
b752ccd1 16763+ nd_set_link(nd, buf.k);
4a4d8108 16764+ return NULL; /* success */
1308ab2a 16765+ }
1facf9fc 16766+
027c5e7a
AM
16767+out_name:
16768+ __putname(buf.k);
4f0767ce 16769+out:
4a4d8108
AM
16770+ path_put(&nd->path);
16771+ AuTraceErr(err);
16772+ return ERR_PTR(err);
16773+}
1facf9fc 16774+
4a4d8108
AM
16775+static void aufs_put_link(struct dentry *dentry __maybe_unused,
16776+ struct nameidata *nd, void *cookie __maybe_unused)
16777+{
16778+ __putname(nd_get_link(nd));
16779+}
1facf9fc 16780+
4a4d8108 16781+/* ---------------------------------------------------------------------- */
1facf9fc 16782+
4a4d8108
AM
16783+static void aufs_truncate_range(struct inode *inode __maybe_unused,
16784+ loff_t start __maybe_unused,
16785+ loff_t end __maybe_unused)
16786+{
16787+ AuUnsupport();
16788+}
1facf9fc 16789+
4a4d8108 16790+/* ---------------------------------------------------------------------- */
1308ab2a 16791+
4a4d8108
AM
16792+struct inode_operations aufs_symlink_iop = {
16793+ .permission = aufs_permission,
16794+ .setattr = aufs_setattr,
16795+ .getattr = aufs_getattr,
16796+ .readlink = aufs_readlink,
16797+ .follow_link = aufs_follow_link,
16798+ .put_link = aufs_put_link
16799+};
16800+
16801+struct inode_operations aufs_dir_iop = {
16802+ .create = aufs_create,
16803+ .lookup = aufs_lookup,
16804+ .link = aufs_link,
16805+ .unlink = aufs_unlink,
16806+ .symlink = aufs_symlink,
16807+ .mkdir = aufs_mkdir,
16808+ .rmdir = aufs_rmdir,
16809+ .mknod = aufs_mknod,
16810+ .rename = aufs_rename,
16811+
16812+ .permission = aufs_permission,
16813+ .setattr = aufs_setattr,
16814+ .getattr = aufs_getattr
16815+};
16816+
16817+struct inode_operations aufs_iop = {
16818+ .permission = aufs_permission,
16819+ .setattr = aufs_setattr,
16820+ .getattr = aufs_getattr,
16821+ .truncate_range = aufs_truncate_range
16822+};
7f207e10
AM
16823diff -urN /usr/share/empty/fs/aufs/i_op_del.c linux/fs/aufs/i_op_del.c
16824--- /usr/share/empty/fs/aufs/i_op_del.c 1970-01-01 01:00:00.000000000 +0100
7ce627cf 16825+++ linux/fs/aufs/i_op_del.c 2012-05-22 09:06:08.867458905 +0200
53392da6 16826@@ -0,0 +1,478 @@
1facf9fc 16827+/*
f6c5ef8b 16828+ * Copyright (C) 2005-2012 Junjiro R. Okajima
1facf9fc 16829+ *
16830+ * This program, aufs is free software; you can redistribute it and/or modify
16831+ * it under the terms of the GNU General Public License as published by
16832+ * the Free Software Foundation; either version 2 of the License, or
16833+ * (at your option) any later version.
dece6358
AM
16834+ *
16835+ * This program is distributed in the hope that it will be useful,
16836+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
16837+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16838+ * GNU General Public License for more details.
16839+ *
16840+ * You should have received a copy of the GNU General Public License
16841+ * along with this program; if not, write to the Free Software
16842+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 16843+ */
16844+
16845+/*
4a4d8108 16846+ * inode operations (del entry)
1308ab2a 16847+ */
dece6358 16848+
1308ab2a 16849+#include "aufs.h"
dece6358 16850+
4a4d8108
AM
16851+/*
16852+ * decide if a new whiteout for @dentry is necessary or not.
16853+ * when it is necessary, prepare the parent dir for the upper branch whose
16854+ * branch index is @bcpup for creation. the actual creation of the whiteout will
16855+ * be done by caller.
16856+ * return value:
16857+ * 0: wh is unnecessary
16858+ * plus: wh is necessary
16859+ * minus: error
16860+ */
16861+int au_wr_dir_need_wh(struct dentry *dentry, int isdir, aufs_bindex_t *bcpup)
1308ab2a 16862+{
4a4d8108
AM
16863+ int need_wh, err;
16864+ aufs_bindex_t bstart;
16865+ struct super_block *sb;
dece6358 16866+
4a4d8108
AM
16867+ sb = dentry->d_sb;
16868+ bstart = au_dbstart(dentry);
16869+ if (*bcpup < 0) {
16870+ *bcpup = bstart;
16871+ if (au_test_ro(sb, bstart, dentry->d_inode)) {
16872+ err = AuWbrCopyup(au_sbi(sb), dentry);
16873+ *bcpup = err;
16874+ if (unlikely(err < 0))
16875+ goto out;
16876+ }
16877+ } else
16878+ AuDebugOn(bstart < *bcpup
16879+ || au_test_ro(sb, *bcpup, dentry->d_inode));
16880+ AuDbg("bcpup %d, bstart %d\n", *bcpup, bstart);
1308ab2a 16881+
4a4d8108
AM
16882+ if (*bcpup != bstart) {
16883+ err = au_cpup_dirs(dentry, *bcpup);
16884+ if (unlikely(err))
16885+ goto out;
16886+ need_wh = 1;
16887+ } else {
027c5e7a 16888+ struct au_dinfo *dinfo, *tmp;
4a4d8108 16889+
027c5e7a
AM
16890+ need_wh = -ENOMEM;
16891+ dinfo = au_di(dentry);
16892+ tmp = au_di_alloc(sb, AuLsc_DI_TMP);
16893+ if (tmp) {
16894+ au_di_cp(tmp, dinfo);
16895+ au_di_swap(tmp, dinfo);
16896+ /* returns the number of positive dentries */
16897+ need_wh = au_lkup_dentry(dentry, bstart + 1, /*type*/0,
16898+ /*nd*/NULL);
16899+ au_di_swap(tmp, dinfo);
16900+ au_rw_write_unlock(&tmp->di_rwsem);
16901+ au_di_free(tmp);
4a4d8108
AM
16902+ }
16903+ }
16904+ AuDbg("need_wh %d\n", need_wh);
16905+ err = need_wh;
16906+
4f0767ce 16907+out:
4a4d8108 16908+ return err;
1facf9fc 16909+}
16910+
4a4d8108
AM
16911+/*
16912+ * simple tests for the del-entry operations.
16913+ * following the checks in vfs, plus the parent-child relationship.
16914+ */
16915+int au_may_del(struct dentry *dentry, aufs_bindex_t bindex,
16916+ struct dentry *h_parent, int isdir)
1facf9fc 16917+{
4a4d8108
AM
16918+ int err;
16919+ umode_t h_mode;
16920+ struct dentry *h_dentry, *h_latest;
1308ab2a 16921+ struct inode *h_inode;
1facf9fc 16922+
4a4d8108
AM
16923+ h_dentry = au_h_dptr(dentry, bindex);
16924+ h_inode = h_dentry->d_inode;
16925+ if (dentry->d_inode) {
16926+ err = -ENOENT;
16927+ if (unlikely(!h_inode || !h_inode->i_nlink))
16928+ goto out;
1facf9fc 16929+
4a4d8108
AM
16930+ h_mode = h_inode->i_mode;
16931+ if (!isdir) {
16932+ err = -EISDIR;
16933+ if (unlikely(S_ISDIR(h_mode)))
16934+ goto out;
16935+ } else if (unlikely(!S_ISDIR(h_mode))) {
16936+ err = -ENOTDIR;
16937+ goto out;
16938+ }
16939+ } else {
16940+ /* rename(2) case */
16941+ err = -EIO;
16942+ if (unlikely(h_inode))
16943+ goto out;
16944+ }
1facf9fc 16945+
4a4d8108
AM
16946+ err = -ENOENT;
16947+ /* expected parent dir is locked */
16948+ if (unlikely(h_parent != h_dentry->d_parent))
16949+ goto out;
16950+ err = 0;
16951+
16952+ /*
16953+ * rmdir a dir may break the consistency on some filesystem.
16954+ * let's try heavy test.
16955+ */
16956+ err = -EACCES;
16957+ if (unlikely(au_test_h_perm(h_parent->d_inode, MAY_EXEC | MAY_WRITE)))
16958+ goto out;
16959+
16960+ h_latest = au_sio_lkup_one(&dentry->d_name, h_parent,
16961+ au_sbr(dentry->d_sb, bindex));
16962+ err = -EIO;
16963+ if (IS_ERR(h_latest))
16964+ goto out;
16965+ if (h_latest == h_dentry)
16966+ err = 0;
16967+ dput(h_latest);
16968+
4f0767ce 16969+out:
4a4d8108 16970+ return err;
1308ab2a 16971+}
1facf9fc 16972+
4a4d8108
AM
16973+/*
16974+ * decide the branch where we operate for @dentry. the branch index will be set
16975+ * @rbcpup. after diciding it, 'pin' it and store the timestamps of the parent
16976+ * dir for reverting.
16977+ * when a new whiteout is necessary, create it.
16978+ */
16979+static struct dentry*
16980+lock_hdir_create_wh(struct dentry *dentry, int isdir, aufs_bindex_t *rbcpup,
16981+ struct au_dtime *dt, struct au_pin *pin)
1308ab2a 16982+{
4a4d8108
AM
16983+ struct dentry *wh_dentry;
16984+ struct super_block *sb;
16985+ struct path h_path;
16986+ int err, need_wh;
16987+ unsigned int udba;
16988+ aufs_bindex_t bcpup;
dece6358 16989+
4a4d8108
AM
16990+ need_wh = au_wr_dir_need_wh(dentry, isdir, rbcpup);
16991+ wh_dentry = ERR_PTR(need_wh);
16992+ if (unlikely(need_wh < 0))
16993+ goto out;
16994+
16995+ sb = dentry->d_sb;
16996+ udba = au_opt_udba(sb);
16997+ bcpup = *rbcpup;
16998+ err = au_pin(pin, dentry, bcpup, udba,
16999+ AuPin_DI_LOCKED | AuPin_MNT_WRITE);
17000+ wh_dentry = ERR_PTR(err);
17001+ if (unlikely(err))
17002+ goto out;
17003+
17004+ h_path.dentry = au_pinned_h_parent(pin);
17005+ if (udba != AuOpt_UDBA_NONE
17006+ && au_dbstart(dentry) == bcpup) {
17007+ err = au_may_del(dentry, bcpup, h_path.dentry, isdir);
17008+ wh_dentry = ERR_PTR(err);
17009+ if (unlikely(err))
17010+ goto out_unpin;
17011+ }
17012+
17013+ h_path.mnt = au_sbr_mnt(sb, bcpup);
17014+ au_dtime_store(dt, au_pinned_parent(pin), &h_path);
17015+ wh_dentry = NULL;
17016+ if (!need_wh)
17017+ goto out; /* success, no need to create whiteout */
17018+
17019+ wh_dentry = au_wh_create(dentry, bcpup, h_path.dentry);
17020+ if (IS_ERR(wh_dentry))
17021+ goto out_unpin;
17022+
17023+ /* returns with the parent is locked and wh_dentry is dget-ed */
17024+ goto out; /* success */
17025+
4f0767ce 17026+out_unpin:
4a4d8108 17027+ au_unpin(pin);
4f0767ce 17028+out:
4a4d8108 17029+ return wh_dentry;
1facf9fc 17030+}
17031+
4a4d8108
AM
17032+/*
17033+ * when removing a dir, rename it to a unique temporary whiteout-ed name first
17034+ * in order to be revertible and save time for removing many child whiteouts
17035+ * under the dir.
17036+ * returns 1 when there are too many child whiteout and caller should remove
17037+ * them asynchronously. returns 0 when the number of children is enough small to
17038+ * remove now or the branch fs is a remote fs.
17039+ * otherwise return an error.
17040+ */
17041+static int renwh_and_rmdir(struct dentry *dentry, aufs_bindex_t bindex,
17042+ struct au_nhash *whlist, struct inode *dir)
1facf9fc 17043+{
4a4d8108
AM
17044+ int rmdir_later, err, dirwh;
17045+ struct dentry *h_dentry;
17046+ struct super_block *sb;
17047+
17048+ sb = dentry->d_sb;
17049+ SiMustAnyLock(sb);
17050+ h_dentry = au_h_dptr(dentry, bindex);
17051+ err = au_whtmp_ren(h_dentry, au_sbr(sb, bindex));
17052+ if (unlikely(err))
17053+ goto out;
17054+
17055+ /* stop monitoring */
17056+ au_hn_free(au_hi(dentry->d_inode, bindex));
17057+
17058+ if (!au_test_fs_remote(h_dentry->d_sb)) {
17059+ dirwh = au_sbi(sb)->si_dirwh;
17060+ rmdir_later = (dirwh <= 1);
17061+ if (!rmdir_later)
17062+ rmdir_later = au_nhash_test_longer_wh(whlist, bindex,
17063+ dirwh);
17064+ if (rmdir_later)
17065+ return rmdir_later;
17066+ }
1facf9fc 17067+
4a4d8108
AM
17068+ err = au_whtmp_rmdir(dir, bindex, h_dentry, whlist);
17069+ if (unlikely(err)) {
17070+ AuIOErr("rmdir %.*s, b%d failed, %d. ignored\n",
17071+ AuDLNPair(h_dentry), bindex, err);
17072+ err = 0;
17073+ }
dece6358 17074+
4f0767ce 17075+out:
4a4d8108
AM
17076+ AuTraceErr(err);
17077+ return err;
17078+}
1308ab2a 17079+
4a4d8108
AM
17080+/*
17081+ * final procedure for deleting a entry.
17082+ * maintain dentry and iattr.
17083+ */
17084+static void epilog(struct inode *dir, struct dentry *dentry,
17085+ aufs_bindex_t bindex)
17086+{
17087+ struct inode *inode;
1308ab2a 17088+
4a4d8108
AM
17089+ inode = dentry->d_inode;
17090+ d_drop(dentry);
17091+ inode->i_ctime = dir->i_ctime;
1308ab2a 17092+
4a4d8108
AM
17093+ if (au_ibstart(dir) == bindex)
17094+ au_cpup_attr_timesizes(dir);
17095+ dir->i_version++;
1facf9fc 17096+}
17097+
4a4d8108
AM
17098+/*
17099+ * when an error happened, remove the created whiteout and revert everything.
17100+ */
7f207e10
AM
17101+static int do_revert(int err, struct inode *dir, aufs_bindex_t bindex,
17102+ aufs_bindex_t bwh, struct dentry *wh_dentry,
17103+ struct dentry *dentry, struct au_dtime *dt)
1facf9fc 17104+{
4a4d8108
AM
17105+ int rerr;
17106+ struct path h_path = {
17107+ .dentry = wh_dentry,
7f207e10 17108+ .mnt = au_sbr_mnt(dir->i_sb, bindex)
4a4d8108 17109+ };
dece6358 17110+
7f207e10 17111+ rerr = au_wh_unlink_dentry(au_h_iptr(dir, bindex), &h_path, dentry);
4a4d8108
AM
17112+ if (!rerr) {
17113+ au_set_dbwh(dentry, bwh);
17114+ au_dtime_revert(dt);
17115+ return 0;
17116+ }
dece6358 17117+
4a4d8108
AM
17118+ AuIOErr("%.*s reverting whiteout failed(%d, %d)\n",
17119+ AuDLNPair(dentry), err, rerr);
17120+ return -EIO;
1facf9fc 17121+}
17122+
4a4d8108 17123+/* ---------------------------------------------------------------------- */
1facf9fc 17124+
4a4d8108 17125+int aufs_unlink(struct inode *dir, struct dentry *dentry)
1308ab2a 17126+{
4a4d8108
AM
17127+ int err;
17128+ aufs_bindex_t bwh, bindex, bstart;
17129+ struct au_dtime dt;
17130+ struct au_pin pin;
17131+ struct path h_path;
17132+ struct inode *inode, *h_dir;
17133+ struct dentry *parent, *wh_dentry;
1facf9fc 17134+
4a4d8108 17135+ IMustLock(dir);
027c5e7a
AM
17136+
17137+ err = aufs_read_lock(dentry, AuLock_DW | AuLock_GEN);
17138+ if (unlikely(err))
17139+ goto out;
17140+ err = au_d_hashed_positive(dentry);
17141+ if (unlikely(err))
17142+ goto out_unlock;
4a4d8108 17143+ inode = dentry->d_inode;
4a4d8108 17144+ IMustLock(inode);
027c5e7a
AM
17145+ err = -EISDIR;
17146+ if (unlikely(S_ISDIR(inode->i_mode)))
17147+ goto out_unlock; /* possible? */
1facf9fc 17148+
4a4d8108
AM
17149+ bstart = au_dbstart(dentry);
17150+ bwh = au_dbwh(dentry);
17151+ bindex = -1;
027c5e7a
AM
17152+ parent = dentry->d_parent; /* dir inode is locked */
17153+ di_write_lock_parent(parent);
4a4d8108
AM
17154+ wh_dentry = lock_hdir_create_wh(dentry, /*isdir*/0, &bindex, &dt, &pin);
17155+ err = PTR_ERR(wh_dentry);
17156+ if (IS_ERR(wh_dentry))
027c5e7a 17157+ goto out_parent;
1facf9fc 17158+
4a4d8108
AM
17159+ h_path.mnt = au_sbr_mnt(dentry->d_sb, bstart);
17160+ h_path.dentry = au_h_dptr(dentry, bstart);
17161+ dget(h_path.dentry);
17162+ if (bindex == bstart) {
17163+ h_dir = au_pinned_h_dir(&pin);
17164+ err = vfsub_unlink(h_dir, &h_path, /*force*/0);
17165+ } else {
17166+ /* dir inode is locked */
17167+ h_dir = wh_dentry->d_parent->d_inode;
17168+ IMustLock(h_dir);
17169+ err = 0;
17170+ }
dece6358 17171+
4a4d8108 17172+ if (!err) {
7f207e10 17173+ vfsub_drop_nlink(inode);
4a4d8108
AM
17174+ epilog(dir, dentry, bindex);
17175+
17176+ /* update target timestamps */
17177+ if (bindex == bstart) {
17178+ vfsub_update_h_iattr(&h_path, /*did*/NULL); /*ignore*/
17179+ inode->i_ctime = h_path.dentry->d_inode->i_ctime;
17180+ } else
17181+ /* todo: this timestamp may be reverted later */
17182+ inode->i_ctime = h_dir->i_ctime;
027c5e7a 17183+ goto out_unpin; /* success */
1facf9fc 17184+ }
17185+
4a4d8108
AM
17186+ /* revert */
17187+ if (wh_dentry) {
17188+ int rerr;
17189+
7f207e10 17190+ rerr = do_revert(err, dir, bindex, bwh, wh_dentry, dentry, &dt);
4a4d8108
AM
17191+ if (rerr)
17192+ err = rerr;
dece6358 17193+ }
1facf9fc 17194+
027c5e7a 17195+out_unpin:
4a4d8108
AM
17196+ au_unpin(&pin);
17197+ dput(wh_dentry);
17198+ dput(h_path.dentry);
027c5e7a 17199+out_parent:
4a4d8108 17200+ di_write_unlock(parent);
027c5e7a 17201+out_unlock:
4a4d8108 17202+ aufs_read_unlock(dentry, AuLock_DW);
027c5e7a 17203+out:
4a4d8108 17204+ return err;
dece6358
AM
17205+}
17206+
4a4d8108 17207+int aufs_rmdir(struct inode *dir, struct dentry *dentry)
1308ab2a 17208+{
4a4d8108
AM
17209+ int err, rmdir_later;
17210+ aufs_bindex_t bwh, bindex, bstart;
17211+ struct au_dtime dt;
17212+ struct au_pin pin;
17213+ struct inode *inode;
17214+ struct dentry *parent, *wh_dentry, *h_dentry;
17215+ struct au_whtmp_rmdir *args;
1facf9fc 17216+
4a4d8108 17217+ IMustLock(dir);
027c5e7a
AM
17218+
17219+ err = aufs_read_lock(dentry, AuLock_DW | AuLock_FLUSH | AuLock_GEN);
17220+ if (unlikely(err))
4a4d8108 17221+ goto out;
53392da6
AM
17222+ err = au_alive_dir(dentry);
17223+ if (unlikely(err))
027c5e7a 17224+ goto out_unlock;
53392da6 17225+ inode = dentry->d_inode;
4a4d8108 17226+ IMustLock(inode);
027c5e7a
AM
17227+ err = -ENOTDIR;
17228+ if (unlikely(!S_ISDIR(inode->i_mode)))
17229+ goto out_unlock; /* possible? */
dece6358 17230+
4a4d8108
AM
17231+ err = -ENOMEM;
17232+ args = au_whtmp_rmdir_alloc(dir->i_sb, GFP_NOFS);
17233+ if (unlikely(!args))
17234+ goto out_unlock;
dece6358 17235+
4a4d8108
AM
17236+ parent = dentry->d_parent; /* dir inode is locked */
17237+ di_write_lock_parent(parent);
17238+ err = au_test_empty(dentry, &args->whlist);
17239+ if (unlikely(err))
027c5e7a 17240+ goto out_parent;
1facf9fc 17241+
4a4d8108
AM
17242+ bstart = au_dbstart(dentry);
17243+ bwh = au_dbwh(dentry);
17244+ bindex = -1;
17245+ wh_dentry = lock_hdir_create_wh(dentry, /*isdir*/1, &bindex, &dt, &pin);
17246+ err = PTR_ERR(wh_dentry);
17247+ if (IS_ERR(wh_dentry))
027c5e7a 17248+ goto out_parent;
1facf9fc 17249+
4a4d8108
AM
17250+ h_dentry = au_h_dptr(dentry, bstart);
17251+ dget(h_dentry);
17252+ rmdir_later = 0;
17253+ if (bindex == bstart) {
17254+ err = renwh_and_rmdir(dentry, bstart, &args->whlist, dir);
17255+ if (err > 0) {
17256+ rmdir_later = err;
17257+ err = 0;
17258+ }
17259+ } else {
17260+ /* stop monitoring */
17261+ au_hn_free(au_hi(inode, bstart));
17262+
17263+ /* dir inode is locked */
17264+ IMustLock(wh_dentry->d_parent->d_inode);
1facf9fc 17265+ err = 0;
17266+ }
17267+
4a4d8108 17268+ if (!err) {
027c5e7a 17269+ vfsub_dead_dir(inode);
4a4d8108
AM
17270+ au_set_dbdiropq(dentry, -1);
17271+ epilog(dir, dentry, bindex);
1308ab2a 17272+
4a4d8108
AM
17273+ if (rmdir_later) {
17274+ au_whtmp_kick_rmdir(dir, bstart, h_dentry, args);
17275+ args = NULL;
17276+ }
1308ab2a 17277+
4a4d8108 17278+ goto out_unpin; /* success */
1facf9fc 17279+ }
17280+
4a4d8108
AM
17281+ /* revert */
17282+ AuLabel(revert);
17283+ if (wh_dentry) {
17284+ int rerr;
1308ab2a 17285+
7f207e10 17286+ rerr = do_revert(err, dir, bindex, bwh, wh_dentry, dentry, &dt);
4a4d8108
AM
17287+ if (rerr)
17288+ err = rerr;
1facf9fc 17289+ }
17290+
4f0767ce 17291+out_unpin:
4a4d8108
AM
17292+ au_unpin(&pin);
17293+ dput(wh_dentry);
17294+ dput(h_dentry);
027c5e7a 17295+out_parent:
4a4d8108
AM
17296+ di_write_unlock(parent);
17297+ if (args)
17298+ au_whtmp_rmdir_free(args);
4f0767ce 17299+out_unlock:
4a4d8108 17300+ aufs_read_unlock(dentry, AuLock_DW);
4f0767ce 17301+out:
4a4d8108
AM
17302+ AuTraceErr(err);
17303+ return err;
dece6358 17304+}
7f207e10
AM
17305diff -urN /usr/share/empty/fs/aufs/i_op_ren.c linux/fs/aufs/i_op_ren.c
17306--- /usr/share/empty/fs/aufs/i_op_ren.c 1970-01-01 01:00:00.000000000 +0100
7ce627cf 17307+++ linux/fs/aufs/i_op_ren.c 2012-05-22 09:06:08.867458905 +0200
7eafdf33 17308@@ -0,0 +1,1026 @@
1facf9fc 17309+/*
f6c5ef8b 17310+ * Copyright (C) 2005-2012 Junjiro R. Okajima
1facf9fc 17311+ *
17312+ * This program, aufs is free software; you can redistribute it and/or modify
17313+ * it under the terms of the GNU General Public License as published by
17314+ * the Free Software Foundation; either version 2 of the License, or
17315+ * (at your option) any later version.
dece6358
AM
17316+ *
17317+ * This program is distributed in the hope that it will be useful,
17318+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
17319+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17320+ * GNU General Public License for more details.
17321+ *
17322+ * You should have received a copy of the GNU General Public License
17323+ * along with this program; if not, write to the Free Software
17324+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 17325+ */
17326+
17327+/*
4a4d8108
AM
17328+ * inode operation (rename entry)
17329+ * todo: this is crazy monster
1facf9fc 17330+ */
17331+
17332+#include "aufs.h"
17333+
4a4d8108
AM
17334+enum { AuSRC, AuDST, AuSrcDst };
17335+enum { AuPARENT, AuCHILD, AuParentChild };
1facf9fc 17336+
4a4d8108
AM
17337+#define AuRen_ISDIR 1
17338+#define AuRen_ISSAMEDIR (1 << 1)
17339+#define AuRen_WHSRC (1 << 2)
17340+#define AuRen_WHDST (1 << 3)
17341+#define AuRen_MNT_WRITE (1 << 4)
17342+#define AuRen_DT_DSTDIR (1 << 5)
17343+#define AuRen_DIROPQ (1 << 6)
17344+#define AuRen_CPUP (1 << 7)
17345+#define au_ftest_ren(flags, name) ((flags) & AuRen_##name)
7f207e10
AM
17346+#define au_fset_ren(flags, name) \
17347+ do { (flags) |= AuRen_##name; } while (0)
17348+#define au_fclr_ren(flags, name) \
17349+ do { (flags) &= ~AuRen_##name; } while (0)
1facf9fc 17350+
4a4d8108
AM
17351+struct au_ren_args {
17352+ struct {
17353+ struct dentry *dentry, *h_dentry, *parent, *h_parent,
17354+ *wh_dentry;
17355+ struct inode *dir, *inode;
17356+ struct au_hinode *hdir;
17357+ struct au_dtime dt[AuParentChild];
17358+ aufs_bindex_t bstart;
17359+ } sd[AuSrcDst];
1facf9fc 17360+
4a4d8108
AM
17361+#define src_dentry sd[AuSRC].dentry
17362+#define src_dir sd[AuSRC].dir
17363+#define src_inode sd[AuSRC].inode
17364+#define src_h_dentry sd[AuSRC].h_dentry
17365+#define src_parent sd[AuSRC].parent
17366+#define src_h_parent sd[AuSRC].h_parent
17367+#define src_wh_dentry sd[AuSRC].wh_dentry
17368+#define src_hdir sd[AuSRC].hdir
17369+#define src_h_dir sd[AuSRC].hdir->hi_inode
17370+#define src_dt sd[AuSRC].dt
17371+#define src_bstart sd[AuSRC].bstart
1facf9fc 17372+
4a4d8108
AM
17373+#define dst_dentry sd[AuDST].dentry
17374+#define dst_dir sd[AuDST].dir
17375+#define dst_inode sd[AuDST].inode
17376+#define dst_h_dentry sd[AuDST].h_dentry
17377+#define dst_parent sd[AuDST].parent
17378+#define dst_h_parent sd[AuDST].h_parent
17379+#define dst_wh_dentry sd[AuDST].wh_dentry
17380+#define dst_hdir sd[AuDST].hdir
17381+#define dst_h_dir sd[AuDST].hdir->hi_inode
17382+#define dst_dt sd[AuDST].dt
17383+#define dst_bstart sd[AuDST].bstart
17384+
17385+ struct dentry *h_trap;
17386+ struct au_branch *br;
17387+ struct au_hinode *src_hinode;
17388+ struct path h_path;
17389+ struct au_nhash whlist;
027c5e7a 17390+ aufs_bindex_t btgt, src_bwh, src_bdiropq;
1facf9fc 17391+
1308ab2a 17392+ unsigned int flags;
1facf9fc 17393+
4a4d8108
AM
17394+ struct au_whtmp_rmdir *thargs;
17395+ struct dentry *h_dst;
17396+};
1308ab2a 17397+
4a4d8108 17398+/* ---------------------------------------------------------------------- */
1308ab2a 17399+
4a4d8108
AM
17400+/*
17401+ * functions for reverting.
17402+ * when an error happened in a single rename systemcall, we should revert
17403+ * everything as if nothing happend.
17404+ * we don't need to revert the copied-up/down the parent dir since they are
17405+ * harmless.
17406+ */
1facf9fc 17407+
4a4d8108
AM
17408+#define RevertFailure(fmt, ...) do { \
17409+ AuIOErr("revert failure: " fmt " (%d, %d)\n", \
17410+ ##__VA_ARGS__, err, rerr); \
17411+ err = -EIO; \
17412+} while (0)
1facf9fc 17413+
4a4d8108 17414+static void au_ren_rev_diropq(int err, struct au_ren_args *a)
1facf9fc 17415+{
4a4d8108 17416+ int rerr;
1facf9fc 17417+
4a4d8108
AM
17418+ au_hn_imtx_lock_nested(a->src_hinode, AuLsc_I_CHILD);
17419+ rerr = au_diropq_remove(a->src_dentry, a->btgt);
17420+ au_hn_imtx_unlock(a->src_hinode);
027c5e7a 17421+ au_set_dbdiropq(a->src_dentry, a->src_bdiropq);
4a4d8108
AM
17422+ if (rerr)
17423+ RevertFailure("remove diropq %.*s", AuDLNPair(a->src_dentry));
17424+}
1facf9fc 17425+
4a4d8108
AM
17426+static void au_ren_rev_rename(int err, struct au_ren_args *a)
17427+{
17428+ int rerr;
1facf9fc 17429+
4a4d8108
AM
17430+ a->h_path.dentry = au_lkup_one(&a->src_dentry->d_name, a->src_h_parent,
17431+ a->br, /*nd*/NULL);
17432+ rerr = PTR_ERR(a->h_path.dentry);
17433+ if (IS_ERR(a->h_path.dentry)) {
17434+ RevertFailure("au_lkup_one %.*s", AuDLNPair(a->src_dentry));
17435+ return;
1facf9fc 17436+ }
17437+
4a4d8108
AM
17438+ rerr = vfsub_rename(a->dst_h_dir,
17439+ au_h_dptr(a->src_dentry, a->btgt),
17440+ a->src_h_dir, &a->h_path);
17441+ d_drop(a->h_path.dentry);
17442+ dput(a->h_path.dentry);
17443+ /* au_set_h_dptr(a->src_dentry, a->btgt, NULL); */
17444+ if (rerr)
17445+ RevertFailure("rename %.*s", AuDLNPair(a->src_dentry));
1facf9fc 17446+}
17447+
4a4d8108 17448+static void au_ren_rev_cpup(int err, struct au_ren_args *a)
1facf9fc 17449+{
4a4d8108 17450+ int rerr;
1facf9fc 17451+
4a4d8108
AM
17452+ a->h_path.dentry = a->dst_h_dentry;
17453+ rerr = vfsub_unlink(a->dst_h_dir, &a->h_path, /*force*/0);
17454+ au_set_h_dptr(a->src_dentry, a->btgt, NULL);
17455+ au_set_dbstart(a->src_dentry, a->src_bstart);
17456+ if (rerr)
17457+ RevertFailure("unlink %.*s", AuDLNPair(a->dst_h_dentry));
1facf9fc 17458+}
17459+
4a4d8108 17460+static void au_ren_rev_whtmp(int err, struct au_ren_args *a)
1facf9fc 17461+{
4a4d8108 17462+ int rerr;
dece6358 17463+
4a4d8108
AM
17464+ a->h_path.dentry = au_lkup_one(&a->dst_dentry->d_name, a->dst_h_parent,
17465+ a->br, /*nd*/NULL);
17466+ rerr = PTR_ERR(a->h_path.dentry);
17467+ if (IS_ERR(a->h_path.dentry)) {
17468+ RevertFailure("lookup %.*s", AuDLNPair(a->dst_dentry));
17469+ return;
17470+ }
17471+ if (a->h_path.dentry->d_inode) {
17472+ d_drop(a->h_path.dentry);
17473+ dput(a->h_path.dentry);
17474+ return;
dece6358
AM
17475+ }
17476+
4a4d8108
AM
17477+ rerr = vfsub_rename(a->dst_h_dir, a->h_dst, a->dst_h_dir, &a->h_path);
17478+ d_drop(a->h_path.dentry);
17479+ dput(a->h_path.dentry);
17480+ if (!rerr)
17481+ au_set_h_dptr(a->dst_dentry, a->btgt, dget(a->h_dst));
17482+ else
17483+ RevertFailure("rename %.*s", AuDLNPair(a->h_dst));
17484+}
1308ab2a 17485+
4a4d8108
AM
17486+static void au_ren_rev_whsrc(int err, struct au_ren_args *a)
17487+{
17488+ int rerr;
1308ab2a 17489+
4a4d8108
AM
17490+ a->h_path.dentry = a->src_wh_dentry;
17491+ rerr = au_wh_unlink_dentry(a->src_h_dir, &a->h_path, a->src_dentry);
027c5e7a 17492+ au_set_dbwh(a->src_dentry, a->src_bwh);
4a4d8108
AM
17493+ if (rerr)
17494+ RevertFailure("unlink %.*s", AuDLNPair(a->src_wh_dentry));
17495+}
4a4d8108 17496+#undef RevertFailure
1facf9fc 17497+
1308ab2a 17498+/* ---------------------------------------------------------------------- */
17499+
4a4d8108
AM
17500+/*
17501+ * when we have to copyup the renaming entry, do it with the rename-target name
17502+ * in order to minimize the cost (the later actual rename is unnecessary).
17503+ * otherwise rename it on the target branch.
17504+ */
17505+static int au_ren_or_cpup(struct au_ren_args *a)
1facf9fc 17506+{
dece6358 17507+ int err;
4a4d8108 17508+ struct dentry *d;
1facf9fc 17509+
4a4d8108
AM
17510+ d = a->src_dentry;
17511+ if (au_dbstart(d) == a->btgt) {
17512+ a->h_path.dentry = a->dst_h_dentry;
17513+ if (au_ftest_ren(a->flags, DIROPQ)
17514+ && au_dbdiropq(d) == a->btgt)
17515+ au_fclr_ren(a->flags, DIROPQ);
17516+ AuDebugOn(au_dbstart(d) != a->btgt);
17517+ err = vfsub_rename(a->src_h_dir, au_h_dptr(d, a->btgt),
17518+ a->dst_h_dir, &a->h_path);
17519+ } else {
17520+ struct mutex *h_mtx = &a->src_h_dentry->d_inode->i_mutex;
17521+ struct file *h_file;
1308ab2a 17522+
4a4d8108
AM
17523+ au_fset_ren(a->flags, CPUP);
17524+ mutex_lock_nested(h_mtx, AuLsc_I_CHILD);
17525+ au_set_dbstart(d, a->btgt);
17526+ au_set_h_dptr(d, a->btgt, dget(a->dst_h_dentry));
17527+ h_file = au_h_open_pre(d, a->src_bstart);
17528+ if (IS_ERR(h_file)) {
17529+ err = PTR_ERR(h_file);
17530+ h_file = NULL;
17531+ } else
17532+ err = au_sio_cpup_single(d, a->btgt, a->src_bstart, -1,
17533+ !AuCpup_DTIME, a->dst_parent);
17534+ mutex_unlock(h_mtx);
17535+ au_h_open_post(d, a->src_bstart, h_file);
17536+ if (!err) {
17537+ d = a->dst_dentry;
17538+ au_set_h_dptr(d, a->btgt, NULL);
17539+ au_update_dbstart(d);
17540+ } else {
17541+ au_set_h_dptr(d, a->btgt, NULL);
17542+ au_set_dbstart(d, a->src_bstart);
17543+ }
1308ab2a 17544+ }
027c5e7a
AM
17545+ if (!err && a->h_dst)
17546+ /* it will be set to dinfo later */
17547+ dget(a->h_dst);
1facf9fc 17548+
dece6358
AM
17549+ return err;
17550+}
1facf9fc 17551+
4a4d8108
AM
17552+/* cf. aufs_rmdir() */
17553+static int au_ren_del_whtmp(struct au_ren_args *a)
dece6358 17554+{
4a4d8108
AM
17555+ int err;
17556+ struct inode *dir;
1facf9fc 17557+
4a4d8108
AM
17558+ dir = a->dst_dir;
17559+ SiMustAnyLock(dir->i_sb);
17560+ if (!au_nhash_test_longer_wh(&a->whlist, a->btgt,
17561+ au_sbi(dir->i_sb)->si_dirwh)
17562+ || au_test_fs_remote(a->h_dst->d_sb)) {
17563+ err = au_whtmp_rmdir(dir, a->btgt, a->h_dst, &a->whlist);
17564+ if (unlikely(err))
17565+ pr_warning("failed removing whtmp dir %.*s (%d), "
17566+ "ignored.\n", AuDLNPair(a->h_dst), err);
17567+ } else {
17568+ au_nhash_wh_free(&a->thargs->whlist);
17569+ a->thargs->whlist = a->whlist;
17570+ a->whlist.nh_num = 0;
17571+ au_whtmp_kick_rmdir(dir, a->btgt, a->h_dst, a->thargs);
17572+ dput(a->h_dst);
17573+ a->thargs = NULL;
17574+ }
17575+
17576+ return 0;
1308ab2a 17577+}
1facf9fc 17578+
4a4d8108
AM
17579+/* make it 'opaque' dir. */
17580+static int au_ren_diropq(struct au_ren_args *a)
17581+{
17582+ int err;
17583+ struct dentry *diropq;
1facf9fc 17584+
4a4d8108 17585+ err = 0;
027c5e7a 17586+ a->src_bdiropq = au_dbdiropq(a->src_dentry);
4a4d8108
AM
17587+ a->src_hinode = au_hi(a->src_inode, a->btgt);
17588+ au_hn_imtx_lock_nested(a->src_hinode, AuLsc_I_CHILD);
17589+ diropq = au_diropq_create(a->src_dentry, a->btgt);
17590+ au_hn_imtx_unlock(a->src_hinode);
17591+ if (IS_ERR(diropq))
17592+ err = PTR_ERR(diropq);
17593+ dput(diropq);
1facf9fc 17594+
4a4d8108
AM
17595+ return err;
17596+}
1facf9fc 17597+
4a4d8108
AM
17598+static int do_rename(struct au_ren_args *a)
17599+{
17600+ int err;
17601+ struct dentry *d, *h_d;
1facf9fc 17602+
4a4d8108
AM
17603+ /* prepare workqueue args for asynchronous rmdir */
17604+ h_d = a->dst_h_dentry;
17605+ if (au_ftest_ren(a->flags, ISDIR) && h_d->d_inode) {
17606+ err = -ENOMEM;
17607+ a->thargs = au_whtmp_rmdir_alloc(a->src_dentry->d_sb, GFP_NOFS);
17608+ if (unlikely(!a->thargs))
17609+ goto out;
17610+ a->h_dst = dget(h_d);
17611+ }
1facf9fc 17612+
4a4d8108
AM
17613+ /* create whiteout for src_dentry */
17614+ if (au_ftest_ren(a->flags, WHSRC)) {
027c5e7a
AM
17615+ a->src_bwh = au_dbwh(a->src_dentry);
17616+ AuDebugOn(a->src_bwh >= 0);
4a4d8108
AM
17617+ a->src_wh_dentry
17618+ = au_wh_create(a->src_dentry, a->btgt, a->src_h_parent);
17619+ err = PTR_ERR(a->src_wh_dentry);
17620+ if (IS_ERR(a->src_wh_dentry))
17621+ goto out_thargs;
17622+ }
1facf9fc 17623+
4a4d8108
AM
17624+ /* lookup whiteout for dentry */
17625+ if (au_ftest_ren(a->flags, WHDST)) {
17626+ h_d = au_wh_lkup(a->dst_h_parent, &a->dst_dentry->d_name,
17627+ a->br);
17628+ err = PTR_ERR(h_d);
17629+ if (IS_ERR(h_d))
17630+ goto out_whsrc;
17631+ if (!h_d->d_inode)
17632+ dput(h_d);
17633+ else
17634+ a->dst_wh_dentry = h_d;
17635+ }
1facf9fc 17636+
4a4d8108
AM
17637+ /* rename dentry to tmpwh */
17638+ if (a->thargs) {
17639+ err = au_whtmp_ren(a->dst_h_dentry, a->br);
17640+ if (unlikely(err))
17641+ goto out_whdst;
dece6358 17642+
4a4d8108
AM
17643+ d = a->dst_dentry;
17644+ au_set_h_dptr(d, a->btgt, NULL);
17645+ err = au_lkup_neg(d, a->btgt);
17646+ if (unlikely(err))
17647+ goto out_whtmp;
17648+ a->dst_h_dentry = au_h_dptr(d, a->btgt);
17649+ }
1facf9fc 17650+
4a4d8108
AM
17651+ /* cpup src */
17652+ if (a->dst_h_dentry->d_inode && a->src_bstart != a->btgt) {
17653+ struct mutex *h_mtx = &a->src_h_dentry->d_inode->i_mutex;
17654+ struct file *h_file;
1facf9fc 17655+
4a4d8108
AM
17656+ mutex_lock_nested(h_mtx, AuLsc_I_CHILD);
17657+ AuDebugOn(au_dbstart(a->src_dentry) != a->src_bstart);
17658+ h_file = au_h_open_pre(a->src_dentry, a->src_bstart);
17659+ if (IS_ERR(h_file)) {
17660+ err = PTR_ERR(h_file);
17661+ h_file = NULL;
17662+ } else
17663+ err = au_sio_cpup_simple(a->src_dentry, a->btgt, -1,
17664+ !AuCpup_DTIME);
17665+ mutex_unlock(h_mtx);
17666+ au_h_open_post(a->src_dentry, a->src_bstart, h_file);
17667+ if (unlikely(err))
17668+ goto out_whtmp;
17669+ }
1facf9fc 17670+
4a4d8108
AM
17671+ /* rename by vfs_rename or cpup */
17672+ d = a->dst_dentry;
17673+ if (au_ftest_ren(a->flags, ISDIR)
17674+ && (a->dst_wh_dentry
17675+ || au_dbdiropq(d) == a->btgt
17676+ /* hide the lower to keep xino */
17677+ || a->btgt < au_dbend(d)
17678+ || au_opt_test(au_mntflags(d->d_sb), ALWAYS_DIROPQ)))
17679+ au_fset_ren(a->flags, DIROPQ);
17680+ err = au_ren_or_cpup(a);
17681+ if (unlikely(err))
17682+ /* leave the copied-up one */
17683+ goto out_whtmp;
1308ab2a 17684+
4a4d8108
AM
17685+ /* make dir opaque */
17686+ if (au_ftest_ren(a->flags, DIROPQ)) {
17687+ err = au_ren_diropq(a);
17688+ if (unlikely(err))
17689+ goto out_rename;
17690+ }
1308ab2a 17691+
4a4d8108
AM
17692+ /* update target timestamps */
17693+ AuDebugOn(au_dbstart(a->src_dentry) != a->btgt);
17694+ a->h_path.dentry = au_h_dptr(a->src_dentry, a->btgt);
17695+ vfsub_update_h_iattr(&a->h_path, /*did*/NULL); /*ignore*/
17696+ a->src_inode->i_ctime = a->h_path.dentry->d_inode->i_ctime;
1facf9fc 17697+
4a4d8108
AM
17698+ /* remove whiteout for dentry */
17699+ if (a->dst_wh_dentry) {
17700+ a->h_path.dentry = a->dst_wh_dentry;
17701+ err = au_wh_unlink_dentry(a->dst_h_dir, &a->h_path,
17702+ a->dst_dentry);
17703+ if (unlikely(err))
17704+ goto out_diropq;
17705+ }
1facf9fc 17706+
4a4d8108
AM
17707+ /* remove whtmp */
17708+ if (a->thargs)
17709+ au_ren_del_whtmp(a); /* ignore this error */
1308ab2a 17710+
4a4d8108
AM
17711+ err = 0;
17712+ goto out_success;
17713+
4f0767ce 17714+out_diropq:
4a4d8108
AM
17715+ if (au_ftest_ren(a->flags, DIROPQ))
17716+ au_ren_rev_diropq(err, a);
4f0767ce 17717+out_rename:
4a4d8108
AM
17718+ if (!au_ftest_ren(a->flags, CPUP))
17719+ au_ren_rev_rename(err, a);
17720+ else
17721+ au_ren_rev_cpup(err, a);
027c5e7a 17722+ dput(a->h_dst);
4f0767ce 17723+out_whtmp:
4a4d8108
AM
17724+ if (a->thargs)
17725+ au_ren_rev_whtmp(err, a);
4f0767ce 17726+out_whdst:
4a4d8108
AM
17727+ dput(a->dst_wh_dentry);
17728+ a->dst_wh_dentry = NULL;
4f0767ce 17729+out_whsrc:
4a4d8108
AM
17730+ if (a->src_wh_dentry)
17731+ au_ren_rev_whsrc(err, a);
4f0767ce 17732+out_success:
4a4d8108
AM
17733+ dput(a->src_wh_dentry);
17734+ dput(a->dst_wh_dentry);
4f0767ce 17735+out_thargs:
4a4d8108
AM
17736+ if (a->thargs) {
17737+ dput(a->h_dst);
17738+ au_whtmp_rmdir_free(a->thargs);
17739+ a->thargs = NULL;
17740+ }
4f0767ce 17741+out:
4a4d8108 17742+ return err;
dece6358 17743+}
1facf9fc 17744+
1308ab2a 17745+/* ---------------------------------------------------------------------- */
1facf9fc 17746+
4a4d8108
AM
17747+/*
17748+ * test if @dentry dir can be rename destination or not.
17749+ * success means, it is a logically empty dir.
17750+ */
17751+static int may_rename_dstdir(struct dentry *dentry, struct au_nhash *whlist)
1308ab2a 17752+{
4a4d8108 17753+ return au_test_empty(dentry, whlist);
1308ab2a 17754+}
1facf9fc 17755+
4a4d8108
AM
17756+/*
17757+ * test if @dentry dir can be rename source or not.
17758+ * if it can, return 0 and @children is filled.
17759+ * success means,
17760+ * - it is a logically empty dir.
17761+ * - or, it exists on writable branch and has no children including whiteouts
17762+ * on the lower branch.
17763+ */
17764+static int may_rename_srcdir(struct dentry *dentry, aufs_bindex_t btgt)
17765+{
17766+ int err;
17767+ unsigned int rdhash;
17768+ aufs_bindex_t bstart;
1facf9fc 17769+
4a4d8108
AM
17770+ bstart = au_dbstart(dentry);
17771+ if (bstart != btgt) {
17772+ struct au_nhash whlist;
dece6358 17773+
4a4d8108
AM
17774+ SiMustAnyLock(dentry->d_sb);
17775+ rdhash = au_sbi(dentry->d_sb)->si_rdhash;
17776+ if (!rdhash)
17777+ rdhash = au_rdhash_est(au_dir_size(/*file*/NULL,
17778+ dentry));
17779+ err = au_nhash_alloc(&whlist, rdhash, GFP_NOFS);
17780+ if (unlikely(err))
17781+ goto out;
17782+ err = au_test_empty(dentry, &whlist);
17783+ au_nhash_wh_free(&whlist);
17784+ goto out;
17785+ }
dece6358 17786+
4a4d8108
AM
17787+ if (bstart == au_dbtaildir(dentry))
17788+ return 0; /* success */
dece6358 17789+
4a4d8108 17790+ err = au_test_empty_lower(dentry);
1facf9fc 17791+
4f0767ce 17792+out:
4a4d8108
AM
17793+ if (err == -ENOTEMPTY) {
17794+ AuWarn1("renaming dir who has child(ren) on multiple branches,"
17795+ " is not supported\n");
17796+ err = -EXDEV;
17797+ }
17798+ return err;
17799+}
1308ab2a 17800+
4a4d8108
AM
17801+/* side effect: sets whlist and h_dentry */
17802+static int au_ren_may_dir(struct au_ren_args *a)
1308ab2a 17803+{
4a4d8108
AM
17804+ int err;
17805+ unsigned int rdhash;
17806+ struct dentry *d;
1facf9fc 17807+
4a4d8108
AM
17808+ d = a->dst_dentry;
17809+ SiMustAnyLock(d->d_sb);
1facf9fc 17810+
4a4d8108
AM
17811+ err = 0;
17812+ if (au_ftest_ren(a->flags, ISDIR) && a->dst_inode) {
17813+ rdhash = au_sbi(d->d_sb)->si_rdhash;
17814+ if (!rdhash)
17815+ rdhash = au_rdhash_est(au_dir_size(/*file*/NULL, d));
17816+ err = au_nhash_alloc(&a->whlist, rdhash, GFP_NOFS);
17817+ if (unlikely(err))
17818+ goto out;
1308ab2a 17819+
4a4d8108
AM
17820+ au_set_dbstart(d, a->dst_bstart);
17821+ err = may_rename_dstdir(d, &a->whlist);
17822+ au_set_dbstart(d, a->btgt);
17823+ }
17824+ a->dst_h_dentry = au_h_dptr(d, au_dbstart(d));
17825+ if (unlikely(err))
17826+ goto out;
17827+
17828+ d = a->src_dentry;
17829+ a->src_h_dentry = au_h_dptr(d, au_dbstart(d));
17830+ if (au_ftest_ren(a->flags, ISDIR)) {
17831+ err = may_rename_srcdir(d, a->btgt);
17832+ if (unlikely(err)) {
17833+ au_nhash_wh_free(&a->whlist);
17834+ a->whlist.nh_num = 0;
17835+ }
17836+ }
4f0767ce 17837+out:
4a4d8108 17838+ return err;
1facf9fc 17839+}
17840+
4a4d8108 17841+/* ---------------------------------------------------------------------- */
1facf9fc 17842+
4a4d8108
AM
17843+/*
17844+ * simple tests for rename.
17845+ * following the checks in vfs, plus the parent-child relationship.
17846+ */
17847+static int au_may_ren(struct au_ren_args *a)
17848+{
17849+ int err, isdir;
17850+ struct inode *h_inode;
1facf9fc 17851+
4a4d8108
AM
17852+ if (a->src_bstart == a->btgt) {
17853+ err = au_may_del(a->src_dentry, a->btgt, a->src_h_parent,
17854+ au_ftest_ren(a->flags, ISDIR));
17855+ if (unlikely(err))
17856+ goto out;
17857+ err = -EINVAL;
17858+ if (unlikely(a->src_h_dentry == a->h_trap))
17859+ goto out;
17860+ }
1facf9fc 17861+
4a4d8108
AM
17862+ err = 0;
17863+ if (a->dst_bstart != a->btgt)
17864+ goto out;
1facf9fc 17865+
027c5e7a
AM
17866+ err = -ENOTEMPTY;
17867+ if (unlikely(a->dst_h_dentry == a->h_trap))
17868+ goto out;
17869+
4a4d8108
AM
17870+ err = -EIO;
17871+ h_inode = a->dst_h_dentry->d_inode;
17872+ isdir = !!au_ftest_ren(a->flags, ISDIR);
17873+ if (!a->dst_dentry->d_inode) {
17874+ if (unlikely(h_inode))
17875+ goto out;
17876+ err = au_may_add(a->dst_dentry, a->btgt, a->dst_h_parent,
17877+ isdir);
17878+ } else {
17879+ if (unlikely(!h_inode || !h_inode->i_nlink))
17880+ goto out;
17881+ err = au_may_del(a->dst_dentry, a->btgt, a->dst_h_parent,
17882+ isdir);
17883+ if (unlikely(err))
17884+ goto out;
4a4d8108 17885+ }
1facf9fc 17886+
4f0767ce 17887+out:
4a4d8108
AM
17888+ if (unlikely(err == -ENOENT || err == -EEXIST))
17889+ err = -EIO;
17890+ AuTraceErr(err);
17891+ return err;
17892+}
1facf9fc 17893+
1308ab2a 17894+/* ---------------------------------------------------------------------- */
1facf9fc 17895+
4a4d8108
AM
17896+/*
17897+ * locking order
17898+ * (VFS)
17899+ * - src_dir and dir by lock_rename()
17900+ * - inode if exitsts
17901+ * (aufs)
17902+ * - lock all
17903+ * + src_dentry and dentry by aufs_read_and_write_lock2() which calls,
17904+ * + si_read_lock
17905+ * + di_write_lock2_child()
17906+ * + di_write_lock_child()
17907+ * + ii_write_lock_child()
17908+ * + di_write_lock_child2()
17909+ * + ii_write_lock_child2()
17910+ * + src_parent and parent
17911+ * + di_write_lock_parent()
17912+ * + ii_write_lock_parent()
17913+ * + di_write_lock_parent2()
17914+ * + ii_write_lock_parent2()
17915+ * + lower src_dir and dir by vfsub_lock_rename()
17916+ * + verify the every relationships between child and parent. if any
17917+ * of them failed, unlock all and return -EBUSY.
17918+ */
17919+static void au_ren_unlock(struct au_ren_args *a)
1308ab2a 17920+{
4a4d8108
AM
17921+ struct super_block *sb;
17922+
17923+ sb = a->dst_dentry->d_sb;
17924+ if (au_ftest_ren(a->flags, MNT_WRITE))
17925+ mnt_drop_write(a->br->br_mnt);
17926+ vfsub_unlock_rename(a->src_h_parent, a->src_hdir,
17927+ a->dst_h_parent, a->dst_hdir);
1308ab2a 17928+}
17929+
4a4d8108 17930+static int au_ren_lock(struct au_ren_args *a)
1308ab2a 17931+{
4a4d8108
AM
17932+ int err;
17933+ unsigned int udba;
1308ab2a 17934+
4a4d8108
AM
17935+ err = 0;
17936+ a->src_h_parent = au_h_dptr(a->src_parent, a->btgt);
17937+ a->src_hdir = au_hi(a->src_dir, a->btgt);
17938+ a->dst_h_parent = au_h_dptr(a->dst_parent, a->btgt);
17939+ a->dst_hdir = au_hi(a->dst_dir, a->btgt);
17940+ a->h_trap = vfsub_lock_rename(a->src_h_parent, a->src_hdir,
17941+ a->dst_h_parent, a->dst_hdir);
17942+ udba = au_opt_udba(a->src_dentry->d_sb);
17943+ if (unlikely(a->src_hdir->hi_inode != a->src_h_parent->d_inode
17944+ || a->dst_hdir->hi_inode != a->dst_h_parent->d_inode))
17945+ err = au_busy_or_stale();
17946+ if (!err && au_dbstart(a->src_dentry) == a->btgt)
17947+ err = au_h_verify(a->src_h_dentry, udba,
17948+ a->src_h_parent->d_inode, a->src_h_parent,
17949+ a->br);
17950+ if (!err && au_dbstart(a->dst_dentry) == a->btgt)
17951+ err = au_h_verify(a->dst_h_dentry, udba,
17952+ a->dst_h_parent->d_inode, a->dst_h_parent,
17953+ a->br);
17954+ if (!err) {
17955+ err = mnt_want_write(a->br->br_mnt);
17956+ if (unlikely(err))
17957+ goto out_unlock;
17958+ au_fset_ren(a->flags, MNT_WRITE);
17959+ goto out; /* success */
17960+ }
17961+
17962+ err = au_busy_or_stale();
17963+
4f0767ce 17964+out_unlock:
4a4d8108 17965+ au_ren_unlock(a);
4f0767ce 17966+out:
4a4d8108 17967+ return err;
1facf9fc 17968+}
17969+
17970+/* ---------------------------------------------------------------------- */
17971+
4a4d8108 17972+static void au_ren_refresh_dir(struct au_ren_args *a)
1facf9fc 17973+{
4a4d8108 17974+ struct inode *dir;
dece6358 17975+
4a4d8108
AM
17976+ dir = a->dst_dir;
17977+ dir->i_version++;
17978+ if (au_ftest_ren(a->flags, ISDIR)) {
17979+ /* is this updating defined in POSIX? */
17980+ au_cpup_attr_timesizes(a->src_inode);
17981+ au_cpup_attr_nlink(dir, /*force*/1);
4a4d8108 17982+ }
027c5e7a 17983+
4a4d8108
AM
17984+ if (au_ibstart(dir) == a->btgt)
17985+ au_cpup_attr_timesizes(dir);
dece6358 17986+
4a4d8108
AM
17987+ if (au_ftest_ren(a->flags, ISSAMEDIR))
17988+ return;
dece6358 17989+
4a4d8108
AM
17990+ dir = a->src_dir;
17991+ dir->i_version++;
17992+ if (au_ftest_ren(a->flags, ISDIR))
17993+ au_cpup_attr_nlink(dir, /*force*/1);
17994+ if (au_ibstart(dir) == a->btgt)
17995+ au_cpup_attr_timesizes(dir);
1facf9fc 17996+}
17997+
4a4d8108 17998+static void au_ren_refresh(struct au_ren_args *a)
1facf9fc 17999+{
4a4d8108
AM
18000+ aufs_bindex_t bend, bindex;
18001+ struct dentry *d, *h_d;
18002+ struct inode *i, *h_i;
18003+ struct super_block *sb;
dece6358 18004+
027c5e7a
AM
18005+ d = a->dst_dentry;
18006+ d_drop(d);
18007+ if (a->h_dst)
18008+ /* already dget-ed by au_ren_or_cpup() */
18009+ au_set_h_dptr(d, a->btgt, a->h_dst);
18010+
18011+ i = a->dst_inode;
18012+ if (i) {
18013+ if (!au_ftest_ren(a->flags, ISDIR))
18014+ vfsub_drop_nlink(i);
18015+ else {
18016+ vfsub_dead_dir(i);
18017+ au_cpup_attr_timesizes(i);
18018+ }
18019+ au_update_dbrange(d, /*do_put_zero*/1);
18020+ } else {
18021+ bend = a->btgt;
18022+ for (bindex = au_dbstart(d); bindex < bend; bindex++)
18023+ au_set_h_dptr(d, bindex, NULL);
18024+ bend = au_dbend(d);
18025+ for (bindex = a->btgt + 1; bindex <= bend; bindex++)
18026+ au_set_h_dptr(d, bindex, NULL);
18027+ au_update_dbrange(d, /*do_put_zero*/0);
18028+ }
18029+
4a4d8108
AM
18030+ d = a->src_dentry;
18031+ au_set_dbwh(d, -1);
18032+ bend = au_dbend(d);
18033+ for (bindex = a->btgt + 1; bindex <= bend; bindex++) {
18034+ h_d = au_h_dptr(d, bindex);
18035+ if (h_d)
18036+ au_set_h_dptr(d, bindex, NULL);
18037+ }
18038+ au_set_dbend(d, a->btgt);
18039+
18040+ sb = d->d_sb;
18041+ i = a->src_inode;
18042+ if (au_opt_test(au_mntflags(sb), PLINK) && au_plink_test(i))
18043+ return; /* success */
18044+
18045+ bend = au_ibend(i);
18046+ for (bindex = a->btgt + 1; bindex <= bend; bindex++) {
18047+ h_i = au_h_iptr(i, bindex);
18048+ if (h_i) {
18049+ au_xino_write(sb, bindex, h_i->i_ino, /*ino*/0);
18050+ /* ignore this error */
18051+ au_set_h_iptr(i, bindex, NULL, 0);
18052+ }
18053+ }
18054+ au_set_ibend(i, a->btgt);
1308ab2a 18055+}
dece6358 18056+
4a4d8108
AM
18057+/* ---------------------------------------------------------------------- */
18058+
18059+/* mainly for link(2) and rename(2) */
18060+int au_wbr(struct dentry *dentry, aufs_bindex_t btgt)
1308ab2a 18061+{
4a4d8108
AM
18062+ aufs_bindex_t bdiropq, bwh;
18063+ struct dentry *parent;
18064+ struct au_branch *br;
18065+
18066+ parent = dentry->d_parent;
18067+ IMustLock(parent->d_inode); /* dir is locked */
18068+
18069+ bdiropq = au_dbdiropq(parent);
18070+ bwh = au_dbwh(dentry);
18071+ br = au_sbr(dentry->d_sb, btgt);
18072+ if (au_br_rdonly(br)
18073+ || (0 <= bdiropq && bdiropq < btgt)
18074+ || (0 <= bwh && bwh < btgt))
18075+ btgt = -1;
18076+
18077+ AuDbg("btgt %d\n", btgt);
18078+ return btgt;
1facf9fc 18079+}
18080+
4a4d8108
AM
18081+/* sets src_bstart, dst_bstart and btgt */
18082+static int au_ren_wbr(struct au_ren_args *a)
1facf9fc 18083+{
4a4d8108
AM
18084+ int err;
18085+ struct au_wr_dir_args wr_dir_args = {
18086+ /* .force_btgt = -1, */
18087+ .flags = AuWrDir_ADD_ENTRY
18088+ };
dece6358 18089+
4a4d8108
AM
18090+ a->src_bstart = au_dbstart(a->src_dentry);
18091+ a->dst_bstart = au_dbstart(a->dst_dentry);
18092+ if (au_ftest_ren(a->flags, ISDIR))
18093+ au_fset_wrdir(wr_dir_args.flags, ISDIR);
18094+ wr_dir_args.force_btgt = a->src_bstart;
18095+ if (a->dst_inode && a->dst_bstart < a->src_bstart)
18096+ wr_dir_args.force_btgt = a->dst_bstart;
18097+ wr_dir_args.force_btgt = au_wbr(a->dst_dentry, wr_dir_args.force_btgt);
18098+ err = au_wr_dir(a->dst_dentry, a->src_dentry, &wr_dir_args);
18099+ a->btgt = err;
dece6358 18100+
4a4d8108 18101+ return err;
1facf9fc 18102+}
18103+
4a4d8108 18104+static void au_ren_dt(struct au_ren_args *a)
1facf9fc 18105+{
4a4d8108
AM
18106+ a->h_path.dentry = a->src_h_parent;
18107+ au_dtime_store(a->src_dt + AuPARENT, a->src_parent, &a->h_path);
18108+ if (!au_ftest_ren(a->flags, ISSAMEDIR)) {
18109+ a->h_path.dentry = a->dst_h_parent;
18110+ au_dtime_store(a->dst_dt + AuPARENT, a->dst_parent, &a->h_path);
18111+ }
1facf9fc 18112+
4a4d8108
AM
18113+ au_fclr_ren(a->flags, DT_DSTDIR);
18114+ if (!au_ftest_ren(a->flags, ISDIR))
18115+ return;
dece6358 18116+
4a4d8108
AM
18117+ a->h_path.dentry = a->src_h_dentry;
18118+ au_dtime_store(a->src_dt + AuCHILD, a->src_dentry, &a->h_path);
18119+ if (a->dst_h_dentry->d_inode) {
18120+ au_fset_ren(a->flags, DT_DSTDIR);
18121+ a->h_path.dentry = a->dst_h_dentry;
18122+ au_dtime_store(a->dst_dt + AuCHILD, a->dst_dentry, &a->h_path);
18123+ }
1308ab2a 18124+}
dece6358 18125+
4a4d8108 18126+static void au_ren_rev_dt(int err, struct au_ren_args *a)
1308ab2a 18127+{
4a4d8108
AM
18128+ struct dentry *h_d;
18129+ struct mutex *h_mtx;
18130+
18131+ au_dtime_revert(a->src_dt + AuPARENT);
18132+ if (!au_ftest_ren(a->flags, ISSAMEDIR))
18133+ au_dtime_revert(a->dst_dt + AuPARENT);
18134+
18135+ if (au_ftest_ren(a->flags, ISDIR) && err != -EIO) {
18136+ h_d = a->src_dt[AuCHILD].dt_h_path.dentry;
18137+ h_mtx = &h_d->d_inode->i_mutex;
18138+ mutex_lock_nested(h_mtx, AuLsc_I_CHILD);
18139+ au_dtime_revert(a->src_dt + AuCHILD);
18140+ mutex_unlock(h_mtx);
18141+
18142+ if (au_ftest_ren(a->flags, DT_DSTDIR)) {
18143+ h_d = a->dst_dt[AuCHILD].dt_h_path.dentry;
18144+ h_mtx = &h_d->d_inode->i_mutex;
18145+ mutex_lock_nested(h_mtx, AuLsc_I_CHILD);
18146+ au_dtime_revert(a->dst_dt + AuCHILD);
18147+ mutex_unlock(h_mtx);
1facf9fc 18148+ }
18149+ }
18150+}
18151+
4a4d8108
AM
18152+/* ---------------------------------------------------------------------- */
18153+
18154+int aufs_rename(struct inode *_src_dir, struct dentry *_src_dentry,
18155+ struct inode *_dst_dir, struct dentry *_dst_dentry)
1facf9fc 18156+{
e49829fe 18157+ int err, flags;
4a4d8108
AM
18158+ /* reduce stack space */
18159+ struct au_ren_args *a;
18160+
18161+ AuDbg("%.*s, %.*s\n", AuDLNPair(_src_dentry), AuDLNPair(_dst_dentry));
18162+ IMustLock(_src_dir);
18163+ IMustLock(_dst_dir);
18164+
18165+ err = -ENOMEM;
18166+ BUILD_BUG_ON(sizeof(*a) > PAGE_SIZE);
18167+ a = kzalloc(sizeof(*a), GFP_NOFS);
18168+ if (unlikely(!a))
18169+ goto out;
18170+
18171+ a->src_dir = _src_dir;
18172+ a->src_dentry = _src_dentry;
18173+ a->src_inode = a->src_dentry->d_inode;
18174+ a->src_parent = a->src_dentry->d_parent; /* dir inode is locked */
18175+ a->dst_dir = _dst_dir;
18176+ a->dst_dentry = _dst_dentry;
18177+ a->dst_inode = a->dst_dentry->d_inode;
18178+ a->dst_parent = a->dst_dentry->d_parent; /* dir inode is locked */
18179+ if (a->dst_inode) {
18180+ IMustLock(a->dst_inode);
18181+ au_igrab(a->dst_inode);
1facf9fc 18182+ }
1facf9fc 18183+
4a4d8108 18184+ err = -ENOTDIR;
027c5e7a 18185+ flags = AuLock_FLUSH | AuLock_NOPLM | AuLock_GEN;
4a4d8108
AM
18186+ if (S_ISDIR(a->src_inode->i_mode)) {
18187+ au_fset_ren(a->flags, ISDIR);
18188+ if (unlikely(a->dst_inode && !S_ISDIR(a->dst_inode->i_mode)))
18189+ goto out_free;
e49829fe
JR
18190+ err = aufs_read_and_write_lock2(a->dst_dentry, a->src_dentry,
18191+ AuLock_DIR | flags);
4a4d8108 18192+ } else
e49829fe
JR
18193+ err = aufs_read_and_write_lock2(a->dst_dentry, a->src_dentry,
18194+ flags);
18195+ if (unlikely(err))
18196+ goto out_free;
1facf9fc 18197+
027c5e7a
AM
18198+ err = au_d_hashed_positive(a->src_dentry);
18199+ if (unlikely(err))
18200+ goto out_unlock;
18201+ err = -ENOENT;
18202+ if (a->dst_inode) {
18203+ /*
18204+ * If it is a dir, VFS unhash dst_dentry before this
18205+ * function. It means we cannot rely upon d_unhashed().
18206+ */
18207+ if (unlikely(!a->dst_inode->i_nlink))
18208+ goto out_unlock;
18209+ if (!S_ISDIR(a->dst_inode->i_mode)) {
18210+ err = au_d_hashed_positive(a->dst_dentry);
18211+ if (unlikely(err))
18212+ goto out_unlock;
18213+ } else if (unlikely(IS_DEADDIR(a->dst_inode)))
18214+ goto out_unlock;
18215+ } else if (unlikely(d_unhashed(a->dst_dentry)))
18216+ goto out_unlock;
18217+
7eafdf33
AM
18218+ /*
18219+ * is it possible?
18220+ * yes, it happend (in linux-3.3-rcN) but I don't know why.
18221+ * there may exist a problem somewhere else.
18222+ */
18223+ err = -EINVAL;
18224+ if (unlikely(a->dst_parent->d_inode == a->src_dentry->d_inode))
18225+ goto out_unlock;
18226+
4a4d8108
AM
18227+ au_fset_ren(a->flags, ISSAMEDIR); /* temporary */
18228+ di_write_lock_parent(a->dst_parent);
1facf9fc 18229+
4a4d8108
AM
18230+ /* which branch we process */
18231+ err = au_ren_wbr(a);
18232+ if (unlikely(err < 0))
027c5e7a 18233+ goto out_parent;
4a4d8108
AM
18234+ a->br = au_sbr(a->dst_dentry->d_sb, a->btgt);
18235+ a->h_path.mnt = a->br->br_mnt;
1facf9fc 18236+
4a4d8108
AM
18237+ /* are they available to be renamed */
18238+ err = au_ren_may_dir(a);
18239+ if (unlikely(err))
18240+ goto out_children;
1facf9fc 18241+
4a4d8108
AM
18242+ /* prepare the writable parent dir on the same branch */
18243+ if (a->dst_bstart == a->btgt) {
18244+ au_fset_ren(a->flags, WHDST);
18245+ } else {
18246+ err = au_cpup_dirs(a->dst_dentry, a->btgt);
18247+ if (unlikely(err))
18248+ goto out_children;
18249+ }
1facf9fc 18250+
4a4d8108
AM
18251+ if (a->src_dir != a->dst_dir) {
18252+ /*
18253+ * this temporary unlock is safe,
18254+ * because both dir->i_mutex are locked.
18255+ */
18256+ di_write_unlock(a->dst_parent);
18257+ di_write_lock_parent(a->src_parent);
18258+ err = au_wr_dir_need_wh(a->src_dentry,
18259+ au_ftest_ren(a->flags, ISDIR),
18260+ &a->btgt);
18261+ di_write_unlock(a->src_parent);
18262+ di_write_lock2_parent(a->src_parent, a->dst_parent, /*isdir*/1);
18263+ au_fclr_ren(a->flags, ISSAMEDIR);
18264+ } else
18265+ err = au_wr_dir_need_wh(a->src_dentry,
18266+ au_ftest_ren(a->flags, ISDIR),
18267+ &a->btgt);
18268+ if (unlikely(err < 0))
18269+ goto out_children;
18270+ if (err)
18271+ au_fset_ren(a->flags, WHSRC);
1facf9fc 18272+
4a4d8108
AM
18273+ /* lock them all */
18274+ err = au_ren_lock(a);
18275+ if (unlikely(err))
18276+ goto out_children;
1facf9fc 18277+
4a4d8108
AM
18278+ if (!au_opt_test(au_mntflags(a->dst_dir->i_sb), UDBA_NONE))
18279+ err = au_may_ren(a);
18280+ else if (unlikely(a->dst_dentry->d_name.len > AUFS_MAX_NAMELEN))
18281+ err = -ENAMETOOLONG;
18282+ if (unlikely(err))
18283+ goto out_hdir;
1facf9fc 18284+
4a4d8108
AM
18285+ /* store timestamps to be revertible */
18286+ au_ren_dt(a);
1facf9fc 18287+
4a4d8108
AM
18288+ /* here we go */
18289+ err = do_rename(a);
18290+ if (unlikely(err))
18291+ goto out_dt;
18292+
18293+ /* update dir attributes */
18294+ au_ren_refresh_dir(a);
18295+
18296+ /* dput/iput all lower dentries */
18297+ au_ren_refresh(a);
18298+
18299+ goto out_hdir; /* success */
18300+
4f0767ce 18301+out_dt:
4a4d8108 18302+ au_ren_rev_dt(err, a);
4f0767ce 18303+out_hdir:
4a4d8108 18304+ au_ren_unlock(a);
4f0767ce 18305+out_children:
4a4d8108 18306+ au_nhash_wh_free(&a->whlist);
027c5e7a
AM
18307+ if (err && a->dst_inode && a->dst_bstart != a->btgt) {
18308+ AuDbg("bstart %d, btgt %d\n", a->dst_bstart, a->btgt);
18309+ au_set_h_dptr(a->dst_dentry, a->btgt, NULL);
18310+ au_set_dbstart(a->dst_dentry, a->dst_bstart);
4a4d8108 18311+ }
027c5e7a 18312+out_parent:
4a4d8108
AM
18313+ if (!err)
18314+ d_move(a->src_dentry, a->dst_dentry);
027c5e7a
AM
18315+ else {
18316+ au_update_dbstart(a->dst_dentry);
18317+ if (!a->dst_inode)
18318+ d_drop(a->dst_dentry);
18319+ }
4a4d8108
AM
18320+ if (au_ftest_ren(a->flags, ISSAMEDIR))
18321+ di_write_unlock(a->dst_parent);
18322+ else
18323+ di_write_unlock2(a->src_parent, a->dst_parent);
027c5e7a 18324+out_unlock:
4a4d8108 18325+ aufs_read_and_write_unlock2(a->dst_dentry, a->src_dentry);
4f0767ce 18326+out_free:
4a4d8108
AM
18327+ iput(a->dst_inode);
18328+ if (a->thargs)
18329+ au_whtmp_rmdir_free(a->thargs);
18330+ kfree(a);
4f0767ce 18331+out:
4a4d8108
AM
18332+ AuTraceErr(err);
18333+ return err;
1308ab2a 18334+}
7f207e10
AM
18335diff -urN /usr/share/empty/fs/aufs/Kconfig linux/fs/aufs/Kconfig
18336--- /usr/share/empty/fs/aufs/Kconfig 1970-01-01 01:00:00.000000000 +0100
7ce627cf 18337+++ linux/fs/aufs/Kconfig 2012-05-22 09:06:08.864125478 +0200
2cbb1c4b 18338@@ -0,0 +1,203 @@
4a4d8108
AM
18339+config AUFS_FS
18340+ tristate "Aufs (Advanced multi layered unification filesystem) support"
18341+ depends on EXPERIMENTAL
18342+ help
18343+ Aufs is a stackable unification filesystem such as Unionfs,
18344+ which unifies several directories and provides a merged single
18345+ directory.
18346+ In the early days, aufs was entirely re-designed and
18347+ re-implemented Unionfs Version 1.x series. Introducing many
18348+ original ideas, approaches and improvements, it becomes totally
18349+ different from Unionfs while keeping the basic features.
1facf9fc 18350+
4a4d8108
AM
18351+if AUFS_FS
18352+choice
18353+ prompt "Maximum number of branches"
18354+ default AUFS_BRANCH_MAX_127
18355+ help
18356+ Specifies the maximum number of branches (or member directories)
18357+ in a single aufs. The larger value consumes more system
18358+ resources and has a minor impact to performance.
18359+config AUFS_BRANCH_MAX_127
18360+ bool "127"
18361+ help
18362+ Specifies the maximum number of branches (or member directories)
18363+ in a single aufs. The larger value consumes more system
18364+ resources and has a minor impact to performance.
18365+config AUFS_BRANCH_MAX_511
18366+ bool "511"
18367+ help
18368+ Specifies the maximum number of branches (or member directories)
18369+ in a single aufs. The larger value consumes more system
18370+ resources and has a minor impact to performance.
18371+config AUFS_BRANCH_MAX_1023
18372+ bool "1023"
18373+ help
18374+ Specifies the maximum number of branches (or member directories)
18375+ in a single aufs. The larger value consumes more system
18376+ resources and has a minor impact to performance.
18377+config AUFS_BRANCH_MAX_32767
18378+ bool "32767"
18379+ help
18380+ Specifies the maximum number of branches (or member directories)
18381+ in a single aufs. The larger value consumes more system
18382+ resources and has a minor impact to performance.
18383+endchoice
1facf9fc 18384+
e49829fe
JR
18385+config AUFS_SBILIST
18386+ bool
18387+ depends on AUFS_MAGIC_SYSRQ || PROC_FS
18388+ default y
18389+ help
18390+ Automatic configuration for internal use.
18391+ When aufs supports Magic SysRq or /proc, enabled automatically.
18392+
4a4d8108
AM
18393+config AUFS_HNOTIFY
18394+ bool "Detect direct branch access (bypassing aufs)"
18395+ help
18396+ If you want to modify files on branches directly, eg. bypassing aufs,
18397+ and want aufs to detect the changes of them fully, then enable this
18398+ option and use 'udba=notify' mount option.
7f207e10 18399+ Currently there is only one available configuration, "fsnotify".
4a4d8108
AM
18400+ It will have a negative impact to the performance.
18401+ See detail in aufs.5.
dece6358 18402+
4a4d8108
AM
18403+choice
18404+ prompt "method" if AUFS_HNOTIFY
18405+ default AUFS_HFSNOTIFY
18406+config AUFS_HFSNOTIFY
18407+ bool "fsnotify"
18408+ select FSNOTIFY
4a4d8108 18409+endchoice
1facf9fc 18410+
4a4d8108
AM
18411+config AUFS_EXPORT
18412+ bool "NFS-exportable aufs"
2cbb1c4b 18413+ depends on EXPORTFS
4a4d8108
AM
18414+ help
18415+ If you want to export your mounted aufs via NFS, then enable this
18416+ option. There are several requirements for this configuration.
18417+ See detail in aufs.5.
1facf9fc 18418+
4a4d8108
AM
18419+config AUFS_INO_T_64
18420+ bool
18421+ depends on AUFS_EXPORT
18422+ depends on 64BIT && !(ALPHA || S390)
18423+ default y
18424+ help
18425+ Automatic configuration for internal use.
18426+ /* typedef unsigned long/int __kernel_ino_t */
18427+ /* alpha and s390x are int */
1facf9fc 18428+
4a4d8108
AM
18429+config AUFS_RDU
18430+ bool "Readdir in userspace"
18431+ help
18432+ Aufs has two methods to provide a merged view for a directory,
18433+ by a user-space library and by kernel-space natively. The latter
18434+ is always enabled but sometimes large and slow.
18435+ If you enable this option, install the library in aufs2-util
18436+ package, and set some environment variables for your readdir(3),
18437+ then the work will be handled in user-space which generally
18438+ shows better performance in most cases.
18439+ See detail in aufs.5.
1facf9fc 18440+
2cbb1c4b
JR
18441+config AUFS_PROC_MAP
18442+ bool "support for /proc/maps and lsof(1)"
18443+ depends on PROC_FS
18444+ help
18445+ When you issue mmap(2) in aufs, it is actually a direct mmap(2)
18446+ call to the file on the branch fs since the file in aufs is
18447+ purely virtual. And the file path printed in /proc/maps (and
18448+ others) will be the path on the branch fs. In most cases, it
18449+ does no harm. But some utilities like lsof(1) may confuse since
18450+ the utility or user may expect the file path in aufs to be
18451+ printed.
18452+ To address this issue, aufs provides a patch which introduces a
18453+ new member called vm_prfile into struct vm_are_struct. The patch
18454+ is meaningless without enabling this configuration since nobody
18455+ sets the new vm_prfile member.
18456+ If you don't apply the patch, then enabling this configuration
18457+ will cause a compile error.
18458+ This approach is fragile since if someone else make some changes
18459+ around vm_file, then vm_prfile may not work anymore. As a
18460+ workaround such case, aufs provides this configuration. If you
18461+ disable it, then lsof(1) may produce incorrect result but the
18462+ problem will be gone even if the aufs patch is applied (I hope).
18463+
4a4d8108
AM
18464+config AUFS_SP_IATTR
18465+ bool "Respect the attributes (mtime/ctime mainly) of special files"
18466+ help
18467+ When you write something to a special file, some attributes of it
18468+ (mtime/ctime mainly) may be updated. Generally such updates are
18469+ less important (actually some device drivers and NFS ignore
18470+ it). But some applications (such like test program) requires
18471+ such updates. If you need these updates, then enable this
18472+ configuration which introduces some overhead.
18473+ Currently this configuration handles FIFO only.
1facf9fc 18474+
4a4d8108
AM
18475+config AUFS_SHWH
18476+ bool "Show whiteouts"
18477+ help
18478+ If you want to make the whiteouts in aufs visible, then enable
18479+ this option and specify 'shwh' mount option. Although it may
18480+ sounds like philosophy or something, but in technically it
18481+ simply shows the name of whiteout with keeping its behaviour.
1facf9fc 18482+
4a4d8108
AM
18483+config AUFS_BR_RAMFS
18484+ bool "Ramfs (initramfs/rootfs) as an aufs branch"
18485+ help
18486+ If you want to use ramfs as an aufs branch fs, then enable this
18487+ option. Generally tmpfs is recommended.
18488+ Aufs prohibited them to be a branch fs by default, because
18489+ initramfs becomes unusable after switch_root or something
18490+ generally. If you sets initramfs as an aufs branch and boot your
18491+ system by switch_root, you will meet a problem easily since the
18492+ files in initramfs may be inaccessible.
18493+ Unless you are going to use ramfs as an aufs branch fs without
18494+ switch_root or something, leave it N.
1facf9fc 18495+
4a4d8108
AM
18496+config AUFS_BR_FUSE
18497+ bool "Fuse fs as an aufs branch"
18498+ depends on FUSE_FS
18499+ select AUFS_POLL
18500+ help
18501+ If you want to use fuse-based userspace filesystem as an aufs
18502+ branch fs, then enable this option.
18503+ It implements the internal poll(2) operation which is
18504+ implemented by fuse only (curretnly).
1facf9fc 18505+
4a4d8108
AM
18506+config AUFS_POLL
18507+ bool
18508+ help
18509+ Automatic configuration for internal use.
1facf9fc 18510+
4a4d8108
AM
18511+config AUFS_BR_HFSPLUS
18512+ bool "Hfsplus as an aufs branch"
18513+ depends on HFSPLUS_FS
18514+ default y
18515+ help
18516+ If you want to use hfsplus fs as an aufs branch fs, then enable
18517+ this option. This option introduces a small overhead at
18518+ copying-up a file on hfsplus.
1facf9fc 18519+
4a4d8108
AM
18520+config AUFS_BDEV_LOOP
18521+ bool
18522+ depends on BLK_DEV_LOOP
18523+ default y
18524+ help
18525+ Automatic configuration for internal use.
18526+ Convert =[ym] into =y.
1308ab2a 18527+
4a4d8108
AM
18528+config AUFS_DEBUG
18529+ bool "Debug aufs"
18530+ help
18531+ Enable this to compile aufs internal debug code.
18532+ It will have a negative impact to the performance.
18533+
18534+config AUFS_MAGIC_SYSRQ
18535+ bool
18536+ depends on AUFS_DEBUG && MAGIC_SYSRQ
18537+ default y
18538+ help
18539+ Automatic configuration for internal use.
18540+ When aufs supports Magic SysRq, enabled automatically.
18541+endif
7f207e10
AM
18542diff -urN /usr/share/empty/fs/aufs/loop.c linux/fs/aufs/loop.c
18543--- /usr/share/empty/fs/aufs/loop.c 1970-01-01 01:00:00.000000000 +0100
7ce627cf 18544+++ linux/fs/aufs/loop.c 2012-05-22 09:06:08.870792417 +0200
87a755f4 18545@@ -0,0 +1,133 @@
1facf9fc 18546+/*
f6c5ef8b 18547+ * Copyright (C) 2005-2012 Junjiro R. Okajima
1facf9fc 18548+ *
18549+ * This program, aufs is free software; you can redistribute it and/or modify
18550+ * it under the terms of the GNU General Public License as published by
18551+ * the Free Software Foundation; either version 2 of the License, or
18552+ * (at your option) any later version.
dece6358
AM
18553+ *
18554+ * This program is distributed in the hope that it will be useful,
18555+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
18556+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18557+ * GNU General Public License for more details.
18558+ *
18559+ * You should have received a copy of the GNU General Public License
18560+ * along with this program; if not, write to the Free Software
18561+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 18562+ */
18563+
18564+/*
18565+ * support for loopback block device as a branch
18566+ */
18567+
18568+#include <linux/loop.h>
18569+#include "aufs.h"
18570+
18571+/*
18572+ * test if two lower dentries have overlapping branches.
18573+ */
b752ccd1 18574+int au_test_loopback_overlap(struct super_block *sb, struct dentry *h_adding)
1facf9fc 18575+{
b752ccd1 18576+ struct super_block *h_sb;
1facf9fc 18577+ struct loop_device *l;
18578+
b752ccd1
AM
18579+ h_sb = h_adding->d_sb;
18580+ if (MAJOR(h_sb->s_dev) != LOOP_MAJOR)
1facf9fc 18581+ return 0;
18582+
b752ccd1
AM
18583+ l = h_sb->s_bdev->bd_disk->private_data;
18584+ h_adding = l->lo_backing_file->f_dentry;
18585+ /*
18586+ * h_adding can be local NFS.
18587+ * in this case aufs cannot detect the loop.
18588+ */
18589+ if (unlikely(h_adding->d_sb == sb))
1facf9fc 18590+ return 1;
b752ccd1 18591+ return !!au_test_subdir(h_adding, sb->s_root);
1facf9fc 18592+}
18593+
18594+/* true if a kernel thread named 'loop[0-9].*' accesses a file */
18595+int au_test_loopback_kthread(void)
18596+{
b752ccd1
AM
18597+ int ret;
18598+ struct task_struct *tsk = current;
18599+
18600+ ret = 0;
18601+ if (tsk->flags & PF_KTHREAD) {
18602+ const char c = tsk->comm[4];
18603+ ret = ('0' <= c && c <= '9'
18604+ && !strncmp(tsk->comm, "loop", 4));
18605+ }
1facf9fc 18606+
b752ccd1 18607+ return ret;
1facf9fc 18608+}
87a755f4
AM
18609+
18610+/* ---------------------------------------------------------------------- */
18611+
18612+#define au_warn_loopback_step 16
18613+static int au_warn_loopback_nelem = au_warn_loopback_step;
18614+static unsigned long *au_warn_loopback_array;
18615+
18616+void au_warn_loopback(struct super_block *h_sb)
18617+{
18618+ int i, new_nelem;
18619+ unsigned long *a, magic;
18620+ static DEFINE_SPINLOCK(spin);
18621+
18622+ magic = h_sb->s_magic;
18623+ spin_lock(&spin);
18624+ a = au_warn_loopback_array;
18625+ for (i = 0; i < au_warn_loopback_nelem && *a; i++)
18626+ if (a[i] == magic) {
18627+ spin_unlock(&spin);
18628+ return;
18629+ }
18630+
18631+ /* h_sb is new to us, print it */
18632+ if (i < au_warn_loopback_nelem) {
18633+ a[i] = magic;
18634+ goto pr;
18635+ }
18636+
18637+ /* expand the array */
18638+ new_nelem = au_warn_loopback_nelem + au_warn_loopback_step;
18639+ a = au_kzrealloc(au_warn_loopback_array,
18640+ au_warn_loopback_nelem * sizeof(unsigned long),
18641+ new_nelem * sizeof(unsigned long), GFP_ATOMIC);
18642+ if (a) {
18643+ au_warn_loopback_nelem = new_nelem;
18644+ au_warn_loopback_array = a;
18645+ a[i] = magic;
18646+ goto pr;
18647+ }
18648+
18649+ spin_unlock(&spin);
18650+ AuWarn1("realloc failed, ignored\n");
18651+ return;
18652+
18653+pr:
18654+ spin_unlock(&spin);
18655+ pr_warning("you may want to try another patch for loopback file "
18656+ "on %s(0x%lx) branch\n", au_sbtype(h_sb), magic);
18657+}
18658+
18659+int au_loopback_init(void)
18660+{
18661+ int err;
18662+ struct super_block *sb __maybe_unused;
18663+
18664+ AuDebugOn(sizeof(sb->s_magic) != sizeof(unsigned long));
18665+
18666+ err = 0;
18667+ au_warn_loopback_array = kcalloc(au_warn_loopback_step,
18668+ sizeof(unsigned long), GFP_NOFS);
18669+ if (unlikely(!au_warn_loopback_array))
18670+ err = -ENOMEM;
18671+
18672+ return err;
18673+}
18674+
18675+void au_loopback_fin(void)
18676+{
18677+ kfree(au_warn_loopback_array);
18678+}
7f207e10
AM
18679diff -urN /usr/share/empty/fs/aufs/loop.h linux/fs/aufs/loop.h
18680--- /usr/share/empty/fs/aufs/loop.h 1970-01-01 01:00:00.000000000 +0100
7ce627cf 18681+++ linux/fs/aufs/loop.h 2012-05-22 09:06:08.870792417 +0200
87a755f4 18682@@ -0,0 +1,50 @@
1facf9fc 18683+/*
f6c5ef8b 18684+ * Copyright (C) 2005-2012 Junjiro R. Okajima
1facf9fc 18685+ *
18686+ * This program, aufs is free software; you can redistribute it and/or modify
18687+ * it under the terms of the GNU General Public License as published by
18688+ * the Free Software Foundation; either version 2 of the License, or
18689+ * (at your option) any later version.
dece6358
AM
18690+ *
18691+ * This program is distributed in the hope that it will be useful,
18692+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
18693+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18694+ * GNU General Public License for more details.
18695+ *
18696+ * You should have received a copy of the GNU General Public License
18697+ * along with this program; if not, write to the Free Software
18698+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 18699+ */
18700+
18701+/*
18702+ * support for loopback mount as a branch
18703+ */
18704+
18705+#ifndef __AUFS_LOOP_H__
18706+#define __AUFS_LOOP_H__
18707+
18708+#ifdef __KERNEL__
18709+
dece6358
AM
18710+struct dentry;
18711+struct super_block;
1facf9fc 18712+
18713+#ifdef CONFIG_AUFS_BDEV_LOOP
18714+/* loop.c */
b752ccd1 18715+int au_test_loopback_overlap(struct super_block *sb, struct dentry *h_adding);
1facf9fc 18716+int au_test_loopback_kthread(void);
87a755f4
AM
18717+void au_warn_loopback(struct super_block *h_sb);
18718+
18719+int au_loopback_init(void);
18720+void au_loopback_fin(void);
1facf9fc 18721+#else
4a4d8108 18722+AuStubInt0(au_test_loopback_overlap, struct super_block *sb,
b752ccd1 18723+ struct dentry *h_adding)
4a4d8108 18724+AuStubInt0(au_test_loopback_kthread, void)
87a755f4
AM
18725+AuStubVoid(au_warn_loopback, struct super_block *h_sb)
18726+
18727+AuStubInt0(au_loopback_init, void)
18728+AuStubVoid(au_loopback_fin, void)
1facf9fc 18729+#endif /* BLK_DEV_LOOP */
18730+
18731+#endif /* __KERNEL__ */
18732+#endif /* __AUFS_LOOP_H__ */
7f207e10
AM
18733diff -urN /usr/share/empty/fs/aufs/magic.mk linux/fs/aufs/magic.mk
18734--- /usr/share/empty/fs/aufs/magic.mk 1970-01-01 01:00:00.000000000 +0100
7ce627cf 18735+++ linux/fs/aufs/magic.mk 2012-05-22 09:06:08.870792417 +0200
4a4d8108 18736@@ -0,0 +1,54 @@
1facf9fc 18737+
18738+# defined in ${srctree}/fs/fuse/inode.c
18739+# tristate
18740+ifdef CONFIG_FUSE_FS
18741+ccflags-y += -DFUSE_SUPER_MAGIC=0x65735546
18742+endif
18743+
18744+# defined in ${srctree}/fs/ocfs2/ocfs2_fs.h
18745+# tristate
18746+ifdef CONFIG_OCFS2_FS
18747+ccflags-y += -DOCFS2_SUPER_MAGIC=0x7461636f
18748+endif
18749+
18750+# defined in ${srctree}/fs/ocfs2/dlm/userdlm.h
18751+# tristate
18752+ifdef CONFIG_OCFS2_FS_O2CB
18753+ccflags-y += -DDLMFS_MAGIC=0x76a9f425
18754+endif
18755+
1facf9fc 18756+# defined in ${srctree}/fs/cifs/cifsfs.c
18757+# tristate
18758+ifdef CONFIG_CIFS_FS
18759+ccflags-y += -DCIFS_MAGIC_NUMBER=0xFF534D42
18760+endif
18761+
18762+# defined in ${srctree}/fs/xfs/xfs_sb.h
18763+# tristate
18764+ifdef CONFIG_XFS_FS
18765+ccflags-y += -DXFS_SB_MAGIC=0x58465342
18766+endif
18767+
18768+# defined in ${srctree}/fs/configfs/mount.c
18769+# tristate
18770+ifdef CONFIG_CONFIGFS_FS
18771+ccflags-y += -DCONFIGFS_MAGIC=0x62656570
18772+endif
18773+
18774+# defined in ${srctree}/fs/9p/v9fs.h
18775+# tristate
18776+ifdef CONFIG_9P_FS
18777+ccflags-y += -DV9FS_MAGIC=0x01021997
18778+endif
18779+
18780+# defined in ${srctree}/fs/ubifs/ubifs.h
18781+# tristate
18782+ifdef CONFIG_UBIFS_FS
18783+ccflags-y += -DUBIFS_SUPER_MAGIC=0x24051905
18784+endif
4a4d8108
AM
18785+
18786+# defined in ${srctree}/fs/hfsplus/hfsplus_raw.h
18787+# tristate
18788+ifdef CONFIG_HFSPLUS_FS
18789+ccflags-y += -DHFSPLUS_SUPER_MAGIC=0x482b
18790+endif
7f207e10
AM
18791diff -urN /usr/share/empty/fs/aufs/Makefile linux/fs/aufs/Makefile
18792--- /usr/share/empty/fs/aufs/Makefile 1970-01-01 01:00:00.000000000 +0100
7ce627cf 18793+++ linux/fs/aufs/Makefile 2012-05-22 09:06:08.864125478 +0200
f6c5ef8b 18794@@ -0,0 +1,42 @@
4a4d8108
AM
18795+
18796+include ${src}/magic.mk
18797+ifeq (${CONFIG_AUFS_FS},m)
18798+include ${src}/conf.mk
18799+endif
18800+-include ${src}/priv_def.mk
18801+
18802+# cf. include/linux/kernel.h
18803+# enable pr_debug
18804+ccflags-y += -DDEBUG
f6c5ef8b
AM
18805+# sparse requires the full pathname
18806+ifdef M
18807+ccflags-y += -include ${M}/../../include/linux/aufs_type.h
18808+else
18809+ccflags-y += -include ${srctree}/include/linux/aufs_type.h
18810+endif
4a4d8108
AM
18811+
18812+obj-$(CONFIG_AUFS_FS) += aufs.o
18813+aufs-y := module.o sbinfo.o super.o branch.o xino.o sysaufs.o opts.o \
18814+ wkq.o vfsub.o dcsub.o \
e49829fe 18815+ cpup.o whout.o wbr_policy.o \
4a4d8108
AM
18816+ dinfo.o dentry.o \
18817+ dynop.o \
18818+ finfo.o file.o f_op.o \
18819+ dir.o vdir.o \
18820+ iinfo.o inode.o i_op.o i_op_add.o i_op_del.o i_op_ren.o \
18821+ ioctl.o
18822+
18823+# all are boolean
e49829fe 18824+aufs-$(CONFIG_PROC_FS) += procfs.o plink.o
4a4d8108
AM
18825+aufs-$(CONFIG_SYSFS) += sysfs.o
18826+aufs-$(CONFIG_DEBUG_FS) += dbgaufs.o
18827+aufs-$(CONFIG_AUFS_BDEV_LOOP) += loop.o
18828+aufs-$(CONFIG_AUFS_HNOTIFY) += hnotify.o
18829+aufs-$(CONFIG_AUFS_HFSNOTIFY) += hfsnotify.o
4a4d8108
AM
18830+aufs-$(CONFIG_AUFS_EXPORT) += export.o
18831+aufs-$(CONFIG_AUFS_POLL) += poll.o
18832+aufs-$(CONFIG_AUFS_RDU) += rdu.o
18833+aufs-$(CONFIG_AUFS_SP_IATTR) += f_op_sp.o
18834+aufs-$(CONFIG_AUFS_BR_HFSPLUS) += hfsplus.o
18835+aufs-$(CONFIG_AUFS_DEBUG) += debug.o
18836+aufs-$(CONFIG_AUFS_MAGIC_SYSRQ) += sysrq.o
7f207e10
AM
18837diff -urN /usr/share/empty/fs/aufs/module.c linux/fs/aufs/module.c
18838--- /usr/share/empty/fs/aufs/module.c 1970-01-01 01:00:00.000000000 +0100
7ce627cf 18839+++ linux/fs/aufs/module.c 2012-05-22 09:06:08.870792417 +0200
7eafdf33 18840@@ -0,0 +1,196 @@
1facf9fc 18841+/*
f6c5ef8b 18842+ * Copyright (C) 2005-2012 Junjiro R. Okajima
1facf9fc 18843+ *
18844+ * This program, aufs is free software; you can redistribute it and/or modify
18845+ * it under the terms of the GNU General Public License as published by
18846+ * the Free Software Foundation; either version 2 of the License, or
18847+ * (at your option) any later version.
dece6358
AM
18848+ *
18849+ * This program is distributed in the hope that it will be useful,
18850+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
18851+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18852+ * GNU General Public License for more details.
18853+ *
18854+ * You should have received a copy of the GNU General Public License
18855+ * along with this program; if not, write to the Free Software
18856+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 18857+ */
18858+
18859+/*
18860+ * module global variables and operations
18861+ */
18862+
18863+#include <linux/module.h>
18864+#include <linux/seq_file.h>
18865+#include "aufs.h"
18866+
18867+void *au_kzrealloc(void *p, unsigned int nused, unsigned int new_sz, gfp_t gfp)
18868+{
18869+ if (new_sz <= nused)
18870+ return p;
18871+
18872+ p = krealloc(p, new_sz, gfp);
18873+ if (p)
18874+ memset(p + nused, 0, new_sz - nused);
18875+ return p;
18876+}
18877+
18878+/* ---------------------------------------------------------------------- */
18879+
18880+/*
18881+ * aufs caches
18882+ */
18883+struct kmem_cache *au_cachep[AuCache_Last];
18884+static int __init au_cache_init(void)
18885+{
4a4d8108 18886+ au_cachep[AuCache_DINFO] = AuCacheCtor(au_dinfo, au_di_init_once);
1facf9fc 18887+ if (au_cachep[AuCache_DINFO])
027c5e7a 18888+ /* SLAB_DESTROY_BY_RCU */
4a4d8108
AM
18889+ au_cachep[AuCache_ICNTNR] = AuCacheCtor(au_icntnr,
18890+ au_icntnr_init_once);
1facf9fc 18891+ if (au_cachep[AuCache_ICNTNR])
4a4d8108
AM
18892+ au_cachep[AuCache_FINFO] = AuCacheCtor(au_finfo,
18893+ au_fi_init_once);
1facf9fc 18894+ if (au_cachep[AuCache_FINFO])
18895+ au_cachep[AuCache_VDIR] = AuCache(au_vdir);
18896+ if (au_cachep[AuCache_VDIR])
18897+ au_cachep[AuCache_DEHSTR] = AuCache(au_vdir_dehstr);
18898+ if (au_cachep[AuCache_DEHSTR])
18899+ return 0;
18900+
18901+ return -ENOMEM;
18902+}
18903+
18904+static void au_cache_fin(void)
18905+{
18906+ int i;
4a4d8108 18907+
7eafdf33
AM
18908+ /* excluding AuCache_HNOTIFY */
18909+ BUILD_BUG_ON(AuCache_HNOTIFY + 1 != AuCache_Last);
18910+ for (i = 0; i < AuCache_HNOTIFY; i++)
1facf9fc 18911+ if (au_cachep[i]) {
18912+ kmem_cache_destroy(au_cachep[i]);
18913+ au_cachep[i] = NULL;
18914+ }
18915+}
18916+
18917+/* ---------------------------------------------------------------------- */
18918+
18919+int au_dir_roflags;
18920+
e49829fe 18921+#ifdef CONFIG_AUFS_SBILIST
1e00d052
AM
18922+/*
18923+ * iterate_supers_type() doesn't protect us from
18924+ * remounting (branch management)
18925+ */
e49829fe
JR
18926+struct au_splhead au_sbilist;
18927+#endif
18928+
9dbd164d
AM
18929+struct lock_class_key au_lc_key[AuLcKey_Last];
18930+
1facf9fc 18931+/*
18932+ * functions for module interface.
18933+ */
18934+MODULE_LICENSE("GPL");
18935+/* MODULE_LICENSE("GPL v2"); */
dece6358 18936+MODULE_AUTHOR("Junjiro R. Okajima <aufs-users@lists.sourceforge.net>");
1facf9fc 18937+MODULE_DESCRIPTION(AUFS_NAME
18938+ " -- Advanced multi layered unification filesystem");
18939+MODULE_VERSION(AUFS_VERSION);
18940+
1facf9fc 18941+/* this module parameter has no meaning when SYSFS is disabled */
18942+int sysaufs_brs = 1;
18943+MODULE_PARM_DESC(brs, "use <sysfs>/fs/aufs/si_*/brN");
18944+module_param_named(brs, sysaufs_brs, int, S_IRUGO);
18945+
18946+/* ---------------------------------------------------------------------- */
18947+
18948+static char au_esc_chars[0x20 + 3]; /* 0x01-0x20, backslash, del, and NULL */
18949+
18950+int au_seq_path(struct seq_file *seq, struct path *path)
18951+{
18952+ return seq_path(seq, path, au_esc_chars);
18953+}
18954+
18955+/* ---------------------------------------------------------------------- */
18956+
18957+static int __init aufs_init(void)
18958+{
18959+ int err, i;
18960+ char *p;
18961+
18962+ p = au_esc_chars;
18963+ for (i = 1; i <= ' '; i++)
18964+ *p++ = i;
18965+ *p++ = '\\';
18966+ *p++ = '\x7f';
18967+ *p = 0;
18968+
18969+ au_dir_roflags = au_file_roflags(O_DIRECTORY | O_LARGEFILE);
18970+
e49829fe 18971+ au_sbilist_init();
1facf9fc 18972+ sysaufs_brs_init();
18973+ au_debug_init();
4a4d8108 18974+ au_dy_init();
1facf9fc 18975+ err = sysaufs_init();
18976+ if (unlikely(err))
18977+ goto out;
e49829fe 18978+ err = au_procfs_init();
4f0767ce 18979+ if (unlikely(err))
953406b4 18980+ goto out_sysaufs;
e49829fe
JR
18981+ err = au_wkq_init();
18982+ if (unlikely(err))
18983+ goto out_procfs;
87a755f4 18984+ err = au_loopback_init();
1facf9fc 18985+ if (unlikely(err))
18986+ goto out_wkq;
87a755f4
AM
18987+ err = au_hnotify_init();
18988+ if (unlikely(err))
18989+ goto out_loopback;
1facf9fc 18990+ err = au_sysrq_init();
18991+ if (unlikely(err))
18992+ goto out_hin;
18993+ err = au_cache_init();
18994+ if (unlikely(err))
18995+ goto out_sysrq;
18996+ err = register_filesystem(&aufs_fs_type);
18997+ if (unlikely(err))
18998+ goto out_cache;
4a4d8108
AM
18999+ /* since we define pr_fmt, call printk directly */
19000+ printk(KERN_INFO AUFS_NAME " " AUFS_VERSION "\n");
1facf9fc 19001+ goto out; /* success */
19002+
4f0767ce 19003+out_cache:
1facf9fc 19004+ au_cache_fin();
4f0767ce 19005+out_sysrq:
1facf9fc 19006+ au_sysrq_fin();
4f0767ce 19007+out_hin:
4a4d8108 19008+ au_hnotify_fin();
87a755f4
AM
19009+out_loopback:
19010+ au_loopback_fin();
4f0767ce 19011+out_wkq:
1facf9fc 19012+ au_wkq_fin();
e49829fe
JR
19013+out_procfs:
19014+ au_procfs_fin();
4f0767ce 19015+out_sysaufs:
1facf9fc 19016+ sysaufs_fin();
4a4d8108 19017+ au_dy_fin();
4f0767ce 19018+out:
1facf9fc 19019+ return err;
19020+}
19021+
19022+static void __exit aufs_exit(void)
19023+{
19024+ unregister_filesystem(&aufs_fs_type);
19025+ au_cache_fin();
19026+ au_sysrq_fin();
4a4d8108 19027+ au_hnotify_fin();
87a755f4 19028+ au_loopback_fin();
1facf9fc 19029+ au_wkq_fin();
e49829fe 19030+ au_procfs_fin();
1facf9fc 19031+ sysaufs_fin();
4a4d8108 19032+ au_dy_fin();
1facf9fc 19033+}
19034+
19035+module_init(aufs_init);
19036+module_exit(aufs_exit);
7f207e10
AM
19037diff -urN /usr/share/empty/fs/aufs/module.h linux/fs/aufs/module.h
19038--- /usr/share/empty/fs/aufs/module.h 1970-01-01 01:00:00.000000000 +0100
7ce627cf 19039+++ linux/fs/aufs/module.h 2012-05-22 09:06:08.870792417 +0200
7eafdf33 19040@@ -0,0 +1,105 @@
1facf9fc 19041+/*
f6c5ef8b 19042+ * Copyright (C) 2005-2012 Junjiro R. Okajima
1facf9fc 19043+ *
19044+ * This program, aufs is free software; you can redistribute it and/or modify
19045+ * it under the terms of the GNU General Public License as published by
19046+ * the Free Software Foundation; either version 2 of the License, or
19047+ * (at your option) any later version.
dece6358
AM
19048+ *
19049+ * This program is distributed in the hope that it will be useful,
19050+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
19051+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19052+ * GNU General Public License for more details.
19053+ *
19054+ * You should have received a copy of the GNU General Public License
19055+ * along with this program; if not, write to the Free Software
19056+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 19057+ */
19058+
19059+/*
19060+ * module initialization and module-global
19061+ */
19062+
19063+#ifndef __AUFS_MODULE_H__
19064+#define __AUFS_MODULE_H__
19065+
19066+#ifdef __KERNEL__
19067+
19068+#include <linux/slab.h>
19069+
dece6358
AM
19070+struct path;
19071+struct seq_file;
19072+
1facf9fc 19073+/* module parameters */
1facf9fc 19074+extern int sysaufs_brs;
19075+
19076+/* ---------------------------------------------------------------------- */
19077+
19078+extern int au_dir_roflags;
19079+
9dbd164d
AM
19080+enum {
19081+ AuLcNonDir_FIINFO,
19082+ AuLcNonDir_DIINFO,
19083+ AuLcNonDir_IIINFO,
19084+
19085+ AuLcDir_FIINFO,
19086+ AuLcDir_DIINFO,
19087+ AuLcDir_IIINFO,
19088+
19089+ AuLcSymlink_DIINFO,
19090+ AuLcSymlink_IIINFO,
19091+
19092+ AuLcKey_Last
19093+};
19094+extern struct lock_class_key au_lc_key[AuLcKey_Last];
19095+
1facf9fc 19096+void *au_kzrealloc(void *p, unsigned int nused, unsigned int new_sz, gfp_t gfp);
19097+int au_seq_path(struct seq_file *seq, struct path *path);
19098+
e49829fe
JR
19099+#ifdef CONFIG_PROC_FS
19100+/* procfs.c */
19101+int __init au_procfs_init(void);
19102+void au_procfs_fin(void);
19103+#else
19104+AuStubInt0(au_procfs_init, void);
19105+AuStubVoid(au_procfs_fin, void);
19106+#endif
19107+
4f0767ce
JR
19108+/* ---------------------------------------------------------------------- */
19109+
19110+/* kmem cache */
1facf9fc 19111+enum {
19112+ AuCache_DINFO,
19113+ AuCache_ICNTNR,
19114+ AuCache_FINFO,
19115+ AuCache_VDIR,
19116+ AuCache_DEHSTR,
7eafdf33 19117+ AuCache_HNOTIFY, /* must be last */
1facf9fc 19118+ AuCache_Last
19119+};
19120+
4a4d8108
AM
19121+#define AuCacheFlags (SLAB_RECLAIM_ACCOUNT | SLAB_MEM_SPREAD)
19122+#define AuCache(type) KMEM_CACHE(type, AuCacheFlags)
19123+#define AuCacheCtor(type, ctor) \
19124+ kmem_cache_create(#type, sizeof(struct type), \
19125+ __alignof__(struct type), AuCacheFlags, ctor)
1facf9fc 19126+
19127+extern struct kmem_cache *au_cachep[];
19128+
19129+#define AuCacheFuncs(name, index) \
4a4d8108 19130+static inline struct au_##name *au_cache_alloc_##name(void) \
1facf9fc 19131+{ return kmem_cache_alloc(au_cachep[AuCache_##index], GFP_NOFS); } \
4a4d8108 19132+static inline void au_cache_free_##name(struct au_##name *p) \
1facf9fc 19133+{ kmem_cache_free(au_cachep[AuCache_##index], p); }
19134+
19135+AuCacheFuncs(dinfo, DINFO);
19136+AuCacheFuncs(icntnr, ICNTNR);
19137+AuCacheFuncs(finfo, FINFO);
19138+AuCacheFuncs(vdir, VDIR);
4a4d8108
AM
19139+AuCacheFuncs(vdir_dehstr, DEHSTR);
19140+#ifdef CONFIG_AUFS_HNOTIFY
19141+AuCacheFuncs(hnotify, HNOTIFY);
19142+#endif
1facf9fc 19143+
4a4d8108
AM
19144+#endif /* __KERNEL__ */
19145+#endif /* __AUFS_MODULE_H__ */
7f207e10
AM
19146diff -urN /usr/share/empty/fs/aufs/opts.c linux/fs/aufs/opts.c
19147--- /usr/share/empty/fs/aufs/opts.c 1970-01-01 01:00:00.000000000 +0100
7ce627cf 19148+++ linux/fs/aufs/opts.c 2012-05-22 09:06:08.870792417 +0200
f6c5ef8b 19149@@ -0,0 +1,1677 @@
1facf9fc 19150+/*
f6c5ef8b 19151+ * Copyright (C) 2005-2012 Junjiro R. Okajima
1facf9fc 19152+ *
19153+ * This program, aufs is free software; you can redistribute it and/or modify
19154+ * it under the terms of the GNU General Public License as published by
19155+ * the Free Software Foundation; either version 2 of the License, or
19156+ * (at your option) any later version.
dece6358
AM
19157+ *
19158+ * This program is distributed in the hope that it will be useful,
19159+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
19160+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19161+ * GNU General Public License for more details.
19162+ *
19163+ * You should have received a copy of the GNU General Public License
19164+ * along with this program; if not, write to the Free Software
19165+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 19166+ */
19167+
19168+/*
19169+ * mount options/flags
19170+ */
19171+
dece6358 19172+#include <linux/namei.h>
1facf9fc 19173+#include <linux/types.h> /* a distribution requires */
19174+#include <linux/parser.h>
19175+#include "aufs.h"
19176+
19177+/* ---------------------------------------------------------------------- */
19178+
19179+enum {
19180+ Opt_br,
19181+ Opt_add, Opt_del, Opt_mod, Opt_reorder, Opt_append, Opt_prepend,
19182+ Opt_idel, Opt_imod, Opt_ireorder,
19183+ Opt_dirwh, Opt_rdcache, Opt_rdblk, Opt_rdhash, Opt_rendir,
dece6358 19184+ Opt_rdblk_def, Opt_rdhash_def,
1facf9fc 19185+ Opt_xino, Opt_zxino, Opt_noxino,
19186+ Opt_trunc_xino, Opt_trunc_xino_v, Opt_notrunc_xino,
19187+ Opt_trunc_xino_path, Opt_itrunc_xino,
19188+ Opt_trunc_xib, Opt_notrunc_xib,
dece6358 19189+ Opt_shwh, Opt_noshwh,
1facf9fc 19190+ Opt_plink, Opt_noplink, Opt_list_plink,
19191+ Opt_udba,
4a4d8108 19192+ Opt_dio, Opt_nodio,
1facf9fc 19193+ /* Opt_lock, Opt_unlock, */
19194+ Opt_cmd, Opt_cmd_args,
19195+ Opt_diropq_a, Opt_diropq_w,
19196+ Opt_warn_perm, Opt_nowarn_perm,
19197+ Opt_wbr_copyup, Opt_wbr_create,
19198+ Opt_refrof, Opt_norefrof,
19199+ Opt_verbose, Opt_noverbose,
19200+ Opt_sum, Opt_nosum, Opt_wsum,
19201+ Opt_tail, Opt_ignore, Opt_ignore_silent, Opt_err
19202+};
19203+
19204+static match_table_t options = {
19205+ {Opt_br, "br=%s"},
19206+ {Opt_br, "br:%s"},
19207+
19208+ {Opt_add, "add=%d:%s"},
19209+ {Opt_add, "add:%d:%s"},
19210+ {Opt_add, "ins=%d:%s"},
19211+ {Opt_add, "ins:%d:%s"},
19212+ {Opt_append, "append=%s"},
19213+ {Opt_append, "append:%s"},
19214+ {Opt_prepend, "prepend=%s"},
19215+ {Opt_prepend, "prepend:%s"},
19216+
19217+ {Opt_del, "del=%s"},
19218+ {Opt_del, "del:%s"},
19219+ /* {Opt_idel, "idel:%d"}, */
19220+ {Opt_mod, "mod=%s"},
19221+ {Opt_mod, "mod:%s"},
19222+ /* {Opt_imod, "imod:%d:%s"}, */
19223+
19224+ {Opt_dirwh, "dirwh=%d"},
19225+
19226+ {Opt_xino, "xino=%s"},
19227+ {Opt_noxino, "noxino"},
19228+ {Opt_trunc_xino, "trunc_xino"},
19229+ {Opt_trunc_xino_v, "trunc_xino_v=%d:%d"},
19230+ {Opt_notrunc_xino, "notrunc_xino"},
19231+ {Opt_trunc_xino_path, "trunc_xino=%s"},
19232+ {Opt_itrunc_xino, "itrunc_xino=%d"},
19233+ /* {Opt_zxino, "zxino=%s"}, */
19234+ {Opt_trunc_xib, "trunc_xib"},
19235+ {Opt_notrunc_xib, "notrunc_xib"},
19236+
e49829fe 19237+#ifdef CONFIG_PROC_FS
1facf9fc 19238+ {Opt_plink, "plink"},
e49829fe
JR
19239+#else
19240+ {Opt_ignore_silent, "plink"},
19241+#endif
19242+
1facf9fc 19243+ {Opt_noplink, "noplink"},
e49829fe 19244+
1facf9fc 19245+#ifdef CONFIG_AUFS_DEBUG
19246+ {Opt_list_plink, "list_plink"},
19247+#endif
19248+
19249+ {Opt_udba, "udba=%s"},
19250+
4a4d8108
AM
19251+ {Opt_dio, "dio"},
19252+ {Opt_nodio, "nodio"},
19253+
1facf9fc 19254+ {Opt_diropq_a, "diropq=always"},
19255+ {Opt_diropq_a, "diropq=a"},
19256+ {Opt_diropq_w, "diropq=whiteouted"},
19257+ {Opt_diropq_w, "diropq=w"},
19258+
19259+ {Opt_warn_perm, "warn_perm"},
19260+ {Opt_nowarn_perm, "nowarn_perm"},
19261+
19262+ /* keep them temporary */
19263+ {Opt_ignore_silent, "coo=%s"},
19264+ {Opt_ignore_silent, "nodlgt"},
19265+ {Opt_ignore_silent, "nodirperm1"},
1facf9fc 19266+ {Opt_ignore_silent, "clean_plink"},
19267+
dece6358
AM
19268+#ifdef CONFIG_AUFS_SHWH
19269+ {Opt_shwh, "shwh"},
19270+#endif
19271+ {Opt_noshwh, "noshwh"},
19272+
1facf9fc 19273+ {Opt_rendir, "rendir=%d"},
19274+
19275+ {Opt_refrof, "refrof"},
19276+ {Opt_norefrof, "norefrof"},
19277+
19278+ {Opt_verbose, "verbose"},
19279+ {Opt_verbose, "v"},
19280+ {Opt_noverbose, "noverbose"},
19281+ {Opt_noverbose, "quiet"},
19282+ {Opt_noverbose, "q"},
19283+ {Opt_noverbose, "silent"},
19284+
19285+ {Opt_sum, "sum"},
19286+ {Opt_nosum, "nosum"},
19287+ {Opt_wsum, "wsum"},
19288+
19289+ {Opt_rdcache, "rdcache=%d"},
19290+ {Opt_rdblk, "rdblk=%d"},
dece6358 19291+ {Opt_rdblk_def, "rdblk=def"},
1facf9fc 19292+ {Opt_rdhash, "rdhash=%d"},
dece6358 19293+ {Opt_rdhash_def, "rdhash=def"},
1facf9fc 19294+
19295+ {Opt_wbr_create, "create=%s"},
19296+ {Opt_wbr_create, "create_policy=%s"},
19297+ {Opt_wbr_copyup, "cpup=%s"},
19298+ {Opt_wbr_copyup, "copyup=%s"},
19299+ {Opt_wbr_copyup, "copyup_policy=%s"},
19300+
19301+ /* internal use for the scripts */
19302+ {Opt_ignore_silent, "si=%s"},
19303+
19304+ {Opt_br, "dirs=%s"},
19305+ {Opt_ignore, "debug=%d"},
19306+ {Opt_ignore, "delete=whiteout"},
19307+ {Opt_ignore, "delete=all"},
19308+ {Opt_ignore, "imap=%s"},
19309+
1308ab2a 19310+ /* temporary workaround, due to old mount(8)? */
19311+ {Opt_ignore_silent, "relatime"},
19312+
1facf9fc 19313+ {Opt_err, NULL}
19314+};
19315+
19316+/* ---------------------------------------------------------------------- */
19317+
19318+static const char *au_parser_pattern(int val, struct match_token *token)
19319+{
19320+ while (token->pattern) {
19321+ if (token->token == val)
19322+ return token->pattern;
19323+ token++;
19324+ }
19325+ BUG();
19326+ return "??";
19327+}
19328+
19329+/* ---------------------------------------------------------------------- */
19330+
1e00d052 19331+static match_table_t brperm = {
1facf9fc 19332+ {AuBrPerm_RO, AUFS_BRPERM_RO},
19333+ {AuBrPerm_RR, AUFS_BRPERM_RR},
19334+ {AuBrPerm_RW, AUFS_BRPERM_RW},
1e00d052
AM
19335+ {0, NULL}
19336+};
1facf9fc 19337+
1e00d052
AM
19338+static match_table_t brrattr = {
19339+ {AuBrRAttr_WH, AUFS_BRRATTR_WH},
19340+ {0, NULL}
19341+};
1facf9fc 19342+
1e00d052
AM
19343+static match_table_t brwattr = {
19344+ {AuBrWAttr_NoLinkWH, AUFS_BRWATTR_NLWH},
19345+ {0, NULL}
1facf9fc 19346+};
19347+
1e00d052
AM
19348+#define AuBrStr_LONGEST AUFS_BRPERM_RW "+" AUFS_BRWATTR_NLWH
19349+
19350+static int br_attr_val(char *str, match_table_t table, substring_t args[])
19351+{
19352+ int attr, v;
19353+ char *p;
19354+
19355+ attr = 0;
19356+ do {
19357+ p = strchr(str, '+');
19358+ if (p)
19359+ *p = 0;
19360+ v = match_token(str, table, args);
19361+ if (v)
19362+ attr |= v;
19363+ else {
19364+ if (p)
19365+ *p = '+';
19366+ pr_warning("ignored branch attribute %s\n", str);
19367+ break;
19368+ }
19369+ if (p)
19370+ str = p + 1;
19371+ } while (p);
19372+
19373+ return attr;
19374+}
19375+
4a4d8108 19376+static int noinline_for_stack br_perm_val(char *perm)
1facf9fc 19377+{
19378+ int val;
1e00d052 19379+ char *p;
1facf9fc 19380+ substring_t args[MAX_OPT_ARGS];
19381+
1e00d052
AM
19382+ p = strchr(perm, '+');
19383+ if (p)
19384+ *p = 0;
19385+ val = match_token(perm, brperm, args);
19386+ if (!val) {
19387+ if (p)
19388+ *p = '+';
19389+ pr_warning("ignored branch permission %s\n", perm);
19390+ val = AuBrPerm_RO;
19391+ goto out;
19392+ }
19393+ if (!p)
19394+ goto out;
19395+
19396+ switch (val) {
19397+ case AuBrPerm_RO:
19398+ case AuBrPerm_RR:
19399+ val |= br_attr_val(p + 1, brrattr, args);
19400+ break;
19401+ case AuBrPerm_RW:
19402+ val |= br_attr_val(p + 1, brwattr, args);
19403+ break;
19404+ }
19405+
19406+out:
1facf9fc 19407+ return val;
19408+}
19409+
1e00d052
AM
19410+/* Caller should free the return value */
19411+char *au_optstr_br_perm(int brperm)
1facf9fc 19412+{
1e00d052
AM
19413+ char *p, a[sizeof(AuBrStr_LONGEST)];
19414+ int sz;
19415+
19416+#define SetPerm(str) do { \
19417+ sz = sizeof(str); \
19418+ memcpy(a, str, sz); \
19419+ p = a + sz - 1; \
19420+ } while (0)
19421+
19422+#define AppendAttr(flag, str) do { \
19423+ if (brperm & flag) { \
19424+ sz = sizeof(str); \
19425+ *p++ = '+'; \
19426+ memcpy(p, str, sz); \
19427+ p += sz - 1; \
19428+ } \
19429+ } while (0)
19430+
19431+ switch (brperm & AuBrPerm_Mask) {
19432+ case AuBrPerm_RO:
19433+ SetPerm(AUFS_BRPERM_RO);
19434+ break;
19435+ case AuBrPerm_RR:
19436+ SetPerm(AUFS_BRPERM_RR);
19437+ break;
19438+ case AuBrPerm_RW:
19439+ SetPerm(AUFS_BRPERM_RW);
19440+ break;
19441+ default:
19442+ AuDebugOn(1);
19443+ }
19444+
19445+ AppendAttr(AuBrRAttr_WH, AUFS_BRRATTR_WH);
19446+ AppendAttr(AuBrWAttr_NoLinkWH, AUFS_BRWATTR_NLWH);
19447+
19448+ AuDebugOn(strlen(a) >= sizeof(a));
19449+ return kstrdup(a, GFP_NOFS);
19450+#undef SetPerm
19451+#undef AppendAttr
1facf9fc 19452+}
19453+
19454+/* ---------------------------------------------------------------------- */
19455+
19456+static match_table_t udbalevel = {
19457+ {AuOpt_UDBA_REVAL, "reval"},
19458+ {AuOpt_UDBA_NONE, "none"},
4a4d8108
AM
19459+#ifdef CONFIG_AUFS_HNOTIFY
19460+ {AuOpt_UDBA_HNOTIFY, "notify"}, /* abstraction */
19461+#ifdef CONFIG_AUFS_HFSNOTIFY
19462+ {AuOpt_UDBA_HNOTIFY, "fsnotify"},
4a4d8108 19463+#endif
1facf9fc 19464+#endif
19465+ {-1, NULL}
19466+};
19467+
4a4d8108 19468+static int noinline_for_stack udba_val(char *str)
1facf9fc 19469+{
19470+ substring_t args[MAX_OPT_ARGS];
19471+
7f207e10 19472+ return match_token(str, udbalevel, args);
1facf9fc 19473+}
19474+
19475+const char *au_optstr_udba(int udba)
19476+{
19477+ return au_parser_pattern(udba, (void *)udbalevel);
19478+}
19479+
19480+/* ---------------------------------------------------------------------- */
19481+
19482+static match_table_t au_wbr_create_policy = {
19483+ {AuWbrCreate_TDP, "tdp"},
19484+ {AuWbrCreate_TDP, "top-down-parent"},
19485+ {AuWbrCreate_RR, "rr"},
19486+ {AuWbrCreate_RR, "round-robin"},
19487+ {AuWbrCreate_MFS, "mfs"},
19488+ {AuWbrCreate_MFS, "most-free-space"},
19489+ {AuWbrCreate_MFSV, "mfs:%d"},
19490+ {AuWbrCreate_MFSV, "most-free-space:%d"},
19491+
19492+ {AuWbrCreate_MFSRR, "mfsrr:%d"},
19493+ {AuWbrCreate_MFSRRV, "mfsrr:%d:%d"},
19494+ {AuWbrCreate_PMFS, "pmfs"},
19495+ {AuWbrCreate_PMFSV, "pmfs:%d"},
19496+
19497+ {-1, NULL}
19498+};
19499+
dece6358
AM
19500+/*
19501+ * cf. linux/lib/parser.c and cmdline.c
19502+ * gave up calling memparse() since it uses simple_strtoull() instead of
9dbd164d 19503+ * kstrto...().
dece6358 19504+ */
4a4d8108
AM
19505+static int noinline_for_stack
19506+au_match_ull(substring_t *s, unsigned long long *result)
1facf9fc 19507+{
19508+ int err;
19509+ unsigned int len;
19510+ char a[32];
19511+
19512+ err = -ERANGE;
19513+ len = s->to - s->from;
19514+ if (len + 1 <= sizeof(a)) {
19515+ memcpy(a, s->from, len);
19516+ a[len] = '\0';
9dbd164d 19517+ err = kstrtoull(a, 0, result);
1facf9fc 19518+ }
19519+ return err;
19520+}
19521+
19522+static int au_wbr_mfs_wmark(substring_t *arg, char *str,
19523+ struct au_opt_wbr_create *create)
19524+{
19525+ int err;
19526+ unsigned long long ull;
19527+
19528+ err = 0;
19529+ if (!au_match_ull(arg, &ull))
19530+ create->mfsrr_watermark = ull;
19531+ else {
4a4d8108 19532+ pr_err("bad integer in %s\n", str);
1facf9fc 19533+ err = -EINVAL;
19534+ }
19535+
19536+ return err;
19537+}
19538+
19539+static int au_wbr_mfs_sec(substring_t *arg, char *str,
19540+ struct au_opt_wbr_create *create)
19541+{
19542+ int n, err;
19543+
19544+ err = 0;
027c5e7a 19545+ if (!match_int(arg, &n) && 0 <= n && n <= AUFS_MFS_MAX_SEC)
1facf9fc 19546+ create->mfs_second = n;
19547+ else {
4a4d8108 19548+ pr_err("bad integer in %s\n", str);
1facf9fc 19549+ err = -EINVAL;
19550+ }
19551+
19552+ return err;
19553+}
19554+
4a4d8108
AM
19555+static int noinline_for_stack
19556+au_wbr_create_val(char *str, struct au_opt_wbr_create *create)
1facf9fc 19557+{
19558+ int err, e;
19559+ substring_t args[MAX_OPT_ARGS];
19560+
19561+ err = match_token(str, au_wbr_create_policy, args);
19562+ create->wbr_create = err;
19563+ switch (err) {
19564+ case AuWbrCreate_MFSRRV:
19565+ e = au_wbr_mfs_wmark(&args[0], str, create);
19566+ if (!e)
19567+ e = au_wbr_mfs_sec(&args[1], str, create);
19568+ if (unlikely(e))
19569+ err = e;
19570+ break;
19571+ case AuWbrCreate_MFSRR:
19572+ e = au_wbr_mfs_wmark(&args[0], str, create);
19573+ if (unlikely(e)) {
19574+ err = e;
19575+ break;
19576+ }
19577+ /*FALLTHROUGH*/
19578+ case AuWbrCreate_MFS:
19579+ case AuWbrCreate_PMFS:
027c5e7a 19580+ create->mfs_second = AUFS_MFS_DEF_SEC;
1facf9fc 19581+ break;
19582+ case AuWbrCreate_MFSV:
19583+ case AuWbrCreate_PMFSV:
19584+ e = au_wbr_mfs_sec(&args[0], str, create);
19585+ if (unlikely(e))
19586+ err = e;
19587+ break;
19588+ }
19589+
19590+ return err;
19591+}
19592+
19593+const char *au_optstr_wbr_create(int wbr_create)
19594+{
19595+ return au_parser_pattern(wbr_create, (void *)au_wbr_create_policy);
19596+}
19597+
19598+static match_table_t au_wbr_copyup_policy = {
19599+ {AuWbrCopyup_TDP, "tdp"},
19600+ {AuWbrCopyup_TDP, "top-down-parent"},
19601+ {AuWbrCopyup_BUP, "bup"},
19602+ {AuWbrCopyup_BUP, "bottom-up-parent"},
19603+ {AuWbrCopyup_BU, "bu"},
19604+ {AuWbrCopyup_BU, "bottom-up"},
19605+ {-1, NULL}
19606+};
19607+
4a4d8108 19608+static int noinline_for_stack au_wbr_copyup_val(char *str)
1facf9fc 19609+{
19610+ substring_t args[MAX_OPT_ARGS];
19611+
19612+ return match_token(str, au_wbr_copyup_policy, args);
19613+}
19614+
19615+const char *au_optstr_wbr_copyup(int wbr_copyup)
19616+{
19617+ return au_parser_pattern(wbr_copyup, (void *)au_wbr_copyup_policy);
19618+}
19619+
19620+/* ---------------------------------------------------------------------- */
19621+
19622+static const int lkup_dirflags = LOOKUP_FOLLOW | LOOKUP_DIRECTORY;
19623+
19624+static void dump_opts(struct au_opts *opts)
19625+{
19626+#ifdef CONFIG_AUFS_DEBUG
19627+ /* reduce stack space */
19628+ union {
19629+ struct au_opt_add *add;
19630+ struct au_opt_del *del;
19631+ struct au_opt_mod *mod;
19632+ struct au_opt_xino *xino;
19633+ struct au_opt_xino_itrunc *xino_itrunc;
19634+ struct au_opt_wbr_create *create;
19635+ } u;
19636+ struct au_opt *opt;
19637+
19638+ opt = opts->opt;
19639+ while (opt->type != Opt_tail) {
19640+ switch (opt->type) {
19641+ case Opt_add:
19642+ u.add = &opt->add;
19643+ AuDbg("add {b%d, %s, 0x%x, %p}\n",
19644+ u.add->bindex, u.add->pathname, u.add->perm,
19645+ u.add->path.dentry);
19646+ break;
19647+ case Opt_del:
19648+ case Opt_idel:
19649+ u.del = &opt->del;
19650+ AuDbg("del {%s, %p}\n",
19651+ u.del->pathname, u.del->h_path.dentry);
19652+ break;
19653+ case Opt_mod:
19654+ case Opt_imod:
19655+ u.mod = &opt->mod;
19656+ AuDbg("mod {%s, 0x%x, %p}\n",
19657+ u.mod->path, u.mod->perm, u.mod->h_root);
19658+ break;
19659+ case Opt_append:
19660+ u.add = &opt->add;
19661+ AuDbg("append {b%d, %s, 0x%x, %p}\n",
19662+ u.add->bindex, u.add->pathname, u.add->perm,
19663+ u.add->path.dentry);
19664+ break;
19665+ case Opt_prepend:
19666+ u.add = &opt->add;
19667+ AuDbg("prepend {b%d, %s, 0x%x, %p}\n",
19668+ u.add->bindex, u.add->pathname, u.add->perm,
19669+ u.add->path.dentry);
19670+ break;
19671+ case Opt_dirwh:
19672+ AuDbg("dirwh %d\n", opt->dirwh);
19673+ break;
19674+ case Opt_rdcache:
19675+ AuDbg("rdcache %d\n", opt->rdcache);
19676+ break;
19677+ case Opt_rdblk:
19678+ AuDbg("rdblk %u\n", opt->rdblk);
19679+ break;
dece6358
AM
19680+ case Opt_rdblk_def:
19681+ AuDbg("rdblk_def\n");
19682+ break;
1facf9fc 19683+ case Opt_rdhash:
19684+ AuDbg("rdhash %u\n", opt->rdhash);
19685+ break;
dece6358
AM
19686+ case Opt_rdhash_def:
19687+ AuDbg("rdhash_def\n");
19688+ break;
1facf9fc 19689+ case Opt_xino:
19690+ u.xino = &opt->xino;
19691+ AuDbg("xino {%s %.*s}\n",
19692+ u.xino->path,
19693+ AuDLNPair(u.xino->file->f_dentry));
19694+ break;
19695+ case Opt_trunc_xino:
19696+ AuLabel(trunc_xino);
19697+ break;
19698+ case Opt_notrunc_xino:
19699+ AuLabel(notrunc_xino);
19700+ break;
19701+ case Opt_trunc_xino_path:
19702+ case Opt_itrunc_xino:
19703+ u.xino_itrunc = &opt->xino_itrunc;
19704+ AuDbg("trunc_xino %d\n", u.xino_itrunc->bindex);
19705+ break;
19706+
19707+ case Opt_noxino:
19708+ AuLabel(noxino);
19709+ break;
19710+ case Opt_trunc_xib:
19711+ AuLabel(trunc_xib);
19712+ break;
19713+ case Opt_notrunc_xib:
19714+ AuLabel(notrunc_xib);
19715+ break;
dece6358
AM
19716+ case Opt_shwh:
19717+ AuLabel(shwh);
19718+ break;
19719+ case Opt_noshwh:
19720+ AuLabel(noshwh);
19721+ break;
1facf9fc 19722+ case Opt_plink:
19723+ AuLabel(plink);
19724+ break;
19725+ case Opt_noplink:
19726+ AuLabel(noplink);
19727+ break;
19728+ case Opt_list_plink:
19729+ AuLabel(list_plink);
19730+ break;
19731+ case Opt_udba:
19732+ AuDbg("udba %d, %s\n",
19733+ opt->udba, au_optstr_udba(opt->udba));
19734+ break;
4a4d8108
AM
19735+ case Opt_dio:
19736+ AuLabel(dio);
19737+ break;
19738+ case Opt_nodio:
19739+ AuLabel(nodio);
19740+ break;
1facf9fc 19741+ case Opt_diropq_a:
19742+ AuLabel(diropq_a);
19743+ break;
19744+ case Opt_diropq_w:
19745+ AuLabel(diropq_w);
19746+ break;
19747+ case Opt_warn_perm:
19748+ AuLabel(warn_perm);
19749+ break;
19750+ case Opt_nowarn_perm:
19751+ AuLabel(nowarn_perm);
19752+ break;
19753+ case Opt_refrof:
19754+ AuLabel(refrof);
19755+ break;
19756+ case Opt_norefrof:
19757+ AuLabel(norefrof);
19758+ break;
19759+ case Opt_verbose:
19760+ AuLabel(verbose);
19761+ break;
19762+ case Opt_noverbose:
19763+ AuLabel(noverbose);
19764+ break;
19765+ case Opt_sum:
19766+ AuLabel(sum);
19767+ break;
19768+ case Opt_nosum:
19769+ AuLabel(nosum);
19770+ break;
19771+ case Opt_wsum:
19772+ AuLabel(wsum);
19773+ break;
19774+ case Opt_wbr_create:
19775+ u.create = &opt->wbr_create;
19776+ AuDbg("create %d, %s\n", u.create->wbr_create,
19777+ au_optstr_wbr_create(u.create->wbr_create));
19778+ switch (u.create->wbr_create) {
19779+ case AuWbrCreate_MFSV:
19780+ case AuWbrCreate_PMFSV:
19781+ AuDbg("%d sec\n", u.create->mfs_second);
19782+ break;
19783+ case AuWbrCreate_MFSRR:
19784+ AuDbg("%llu watermark\n",
19785+ u.create->mfsrr_watermark);
19786+ break;
19787+ case AuWbrCreate_MFSRRV:
19788+ AuDbg("%llu watermark, %d sec\n",
19789+ u.create->mfsrr_watermark,
19790+ u.create->mfs_second);
19791+ break;
19792+ }
19793+ break;
19794+ case Opt_wbr_copyup:
19795+ AuDbg("copyup %d, %s\n", opt->wbr_copyup,
19796+ au_optstr_wbr_copyup(opt->wbr_copyup));
19797+ break;
19798+ default:
19799+ BUG();
19800+ }
19801+ opt++;
19802+ }
19803+#endif
19804+}
19805+
19806+void au_opts_free(struct au_opts *opts)
19807+{
19808+ struct au_opt *opt;
19809+
19810+ opt = opts->opt;
19811+ while (opt->type != Opt_tail) {
19812+ switch (opt->type) {
19813+ case Opt_add:
19814+ case Opt_append:
19815+ case Opt_prepend:
19816+ path_put(&opt->add.path);
19817+ break;
19818+ case Opt_del:
19819+ case Opt_idel:
19820+ path_put(&opt->del.h_path);
19821+ break;
19822+ case Opt_mod:
19823+ case Opt_imod:
19824+ dput(opt->mod.h_root);
19825+ break;
19826+ case Opt_xino:
19827+ fput(opt->xino.file);
19828+ break;
19829+ }
19830+ opt++;
19831+ }
19832+}
19833+
19834+static int opt_add(struct au_opt *opt, char *opt_str, unsigned long sb_flags,
19835+ aufs_bindex_t bindex)
19836+{
19837+ int err;
19838+ struct au_opt_add *add = &opt->add;
19839+ char *p;
19840+
19841+ add->bindex = bindex;
1e00d052 19842+ add->perm = AuBrPerm_RO;
1facf9fc 19843+ add->pathname = opt_str;
19844+ p = strchr(opt_str, '=');
19845+ if (p) {
19846+ *p++ = 0;
19847+ if (*p)
19848+ add->perm = br_perm_val(p);
19849+ }
19850+
19851+ err = vfsub_kern_path(add->pathname, lkup_dirflags, &add->path);
19852+ if (!err) {
19853+ if (!p) {
19854+ add->perm = AuBrPerm_RO;
19855+ if (au_test_fs_rr(add->path.dentry->d_sb))
19856+ add->perm = AuBrPerm_RR;
19857+ else if (!bindex && !(sb_flags & MS_RDONLY))
19858+ add->perm = AuBrPerm_RW;
19859+ }
19860+ opt->type = Opt_add;
19861+ goto out;
19862+ }
4a4d8108 19863+ pr_err("lookup failed %s (%d)\n", add->pathname, err);
1facf9fc 19864+ err = -EINVAL;
19865+
4f0767ce 19866+out:
1facf9fc 19867+ return err;
19868+}
19869+
19870+static int au_opts_parse_del(struct au_opt_del *del, substring_t args[])
19871+{
19872+ int err;
19873+
19874+ del->pathname = args[0].from;
19875+ AuDbg("del path %s\n", del->pathname);
19876+
19877+ err = vfsub_kern_path(del->pathname, lkup_dirflags, &del->h_path);
19878+ if (unlikely(err))
4a4d8108 19879+ pr_err("lookup failed %s (%d)\n", del->pathname, err);
1facf9fc 19880+
19881+ return err;
19882+}
19883+
19884+#if 0 /* reserved for future use */
19885+static int au_opts_parse_idel(struct super_block *sb, aufs_bindex_t bindex,
19886+ struct au_opt_del *del, substring_t args[])
19887+{
19888+ int err;
19889+ struct dentry *root;
19890+
19891+ err = -EINVAL;
19892+ root = sb->s_root;
19893+ aufs_read_lock(root, AuLock_FLUSH);
19894+ if (bindex < 0 || au_sbend(sb) < bindex) {
4a4d8108 19895+ pr_err("out of bounds, %d\n", bindex);
1facf9fc 19896+ goto out;
19897+ }
19898+
19899+ err = 0;
19900+ del->h_path.dentry = dget(au_h_dptr(root, bindex));
19901+ del->h_path.mnt = mntget(au_sbr_mnt(sb, bindex));
19902+
4f0767ce 19903+out:
1facf9fc 19904+ aufs_read_unlock(root, !AuLock_IR);
19905+ return err;
19906+}
19907+#endif
19908+
4a4d8108
AM
19909+static int noinline_for_stack
19910+au_opts_parse_mod(struct au_opt_mod *mod, substring_t args[])
1facf9fc 19911+{
19912+ int err;
19913+ struct path path;
19914+ char *p;
19915+
19916+ err = -EINVAL;
19917+ mod->path = args[0].from;
19918+ p = strchr(mod->path, '=');
19919+ if (unlikely(!p)) {
4a4d8108 19920+ pr_err("no permssion %s\n", args[0].from);
1facf9fc 19921+ goto out;
19922+ }
19923+
19924+ *p++ = 0;
19925+ err = vfsub_kern_path(mod->path, lkup_dirflags, &path);
19926+ if (unlikely(err)) {
4a4d8108 19927+ pr_err("lookup failed %s (%d)\n", mod->path, err);
1facf9fc 19928+ goto out;
19929+ }
19930+
19931+ mod->perm = br_perm_val(p);
19932+ AuDbg("mod path %s, perm 0x%x, %s\n", mod->path, mod->perm, p);
19933+ mod->h_root = dget(path.dentry);
19934+ path_put(&path);
19935+
4f0767ce 19936+out:
1facf9fc 19937+ return err;
19938+}
19939+
19940+#if 0 /* reserved for future use */
19941+static int au_opts_parse_imod(struct super_block *sb, aufs_bindex_t bindex,
19942+ struct au_opt_mod *mod, substring_t args[])
19943+{
19944+ int err;
19945+ struct dentry *root;
19946+
19947+ err = -EINVAL;
19948+ root = sb->s_root;
19949+ aufs_read_lock(root, AuLock_FLUSH);
19950+ if (bindex < 0 || au_sbend(sb) < bindex) {
4a4d8108 19951+ pr_err("out of bounds, %d\n", bindex);
1facf9fc 19952+ goto out;
19953+ }
19954+
19955+ err = 0;
19956+ mod->perm = br_perm_val(args[1].from);
19957+ AuDbg("mod path %s, perm 0x%x, %s\n",
19958+ mod->path, mod->perm, args[1].from);
19959+ mod->h_root = dget(au_h_dptr(root, bindex));
19960+
4f0767ce 19961+out:
1facf9fc 19962+ aufs_read_unlock(root, !AuLock_IR);
19963+ return err;
19964+}
19965+#endif
19966+
19967+static int au_opts_parse_xino(struct super_block *sb, struct au_opt_xino *xino,
19968+ substring_t args[])
19969+{
19970+ int err;
19971+ struct file *file;
19972+
19973+ file = au_xino_create(sb, args[0].from, /*silent*/0);
19974+ err = PTR_ERR(file);
19975+ if (IS_ERR(file))
19976+ goto out;
19977+
19978+ err = -EINVAL;
19979+ if (unlikely(file->f_dentry->d_sb == sb)) {
19980+ fput(file);
4a4d8108 19981+ pr_err("%s must be outside\n", args[0].from);
1facf9fc 19982+ goto out;
19983+ }
19984+
19985+ err = 0;
19986+ xino->file = file;
19987+ xino->path = args[0].from;
19988+
4f0767ce 19989+out:
1facf9fc 19990+ return err;
19991+}
19992+
4a4d8108
AM
19993+static int noinline_for_stack
19994+au_opts_parse_xino_itrunc_path(struct super_block *sb,
19995+ struct au_opt_xino_itrunc *xino_itrunc,
19996+ substring_t args[])
1facf9fc 19997+{
19998+ int err;
19999+ aufs_bindex_t bend, bindex;
20000+ struct path path;
20001+ struct dentry *root;
20002+
20003+ err = vfsub_kern_path(args[0].from, lkup_dirflags, &path);
20004+ if (unlikely(err)) {
4a4d8108 20005+ pr_err("lookup failed %s (%d)\n", args[0].from, err);
1facf9fc 20006+ goto out;
20007+ }
20008+
20009+ xino_itrunc->bindex = -1;
20010+ root = sb->s_root;
20011+ aufs_read_lock(root, AuLock_FLUSH);
20012+ bend = au_sbend(sb);
20013+ for (bindex = 0; bindex <= bend; bindex++) {
20014+ if (au_h_dptr(root, bindex) == path.dentry) {
20015+ xino_itrunc->bindex = bindex;
20016+ break;
20017+ }
20018+ }
20019+ aufs_read_unlock(root, !AuLock_IR);
20020+ path_put(&path);
20021+
20022+ if (unlikely(xino_itrunc->bindex < 0)) {
4a4d8108 20023+ pr_err("no such branch %s\n", args[0].from);
1facf9fc 20024+ err = -EINVAL;
20025+ }
20026+
4f0767ce 20027+out:
1facf9fc 20028+ return err;
20029+}
20030+
20031+/* called without aufs lock */
20032+int au_opts_parse(struct super_block *sb, char *str, struct au_opts *opts)
20033+{
20034+ int err, n, token;
20035+ aufs_bindex_t bindex;
20036+ unsigned char skipped;
20037+ struct dentry *root;
20038+ struct au_opt *opt, *opt_tail;
20039+ char *opt_str;
20040+ /* reduce the stack space */
20041+ union {
20042+ struct au_opt_xino_itrunc *xino_itrunc;
20043+ struct au_opt_wbr_create *create;
20044+ } u;
20045+ struct {
20046+ substring_t args[MAX_OPT_ARGS];
20047+ } *a;
20048+
20049+ err = -ENOMEM;
20050+ a = kmalloc(sizeof(*a), GFP_NOFS);
20051+ if (unlikely(!a))
20052+ goto out;
20053+
20054+ root = sb->s_root;
20055+ err = 0;
20056+ bindex = 0;
20057+ opt = opts->opt;
20058+ opt_tail = opt + opts->max_opt - 1;
20059+ opt->type = Opt_tail;
20060+ while (!err && (opt_str = strsep(&str, ",")) && *opt_str) {
20061+ err = -EINVAL;
20062+ skipped = 0;
20063+ token = match_token(opt_str, options, a->args);
20064+ switch (token) {
20065+ case Opt_br:
20066+ err = 0;
20067+ while (!err && (opt_str = strsep(&a->args[0].from, ":"))
20068+ && *opt_str) {
20069+ err = opt_add(opt, opt_str, opts->sb_flags,
20070+ bindex++);
20071+ if (unlikely(!err && ++opt > opt_tail)) {
20072+ err = -E2BIG;
20073+ break;
20074+ }
20075+ opt->type = Opt_tail;
20076+ skipped = 1;
20077+ }
20078+ break;
20079+ case Opt_add:
20080+ if (unlikely(match_int(&a->args[0], &n))) {
4a4d8108 20081+ pr_err("bad integer in %s\n", opt_str);
1facf9fc 20082+ break;
20083+ }
20084+ bindex = n;
20085+ err = opt_add(opt, a->args[1].from, opts->sb_flags,
20086+ bindex);
20087+ if (!err)
20088+ opt->type = token;
20089+ break;
20090+ case Opt_append:
20091+ err = opt_add(opt, a->args[0].from, opts->sb_flags,
20092+ /*dummy bindex*/1);
20093+ if (!err)
20094+ opt->type = token;
20095+ break;
20096+ case Opt_prepend:
20097+ err = opt_add(opt, a->args[0].from, opts->sb_flags,
20098+ /*bindex*/0);
20099+ if (!err)
20100+ opt->type = token;
20101+ break;
20102+ case Opt_del:
20103+ err = au_opts_parse_del(&opt->del, a->args);
20104+ if (!err)
20105+ opt->type = token;
20106+ break;
20107+#if 0 /* reserved for future use */
20108+ case Opt_idel:
20109+ del->pathname = "(indexed)";
20110+ if (unlikely(match_int(&args[0], &n))) {
4a4d8108 20111+ pr_err("bad integer in %s\n", opt_str);
1facf9fc 20112+ break;
20113+ }
20114+ err = au_opts_parse_idel(sb, n, &opt->del, a->args);
20115+ if (!err)
20116+ opt->type = token;
20117+ break;
20118+#endif
20119+ case Opt_mod:
20120+ err = au_opts_parse_mod(&opt->mod, a->args);
20121+ if (!err)
20122+ opt->type = token;
20123+ break;
20124+#ifdef IMOD /* reserved for future use */
20125+ case Opt_imod:
20126+ u.mod->path = "(indexed)";
20127+ if (unlikely(match_int(&a->args[0], &n))) {
4a4d8108 20128+ pr_err("bad integer in %s\n", opt_str);
1facf9fc 20129+ break;
20130+ }
20131+ err = au_opts_parse_imod(sb, n, &opt->mod, a->args);
20132+ if (!err)
20133+ opt->type = token;
20134+ break;
20135+#endif
20136+ case Opt_xino:
20137+ err = au_opts_parse_xino(sb, &opt->xino, a->args);
20138+ if (!err)
20139+ opt->type = token;
20140+ break;
20141+
20142+ case Opt_trunc_xino_path:
20143+ err = au_opts_parse_xino_itrunc_path
20144+ (sb, &opt->xino_itrunc, a->args);
20145+ if (!err)
20146+ opt->type = token;
20147+ break;
20148+
20149+ case Opt_itrunc_xino:
20150+ u.xino_itrunc = &opt->xino_itrunc;
20151+ if (unlikely(match_int(&a->args[0], &n))) {
4a4d8108 20152+ pr_err("bad integer in %s\n", opt_str);
1facf9fc 20153+ break;
20154+ }
20155+ u.xino_itrunc->bindex = n;
20156+ aufs_read_lock(root, AuLock_FLUSH);
20157+ if (n < 0 || au_sbend(sb) < n) {
4a4d8108 20158+ pr_err("out of bounds, %d\n", n);
1facf9fc 20159+ aufs_read_unlock(root, !AuLock_IR);
20160+ break;
20161+ }
20162+ aufs_read_unlock(root, !AuLock_IR);
20163+ err = 0;
20164+ opt->type = token;
20165+ break;
20166+
20167+ case Opt_dirwh:
20168+ if (unlikely(match_int(&a->args[0], &opt->dirwh)))
20169+ break;
20170+ err = 0;
20171+ opt->type = token;
20172+ break;
20173+
20174+ case Opt_rdcache:
027c5e7a
AM
20175+ if (unlikely(match_int(&a->args[0], &n))) {
20176+ pr_err("bad integer in %s\n", opt_str);
1facf9fc 20177+ break;
027c5e7a
AM
20178+ }
20179+ if (unlikely(n > AUFS_RDCACHE_MAX)) {
20180+ pr_err("rdcache must be smaller than %d\n",
20181+ AUFS_RDCACHE_MAX);
20182+ break;
20183+ }
20184+ opt->rdcache = n;
1facf9fc 20185+ err = 0;
20186+ opt->type = token;
20187+ break;
20188+ case Opt_rdblk:
20189+ if (unlikely(match_int(&a->args[0], &n)
1308ab2a 20190+ || n < 0
1facf9fc 20191+ || n > KMALLOC_MAX_SIZE)) {
4a4d8108 20192+ pr_err("bad integer in %s\n", opt_str);
1facf9fc 20193+ break;
20194+ }
1308ab2a 20195+ if (unlikely(n && n < NAME_MAX)) {
4a4d8108
AM
20196+ pr_err("rdblk must be larger than %d\n",
20197+ NAME_MAX);
1facf9fc 20198+ break;
20199+ }
20200+ opt->rdblk = n;
20201+ err = 0;
20202+ opt->type = token;
20203+ break;
20204+ case Opt_rdhash:
20205+ if (unlikely(match_int(&a->args[0], &n)
1308ab2a 20206+ || n < 0
1facf9fc 20207+ || n * sizeof(struct hlist_head)
20208+ > KMALLOC_MAX_SIZE)) {
4a4d8108 20209+ pr_err("bad integer in %s\n", opt_str);
1facf9fc 20210+ break;
20211+ }
20212+ opt->rdhash = n;
20213+ err = 0;
20214+ opt->type = token;
20215+ break;
20216+
20217+ case Opt_trunc_xino:
20218+ case Opt_notrunc_xino:
20219+ case Opt_noxino:
20220+ case Opt_trunc_xib:
20221+ case Opt_notrunc_xib:
dece6358
AM
20222+ case Opt_shwh:
20223+ case Opt_noshwh:
1facf9fc 20224+ case Opt_plink:
20225+ case Opt_noplink:
20226+ case Opt_list_plink:
4a4d8108
AM
20227+ case Opt_dio:
20228+ case Opt_nodio:
1facf9fc 20229+ case Opt_diropq_a:
20230+ case Opt_diropq_w:
20231+ case Opt_warn_perm:
20232+ case Opt_nowarn_perm:
20233+ case Opt_refrof:
20234+ case Opt_norefrof:
20235+ case Opt_verbose:
20236+ case Opt_noverbose:
20237+ case Opt_sum:
20238+ case Opt_nosum:
20239+ case Opt_wsum:
dece6358
AM
20240+ case Opt_rdblk_def:
20241+ case Opt_rdhash_def:
1facf9fc 20242+ err = 0;
20243+ opt->type = token;
20244+ break;
20245+
20246+ case Opt_udba:
20247+ opt->udba = udba_val(a->args[0].from);
20248+ if (opt->udba >= 0) {
20249+ err = 0;
20250+ opt->type = token;
20251+ } else
4a4d8108 20252+ pr_err("wrong value, %s\n", opt_str);
1facf9fc 20253+ break;
20254+
20255+ case Opt_wbr_create:
20256+ u.create = &opt->wbr_create;
20257+ u.create->wbr_create
20258+ = au_wbr_create_val(a->args[0].from, u.create);
20259+ if (u.create->wbr_create >= 0) {
20260+ err = 0;
20261+ opt->type = token;
20262+ } else
4a4d8108 20263+ pr_err("wrong value, %s\n", opt_str);
1facf9fc 20264+ break;
20265+ case Opt_wbr_copyup:
20266+ opt->wbr_copyup = au_wbr_copyup_val(a->args[0].from);
20267+ if (opt->wbr_copyup >= 0) {
20268+ err = 0;
20269+ opt->type = token;
20270+ } else
4a4d8108 20271+ pr_err("wrong value, %s\n", opt_str);
1facf9fc 20272+ break;
20273+
20274+ case Opt_ignore:
4a4d8108 20275+ pr_warning("ignored %s\n", opt_str);
1facf9fc 20276+ /*FALLTHROUGH*/
20277+ case Opt_ignore_silent:
20278+ skipped = 1;
20279+ err = 0;
20280+ break;
20281+ case Opt_err:
4a4d8108 20282+ pr_err("unknown option %s\n", opt_str);
1facf9fc 20283+ break;
20284+ }
20285+
20286+ if (!err && !skipped) {
20287+ if (unlikely(++opt > opt_tail)) {
20288+ err = -E2BIG;
20289+ opt--;
20290+ opt->type = Opt_tail;
20291+ break;
20292+ }
20293+ opt->type = Opt_tail;
20294+ }
20295+ }
20296+
20297+ kfree(a);
20298+ dump_opts(opts);
20299+ if (unlikely(err))
20300+ au_opts_free(opts);
20301+
4f0767ce 20302+out:
1facf9fc 20303+ return err;
20304+}
20305+
20306+static int au_opt_wbr_create(struct super_block *sb,
20307+ struct au_opt_wbr_create *create)
20308+{
20309+ int err;
20310+ struct au_sbinfo *sbinfo;
20311+
dece6358
AM
20312+ SiMustWriteLock(sb);
20313+
1facf9fc 20314+ err = 1; /* handled */
20315+ sbinfo = au_sbi(sb);
20316+ if (sbinfo->si_wbr_create_ops->fin) {
20317+ err = sbinfo->si_wbr_create_ops->fin(sb);
20318+ if (!err)
20319+ err = 1;
20320+ }
20321+
20322+ sbinfo->si_wbr_create = create->wbr_create;
20323+ sbinfo->si_wbr_create_ops = au_wbr_create_ops + create->wbr_create;
20324+ switch (create->wbr_create) {
20325+ case AuWbrCreate_MFSRRV:
20326+ case AuWbrCreate_MFSRR:
20327+ sbinfo->si_wbr_mfs.mfsrr_watermark = create->mfsrr_watermark;
20328+ /*FALLTHROUGH*/
20329+ case AuWbrCreate_MFS:
20330+ case AuWbrCreate_MFSV:
20331+ case AuWbrCreate_PMFS:
20332+ case AuWbrCreate_PMFSV:
e49829fe
JR
20333+ sbinfo->si_wbr_mfs.mfs_expire
20334+ = msecs_to_jiffies(create->mfs_second * MSEC_PER_SEC);
1facf9fc 20335+ break;
20336+ }
20337+
20338+ if (sbinfo->si_wbr_create_ops->init)
20339+ sbinfo->si_wbr_create_ops->init(sb); /* ignore */
20340+
20341+ return err;
20342+}
20343+
20344+/*
20345+ * returns,
20346+ * plus: processed without an error
20347+ * zero: unprocessed
20348+ */
20349+static int au_opt_simple(struct super_block *sb, struct au_opt *opt,
20350+ struct au_opts *opts)
20351+{
20352+ int err;
20353+ struct au_sbinfo *sbinfo;
20354+
dece6358
AM
20355+ SiMustWriteLock(sb);
20356+
1facf9fc 20357+ err = 1; /* handled */
20358+ sbinfo = au_sbi(sb);
20359+ switch (opt->type) {
20360+ case Opt_udba:
20361+ sbinfo->si_mntflags &= ~AuOptMask_UDBA;
20362+ sbinfo->si_mntflags |= opt->udba;
20363+ opts->given_udba |= opt->udba;
20364+ break;
20365+
20366+ case Opt_plink:
20367+ au_opt_set(sbinfo->si_mntflags, PLINK);
20368+ break;
20369+ case Opt_noplink:
20370+ if (au_opt_test(sbinfo->si_mntflags, PLINK))
e49829fe 20371+ au_plink_put(sb, /*verbose*/1);
1facf9fc 20372+ au_opt_clr(sbinfo->si_mntflags, PLINK);
20373+ break;
20374+ case Opt_list_plink:
20375+ if (au_opt_test(sbinfo->si_mntflags, PLINK))
20376+ au_plink_list(sb);
20377+ break;
20378+
4a4d8108
AM
20379+ case Opt_dio:
20380+ au_opt_set(sbinfo->si_mntflags, DIO);
20381+ au_fset_opts(opts->flags, REFRESH_DYAOP);
20382+ break;
20383+ case Opt_nodio:
20384+ au_opt_clr(sbinfo->si_mntflags, DIO);
20385+ au_fset_opts(opts->flags, REFRESH_DYAOP);
20386+ break;
20387+
1facf9fc 20388+ case Opt_diropq_a:
20389+ au_opt_set(sbinfo->si_mntflags, ALWAYS_DIROPQ);
20390+ break;
20391+ case Opt_diropq_w:
20392+ au_opt_clr(sbinfo->si_mntflags, ALWAYS_DIROPQ);
20393+ break;
20394+
20395+ case Opt_warn_perm:
20396+ au_opt_set(sbinfo->si_mntflags, WARN_PERM);
20397+ break;
20398+ case Opt_nowarn_perm:
20399+ au_opt_clr(sbinfo->si_mntflags, WARN_PERM);
20400+ break;
20401+
20402+ case Opt_refrof:
20403+ au_opt_set(sbinfo->si_mntflags, REFROF);
20404+ break;
20405+ case Opt_norefrof:
20406+ au_opt_clr(sbinfo->si_mntflags, REFROF);
20407+ break;
20408+
20409+ case Opt_verbose:
20410+ au_opt_set(sbinfo->si_mntflags, VERBOSE);
20411+ break;
20412+ case Opt_noverbose:
20413+ au_opt_clr(sbinfo->si_mntflags, VERBOSE);
20414+ break;
20415+
20416+ case Opt_sum:
20417+ au_opt_set(sbinfo->si_mntflags, SUM);
20418+ break;
20419+ case Opt_wsum:
20420+ au_opt_clr(sbinfo->si_mntflags, SUM);
20421+ au_opt_set(sbinfo->si_mntflags, SUM_W);
20422+ case Opt_nosum:
20423+ au_opt_clr(sbinfo->si_mntflags, SUM);
20424+ au_opt_clr(sbinfo->si_mntflags, SUM_W);
20425+ break;
20426+
20427+ case Opt_wbr_create:
20428+ err = au_opt_wbr_create(sb, &opt->wbr_create);
20429+ break;
20430+ case Opt_wbr_copyup:
20431+ sbinfo->si_wbr_copyup = opt->wbr_copyup;
20432+ sbinfo->si_wbr_copyup_ops = au_wbr_copyup_ops + opt->wbr_copyup;
20433+ break;
20434+
20435+ case Opt_dirwh:
20436+ sbinfo->si_dirwh = opt->dirwh;
20437+ break;
20438+
20439+ case Opt_rdcache:
e49829fe
JR
20440+ sbinfo->si_rdcache
20441+ = msecs_to_jiffies(opt->rdcache * MSEC_PER_SEC);
1facf9fc 20442+ break;
20443+ case Opt_rdblk:
20444+ sbinfo->si_rdblk = opt->rdblk;
20445+ break;
dece6358
AM
20446+ case Opt_rdblk_def:
20447+ sbinfo->si_rdblk = AUFS_RDBLK_DEF;
20448+ break;
1facf9fc 20449+ case Opt_rdhash:
20450+ sbinfo->si_rdhash = opt->rdhash;
20451+ break;
dece6358
AM
20452+ case Opt_rdhash_def:
20453+ sbinfo->si_rdhash = AUFS_RDHASH_DEF;
20454+ break;
20455+
20456+ case Opt_shwh:
20457+ au_opt_set(sbinfo->si_mntflags, SHWH);
20458+ break;
20459+ case Opt_noshwh:
20460+ au_opt_clr(sbinfo->si_mntflags, SHWH);
20461+ break;
1facf9fc 20462+
20463+ case Opt_trunc_xino:
20464+ au_opt_set(sbinfo->si_mntflags, TRUNC_XINO);
20465+ break;
20466+ case Opt_notrunc_xino:
20467+ au_opt_clr(sbinfo->si_mntflags, TRUNC_XINO);
20468+ break;
20469+
20470+ case Opt_trunc_xino_path:
20471+ case Opt_itrunc_xino:
20472+ err = au_xino_trunc(sb, opt->xino_itrunc.bindex);
20473+ if (!err)
20474+ err = 1;
20475+ break;
20476+
20477+ case Opt_trunc_xib:
20478+ au_fset_opts(opts->flags, TRUNC_XIB);
20479+ break;
20480+ case Opt_notrunc_xib:
20481+ au_fclr_opts(opts->flags, TRUNC_XIB);
20482+ break;
20483+
20484+ default:
20485+ err = 0;
20486+ break;
20487+ }
20488+
20489+ return err;
20490+}
20491+
20492+/*
20493+ * returns tri-state.
20494+ * plus: processed without an error
20495+ * zero: unprocessed
20496+ * minus: error
20497+ */
20498+static int au_opt_br(struct super_block *sb, struct au_opt *opt,
20499+ struct au_opts *opts)
20500+{
20501+ int err, do_refresh;
20502+
20503+ err = 0;
20504+ switch (opt->type) {
20505+ case Opt_append:
20506+ opt->add.bindex = au_sbend(sb) + 1;
20507+ if (opt->add.bindex < 0)
20508+ opt->add.bindex = 0;
20509+ goto add;
20510+ case Opt_prepend:
20511+ opt->add.bindex = 0;
20512+ add:
20513+ case Opt_add:
20514+ err = au_br_add(sb, &opt->add,
20515+ au_ftest_opts(opts->flags, REMOUNT));
20516+ if (!err) {
20517+ err = 1;
027c5e7a 20518+ au_fset_opts(opts->flags, REFRESH);
1facf9fc 20519+ }
20520+ break;
20521+
20522+ case Opt_del:
20523+ case Opt_idel:
20524+ err = au_br_del(sb, &opt->del,
20525+ au_ftest_opts(opts->flags, REMOUNT));
20526+ if (!err) {
20527+ err = 1;
20528+ au_fset_opts(opts->flags, TRUNC_XIB);
027c5e7a 20529+ au_fset_opts(opts->flags, REFRESH);
1facf9fc 20530+ }
20531+ break;
20532+
20533+ case Opt_mod:
20534+ case Opt_imod:
20535+ err = au_br_mod(sb, &opt->mod,
20536+ au_ftest_opts(opts->flags, REMOUNT),
20537+ &do_refresh);
20538+ if (!err) {
20539+ err = 1;
027c5e7a
AM
20540+ if (do_refresh)
20541+ au_fset_opts(opts->flags, REFRESH);
1facf9fc 20542+ }
20543+ break;
20544+ }
20545+
20546+ return err;
20547+}
20548+
20549+static int au_opt_xino(struct super_block *sb, struct au_opt *opt,
20550+ struct au_opt_xino **opt_xino,
20551+ struct au_opts *opts)
20552+{
20553+ int err;
20554+ aufs_bindex_t bend, bindex;
20555+ struct dentry *root, *parent, *h_root;
20556+
20557+ err = 0;
20558+ switch (opt->type) {
20559+ case Opt_xino:
20560+ err = au_xino_set(sb, &opt->xino,
20561+ !!au_ftest_opts(opts->flags, REMOUNT));
20562+ if (unlikely(err))
20563+ break;
20564+
20565+ *opt_xino = &opt->xino;
20566+ au_xino_brid_set(sb, -1);
20567+
20568+ /* safe d_parent access */
20569+ parent = opt->xino.file->f_dentry->d_parent;
20570+ root = sb->s_root;
20571+ bend = au_sbend(sb);
20572+ for (bindex = 0; bindex <= bend; bindex++) {
20573+ h_root = au_h_dptr(root, bindex);
20574+ if (h_root == parent) {
20575+ au_xino_brid_set(sb, au_sbr_id(sb, bindex));
20576+ break;
20577+ }
20578+ }
20579+ break;
20580+
20581+ case Opt_noxino:
20582+ au_xino_clr(sb);
20583+ au_xino_brid_set(sb, -1);
20584+ *opt_xino = (void *)-1;
20585+ break;
20586+ }
20587+
20588+ return err;
20589+}
20590+
20591+int au_opts_verify(struct super_block *sb, unsigned long sb_flags,
20592+ unsigned int pending)
20593+{
20594+ int err;
20595+ aufs_bindex_t bindex, bend;
20596+ unsigned char do_plink, skip, do_free;
20597+ struct au_branch *br;
20598+ struct au_wbr *wbr;
20599+ struct dentry *root;
20600+ struct inode *dir, *h_dir;
20601+ struct au_sbinfo *sbinfo;
20602+ struct au_hinode *hdir;
20603+
dece6358
AM
20604+ SiMustAnyLock(sb);
20605+
1facf9fc 20606+ sbinfo = au_sbi(sb);
20607+ AuDebugOn(!(sbinfo->si_mntflags & AuOptMask_UDBA));
20608+
dece6358
AM
20609+ if (!(sb_flags & MS_RDONLY)) {
20610+ if (unlikely(!au_br_writable(au_sbr_perm(sb, 0))))
4a4d8108 20611+ pr_warning("first branch should be rw\n");
dece6358 20612+ if (unlikely(au_opt_test(sbinfo->si_mntflags, SHWH)))
4a4d8108 20613+ pr_warning("shwh should be used with ro\n");
dece6358 20614+ }
1facf9fc 20615+
4a4d8108 20616+ if (au_opt_test((sbinfo->si_mntflags | pending), UDBA_HNOTIFY)
1facf9fc 20617+ && !au_opt_test(sbinfo->si_mntflags, XINO))
4a4d8108 20618+ pr_warning("udba=*notify requires xino\n");
1facf9fc 20619+
20620+ err = 0;
20621+ root = sb->s_root;
4a4d8108 20622+ dir = root->d_inode;
1facf9fc 20623+ do_plink = !!au_opt_test(sbinfo->si_mntflags, PLINK);
20624+ bend = au_sbend(sb);
20625+ for (bindex = 0; !err && bindex <= bend; bindex++) {
20626+ skip = 0;
20627+ h_dir = au_h_iptr(dir, bindex);
20628+ br = au_sbr(sb, bindex);
20629+ do_free = 0;
20630+
20631+ wbr = br->br_wbr;
20632+ if (wbr)
20633+ wbr_wh_read_lock(wbr);
20634+
1e00d052 20635+ if (!au_br_writable(br->br_perm)) {
1facf9fc 20636+ do_free = !!wbr;
20637+ skip = (!wbr
20638+ || (!wbr->wbr_whbase
20639+ && !wbr->wbr_plink
20640+ && !wbr->wbr_orph));
1e00d052 20641+ } else if (!au_br_wh_linkable(br->br_perm)) {
1facf9fc 20642+ /* skip = (!br->br_whbase && !br->br_orph); */
20643+ skip = (!wbr || !wbr->wbr_whbase);
20644+ if (skip && wbr) {
20645+ if (do_plink)
20646+ skip = !!wbr->wbr_plink;
20647+ else
20648+ skip = !wbr->wbr_plink;
20649+ }
1e00d052 20650+ } else {
1facf9fc 20651+ /* skip = (br->br_whbase && br->br_ohph); */
20652+ skip = (wbr && wbr->wbr_whbase);
20653+ if (skip) {
20654+ if (do_plink)
20655+ skip = !!wbr->wbr_plink;
20656+ else
20657+ skip = !wbr->wbr_plink;
20658+ }
1facf9fc 20659+ }
20660+ if (wbr)
20661+ wbr_wh_read_unlock(wbr);
20662+
20663+ if (skip)
20664+ continue;
20665+
20666+ hdir = au_hi(dir, bindex);
4a4d8108 20667+ au_hn_imtx_lock_nested(hdir, AuLsc_I_PARENT);
1facf9fc 20668+ if (wbr)
20669+ wbr_wh_write_lock(wbr);
20670+ err = au_wh_init(au_h_dptr(root, bindex), br, sb);
20671+ if (wbr)
20672+ wbr_wh_write_unlock(wbr);
4a4d8108 20673+ au_hn_imtx_unlock(hdir);
1facf9fc 20674+
20675+ if (!err && do_free) {
20676+ kfree(wbr);
20677+ br->br_wbr = NULL;
20678+ }
20679+ }
20680+
20681+ return err;
20682+}
20683+
20684+int au_opts_mount(struct super_block *sb, struct au_opts *opts)
20685+{
20686+ int err;
20687+ unsigned int tmp;
027c5e7a 20688+ aufs_bindex_t bindex, bend;
1facf9fc 20689+ struct au_opt *opt;
20690+ struct au_opt_xino *opt_xino, xino;
20691+ struct au_sbinfo *sbinfo;
027c5e7a 20692+ struct au_branch *br;
1facf9fc 20693+
dece6358
AM
20694+ SiMustWriteLock(sb);
20695+
1facf9fc 20696+ err = 0;
20697+ opt_xino = NULL;
20698+ opt = opts->opt;
20699+ while (err >= 0 && opt->type != Opt_tail)
20700+ err = au_opt_simple(sb, opt++, opts);
20701+ if (err > 0)
20702+ err = 0;
20703+ else if (unlikely(err < 0))
20704+ goto out;
20705+
20706+ /* disable xino and udba temporary */
20707+ sbinfo = au_sbi(sb);
20708+ tmp = sbinfo->si_mntflags;
20709+ au_opt_clr(sbinfo->si_mntflags, XINO);
20710+ au_opt_set_udba(sbinfo->si_mntflags, UDBA_REVAL);
20711+
20712+ opt = opts->opt;
20713+ while (err >= 0 && opt->type != Opt_tail)
20714+ err = au_opt_br(sb, opt++, opts);
20715+ if (err > 0)
20716+ err = 0;
20717+ else if (unlikely(err < 0))
20718+ goto out;
20719+
20720+ bend = au_sbend(sb);
20721+ if (unlikely(bend < 0)) {
20722+ err = -EINVAL;
4a4d8108 20723+ pr_err("no branches\n");
1facf9fc 20724+ goto out;
20725+ }
20726+
20727+ if (au_opt_test(tmp, XINO))
20728+ au_opt_set(sbinfo->si_mntflags, XINO);
20729+ opt = opts->opt;
20730+ while (!err && opt->type != Opt_tail)
20731+ err = au_opt_xino(sb, opt++, &opt_xino, opts);
20732+ if (unlikely(err))
20733+ goto out;
20734+
20735+ err = au_opts_verify(sb, sb->s_flags, tmp);
20736+ if (unlikely(err))
20737+ goto out;
20738+
20739+ /* restore xino */
20740+ if (au_opt_test(tmp, XINO) && !opt_xino) {
20741+ xino.file = au_xino_def(sb);
20742+ err = PTR_ERR(xino.file);
20743+ if (IS_ERR(xino.file))
20744+ goto out;
20745+
20746+ err = au_xino_set(sb, &xino, /*remount*/0);
20747+ fput(xino.file);
20748+ if (unlikely(err))
20749+ goto out;
20750+ }
20751+
20752+ /* restore udba */
027c5e7a 20753+ tmp &= AuOptMask_UDBA;
1facf9fc 20754+ sbinfo->si_mntflags &= ~AuOptMask_UDBA;
027c5e7a
AM
20755+ sbinfo->si_mntflags |= tmp;
20756+ bend = au_sbend(sb);
20757+ for (bindex = 0; bindex <= bend; bindex++) {
20758+ br = au_sbr(sb, bindex);
20759+ err = au_hnotify_reset_br(tmp, br, br->br_perm);
20760+ if (unlikely(err))
20761+ AuIOErr("hnotify failed on br %d, %d, ignored\n",
20762+ bindex, err);
20763+ /* go on even if err */
20764+ }
4a4d8108 20765+ if (au_opt_test(tmp, UDBA_HNOTIFY)) {
1facf9fc 20766+ struct inode *dir = sb->s_root->d_inode;
4a4d8108 20767+ au_hn_reset(dir, au_hi_flags(dir, /*isdir*/1) & ~AuHi_XINO);
1facf9fc 20768+ }
20769+
4f0767ce 20770+out:
1facf9fc 20771+ return err;
20772+}
20773+
20774+int au_opts_remount(struct super_block *sb, struct au_opts *opts)
20775+{
20776+ int err, rerr;
20777+ struct inode *dir;
20778+ struct au_opt_xino *opt_xino;
20779+ struct au_opt *opt;
20780+ struct au_sbinfo *sbinfo;
20781+
dece6358
AM
20782+ SiMustWriteLock(sb);
20783+
1facf9fc 20784+ dir = sb->s_root->d_inode;
20785+ sbinfo = au_sbi(sb);
20786+ err = 0;
20787+ opt_xino = NULL;
20788+ opt = opts->opt;
20789+ while (err >= 0 && opt->type != Opt_tail) {
20790+ err = au_opt_simple(sb, opt, opts);
20791+ if (!err)
20792+ err = au_opt_br(sb, opt, opts);
20793+ if (!err)
20794+ err = au_opt_xino(sb, opt, &opt_xino, opts);
20795+ opt++;
20796+ }
20797+ if (err > 0)
20798+ err = 0;
20799+ AuTraceErr(err);
20800+ /* go on even err */
20801+
20802+ rerr = au_opts_verify(sb, opts->sb_flags, /*pending*/0);
20803+ if (unlikely(rerr && !err))
20804+ err = rerr;
20805+
20806+ if (au_ftest_opts(opts->flags, TRUNC_XIB)) {
20807+ rerr = au_xib_trunc(sb);
20808+ if (unlikely(rerr && !err))
20809+ err = rerr;
20810+ }
20811+
20812+ /* will be handled by the caller */
027c5e7a 20813+ if (!au_ftest_opts(opts->flags, REFRESH)
1facf9fc 20814+ && (opts->given_udba || au_opt_test(sbinfo->si_mntflags, XINO)))
027c5e7a 20815+ au_fset_opts(opts->flags, REFRESH);
1facf9fc 20816+
20817+ AuDbg("status 0x%x\n", opts->flags);
20818+ return err;
20819+}
20820+
20821+/* ---------------------------------------------------------------------- */
20822+
20823+unsigned int au_opt_udba(struct super_block *sb)
20824+{
20825+ return au_mntflags(sb) & AuOptMask_UDBA;
20826+}
7f207e10
AM
20827diff -urN /usr/share/empty/fs/aufs/opts.h linux/fs/aufs/opts.h
20828--- /usr/share/empty/fs/aufs/opts.h 1970-01-01 01:00:00.000000000 +0100
7ce627cf 20829+++ linux/fs/aufs/opts.h 2012-05-22 09:06:08.870792417 +0200
f6c5ef8b 20830@@ -0,0 +1,209 @@
1facf9fc 20831+/*
f6c5ef8b 20832+ * Copyright (C) 2005-2012 Junjiro R. Okajima
1facf9fc 20833+ *
20834+ * This program, aufs is free software; you can redistribute it and/or modify
20835+ * it under the terms of the GNU General Public License as published by
20836+ * the Free Software Foundation; either version 2 of the License, or
20837+ * (at your option) any later version.
dece6358
AM
20838+ *
20839+ * This program is distributed in the hope that it will be useful,
20840+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
20841+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20842+ * GNU General Public License for more details.
20843+ *
20844+ * You should have received a copy of the GNU General Public License
20845+ * along with this program; if not, write to the Free Software
20846+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 20847+ */
20848+
20849+/*
20850+ * mount options/flags
20851+ */
20852+
20853+#ifndef __AUFS_OPTS_H__
20854+#define __AUFS_OPTS_H__
20855+
20856+#ifdef __KERNEL__
20857+
dece6358 20858+#include <linux/path.h>
1facf9fc 20859+
dece6358
AM
20860+struct file;
20861+struct super_block;
20862+
1facf9fc 20863+/* ---------------------------------------------------------------------- */
20864+
20865+/* mount flags */
20866+#define AuOpt_XINO 1 /* external inode number bitmap
20867+ and translation table */
20868+#define AuOpt_TRUNC_XINO (1 << 1) /* truncate xino files */
20869+#define AuOpt_UDBA_NONE (1 << 2) /* users direct branch access */
20870+#define AuOpt_UDBA_REVAL (1 << 3)
4a4d8108 20871+#define AuOpt_UDBA_HNOTIFY (1 << 4)
dece6358
AM
20872+#define AuOpt_SHWH (1 << 5) /* show whiteout */
20873+#define AuOpt_PLINK (1 << 6) /* pseudo-link */
20874+#define AuOpt_DIRPERM1 (1 << 7) /* unimplemented */
20875+#define AuOpt_REFROF (1 << 8) /* unimplemented */
20876+#define AuOpt_ALWAYS_DIROPQ (1 << 9) /* policy to creating diropq */
20877+#define AuOpt_SUM (1 << 10) /* summation for statfs(2) */
20878+#define AuOpt_SUM_W (1 << 11) /* unimplemented */
20879+#define AuOpt_WARN_PERM (1 << 12) /* warn when add-branch */
20880+#define AuOpt_VERBOSE (1 << 13) /* busy inode when del-branch */
4a4d8108 20881+#define AuOpt_DIO (1 << 14) /* direct io */
1facf9fc 20882+
4a4d8108
AM
20883+#ifndef CONFIG_AUFS_HNOTIFY
20884+#undef AuOpt_UDBA_HNOTIFY
20885+#define AuOpt_UDBA_HNOTIFY 0
1facf9fc 20886+#endif
dece6358
AM
20887+#ifndef CONFIG_AUFS_SHWH
20888+#undef AuOpt_SHWH
20889+#define AuOpt_SHWH 0
20890+#endif
1facf9fc 20891+
20892+#define AuOpt_Def (AuOpt_XINO \
20893+ | AuOpt_UDBA_REVAL \
20894+ | AuOpt_PLINK \
20895+ /* | AuOpt_DIRPERM1 */ \
20896+ | AuOpt_WARN_PERM)
20897+#define AuOptMask_UDBA (AuOpt_UDBA_NONE \
20898+ | AuOpt_UDBA_REVAL \
4a4d8108 20899+ | AuOpt_UDBA_HNOTIFY)
1facf9fc 20900+
20901+#define au_opt_test(flags, name) (flags & AuOpt_##name)
20902+#define au_opt_set(flags, name) do { \
20903+ BUILD_BUG_ON(AuOpt_##name & AuOptMask_UDBA); \
20904+ ((flags) |= AuOpt_##name); \
20905+} while (0)
20906+#define au_opt_set_udba(flags, name) do { \
20907+ (flags) &= ~AuOptMask_UDBA; \
20908+ ((flags) |= AuOpt_##name); \
20909+} while (0)
7f207e10
AM
20910+#define au_opt_clr(flags, name) do { \
20911+ ((flags) &= ~AuOpt_##name); \
20912+} while (0)
1facf9fc 20913+
e49829fe
JR
20914+static inline unsigned int au_opts_plink(unsigned int mntflags)
20915+{
20916+#ifdef CONFIG_PROC_FS
20917+ return mntflags;
20918+#else
20919+ return mntflags & ~AuOpt_PLINK;
20920+#endif
20921+}
20922+
1facf9fc 20923+/* ---------------------------------------------------------------------- */
20924+
20925+/* policies to select one among multiple writable branches */
20926+enum {
20927+ AuWbrCreate_TDP, /* top down parent */
20928+ AuWbrCreate_RR, /* round robin */
20929+ AuWbrCreate_MFS, /* most free space */
20930+ AuWbrCreate_MFSV, /* mfs with seconds */
20931+ AuWbrCreate_MFSRR, /* mfs then rr */
20932+ AuWbrCreate_MFSRRV, /* mfs then rr with seconds */
20933+ AuWbrCreate_PMFS, /* parent and mfs */
20934+ AuWbrCreate_PMFSV, /* parent and mfs with seconds */
20935+
20936+ AuWbrCreate_Def = AuWbrCreate_TDP
20937+};
20938+
20939+enum {
20940+ AuWbrCopyup_TDP, /* top down parent */
20941+ AuWbrCopyup_BUP, /* bottom up parent */
20942+ AuWbrCopyup_BU, /* bottom up */
20943+
20944+ AuWbrCopyup_Def = AuWbrCopyup_TDP
20945+};
20946+
20947+/* ---------------------------------------------------------------------- */
20948+
20949+struct au_opt_add {
20950+ aufs_bindex_t bindex;
20951+ char *pathname;
20952+ int perm;
20953+ struct path path;
20954+};
20955+
20956+struct au_opt_del {
20957+ char *pathname;
20958+ struct path h_path;
20959+};
20960+
20961+struct au_opt_mod {
20962+ char *path;
20963+ int perm;
20964+ struct dentry *h_root;
20965+};
20966+
20967+struct au_opt_xino {
20968+ char *path;
20969+ struct file *file;
20970+};
20971+
20972+struct au_opt_xino_itrunc {
20973+ aufs_bindex_t bindex;
20974+};
20975+
20976+struct au_opt_wbr_create {
20977+ int wbr_create;
20978+ int mfs_second;
20979+ unsigned long long mfsrr_watermark;
20980+};
20981+
20982+struct au_opt {
20983+ int type;
20984+ union {
20985+ struct au_opt_xino xino;
20986+ struct au_opt_xino_itrunc xino_itrunc;
20987+ struct au_opt_add add;
20988+ struct au_opt_del del;
20989+ struct au_opt_mod mod;
20990+ int dirwh;
20991+ int rdcache;
20992+ unsigned int rdblk;
20993+ unsigned int rdhash;
20994+ int udba;
20995+ struct au_opt_wbr_create wbr_create;
20996+ int wbr_copyup;
20997+ };
20998+};
20999+
21000+/* opts flags */
21001+#define AuOpts_REMOUNT 1
027c5e7a
AM
21002+#define AuOpts_REFRESH (1 << 1)
21003+#define AuOpts_TRUNC_XIB (1 << 2)
21004+#define AuOpts_REFRESH_DYAOP (1 << 3)
1facf9fc 21005+#define au_ftest_opts(flags, name) ((flags) & AuOpts_##name)
7f207e10
AM
21006+#define au_fset_opts(flags, name) \
21007+ do { (flags) |= AuOpts_##name; } while (0)
21008+#define au_fclr_opts(flags, name) \
21009+ do { (flags) &= ~AuOpts_##name; } while (0)
1facf9fc 21010+
21011+struct au_opts {
21012+ struct au_opt *opt;
21013+ int max_opt;
21014+
21015+ unsigned int given_udba;
21016+ unsigned int flags;
21017+ unsigned long sb_flags;
21018+};
21019+
21020+/* ---------------------------------------------------------------------- */
21021+
1e00d052 21022+char *au_optstr_br_perm(int brperm);
1facf9fc 21023+const char *au_optstr_udba(int udba);
21024+const char *au_optstr_wbr_copyup(int wbr_copyup);
21025+const char *au_optstr_wbr_create(int wbr_create);
21026+
21027+void au_opts_free(struct au_opts *opts);
21028+int au_opts_parse(struct super_block *sb, char *str, struct au_opts *opts);
21029+int au_opts_verify(struct super_block *sb, unsigned long sb_flags,
21030+ unsigned int pending);
21031+int au_opts_mount(struct super_block *sb, struct au_opts *opts);
21032+int au_opts_remount(struct super_block *sb, struct au_opts *opts);
21033+
21034+unsigned int au_opt_udba(struct super_block *sb);
21035+
21036+/* ---------------------------------------------------------------------- */
21037+
21038+#endif /* __KERNEL__ */
21039+#endif /* __AUFS_OPTS_H__ */
7f207e10
AM
21040diff -urN /usr/share/empty/fs/aufs/plink.c linux/fs/aufs/plink.c
21041--- /usr/share/empty/fs/aufs/plink.c 1970-01-01 01:00:00.000000000 +0100
7ce627cf 21042+++ linux/fs/aufs/plink.c 2012-05-22 09:06:08.870792417 +0200
027c5e7a 21043@@ -0,0 +1,515 @@
1facf9fc 21044+/*
f6c5ef8b 21045+ * Copyright (C) 2005-2012 Junjiro R. Okajima
1facf9fc 21046+ *
21047+ * This program, aufs is free software; you can redistribute it and/or modify
21048+ * it under the terms of the GNU General Public License as published by
21049+ * the Free Software Foundation; either version 2 of the License, or
21050+ * (at your option) any later version.
dece6358
AM
21051+ *
21052+ * This program is distributed in the hope that it will be useful,
21053+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
21054+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21055+ * GNU General Public License for more details.
21056+ *
21057+ * You should have received a copy of the GNU General Public License
21058+ * along with this program; if not, write to the Free Software
21059+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 21060+ */
21061+
21062+/*
21063+ * pseudo-link
21064+ */
21065+
21066+#include "aufs.h"
21067+
21068+/*
e49829fe 21069+ * the pseudo-link maintenance mode.
1facf9fc 21070+ * during a user process maintains the pseudo-links,
21071+ * prohibit adding a new plink and branch manipulation.
e49829fe
JR
21072+ *
21073+ * Flags
21074+ * NOPLM:
21075+ * For entry functions which will handle plink, and i_mutex is already held
21076+ * in VFS.
21077+ * They cannot wait and should return an error at once.
21078+ * Callers has to check the error.
21079+ * NOPLMW:
21080+ * For entry functions which will handle plink, but i_mutex is not held
21081+ * in VFS.
21082+ * They can wait the plink maintenance mode to finish.
21083+ *
21084+ * They behave like F_SETLK and F_SETLKW.
21085+ * If the caller never handle plink, then both flags are unnecessary.
1facf9fc 21086+ */
e49829fe
JR
21087+
21088+int au_plink_maint(struct super_block *sb, int flags)
1facf9fc 21089+{
e49829fe
JR
21090+ int err;
21091+ pid_t pid, ppid;
21092+ struct au_sbinfo *sbi;
dece6358
AM
21093+
21094+ SiMustAnyLock(sb);
21095+
e49829fe
JR
21096+ err = 0;
21097+ if (!au_opt_test(au_mntflags(sb), PLINK))
21098+ goto out;
21099+
21100+ sbi = au_sbi(sb);
21101+ pid = sbi->si_plink_maint_pid;
21102+ if (!pid || pid == current->pid)
21103+ goto out;
21104+
21105+ /* todo: it highly depends upon /sbin/mount.aufs */
21106+ rcu_read_lock();
21107+ ppid = task_pid_vnr(rcu_dereference(current->real_parent));
21108+ rcu_read_unlock();
21109+ if (pid == ppid)
21110+ goto out;
21111+
21112+ if (au_ftest_lock(flags, NOPLMW)) {
027c5e7a
AM
21113+ /* if there is no i_mutex lock in VFS, we don't need to wait */
21114+ /* AuDebugOn(!lockdep_depth(current)); */
e49829fe
JR
21115+ while (sbi->si_plink_maint_pid) {
21116+ si_read_unlock(sb);
21117+ /* gave up wake_up_bit() */
21118+ wait_event(sbi->si_plink_wq, !sbi->si_plink_maint_pid);
21119+
21120+ if (au_ftest_lock(flags, FLUSH))
21121+ au_nwt_flush(&sbi->si_nowait);
21122+ si_noflush_read_lock(sb);
21123+ }
21124+ } else if (au_ftest_lock(flags, NOPLM)) {
21125+ AuDbg("ppid %d, pid %d\n", ppid, pid);
21126+ err = -EAGAIN;
21127+ }
21128+
21129+out:
21130+ return err;
4a4d8108
AM
21131+}
21132+
e49829fe 21133+void au_plink_maint_leave(struct au_sbinfo *sbinfo)
4a4d8108 21134+{
4a4d8108 21135+ spin_lock(&sbinfo->si_plink_maint_lock);
027c5e7a 21136+ sbinfo->si_plink_maint_pid = 0;
4a4d8108 21137+ spin_unlock(&sbinfo->si_plink_maint_lock);
027c5e7a 21138+ wake_up_all(&sbinfo->si_plink_wq);
4a4d8108
AM
21139+}
21140+
e49829fe 21141+int au_plink_maint_enter(struct super_block *sb)
4a4d8108
AM
21142+{
21143+ int err;
4a4d8108
AM
21144+ struct au_sbinfo *sbinfo;
21145+
21146+ err = 0;
4a4d8108
AM
21147+ sbinfo = au_sbi(sb);
21148+ /* make sure i am the only one in this fs */
e49829fe
JR
21149+ si_write_lock(sb, AuLock_FLUSH);
21150+ if (au_opt_test(au_mntflags(sb), PLINK)) {
21151+ spin_lock(&sbinfo->si_plink_maint_lock);
21152+ if (!sbinfo->si_plink_maint_pid)
21153+ sbinfo->si_plink_maint_pid = current->pid;
21154+ else
21155+ err = -EBUSY;
21156+ spin_unlock(&sbinfo->si_plink_maint_lock);
21157+ }
4a4d8108
AM
21158+ si_write_unlock(sb);
21159+
21160+ return err;
1facf9fc 21161+}
21162+
21163+/* ---------------------------------------------------------------------- */
21164+
21165+struct pseudo_link {
4a4d8108
AM
21166+ union {
21167+ struct list_head list;
21168+ struct rcu_head rcu;
21169+ };
1facf9fc 21170+ struct inode *inode;
21171+};
21172+
21173+#ifdef CONFIG_AUFS_DEBUG
21174+void au_plink_list(struct super_block *sb)
21175+{
21176+ struct au_sbinfo *sbinfo;
21177+ struct list_head *plink_list;
21178+ struct pseudo_link *plink;
21179+
dece6358
AM
21180+ SiMustAnyLock(sb);
21181+
1facf9fc 21182+ sbinfo = au_sbi(sb);
21183+ AuDebugOn(!au_opt_test(au_mntflags(sb), PLINK));
e49829fe 21184+ AuDebugOn(au_plink_maint(sb, AuLock_NOPLM));
1facf9fc 21185+
21186+ plink_list = &sbinfo->si_plink.head;
4a4d8108
AM
21187+ rcu_read_lock();
21188+ list_for_each_entry_rcu(plink, plink_list, list)
1facf9fc 21189+ AuDbg("%lu\n", plink->inode->i_ino);
4a4d8108 21190+ rcu_read_unlock();
1facf9fc 21191+}
21192+#endif
21193+
21194+/* is the inode pseudo-linked? */
21195+int au_plink_test(struct inode *inode)
21196+{
21197+ int found;
21198+ struct au_sbinfo *sbinfo;
21199+ struct list_head *plink_list;
21200+ struct pseudo_link *plink;
21201+
21202+ sbinfo = au_sbi(inode->i_sb);
dece6358 21203+ AuRwMustAnyLock(&sbinfo->si_rwsem);
1facf9fc 21204+ AuDebugOn(!au_opt_test(au_mntflags(inode->i_sb), PLINK));
e49829fe 21205+ AuDebugOn(au_plink_maint(inode->i_sb, AuLock_NOPLM));
1facf9fc 21206+
21207+ found = 0;
21208+ plink_list = &sbinfo->si_plink.head;
4a4d8108
AM
21209+ rcu_read_lock();
21210+ list_for_each_entry_rcu(plink, plink_list, list)
1facf9fc 21211+ if (plink->inode == inode) {
21212+ found = 1;
21213+ break;
21214+ }
4a4d8108 21215+ rcu_read_unlock();
1facf9fc 21216+ return found;
21217+}
21218+
21219+/* ---------------------------------------------------------------------- */
21220+
21221+/*
21222+ * generate a name for plink.
21223+ * the file will be stored under AUFS_WH_PLINKDIR.
21224+ */
21225+/* 20 is max digits length of ulong 64 */
21226+#define PLINK_NAME_LEN ((20 + 1) * 2)
21227+
21228+static int plink_name(char *name, int len, struct inode *inode,
21229+ aufs_bindex_t bindex)
21230+{
21231+ int rlen;
21232+ struct inode *h_inode;
21233+
21234+ h_inode = au_h_iptr(inode, bindex);
21235+ rlen = snprintf(name, len, "%lu.%lu", inode->i_ino, h_inode->i_ino);
21236+ return rlen;
21237+}
21238+
7f207e10
AM
21239+struct au_do_plink_lkup_args {
21240+ struct dentry **errp;
21241+ struct qstr *tgtname;
21242+ struct dentry *h_parent;
21243+ struct au_branch *br;
21244+};
21245+
21246+static struct dentry *au_do_plink_lkup(struct qstr *tgtname,
21247+ struct dentry *h_parent,
21248+ struct au_branch *br)
21249+{
21250+ struct dentry *h_dentry;
21251+ struct mutex *h_mtx;
21252+
21253+ h_mtx = &h_parent->d_inode->i_mutex;
21254+ mutex_lock_nested(h_mtx, AuLsc_I_CHILD2);
21255+ h_dentry = au_lkup_one(tgtname, h_parent, br, /*nd*/NULL);
21256+ mutex_unlock(h_mtx);
21257+ return h_dentry;
21258+}
21259+
21260+static void au_call_do_plink_lkup(void *args)
21261+{
21262+ struct au_do_plink_lkup_args *a = args;
21263+ *a->errp = au_do_plink_lkup(a->tgtname, a->h_parent, a->br);
21264+}
21265+
1facf9fc 21266+/* lookup the plink-ed @inode under the branch at @bindex */
21267+struct dentry *au_plink_lkup(struct inode *inode, aufs_bindex_t bindex)
21268+{
21269+ struct dentry *h_dentry, *h_parent;
21270+ struct au_branch *br;
21271+ struct inode *h_dir;
7f207e10 21272+ int wkq_err;
1facf9fc 21273+ char a[PLINK_NAME_LEN];
21274+ struct qstr tgtname = {
21275+ .name = a
21276+ };
21277+
e49829fe
JR
21278+ AuDebugOn(au_plink_maint(inode->i_sb, AuLock_NOPLM));
21279+
1facf9fc 21280+ br = au_sbr(inode->i_sb, bindex);
21281+ h_parent = br->br_wbr->wbr_plink;
21282+ h_dir = h_parent->d_inode;
21283+ tgtname.len = plink_name(a, sizeof(a), inode, bindex);
21284+
7f207e10
AM
21285+ if (current_fsuid()) {
21286+ struct au_do_plink_lkup_args args = {
21287+ .errp = &h_dentry,
21288+ .tgtname = &tgtname,
21289+ .h_parent = h_parent,
21290+ .br = br
21291+ };
21292+
21293+ wkq_err = au_wkq_wait(au_call_do_plink_lkup, &args);
21294+ if (unlikely(wkq_err))
21295+ h_dentry = ERR_PTR(wkq_err);
21296+ } else
21297+ h_dentry = au_do_plink_lkup(&tgtname, h_parent, br);
21298+
1facf9fc 21299+ return h_dentry;
21300+}
21301+
21302+/* create a pseudo-link */
21303+static int do_whplink(struct qstr *tgt, struct dentry *h_parent,
21304+ struct dentry *h_dentry, struct au_branch *br)
21305+{
21306+ int err;
21307+ struct path h_path = {
21308+ .mnt = br->br_mnt
21309+ };
21310+ struct inode *h_dir;
21311+
21312+ h_dir = h_parent->d_inode;
7f207e10 21313+ mutex_lock_nested(&h_dir->i_mutex, AuLsc_I_CHILD2);
4f0767ce 21314+again:
1facf9fc 21315+ h_path.dentry = au_lkup_one(tgt, h_parent, br, /*nd*/NULL);
21316+ err = PTR_ERR(h_path.dentry);
21317+ if (IS_ERR(h_path.dentry))
21318+ goto out;
21319+
21320+ err = 0;
21321+ /* wh.plink dir is not monitored */
7f207e10 21322+ /* todo: is it really safe? */
1facf9fc 21323+ if (h_path.dentry->d_inode
21324+ && h_path.dentry->d_inode != h_dentry->d_inode) {
21325+ err = vfsub_unlink(h_dir, &h_path, /*force*/0);
21326+ dput(h_path.dentry);
21327+ h_path.dentry = NULL;
21328+ if (!err)
21329+ goto again;
21330+ }
21331+ if (!err && !h_path.dentry->d_inode)
21332+ err = vfsub_link(h_dentry, h_dir, &h_path);
21333+ dput(h_path.dentry);
21334+
4f0767ce 21335+out:
7f207e10 21336+ mutex_unlock(&h_dir->i_mutex);
1facf9fc 21337+ return err;
21338+}
21339+
21340+struct do_whplink_args {
21341+ int *errp;
21342+ struct qstr *tgt;
21343+ struct dentry *h_parent;
21344+ struct dentry *h_dentry;
21345+ struct au_branch *br;
21346+};
21347+
21348+static void call_do_whplink(void *args)
21349+{
21350+ struct do_whplink_args *a = args;
21351+ *a->errp = do_whplink(a->tgt, a->h_parent, a->h_dentry, a->br);
21352+}
21353+
21354+static int whplink(struct dentry *h_dentry, struct inode *inode,
21355+ aufs_bindex_t bindex, struct au_branch *br)
21356+{
21357+ int err, wkq_err;
21358+ struct au_wbr *wbr;
21359+ struct dentry *h_parent;
21360+ struct inode *h_dir;
21361+ char a[PLINK_NAME_LEN];
21362+ struct qstr tgtname = {
21363+ .name = a
21364+ };
21365+
21366+ wbr = au_sbr(inode->i_sb, bindex)->br_wbr;
21367+ h_parent = wbr->wbr_plink;
21368+ h_dir = h_parent->d_inode;
21369+ tgtname.len = plink_name(a, sizeof(a), inode, bindex);
21370+
21371+ /* always superio. */
b752ccd1 21372+ if (current_fsuid()) {
1facf9fc 21373+ struct do_whplink_args args = {
21374+ .errp = &err,
21375+ .tgt = &tgtname,
21376+ .h_parent = h_parent,
21377+ .h_dentry = h_dentry,
21378+ .br = br
21379+ };
21380+ wkq_err = au_wkq_wait(call_do_whplink, &args);
21381+ if (unlikely(wkq_err))
21382+ err = wkq_err;
21383+ } else
21384+ err = do_whplink(&tgtname, h_parent, h_dentry, br);
1facf9fc 21385+
21386+ return err;
21387+}
21388+
21389+/* free a single plink */
21390+static void do_put_plink(struct pseudo_link *plink, int do_del)
21391+{
1facf9fc 21392+ if (do_del)
21393+ list_del(&plink->list);
4a4d8108
AM
21394+ iput(plink->inode);
21395+ kfree(plink);
21396+}
21397+
21398+static void do_put_plink_rcu(struct rcu_head *rcu)
21399+{
21400+ struct pseudo_link *plink;
21401+
21402+ plink = container_of(rcu, struct pseudo_link, rcu);
21403+ iput(plink->inode);
1facf9fc 21404+ kfree(plink);
21405+}
21406+
21407+/*
21408+ * create a new pseudo-link for @h_dentry on @bindex.
21409+ * the linked inode is held in aufs @inode.
21410+ */
21411+void au_plink_append(struct inode *inode, aufs_bindex_t bindex,
21412+ struct dentry *h_dentry)
21413+{
21414+ struct super_block *sb;
21415+ struct au_sbinfo *sbinfo;
21416+ struct list_head *plink_list;
4a4d8108 21417+ struct pseudo_link *plink, *tmp;
1facf9fc 21418+ int found, err, cnt;
21419+
21420+ sb = inode->i_sb;
21421+ sbinfo = au_sbi(sb);
21422+ AuDebugOn(!au_opt_test(au_mntflags(sb), PLINK));
e49829fe 21423+ AuDebugOn(au_plink_maint(sb, AuLock_NOPLM));
1facf9fc 21424+
1facf9fc 21425+ cnt = 0;
21426+ found = 0;
21427+ plink_list = &sbinfo->si_plink.head;
4a4d8108
AM
21428+ rcu_read_lock();
21429+ list_for_each_entry_rcu(plink, plink_list, list) {
1facf9fc 21430+ cnt++;
21431+ if (plink->inode == inode) {
21432+ found = 1;
21433+ break;
21434+ }
21435+ }
4a4d8108
AM
21436+ rcu_read_unlock();
21437+ if (found)
1facf9fc 21438+ return;
4a4d8108
AM
21439+
21440+ tmp = kmalloc(sizeof(*plink), GFP_NOFS);
21441+ if (tmp)
21442+ tmp->inode = au_igrab(inode);
21443+ else {
21444+ err = -ENOMEM;
21445+ goto out;
1facf9fc 21446+ }
21447+
4a4d8108
AM
21448+ spin_lock(&sbinfo->si_plink.spin);
21449+ list_for_each_entry(plink, plink_list, list) {
21450+ if (plink->inode == inode) {
21451+ found = 1;
21452+ break;
21453+ }
1facf9fc 21454+ }
4a4d8108
AM
21455+ if (!found)
21456+ list_add_rcu(&tmp->list, plink_list);
1facf9fc 21457+ spin_unlock(&sbinfo->si_plink.spin);
4a4d8108
AM
21458+ if (!found) {
21459+ cnt++;
21460+ WARN_ONCE(cnt > AUFS_PLINK_WARN,
21461+ "unexpectedly many pseudo links, %d\n", cnt);
1facf9fc 21462+ err = whplink(h_dentry, inode, bindex, au_sbr(sb, bindex));
4a4d8108
AM
21463+ } else {
21464+ do_put_plink(tmp, 0);
21465+ return;
1facf9fc 21466+ }
21467+
4a4d8108 21468+out:
1facf9fc 21469+ if (unlikely(err)) {
4a4d8108
AM
21470+ pr_warning("err %d, damaged pseudo link.\n", err);
21471+ if (tmp) {
21472+ au_spl_del_rcu(&tmp->list, &sbinfo->si_plink);
21473+ call_rcu(&tmp->rcu, do_put_plink_rcu);
21474+ }
1facf9fc 21475+ }
21476+}
21477+
21478+/* free all plinks */
e49829fe 21479+void au_plink_put(struct super_block *sb, int verbose)
1facf9fc 21480+{
21481+ struct au_sbinfo *sbinfo;
21482+ struct list_head *plink_list;
21483+ struct pseudo_link *plink, *tmp;
21484+
dece6358
AM
21485+ SiMustWriteLock(sb);
21486+
1facf9fc 21487+ sbinfo = au_sbi(sb);
21488+ AuDebugOn(!au_opt_test(au_mntflags(sb), PLINK));
e49829fe 21489+ AuDebugOn(au_plink_maint(sb, AuLock_NOPLM));
1facf9fc 21490+
21491+ plink_list = &sbinfo->si_plink.head;
21492+ /* no spin_lock since sbinfo is write-locked */
e49829fe 21493+ WARN(verbose && !list_empty(plink_list), "pseudo-link is not flushed");
1facf9fc 21494+ list_for_each_entry_safe(plink, tmp, plink_list, list)
21495+ do_put_plink(plink, 0);
21496+ INIT_LIST_HEAD(plink_list);
21497+}
21498+
e49829fe
JR
21499+void au_plink_clean(struct super_block *sb, int verbose)
21500+{
21501+ struct dentry *root;
21502+
21503+ root = sb->s_root;
21504+ aufs_write_lock(root);
21505+ if (au_opt_test(au_mntflags(sb), PLINK))
21506+ au_plink_put(sb, verbose);
21507+ aufs_write_unlock(root);
21508+}
21509+
1facf9fc 21510+/* free the plinks on a branch specified by @br_id */
21511+void au_plink_half_refresh(struct super_block *sb, aufs_bindex_t br_id)
21512+{
21513+ struct au_sbinfo *sbinfo;
21514+ struct list_head *plink_list;
21515+ struct pseudo_link *plink, *tmp;
21516+ struct inode *inode;
21517+ aufs_bindex_t bstart, bend, bindex;
21518+ unsigned char do_put;
21519+
dece6358
AM
21520+ SiMustWriteLock(sb);
21521+
1facf9fc 21522+ sbinfo = au_sbi(sb);
21523+ AuDebugOn(!au_opt_test(au_mntflags(sb), PLINK));
e49829fe 21524+ AuDebugOn(au_plink_maint(sb, AuLock_NOPLM));
1facf9fc 21525+
21526+ plink_list = &sbinfo->si_plink.head;
21527+ /* no spin_lock since sbinfo is write-locked */
21528+ list_for_each_entry_safe(plink, tmp, plink_list, list) {
21529+ do_put = 0;
21530+ inode = au_igrab(plink->inode);
21531+ ii_write_lock_child(inode);
21532+ bstart = au_ibstart(inode);
21533+ bend = au_ibend(inode);
21534+ if (bstart >= 0) {
21535+ for (bindex = bstart; bindex <= bend; bindex++) {
21536+ if (!au_h_iptr(inode, bindex)
21537+ || au_ii_br_id(inode, bindex) != br_id)
21538+ continue;
21539+ au_set_h_iptr(inode, bindex, NULL, 0);
21540+ do_put = 1;
21541+ break;
21542+ }
21543+ } else
21544+ do_put_plink(plink, 1);
21545+
dece6358
AM
21546+ if (do_put) {
21547+ for (bindex = bstart; bindex <= bend; bindex++)
21548+ if (au_h_iptr(inode, bindex)) {
21549+ do_put = 0;
21550+ break;
21551+ }
21552+ if (do_put)
21553+ do_put_plink(plink, 1);
21554+ }
21555+ ii_write_unlock(inode);
21556+ iput(inode);
21557+ }
21558+}
7f207e10
AM
21559diff -urN /usr/share/empty/fs/aufs/poll.c linux/fs/aufs/poll.c
21560--- /usr/share/empty/fs/aufs/poll.c 1970-01-01 01:00:00.000000000 +0100
7ce627cf 21561+++ linux/fs/aufs/poll.c 2012-05-22 09:06:08.870792417 +0200
dece6358
AM
21562@@ -0,0 +1,56 @@
21563+/*
f6c5ef8b 21564+ * Copyright (C) 2005-2012 Junjiro R. Okajima
dece6358
AM
21565+ *
21566+ * This program, aufs is free software; you can redistribute it and/or modify
21567+ * it under the terms of the GNU General Public License as published by
21568+ * the Free Software Foundation; either version 2 of the License, or
21569+ * (at your option) any later version.
21570+ *
21571+ * This program is distributed in the hope that it will be useful,
21572+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
21573+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21574+ * GNU General Public License for more details.
21575+ *
21576+ * You should have received a copy of the GNU General Public License
21577+ * along with this program; if not, write to the Free Software
21578+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
21579+ */
21580+
1308ab2a 21581+/*
21582+ * poll operation
21583+ * There is only one filesystem which implements ->poll operation, currently.
21584+ */
21585+
21586+#include "aufs.h"
21587+
21588+unsigned int aufs_poll(struct file *file, poll_table *wait)
21589+{
21590+ unsigned int mask;
21591+ int err;
21592+ struct file *h_file;
21593+ struct dentry *dentry;
21594+ struct super_block *sb;
21595+
21596+ /* We should pretend an error happened. */
21597+ mask = POLLERR /* | POLLIN | POLLOUT */;
21598+ dentry = file->f_dentry;
21599+ sb = dentry->d_sb;
e49829fe 21600+ si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLMW);
1308ab2a 21601+ err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/0);
21602+ if (unlikely(err))
21603+ goto out;
21604+
21605+ /* it is not an error if h_file has no operation */
21606+ mask = DEFAULT_POLLMASK;
4a4d8108 21607+ h_file = au_hf_top(file);
1308ab2a 21608+ if (h_file->f_op && h_file->f_op->poll)
21609+ mask = h_file->f_op->poll(h_file, wait);
21610+
21611+ di_read_unlock(dentry, AuLock_IR);
21612+ fi_read_unlock(file);
21613+
4f0767ce 21614+out:
1308ab2a 21615+ si_read_unlock(sb);
21616+ AuTraceErr((int)mask);
21617+ return mask;
21618+}
7f207e10
AM
21619diff -urN /usr/share/empty/fs/aufs/procfs.c linux/fs/aufs/procfs.c
21620--- /usr/share/empty/fs/aufs/procfs.c 1970-01-01 01:00:00.000000000 +0100
7ce627cf 21621+++ linux/fs/aufs/procfs.c 2012-05-22 09:06:08.870792417 +0200
53392da6 21622@@ -0,0 +1,170 @@
e49829fe 21623+/*
f6c5ef8b 21624+ * Copyright (C) 2010-2012 Junjiro R. Okajima
e49829fe
JR
21625+ *
21626+ * This program, aufs is free software; you can redistribute it and/or modify
21627+ * it under the terms of the GNU General Public License as published by
21628+ * the Free Software Foundation; either version 2 of the License, or
21629+ * (at your option) any later version.
21630+ *
21631+ * This program is distributed in the hope that it will be useful,
21632+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
21633+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21634+ * GNU General Public License for more details.
21635+ *
21636+ * You should have received a copy of the GNU General Public License
21637+ * along with this program; if not, write to the Free Software
21638+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
21639+ */
21640+
21641+/*
21642+ * procfs interfaces
21643+ */
21644+
21645+#include <linux/proc_fs.h>
21646+#include "aufs.h"
21647+
21648+static int au_procfs_plm_release(struct inode *inode, struct file *file)
21649+{
21650+ struct au_sbinfo *sbinfo;
21651+
21652+ sbinfo = file->private_data;
21653+ if (sbinfo) {
21654+ au_plink_maint_leave(sbinfo);
21655+ kobject_put(&sbinfo->si_kobj);
21656+ }
21657+
21658+ return 0;
21659+}
21660+
21661+static void au_procfs_plm_write_clean(struct file *file)
21662+{
21663+ struct au_sbinfo *sbinfo;
21664+
21665+ sbinfo = file->private_data;
21666+ if (sbinfo)
21667+ au_plink_clean(sbinfo->si_sb, /*verbose*/0);
21668+}
21669+
21670+static int au_procfs_plm_write_si(struct file *file, unsigned long id)
21671+{
21672+ int err;
21673+ struct super_block *sb;
21674+ struct au_sbinfo *sbinfo;
21675+
21676+ err = -EBUSY;
21677+ if (unlikely(file->private_data))
21678+ goto out;
21679+
21680+ sb = NULL;
53392da6 21681+ /* don't use au_sbilist_lock() here */
e49829fe
JR
21682+ spin_lock(&au_sbilist.spin);
21683+ list_for_each_entry(sbinfo, &au_sbilist.head, si_list)
21684+ if (id == sysaufs_si_id(sbinfo)) {
21685+ kobject_get(&sbinfo->si_kobj);
21686+ sb = sbinfo->si_sb;
21687+ break;
21688+ }
21689+ spin_unlock(&au_sbilist.spin);
21690+
21691+ err = -EINVAL;
21692+ if (unlikely(!sb))
21693+ goto out;
21694+
21695+ err = au_plink_maint_enter(sb);
21696+ if (!err)
21697+ /* keep kobject_get() */
21698+ file->private_data = sbinfo;
21699+ else
21700+ kobject_put(&sbinfo->si_kobj);
21701+out:
21702+ return err;
21703+}
21704+
21705+/*
21706+ * Accept a valid "si=xxxx" only.
21707+ * Once it is accepted successfully, accept "clean" too.
21708+ */
21709+static ssize_t au_procfs_plm_write(struct file *file, const char __user *ubuf,
21710+ size_t count, loff_t *ppos)
21711+{
21712+ ssize_t err;
21713+ unsigned long id;
21714+ /* last newline is allowed */
21715+ char buf[3 + sizeof(unsigned long) * 2 + 1];
21716+
21717+ err = -EACCES;
21718+ if (unlikely(!capable(CAP_SYS_ADMIN)))
21719+ goto out;
21720+
21721+ err = -EINVAL;
21722+ if (unlikely(count > sizeof(buf)))
21723+ goto out;
21724+
21725+ err = copy_from_user(buf, ubuf, count);
21726+ if (unlikely(err)) {
21727+ err = -EFAULT;
21728+ goto out;
21729+ }
21730+ buf[count] = 0;
21731+
21732+ err = -EINVAL;
21733+ if (!strcmp("clean", buf)) {
21734+ au_procfs_plm_write_clean(file);
21735+ goto out_success;
21736+ } else if (unlikely(strncmp("si=", buf, 3)))
21737+ goto out;
21738+
9dbd164d 21739+ err = kstrtoul(buf + 3, 16, &id);
e49829fe
JR
21740+ if (unlikely(err))
21741+ goto out;
21742+
21743+ err = au_procfs_plm_write_si(file, id);
21744+ if (unlikely(err))
21745+ goto out;
21746+
21747+out_success:
21748+ err = count; /* success */
21749+out:
21750+ return err;
21751+}
21752+
21753+static const struct file_operations au_procfs_plm_fop = {
21754+ .write = au_procfs_plm_write,
21755+ .release = au_procfs_plm_release,
21756+ .owner = THIS_MODULE
21757+};
21758+
21759+/* ---------------------------------------------------------------------- */
21760+
21761+static struct proc_dir_entry *au_procfs_dir;
21762+
21763+void au_procfs_fin(void)
21764+{
21765+ remove_proc_entry(AUFS_PLINK_MAINT_NAME, au_procfs_dir);
21766+ remove_proc_entry(AUFS_PLINK_MAINT_DIR, NULL);
21767+}
21768+
21769+int __init au_procfs_init(void)
21770+{
21771+ int err;
21772+ struct proc_dir_entry *entry;
21773+
21774+ err = -ENOMEM;
21775+ au_procfs_dir = proc_mkdir(AUFS_PLINK_MAINT_DIR, NULL);
21776+ if (unlikely(!au_procfs_dir))
21777+ goto out;
21778+
21779+ entry = proc_create(AUFS_PLINK_MAINT_NAME, S_IFREG | S_IWUSR,
21780+ au_procfs_dir, &au_procfs_plm_fop);
21781+ if (unlikely(!entry))
21782+ goto out_dir;
21783+
21784+ err = 0;
21785+ goto out; /* success */
21786+
21787+
21788+out_dir:
21789+ remove_proc_entry(AUFS_PLINK_MAINT_DIR, NULL);
21790+out:
21791+ return err;
21792+}
7f207e10
AM
21793diff -urN /usr/share/empty/fs/aufs/rdu.c linux/fs/aufs/rdu.c
21794--- /usr/share/empty/fs/aufs/rdu.c 1970-01-01 01:00:00.000000000 +0100
7ce627cf 21795+++ linux/fs/aufs/rdu.c 2012-05-22 09:06:08.870792417 +0200
92d182d2 21796@@ -0,0 +1,384 @@
1308ab2a 21797+/*
f6c5ef8b 21798+ * Copyright (C) 2005-2012 Junjiro R. Okajima
1308ab2a 21799+ *
21800+ * This program, aufs is free software; you can redistribute it and/or modify
21801+ * it under the terms of the GNU General Public License as published by
21802+ * the Free Software Foundation; either version 2 of the License, or
21803+ * (at your option) any later version.
21804+ *
21805+ * This program is distributed in the hope that it will be useful,
21806+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
21807+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21808+ * GNU General Public License for more details.
21809+ *
21810+ * You should have received a copy of the GNU General Public License
21811+ * along with this program; if not, write to the Free Software
21812+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
21813+ */
21814+
21815+/*
21816+ * readdir in userspace.
21817+ */
21818+
b752ccd1 21819+#include <linux/compat.h>
4a4d8108 21820+#include <linux/fs_stack.h>
1308ab2a 21821+#include <linux/security.h>
1308ab2a 21822+#include "aufs.h"
21823+
21824+/* bits for struct aufs_rdu.flags */
21825+#define AuRdu_CALLED 1
21826+#define AuRdu_CONT (1 << 1)
21827+#define AuRdu_FULL (1 << 2)
21828+#define au_ftest_rdu(flags, name) ((flags) & AuRdu_##name)
7f207e10
AM
21829+#define au_fset_rdu(flags, name) \
21830+ do { (flags) |= AuRdu_##name; } while (0)
21831+#define au_fclr_rdu(flags, name) \
21832+ do { (flags) &= ~AuRdu_##name; } while (0)
1308ab2a 21833+
21834+struct au_rdu_arg {
21835+ struct aufs_rdu *rdu;
21836+ union au_rdu_ent_ul ent;
21837+ unsigned long end;
21838+
21839+ struct super_block *sb;
21840+ int err;
21841+};
21842+
21843+static int au_rdu_fill(void *__arg, const char *name, int nlen,
21844+ loff_t offset, u64 h_ino, unsigned int d_type)
21845+{
21846+ int err, len;
21847+ struct au_rdu_arg *arg = __arg;
21848+ struct aufs_rdu *rdu = arg->rdu;
21849+ struct au_rdu_ent ent;
21850+
21851+ err = 0;
21852+ arg->err = 0;
21853+ au_fset_rdu(rdu->cookie.flags, CALLED);
21854+ len = au_rdu_len(nlen);
21855+ if (arg->ent.ul + len < arg->end) {
21856+ ent.ino = h_ino;
21857+ ent.bindex = rdu->cookie.bindex;
21858+ ent.type = d_type;
21859+ ent.nlen = nlen;
4a4d8108
AM
21860+ if (unlikely(nlen > AUFS_MAX_NAMELEN))
21861+ ent.type = DT_UNKNOWN;
1308ab2a 21862+
9dbd164d 21863+ /* unnecessary to support mmap_sem since this is a dir */
1308ab2a 21864+ err = -EFAULT;
21865+ if (copy_to_user(arg->ent.e, &ent, sizeof(ent)))
21866+ goto out;
21867+ if (copy_to_user(arg->ent.e->name, name, nlen))
21868+ goto out;
21869+ /* the terminating NULL */
21870+ if (__put_user(0, arg->ent.e->name + nlen))
21871+ goto out;
21872+ err = 0;
21873+ /* AuDbg("%p, %.*s\n", arg->ent.p, nlen, name); */
21874+ arg->ent.ul += len;
21875+ rdu->rent++;
21876+ } else {
21877+ err = -EFAULT;
21878+ au_fset_rdu(rdu->cookie.flags, FULL);
21879+ rdu->full = 1;
21880+ rdu->tail = arg->ent;
21881+ }
21882+
4f0767ce 21883+out:
1308ab2a 21884+ /* AuTraceErr(err); */
21885+ return err;
21886+}
21887+
21888+static int au_rdu_do(struct file *h_file, struct au_rdu_arg *arg)
21889+{
21890+ int err;
21891+ loff_t offset;
21892+ struct au_rdu_cookie *cookie = &arg->rdu->cookie;
21893+
92d182d2 21894+ /* we don't have to care (FMODE_32BITHASH | FMODE_64BITHASH) for ext4 */
1308ab2a 21895+ offset = vfsub_llseek(h_file, cookie->h_pos, SEEK_SET);
21896+ err = offset;
21897+ if (unlikely(offset != cookie->h_pos))
21898+ goto out;
21899+
21900+ err = 0;
21901+ do {
21902+ arg->err = 0;
21903+ au_fclr_rdu(cookie->flags, CALLED);
21904+ /* smp_mb(); */
21905+ err = vfsub_readdir(h_file, au_rdu_fill, arg);
21906+ if (err >= 0)
21907+ err = arg->err;
21908+ } while (!err
21909+ && au_ftest_rdu(cookie->flags, CALLED)
21910+ && !au_ftest_rdu(cookie->flags, FULL));
21911+ cookie->h_pos = h_file->f_pos;
21912+
4f0767ce 21913+out:
1308ab2a 21914+ AuTraceErr(err);
21915+ return err;
21916+}
21917+
21918+static int au_rdu(struct file *file, struct aufs_rdu *rdu)
21919+{
21920+ int err;
21921+ aufs_bindex_t bend;
21922+ struct au_rdu_arg arg;
21923+ struct dentry *dentry;
21924+ struct inode *inode;
21925+ struct file *h_file;
21926+ struct au_rdu_cookie *cookie = &rdu->cookie;
21927+
21928+ err = !access_ok(VERIFY_WRITE, rdu->ent.e, rdu->sz);
21929+ if (unlikely(err)) {
21930+ err = -EFAULT;
21931+ AuTraceErr(err);
21932+ goto out;
21933+ }
21934+ rdu->rent = 0;
21935+ rdu->tail = rdu->ent;
21936+ rdu->full = 0;
21937+ arg.rdu = rdu;
21938+ arg.ent = rdu->ent;
21939+ arg.end = arg.ent.ul;
21940+ arg.end += rdu->sz;
21941+
21942+ err = -ENOTDIR;
21943+ if (unlikely(!file->f_op || !file->f_op->readdir))
21944+ goto out;
21945+
21946+ err = security_file_permission(file, MAY_READ);
21947+ AuTraceErr(err);
21948+ if (unlikely(err))
21949+ goto out;
21950+
21951+ dentry = file->f_dentry;
21952+ inode = dentry->d_inode;
21953+#if 1
21954+ mutex_lock(&inode->i_mutex);
21955+#else
21956+ err = mutex_lock_killable(&inode->i_mutex);
21957+ AuTraceErr(err);
21958+ if (unlikely(err))
21959+ goto out;
21960+#endif
1308ab2a 21961+
21962+ arg.sb = inode->i_sb;
e49829fe
JR
21963+ err = si_read_lock(arg.sb, AuLock_FLUSH | AuLock_NOPLM);
21964+ if (unlikely(err))
21965+ goto out_mtx;
027c5e7a
AM
21966+ err = au_alive_dir(dentry);
21967+ if (unlikely(err))
21968+ goto out_si;
e49829fe 21969+ /* todo: reval? */
1308ab2a 21970+ fi_read_lock(file);
21971+
21972+ err = -EAGAIN;
21973+ if (unlikely(au_ftest_rdu(cookie->flags, CONT)
21974+ && cookie->generation != au_figen(file)))
21975+ goto out_unlock;
21976+
21977+ err = 0;
21978+ if (!rdu->blk) {
21979+ rdu->blk = au_sbi(arg.sb)->si_rdblk;
21980+ if (!rdu->blk)
21981+ rdu->blk = au_dir_size(file, /*dentry*/NULL);
21982+ }
21983+ bend = au_fbstart(file);
21984+ if (cookie->bindex < bend)
21985+ cookie->bindex = bend;
4a4d8108 21986+ bend = au_fbend_dir(file);
1308ab2a 21987+ /* AuDbg("b%d, b%d\n", cookie->bindex, bend); */
21988+ for (; !err && cookie->bindex <= bend;
21989+ cookie->bindex++, cookie->h_pos = 0) {
4a4d8108 21990+ h_file = au_hf_dir(file, cookie->bindex);
1308ab2a 21991+ if (!h_file)
21992+ continue;
21993+
21994+ au_fclr_rdu(cookie->flags, FULL);
21995+ err = au_rdu_do(h_file, &arg);
21996+ AuTraceErr(err);
21997+ if (unlikely(au_ftest_rdu(cookie->flags, FULL) || err))
21998+ break;
21999+ }
22000+ AuDbg("rent %llu\n", rdu->rent);
22001+
22002+ if (!err && !au_ftest_rdu(cookie->flags, CONT)) {
22003+ rdu->shwh = !!au_opt_test(au_sbi(arg.sb)->si_mntflags, SHWH);
22004+ au_fset_rdu(cookie->flags, CONT);
22005+ cookie->generation = au_figen(file);
22006+ }
22007+
22008+ ii_read_lock_child(inode);
22009+ fsstack_copy_attr_atime(inode, au_h_iptr(inode, au_ibstart(inode)));
22010+ ii_read_unlock(inode);
22011+
4f0767ce 22012+out_unlock:
1308ab2a 22013+ fi_read_unlock(file);
027c5e7a 22014+out_si:
1308ab2a 22015+ si_read_unlock(arg.sb);
4f0767ce 22016+out_mtx:
1308ab2a 22017+ mutex_unlock(&inode->i_mutex);
4f0767ce 22018+out:
1308ab2a 22019+ AuTraceErr(err);
22020+ return err;
22021+}
22022+
22023+static int au_rdu_ino(struct file *file, struct aufs_rdu *rdu)
22024+{
22025+ int err;
22026+ ino_t ino;
22027+ unsigned long long nent;
22028+ union au_rdu_ent_ul *u;
22029+ struct au_rdu_ent ent;
22030+ struct super_block *sb;
22031+
22032+ err = 0;
22033+ nent = rdu->nent;
22034+ u = &rdu->ent;
22035+ sb = file->f_dentry->d_sb;
22036+ si_read_lock(sb, AuLock_FLUSH);
22037+ while (nent-- > 0) {
9dbd164d 22038+ /* unnecessary to support mmap_sem since this is a dir */
1308ab2a 22039+ err = copy_from_user(&ent, u->e, sizeof(ent));
4a4d8108
AM
22040+ if (!err)
22041+ err = !access_ok(VERIFY_WRITE, &u->e->ino, sizeof(ino));
1308ab2a 22042+ if (unlikely(err)) {
22043+ err = -EFAULT;
22044+ AuTraceErr(err);
22045+ break;
22046+ }
22047+
22048+ /* AuDbg("b%d, i%llu\n", ent.bindex, ent.ino); */
22049+ if (!ent.wh)
22050+ err = au_ino(sb, ent.bindex, ent.ino, ent.type, &ino);
22051+ else
22052+ err = au_wh_ino(sb, ent.bindex, ent.ino, ent.type,
22053+ &ino);
22054+ if (unlikely(err)) {
22055+ AuTraceErr(err);
22056+ break;
22057+ }
22058+
22059+ err = __put_user(ino, &u->e->ino);
22060+ if (unlikely(err)) {
22061+ err = -EFAULT;
22062+ AuTraceErr(err);
22063+ break;
22064+ }
22065+ u->ul += au_rdu_len(ent.nlen);
22066+ }
22067+ si_read_unlock(sb);
22068+
22069+ return err;
22070+}
22071+
22072+/* ---------------------------------------------------------------------- */
22073+
22074+static int au_rdu_verify(struct aufs_rdu *rdu)
22075+{
b752ccd1 22076+ AuDbg("rdu{%llu, %p, %u | %u | %llu, %u, %u | "
1308ab2a 22077+ "%llu, b%d, 0x%x, g%u}\n",
b752ccd1 22078+ rdu->sz, rdu->ent.e, rdu->verify[AufsCtlRduV_SZ],
1308ab2a 22079+ rdu->blk,
22080+ rdu->rent, rdu->shwh, rdu->full,
22081+ rdu->cookie.h_pos, rdu->cookie.bindex, rdu->cookie.flags,
22082+ rdu->cookie.generation);
dece6358 22083+
b752ccd1 22084+ if (rdu->verify[AufsCtlRduV_SZ] == sizeof(*rdu))
1308ab2a 22085+ return 0;
dece6358 22086+
b752ccd1
AM
22087+ AuDbg("%u:%u\n",
22088+ rdu->verify[AufsCtlRduV_SZ], (unsigned int)sizeof(*rdu));
1308ab2a 22089+ return -EINVAL;
22090+}
22091+
22092+long au_rdu_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
dece6358 22093+{
1308ab2a 22094+ long err, e;
22095+ struct aufs_rdu rdu;
22096+ void __user *p = (void __user *)arg;
dece6358 22097+
1308ab2a 22098+ err = copy_from_user(&rdu, p, sizeof(rdu));
22099+ if (unlikely(err)) {
22100+ err = -EFAULT;
22101+ AuTraceErr(err);
22102+ goto out;
22103+ }
22104+ err = au_rdu_verify(&rdu);
dece6358
AM
22105+ if (unlikely(err))
22106+ goto out;
22107+
1308ab2a 22108+ switch (cmd) {
22109+ case AUFS_CTL_RDU:
22110+ err = au_rdu(file, &rdu);
22111+ if (unlikely(err))
22112+ break;
dece6358 22113+
1308ab2a 22114+ e = copy_to_user(p, &rdu, sizeof(rdu));
22115+ if (unlikely(e)) {
22116+ err = -EFAULT;
22117+ AuTraceErr(err);
22118+ }
22119+ break;
22120+ case AUFS_CTL_RDU_INO:
22121+ err = au_rdu_ino(file, &rdu);
22122+ break;
22123+
22124+ default:
4a4d8108 22125+ /* err = -ENOTTY; */
1308ab2a 22126+ err = -EINVAL;
22127+ }
dece6358 22128+
4f0767ce 22129+out:
1308ab2a 22130+ AuTraceErr(err);
22131+ return err;
1facf9fc 22132+}
b752ccd1
AM
22133+
22134+#ifdef CONFIG_COMPAT
22135+long au_rdu_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
22136+{
22137+ long err, e;
22138+ struct aufs_rdu rdu;
22139+ void __user *p = compat_ptr(arg);
22140+
22141+ /* todo: get_user()? */
22142+ err = copy_from_user(&rdu, p, sizeof(rdu));
22143+ if (unlikely(err)) {
22144+ err = -EFAULT;
22145+ AuTraceErr(err);
22146+ goto out;
22147+ }
22148+ rdu.ent.e = compat_ptr(rdu.ent.ul);
22149+ err = au_rdu_verify(&rdu);
22150+ if (unlikely(err))
22151+ goto out;
22152+
22153+ switch (cmd) {
22154+ case AUFS_CTL_RDU:
22155+ err = au_rdu(file, &rdu);
22156+ if (unlikely(err))
22157+ break;
22158+
22159+ rdu.ent.ul = ptr_to_compat(rdu.ent.e);
22160+ rdu.tail.ul = ptr_to_compat(rdu.tail.e);
22161+ e = copy_to_user(p, &rdu, sizeof(rdu));
22162+ if (unlikely(e)) {
22163+ err = -EFAULT;
22164+ AuTraceErr(err);
22165+ }
22166+ break;
22167+ case AUFS_CTL_RDU_INO:
22168+ err = au_rdu_ino(file, &rdu);
22169+ break;
22170+
22171+ default:
22172+ /* err = -ENOTTY; */
22173+ err = -EINVAL;
22174+ }
22175+
4f0767ce 22176+out:
b752ccd1
AM
22177+ AuTraceErr(err);
22178+ return err;
22179+}
22180+#endif
7f207e10
AM
22181diff -urN /usr/share/empty/fs/aufs/rwsem.h linux/fs/aufs/rwsem.h
22182--- /usr/share/empty/fs/aufs/rwsem.h 1970-01-01 01:00:00.000000000 +0100
7ce627cf 22183+++ linux/fs/aufs/rwsem.h 2012-05-22 09:06:08.870792417 +0200
f6c5ef8b 22184@@ -0,0 +1,188 @@
1facf9fc 22185+/*
f6c5ef8b 22186+ * Copyright (C) 2005-2012 Junjiro R. Okajima
1facf9fc 22187+ *
22188+ * This program, aufs is free software; you can redistribute it and/or modify
22189+ * it under the terms of the GNU General Public License as published by
22190+ * the Free Software Foundation; either version 2 of the License, or
22191+ * (at your option) any later version.
dece6358
AM
22192+ *
22193+ * This program is distributed in the hope that it will be useful,
22194+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
22195+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22196+ * GNU General Public License for more details.
22197+ *
22198+ * You should have received a copy of the GNU General Public License
22199+ * along with this program; if not, write to the Free Software
22200+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 22201+ */
22202+
22203+/*
22204+ * simple read-write semaphore wrappers
22205+ */
22206+
22207+#ifndef __AUFS_RWSEM_H__
22208+#define __AUFS_RWSEM_H__
22209+
22210+#ifdef __KERNEL__
22211+
4a4d8108 22212+#include "debug.h"
dece6358
AM
22213+
22214+struct au_rwsem {
22215+ struct rw_semaphore rwsem;
22216+#ifdef CONFIG_AUFS_DEBUG
22217+ /* just for debugging, not almighty counter */
22218+ atomic_t rcnt, wcnt;
22219+#endif
22220+};
22221+
22222+#ifdef CONFIG_AUFS_DEBUG
22223+#define AuDbgCntInit(rw) do { \
22224+ atomic_set(&(rw)->rcnt, 0); \
22225+ atomic_set(&(rw)->wcnt, 0); \
22226+ smp_mb(); /* atomic set */ \
22227+} while (0)
22228+
e49829fe 22229+#define AuDbgRcntInc(rw) atomic_inc(&(rw)->rcnt)
dece6358 22230+#define AuDbgRcntDec(rw) WARN_ON(atomic_dec_return(&(rw)->rcnt) < 0)
e49829fe 22231+#define AuDbgWcntInc(rw) atomic_inc(&(rw)->wcnt)
dece6358
AM
22232+#define AuDbgWcntDec(rw) WARN_ON(atomic_dec_return(&(rw)->wcnt) < 0)
22233+#else
22234+#define AuDbgCntInit(rw) do {} while (0)
22235+#define AuDbgRcntInc(rw) do {} while (0)
22236+#define AuDbgRcntDec(rw) do {} while (0)
22237+#define AuDbgWcntInc(rw) do {} while (0)
22238+#define AuDbgWcntDec(rw) do {} while (0)
22239+#endif /* CONFIG_AUFS_DEBUG */
22240+
22241+/* to debug easier, do not make them inlined functions */
22242+#define AuRwMustNoWaiters(rw) AuDebugOn(!list_empty(&(rw)->rwsem.wait_list))
22243+/* rwsem_is_locked() is unusable */
22244+#define AuRwMustReadLock(rw) AuDebugOn(atomic_read(&(rw)->rcnt) <= 0)
22245+#define AuRwMustWriteLock(rw) AuDebugOn(atomic_read(&(rw)->wcnt) <= 0)
22246+#define AuRwMustAnyLock(rw) AuDebugOn(atomic_read(&(rw)->rcnt) <= 0 \
22247+ && atomic_read(&(rw)->wcnt) <= 0)
22248+#define AuRwDestroy(rw) AuDebugOn(atomic_read(&(rw)->rcnt) \
22249+ || atomic_read(&(rw)->wcnt))
22250+
e49829fe
JR
22251+#define au_rw_class(rw, key) lockdep_set_class(&(rw)->rwsem, key)
22252+
dece6358
AM
22253+static inline void au_rw_init(struct au_rwsem *rw)
22254+{
22255+ AuDbgCntInit(rw);
22256+ init_rwsem(&rw->rwsem);
22257+}
22258+
22259+static inline void au_rw_init_wlock(struct au_rwsem *rw)
22260+{
22261+ au_rw_init(rw);
22262+ down_write(&rw->rwsem);
22263+ AuDbgWcntInc(rw);
22264+}
22265+
22266+static inline void au_rw_init_wlock_nested(struct au_rwsem *rw,
22267+ unsigned int lsc)
22268+{
22269+ au_rw_init(rw);
22270+ down_write_nested(&rw->rwsem, lsc);
22271+ AuDbgWcntInc(rw);
22272+}
22273+
22274+static inline void au_rw_read_lock(struct au_rwsem *rw)
22275+{
22276+ down_read(&rw->rwsem);
22277+ AuDbgRcntInc(rw);
22278+}
22279+
22280+static inline void au_rw_read_lock_nested(struct au_rwsem *rw, unsigned int lsc)
22281+{
22282+ down_read_nested(&rw->rwsem, lsc);
22283+ AuDbgRcntInc(rw);
22284+}
22285+
22286+static inline void au_rw_read_unlock(struct au_rwsem *rw)
22287+{
22288+ AuRwMustReadLock(rw);
22289+ AuDbgRcntDec(rw);
22290+ up_read(&rw->rwsem);
22291+}
22292+
22293+static inline void au_rw_dgrade_lock(struct au_rwsem *rw)
22294+{
22295+ AuRwMustWriteLock(rw);
22296+ AuDbgRcntInc(rw);
22297+ AuDbgWcntDec(rw);
22298+ downgrade_write(&rw->rwsem);
22299+}
22300+
22301+static inline void au_rw_write_lock(struct au_rwsem *rw)
22302+{
22303+ down_write(&rw->rwsem);
22304+ AuDbgWcntInc(rw);
22305+}
22306+
22307+static inline void au_rw_write_lock_nested(struct au_rwsem *rw,
22308+ unsigned int lsc)
22309+{
22310+ down_write_nested(&rw->rwsem, lsc);
22311+ AuDbgWcntInc(rw);
22312+}
1facf9fc 22313+
dece6358
AM
22314+static inline void au_rw_write_unlock(struct au_rwsem *rw)
22315+{
22316+ AuRwMustWriteLock(rw);
22317+ AuDbgWcntDec(rw);
22318+ up_write(&rw->rwsem);
22319+}
22320+
22321+/* why is not _nested version defined */
22322+static inline int au_rw_read_trylock(struct au_rwsem *rw)
22323+{
22324+ int ret = down_read_trylock(&rw->rwsem);
22325+ if (ret)
22326+ AuDbgRcntInc(rw);
22327+ return ret;
22328+}
22329+
22330+static inline int au_rw_write_trylock(struct au_rwsem *rw)
22331+{
22332+ int ret = down_write_trylock(&rw->rwsem);
22333+ if (ret)
22334+ AuDbgWcntInc(rw);
22335+ return ret;
22336+}
22337+
22338+#undef AuDbgCntInit
22339+#undef AuDbgRcntInc
22340+#undef AuDbgRcntDec
22341+#undef AuDbgWcntInc
22342+#undef AuDbgWcntDec
1facf9fc 22343+
22344+#define AuSimpleLockRwsemFuncs(prefix, param, rwsem) \
22345+static inline void prefix##_read_lock(param) \
dece6358 22346+{ au_rw_read_lock(rwsem); } \
1facf9fc 22347+static inline void prefix##_write_lock(param) \
dece6358 22348+{ au_rw_write_lock(rwsem); } \
1facf9fc 22349+static inline int prefix##_read_trylock(param) \
dece6358 22350+{ return au_rw_read_trylock(rwsem); } \
1facf9fc 22351+static inline int prefix##_write_trylock(param) \
dece6358 22352+{ return au_rw_write_trylock(rwsem); }
1facf9fc 22353+/* why is not _nested version defined */
22354+/* static inline void prefix##_read_trylock_nested(param, lsc)
dece6358 22355+{ au_rw_read_trylock_nested(rwsem, lsc)); }
1facf9fc 22356+static inline void prefix##_write_trylock_nestd(param, lsc)
dece6358 22357+{ au_rw_write_trylock_nested(rwsem, lsc); } */
1facf9fc 22358+
22359+#define AuSimpleUnlockRwsemFuncs(prefix, param, rwsem) \
22360+static inline void prefix##_read_unlock(param) \
dece6358 22361+{ au_rw_read_unlock(rwsem); } \
1facf9fc 22362+static inline void prefix##_write_unlock(param) \
dece6358 22363+{ au_rw_write_unlock(rwsem); } \
1facf9fc 22364+static inline void prefix##_downgrade_lock(param) \
dece6358 22365+{ au_rw_dgrade_lock(rwsem); }
1facf9fc 22366+
22367+#define AuSimpleRwsemFuncs(prefix, param, rwsem) \
22368+ AuSimpleLockRwsemFuncs(prefix, param, rwsem) \
22369+ AuSimpleUnlockRwsemFuncs(prefix, param, rwsem)
22370+
22371+#endif /* __KERNEL__ */
22372+#endif /* __AUFS_RWSEM_H__ */
7f207e10
AM
22373diff -urN /usr/share/empty/fs/aufs/sbinfo.c linux/fs/aufs/sbinfo.c
22374--- /usr/share/empty/fs/aufs/sbinfo.c 1970-01-01 01:00:00.000000000 +0100
7ce627cf 22375+++ linux/fs/aufs/sbinfo.c 2012-05-22 09:06:08.870792417 +0200
f6c5ef8b 22376@@ -0,0 +1,343 @@
1facf9fc 22377+/*
f6c5ef8b 22378+ * Copyright (C) 2005-2012 Junjiro R. Okajima
1facf9fc 22379+ *
22380+ * This program, aufs is free software; you can redistribute it and/or modify
22381+ * it under the terms of the GNU General Public License as published by
22382+ * the Free Software Foundation; either version 2 of the License, or
22383+ * (at your option) any later version.
dece6358
AM
22384+ *
22385+ * This program is distributed in the hope that it will be useful,
22386+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
22387+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22388+ * GNU General Public License for more details.
22389+ *
22390+ * You should have received a copy of the GNU General Public License
22391+ * along with this program; if not, write to the Free Software
22392+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 22393+ */
22394+
22395+/*
22396+ * superblock private data
22397+ */
22398+
22399+#include "aufs.h"
22400+
22401+/*
22402+ * they are necessary regardless sysfs is disabled.
22403+ */
22404+void au_si_free(struct kobject *kobj)
22405+{
22406+ struct au_sbinfo *sbinfo;
b752ccd1 22407+ char *locked __maybe_unused; /* debug only */
1facf9fc 22408+
22409+ sbinfo = container_of(kobj, struct au_sbinfo, si_kobj);
22410+ AuDebugOn(!list_empty(&sbinfo->si_plink.head));
e49829fe 22411+ AuDebugOn(atomic_read(&sbinfo->si_nowait.nw_len));
1facf9fc 22412+
e49829fe 22413+ au_rw_write_lock(&sbinfo->si_rwsem);
1facf9fc 22414+ au_br_free(sbinfo);
e49829fe 22415+ au_rw_write_unlock(&sbinfo->si_rwsem);
b752ccd1
AM
22416+
22417+ AuDebugOn(radix_tree_gang_lookup
22418+ (&sbinfo->au_si_pid.tree, (void **)&locked,
22419+ /*first_index*/PID_MAX_DEFAULT - 1,
22420+ /*max_items*/sizeof(locked)/sizeof(*locked)));
22421+
1facf9fc 22422+ kfree(sbinfo->si_branch);
b752ccd1 22423+ kfree(sbinfo->au_si_pid.bitmap);
1facf9fc 22424+ mutex_destroy(&sbinfo->si_xib_mtx);
dece6358 22425+ AuRwDestroy(&sbinfo->si_rwsem);
1facf9fc 22426+
22427+ kfree(sbinfo);
22428+}
22429+
22430+int au_si_alloc(struct super_block *sb)
22431+{
22432+ int err;
22433+ struct au_sbinfo *sbinfo;
e49829fe 22434+ static struct lock_class_key aufs_si;
1facf9fc 22435+
22436+ err = -ENOMEM;
4a4d8108 22437+ sbinfo = kzalloc(sizeof(*sbinfo), GFP_NOFS);
1facf9fc 22438+ if (unlikely(!sbinfo))
22439+ goto out;
22440+
b752ccd1
AM
22441+ BUILD_BUG_ON(sizeof(unsigned long) !=
22442+ sizeof(*sbinfo->au_si_pid.bitmap));
22443+ sbinfo->au_si_pid.bitmap = kcalloc(BITS_TO_LONGS(PID_MAX_DEFAULT),
22444+ sizeof(*sbinfo->au_si_pid.bitmap),
22445+ GFP_NOFS);
22446+ if (unlikely(!sbinfo->au_si_pid.bitmap))
22447+ goto out_sbinfo;
22448+
1facf9fc 22449+ /* will be reallocated separately */
22450+ sbinfo->si_branch = kzalloc(sizeof(*sbinfo->si_branch), GFP_NOFS);
22451+ if (unlikely(!sbinfo->si_branch))
b752ccd1 22452+ goto out_pidmap;
1facf9fc 22453+
1facf9fc 22454+ err = sysaufs_si_init(sbinfo);
22455+ if (unlikely(err))
22456+ goto out_br;
22457+
22458+ au_nwt_init(&sbinfo->si_nowait);
dece6358 22459+ au_rw_init_wlock(&sbinfo->si_rwsem);
e49829fe 22460+ au_rw_class(&sbinfo->si_rwsem, &aufs_si);
b752ccd1
AM
22461+ spin_lock_init(&sbinfo->au_si_pid.tree_lock);
22462+ INIT_RADIX_TREE(&sbinfo->au_si_pid.tree, GFP_ATOMIC | __GFP_NOFAIL);
22463+
7f207e10 22464+ atomic_long_set(&sbinfo->si_ninodes, 0);
7f207e10
AM
22465+ atomic_long_set(&sbinfo->si_nfiles, 0);
22466+
1facf9fc 22467+ sbinfo->si_bend = -1;
1facf9fc 22468+
22469+ sbinfo->si_wbr_copyup = AuWbrCopyup_Def;
22470+ sbinfo->si_wbr_create = AuWbrCreate_Def;
4a4d8108
AM
22471+ sbinfo->si_wbr_copyup_ops = au_wbr_copyup_ops + sbinfo->si_wbr_copyup;
22472+ sbinfo->si_wbr_create_ops = au_wbr_create_ops + sbinfo->si_wbr_create;
1facf9fc 22473+
e49829fe 22474+ sbinfo->si_mntflags = au_opts_plink(AuOpt_Def);
1facf9fc 22475+
1facf9fc 22476+ mutex_init(&sbinfo->si_xib_mtx);
1facf9fc 22477+ sbinfo->si_xino_brid = -1;
22478+ /* leave si_xib_last_pindex and si_xib_next_bit */
22479+
e49829fe 22480+ sbinfo->si_rdcache = msecs_to_jiffies(AUFS_RDCACHE_DEF * MSEC_PER_SEC);
1facf9fc 22481+ sbinfo->si_rdblk = AUFS_RDBLK_DEF;
22482+ sbinfo->si_rdhash = AUFS_RDHASH_DEF;
22483+ sbinfo->si_dirwh = AUFS_DIRWH_DEF;
22484+
22485+ au_spl_init(&sbinfo->si_plink);
22486+ init_waitqueue_head(&sbinfo->si_plink_wq);
4a4d8108 22487+ spin_lock_init(&sbinfo->si_plink_maint_lock);
1facf9fc 22488+
22489+ /* leave other members for sysaufs and si_mnt. */
22490+ sbinfo->si_sb = sb;
22491+ sb->s_fs_info = sbinfo;
b752ccd1 22492+ si_pid_set(sb);
1facf9fc 22493+ au_debug_sbinfo_init(sbinfo);
22494+ return 0; /* success */
22495+
4f0767ce 22496+out_br:
1facf9fc 22497+ kfree(sbinfo->si_branch);
4f0767ce 22498+out_pidmap:
b752ccd1 22499+ kfree(sbinfo->au_si_pid.bitmap);
4f0767ce 22500+out_sbinfo:
1facf9fc 22501+ kfree(sbinfo);
4f0767ce 22502+out:
1facf9fc 22503+ return err;
22504+}
22505+
22506+int au_sbr_realloc(struct au_sbinfo *sbinfo, int nbr)
22507+{
22508+ int err, sz;
22509+ struct au_branch **brp;
22510+
dece6358
AM
22511+ AuRwMustWriteLock(&sbinfo->si_rwsem);
22512+
1facf9fc 22513+ err = -ENOMEM;
22514+ sz = sizeof(*brp) * (sbinfo->si_bend + 1);
22515+ if (unlikely(!sz))
22516+ sz = sizeof(*brp);
22517+ brp = au_kzrealloc(sbinfo->si_branch, sz, sizeof(*brp) * nbr, GFP_NOFS);
22518+ if (brp) {
22519+ sbinfo->si_branch = brp;
22520+ err = 0;
22521+ }
22522+
22523+ return err;
22524+}
22525+
22526+/* ---------------------------------------------------------------------- */
22527+
22528+unsigned int au_sigen_inc(struct super_block *sb)
22529+{
22530+ unsigned int gen;
22531+
dece6358
AM
22532+ SiMustWriteLock(sb);
22533+
1facf9fc 22534+ gen = ++au_sbi(sb)->si_generation;
22535+ au_update_digen(sb->s_root);
22536+ au_update_iigen(sb->s_root->d_inode);
22537+ sb->s_root->d_inode->i_version++;
22538+ return gen;
22539+}
22540+
22541+aufs_bindex_t au_new_br_id(struct super_block *sb)
22542+{
22543+ aufs_bindex_t br_id;
22544+ int i;
22545+ struct au_sbinfo *sbinfo;
22546+
dece6358
AM
22547+ SiMustWriteLock(sb);
22548+
1facf9fc 22549+ sbinfo = au_sbi(sb);
22550+ for (i = 0; i <= AUFS_BRANCH_MAX; i++) {
22551+ br_id = ++sbinfo->si_last_br_id;
7f207e10 22552+ AuDebugOn(br_id < 0);
1facf9fc 22553+ if (br_id && au_br_index(sb, br_id) < 0)
22554+ return br_id;
22555+ }
22556+
22557+ return -1;
22558+}
22559+
22560+/* ---------------------------------------------------------------------- */
22561+
e49829fe
JR
22562+/* it is ok that new 'nwt' tasks are appended while we are sleeping */
22563+int si_read_lock(struct super_block *sb, int flags)
22564+{
22565+ int err;
22566+
22567+ err = 0;
22568+ if (au_ftest_lock(flags, FLUSH))
22569+ au_nwt_flush(&au_sbi(sb)->si_nowait);
22570+
22571+ si_noflush_read_lock(sb);
22572+ err = au_plink_maint(sb, flags);
22573+ if (unlikely(err))
22574+ si_read_unlock(sb);
22575+
22576+ return err;
22577+}
22578+
22579+int si_write_lock(struct super_block *sb, int flags)
22580+{
22581+ int err;
22582+
22583+ if (au_ftest_lock(flags, FLUSH))
22584+ au_nwt_flush(&au_sbi(sb)->si_nowait);
22585+
22586+ si_noflush_write_lock(sb);
22587+ err = au_plink_maint(sb, flags);
22588+ if (unlikely(err))
22589+ si_write_unlock(sb);
22590+
22591+ return err;
22592+}
22593+
1facf9fc 22594+/* dentry and super_block lock. call at entry point */
e49829fe 22595+int aufs_read_lock(struct dentry *dentry, int flags)
1facf9fc 22596+{
e49829fe 22597+ int err;
027c5e7a 22598+ struct super_block *sb;
e49829fe 22599+
027c5e7a
AM
22600+ sb = dentry->d_sb;
22601+ err = si_read_lock(sb, flags);
22602+ if (unlikely(err))
22603+ goto out;
22604+
22605+ if (au_ftest_lock(flags, DW))
22606+ di_write_lock_child(dentry);
22607+ else
22608+ di_read_lock_child(dentry, flags);
22609+
22610+ if (au_ftest_lock(flags, GEN)) {
22611+ err = au_digen_test(dentry, au_sigen(sb));
22612+ AuDebugOn(!err && au_dbrange_test(dentry));
22613+ if (unlikely(err))
22614+ aufs_read_unlock(dentry, flags);
e49829fe
JR
22615+ }
22616+
027c5e7a 22617+out:
e49829fe 22618+ return err;
1facf9fc 22619+}
22620+
22621+void aufs_read_unlock(struct dentry *dentry, int flags)
22622+{
22623+ if (au_ftest_lock(flags, DW))
22624+ di_write_unlock(dentry);
22625+ else
22626+ di_read_unlock(dentry, flags);
22627+ si_read_unlock(dentry->d_sb);
22628+}
22629+
22630+void aufs_write_lock(struct dentry *dentry)
22631+{
e49829fe 22632+ si_write_lock(dentry->d_sb, AuLock_FLUSH | AuLock_NOPLMW);
1facf9fc 22633+ di_write_lock_child(dentry);
22634+}
22635+
22636+void aufs_write_unlock(struct dentry *dentry)
22637+{
22638+ di_write_unlock(dentry);
22639+ si_write_unlock(dentry->d_sb);
22640+}
22641+
e49829fe 22642+int aufs_read_and_write_lock2(struct dentry *d1, struct dentry *d2, int flags)
1facf9fc 22643+{
e49829fe 22644+ int err;
027c5e7a
AM
22645+ unsigned int sigen;
22646+ struct super_block *sb;
e49829fe 22647+
027c5e7a
AM
22648+ sb = d1->d_sb;
22649+ err = si_read_lock(sb, flags);
22650+ if (unlikely(err))
22651+ goto out;
22652+
22653+ di_write_lock2_child(d1, d2, au_ftest_lock(flags, DIR));
22654+
22655+ if (au_ftest_lock(flags, GEN)) {
22656+ sigen = au_sigen(sb);
22657+ err = au_digen_test(d1, sigen);
22658+ AuDebugOn(!err && au_dbrange_test(d1));
22659+ if (!err) {
22660+ err = au_digen_test(d2, sigen);
22661+ AuDebugOn(!err && au_dbrange_test(d2));
22662+ }
22663+ if (unlikely(err))
22664+ aufs_read_and_write_unlock2(d1, d2);
22665+ }
22666+
22667+out:
e49829fe 22668+ return err;
1facf9fc 22669+}
22670+
22671+void aufs_read_and_write_unlock2(struct dentry *d1, struct dentry *d2)
22672+{
22673+ di_write_unlock2(d1, d2);
22674+ si_read_unlock(d1->d_sb);
22675+}
b752ccd1
AM
22676+
22677+/* ---------------------------------------------------------------------- */
22678+
22679+int si_pid_test_slow(struct super_block *sb)
22680+{
22681+ void *p;
22682+
22683+ rcu_read_lock();
22684+ p = radix_tree_lookup(&au_sbi(sb)->au_si_pid.tree, current->pid);
22685+ rcu_read_unlock();
22686+
027c5e7a 22687+ return (long)!!p;
b752ccd1
AM
22688+}
22689+
22690+void si_pid_set_slow(struct super_block *sb)
22691+{
22692+ int err;
22693+ struct au_sbinfo *sbinfo;
22694+
22695+ AuDebugOn(si_pid_test_slow(sb));
22696+
22697+ sbinfo = au_sbi(sb);
22698+ err = radix_tree_preload(GFP_NOFS | __GFP_NOFAIL);
22699+ AuDebugOn(err);
22700+ spin_lock(&sbinfo->au_si_pid.tree_lock);
22701+ err = radix_tree_insert(&sbinfo->au_si_pid.tree, current->pid,
027c5e7a 22702+ /*any valid ptr*/sb);
b752ccd1
AM
22703+ spin_unlock(&sbinfo->au_si_pid.tree_lock);
22704+ AuDebugOn(err);
22705+ radix_tree_preload_end();
22706+}
22707+
22708+void si_pid_clr_slow(struct super_block *sb)
22709+{
22710+ void *p;
22711+ struct au_sbinfo *sbinfo;
22712+
22713+ AuDebugOn(!si_pid_test_slow(sb));
22714+
22715+ sbinfo = au_sbi(sb);
22716+ spin_lock(&sbinfo->au_si_pid.tree_lock);
22717+ p = radix_tree_delete(&sbinfo->au_si_pid.tree, current->pid);
22718+ spin_unlock(&sbinfo->au_si_pid.tree_lock);
b752ccd1 22719+}
7f207e10
AM
22720diff -urN /usr/share/empty/fs/aufs/spl.h linux/fs/aufs/spl.h
22721--- /usr/share/empty/fs/aufs/spl.h 1970-01-01 01:00:00.000000000 +0100
7ce627cf 22722+++ linux/fs/aufs/spl.h 2012-05-22 09:06:08.870792417 +0200
f6c5ef8b 22723@@ -0,0 +1,62 @@
1facf9fc 22724+/*
f6c5ef8b 22725+ * Copyright (C) 2005-2012 Junjiro R. Okajima
1facf9fc 22726+ *
22727+ * This program, aufs is free software; you can redistribute it and/or modify
22728+ * it under the terms of the GNU General Public License as published by
22729+ * the Free Software Foundation; either version 2 of the License, or
22730+ * (at your option) any later version.
dece6358
AM
22731+ *
22732+ * This program is distributed in the hope that it will be useful,
22733+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
22734+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22735+ * GNU General Public License for more details.
22736+ *
22737+ * You should have received a copy of the GNU General Public License
22738+ * along with this program; if not, write to the Free Software
22739+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 22740+ */
22741+
22742+/*
22743+ * simple list protected by a spinlock
22744+ */
22745+
22746+#ifndef __AUFS_SPL_H__
22747+#define __AUFS_SPL_H__
22748+
22749+#ifdef __KERNEL__
22750+
1facf9fc 22751+struct au_splhead {
22752+ spinlock_t spin;
22753+ struct list_head head;
22754+};
22755+
22756+static inline void au_spl_init(struct au_splhead *spl)
22757+{
22758+ spin_lock_init(&spl->spin);
22759+ INIT_LIST_HEAD(&spl->head);
22760+}
22761+
22762+static inline void au_spl_add(struct list_head *list, struct au_splhead *spl)
22763+{
22764+ spin_lock(&spl->spin);
22765+ list_add(list, &spl->head);
22766+ spin_unlock(&spl->spin);
22767+}
22768+
22769+static inline void au_spl_del(struct list_head *list, struct au_splhead *spl)
22770+{
22771+ spin_lock(&spl->spin);
22772+ list_del(list);
22773+ spin_unlock(&spl->spin);
22774+}
22775+
4a4d8108
AM
22776+static inline void au_spl_del_rcu(struct list_head *list,
22777+ struct au_splhead *spl)
22778+{
22779+ spin_lock(&spl->spin);
22780+ list_del_rcu(list);
22781+ spin_unlock(&spl->spin);
22782+}
22783+
1facf9fc 22784+#endif /* __KERNEL__ */
22785+#endif /* __AUFS_SPL_H__ */
7f207e10
AM
22786diff -urN /usr/share/empty/fs/aufs/super.c linux/fs/aufs/super.c
22787--- /usr/share/empty/fs/aufs/super.c 1970-01-01 01:00:00.000000000 +0100
7ce627cf 22788+++ linux/fs/aufs/super.c 2012-05-22 09:06:08.870792417 +0200
92d182d2 22789@@ -0,0 +1,962 @@
1facf9fc 22790+/*
f6c5ef8b 22791+ * Copyright (C) 2005-2012 Junjiro R. Okajima
1facf9fc 22792+ *
22793+ * This program, aufs is free software; you can redistribute it and/or modify
22794+ * it under the terms of the GNU General Public License as published by
22795+ * the Free Software Foundation; either version 2 of the License, or
22796+ * (at your option) any later version.
dece6358
AM
22797+ *
22798+ * This program is distributed in the hope that it will be useful,
22799+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
22800+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22801+ * GNU General Public License for more details.
22802+ *
22803+ * You should have received a copy of the GNU General Public License
22804+ * along with this program; if not, write to the Free Software
22805+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 22806+ */
22807+
22808+/*
22809+ * mount and super_block operations
22810+ */
22811+
f6c5ef8b 22812+#include <linux/mm.h>
dece6358 22813+#include <linux/module.h>
1facf9fc 22814+#include <linux/seq_file.h>
22815+#include <linux/statfs.h>
7f207e10
AM
22816+#include <linux/vmalloc.h>
22817+#include <linux/writeback.h>
1facf9fc 22818+#include "aufs.h"
22819+
22820+/*
22821+ * super_operations
22822+ */
22823+static struct inode *aufs_alloc_inode(struct super_block *sb __maybe_unused)
22824+{
22825+ struct au_icntnr *c;
22826+
22827+ c = au_cache_alloc_icntnr();
22828+ if (c) {
027c5e7a 22829+ au_icntnr_init(c);
1facf9fc 22830+ c->vfs_inode.i_version = 1; /* sigen(sb); */
22831+ c->iinfo.ii_hinode = NULL;
22832+ return &c->vfs_inode;
22833+ }
22834+ return NULL;
22835+}
22836+
027c5e7a
AM
22837+static void aufs_destroy_inode_cb(struct rcu_head *head)
22838+{
22839+ struct inode *inode = container_of(head, struct inode, i_rcu);
22840+
22841+ INIT_LIST_HEAD(&inode->i_dentry);
22842+ au_cache_free_icntnr(container_of(inode, struct au_icntnr, vfs_inode));
22843+}
22844+
1facf9fc 22845+static void aufs_destroy_inode(struct inode *inode)
22846+{
22847+ au_iinfo_fin(inode);
027c5e7a 22848+ call_rcu(&inode->i_rcu, aufs_destroy_inode_cb);
1facf9fc 22849+}
22850+
22851+struct inode *au_iget_locked(struct super_block *sb, ino_t ino)
22852+{
22853+ struct inode *inode;
22854+ int err;
22855+
22856+ inode = iget_locked(sb, ino);
22857+ if (unlikely(!inode)) {
22858+ inode = ERR_PTR(-ENOMEM);
22859+ goto out;
22860+ }
22861+ if (!(inode->i_state & I_NEW))
22862+ goto out;
22863+
22864+ err = au_xigen_new(inode);
22865+ if (!err)
22866+ err = au_iinfo_init(inode);
22867+ if (!err)
22868+ inode->i_version++;
22869+ else {
22870+ iget_failed(inode);
22871+ inode = ERR_PTR(err);
22872+ }
22873+
4f0767ce 22874+out:
1facf9fc 22875+ /* never return NULL */
22876+ AuDebugOn(!inode);
22877+ AuTraceErrPtr(inode);
22878+ return inode;
22879+}
22880+
22881+/* lock free root dinfo */
22882+static int au_show_brs(struct seq_file *seq, struct super_block *sb)
22883+{
22884+ int err;
22885+ aufs_bindex_t bindex, bend;
22886+ struct path path;
4a4d8108 22887+ struct au_hdentry *hdp;
1facf9fc 22888+ struct au_branch *br;
1e00d052 22889+ char *perm;
1facf9fc 22890+
22891+ err = 0;
22892+ bend = au_sbend(sb);
4a4d8108 22893+ hdp = au_di(sb->s_root)->di_hdentry;
1facf9fc 22894+ for (bindex = 0; !err && bindex <= bend; bindex++) {
22895+ br = au_sbr(sb, bindex);
22896+ path.mnt = br->br_mnt;
4a4d8108 22897+ path.dentry = hdp[bindex].hd_dentry;
1facf9fc 22898+ err = au_seq_path(seq, &path);
1e00d052
AM
22899+ if (err > 0) {
22900+ perm = au_optstr_br_perm(br->br_perm);
22901+ if (perm) {
22902+ err = seq_printf(seq, "=%s", perm);
22903+ kfree(perm);
22904+ if (err == -1)
22905+ err = -E2BIG;
22906+ } else
22907+ err = -ENOMEM;
22908+ }
1facf9fc 22909+ if (!err && bindex != bend)
22910+ err = seq_putc(seq, ':');
22911+ }
22912+
22913+ return err;
22914+}
22915+
22916+static void au_show_wbr_create(struct seq_file *m, int v,
22917+ struct au_sbinfo *sbinfo)
22918+{
22919+ const char *pat;
22920+
dece6358
AM
22921+ AuRwMustAnyLock(&sbinfo->si_rwsem);
22922+
1facf9fc 22923+ seq_printf(m, ",create=");
22924+ pat = au_optstr_wbr_create(v);
22925+ switch (v) {
22926+ case AuWbrCreate_TDP:
22927+ case AuWbrCreate_RR:
22928+ case AuWbrCreate_MFS:
22929+ case AuWbrCreate_PMFS:
22930+ seq_printf(m, pat);
22931+ break;
22932+ case AuWbrCreate_MFSV:
22933+ seq_printf(m, /*pat*/"mfs:%lu",
e49829fe
JR
22934+ jiffies_to_msecs(sbinfo->si_wbr_mfs.mfs_expire)
22935+ / MSEC_PER_SEC);
1facf9fc 22936+ break;
22937+ case AuWbrCreate_PMFSV:
22938+ seq_printf(m, /*pat*/"pmfs:%lu",
e49829fe
JR
22939+ jiffies_to_msecs(sbinfo->si_wbr_mfs.mfs_expire)
22940+ / MSEC_PER_SEC);
1facf9fc 22941+ break;
22942+ case AuWbrCreate_MFSRR:
22943+ seq_printf(m, /*pat*/"mfsrr:%llu",
22944+ sbinfo->si_wbr_mfs.mfsrr_watermark);
22945+ break;
22946+ case AuWbrCreate_MFSRRV:
22947+ seq_printf(m, /*pat*/"mfsrr:%llu:%lu",
22948+ sbinfo->si_wbr_mfs.mfsrr_watermark,
e49829fe
JR
22949+ jiffies_to_msecs(sbinfo->si_wbr_mfs.mfs_expire)
22950+ / MSEC_PER_SEC);
1facf9fc 22951+ break;
22952+ }
22953+}
22954+
7eafdf33 22955+static int au_show_xino(struct seq_file *seq, struct super_block *sb)
1facf9fc 22956+{
22957+#ifdef CONFIG_SYSFS
22958+ return 0;
22959+#else
22960+ int err;
22961+ const int len = sizeof(AUFS_XINO_FNAME) - 1;
22962+ aufs_bindex_t bindex, brid;
1facf9fc 22963+ struct qstr *name;
22964+ struct file *f;
22965+ struct dentry *d, *h_root;
4a4d8108 22966+ struct au_hdentry *hdp;
1facf9fc 22967+
dece6358
AM
22968+ AuRwMustAnyLock(&sbinfo->si_rwsem);
22969+
1facf9fc 22970+ err = 0;
1facf9fc 22971+ f = au_sbi(sb)->si_xib;
22972+ if (!f)
22973+ goto out;
22974+
22975+ /* stop printing the default xino path on the first writable branch */
22976+ h_root = NULL;
22977+ brid = au_xino_brid(sb);
22978+ if (brid >= 0) {
22979+ bindex = au_br_index(sb, brid);
4a4d8108
AM
22980+ hdp = au_di(sb->s_root)->di_hdentry;
22981+ h_root = hdp[0 + bindex].hd_dentry;
1facf9fc 22982+ }
22983+ d = f->f_dentry;
22984+ name = &d->d_name;
22985+ /* safe ->d_parent because the file is unlinked */
22986+ if (d->d_parent == h_root
22987+ && name->len == len
22988+ && !memcmp(name->name, AUFS_XINO_FNAME, len))
22989+ goto out;
22990+
22991+ seq_puts(seq, ",xino=");
22992+ err = au_xino_path(seq, f);
22993+
4f0767ce 22994+out:
1facf9fc 22995+ return err;
22996+#endif
22997+}
22998+
22999+/* seq_file will re-call me in case of too long string */
7eafdf33 23000+static int aufs_show_options(struct seq_file *m, struct dentry *dentry)
1facf9fc 23001+{
027c5e7a 23002+ int err;
1facf9fc 23003+ unsigned int mnt_flags, v;
23004+ struct super_block *sb;
23005+ struct au_sbinfo *sbinfo;
23006+
23007+#define AuBool(name, str) do { \
23008+ v = au_opt_test(mnt_flags, name); \
23009+ if (v != au_opt_test(AuOpt_Def, name)) \
23010+ seq_printf(m, ",%s" #str, v ? "" : "no"); \
23011+} while (0)
23012+
23013+#define AuStr(name, str) do { \
23014+ v = mnt_flags & AuOptMask_##name; \
23015+ if (v != (AuOpt_Def & AuOptMask_##name)) \
23016+ seq_printf(m, "," #str "=%s", au_optstr_##str(v)); \
23017+} while (0)
23018+
23019+#define AuUInt(name, str, val) do { \
23020+ if (val != AUFS_##name##_DEF) \
23021+ seq_printf(m, "," #str "=%u", val); \
23022+} while (0)
23023+
23024+ /* lock free root dinfo */
7eafdf33 23025+ sb = dentry->d_sb;
1facf9fc 23026+ si_noflush_read_lock(sb);
23027+ sbinfo = au_sbi(sb);
23028+ seq_printf(m, ",si=%lx", sysaufs_si_id(sbinfo));
23029+
23030+ mnt_flags = au_mntflags(sb);
23031+ if (au_opt_test(mnt_flags, XINO)) {
7eafdf33 23032+ err = au_show_xino(m, sb);
1facf9fc 23033+ if (unlikely(err))
23034+ goto out;
23035+ } else
23036+ seq_puts(m, ",noxino");
23037+
23038+ AuBool(TRUNC_XINO, trunc_xino);
23039+ AuStr(UDBA, udba);
dece6358 23040+ AuBool(SHWH, shwh);
1facf9fc 23041+ AuBool(PLINK, plink);
4a4d8108 23042+ AuBool(DIO, dio);
1facf9fc 23043+ /* AuBool(DIRPERM1, dirperm1); */
23044+ /* AuBool(REFROF, refrof); */
23045+
23046+ v = sbinfo->si_wbr_create;
23047+ if (v != AuWbrCreate_Def)
23048+ au_show_wbr_create(m, v, sbinfo);
23049+
23050+ v = sbinfo->si_wbr_copyup;
23051+ if (v != AuWbrCopyup_Def)
23052+ seq_printf(m, ",cpup=%s", au_optstr_wbr_copyup(v));
23053+
23054+ v = au_opt_test(mnt_flags, ALWAYS_DIROPQ);
23055+ if (v != au_opt_test(AuOpt_Def, ALWAYS_DIROPQ))
23056+ seq_printf(m, ",diropq=%c", v ? 'a' : 'w');
23057+
23058+ AuUInt(DIRWH, dirwh, sbinfo->si_dirwh);
23059+
027c5e7a
AM
23060+ v = jiffies_to_msecs(sbinfo->si_rdcache) / MSEC_PER_SEC;
23061+ AuUInt(RDCACHE, rdcache, v);
1facf9fc 23062+
23063+ AuUInt(RDBLK, rdblk, sbinfo->si_rdblk);
23064+ AuUInt(RDHASH, rdhash, sbinfo->si_rdhash);
23065+
23066+ AuBool(SUM, sum);
23067+ /* AuBool(SUM_W, wsum); */
23068+ AuBool(WARN_PERM, warn_perm);
23069+ AuBool(VERBOSE, verbose);
23070+
4f0767ce 23071+out:
1facf9fc 23072+ /* be sure to print "br:" last */
23073+ if (!sysaufs_brs) {
23074+ seq_puts(m, ",br:");
23075+ au_show_brs(m, sb);
23076+ }
23077+ si_read_unlock(sb);
23078+ return 0;
23079+
1facf9fc 23080+#undef AuBool
23081+#undef AuStr
4a4d8108 23082+#undef AuUInt
1facf9fc 23083+}
23084+
23085+/* ---------------------------------------------------------------------- */
23086+
23087+/* sum mode which returns the summation for statfs(2) */
23088+
23089+static u64 au_add_till_max(u64 a, u64 b)
23090+{
23091+ u64 old;
23092+
23093+ old = a;
23094+ a += b;
92d182d2
AM
23095+ if (old <= a)
23096+ return a;
23097+ return ULLONG_MAX;
23098+}
23099+
23100+static u64 au_mul_till_max(u64 a, long mul)
23101+{
23102+ u64 old;
23103+
23104+ old = a;
23105+ a *= mul;
23106+ if (old <= a)
1facf9fc 23107+ return a;
23108+ return ULLONG_MAX;
23109+}
23110+
23111+static int au_statfs_sum(struct super_block *sb, struct kstatfs *buf)
23112+{
23113+ int err;
92d182d2 23114+ long bsize, factor;
1facf9fc 23115+ u64 blocks, bfree, bavail, files, ffree;
23116+ aufs_bindex_t bend, bindex, i;
23117+ unsigned char shared;
7f207e10 23118+ struct path h_path;
1facf9fc 23119+ struct super_block *h_sb;
23120+
92d182d2
AM
23121+ err = 0;
23122+ bsize = LONG_MAX;
23123+ files = 0;
23124+ ffree = 0;
1facf9fc 23125+ blocks = 0;
23126+ bfree = 0;
23127+ bavail = 0;
1facf9fc 23128+ bend = au_sbend(sb);
92d182d2 23129+ for (bindex = 0; bindex <= bend; bindex++) {
7f207e10
AM
23130+ h_path.mnt = au_sbr_mnt(sb, bindex);
23131+ h_sb = h_path.mnt->mnt_sb;
1facf9fc 23132+ shared = 0;
92d182d2 23133+ for (i = 0; !shared && i < bindex; i++)
1facf9fc 23134+ shared = (au_sbr_sb(sb, i) == h_sb);
23135+ if (shared)
23136+ continue;
23137+
23138+ /* sb->s_root for NFS is unreliable */
7f207e10
AM
23139+ h_path.dentry = h_path.mnt->mnt_root;
23140+ err = vfs_statfs(&h_path, buf);
1facf9fc 23141+ if (unlikely(err))
23142+ goto out;
23143+
92d182d2
AM
23144+ if (bsize > buf->f_bsize) {
23145+ /*
23146+ * we will reduce bsize, so we have to expand blocks
23147+ * etc. to match them again
23148+ */
23149+ factor = (bsize / buf->f_bsize);
23150+ blocks = au_mul_till_max(blocks, factor);
23151+ bfree = au_mul_till_max(bfree, factor);
23152+ bavail = au_mul_till_max(bavail, factor);
23153+ bsize = buf->f_bsize;
23154+ }
23155+
23156+ factor = (buf->f_bsize / bsize);
23157+ blocks = au_add_till_max(blocks,
23158+ au_mul_till_max(buf->f_blocks, factor));
23159+ bfree = au_add_till_max(bfree,
23160+ au_mul_till_max(buf->f_bfree, factor));
23161+ bavail = au_add_till_max(bavail,
23162+ au_mul_till_max(buf->f_bavail, factor));
1facf9fc 23163+ files = au_add_till_max(files, buf->f_files);
23164+ ffree = au_add_till_max(ffree, buf->f_ffree);
23165+ }
23166+
92d182d2 23167+ buf->f_bsize = bsize;
1facf9fc 23168+ buf->f_blocks = blocks;
23169+ buf->f_bfree = bfree;
23170+ buf->f_bavail = bavail;
23171+ buf->f_files = files;
23172+ buf->f_ffree = ffree;
92d182d2 23173+ buf->f_frsize = 0;
1facf9fc 23174+
4f0767ce 23175+out:
1facf9fc 23176+ return err;
23177+}
23178+
23179+static int aufs_statfs(struct dentry *dentry, struct kstatfs *buf)
23180+{
23181+ int err;
7f207e10 23182+ struct path h_path;
1facf9fc 23183+ struct super_block *sb;
23184+
23185+ /* lock free root dinfo */
23186+ sb = dentry->d_sb;
23187+ si_noflush_read_lock(sb);
7f207e10 23188+ if (!au_opt_test(au_mntflags(sb), SUM)) {
1facf9fc 23189+ /* sb->s_root for NFS is unreliable */
7f207e10
AM
23190+ h_path.mnt = au_sbr_mnt(sb, 0);
23191+ h_path.dentry = h_path.mnt->mnt_root;
23192+ err = vfs_statfs(&h_path, buf);
23193+ } else
1facf9fc 23194+ err = au_statfs_sum(sb, buf);
23195+ si_read_unlock(sb);
23196+
23197+ if (!err) {
23198+ buf->f_type = AUFS_SUPER_MAGIC;
4a4d8108 23199+ buf->f_namelen = AUFS_MAX_NAMELEN;
1facf9fc 23200+ memset(&buf->f_fsid, 0, sizeof(buf->f_fsid));
23201+ }
23202+ /* buf->f_bsize = buf->f_blocks = buf->f_bfree = buf->f_bavail = -1; */
23203+
23204+ return err;
23205+}
23206+
23207+/* ---------------------------------------------------------------------- */
23208+
1facf9fc 23209+/* final actions when unmounting a file system */
23210+static void aufs_put_super(struct super_block *sb)
23211+{
23212+ struct au_sbinfo *sbinfo;
23213+
23214+ sbinfo = au_sbi(sb);
23215+ if (!sbinfo)
23216+ return;
23217+
1facf9fc 23218+ dbgaufs_si_fin(sbinfo);
23219+ kobject_put(&sbinfo->si_kobj);
23220+}
23221+
23222+/* ---------------------------------------------------------------------- */
23223+
7f207e10
AM
23224+void au_array_free(void *array)
23225+{
23226+ if (array) {
23227+ if (!is_vmalloc_addr(array))
23228+ kfree(array);
23229+ else
23230+ vfree(array);
23231+ }
23232+}
23233+
23234+void *au_array_alloc(unsigned long long *hint, au_arraycb_t cb, void *arg)
23235+{
23236+ void *array;
23237+ unsigned long long n;
23238+
23239+ array = NULL;
23240+ n = 0;
23241+ if (!*hint)
23242+ goto out;
23243+
23244+ if (*hint > ULLONG_MAX / sizeof(array)) {
23245+ array = ERR_PTR(-EMFILE);
23246+ pr_err("hint %llu\n", *hint);
23247+ goto out;
23248+ }
23249+
23250+ array = kmalloc(sizeof(array) * *hint, GFP_NOFS);
23251+ if (unlikely(!array))
23252+ array = vmalloc(sizeof(array) * *hint);
23253+ if (unlikely(!array)) {
23254+ array = ERR_PTR(-ENOMEM);
23255+ goto out;
23256+ }
23257+
23258+ n = cb(array, *hint, arg);
23259+ AuDebugOn(n > *hint);
23260+
23261+out:
23262+ *hint = n;
23263+ return array;
23264+}
23265+
23266+static unsigned long long au_iarray_cb(void *a,
23267+ unsigned long long max __maybe_unused,
23268+ void *arg)
23269+{
23270+ unsigned long long n;
23271+ struct inode **p, *inode;
23272+ struct list_head *head;
23273+
23274+ n = 0;
23275+ p = a;
23276+ head = arg;
2cbb1c4b 23277+ spin_lock(&inode_sb_list_lock);
7f207e10
AM
23278+ list_for_each_entry(inode, head, i_sb_list) {
23279+ if (!is_bad_inode(inode)
23280+ && au_ii(inode)->ii_bstart >= 0) {
2cbb1c4b
JR
23281+ spin_lock(&inode->i_lock);
23282+ if (atomic_read(&inode->i_count)) {
23283+ au_igrab(inode);
23284+ *p++ = inode;
23285+ n++;
23286+ AuDebugOn(n > max);
23287+ }
23288+ spin_unlock(&inode->i_lock);
7f207e10
AM
23289+ }
23290+ }
2cbb1c4b 23291+ spin_unlock(&inode_sb_list_lock);
7f207e10
AM
23292+
23293+ return n;
23294+}
23295+
23296+struct inode **au_iarray_alloc(struct super_block *sb, unsigned long long *max)
23297+{
23298+ *max = atomic_long_read(&au_sbi(sb)->si_ninodes);
23299+ return au_array_alloc(max, au_iarray_cb, &sb->s_inodes);
23300+}
23301+
23302+void au_iarray_free(struct inode **a, unsigned long long max)
23303+{
23304+ unsigned long long ull;
23305+
23306+ for (ull = 0; ull < max; ull++)
23307+ iput(a[ull]);
23308+ au_array_free(a);
23309+}
23310+
23311+/* ---------------------------------------------------------------------- */
23312+
1facf9fc 23313+/*
23314+ * refresh dentry and inode at remount time.
23315+ */
027c5e7a
AM
23316+/* todo: consolidate with simple_reval_dpath() and au_reval_for_attr() */
23317+static int au_do_refresh(struct dentry *dentry, unsigned int dir_flags,
23318+ struct dentry *parent)
1facf9fc 23319+{
23320+ int err;
1facf9fc 23321+
23322+ di_write_lock_child(dentry);
1facf9fc 23323+ di_read_lock_parent(parent, AuLock_IR);
027c5e7a
AM
23324+ err = au_refresh_dentry(dentry, parent);
23325+ if (!err && dir_flags)
23326+ au_hn_reset(dentry->d_inode, dir_flags);
1facf9fc 23327+ di_read_unlock(parent, AuLock_IR);
1facf9fc 23328+ di_write_unlock(dentry);
23329+
23330+ return err;
23331+}
23332+
027c5e7a
AM
23333+static int au_do_refresh_d(struct dentry *dentry, unsigned int sigen,
23334+ struct au_sbinfo *sbinfo,
23335+ const unsigned int dir_flags)
1facf9fc 23336+{
027c5e7a
AM
23337+ int err;
23338+ struct dentry *parent;
23339+ struct inode *inode;
23340+
23341+ err = 0;
23342+ parent = dget_parent(dentry);
23343+ if (!au_digen_test(parent, sigen) && au_digen_test(dentry, sigen)) {
23344+ inode = dentry->d_inode;
23345+ if (inode) {
23346+ if (!S_ISDIR(inode->i_mode))
23347+ err = au_do_refresh(dentry, /*dir_flags*/0,
23348+ parent);
23349+ else {
23350+ err = au_do_refresh(dentry, dir_flags, parent);
23351+ if (unlikely(err))
23352+ au_fset_si(sbinfo, FAILED_REFRESH_DIR);
23353+ }
23354+ } else
23355+ err = au_do_refresh(dentry, /*dir_flags*/0, parent);
23356+ AuDbgDentry(dentry);
23357+ }
23358+ dput(parent);
23359+
23360+ AuTraceErr(err);
23361+ return err;
1facf9fc 23362+}
23363+
027c5e7a 23364+static int au_refresh_d(struct super_block *sb)
1facf9fc 23365+{
23366+ int err, i, j, ndentry, e;
027c5e7a 23367+ unsigned int sigen;
1facf9fc 23368+ struct au_dcsub_pages dpages;
23369+ struct au_dpage *dpage;
027c5e7a
AM
23370+ struct dentry **dentries, *d;
23371+ struct au_sbinfo *sbinfo;
23372+ struct dentry *root = sb->s_root;
23373+ const unsigned int dir_flags = au_hi_flags(root->d_inode, /*isdir*/1);
1facf9fc 23374+
027c5e7a
AM
23375+ err = au_dpages_init(&dpages, GFP_NOFS);
23376+ if (unlikely(err))
1facf9fc 23377+ goto out;
027c5e7a
AM
23378+ err = au_dcsub_pages(&dpages, root, NULL, NULL);
23379+ if (unlikely(err))
1facf9fc 23380+ goto out_dpages;
1facf9fc 23381+
027c5e7a
AM
23382+ sigen = au_sigen(sb);
23383+ sbinfo = au_sbi(sb);
23384+ for (i = 0; i < dpages.ndpage; i++) {
1facf9fc 23385+ dpage = dpages.dpages + i;
23386+ dentries = dpage->dentries;
23387+ ndentry = dpage->ndentry;
027c5e7a 23388+ for (j = 0; j < ndentry; j++) {
1facf9fc 23389+ d = dentries[j];
027c5e7a
AM
23390+ e = au_do_refresh_d(d, sigen, sbinfo, dir_flags);
23391+ if (unlikely(e && !err))
23392+ err = e;
23393+ /* go on even err */
1facf9fc 23394+ }
23395+ }
23396+
4f0767ce 23397+out_dpages:
1facf9fc 23398+ au_dpages_free(&dpages);
4f0767ce 23399+out:
1facf9fc 23400+ return err;
23401+}
23402+
027c5e7a 23403+static int au_refresh_i(struct super_block *sb)
1facf9fc 23404+{
027c5e7a
AM
23405+ int err, e;
23406+ unsigned int sigen;
23407+ unsigned long long max, ull;
23408+ struct inode *inode, **array;
1facf9fc 23409+
027c5e7a
AM
23410+ array = au_iarray_alloc(sb, &max);
23411+ err = PTR_ERR(array);
23412+ if (IS_ERR(array))
23413+ goto out;
1facf9fc 23414+
23415+ err = 0;
027c5e7a
AM
23416+ sigen = au_sigen(sb);
23417+ for (ull = 0; ull < max; ull++) {
23418+ inode = array[ull];
23419+ if (au_iigen(inode) != sigen) {
1facf9fc 23420+ ii_write_lock_child(inode);
027c5e7a 23421+ e = au_refresh_hinode_self(inode);
1facf9fc 23422+ ii_write_unlock(inode);
23423+ if (unlikely(e)) {
027c5e7a 23424+ pr_err("error %d, i%lu\n", e, inode->i_ino);
1facf9fc 23425+ if (!err)
23426+ err = e;
23427+ /* go on even if err */
23428+ }
23429+ }
1facf9fc 23430+ }
23431+
027c5e7a 23432+ au_iarray_free(array, max);
1facf9fc 23433+
4f0767ce 23434+out:
1facf9fc 23435+ return err;
23436+}
23437+
027c5e7a 23438+static void au_remount_refresh(struct super_block *sb)
1facf9fc 23439+{
027c5e7a
AM
23440+ int err, e;
23441+ unsigned int udba;
23442+ aufs_bindex_t bindex, bend;
1facf9fc 23443+ struct dentry *root;
23444+ struct inode *inode;
027c5e7a 23445+ struct au_branch *br;
1facf9fc 23446+
23447+ au_sigen_inc(sb);
027c5e7a 23448+ au_fclr_si(au_sbi(sb), FAILED_REFRESH_DIR);
1facf9fc 23449+
23450+ root = sb->s_root;
23451+ DiMustNoWaiters(root);
23452+ inode = root->d_inode;
23453+ IiMustNoWaiters(inode);
1facf9fc 23454+
027c5e7a
AM
23455+ udba = au_opt_udba(sb);
23456+ bend = au_sbend(sb);
23457+ for (bindex = 0; bindex <= bend; bindex++) {
23458+ br = au_sbr(sb, bindex);
23459+ err = au_hnotify_reset_br(udba, br, br->br_perm);
1facf9fc 23460+ if (unlikely(err))
027c5e7a
AM
23461+ AuIOErr("hnotify failed on br %d, %d, ignored\n",
23462+ bindex, err);
23463+ /* go on even if err */
1facf9fc 23464+ }
027c5e7a 23465+ au_hn_reset(inode, au_hi_flags(inode, /*isdir*/1));
1facf9fc 23466+
027c5e7a
AM
23467+ di_write_unlock(root);
23468+ err = au_refresh_d(sb);
23469+ e = au_refresh_i(sb);
23470+ if (unlikely(e && !err))
23471+ err = e;
1facf9fc 23472+ /* aufs_write_lock() calls ..._child() */
23473+ di_write_lock_child(root);
027c5e7a
AM
23474+
23475+ au_cpup_attr_all(inode, /*force*/1);
23476+
23477+ if (unlikely(err))
23478+ AuIOErr("refresh failed, ignored, %d\n", err);
1facf9fc 23479+}
23480+
23481+/* stop extra interpretation of errno in mount(8), and strange error messages */
23482+static int cvt_err(int err)
23483+{
23484+ AuTraceErr(err);
23485+
23486+ switch (err) {
23487+ case -ENOENT:
23488+ case -ENOTDIR:
23489+ case -EEXIST:
23490+ case -EIO:
23491+ err = -EINVAL;
23492+ }
23493+ return err;
23494+}
23495+
23496+static int aufs_remount_fs(struct super_block *sb, int *flags, char *data)
23497+{
4a4d8108
AM
23498+ int err, do_dx;
23499+ unsigned int mntflags;
1facf9fc 23500+ struct au_opts opts;
23501+ struct dentry *root;
23502+ struct inode *inode;
23503+ struct au_sbinfo *sbinfo;
23504+
23505+ err = 0;
23506+ root = sb->s_root;
23507+ if (!data || !*data) {
e49829fe
JR
23508+ err = si_write_lock(sb, AuLock_FLUSH | AuLock_NOPLM);
23509+ if (!err) {
23510+ di_write_lock_child(root);
23511+ err = au_opts_verify(sb, *flags, /*pending*/0);
23512+ aufs_write_unlock(root);
23513+ }
1facf9fc 23514+ goto out;
23515+ }
23516+
23517+ err = -ENOMEM;
23518+ memset(&opts, 0, sizeof(opts));
23519+ opts.opt = (void *)__get_free_page(GFP_NOFS);
23520+ if (unlikely(!opts.opt))
23521+ goto out;
23522+ opts.max_opt = PAGE_SIZE / sizeof(*opts.opt);
23523+ opts.flags = AuOpts_REMOUNT;
23524+ opts.sb_flags = *flags;
23525+
23526+ /* parse it before aufs lock */
23527+ err = au_opts_parse(sb, data, &opts);
23528+ if (unlikely(err))
23529+ goto out_opts;
23530+
23531+ sbinfo = au_sbi(sb);
23532+ inode = root->d_inode;
23533+ mutex_lock(&inode->i_mutex);
e49829fe
JR
23534+ err = si_write_lock(sb, AuLock_FLUSH | AuLock_NOPLM);
23535+ if (unlikely(err))
23536+ goto out_mtx;
23537+ di_write_lock_child(root);
1facf9fc 23538+
23539+ /* au_opts_remount() may return an error */
23540+ err = au_opts_remount(sb, &opts);
23541+ au_opts_free(&opts);
23542+
027c5e7a
AM
23543+ if (au_ftest_opts(opts.flags, REFRESH))
23544+ au_remount_refresh(sb);
1facf9fc 23545+
4a4d8108
AM
23546+ if (au_ftest_opts(opts.flags, REFRESH_DYAOP)) {
23547+ mntflags = au_mntflags(sb);
23548+ do_dx = !!au_opt_test(mntflags, DIO);
23549+ au_dy_arefresh(do_dx);
23550+ }
23551+
1facf9fc 23552+ aufs_write_unlock(root);
953406b4 23553+
e49829fe
JR
23554+out_mtx:
23555+ mutex_unlock(&inode->i_mutex);
4f0767ce 23556+out_opts:
1facf9fc 23557+ free_page((unsigned long)opts.opt);
4f0767ce 23558+out:
1facf9fc 23559+ err = cvt_err(err);
23560+ AuTraceErr(err);
23561+ return err;
23562+}
23563+
4a4d8108 23564+static const struct super_operations aufs_sop = {
1facf9fc 23565+ .alloc_inode = aufs_alloc_inode,
23566+ .destroy_inode = aufs_destroy_inode,
b752ccd1 23567+ /* always deleting, no clearing */
1facf9fc 23568+ .drop_inode = generic_delete_inode,
23569+ .show_options = aufs_show_options,
23570+ .statfs = aufs_statfs,
23571+ .put_super = aufs_put_super,
23572+ .remount_fs = aufs_remount_fs
23573+};
23574+
23575+/* ---------------------------------------------------------------------- */
23576+
23577+static int alloc_root(struct super_block *sb)
23578+{
23579+ int err;
23580+ struct inode *inode;
23581+ struct dentry *root;
23582+
23583+ err = -ENOMEM;
23584+ inode = au_iget_locked(sb, AUFS_ROOT_INO);
23585+ err = PTR_ERR(inode);
23586+ if (IS_ERR(inode))
23587+ goto out;
23588+
23589+ inode->i_op = &aufs_dir_iop;
23590+ inode->i_fop = &aufs_dir_fop;
23591+ inode->i_mode = S_IFDIR;
9dbd164d 23592+ set_nlink(inode, 2);
1facf9fc 23593+ unlock_new_inode(inode);
23594+
92d182d2 23595+ root = d_make_root(inode);
1facf9fc 23596+ if (unlikely(!root))
92d182d2 23597+ goto out;
1facf9fc 23598+ err = PTR_ERR(root);
23599+ if (IS_ERR(root))
92d182d2 23600+ goto out;
1facf9fc 23601+
4a4d8108 23602+ err = au_di_init(root);
1facf9fc 23603+ if (!err) {
23604+ sb->s_root = root;
23605+ return 0; /* success */
23606+ }
23607+ dput(root);
1facf9fc 23608+
4f0767ce 23609+out:
1facf9fc 23610+ return err;
1facf9fc 23611+}
23612+
23613+static int aufs_fill_super(struct super_block *sb, void *raw_data,
23614+ int silent __maybe_unused)
23615+{
23616+ int err;
23617+ struct au_opts opts;
23618+ struct dentry *root;
23619+ struct inode *inode;
23620+ char *arg = raw_data;
23621+
23622+ if (unlikely(!arg || !*arg)) {
23623+ err = -EINVAL;
4a4d8108 23624+ pr_err("no arg\n");
1facf9fc 23625+ goto out;
23626+ }
23627+
23628+ err = -ENOMEM;
23629+ memset(&opts, 0, sizeof(opts));
23630+ opts.opt = (void *)__get_free_page(GFP_NOFS);
23631+ if (unlikely(!opts.opt))
23632+ goto out;
23633+ opts.max_opt = PAGE_SIZE / sizeof(*opts.opt);
23634+ opts.sb_flags = sb->s_flags;
23635+
23636+ err = au_si_alloc(sb);
23637+ if (unlikely(err))
23638+ goto out_opts;
23639+
23640+ /* all timestamps always follow the ones on the branch */
23641+ sb->s_flags |= MS_NOATIME | MS_NODIRATIME;
23642+ sb->s_op = &aufs_sop;
027c5e7a 23643+ sb->s_d_op = &aufs_dop;
1facf9fc 23644+ sb->s_magic = AUFS_SUPER_MAGIC;
23645+ sb->s_maxbytes = 0;
23646+ au_export_init(sb);
23647+
23648+ err = alloc_root(sb);
23649+ if (unlikely(err)) {
23650+ si_write_unlock(sb);
23651+ goto out_info;
23652+ }
23653+ root = sb->s_root;
23654+ inode = root->d_inode;
23655+
23656+ /*
23657+ * actually we can parse options regardless aufs lock here.
23658+ * but at remount time, parsing must be done before aufs lock.
23659+ * so we follow the same rule.
23660+ */
23661+ ii_write_lock_parent(inode);
23662+ aufs_write_unlock(root);
23663+ err = au_opts_parse(sb, arg, &opts);
23664+ if (unlikely(err))
23665+ goto out_root;
23666+
23667+ /* lock vfs_inode first, then aufs. */
23668+ mutex_lock(&inode->i_mutex);
1facf9fc 23669+ aufs_write_lock(root);
23670+ err = au_opts_mount(sb, &opts);
23671+ au_opts_free(&opts);
1facf9fc 23672+ aufs_write_unlock(root);
23673+ mutex_unlock(&inode->i_mutex);
4a4d8108
AM
23674+ if (!err)
23675+ goto out_opts; /* success */
1facf9fc 23676+
4f0767ce 23677+out_root:
1facf9fc 23678+ dput(root);
23679+ sb->s_root = NULL;
4f0767ce 23680+out_info:
2cbb1c4b 23681+ dbgaufs_si_fin(au_sbi(sb));
1facf9fc 23682+ kobject_put(&au_sbi(sb)->si_kobj);
23683+ sb->s_fs_info = NULL;
4f0767ce 23684+out_opts:
1facf9fc 23685+ free_page((unsigned long)opts.opt);
4f0767ce 23686+out:
1facf9fc 23687+ AuTraceErr(err);
23688+ err = cvt_err(err);
23689+ AuTraceErr(err);
23690+ return err;
23691+}
23692+
23693+/* ---------------------------------------------------------------------- */
23694+
027c5e7a
AM
23695+static struct dentry *aufs_mount(struct file_system_type *fs_type, int flags,
23696+ const char *dev_name __maybe_unused,
23697+ void *raw_data)
1facf9fc 23698+{
027c5e7a 23699+ struct dentry *root;
1facf9fc 23700+ struct super_block *sb;
23701+
23702+ /* all timestamps always follow the ones on the branch */
23703+ /* mnt->mnt_flags |= MNT_NOATIME | MNT_NODIRATIME; */
027c5e7a
AM
23704+ root = mount_nodev(fs_type, flags, raw_data, aufs_fill_super);
23705+ if (IS_ERR(root))
23706+ goto out;
23707+
23708+ sb = root->d_sb;
23709+ si_write_lock(sb, !AuLock_FLUSH);
23710+ sysaufs_brs_add(sb, 0);
23711+ si_write_unlock(sb);
23712+ au_sbilist_add(sb);
23713+
23714+out:
23715+ return root;
1facf9fc 23716+}
23717+
e49829fe
JR
23718+static void aufs_kill_sb(struct super_block *sb)
23719+{
23720+ struct au_sbinfo *sbinfo;
23721+
23722+ sbinfo = au_sbi(sb);
23723+ if (sbinfo) {
23724+ au_sbilist_del(sb);
23725+ aufs_write_lock(sb->s_root);
23726+ if (sbinfo->si_wbr_create_ops->fin)
23727+ sbinfo->si_wbr_create_ops->fin(sb);
23728+ if (au_opt_test(sbinfo->si_mntflags, UDBA_HNOTIFY)) {
23729+ au_opt_set_udba(sbinfo->si_mntflags, UDBA_NONE);
027c5e7a 23730+ au_remount_refresh(sb);
e49829fe
JR
23731+ }
23732+ if (au_opt_test(sbinfo->si_mntflags, PLINK))
23733+ au_plink_put(sb, /*verbose*/1);
23734+ au_xino_clr(sb);
1e00d052 23735+ sbinfo->si_sb = NULL;
e49829fe 23736+ aufs_write_unlock(sb->s_root);
e49829fe
JR
23737+ au_nwt_flush(&sbinfo->si_nowait);
23738+ }
23739+ generic_shutdown_super(sb);
23740+}
23741+
1facf9fc 23742+struct file_system_type aufs_fs_type = {
23743+ .name = AUFS_FSTYPE,
23744+ .fs_flags =
23745+ FS_RENAME_DOES_D_MOVE /* a race between rename and others */
23746+ | FS_REVAL_DOT, /* for NFS branch and udba */
027c5e7a 23747+ .mount = aufs_mount,
e49829fe 23748+ .kill_sb = aufs_kill_sb,
1facf9fc 23749+ /* no need to __module_get() and module_put(). */
23750+ .owner = THIS_MODULE,
23751+};
7f207e10
AM
23752diff -urN /usr/share/empty/fs/aufs/super.h linux/fs/aufs/super.h
23753--- /usr/share/empty/fs/aufs/super.h 1970-01-01 01:00:00.000000000 +0100
7ce627cf 23754+++ linux/fs/aufs/super.h 2012-05-22 09:06:08.870792417 +0200
f6c5ef8b 23755@@ -0,0 +1,546 @@
1facf9fc 23756+/*
f6c5ef8b 23757+ * Copyright (C) 2005-2012 Junjiro R. Okajima
1facf9fc 23758+ *
23759+ * This program, aufs is free software; you can redistribute it and/or modify
23760+ * it under the terms of the GNU General Public License as published by
23761+ * the Free Software Foundation; either version 2 of the License, or
23762+ * (at your option) any later version.
dece6358
AM
23763+ *
23764+ * This program is distributed in the hope that it will be useful,
23765+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
23766+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23767+ * GNU General Public License for more details.
23768+ *
23769+ * You should have received a copy of the GNU General Public License
23770+ * along with this program; if not, write to the Free Software
23771+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 23772+ */
23773+
23774+/*
23775+ * super_block operations
23776+ */
23777+
23778+#ifndef __AUFS_SUPER_H__
23779+#define __AUFS_SUPER_H__
23780+
23781+#ifdef __KERNEL__
23782+
23783+#include <linux/fs.h>
1facf9fc 23784+#include "rwsem.h"
23785+#include "spl.h"
23786+#include "wkq.h"
23787+
23788+typedef ssize_t (*au_readf_t)(struct file *, char __user *, size_t, loff_t *);
23789+typedef ssize_t (*au_writef_t)(struct file *, const char __user *, size_t,
23790+ loff_t *);
23791+
23792+/* policies to select one among multiple writable branches */
23793+struct au_wbr_copyup_operations {
23794+ int (*copyup)(struct dentry *dentry);
23795+};
23796+
23797+struct au_wbr_create_operations {
23798+ int (*create)(struct dentry *dentry, int isdir);
23799+ int (*init)(struct super_block *sb);
23800+ int (*fin)(struct super_block *sb);
23801+};
23802+
23803+struct au_wbr_mfs {
23804+ struct mutex mfs_lock; /* protect this structure */
23805+ unsigned long mfs_jiffy;
23806+ unsigned long mfs_expire;
23807+ aufs_bindex_t mfs_bindex;
23808+
23809+ unsigned long long mfsrr_bytes;
23810+ unsigned long long mfsrr_watermark;
23811+};
23812+
1facf9fc 23813+struct au_branch;
23814+struct au_sbinfo {
23815+ /* nowait tasks in the system-wide workqueue */
23816+ struct au_nowait_tasks si_nowait;
23817+
b752ccd1
AM
23818+ /*
23819+ * tried sb->s_umount, but failed due to the dependecy between i_mutex.
23820+ * rwsem for au_sbinfo is necessary.
23821+ */
dece6358 23822+ struct au_rwsem si_rwsem;
1facf9fc 23823+
b752ccd1
AM
23824+ /* prevent recursive locking in deleting inode */
23825+ struct {
23826+ unsigned long *bitmap;
23827+ spinlock_t tree_lock;
23828+ struct radix_tree_root tree;
23829+ } au_si_pid;
23830+
7f207e10
AM
23831+ /*
23832+ * dirty approach to protect sb->sb_inodes and ->s_files from remount.
23833+ */
23834+ atomic_long_t si_ninodes, si_nfiles;
23835+
1facf9fc 23836+ /* branch management */
23837+ unsigned int si_generation;
23838+
23839+ /* see above flags */
23840+ unsigned char au_si_status;
23841+
23842+ aufs_bindex_t si_bend;
7f207e10
AM
23843+
23844+ /* dirty trick to keep br_id plus */
23845+ unsigned int si_last_br_id :
23846+ sizeof(aufs_bindex_t) * BITS_PER_BYTE - 1;
1facf9fc 23847+ struct au_branch **si_branch;
23848+
23849+ /* policy to select a writable branch */
23850+ unsigned char si_wbr_copyup;
23851+ unsigned char si_wbr_create;
23852+ struct au_wbr_copyup_operations *si_wbr_copyup_ops;
23853+ struct au_wbr_create_operations *si_wbr_create_ops;
23854+
23855+ /* round robin */
23856+ atomic_t si_wbr_rr_next;
23857+
23858+ /* most free space */
23859+ struct au_wbr_mfs si_wbr_mfs;
23860+
23861+ /* mount flags */
23862+ /* include/asm-ia64/siginfo.h defines a macro named si_flags */
23863+ unsigned int si_mntflags;
23864+
23865+ /* external inode number (bitmap and translation table) */
23866+ au_readf_t si_xread;
23867+ au_writef_t si_xwrite;
23868+ struct file *si_xib;
23869+ struct mutex si_xib_mtx; /* protect xib members */
23870+ unsigned long *si_xib_buf;
23871+ unsigned long si_xib_last_pindex;
23872+ int si_xib_next_bit;
23873+ aufs_bindex_t si_xino_brid;
23874+ /* reserved for future use */
23875+ /* unsigned long long si_xib_limit; */ /* Max xib file size */
23876+
23877+#ifdef CONFIG_AUFS_EXPORT
23878+ /* i_generation */
23879+ struct file *si_xigen;
23880+ atomic_t si_xigen_next;
23881+#endif
23882+
23883+ /* vdir parameters */
e49829fe 23884+ unsigned long si_rdcache; /* max cache time in jiffies */
1facf9fc 23885+ unsigned int si_rdblk; /* deblk size */
23886+ unsigned int si_rdhash; /* hash size */
23887+
23888+ /*
23889+ * If the number of whiteouts are larger than si_dirwh, leave all of
23890+ * them after au_whtmp_ren to reduce the cost of rmdir(2).
23891+ * future fsck.aufs or kernel thread will remove them later.
23892+ * Otherwise, remove all whiteouts and the dir in rmdir(2).
23893+ */
23894+ unsigned int si_dirwh;
23895+
23896+ /*
23897+ * rename(2) a directory with all children.
23898+ */
23899+ /* reserved for future use */
23900+ /* int si_rendir; */
23901+
23902+ /* pseudo_link list */
23903+ struct au_splhead si_plink;
23904+ wait_queue_head_t si_plink_wq;
4a4d8108 23905+ spinlock_t si_plink_maint_lock;
e49829fe 23906+ pid_t si_plink_maint_pid;
1facf9fc 23907+
23908+ /*
23909+ * sysfs and lifetime management.
23910+ * this is not a small structure and it may be a waste of memory in case
23911+ * of sysfs is disabled, particulary when many aufs-es are mounted.
23912+ * but using sysfs is majority.
23913+ */
23914+ struct kobject si_kobj;
23915+#ifdef CONFIG_DEBUG_FS
23916+ struct dentry *si_dbgaufs, *si_dbgaufs_xib;
23917+#ifdef CONFIG_AUFS_EXPORT
23918+ struct dentry *si_dbgaufs_xigen;
23919+#endif
23920+#endif
23921+
e49829fe
JR
23922+#ifdef CONFIG_AUFS_SBILIST
23923+ struct list_head si_list;
23924+#endif
23925+
1facf9fc 23926+ /* dirty, necessary for unmounting, sysfs and sysrq */
23927+ struct super_block *si_sb;
23928+};
23929+
dece6358
AM
23930+/* sbinfo status flags */
23931+/*
23932+ * set true when refresh_dirs() failed at remount time.
23933+ * then try refreshing dirs at access time again.
23934+ * if it is false, refreshing dirs at access time is unnecesary
23935+ */
027c5e7a 23936+#define AuSi_FAILED_REFRESH_DIR 1
dece6358
AM
23937+static inline unsigned char au_do_ftest_si(struct au_sbinfo *sbi,
23938+ unsigned int flag)
23939+{
23940+ AuRwMustAnyLock(&sbi->si_rwsem);
23941+ return sbi->au_si_status & flag;
23942+}
23943+#define au_ftest_si(sbinfo, name) au_do_ftest_si(sbinfo, AuSi_##name)
23944+#define au_fset_si(sbinfo, name) do { \
23945+ AuRwMustWriteLock(&(sbinfo)->si_rwsem); \
23946+ (sbinfo)->au_si_status |= AuSi_##name; \
23947+} while (0)
23948+#define au_fclr_si(sbinfo, name) do { \
23949+ AuRwMustWriteLock(&(sbinfo)->si_rwsem); \
23950+ (sbinfo)->au_si_status &= ~AuSi_##name; \
23951+} while (0)
23952+
1facf9fc 23953+/* ---------------------------------------------------------------------- */
23954+
23955+/* policy to select one among writable branches */
4a4d8108
AM
23956+#define AuWbrCopyup(sbinfo, ...) \
23957+ ((sbinfo)->si_wbr_copyup_ops->copyup(__VA_ARGS__))
23958+#define AuWbrCreate(sbinfo, ...) \
23959+ ((sbinfo)->si_wbr_create_ops->create(__VA_ARGS__))
1facf9fc 23960+
23961+/* flags for si_read_lock()/aufs_read_lock()/di_read_lock() */
23962+#define AuLock_DW 1 /* write-lock dentry */
23963+#define AuLock_IR (1 << 1) /* read-lock inode */
23964+#define AuLock_IW (1 << 2) /* write-lock inode */
23965+#define AuLock_FLUSH (1 << 3) /* wait for 'nowait' tasks */
23966+#define AuLock_DIR (1 << 4) /* target is a dir */
e49829fe
JR
23967+#define AuLock_NOPLM (1 << 5) /* return err in plm mode */
23968+#define AuLock_NOPLMW (1 << 6) /* wait for plm mode ends */
027c5e7a 23969+#define AuLock_GEN (1 << 7) /* test digen/iigen */
1facf9fc 23970+#define au_ftest_lock(flags, name) ((flags) & AuLock_##name)
7f207e10
AM
23971+#define au_fset_lock(flags, name) \
23972+ do { (flags) |= AuLock_##name; } while (0)
23973+#define au_fclr_lock(flags, name) \
23974+ do { (flags) &= ~AuLock_##name; } while (0)
1facf9fc 23975+
23976+/* ---------------------------------------------------------------------- */
23977+
23978+/* super.c */
23979+extern struct file_system_type aufs_fs_type;
23980+struct inode *au_iget_locked(struct super_block *sb, ino_t ino);
7f207e10
AM
23981+typedef unsigned long long (*au_arraycb_t)(void *array, unsigned long long max,
23982+ void *arg);
23983+void au_array_free(void *array);
23984+void *au_array_alloc(unsigned long long *hint, au_arraycb_t cb, void *arg);
23985+struct inode **au_iarray_alloc(struct super_block *sb, unsigned long long *max);
23986+void au_iarray_free(struct inode **a, unsigned long long max);
1facf9fc 23987+
23988+/* sbinfo.c */
23989+void au_si_free(struct kobject *kobj);
23990+int au_si_alloc(struct super_block *sb);
23991+int au_sbr_realloc(struct au_sbinfo *sbinfo, int nbr);
23992+
23993+unsigned int au_sigen_inc(struct super_block *sb);
23994+aufs_bindex_t au_new_br_id(struct super_block *sb);
23995+
e49829fe
JR
23996+int si_read_lock(struct super_block *sb, int flags);
23997+int si_write_lock(struct super_block *sb, int flags);
23998+int aufs_read_lock(struct dentry *dentry, int flags);
1facf9fc 23999+void aufs_read_unlock(struct dentry *dentry, int flags);
24000+void aufs_write_lock(struct dentry *dentry);
24001+void aufs_write_unlock(struct dentry *dentry);
e49829fe 24002+int aufs_read_and_write_lock2(struct dentry *d1, struct dentry *d2, int flags);
1facf9fc 24003+void aufs_read_and_write_unlock2(struct dentry *d1, struct dentry *d2);
24004+
b752ccd1
AM
24005+int si_pid_test_slow(struct super_block *sb);
24006+void si_pid_set_slow(struct super_block *sb);
24007+void si_pid_clr_slow(struct super_block *sb);
24008+
1facf9fc 24009+/* wbr_policy.c */
24010+extern struct au_wbr_copyup_operations au_wbr_copyup_ops[];
24011+extern struct au_wbr_create_operations au_wbr_create_ops[];
24012+int au_cpdown_dirs(struct dentry *dentry, aufs_bindex_t bdst);
24013+
24014+/* ---------------------------------------------------------------------- */
24015+
24016+static inline struct au_sbinfo *au_sbi(struct super_block *sb)
24017+{
24018+ return sb->s_fs_info;
24019+}
24020+
24021+/* ---------------------------------------------------------------------- */
24022+
24023+#ifdef CONFIG_AUFS_EXPORT
24024+void au_export_init(struct super_block *sb);
24025+
b752ccd1 24026+static inline int au_test_nfsd(void)
1facf9fc 24027+{
b752ccd1
AM
24028+ struct task_struct *tsk = current;
24029+
24030+ return (tsk->flags & PF_KTHREAD)
24031+ && !strcmp(tsk->comm, "nfsd");
1facf9fc 24032+}
24033+
b752ccd1 24034+void au_xigen_inc(struct inode *inode);
1facf9fc 24035+int au_xigen_new(struct inode *inode);
24036+int au_xigen_set(struct super_block *sb, struct file *base);
24037+void au_xigen_clr(struct super_block *sb);
24038+
24039+static inline int au_busy_or_stale(void)
24040+{
b752ccd1 24041+ if (!au_test_nfsd())
1facf9fc 24042+ return -EBUSY;
24043+ return -ESTALE;
24044+}
24045+#else
4a4d8108 24046+AuStubVoid(au_export_init, struct super_block *sb)
b752ccd1
AM
24047+AuStubInt0(au_test_nfsd, void)
24048+AuStubVoid(au_xigen_inc, struct inode *inode)
4a4d8108
AM
24049+AuStubInt0(au_xigen_new, struct inode *inode)
24050+AuStubInt0(au_xigen_set, struct super_block *sb, struct file *base)
24051+AuStubVoid(au_xigen_clr, struct super_block *sb)
1facf9fc 24052+static inline int au_busy_or_stale(void)
24053+{
24054+ return -EBUSY;
24055+}
24056+#endif /* CONFIG_AUFS_EXPORT */
24057+
24058+/* ---------------------------------------------------------------------- */
24059+
e49829fe
JR
24060+#ifdef CONFIG_AUFS_SBILIST
24061+/* module.c */
24062+extern struct au_splhead au_sbilist;
24063+
24064+static inline void au_sbilist_init(void)
24065+{
24066+ au_spl_init(&au_sbilist);
24067+}
24068+
24069+static inline void au_sbilist_add(struct super_block *sb)
24070+{
24071+ au_spl_add(&au_sbi(sb)->si_list, &au_sbilist);
24072+}
24073+
24074+static inline void au_sbilist_del(struct super_block *sb)
24075+{
24076+ au_spl_del(&au_sbi(sb)->si_list, &au_sbilist);
24077+}
53392da6
AM
24078+
24079+#ifdef CONFIG_AUFS_MAGIC_SYSRQ
24080+static inline void au_sbilist_lock(void)
24081+{
24082+ spin_lock(&au_sbilist.spin);
24083+}
24084+
24085+static inline void au_sbilist_unlock(void)
24086+{
24087+ spin_unlock(&au_sbilist.spin);
24088+}
24089+#define AuGFP_SBILIST GFP_ATOMIC
24090+#else
24091+AuStubVoid(au_sbilist_lock, void)
24092+AuStubVoid(au_sbilist_unlock, void)
24093+#define AuGFP_SBILIST GFP_NOFS
24094+#endif /* CONFIG_AUFS_MAGIC_SYSRQ */
e49829fe
JR
24095+#else
24096+AuStubVoid(au_sbilist_init, void)
24097+AuStubVoid(au_sbilist_add, struct super_block*)
24098+AuStubVoid(au_sbilist_del, struct super_block*)
53392da6
AM
24099+AuStubVoid(au_sbilist_lock, void)
24100+AuStubVoid(au_sbilist_unlock, void)
24101+#define AuGFP_SBILIST GFP_NOFS
e49829fe
JR
24102+#endif
24103+
24104+/* ---------------------------------------------------------------------- */
24105+
1facf9fc 24106+static inline void dbgaufs_si_null(struct au_sbinfo *sbinfo)
24107+{
dece6358
AM
24108+ /*
24109+ * This function is a dynamic '__init' fucntion actually,
24110+ * so the tiny check for si_rwsem is unnecessary.
24111+ */
24112+ /* AuRwMustWriteLock(&sbinfo->si_rwsem); */
1facf9fc 24113+#ifdef CONFIG_DEBUG_FS
24114+ sbinfo->si_dbgaufs = NULL;
24115+ sbinfo->si_dbgaufs_xib = NULL;
24116+#ifdef CONFIG_AUFS_EXPORT
24117+ sbinfo->si_dbgaufs_xigen = NULL;
24118+#endif
24119+#endif
24120+}
24121+
24122+/* ---------------------------------------------------------------------- */
24123+
b752ccd1
AM
24124+static inline pid_t si_pid_bit(void)
24125+{
24126+ /* the origin of pid is 1, but the bitmap's is 0 */
24127+ return current->pid - 1;
24128+}
24129+
24130+static inline int si_pid_test(struct super_block *sb)
24131+{
24132+ pid_t bit = si_pid_bit();
24133+ if (bit < PID_MAX_DEFAULT)
24134+ return test_bit(bit, au_sbi(sb)->au_si_pid.bitmap);
24135+ else
24136+ return si_pid_test_slow(sb);
24137+}
24138+
24139+static inline void si_pid_set(struct super_block *sb)
24140+{
24141+ pid_t bit = si_pid_bit();
24142+ if (bit < PID_MAX_DEFAULT) {
24143+ AuDebugOn(test_bit(bit, au_sbi(sb)->au_si_pid.bitmap));
24144+ set_bit(bit, au_sbi(sb)->au_si_pid.bitmap);
24145+ /* smp_mb(); */
24146+ } else
24147+ si_pid_set_slow(sb);
24148+}
24149+
24150+static inline void si_pid_clr(struct super_block *sb)
24151+{
24152+ pid_t bit = si_pid_bit();
24153+ if (bit < PID_MAX_DEFAULT) {
24154+ AuDebugOn(!test_bit(bit, au_sbi(sb)->au_si_pid.bitmap));
24155+ clear_bit(bit, au_sbi(sb)->au_si_pid.bitmap);
24156+ /* smp_mb(); */
24157+ } else
24158+ si_pid_clr_slow(sb);
24159+}
24160+
24161+/* ---------------------------------------------------------------------- */
24162+
1facf9fc 24163+/* lock superblock. mainly for entry point functions */
24164+/*
b752ccd1
AM
24165+ * __si_read_lock, __si_write_lock,
24166+ * __si_read_unlock, __si_write_unlock, __si_downgrade_lock
1facf9fc 24167+ */
b752ccd1 24168+AuSimpleRwsemFuncs(__si, struct super_block *sb, &au_sbi(sb)->si_rwsem);
1facf9fc 24169+
dece6358
AM
24170+#define SiMustNoWaiters(sb) AuRwMustNoWaiters(&au_sbi(sb)->si_rwsem)
24171+#define SiMustAnyLock(sb) AuRwMustAnyLock(&au_sbi(sb)->si_rwsem)
24172+#define SiMustWriteLock(sb) AuRwMustWriteLock(&au_sbi(sb)->si_rwsem)
24173+
b752ccd1
AM
24174+static inline void si_noflush_read_lock(struct super_block *sb)
24175+{
24176+ __si_read_lock(sb);
24177+ si_pid_set(sb);
24178+}
24179+
24180+static inline int si_noflush_read_trylock(struct super_block *sb)
24181+{
24182+ int locked = __si_read_trylock(sb);
24183+ if (locked)
24184+ si_pid_set(sb);
24185+ return locked;
24186+}
24187+
24188+static inline void si_noflush_write_lock(struct super_block *sb)
24189+{
24190+ __si_write_lock(sb);
24191+ si_pid_set(sb);
24192+}
24193+
24194+static inline int si_noflush_write_trylock(struct super_block *sb)
24195+{
24196+ int locked = __si_write_trylock(sb);
24197+ if (locked)
24198+ si_pid_set(sb);
24199+ return locked;
24200+}
24201+
e49829fe 24202+#if 0 /* unused */
1facf9fc 24203+static inline int si_read_trylock(struct super_block *sb, int flags)
24204+{
24205+ if (au_ftest_lock(flags, FLUSH))
24206+ au_nwt_flush(&au_sbi(sb)->si_nowait);
24207+ return si_noflush_read_trylock(sb);
24208+}
e49829fe 24209+#endif
1facf9fc 24210+
b752ccd1
AM
24211+static inline void si_read_unlock(struct super_block *sb)
24212+{
24213+ si_pid_clr(sb);
24214+ __si_read_unlock(sb);
24215+}
24216+
b752ccd1 24217+#if 0 /* unused */
1facf9fc 24218+static inline int si_write_trylock(struct super_block *sb, int flags)
24219+{
24220+ if (au_ftest_lock(flags, FLUSH))
24221+ au_nwt_flush(&au_sbi(sb)->si_nowait);
24222+ return si_noflush_write_trylock(sb);
24223+}
b752ccd1
AM
24224+#endif
24225+
24226+static inline void si_write_unlock(struct super_block *sb)
24227+{
24228+ si_pid_clr(sb);
24229+ __si_write_unlock(sb);
24230+}
24231+
24232+#if 0 /* unused */
24233+static inline void si_downgrade_lock(struct super_block *sb)
24234+{
24235+ __si_downgrade_lock(sb);
24236+}
24237+#endif
1facf9fc 24238+
24239+/* ---------------------------------------------------------------------- */
24240+
24241+static inline aufs_bindex_t au_sbend(struct super_block *sb)
24242+{
dece6358 24243+ SiMustAnyLock(sb);
1facf9fc 24244+ return au_sbi(sb)->si_bend;
24245+}
24246+
24247+static inline unsigned int au_mntflags(struct super_block *sb)
24248+{
dece6358 24249+ SiMustAnyLock(sb);
1facf9fc 24250+ return au_sbi(sb)->si_mntflags;
24251+}
24252+
24253+static inline unsigned int au_sigen(struct super_block *sb)
24254+{
dece6358 24255+ SiMustAnyLock(sb);
1facf9fc 24256+ return au_sbi(sb)->si_generation;
24257+}
24258+
7f207e10
AM
24259+static inline void au_ninodes_inc(struct super_block *sb)
24260+{
24261+ atomic_long_inc(&au_sbi(sb)->si_ninodes);
24262+}
24263+
24264+static inline void au_ninodes_dec(struct super_block *sb)
24265+{
24266+ AuDebugOn(!atomic_long_read(&au_sbi(sb)->si_ninodes));
24267+ atomic_long_dec(&au_sbi(sb)->si_ninodes);
24268+}
24269+
24270+static inline void au_nfiles_inc(struct super_block *sb)
24271+{
24272+ atomic_long_inc(&au_sbi(sb)->si_nfiles);
24273+}
24274+
24275+static inline void au_nfiles_dec(struct super_block *sb)
24276+{
24277+ AuDebugOn(!atomic_long_read(&au_sbi(sb)->si_nfiles));
24278+ atomic_long_dec(&au_sbi(sb)->si_nfiles);
24279+}
24280+
1facf9fc 24281+static inline struct au_branch *au_sbr(struct super_block *sb,
24282+ aufs_bindex_t bindex)
24283+{
dece6358 24284+ SiMustAnyLock(sb);
1facf9fc 24285+ return au_sbi(sb)->si_branch[0 + bindex];
24286+}
24287+
24288+static inline void au_xino_brid_set(struct super_block *sb, aufs_bindex_t brid)
24289+{
dece6358 24290+ SiMustWriteLock(sb);
1facf9fc 24291+ au_sbi(sb)->si_xino_brid = brid;
24292+}
24293+
24294+static inline aufs_bindex_t au_xino_brid(struct super_block *sb)
24295+{
dece6358 24296+ SiMustAnyLock(sb);
1facf9fc 24297+ return au_sbi(sb)->si_xino_brid;
24298+}
24299+
24300+#endif /* __KERNEL__ */
24301+#endif /* __AUFS_SUPER_H__ */
7f207e10
AM
24302diff -urN /usr/share/empty/fs/aufs/sysaufs.c linux/fs/aufs/sysaufs.c
24303--- /usr/share/empty/fs/aufs/sysaufs.c 1970-01-01 01:00:00.000000000 +0100
7ce627cf 24304+++ linux/fs/aufs/sysaufs.c 2012-05-22 09:06:08.870792417 +0200
f6c5ef8b 24305@@ -0,0 +1,105 @@
1facf9fc 24306+/*
f6c5ef8b 24307+ * Copyright (C) 2005-2012 Junjiro R. Okajima
1facf9fc 24308+ *
24309+ * This program, aufs is free software; you can redistribute it and/or modify
24310+ * it under the terms of the GNU General Public License as published by
24311+ * the Free Software Foundation; either version 2 of the License, or
24312+ * (at your option) any later version.
dece6358
AM
24313+ *
24314+ * This program is distributed in the hope that it will be useful,
24315+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
24316+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24317+ * GNU General Public License for more details.
24318+ *
24319+ * You should have received a copy of the GNU General Public License
24320+ * along with this program; if not, write to the Free Software
24321+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 24322+ */
24323+
24324+/*
24325+ * sysfs interface and lifetime management
24326+ * they are necessary regardless sysfs is disabled.
24327+ */
24328+
1facf9fc 24329+#include <linux/random.h>
1facf9fc 24330+#include "aufs.h"
24331+
24332+unsigned long sysaufs_si_mask;
e49829fe 24333+struct kset *sysaufs_kset;
1facf9fc 24334+
24335+#define AuSiAttr(_name) { \
24336+ .attr = { .name = __stringify(_name), .mode = 0444 }, \
24337+ .show = sysaufs_si_##_name, \
24338+}
24339+
24340+static struct sysaufs_si_attr sysaufs_si_attr_xi_path = AuSiAttr(xi_path);
24341+struct attribute *sysaufs_si_attrs[] = {
24342+ &sysaufs_si_attr_xi_path.attr,
24343+ NULL,
24344+};
24345+
4a4d8108 24346+static const struct sysfs_ops au_sbi_ops = {
1facf9fc 24347+ .show = sysaufs_si_show
24348+};
24349+
24350+static struct kobj_type au_sbi_ktype = {
24351+ .release = au_si_free,
24352+ .sysfs_ops = &au_sbi_ops,
24353+ .default_attrs = sysaufs_si_attrs
24354+};
24355+
24356+/* ---------------------------------------------------------------------- */
24357+
24358+int sysaufs_si_init(struct au_sbinfo *sbinfo)
24359+{
24360+ int err;
24361+
e49829fe 24362+ sbinfo->si_kobj.kset = sysaufs_kset;
1facf9fc 24363+ /* cf. sysaufs_name() */
24364+ err = kobject_init_and_add
e49829fe 24365+ (&sbinfo->si_kobj, &au_sbi_ktype, /*&sysaufs_kset->kobj*/NULL,
1facf9fc 24366+ SysaufsSiNamePrefix "%lx", sysaufs_si_id(sbinfo));
24367+
24368+ dbgaufs_si_null(sbinfo);
24369+ if (!err) {
24370+ err = dbgaufs_si_init(sbinfo);
24371+ if (unlikely(err))
24372+ kobject_put(&sbinfo->si_kobj);
24373+ }
24374+ return err;
24375+}
24376+
24377+void sysaufs_fin(void)
24378+{
24379+ dbgaufs_fin();
e49829fe
JR
24380+ sysfs_remove_group(&sysaufs_kset->kobj, sysaufs_attr_group);
24381+ kset_unregister(sysaufs_kset);
1facf9fc 24382+}
24383+
24384+int __init sysaufs_init(void)
24385+{
24386+ int err;
24387+
24388+ do {
24389+ get_random_bytes(&sysaufs_si_mask, sizeof(sysaufs_si_mask));
24390+ } while (!sysaufs_si_mask);
24391+
4a4d8108 24392+ err = -EINVAL;
e49829fe
JR
24393+ sysaufs_kset = kset_create_and_add(AUFS_NAME, NULL, fs_kobj);
24394+ if (unlikely(!sysaufs_kset))
4a4d8108 24395+ goto out;
e49829fe
JR
24396+ err = PTR_ERR(sysaufs_kset);
24397+ if (IS_ERR(sysaufs_kset))
1facf9fc 24398+ goto out;
e49829fe 24399+ err = sysfs_create_group(&sysaufs_kset->kobj, sysaufs_attr_group);
1facf9fc 24400+ if (unlikely(err)) {
e49829fe 24401+ kset_unregister(sysaufs_kset);
1facf9fc 24402+ goto out;
24403+ }
24404+
24405+ err = dbgaufs_init();
24406+ if (unlikely(err))
24407+ sysaufs_fin();
4f0767ce 24408+out:
1facf9fc 24409+ return err;
24410+}
7f207e10
AM
24411diff -urN /usr/share/empty/fs/aufs/sysaufs.h linux/fs/aufs/sysaufs.h
24412--- /usr/share/empty/fs/aufs/sysaufs.h 1970-01-01 01:00:00.000000000 +0100
7ce627cf 24413+++ linux/fs/aufs/sysaufs.h 2012-05-22 09:06:08.870792417 +0200
f6c5ef8b 24414@@ -0,0 +1,104 @@
1facf9fc 24415+/*
f6c5ef8b 24416+ * Copyright (C) 2005-2012 Junjiro R. Okajima
1facf9fc 24417+ *
24418+ * This program, aufs is free software; you can redistribute it and/or modify
24419+ * it under the terms of the GNU General Public License as published by
24420+ * the Free Software Foundation; either version 2 of the License, or
24421+ * (at your option) any later version.
dece6358
AM
24422+ *
24423+ * This program is distributed in the hope that it will be useful,
24424+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
24425+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24426+ * GNU General Public License for more details.
24427+ *
24428+ * You should have received a copy of the GNU General Public License
24429+ * along with this program; if not, write to the Free Software
24430+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 24431+ */
24432+
24433+/*
24434+ * sysfs interface and mount lifetime management
24435+ */
24436+
24437+#ifndef __SYSAUFS_H__
24438+#define __SYSAUFS_H__
24439+
24440+#ifdef __KERNEL__
24441+
1facf9fc 24442+#include <linux/sysfs.h>
1facf9fc 24443+#include "module.h"
24444+
dece6358
AM
24445+struct super_block;
24446+struct au_sbinfo;
24447+
1facf9fc 24448+struct sysaufs_si_attr {
24449+ struct attribute attr;
24450+ int (*show)(struct seq_file *seq, struct super_block *sb);
24451+};
24452+
24453+/* ---------------------------------------------------------------------- */
24454+
24455+/* sysaufs.c */
24456+extern unsigned long sysaufs_si_mask;
e49829fe 24457+extern struct kset *sysaufs_kset;
1facf9fc 24458+extern struct attribute *sysaufs_si_attrs[];
24459+int sysaufs_si_init(struct au_sbinfo *sbinfo);
24460+int __init sysaufs_init(void);
24461+void sysaufs_fin(void);
24462+
24463+/* ---------------------------------------------------------------------- */
24464+
24465+/* some people doesn't like to show a pointer in kernel */
24466+static inline unsigned long sysaufs_si_id(struct au_sbinfo *sbinfo)
24467+{
24468+ return sysaufs_si_mask ^ (unsigned long)sbinfo;
24469+}
24470+
24471+#define SysaufsSiNamePrefix "si_"
24472+#define SysaufsSiNameLen (sizeof(SysaufsSiNamePrefix) + 16)
24473+static inline void sysaufs_name(struct au_sbinfo *sbinfo, char *name)
24474+{
24475+ snprintf(name, SysaufsSiNameLen, SysaufsSiNamePrefix "%lx",
24476+ sysaufs_si_id(sbinfo));
24477+}
24478+
24479+struct au_branch;
24480+#ifdef CONFIG_SYSFS
24481+/* sysfs.c */
24482+extern struct attribute_group *sysaufs_attr_group;
24483+
24484+int sysaufs_si_xi_path(struct seq_file *seq, struct super_block *sb);
24485+ssize_t sysaufs_si_show(struct kobject *kobj, struct attribute *attr,
24486+ char *buf);
24487+
24488+void sysaufs_br_init(struct au_branch *br);
24489+void sysaufs_brs_add(struct super_block *sb, aufs_bindex_t bindex);
24490+void sysaufs_brs_del(struct super_block *sb, aufs_bindex_t bindex);
24491+
24492+#define sysaufs_brs_init() do {} while (0)
24493+
24494+#else
24495+#define sysaufs_attr_group NULL
24496+
4a4d8108 24497+AuStubInt0(sysaufs_si_xi_path, struct seq_file *seq, struct super_block *sb)
1facf9fc 24498+
24499+static inline
24500+ssize_t sysaufs_si_show(struct kobject *kobj, struct attribute *attr,
24501+ char *buf)
24502+{
24503+ return 0;
24504+}
24505+
4a4d8108
AM
24506+AuStubVoid(sysaufs_br_init, struct au_branch *br)
24507+AuStubVoid(sysaufs_brs_add, struct super_block *sb, aufs_bindex_t bindex)
24508+AuStubVoid(sysaufs_brs_del, struct super_block *sb, aufs_bindex_t bindex)
1facf9fc 24509+
24510+static inline void sysaufs_brs_init(void)
24511+{
24512+ sysaufs_brs = 0;
24513+}
24514+
24515+#endif /* CONFIG_SYSFS */
24516+
24517+#endif /* __KERNEL__ */
24518+#endif /* __SYSAUFS_H__ */
7f207e10
AM
24519diff -urN /usr/share/empty/fs/aufs/sysfs.c linux/fs/aufs/sysfs.c
24520--- /usr/share/empty/fs/aufs/sysfs.c 1970-01-01 01:00:00.000000000 +0100
7ce627cf 24521+++ linux/fs/aufs/sysfs.c 2012-05-22 09:06:08.870792417 +0200
f6c5ef8b 24522@@ -0,0 +1,257 @@
1facf9fc 24523+/*
f6c5ef8b 24524+ * Copyright (C) 2005-2012 Junjiro R. Okajima
1facf9fc 24525+ *
24526+ * This program, aufs is free software; you can redistribute it and/or modify
24527+ * it under the terms of the GNU General Public License as published by
24528+ * the Free Software Foundation; either version 2 of the License, or
24529+ * (at your option) any later version.
dece6358
AM
24530+ *
24531+ * This program is distributed in the hope that it will be useful,
24532+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
24533+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24534+ * GNU General Public License for more details.
24535+ *
24536+ * You should have received a copy of the GNU General Public License
24537+ * along with this program; if not, write to the Free Software
24538+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 24539+ */
24540+
24541+/*
24542+ * sysfs interface
24543+ */
24544+
1facf9fc 24545+#include <linux/seq_file.h>
1facf9fc 24546+#include "aufs.h"
24547+
4a4d8108
AM
24548+#ifdef CONFIG_AUFS_FS_MODULE
24549+/* this entry violates the "one line per file" policy of sysfs */
24550+static ssize_t config_show(struct kobject *kobj, struct kobj_attribute *attr,
24551+ char *buf)
24552+{
24553+ ssize_t err;
24554+ static char *conf =
24555+/* this file is generated at compiling */
24556+#include "conf.str"
24557+ ;
24558+
24559+ err = snprintf(buf, PAGE_SIZE, conf);
24560+ if (unlikely(err >= PAGE_SIZE))
24561+ err = -EFBIG;
24562+ return err;
24563+}
24564+
24565+static struct kobj_attribute au_config_attr = __ATTR_RO(config);
24566+#endif
24567+
1facf9fc 24568+static struct attribute *au_attr[] = {
4a4d8108
AM
24569+#ifdef CONFIG_AUFS_FS_MODULE
24570+ &au_config_attr.attr,
24571+#endif
1facf9fc 24572+ NULL, /* need to NULL terminate the list of attributes */
24573+};
24574+
24575+static struct attribute_group sysaufs_attr_group_body = {
24576+ .attrs = au_attr
24577+};
24578+
24579+struct attribute_group *sysaufs_attr_group = &sysaufs_attr_group_body;
24580+
24581+/* ---------------------------------------------------------------------- */
24582+
24583+int sysaufs_si_xi_path(struct seq_file *seq, struct super_block *sb)
24584+{
24585+ int err;
24586+
dece6358
AM
24587+ SiMustAnyLock(sb);
24588+
1facf9fc 24589+ err = 0;
24590+ if (au_opt_test(au_mntflags(sb), XINO)) {
24591+ err = au_xino_path(seq, au_sbi(sb)->si_xib);
24592+ seq_putc(seq, '\n');
24593+ }
24594+ return err;
24595+}
24596+
24597+/*
24598+ * the lifetime of branch is independent from the entry under sysfs.
24599+ * sysfs handles the lifetime of the entry, and never call ->show() after it is
24600+ * unlinked.
24601+ */
24602+static int sysaufs_si_br(struct seq_file *seq, struct super_block *sb,
24603+ aufs_bindex_t bindex)
24604+{
1e00d052 24605+ int err;
1facf9fc 24606+ struct path path;
24607+ struct dentry *root;
24608+ struct au_branch *br;
1e00d052 24609+ char *perm;
1facf9fc 24610+
24611+ AuDbg("b%d\n", bindex);
24612+
1e00d052 24613+ err = 0;
1facf9fc 24614+ root = sb->s_root;
24615+ di_read_lock_parent(root, !AuLock_IR);
24616+ br = au_sbr(sb, bindex);
24617+ path.mnt = br->br_mnt;
24618+ path.dentry = au_h_dptr(root, bindex);
24619+ au_seq_path(seq, &path);
24620+ di_read_unlock(root, !AuLock_IR);
1e00d052
AM
24621+ perm = au_optstr_br_perm(br->br_perm);
24622+ if (perm) {
24623+ err = seq_printf(seq, "=%s\n", perm);
24624+ kfree(perm);
24625+ if (err == -1)
24626+ err = -E2BIG;
24627+ } else
24628+ err = -ENOMEM;
24629+ return err;
1facf9fc 24630+}
24631+
24632+/* ---------------------------------------------------------------------- */
24633+
24634+static struct seq_file *au_seq(char *p, ssize_t len)
24635+{
24636+ struct seq_file *seq;
24637+
24638+ seq = kzalloc(sizeof(*seq), GFP_NOFS);
24639+ if (seq) {
24640+ /* mutex_init(&seq.lock); */
24641+ seq->buf = p;
24642+ seq->size = len;
24643+ return seq; /* success */
24644+ }
24645+
24646+ seq = ERR_PTR(-ENOMEM);
24647+ return seq;
24648+}
24649+
24650+#define SysaufsBr_PREFIX "br"
24651+
24652+/* todo: file size may exceed PAGE_SIZE */
24653+ssize_t sysaufs_si_show(struct kobject *kobj, struct attribute *attr,
1308ab2a 24654+ char *buf)
1facf9fc 24655+{
24656+ ssize_t err;
24657+ long l;
24658+ aufs_bindex_t bend;
24659+ struct au_sbinfo *sbinfo;
24660+ struct super_block *sb;
24661+ struct seq_file *seq;
24662+ char *name;
24663+ struct attribute **cattr;
24664+
24665+ sbinfo = container_of(kobj, struct au_sbinfo, si_kobj);
24666+ sb = sbinfo->si_sb;
1308ab2a 24667+
24668+ /*
24669+ * prevent a race condition between sysfs and aufs.
24670+ * for instance, sysfs_file_read() calls sysfs_get_active_two() which
24671+ * prohibits maintaining the sysfs entries.
24672+ * hew we acquire read lock after sysfs_get_active_two().
24673+ * on the other hand, the remount process may maintain the sysfs/aufs
24674+ * entries after acquiring write lock.
24675+ * it can cause a deadlock.
24676+ * simply we gave up processing read here.
24677+ */
24678+ err = -EBUSY;
24679+ if (unlikely(!si_noflush_read_trylock(sb)))
24680+ goto out;
1facf9fc 24681+
24682+ seq = au_seq(buf, PAGE_SIZE);
24683+ err = PTR_ERR(seq);
24684+ if (IS_ERR(seq))
1308ab2a 24685+ goto out_unlock;
1facf9fc 24686+
24687+ name = (void *)attr->name;
24688+ cattr = sysaufs_si_attrs;
24689+ while (*cattr) {
24690+ if (!strcmp(name, (*cattr)->name)) {
24691+ err = container_of(*cattr, struct sysaufs_si_attr, attr)
24692+ ->show(seq, sb);
24693+ goto out_seq;
24694+ }
24695+ cattr++;
24696+ }
24697+
24698+ bend = au_sbend(sb);
24699+ if (!strncmp(name, SysaufsBr_PREFIX, sizeof(SysaufsBr_PREFIX) - 1)) {
24700+ name += sizeof(SysaufsBr_PREFIX) - 1;
9dbd164d 24701+ err = kstrtol(name, 10, &l);
1facf9fc 24702+ if (!err) {
24703+ if (l <= bend)
24704+ err = sysaufs_si_br(seq, sb, (aufs_bindex_t)l);
24705+ else
24706+ err = -ENOENT;
24707+ }
24708+ goto out_seq;
24709+ }
24710+ BUG();
24711+
4f0767ce 24712+out_seq:
1facf9fc 24713+ if (!err) {
24714+ err = seq->count;
24715+ /* sysfs limit */
24716+ if (unlikely(err == PAGE_SIZE))
24717+ err = -EFBIG;
24718+ }
24719+ kfree(seq);
4f0767ce 24720+out_unlock:
1facf9fc 24721+ si_read_unlock(sb);
4f0767ce 24722+out:
1facf9fc 24723+ return err;
24724+}
24725+
24726+/* ---------------------------------------------------------------------- */
24727+
24728+void sysaufs_br_init(struct au_branch *br)
24729+{
4a4d8108
AM
24730+ struct attribute *attr = &br->br_attr;
24731+
24732+ sysfs_attr_init(attr);
24733+ attr->name = br->br_name;
24734+ attr->mode = S_IRUGO;
1facf9fc 24735+}
24736+
24737+void sysaufs_brs_del(struct super_block *sb, aufs_bindex_t bindex)
24738+{
24739+ struct au_branch *br;
24740+ struct kobject *kobj;
24741+ aufs_bindex_t bend;
24742+
24743+ dbgaufs_brs_del(sb, bindex);
24744+
24745+ if (!sysaufs_brs)
24746+ return;
24747+
24748+ kobj = &au_sbi(sb)->si_kobj;
24749+ bend = au_sbend(sb);
24750+ for (; bindex <= bend; bindex++) {
24751+ br = au_sbr(sb, bindex);
24752+ sysfs_remove_file(kobj, &br->br_attr);
24753+ }
24754+}
24755+
24756+void sysaufs_brs_add(struct super_block *sb, aufs_bindex_t bindex)
24757+{
24758+ int err;
24759+ aufs_bindex_t bend;
24760+ struct kobject *kobj;
24761+ struct au_branch *br;
24762+
24763+ dbgaufs_brs_add(sb, bindex);
24764+
24765+ if (!sysaufs_brs)
24766+ return;
24767+
24768+ kobj = &au_sbi(sb)->si_kobj;
24769+ bend = au_sbend(sb);
24770+ for (; bindex <= bend; bindex++) {
24771+ br = au_sbr(sb, bindex);
24772+ snprintf(br->br_name, sizeof(br->br_name), SysaufsBr_PREFIX
24773+ "%d", bindex);
24774+ err = sysfs_create_file(kobj, &br->br_attr);
24775+ if (unlikely(err))
4a4d8108
AM
24776+ pr_warning("failed %s under sysfs(%d)\n",
24777+ br->br_name, err);
1facf9fc 24778+ }
24779+}
7f207e10
AM
24780diff -urN /usr/share/empty/fs/aufs/sysrq.c linux/fs/aufs/sysrq.c
24781--- /usr/share/empty/fs/aufs/sysrq.c 1970-01-01 01:00:00.000000000 +0100
7ce627cf 24782+++ linux/fs/aufs/sysrq.c 2012-05-22 09:06:08.870792417 +0200
f6c5ef8b 24783@@ -0,0 +1,148 @@
1facf9fc 24784+/*
f6c5ef8b 24785+ * Copyright (C) 2005-2012 Junjiro R. Okajima
1facf9fc 24786+ *
24787+ * This program, aufs is free software; you can redistribute it and/or modify
24788+ * it under the terms of the GNU General Public License as published by
24789+ * the Free Software Foundation; either version 2 of the License, or
24790+ * (at your option) any later version.
dece6358
AM
24791+ *
24792+ * This program is distributed in the hope that it will be useful,
24793+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
24794+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24795+ * GNU General Public License for more details.
24796+ *
24797+ * You should have received a copy of the GNU General Public License
24798+ * along with this program; if not, write to the Free Software
24799+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 24800+ */
24801+
24802+/*
24803+ * magic sysrq hanlder
24804+ */
24805+
1facf9fc 24806+/* #include <linux/sysrq.h> */
027c5e7a 24807+#include <linux/writeback.h>
1facf9fc 24808+#include "aufs.h"
24809+
24810+/* ---------------------------------------------------------------------- */
24811+
24812+static void sysrq_sb(struct super_block *sb)
24813+{
24814+ char *plevel;
24815+ struct au_sbinfo *sbinfo;
24816+ struct file *file;
24817+
24818+ plevel = au_plevel;
24819+ au_plevel = KERN_WARNING;
1facf9fc 24820+
24821+ sbinfo = au_sbi(sb);
4a4d8108
AM
24822+ /* since we define pr_fmt, call printk directly */
24823+ printk(KERN_WARNING "si=%lx\n", sysaufs_si_id(sbinfo));
24824+ printk(KERN_WARNING AUFS_NAME ": superblock\n");
1facf9fc 24825+ au_dpri_sb(sb);
027c5e7a
AM
24826+
24827+#if 0
4a4d8108 24828+ printk(KERN_WARNING AUFS_NAME ": root dentry\n");
1facf9fc 24829+ au_dpri_dentry(sb->s_root);
4a4d8108 24830+ printk(KERN_WARNING AUFS_NAME ": root inode\n");
1facf9fc 24831+ au_dpri_inode(sb->s_root->d_inode);
027c5e7a
AM
24832+#endif
24833+
1facf9fc 24834+#if 0
027c5e7a
AM
24835+ do {
24836+ int err, i, j, ndentry;
24837+ struct au_dcsub_pages dpages;
24838+ struct au_dpage *dpage;
24839+
24840+ err = au_dpages_init(&dpages, GFP_ATOMIC);
24841+ if (unlikely(err))
24842+ break;
24843+ err = au_dcsub_pages(&dpages, sb->s_root, NULL, NULL);
24844+ if (!err)
24845+ for (i = 0; i < dpages.ndpage; i++) {
24846+ dpage = dpages.dpages + i;
24847+ ndentry = dpage->ndentry;
24848+ for (j = 0; j < ndentry; j++)
24849+ au_dpri_dentry(dpage->dentries[j]);
24850+ }
24851+ au_dpages_free(&dpages);
24852+ } while (0);
24853+#endif
24854+
24855+#if 1
24856+ {
24857+ struct inode *i;
24858+ printk(KERN_WARNING AUFS_NAME ": isolated inode\n");
2cbb1c4b
JR
24859+ spin_lock(&inode_sb_list_lock);
24860+ list_for_each_entry(i, &sb->s_inodes, i_sb_list) {
24861+ spin_lock(&i->i_lock);
027c5e7a
AM
24862+ if (1 || list_empty(&i->i_dentry))
24863+ au_dpri_inode(i);
2cbb1c4b
JR
24864+ spin_unlock(&i->i_lock);
24865+ }
24866+ spin_unlock(&inode_sb_list_lock);
027c5e7a 24867+ }
1facf9fc 24868+#endif
4a4d8108 24869+ printk(KERN_WARNING AUFS_NAME ": files\n");
0c5527e5
AM
24870+ lg_global_lock(files_lglock);
24871+ do_file_list_for_each_entry(sb, file) {
4a4d8108
AM
24872+ umode_t mode;
24873+ mode = file->f_dentry->d_inode->i_mode;
24874+ if (!special_file(mode) || au_special_file(mode))
1facf9fc 24875+ au_dpri_file(file);
0c5527e5
AM
24876+ } while_file_list_for_each_entry;
24877+ lg_global_unlock(files_lglock);
e49829fe 24878+ printk(KERN_WARNING AUFS_NAME ": done\n");
1facf9fc 24879+
24880+ au_plevel = plevel;
1facf9fc 24881+}
24882+
24883+/* ---------------------------------------------------------------------- */
24884+
24885+/* module parameter */
24886+static char *aufs_sysrq_key = "a";
24887+module_param_named(sysrq, aufs_sysrq_key, charp, S_IRUGO);
24888+MODULE_PARM_DESC(sysrq, "MagicSysRq key for " AUFS_NAME);
24889+
0c5527e5 24890+static void au_sysrq(int key __maybe_unused)
1facf9fc 24891+{
1facf9fc 24892+ struct au_sbinfo *sbinfo;
24893+
027c5e7a 24894+ lockdep_off();
53392da6 24895+ au_sbilist_lock();
e49829fe 24896+ list_for_each_entry(sbinfo, &au_sbilist.head, si_list)
1facf9fc 24897+ sysrq_sb(sbinfo->si_sb);
53392da6 24898+ au_sbilist_unlock();
027c5e7a 24899+ lockdep_on();
1facf9fc 24900+}
24901+
24902+static struct sysrq_key_op au_sysrq_op = {
24903+ .handler = au_sysrq,
24904+ .help_msg = "Aufs",
24905+ .action_msg = "Aufs",
24906+ .enable_mask = SYSRQ_ENABLE_DUMP
24907+};
24908+
24909+/* ---------------------------------------------------------------------- */
24910+
24911+int __init au_sysrq_init(void)
24912+{
24913+ int err;
24914+ char key;
24915+
24916+ err = -1;
24917+ key = *aufs_sysrq_key;
24918+ if ('a' <= key && key <= 'z')
24919+ err = register_sysrq_key(key, &au_sysrq_op);
24920+ if (unlikely(err))
4a4d8108 24921+ pr_err("err %d, sysrq=%c\n", err, key);
1facf9fc 24922+ return err;
24923+}
24924+
24925+void au_sysrq_fin(void)
24926+{
24927+ int err;
24928+ err = unregister_sysrq_key(*aufs_sysrq_key, &au_sysrq_op);
24929+ if (unlikely(err))
4a4d8108 24930+ pr_err("err %d (ignored)\n", err);
1facf9fc 24931+}
7f207e10
AM
24932diff -urN /usr/share/empty/fs/aufs/vdir.c linux/fs/aufs/vdir.c
24933--- /usr/share/empty/fs/aufs/vdir.c 1970-01-01 01:00:00.000000000 +0100
7ce627cf 24934+++ linux/fs/aufs/vdir.c 2012-05-22 09:06:08.870792417 +0200
f6c5ef8b 24935@@ -0,0 +1,885 @@
1facf9fc 24936+/*
f6c5ef8b 24937+ * Copyright (C) 2005-2012 Junjiro R. Okajima
1facf9fc 24938+ *
24939+ * This program, aufs is free software; you can redistribute it and/or modify
24940+ * it under the terms of the GNU General Public License as published by
24941+ * the Free Software Foundation; either version 2 of the License, or
24942+ * (at your option) any later version.
dece6358
AM
24943+ *
24944+ * This program is distributed in the hope that it will be useful,
24945+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
24946+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24947+ * GNU General Public License for more details.
24948+ *
24949+ * You should have received a copy of the GNU General Public License
24950+ * along with this program; if not, write to the Free Software
24951+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 24952+ */
24953+
24954+/*
24955+ * virtual or vertical directory
24956+ */
24957+
24958+#include "aufs.h"
24959+
dece6358 24960+static unsigned int calc_size(int nlen)
1facf9fc 24961+{
dece6358 24962+ return ALIGN(sizeof(struct au_vdir_de) + nlen, sizeof(ino_t));
1facf9fc 24963+}
24964+
24965+static int set_deblk_end(union au_vdir_deblk_p *p,
24966+ union au_vdir_deblk_p *deblk_end)
24967+{
24968+ if (calc_size(0) <= deblk_end->deblk - p->deblk) {
24969+ p->de->de_str.len = 0;
24970+ /* smp_mb(); */
24971+ return 0;
24972+ }
24973+ return -1; /* error */
24974+}
24975+
24976+/* returns true or false */
24977+static int is_deblk_end(union au_vdir_deblk_p *p,
24978+ union au_vdir_deblk_p *deblk_end)
24979+{
24980+ if (calc_size(0) <= deblk_end->deblk - p->deblk)
24981+ return !p->de->de_str.len;
24982+ return 1;
24983+}
24984+
24985+static unsigned char *last_deblk(struct au_vdir *vdir)
24986+{
24987+ return vdir->vd_deblk[vdir->vd_nblk - 1];
24988+}
24989+
24990+/* ---------------------------------------------------------------------- */
24991+
1308ab2a 24992+/* estimate the apropriate size for name hash table */
24993+unsigned int au_rdhash_est(loff_t sz)
24994+{
24995+ unsigned int n;
24996+
24997+ n = UINT_MAX;
24998+ sz >>= 10;
24999+ if (sz < n)
25000+ n = sz;
25001+ if (sz < AUFS_RDHASH_DEF)
25002+ n = AUFS_RDHASH_DEF;
4a4d8108 25003+ /* pr_info("n %u\n", n); */
1308ab2a 25004+ return n;
25005+}
25006+
1facf9fc 25007+/*
25008+ * the allocated memory has to be freed by
dece6358 25009+ * au_nhash_wh_free() or au_nhash_de_free().
1facf9fc 25010+ */
dece6358 25011+int au_nhash_alloc(struct au_nhash *nhash, unsigned int num_hash, gfp_t gfp)
1facf9fc 25012+{
1facf9fc 25013+ struct hlist_head *head;
dece6358 25014+ unsigned int u;
1facf9fc 25015+
dece6358
AM
25016+ head = kmalloc(sizeof(*nhash->nh_head) * num_hash, gfp);
25017+ if (head) {
25018+ nhash->nh_num = num_hash;
25019+ nhash->nh_head = head;
25020+ for (u = 0; u < num_hash; u++)
1facf9fc 25021+ INIT_HLIST_HEAD(head++);
dece6358 25022+ return 0; /* success */
1facf9fc 25023+ }
1facf9fc 25024+
dece6358 25025+ return -ENOMEM;
1facf9fc 25026+}
25027+
dece6358
AM
25028+static void nhash_count(struct hlist_head *head)
25029+{
25030+#if 0
25031+ unsigned long n;
25032+ struct hlist_node *pos;
25033+
25034+ n = 0;
25035+ hlist_for_each(pos, head)
25036+ n++;
4a4d8108 25037+ pr_info("%lu\n", n);
dece6358
AM
25038+#endif
25039+}
25040+
25041+static void au_nhash_wh_do_free(struct hlist_head *head)
1facf9fc 25042+{
1facf9fc 25043+ struct au_vdir_wh *tpos;
25044+ struct hlist_node *pos, *node;
25045+
dece6358
AM
25046+ hlist_for_each_entry_safe(tpos, pos, node, head, wh_hash) {
25047+ /* hlist_del(pos); */
25048+ kfree(tpos);
1facf9fc 25049+ }
25050+}
25051+
dece6358 25052+static void au_nhash_de_do_free(struct hlist_head *head)
1facf9fc 25053+{
dece6358
AM
25054+ struct au_vdir_dehstr *tpos;
25055+ struct hlist_node *pos, *node;
1facf9fc 25056+
dece6358
AM
25057+ hlist_for_each_entry_safe(tpos, pos, node, head, hash) {
25058+ /* hlist_del(pos); */
4a4d8108 25059+ au_cache_free_vdir_dehstr(tpos);
1facf9fc 25060+ }
1facf9fc 25061+}
25062+
dece6358
AM
25063+static void au_nhash_do_free(struct au_nhash *nhash,
25064+ void (*free)(struct hlist_head *head))
1facf9fc 25065+{
1308ab2a 25066+ unsigned int n;
1facf9fc 25067+ struct hlist_head *head;
1facf9fc 25068+
dece6358 25069+ n = nhash->nh_num;
1308ab2a 25070+ if (!n)
25071+ return;
25072+
dece6358 25073+ head = nhash->nh_head;
1308ab2a 25074+ while (n-- > 0) {
dece6358
AM
25075+ nhash_count(head);
25076+ free(head++);
1facf9fc 25077+ }
dece6358 25078+ kfree(nhash->nh_head);
1facf9fc 25079+}
25080+
dece6358 25081+void au_nhash_wh_free(struct au_nhash *whlist)
1facf9fc 25082+{
dece6358
AM
25083+ au_nhash_do_free(whlist, au_nhash_wh_do_free);
25084+}
1facf9fc 25085+
dece6358
AM
25086+static void au_nhash_de_free(struct au_nhash *delist)
25087+{
25088+ au_nhash_do_free(delist, au_nhash_de_do_free);
1facf9fc 25089+}
25090+
25091+/* ---------------------------------------------------------------------- */
25092+
25093+int au_nhash_test_longer_wh(struct au_nhash *whlist, aufs_bindex_t btgt,
25094+ int limit)
25095+{
25096+ int num;
25097+ unsigned int u, n;
25098+ struct hlist_head *head;
25099+ struct au_vdir_wh *tpos;
25100+ struct hlist_node *pos;
25101+
25102+ num = 0;
25103+ n = whlist->nh_num;
25104+ head = whlist->nh_head;
1308ab2a 25105+ for (u = 0; u < n; u++, head++)
1facf9fc 25106+ hlist_for_each_entry(tpos, pos, head, wh_hash)
25107+ if (tpos->wh_bindex == btgt && ++num > limit)
25108+ return 1;
1facf9fc 25109+ return 0;
25110+}
25111+
25112+static struct hlist_head *au_name_hash(struct au_nhash *nhash,
dece6358 25113+ unsigned char *name,
1facf9fc 25114+ unsigned int len)
25115+{
dece6358
AM
25116+ unsigned int v;
25117+ /* const unsigned int magic_bit = 12; */
25118+
1308ab2a 25119+ AuDebugOn(!nhash->nh_num || !nhash->nh_head);
25120+
dece6358
AM
25121+ v = 0;
25122+ while (len--)
25123+ v += *name++;
25124+ /* v = hash_long(v, magic_bit); */
25125+ v %= nhash->nh_num;
25126+ return nhash->nh_head + v;
25127+}
25128+
25129+static int au_nhash_test_name(struct au_vdir_destr *str, const char *name,
25130+ int nlen)
25131+{
25132+ return str->len == nlen && !memcmp(str->name, name, nlen);
1facf9fc 25133+}
25134+
25135+/* returns found or not */
dece6358 25136+int au_nhash_test_known_wh(struct au_nhash *whlist, char *name, int nlen)
1facf9fc 25137+{
25138+ struct hlist_head *head;
25139+ struct au_vdir_wh *tpos;
25140+ struct hlist_node *pos;
25141+ struct au_vdir_destr *str;
25142+
dece6358 25143+ head = au_name_hash(whlist, name, nlen);
1facf9fc 25144+ hlist_for_each_entry(tpos, pos, head, wh_hash) {
25145+ str = &tpos->wh_str;
25146+ AuDbg("%.*s\n", str->len, str->name);
dece6358
AM
25147+ if (au_nhash_test_name(str, name, nlen))
25148+ return 1;
25149+ }
25150+ return 0;
25151+}
25152+
25153+/* returns found(true) or not */
25154+static int test_known(struct au_nhash *delist, char *name, int nlen)
25155+{
25156+ struct hlist_head *head;
25157+ struct au_vdir_dehstr *tpos;
25158+ struct hlist_node *pos;
25159+ struct au_vdir_destr *str;
25160+
25161+ head = au_name_hash(delist, name, nlen);
25162+ hlist_for_each_entry(tpos, pos, head, hash) {
25163+ str = tpos->str;
25164+ AuDbg("%.*s\n", str->len, str->name);
25165+ if (au_nhash_test_name(str, name, nlen))
1facf9fc 25166+ return 1;
25167+ }
25168+ return 0;
25169+}
25170+
dece6358
AM
25171+static void au_shwh_init_wh(struct au_vdir_wh *wh, ino_t ino,
25172+ unsigned char d_type)
25173+{
25174+#ifdef CONFIG_AUFS_SHWH
25175+ wh->wh_ino = ino;
25176+ wh->wh_type = d_type;
25177+#endif
25178+}
25179+
25180+/* ---------------------------------------------------------------------- */
25181+
25182+int au_nhash_append_wh(struct au_nhash *whlist, char *name, int nlen, ino_t ino,
25183+ unsigned int d_type, aufs_bindex_t bindex,
25184+ unsigned char shwh)
1facf9fc 25185+{
25186+ int err;
25187+ struct au_vdir_destr *str;
25188+ struct au_vdir_wh *wh;
25189+
dece6358 25190+ AuDbg("%.*s\n", nlen, name);
1308ab2a 25191+ AuDebugOn(!whlist->nh_num || !whlist->nh_head);
25192+
1facf9fc 25193+ err = -ENOMEM;
dece6358 25194+ wh = kmalloc(sizeof(*wh) + nlen, GFP_NOFS);
1facf9fc 25195+ if (unlikely(!wh))
25196+ goto out;
25197+
25198+ err = 0;
25199+ wh->wh_bindex = bindex;
dece6358
AM
25200+ if (shwh)
25201+ au_shwh_init_wh(wh, ino, d_type);
1facf9fc 25202+ str = &wh->wh_str;
dece6358
AM
25203+ str->len = nlen;
25204+ memcpy(str->name, name, nlen);
25205+ hlist_add_head(&wh->wh_hash, au_name_hash(whlist, name, nlen));
1facf9fc 25206+ /* smp_mb(); */
25207+
4f0767ce 25208+out:
1facf9fc 25209+ return err;
25210+}
25211+
1facf9fc 25212+static int append_deblk(struct au_vdir *vdir)
25213+{
25214+ int err;
dece6358 25215+ unsigned long ul;
1facf9fc 25216+ const unsigned int deblk_sz = vdir->vd_deblk_sz;
25217+ union au_vdir_deblk_p p, deblk_end;
25218+ unsigned char **o;
25219+
25220+ err = -ENOMEM;
dece6358
AM
25221+ o = krealloc(vdir->vd_deblk, sizeof(*o) * (vdir->vd_nblk + 1),
25222+ GFP_NOFS);
1facf9fc 25223+ if (unlikely(!o))
25224+ goto out;
25225+
25226+ vdir->vd_deblk = o;
25227+ p.deblk = kmalloc(deblk_sz, GFP_NOFS);
25228+ if (p.deblk) {
25229+ ul = vdir->vd_nblk++;
25230+ vdir->vd_deblk[ul] = p.deblk;
25231+ vdir->vd_last.ul = ul;
25232+ vdir->vd_last.p.deblk = p.deblk;
25233+ deblk_end.deblk = p.deblk + deblk_sz;
25234+ err = set_deblk_end(&p, &deblk_end);
25235+ }
25236+
4f0767ce 25237+out:
1facf9fc 25238+ return err;
25239+}
25240+
dece6358
AM
25241+static int append_de(struct au_vdir *vdir, char *name, int nlen, ino_t ino,
25242+ unsigned int d_type, struct au_nhash *delist)
25243+{
25244+ int err;
25245+ unsigned int sz;
25246+ const unsigned int deblk_sz = vdir->vd_deblk_sz;
25247+ union au_vdir_deblk_p p, *room, deblk_end;
25248+ struct au_vdir_dehstr *dehstr;
25249+
25250+ p.deblk = last_deblk(vdir);
25251+ deblk_end.deblk = p.deblk + deblk_sz;
25252+ room = &vdir->vd_last.p;
25253+ AuDebugOn(room->deblk < p.deblk || deblk_end.deblk <= room->deblk
25254+ || !is_deblk_end(room, &deblk_end));
25255+
25256+ sz = calc_size(nlen);
25257+ if (unlikely(sz > deblk_end.deblk - room->deblk)) {
25258+ err = append_deblk(vdir);
25259+ if (unlikely(err))
25260+ goto out;
25261+
25262+ p.deblk = last_deblk(vdir);
25263+ deblk_end.deblk = p.deblk + deblk_sz;
25264+ /* smp_mb(); */
25265+ AuDebugOn(room->deblk != p.deblk);
25266+ }
25267+
25268+ err = -ENOMEM;
4a4d8108 25269+ dehstr = au_cache_alloc_vdir_dehstr();
dece6358
AM
25270+ if (unlikely(!dehstr))
25271+ goto out;
25272+
25273+ dehstr->str = &room->de->de_str;
25274+ hlist_add_head(&dehstr->hash, au_name_hash(delist, name, nlen));
25275+ room->de->de_ino = ino;
25276+ room->de->de_type = d_type;
25277+ room->de->de_str.len = nlen;
25278+ memcpy(room->de->de_str.name, name, nlen);
25279+
25280+ err = 0;
25281+ room->deblk += sz;
25282+ if (unlikely(set_deblk_end(room, &deblk_end)))
25283+ err = append_deblk(vdir);
25284+ /* smp_mb(); */
25285+
4f0767ce 25286+out:
dece6358
AM
25287+ return err;
25288+}
25289+
25290+/* ---------------------------------------------------------------------- */
25291+
25292+void au_vdir_free(struct au_vdir *vdir)
25293+{
25294+ unsigned char **deblk;
25295+
25296+ deblk = vdir->vd_deblk;
25297+ while (vdir->vd_nblk--)
25298+ kfree(*deblk++);
25299+ kfree(vdir->vd_deblk);
25300+ au_cache_free_vdir(vdir);
25301+}
25302+
1308ab2a 25303+static struct au_vdir *alloc_vdir(struct file *file)
1facf9fc 25304+{
25305+ struct au_vdir *vdir;
1308ab2a 25306+ struct super_block *sb;
1facf9fc 25307+ int err;
25308+
1308ab2a 25309+ sb = file->f_dentry->d_sb;
dece6358
AM
25310+ SiMustAnyLock(sb);
25311+
1facf9fc 25312+ err = -ENOMEM;
25313+ vdir = au_cache_alloc_vdir();
25314+ if (unlikely(!vdir))
25315+ goto out;
25316+
25317+ vdir->vd_deblk = kzalloc(sizeof(*vdir->vd_deblk), GFP_NOFS);
25318+ if (unlikely(!vdir->vd_deblk))
25319+ goto out_free;
25320+
25321+ vdir->vd_deblk_sz = au_sbi(sb)->si_rdblk;
1308ab2a 25322+ if (!vdir->vd_deblk_sz) {
25323+ /* estimate the apropriate size for deblk */
25324+ vdir->vd_deblk_sz = au_dir_size(file, /*dentry*/NULL);
4a4d8108 25325+ /* pr_info("vd_deblk_sz %u\n", vdir->vd_deblk_sz); */
1308ab2a 25326+ }
1facf9fc 25327+ vdir->vd_nblk = 0;
25328+ vdir->vd_version = 0;
25329+ vdir->vd_jiffy = 0;
25330+ err = append_deblk(vdir);
25331+ if (!err)
25332+ return vdir; /* success */
25333+
25334+ kfree(vdir->vd_deblk);
25335+
4f0767ce 25336+out_free:
1facf9fc 25337+ au_cache_free_vdir(vdir);
4f0767ce 25338+out:
1facf9fc 25339+ vdir = ERR_PTR(err);
25340+ return vdir;
25341+}
25342+
25343+static int reinit_vdir(struct au_vdir *vdir)
25344+{
25345+ int err;
25346+ union au_vdir_deblk_p p, deblk_end;
25347+
25348+ while (vdir->vd_nblk > 1) {
25349+ kfree(vdir->vd_deblk[vdir->vd_nblk - 1]);
25350+ /* vdir->vd_deblk[vdir->vd_nblk - 1] = NULL; */
25351+ vdir->vd_nblk--;
25352+ }
25353+ p.deblk = vdir->vd_deblk[0];
25354+ deblk_end.deblk = p.deblk + vdir->vd_deblk_sz;
25355+ err = set_deblk_end(&p, &deblk_end);
25356+ /* keep vd_dblk_sz */
25357+ vdir->vd_last.ul = 0;
25358+ vdir->vd_last.p.deblk = vdir->vd_deblk[0];
25359+ vdir->vd_version = 0;
25360+ vdir->vd_jiffy = 0;
25361+ /* smp_mb(); */
25362+ return err;
25363+}
25364+
25365+/* ---------------------------------------------------------------------- */
25366+
1facf9fc 25367+#define AuFillVdir_CALLED 1
25368+#define AuFillVdir_WHABLE (1 << 1)
dece6358 25369+#define AuFillVdir_SHWH (1 << 2)
1facf9fc 25370+#define au_ftest_fillvdir(flags, name) ((flags) & AuFillVdir_##name)
7f207e10
AM
25371+#define au_fset_fillvdir(flags, name) \
25372+ do { (flags) |= AuFillVdir_##name; } while (0)
25373+#define au_fclr_fillvdir(flags, name) \
25374+ do { (flags) &= ~AuFillVdir_##name; } while (0)
1facf9fc 25375+
dece6358
AM
25376+#ifndef CONFIG_AUFS_SHWH
25377+#undef AuFillVdir_SHWH
25378+#define AuFillVdir_SHWH 0
25379+#endif
25380+
1facf9fc 25381+struct fillvdir_arg {
25382+ struct file *file;
25383+ struct au_vdir *vdir;
dece6358
AM
25384+ struct au_nhash delist;
25385+ struct au_nhash whlist;
1facf9fc 25386+ aufs_bindex_t bindex;
25387+ unsigned int flags;
25388+ int err;
25389+};
25390+
dece6358 25391+static int fillvdir(void *__arg, const char *__name, int nlen,
1facf9fc 25392+ loff_t offset __maybe_unused, u64 h_ino,
25393+ unsigned int d_type)
25394+{
25395+ struct fillvdir_arg *arg = __arg;
25396+ char *name = (void *)__name;
25397+ struct super_block *sb;
1facf9fc 25398+ ino_t ino;
dece6358 25399+ const unsigned char shwh = !!au_ftest_fillvdir(arg->flags, SHWH);
1facf9fc 25400+
1facf9fc 25401+ arg->err = 0;
dece6358 25402+ sb = arg->file->f_dentry->d_sb;
1facf9fc 25403+ au_fset_fillvdir(arg->flags, CALLED);
25404+ /* smp_mb(); */
dece6358 25405+ if (nlen <= AUFS_WH_PFX_LEN
1facf9fc 25406+ || memcmp(name, AUFS_WH_PFX, AUFS_WH_PFX_LEN)) {
dece6358
AM
25407+ if (test_known(&arg->delist, name, nlen)
25408+ || au_nhash_test_known_wh(&arg->whlist, name, nlen))
25409+ goto out; /* already exists or whiteouted */
1facf9fc 25410+
25411+ sb = arg->file->f_dentry->d_sb;
dece6358 25412+ arg->err = au_ino(sb, arg->bindex, h_ino, d_type, &ino);
4a4d8108
AM
25413+ if (!arg->err) {
25414+ if (unlikely(nlen > AUFS_MAX_NAMELEN))
25415+ d_type = DT_UNKNOWN;
dece6358
AM
25416+ arg->err = append_de(arg->vdir, name, nlen, ino,
25417+ d_type, &arg->delist);
4a4d8108 25418+ }
1facf9fc 25419+ } else if (au_ftest_fillvdir(arg->flags, WHABLE)) {
25420+ name += AUFS_WH_PFX_LEN;
dece6358
AM
25421+ nlen -= AUFS_WH_PFX_LEN;
25422+ if (au_nhash_test_known_wh(&arg->whlist, name, nlen))
25423+ goto out; /* already whiteouted */
1facf9fc 25424+
dece6358
AM
25425+ if (shwh)
25426+ arg->err = au_wh_ino(sb, arg->bindex, h_ino, d_type,
25427+ &ino);
4a4d8108
AM
25428+ if (!arg->err) {
25429+ if (nlen <= AUFS_MAX_NAMELEN + AUFS_WH_PFX_LEN)
25430+ d_type = DT_UNKNOWN;
1facf9fc 25431+ arg->err = au_nhash_append_wh
dece6358
AM
25432+ (&arg->whlist, name, nlen, ino, d_type,
25433+ arg->bindex, shwh);
4a4d8108 25434+ }
1facf9fc 25435+ }
25436+
4f0767ce 25437+out:
1facf9fc 25438+ if (!arg->err)
25439+ arg->vdir->vd_jiffy = jiffies;
25440+ /* smp_mb(); */
25441+ AuTraceErr(arg->err);
25442+ return arg->err;
25443+}
25444+
dece6358
AM
25445+static int au_handle_shwh(struct super_block *sb, struct au_vdir *vdir,
25446+ struct au_nhash *whlist, struct au_nhash *delist)
25447+{
25448+#ifdef CONFIG_AUFS_SHWH
25449+ int err;
25450+ unsigned int nh, u;
25451+ struct hlist_head *head;
25452+ struct au_vdir_wh *tpos;
25453+ struct hlist_node *pos, *n;
25454+ char *p, *o;
25455+ struct au_vdir_destr *destr;
25456+
25457+ AuDebugOn(!au_opt_test(au_mntflags(sb), SHWH));
25458+
25459+ err = -ENOMEM;
4a4d8108 25460+ o = p = __getname_gfp(GFP_NOFS);
dece6358
AM
25461+ if (unlikely(!p))
25462+ goto out;
25463+
25464+ err = 0;
25465+ nh = whlist->nh_num;
25466+ memcpy(p, AUFS_WH_PFX, AUFS_WH_PFX_LEN);
25467+ p += AUFS_WH_PFX_LEN;
25468+ for (u = 0; u < nh; u++) {
25469+ head = whlist->nh_head + u;
25470+ hlist_for_each_entry_safe(tpos, pos, n, head, wh_hash) {
25471+ destr = &tpos->wh_str;
25472+ memcpy(p, destr->name, destr->len);
25473+ err = append_de(vdir, o, destr->len + AUFS_WH_PFX_LEN,
25474+ tpos->wh_ino, tpos->wh_type, delist);
25475+ if (unlikely(err))
25476+ break;
25477+ }
25478+ }
25479+
25480+ __putname(o);
25481+
4f0767ce 25482+out:
dece6358
AM
25483+ AuTraceErr(err);
25484+ return err;
25485+#else
25486+ return 0;
25487+#endif
25488+}
25489+
1facf9fc 25490+static int au_do_read_vdir(struct fillvdir_arg *arg)
25491+{
25492+ int err;
dece6358 25493+ unsigned int rdhash;
1facf9fc 25494+ loff_t offset;
dece6358
AM
25495+ aufs_bindex_t bend, bindex, bstart;
25496+ unsigned char shwh;
1facf9fc 25497+ struct file *hf, *file;
25498+ struct super_block *sb;
25499+
1facf9fc 25500+ file = arg->file;
25501+ sb = file->f_dentry->d_sb;
dece6358
AM
25502+ SiMustAnyLock(sb);
25503+
25504+ rdhash = au_sbi(sb)->si_rdhash;
1308ab2a 25505+ if (!rdhash)
25506+ rdhash = au_rdhash_est(au_dir_size(file, /*dentry*/NULL));
dece6358
AM
25507+ err = au_nhash_alloc(&arg->delist, rdhash, GFP_NOFS);
25508+ if (unlikely(err))
1facf9fc 25509+ goto out;
dece6358
AM
25510+ err = au_nhash_alloc(&arg->whlist, rdhash, GFP_NOFS);
25511+ if (unlikely(err))
1facf9fc 25512+ goto out_delist;
25513+
25514+ err = 0;
25515+ arg->flags = 0;
dece6358
AM
25516+ shwh = 0;
25517+ if (au_opt_test(au_mntflags(sb), SHWH)) {
25518+ shwh = 1;
25519+ au_fset_fillvdir(arg->flags, SHWH);
25520+ }
25521+ bstart = au_fbstart(file);
4a4d8108 25522+ bend = au_fbend_dir(file);
dece6358 25523+ for (bindex = bstart; !err && bindex <= bend; bindex++) {
4a4d8108 25524+ hf = au_hf_dir(file, bindex);
1facf9fc 25525+ if (!hf)
25526+ continue;
25527+
25528+ offset = vfsub_llseek(hf, 0, SEEK_SET);
25529+ err = offset;
25530+ if (unlikely(offset))
25531+ break;
25532+
25533+ arg->bindex = bindex;
25534+ au_fclr_fillvdir(arg->flags, WHABLE);
dece6358
AM
25535+ if (shwh
25536+ || (bindex != bend
25537+ && au_br_whable(au_sbr_perm(sb, bindex))))
1facf9fc 25538+ au_fset_fillvdir(arg->flags, WHABLE);
25539+ do {
25540+ arg->err = 0;
25541+ au_fclr_fillvdir(arg->flags, CALLED);
25542+ /* smp_mb(); */
25543+ err = vfsub_readdir(hf, fillvdir, arg);
25544+ if (err >= 0)
25545+ err = arg->err;
25546+ } while (!err && au_ftest_fillvdir(arg->flags, CALLED));
25547+ }
dece6358
AM
25548+
25549+ if (!err && shwh)
25550+ err = au_handle_shwh(sb, arg->vdir, &arg->whlist, &arg->delist);
25551+
25552+ au_nhash_wh_free(&arg->whlist);
1facf9fc 25553+
4f0767ce 25554+out_delist:
dece6358 25555+ au_nhash_de_free(&arg->delist);
4f0767ce 25556+out:
1facf9fc 25557+ return err;
25558+}
25559+
25560+static int read_vdir(struct file *file, int may_read)
25561+{
25562+ int err;
25563+ unsigned long expire;
25564+ unsigned char do_read;
25565+ struct fillvdir_arg arg;
25566+ struct inode *inode;
25567+ struct au_vdir *vdir, *allocated;
25568+
25569+ err = 0;
25570+ inode = file->f_dentry->d_inode;
25571+ IMustLock(inode);
dece6358
AM
25572+ SiMustAnyLock(inode->i_sb);
25573+
1facf9fc 25574+ allocated = NULL;
25575+ do_read = 0;
25576+ expire = au_sbi(inode->i_sb)->si_rdcache;
25577+ vdir = au_ivdir(inode);
25578+ if (!vdir) {
25579+ do_read = 1;
1308ab2a 25580+ vdir = alloc_vdir(file);
1facf9fc 25581+ err = PTR_ERR(vdir);
25582+ if (IS_ERR(vdir))
25583+ goto out;
25584+ err = 0;
25585+ allocated = vdir;
25586+ } else if (may_read
25587+ && (inode->i_version != vdir->vd_version
25588+ || time_after(jiffies, vdir->vd_jiffy + expire))) {
25589+ do_read = 1;
25590+ err = reinit_vdir(vdir);
25591+ if (unlikely(err))
25592+ goto out;
25593+ }
25594+
25595+ if (!do_read)
25596+ return 0; /* success */
25597+
25598+ arg.file = file;
25599+ arg.vdir = vdir;
25600+ err = au_do_read_vdir(&arg);
25601+ if (!err) {
25602+ /* file->f_pos = 0; */
25603+ vdir->vd_version = inode->i_version;
25604+ vdir->vd_last.ul = 0;
25605+ vdir->vd_last.p.deblk = vdir->vd_deblk[0];
25606+ if (allocated)
25607+ au_set_ivdir(inode, allocated);
25608+ } else if (allocated)
25609+ au_vdir_free(allocated);
25610+
4f0767ce 25611+out:
1facf9fc 25612+ return err;
25613+}
25614+
25615+static int copy_vdir(struct au_vdir *tgt, struct au_vdir *src)
25616+{
25617+ int err, rerr;
25618+ unsigned long ul, n;
25619+ const unsigned int deblk_sz = src->vd_deblk_sz;
25620+
25621+ AuDebugOn(tgt->vd_nblk != 1);
25622+
25623+ err = -ENOMEM;
25624+ if (tgt->vd_nblk < src->vd_nblk) {
25625+ unsigned char **p;
25626+
dece6358
AM
25627+ p = krealloc(tgt->vd_deblk, sizeof(*p) * src->vd_nblk,
25628+ GFP_NOFS);
1facf9fc 25629+ if (unlikely(!p))
25630+ goto out;
25631+ tgt->vd_deblk = p;
25632+ }
25633+
1308ab2a 25634+ if (tgt->vd_deblk_sz != deblk_sz) {
25635+ unsigned char *p;
25636+
25637+ tgt->vd_deblk_sz = deblk_sz;
25638+ p = krealloc(tgt->vd_deblk[0], deblk_sz, GFP_NOFS);
25639+ if (unlikely(!p))
25640+ goto out;
25641+ tgt->vd_deblk[0] = p;
25642+ }
1facf9fc 25643+ memcpy(tgt->vd_deblk[0], src->vd_deblk[0], deblk_sz);
1facf9fc 25644+ tgt->vd_version = src->vd_version;
25645+ tgt->vd_jiffy = src->vd_jiffy;
25646+
25647+ n = src->vd_nblk;
25648+ for (ul = 1; ul < n; ul++) {
dece6358
AM
25649+ tgt->vd_deblk[ul] = kmemdup(src->vd_deblk[ul], deblk_sz,
25650+ GFP_NOFS);
25651+ if (unlikely(!tgt->vd_deblk[ul]))
1facf9fc 25652+ goto out;
1308ab2a 25653+ tgt->vd_nblk++;
1facf9fc 25654+ }
1308ab2a 25655+ tgt->vd_nblk = n;
25656+ tgt->vd_last.ul = tgt->vd_last.ul;
25657+ tgt->vd_last.p.deblk = tgt->vd_deblk[tgt->vd_last.ul];
25658+ tgt->vd_last.p.deblk += src->vd_last.p.deblk
25659+ - src->vd_deblk[src->vd_last.ul];
1facf9fc 25660+ /* smp_mb(); */
25661+ return 0; /* success */
25662+
4f0767ce 25663+out:
1facf9fc 25664+ rerr = reinit_vdir(tgt);
25665+ BUG_ON(rerr);
25666+ return err;
25667+}
25668+
25669+int au_vdir_init(struct file *file)
25670+{
25671+ int err;
25672+ struct inode *inode;
25673+ struct au_vdir *vdir_cache, *allocated;
25674+
25675+ err = read_vdir(file, !file->f_pos);
25676+ if (unlikely(err))
25677+ goto out;
25678+
25679+ allocated = NULL;
25680+ vdir_cache = au_fvdir_cache(file);
25681+ if (!vdir_cache) {
1308ab2a 25682+ vdir_cache = alloc_vdir(file);
1facf9fc 25683+ err = PTR_ERR(vdir_cache);
25684+ if (IS_ERR(vdir_cache))
25685+ goto out;
25686+ allocated = vdir_cache;
25687+ } else if (!file->f_pos && vdir_cache->vd_version != file->f_version) {
25688+ err = reinit_vdir(vdir_cache);
25689+ if (unlikely(err))
25690+ goto out;
25691+ } else
25692+ return 0; /* success */
25693+
25694+ inode = file->f_dentry->d_inode;
25695+ err = copy_vdir(vdir_cache, au_ivdir(inode));
25696+ if (!err) {
25697+ file->f_version = inode->i_version;
25698+ if (allocated)
25699+ au_set_fvdir_cache(file, allocated);
25700+ } else if (allocated)
25701+ au_vdir_free(allocated);
25702+
4f0767ce 25703+out:
1facf9fc 25704+ return err;
25705+}
25706+
25707+static loff_t calc_offset(struct au_vdir *vdir)
25708+{
25709+ loff_t offset;
25710+ union au_vdir_deblk_p p;
25711+
25712+ p.deblk = vdir->vd_deblk[vdir->vd_last.ul];
25713+ offset = vdir->vd_last.p.deblk - p.deblk;
25714+ offset += vdir->vd_deblk_sz * vdir->vd_last.ul;
25715+ return offset;
25716+}
25717+
25718+/* returns true or false */
25719+static int seek_vdir(struct file *file)
25720+{
25721+ int valid;
25722+ unsigned int deblk_sz;
25723+ unsigned long ul, n;
25724+ loff_t offset;
25725+ union au_vdir_deblk_p p, deblk_end;
25726+ struct au_vdir *vdir_cache;
25727+
25728+ valid = 1;
25729+ vdir_cache = au_fvdir_cache(file);
25730+ offset = calc_offset(vdir_cache);
25731+ AuDbg("offset %lld\n", offset);
25732+ if (file->f_pos == offset)
25733+ goto out;
25734+
25735+ vdir_cache->vd_last.ul = 0;
25736+ vdir_cache->vd_last.p.deblk = vdir_cache->vd_deblk[0];
25737+ if (!file->f_pos)
25738+ goto out;
25739+
25740+ valid = 0;
25741+ deblk_sz = vdir_cache->vd_deblk_sz;
25742+ ul = div64_u64(file->f_pos, deblk_sz);
25743+ AuDbg("ul %lu\n", ul);
25744+ if (ul >= vdir_cache->vd_nblk)
25745+ goto out;
25746+
25747+ n = vdir_cache->vd_nblk;
25748+ for (; ul < n; ul++) {
25749+ p.deblk = vdir_cache->vd_deblk[ul];
25750+ deblk_end.deblk = p.deblk + deblk_sz;
25751+ offset = ul;
25752+ offset *= deblk_sz;
25753+ while (!is_deblk_end(&p, &deblk_end) && offset < file->f_pos) {
25754+ unsigned int l;
25755+
25756+ l = calc_size(p.de->de_str.len);
25757+ offset += l;
25758+ p.deblk += l;
25759+ }
25760+ if (!is_deblk_end(&p, &deblk_end)) {
25761+ valid = 1;
25762+ vdir_cache->vd_last.ul = ul;
25763+ vdir_cache->vd_last.p = p;
25764+ break;
25765+ }
25766+ }
25767+
4f0767ce 25768+out:
1facf9fc 25769+ /* smp_mb(); */
25770+ AuTraceErr(!valid);
25771+ return valid;
25772+}
25773+
25774+int au_vdir_fill_de(struct file *file, void *dirent, filldir_t filldir)
25775+{
25776+ int err;
25777+ unsigned int l, deblk_sz;
25778+ union au_vdir_deblk_p deblk_end;
25779+ struct au_vdir *vdir_cache;
25780+ struct au_vdir_de *de;
25781+
25782+ vdir_cache = au_fvdir_cache(file);
25783+ if (!seek_vdir(file))
25784+ return 0;
25785+
25786+ deblk_sz = vdir_cache->vd_deblk_sz;
25787+ while (1) {
25788+ deblk_end.deblk = vdir_cache->vd_deblk[vdir_cache->vd_last.ul];
25789+ deblk_end.deblk += deblk_sz;
25790+ while (!is_deblk_end(&vdir_cache->vd_last.p, &deblk_end)) {
25791+ de = vdir_cache->vd_last.p.de;
25792+ AuDbg("%.*s, off%lld, i%lu, dt%d\n",
25793+ de->de_str.len, de->de_str.name, file->f_pos,
25794+ (unsigned long)de->de_ino, de->de_type);
25795+ err = filldir(dirent, de->de_str.name, de->de_str.len,
25796+ file->f_pos, de->de_ino, de->de_type);
25797+ if (unlikely(err)) {
25798+ AuTraceErr(err);
25799+ /* todo: ignore the error caused by udba? */
25800+ /* return err; */
25801+ return 0;
25802+ }
25803+
25804+ l = calc_size(de->de_str.len);
25805+ vdir_cache->vd_last.p.deblk += l;
25806+ file->f_pos += l;
25807+ }
25808+ if (vdir_cache->vd_last.ul < vdir_cache->vd_nblk - 1) {
25809+ vdir_cache->vd_last.ul++;
25810+ vdir_cache->vd_last.p.deblk
25811+ = vdir_cache->vd_deblk[vdir_cache->vd_last.ul];
25812+ file->f_pos = deblk_sz * vdir_cache->vd_last.ul;
25813+ continue;
25814+ }
25815+ break;
25816+ }
25817+
25818+ /* smp_mb(); */
25819+ return 0;
25820+}
7f207e10
AM
25821diff -urN /usr/share/empty/fs/aufs/vfsub.c linux/fs/aufs/vfsub.c
25822--- /usr/share/empty/fs/aufs/vfsub.c 1970-01-01 01:00:00.000000000 +0100
7ce627cf 25823+++ linux/fs/aufs/vfsub.c 2012-05-22 09:06:08.870792417 +0200
7eafdf33 25824@@ -0,0 +1,832 @@
1facf9fc 25825+/*
f6c5ef8b 25826+ * Copyright (C) 2005-2012 Junjiro R. Okajima
1facf9fc 25827+ *
25828+ * This program, aufs is free software; you can redistribute it and/or modify
25829+ * it under the terms of the GNU General Public License as published by
25830+ * the Free Software Foundation; either version 2 of the License, or
25831+ * (at your option) any later version.
dece6358
AM
25832+ *
25833+ * This program is distributed in the hope that it will be useful,
25834+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
25835+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
25836+ * GNU General Public License for more details.
25837+ *
25838+ * You should have received a copy of the GNU General Public License
25839+ * along with this program; if not, write to the Free Software
25840+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 25841+ */
25842+
25843+/*
25844+ * sub-routines for VFS
25845+ */
25846+
1308ab2a 25847+#include <linux/ima.h>
dece6358
AM
25848+#include <linux/namei.h>
25849+#include <linux/security.h>
25850+#include <linux/splice.h>
1facf9fc 25851+#include "aufs.h"
25852+
25853+int vfsub_update_h_iattr(struct path *h_path, int *did)
25854+{
25855+ int err;
25856+ struct kstat st;
25857+ struct super_block *h_sb;
25858+
25859+ /* for remote fs, leave work for its getattr or d_revalidate */
25860+ /* for bad i_attr fs, handle them in aufs_getattr() */
25861+ /* still some fs may acquire i_mutex. we need to skip them */
25862+ err = 0;
25863+ if (!did)
25864+ did = &err;
25865+ h_sb = h_path->dentry->d_sb;
25866+ *did = (!au_test_fs_remote(h_sb) && au_test_fs_refresh_iattr(h_sb));
25867+ if (*did)
25868+ err = vfs_getattr(h_path->mnt, h_path->dentry, &st);
25869+
25870+ return err;
25871+}
25872+
25873+/* ---------------------------------------------------------------------- */
25874+
4a4d8108 25875+struct file *vfsub_dentry_open(struct path *path, int flags)
1308ab2a 25876+{
25877+ struct file *file;
25878+
4a4d8108 25879+ path_get(path);
0c5527e5 25880+ file = dentry_open(path->dentry, path->mnt,
2cbb1c4b 25881+ flags /* | __FMODE_NONOTIFY */,
7f207e10 25882+ current_cred());
2cbb1c4b
JR
25883+ if (!IS_ERR_OR_NULL(file)
25884+ && (file->f_mode & (FMODE_READ | FMODE_WRITE)) == FMODE_READ)
25885+ i_readcount_inc(path->dentry->d_inode);
4a4d8108 25886+
1308ab2a 25887+ return file;
25888+}
25889+
1facf9fc 25890+struct file *vfsub_filp_open(const char *path, int oflags, int mode)
25891+{
25892+ struct file *file;
25893+
2cbb1c4b 25894+ lockdep_off();
7f207e10 25895+ file = filp_open(path,
2cbb1c4b 25896+ oflags /* | __FMODE_NONOTIFY */,
7f207e10 25897+ mode);
2cbb1c4b 25898+ lockdep_on();
1facf9fc 25899+ if (IS_ERR(file))
25900+ goto out;
25901+ vfsub_update_h_iattr(&file->f_path, /*did*/NULL); /*ignore*/
25902+
4f0767ce 25903+out:
1facf9fc 25904+ return file;
25905+}
25906+
25907+int vfsub_kern_path(const char *name, unsigned int flags, struct path *path)
25908+{
25909+ int err;
25910+
1facf9fc 25911+ err = kern_path(name, flags, path);
1facf9fc 25912+ if (!err && path->dentry->d_inode)
25913+ vfsub_update_h_iattr(path, /*did*/NULL); /*ignore*/
25914+ return err;
25915+}
25916+
25917+struct dentry *vfsub_lookup_one_len(const char *name, struct dentry *parent,
25918+ int len)
25919+{
25920+ struct path path = {
25921+ .mnt = NULL
25922+ };
25923+
1308ab2a 25924+ /* VFS checks it too, but by WARN_ON_ONCE() */
1facf9fc 25925+ IMustLock(parent->d_inode);
25926+
25927+ path.dentry = lookup_one_len(name, parent, len);
25928+ if (IS_ERR(path.dentry))
25929+ goto out;
25930+ if (path.dentry->d_inode)
25931+ vfsub_update_h_iattr(&path, /*did*/NULL); /*ignore*/
25932+
4f0767ce 25933+out:
4a4d8108 25934+ AuTraceErrPtr(path.dentry);
1facf9fc 25935+ return path.dentry;
25936+}
25937+
25938+struct dentry *vfsub_lookup_hash(struct nameidata *nd)
25939+{
25940+ struct path path = {
25941+ .mnt = nd->path.mnt
25942+ };
25943+
25944+ IMustLock(nd->path.dentry->d_inode);
25945+
25946+ path.dentry = lookup_hash(nd);
4a4d8108
AM
25947+ if (IS_ERR(path.dentry))
25948+ goto out;
25949+ if (path.dentry->d_inode)
1facf9fc 25950+ vfsub_update_h_iattr(&path, /*did*/NULL); /*ignore*/
25951+
4f0767ce 25952+out:
4a4d8108 25953+ AuTraceErrPtr(path.dentry);
1facf9fc 25954+ return path.dentry;
25955+}
25956+
2cbb1c4b
JR
25957+/*
25958+ * this is "VFS:__lookup_one_len()" which was removed and merged into
25959+ * VFS:lookup_one_len() by the commit.
25960+ * 6a96ba5 2011-03-14 kill __lookup_one_len()
25961+ * this function should always be equivalent to the corresponding part in
25962+ * VFS:lookup_one_len().
25963+ */
25964+int vfsub_name_hash(const char *name, struct qstr *this, int len)
25965+{
2cbb1c4b
JR
25966+ unsigned int c;
25967+
25968+ this->name = name;
25969+ this->len = len;
7eafdf33 25970+ this->hash = full_name_hash(name, len);
2cbb1c4b
JR
25971+ if (!len)
25972+ return -EACCES;
25973+
2cbb1c4b
JR
25974+ while (len--) {
25975+ c = *(const unsigned char *)name++;
25976+ if (c == '/' || c == '\0')
25977+ return -EACCES;
2cbb1c4b 25978+ }
2cbb1c4b
JR
25979+ return 0;
25980+}
25981+
1facf9fc 25982+/* ---------------------------------------------------------------------- */
25983+
25984+struct dentry *vfsub_lock_rename(struct dentry *d1, struct au_hinode *hdir1,
25985+ struct dentry *d2, struct au_hinode *hdir2)
25986+{
25987+ struct dentry *d;
25988+
2cbb1c4b 25989+ lockdep_off();
1facf9fc 25990+ d = lock_rename(d1, d2);
2cbb1c4b 25991+ lockdep_on();
4a4d8108 25992+ au_hn_suspend(hdir1);
1facf9fc 25993+ if (hdir1 != hdir2)
4a4d8108 25994+ au_hn_suspend(hdir2);
1facf9fc 25995+
25996+ return d;
25997+}
25998+
25999+void vfsub_unlock_rename(struct dentry *d1, struct au_hinode *hdir1,
26000+ struct dentry *d2, struct au_hinode *hdir2)
26001+{
4a4d8108 26002+ au_hn_resume(hdir1);
1facf9fc 26003+ if (hdir1 != hdir2)
4a4d8108 26004+ au_hn_resume(hdir2);
2cbb1c4b 26005+ lockdep_off();
1facf9fc 26006+ unlock_rename(d1, d2);
2cbb1c4b 26007+ lockdep_on();
1facf9fc 26008+}
26009+
26010+/* ---------------------------------------------------------------------- */
26011+
26012+int vfsub_create(struct inode *dir, struct path *path, int mode)
26013+{
26014+ int err;
26015+ struct dentry *d;
26016+
26017+ IMustLock(dir);
26018+
26019+ d = path->dentry;
26020+ path->dentry = d->d_parent;
b752ccd1 26021+ err = security_path_mknod(path, d, mode, 0);
1facf9fc 26022+ path->dentry = d;
26023+ if (unlikely(err))
26024+ goto out;
26025+
26026+ if (au_test_fs_null_nd(dir->i_sb))
26027+ err = vfs_create(dir, path->dentry, mode, NULL);
26028+ else {
26029+ struct nameidata h_nd;
26030+
26031+ memset(&h_nd, 0, sizeof(h_nd));
26032+ h_nd.flags = LOOKUP_CREATE;
26033+ h_nd.intent.open.flags = O_CREAT
26034+ | vfsub_fmode_to_uint(FMODE_READ);
26035+ h_nd.intent.open.create_mode = mode;
26036+ h_nd.path.dentry = path->dentry->d_parent;
26037+ h_nd.path.mnt = path->mnt;
26038+ path_get(&h_nd.path);
26039+ err = vfs_create(dir, path->dentry, mode, &h_nd);
26040+ path_put(&h_nd.path);
26041+ }
26042+
26043+ if (!err) {
26044+ struct path tmp = *path;
26045+ int did;
26046+
26047+ vfsub_update_h_iattr(&tmp, &did);
26048+ if (did) {
26049+ tmp.dentry = path->dentry->d_parent;
26050+ vfsub_update_h_iattr(&tmp, /*did*/NULL);
26051+ }
26052+ /*ignore*/
26053+ }
26054+
4f0767ce 26055+out:
1facf9fc 26056+ return err;
26057+}
26058+
26059+int vfsub_symlink(struct inode *dir, struct path *path, const char *symname)
26060+{
26061+ int err;
26062+ struct dentry *d;
26063+
26064+ IMustLock(dir);
26065+
26066+ d = path->dentry;
26067+ path->dentry = d->d_parent;
b752ccd1 26068+ err = security_path_symlink(path, d, symname);
1facf9fc 26069+ path->dentry = d;
26070+ if (unlikely(err))
26071+ goto out;
26072+
26073+ err = vfs_symlink(dir, path->dentry, symname);
26074+ if (!err) {
26075+ struct path tmp = *path;
26076+ int did;
26077+
26078+ vfsub_update_h_iattr(&tmp, &did);
26079+ if (did) {
26080+ tmp.dentry = path->dentry->d_parent;
26081+ vfsub_update_h_iattr(&tmp, /*did*/NULL);
26082+ }
26083+ /*ignore*/
26084+ }
26085+
4f0767ce 26086+out:
1facf9fc 26087+ return err;
26088+}
26089+
26090+int vfsub_mknod(struct inode *dir, struct path *path, int mode, dev_t dev)
26091+{
26092+ int err;
26093+ struct dentry *d;
26094+
26095+ IMustLock(dir);
26096+
26097+ d = path->dentry;
26098+ path->dentry = d->d_parent;
027c5e7a 26099+ err = security_path_mknod(path, d, mode, new_encode_dev(dev));
1facf9fc 26100+ path->dentry = d;
26101+ if (unlikely(err))
26102+ goto out;
26103+
26104+ err = vfs_mknod(dir, path->dentry, mode, dev);
26105+ if (!err) {
26106+ struct path tmp = *path;
26107+ int did;
26108+
26109+ vfsub_update_h_iattr(&tmp, &did);
26110+ if (did) {
26111+ tmp.dentry = path->dentry->d_parent;
26112+ vfsub_update_h_iattr(&tmp, /*did*/NULL);
26113+ }
26114+ /*ignore*/
26115+ }
26116+
4f0767ce 26117+out:
1facf9fc 26118+ return err;
26119+}
26120+
26121+static int au_test_nlink(struct inode *inode)
26122+{
26123+ const unsigned int link_max = UINT_MAX >> 1; /* rough margin */
26124+
26125+ if (!au_test_fs_no_limit_nlink(inode->i_sb)
26126+ || inode->i_nlink < link_max)
26127+ return 0;
26128+ return -EMLINK;
26129+}
26130+
26131+int vfsub_link(struct dentry *src_dentry, struct inode *dir, struct path *path)
26132+{
26133+ int err;
26134+ struct dentry *d;
26135+
26136+ IMustLock(dir);
26137+
26138+ err = au_test_nlink(src_dentry->d_inode);
26139+ if (unlikely(err))
26140+ return err;
26141+
26142+ d = path->dentry;
26143+ path->dentry = d->d_parent;
b752ccd1 26144+ err = security_path_link(src_dentry, path, d);
1facf9fc 26145+ path->dentry = d;
26146+ if (unlikely(err))
26147+ goto out;
26148+
2cbb1c4b 26149+ lockdep_off();
1facf9fc 26150+ err = vfs_link(src_dentry, dir, path->dentry);
2cbb1c4b 26151+ lockdep_on();
1facf9fc 26152+ if (!err) {
26153+ struct path tmp = *path;
26154+ int did;
26155+
26156+ /* fuse has different memory inode for the same inumber */
26157+ vfsub_update_h_iattr(&tmp, &did);
26158+ if (did) {
26159+ tmp.dentry = path->dentry->d_parent;
26160+ vfsub_update_h_iattr(&tmp, /*did*/NULL);
26161+ tmp.dentry = src_dentry;
26162+ vfsub_update_h_iattr(&tmp, /*did*/NULL);
26163+ }
26164+ /*ignore*/
26165+ }
26166+
4f0767ce 26167+out:
1facf9fc 26168+ return err;
26169+}
26170+
26171+int vfsub_rename(struct inode *src_dir, struct dentry *src_dentry,
26172+ struct inode *dir, struct path *path)
26173+{
26174+ int err;
26175+ struct path tmp = {
26176+ .mnt = path->mnt
26177+ };
26178+ struct dentry *d;
26179+
26180+ IMustLock(dir);
26181+ IMustLock(src_dir);
26182+
26183+ d = path->dentry;
26184+ path->dentry = d->d_parent;
26185+ tmp.dentry = src_dentry->d_parent;
b752ccd1 26186+ err = security_path_rename(&tmp, src_dentry, path, d);
1facf9fc 26187+ path->dentry = d;
26188+ if (unlikely(err))
26189+ goto out;
26190+
2cbb1c4b 26191+ lockdep_off();
1facf9fc 26192+ err = vfs_rename(src_dir, src_dentry, dir, path->dentry);
2cbb1c4b 26193+ lockdep_on();
1facf9fc 26194+ if (!err) {
26195+ int did;
26196+
26197+ tmp.dentry = d->d_parent;
26198+ vfsub_update_h_iattr(&tmp, &did);
26199+ if (did) {
26200+ tmp.dentry = src_dentry;
26201+ vfsub_update_h_iattr(&tmp, /*did*/NULL);
26202+ tmp.dentry = src_dentry->d_parent;
26203+ vfsub_update_h_iattr(&tmp, /*did*/NULL);
26204+ }
26205+ /*ignore*/
26206+ }
26207+
4f0767ce 26208+out:
1facf9fc 26209+ return err;
26210+}
26211+
26212+int vfsub_mkdir(struct inode *dir, struct path *path, int mode)
26213+{
26214+ int err;
26215+ struct dentry *d;
26216+
26217+ IMustLock(dir);
26218+
26219+ d = path->dentry;
26220+ path->dentry = d->d_parent;
b752ccd1 26221+ err = security_path_mkdir(path, d, mode);
1facf9fc 26222+ path->dentry = d;
26223+ if (unlikely(err))
26224+ goto out;
26225+
26226+ err = vfs_mkdir(dir, path->dentry, mode);
26227+ if (!err) {
26228+ struct path tmp = *path;
26229+ int did;
26230+
26231+ vfsub_update_h_iattr(&tmp, &did);
26232+ if (did) {
26233+ tmp.dentry = path->dentry->d_parent;
26234+ vfsub_update_h_iattr(&tmp, /*did*/NULL);
26235+ }
26236+ /*ignore*/
26237+ }
26238+
4f0767ce 26239+out:
1facf9fc 26240+ return err;
26241+}
26242+
26243+int vfsub_rmdir(struct inode *dir, struct path *path)
26244+{
26245+ int err;
26246+ struct dentry *d;
26247+
26248+ IMustLock(dir);
26249+
26250+ d = path->dentry;
26251+ path->dentry = d->d_parent;
b752ccd1 26252+ err = security_path_rmdir(path, d);
1facf9fc 26253+ path->dentry = d;
26254+ if (unlikely(err))
26255+ goto out;
26256+
2cbb1c4b 26257+ lockdep_off();
1facf9fc 26258+ err = vfs_rmdir(dir, path->dentry);
2cbb1c4b 26259+ lockdep_on();
1facf9fc 26260+ if (!err) {
26261+ struct path tmp = {
26262+ .dentry = path->dentry->d_parent,
26263+ .mnt = path->mnt
26264+ };
26265+
26266+ vfsub_update_h_iattr(&tmp, /*did*/NULL); /*ignore*/
26267+ }
26268+
4f0767ce 26269+out:
1facf9fc 26270+ return err;
26271+}
26272+
26273+/* ---------------------------------------------------------------------- */
26274+
9dbd164d 26275+/* todo: support mmap_sem? */
1facf9fc 26276+ssize_t vfsub_read_u(struct file *file, char __user *ubuf, size_t count,
26277+ loff_t *ppos)
26278+{
26279+ ssize_t err;
26280+
2cbb1c4b 26281+ lockdep_off();
1facf9fc 26282+ err = vfs_read(file, ubuf, count, ppos);
2cbb1c4b 26283+ lockdep_on();
1facf9fc 26284+ if (err >= 0)
26285+ vfsub_update_h_iattr(&file->f_path, /*did*/NULL); /*ignore*/
26286+ return err;
26287+}
26288+
26289+/* todo: kernel_read()? */
26290+ssize_t vfsub_read_k(struct file *file, void *kbuf, size_t count,
26291+ loff_t *ppos)
26292+{
26293+ ssize_t err;
26294+ mm_segment_t oldfs;
b752ccd1
AM
26295+ union {
26296+ void *k;
26297+ char __user *u;
26298+ } buf;
1facf9fc 26299+
b752ccd1 26300+ buf.k = kbuf;
1facf9fc 26301+ oldfs = get_fs();
26302+ set_fs(KERNEL_DS);
b752ccd1 26303+ err = vfsub_read_u(file, buf.u, count, ppos);
1facf9fc 26304+ set_fs(oldfs);
26305+ return err;
26306+}
26307+
26308+ssize_t vfsub_write_u(struct file *file, const char __user *ubuf, size_t count,
26309+ loff_t *ppos)
26310+{
26311+ ssize_t err;
26312+
2cbb1c4b 26313+ lockdep_off();
1facf9fc 26314+ err = vfs_write(file, ubuf, count, ppos);
2cbb1c4b 26315+ lockdep_on();
1facf9fc 26316+ if (err >= 0)
26317+ vfsub_update_h_iattr(&file->f_path, /*did*/NULL); /*ignore*/
26318+ return err;
26319+}
26320+
26321+ssize_t vfsub_write_k(struct file *file, void *kbuf, size_t count, loff_t *ppos)
26322+{
26323+ ssize_t err;
26324+ mm_segment_t oldfs;
b752ccd1
AM
26325+ union {
26326+ void *k;
26327+ const char __user *u;
26328+ } buf;
1facf9fc 26329+
b752ccd1 26330+ buf.k = kbuf;
1facf9fc 26331+ oldfs = get_fs();
26332+ set_fs(KERNEL_DS);
b752ccd1 26333+ err = vfsub_write_u(file, buf.u, count, ppos);
1facf9fc 26334+ set_fs(oldfs);
26335+ return err;
26336+}
26337+
4a4d8108
AM
26338+int vfsub_flush(struct file *file, fl_owner_t id)
26339+{
26340+ int err;
26341+
26342+ err = 0;
26343+ if (file->f_op && file->f_op->flush) {
2cbb1c4b
JR
26344+ if (!au_test_nfs(file->f_dentry->d_sb))
26345+ err = file->f_op->flush(file, id);
26346+ else {
26347+ lockdep_off();
26348+ err = file->f_op->flush(file, id);
26349+ lockdep_on();
26350+ }
4a4d8108
AM
26351+ if (!err)
26352+ vfsub_update_h_iattr(&file->f_path, /*did*/NULL);
26353+ /*ignore*/
26354+ }
26355+ return err;
26356+}
26357+
1facf9fc 26358+int vfsub_readdir(struct file *file, filldir_t filldir, void *arg)
26359+{
26360+ int err;
26361+
2cbb1c4b 26362+ lockdep_off();
1facf9fc 26363+ err = vfs_readdir(file, filldir, arg);
2cbb1c4b 26364+ lockdep_on();
1facf9fc 26365+ if (err >= 0)
26366+ vfsub_update_h_iattr(&file->f_path, /*did*/NULL); /*ignore*/
26367+ return err;
26368+}
26369+
26370+long vfsub_splice_to(struct file *in, loff_t *ppos,
26371+ struct pipe_inode_info *pipe, size_t len,
26372+ unsigned int flags)
26373+{
26374+ long err;
26375+
2cbb1c4b 26376+ lockdep_off();
0fc653ad 26377+ err = do_splice_to(in, ppos, pipe, len, flags);
2cbb1c4b 26378+ lockdep_on();
4a4d8108 26379+ file_accessed(in);
1facf9fc 26380+ if (err >= 0)
26381+ vfsub_update_h_iattr(&in->f_path, /*did*/NULL); /*ignore*/
26382+ return err;
26383+}
26384+
26385+long vfsub_splice_from(struct pipe_inode_info *pipe, struct file *out,
26386+ loff_t *ppos, size_t len, unsigned int flags)
26387+{
26388+ long err;
26389+
2cbb1c4b 26390+ lockdep_off();
0fc653ad 26391+ err = do_splice_from(pipe, out, ppos, len, flags);
2cbb1c4b 26392+ lockdep_on();
1facf9fc 26393+ if (err >= 0)
26394+ vfsub_update_h_iattr(&out->f_path, /*did*/NULL); /*ignore*/
26395+ return err;
26396+}
26397+
53392da6
AM
26398+int vfsub_fsync(struct file *file, struct path *path, int datasync)
26399+{
26400+ int err;
26401+
26402+ /* file can be NULL */
26403+ lockdep_off();
26404+ err = vfs_fsync(file, datasync);
26405+ lockdep_on();
26406+ if (!err) {
26407+ if (!path) {
26408+ AuDebugOn(!file);
26409+ path = &file->f_path;
26410+ }
26411+ vfsub_update_h_iattr(path, /*did*/NULL); /*ignore*/
26412+ }
26413+ return err;
26414+}
26415+
1facf9fc 26416+/* cf. open.c:do_sys_truncate() and do_sys_ftruncate() */
26417+int vfsub_trunc(struct path *h_path, loff_t length, unsigned int attr,
26418+ struct file *h_file)
26419+{
26420+ int err;
26421+ struct inode *h_inode;
26422+
26423+ h_inode = h_path->dentry->d_inode;
26424+ if (!h_file) {
26425+ err = mnt_want_write(h_path->mnt);
26426+ if (err)
26427+ goto out;
26428+ err = inode_permission(h_inode, MAY_WRITE);
26429+ if (err)
26430+ goto out_mnt;
26431+ err = get_write_access(h_inode);
26432+ if (err)
26433+ goto out_mnt;
4a4d8108 26434+ err = break_lease(h_inode, O_WRONLY);
1facf9fc 26435+ if (err)
26436+ goto out_inode;
26437+ }
26438+
26439+ err = locks_verify_truncate(h_inode, h_file, length);
26440+ if (!err)
953406b4 26441+ err = security_path_truncate(h_path);
2cbb1c4b
JR
26442+ if (!err) {
26443+ lockdep_off();
1facf9fc 26444+ err = do_truncate(h_path->dentry, length, attr, h_file);
2cbb1c4b
JR
26445+ lockdep_on();
26446+ }
1facf9fc 26447+
4f0767ce 26448+out_inode:
1facf9fc 26449+ if (!h_file)
26450+ put_write_access(h_inode);
4f0767ce 26451+out_mnt:
1facf9fc 26452+ if (!h_file)
26453+ mnt_drop_write(h_path->mnt);
4f0767ce 26454+out:
1facf9fc 26455+ return err;
26456+}
26457+
26458+/* ---------------------------------------------------------------------- */
26459+
26460+struct au_vfsub_mkdir_args {
26461+ int *errp;
26462+ struct inode *dir;
26463+ struct path *path;
26464+ int mode;
26465+};
26466+
26467+static void au_call_vfsub_mkdir(void *args)
26468+{
26469+ struct au_vfsub_mkdir_args *a = args;
26470+ *a->errp = vfsub_mkdir(a->dir, a->path, a->mode);
26471+}
26472+
26473+int vfsub_sio_mkdir(struct inode *dir, struct path *path, int mode)
26474+{
26475+ int err, do_sio, wkq_err;
26476+
26477+ do_sio = au_test_h_perm_sio(dir, MAY_EXEC | MAY_WRITE);
26478+ if (!do_sio)
26479+ err = vfsub_mkdir(dir, path, mode);
26480+ else {
26481+ struct au_vfsub_mkdir_args args = {
26482+ .errp = &err,
26483+ .dir = dir,
26484+ .path = path,
26485+ .mode = mode
26486+ };
26487+ wkq_err = au_wkq_wait(au_call_vfsub_mkdir, &args);
26488+ if (unlikely(wkq_err))
26489+ err = wkq_err;
26490+ }
26491+
26492+ return err;
26493+}
26494+
26495+struct au_vfsub_rmdir_args {
26496+ int *errp;
26497+ struct inode *dir;
26498+ struct path *path;
26499+};
26500+
26501+static void au_call_vfsub_rmdir(void *args)
26502+{
26503+ struct au_vfsub_rmdir_args *a = args;
26504+ *a->errp = vfsub_rmdir(a->dir, a->path);
26505+}
26506+
26507+int vfsub_sio_rmdir(struct inode *dir, struct path *path)
26508+{
26509+ int err, do_sio, wkq_err;
26510+
26511+ do_sio = au_test_h_perm_sio(dir, MAY_EXEC | MAY_WRITE);
26512+ if (!do_sio)
26513+ err = vfsub_rmdir(dir, path);
26514+ else {
26515+ struct au_vfsub_rmdir_args args = {
26516+ .errp = &err,
26517+ .dir = dir,
26518+ .path = path
26519+ };
26520+ wkq_err = au_wkq_wait(au_call_vfsub_rmdir, &args);
26521+ if (unlikely(wkq_err))
26522+ err = wkq_err;
26523+ }
26524+
26525+ return err;
26526+}
26527+
26528+/* ---------------------------------------------------------------------- */
26529+
26530+struct notify_change_args {
26531+ int *errp;
26532+ struct path *path;
26533+ struct iattr *ia;
26534+};
26535+
26536+static void call_notify_change(void *args)
26537+{
26538+ struct notify_change_args *a = args;
26539+ struct inode *h_inode;
26540+
26541+ h_inode = a->path->dentry->d_inode;
26542+ IMustLock(h_inode);
26543+
26544+ *a->errp = -EPERM;
26545+ if (!IS_IMMUTABLE(h_inode) && !IS_APPEND(h_inode)) {
1facf9fc 26546+ *a->errp = notify_change(a->path->dentry, a->ia);
1facf9fc 26547+ if (!*a->errp)
26548+ vfsub_update_h_iattr(a->path, /*did*/NULL); /*ignore*/
26549+ }
26550+ AuTraceErr(*a->errp);
26551+}
26552+
26553+int vfsub_notify_change(struct path *path, struct iattr *ia)
26554+{
26555+ int err;
26556+ struct notify_change_args args = {
26557+ .errp = &err,
26558+ .path = path,
26559+ .ia = ia
26560+ };
26561+
26562+ call_notify_change(&args);
26563+
26564+ return err;
26565+}
26566+
26567+int vfsub_sio_notify_change(struct path *path, struct iattr *ia)
26568+{
26569+ int err, wkq_err;
26570+ struct notify_change_args args = {
26571+ .errp = &err,
26572+ .path = path,
26573+ .ia = ia
26574+ };
26575+
26576+ wkq_err = au_wkq_wait(call_notify_change, &args);
26577+ if (unlikely(wkq_err))
26578+ err = wkq_err;
26579+
26580+ return err;
26581+}
26582+
26583+/* ---------------------------------------------------------------------- */
26584+
26585+struct unlink_args {
26586+ int *errp;
26587+ struct inode *dir;
26588+ struct path *path;
26589+};
26590+
26591+static void call_unlink(void *args)
26592+{
26593+ struct unlink_args *a = args;
26594+ struct dentry *d = a->path->dentry;
26595+ struct inode *h_inode;
26596+ const int stop_sillyrename = (au_test_nfs(d->d_sb)
027c5e7a 26597+ && d->d_count == 1);
1facf9fc 26598+
26599+ IMustLock(a->dir);
26600+
26601+ a->path->dentry = d->d_parent;
26602+ *a->errp = security_path_unlink(a->path, d);
26603+ a->path->dentry = d;
26604+ if (unlikely(*a->errp))
26605+ return;
26606+
26607+ if (!stop_sillyrename)
26608+ dget(d);
26609+ h_inode = d->d_inode;
26610+ if (h_inode)
027c5e7a 26611+ ihold(h_inode);
1facf9fc 26612+
2cbb1c4b 26613+ lockdep_off();
1facf9fc 26614+ *a->errp = vfs_unlink(a->dir, d);
2cbb1c4b 26615+ lockdep_on();
1facf9fc 26616+ if (!*a->errp) {
26617+ struct path tmp = {
26618+ .dentry = d->d_parent,
26619+ .mnt = a->path->mnt
26620+ };
26621+ vfsub_update_h_iattr(&tmp, /*did*/NULL); /*ignore*/
26622+ }
26623+
26624+ if (!stop_sillyrename)
26625+ dput(d);
26626+ if (h_inode)
26627+ iput(h_inode);
26628+
26629+ AuTraceErr(*a->errp);
26630+}
26631+
26632+/*
26633+ * @dir: must be locked.
26634+ * @dentry: target dentry.
26635+ */
26636+int vfsub_unlink(struct inode *dir, struct path *path, int force)
26637+{
26638+ int err;
26639+ struct unlink_args args = {
26640+ .errp = &err,
26641+ .dir = dir,
26642+ .path = path
26643+ };
26644+
26645+ if (!force)
26646+ call_unlink(&args);
26647+ else {
26648+ int wkq_err;
26649+
26650+ wkq_err = au_wkq_wait(call_unlink, &args);
26651+ if (unlikely(wkq_err))
26652+ err = wkq_err;
26653+ }
26654+
26655+ return err;
26656+}
7f207e10
AM
26657diff -urN /usr/share/empty/fs/aufs/vfsub.h linux/fs/aufs/vfsub.h
26658--- /usr/share/empty/fs/aufs/vfsub.h 1970-01-01 01:00:00.000000000 +0100
7ce627cf 26659+++ linux/fs/aufs/vfsub.h 2012-05-22 09:06:08.870792417 +0200
92d182d2 26660@@ -0,0 +1,232 @@
1facf9fc 26661+/*
f6c5ef8b 26662+ * Copyright (C) 2005-2012 Junjiro R. Okajima
1facf9fc 26663+ *
26664+ * This program, aufs is free software; you can redistribute it and/or modify
26665+ * it under the terms of the GNU General Public License as published by
26666+ * the Free Software Foundation; either version 2 of the License, or
26667+ * (at your option) any later version.
dece6358
AM
26668+ *
26669+ * This program is distributed in the hope that it will be useful,
26670+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
26671+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
26672+ * GNU General Public License for more details.
26673+ *
26674+ * You should have received a copy of the GNU General Public License
26675+ * along with this program; if not, write to the Free Software
26676+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 26677+ */
26678+
26679+/*
26680+ * sub-routines for VFS
26681+ */
26682+
26683+#ifndef __AUFS_VFSUB_H__
26684+#define __AUFS_VFSUB_H__
26685+
26686+#ifdef __KERNEL__
26687+
26688+#include <linux/fs.h>
0c5527e5 26689+#include <linux/lglock.h>
7f207e10 26690+#include "debug.h"
1facf9fc 26691+
7f207e10 26692+/* copied from linux/fs/internal.h */
2cbb1c4b 26693+/* todo: BAD approach!! */
0c5527e5 26694+DECLARE_BRLOCK(vfsmount_lock);
0c5527e5 26695+extern void file_sb_list_del(struct file *f);
2cbb1c4b 26696+extern spinlock_t inode_sb_list_lock;
0c5527e5 26697+
7f207e10
AM
26698+/* copied from linux/fs/file_table.c */
26699+DECLARE_LGLOCK(files_lglock);
0c5527e5
AM
26700+#ifdef CONFIG_SMP
26701+/*
26702+ * These macros iterate all files on all CPUs for a given superblock.
26703+ * files_lglock must be held globally.
26704+ */
26705+#define do_file_list_for_each_entry(__sb, __file) \
26706+{ \
26707+ int i; \
26708+ for_each_possible_cpu(i) { \
26709+ struct list_head *list; \
26710+ list = per_cpu_ptr((__sb)->s_files, i); \
26711+ list_for_each_entry((__file), list, f_u.fu_list)
26712+
26713+#define while_file_list_for_each_entry \
26714+ } \
26715+}
26716+
26717+#else
26718+
26719+#define do_file_list_for_each_entry(__sb, __file) \
26720+{ \
26721+ struct list_head *list; \
26722+ list = &(sb)->s_files; \
26723+ list_for_each_entry((__file), list, f_u.fu_list)
26724+
26725+#define while_file_list_for_each_entry \
26726+}
7f207e10
AM
26727+#endif
26728+
26729+/* ---------------------------------------------------------------------- */
1facf9fc 26730+
26731+/* lock subclass for lower inode */
26732+/* default MAX_LOCKDEP_SUBCLASSES(8) is not enough */
26733+/* reduce? gave up. */
26734+enum {
26735+ AuLsc_I_Begin = I_MUTEX_QUOTA, /* 4 */
26736+ AuLsc_I_PARENT, /* lower inode, parent first */
26737+ AuLsc_I_PARENT2, /* copyup dirs */
dece6358 26738+ AuLsc_I_PARENT3, /* copyup wh */
1facf9fc 26739+ AuLsc_I_CHILD,
26740+ AuLsc_I_CHILD2,
26741+ AuLsc_I_End
26742+};
26743+
26744+/* to debug easier, do not make them inlined functions */
26745+#define MtxMustLock(mtx) AuDebugOn(!mutex_is_locked(mtx))
26746+#define IMustLock(i) MtxMustLock(&(i)->i_mutex)
26747+
26748+/* ---------------------------------------------------------------------- */
26749+
7f207e10
AM
26750+static inline void vfsub_drop_nlink(struct inode *inode)
26751+{
26752+ AuDebugOn(!inode->i_nlink);
26753+ drop_nlink(inode);
26754+}
26755+
027c5e7a
AM
26756+static inline void vfsub_dead_dir(struct inode *inode)
26757+{
26758+ AuDebugOn(!S_ISDIR(inode->i_mode));
26759+ inode->i_flags |= S_DEAD;
26760+ clear_nlink(inode);
26761+}
26762+
7f207e10
AM
26763+/* ---------------------------------------------------------------------- */
26764+
26765+int vfsub_update_h_iattr(struct path *h_path, int *did);
26766+struct file *vfsub_dentry_open(struct path *path, int flags);
26767+struct file *vfsub_filp_open(const char *path, int oflags, int mode);
1facf9fc 26768+int vfsub_kern_path(const char *name, unsigned int flags, struct path *path);
26769+struct dentry *vfsub_lookup_one_len(const char *name, struct dentry *parent,
26770+ int len);
26771+struct dentry *vfsub_lookup_hash(struct nameidata *nd);
2cbb1c4b 26772+int vfsub_name_hash(const char *name, struct qstr *this, int len);
1facf9fc 26773+
26774+/* ---------------------------------------------------------------------- */
26775+
26776+struct au_hinode;
26777+struct dentry *vfsub_lock_rename(struct dentry *d1, struct au_hinode *hdir1,
26778+ struct dentry *d2, struct au_hinode *hdir2);
26779+void vfsub_unlock_rename(struct dentry *d1, struct au_hinode *hdir1,
26780+ struct dentry *d2, struct au_hinode *hdir2);
26781+
26782+int vfsub_create(struct inode *dir, struct path *path, int mode);
26783+int vfsub_symlink(struct inode *dir, struct path *path,
26784+ const char *symname);
26785+int vfsub_mknod(struct inode *dir, struct path *path, int mode, dev_t dev);
26786+int vfsub_link(struct dentry *src_dentry, struct inode *dir,
26787+ struct path *path);
26788+int vfsub_rename(struct inode *src_hdir, struct dentry *src_dentry,
26789+ struct inode *hdir, struct path *path);
26790+int vfsub_mkdir(struct inode *dir, struct path *path, int mode);
26791+int vfsub_rmdir(struct inode *dir, struct path *path);
26792+
26793+/* ---------------------------------------------------------------------- */
26794+
26795+ssize_t vfsub_read_u(struct file *file, char __user *ubuf, size_t count,
26796+ loff_t *ppos);
26797+ssize_t vfsub_read_k(struct file *file, void *kbuf, size_t count,
26798+ loff_t *ppos);
26799+ssize_t vfsub_write_u(struct file *file, const char __user *ubuf, size_t count,
26800+ loff_t *ppos);
26801+ssize_t vfsub_write_k(struct file *file, void *kbuf, size_t count,
26802+ loff_t *ppos);
4a4d8108 26803+int vfsub_flush(struct file *file, fl_owner_t id);
1facf9fc 26804+int vfsub_readdir(struct file *file, filldir_t filldir, void *arg);
26805+
4a4d8108
AM
26806+static inline unsigned int vfsub_file_flags(struct file *file)
26807+{
26808+ unsigned int flags;
26809+
26810+ spin_lock(&file->f_lock);
26811+ flags = file->f_flags;
26812+ spin_unlock(&file->f_lock);
26813+
26814+ return flags;
26815+}
1308ab2a 26816+
1facf9fc 26817+static inline void vfsub_file_accessed(struct file *h_file)
26818+{
26819+ file_accessed(h_file);
26820+ vfsub_update_h_iattr(&h_file->f_path, /*did*/NULL); /*ignore*/
26821+}
26822+
26823+static inline void vfsub_touch_atime(struct vfsmount *h_mnt,
26824+ struct dentry *h_dentry)
26825+{
26826+ struct path h_path = {
26827+ .dentry = h_dentry,
26828+ .mnt = h_mnt
26829+ };
92d182d2 26830+ touch_atime(&h_path);
1facf9fc 26831+ vfsub_update_h_iattr(&h_path, /*did*/NULL); /*ignore*/
26832+}
26833+
4a4d8108
AM
26834+long vfsub_splice_to(struct file *in, loff_t *ppos,
26835+ struct pipe_inode_info *pipe, size_t len,
26836+ unsigned int flags);
26837+long vfsub_splice_from(struct pipe_inode_info *pipe, struct file *out,
26838+ loff_t *ppos, size_t len, unsigned int flags);
26839+int vfsub_trunc(struct path *h_path, loff_t length, unsigned int attr,
26840+ struct file *h_file);
53392da6 26841+int vfsub_fsync(struct file *file, struct path *path, int datasync);
4a4d8108 26842+
1facf9fc 26843+/* ---------------------------------------------------------------------- */
26844+
26845+static inline loff_t vfsub_llseek(struct file *file, loff_t offset, int origin)
26846+{
26847+ loff_t err;
26848+
2cbb1c4b 26849+ lockdep_off();
1facf9fc 26850+ err = vfs_llseek(file, offset, origin);
2cbb1c4b 26851+ lockdep_on();
1facf9fc 26852+ return err;
26853+}
26854+
26855+/* ---------------------------------------------------------------------- */
26856+
26857+/* dirty workaround for strict type of fmode_t */
26858+union vfsub_fmu {
26859+ fmode_t fm;
26860+ unsigned int ui;
26861+};
26862+
26863+static inline unsigned int vfsub_fmode_to_uint(fmode_t fm)
26864+{
26865+ union vfsub_fmu u = {
26866+ .fm = fm
26867+ };
26868+
26869+ BUILD_BUG_ON(sizeof(u.fm) != sizeof(u.ui));
26870+
26871+ return u.ui;
26872+}
26873+
26874+static inline fmode_t vfsub_uint_to_fmode(unsigned int ui)
26875+{
26876+ union vfsub_fmu u = {
26877+ .ui = ui
26878+ };
26879+
26880+ return u.fm;
26881+}
26882+
4a4d8108
AM
26883+/* ---------------------------------------------------------------------- */
26884+
26885+int vfsub_sio_mkdir(struct inode *dir, struct path *path, int mode);
26886+int vfsub_sio_rmdir(struct inode *dir, struct path *path);
26887+int vfsub_sio_notify_change(struct path *path, struct iattr *ia);
26888+int vfsub_notify_change(struct path *path, struct iattr *ia);
26889+int vfsub_unlink(struct inode *dir, struct path *path, int force);
26890+
1facf9fc 26891+#endif /* __KERNEL__ */
26892+#endif /* __AUFS_VFSUB_H__ */
7f207e10
AM
26893diff -urN /usr/share/empty/fs/aufs/wbr_policy.c linux/fs/aufs/wbr_policy.c
26894--- /usr/share/empty/fs/aufs/wbr_policy.c 1970-01-01 01:00:00.000000000 +0100
7ce627cf 26895+++ linux/fs/aufs/wbr_policy.c 2012-05-22 09:06:08.870792417 +0200
027c5e7a 26896@@ -0,0 +1,700 @@
1facf9fc 26897+/*
f6c5ef8b 26898+ * Copyright (C) 2005-2012 Junjiro R. Okajima
1facf9fc 26899+ *
26900+ * This program, aufs is free software; you can redistribute it and/or modify
26901+ * it under the terms of the GNU General Public License as published by
26902+ * the Free Software Foundation; either version 2 of the License, or
26903+ * (at your option) any later version.
dece6358
AM
26904+ *
26905+ * This program is distributed in the hope that it will be useful,
26906+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
26907+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
26908+ * GNU General Public License for more details.
26909+ *
26910+ * You should have received a copy of the GNU General Public License
26911+ * along with this program; if not, write to the Free Software
26912+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 26913+ */
26914+
26915+/*
26916+ * policies for selecting one among multiple writable branches
26917+ */
26918+
26919+#include <linux/statfs.h>
26920+#include "aufs.h"
26921+
26922+/* subset of cpup_attr() */
26923+static noinline_for_stack
26924+int au_cpdown_attr(struct path *h_path, struct dentry *h_src)
26925+{
26926+ int err, sbits;
26927+ struct iattr ia;
26928+ struct inode *h_isrc;
26929+
26930+ h_isrc = h_src->d_inode;
26931+ ia.ia_valid = ATTR_FORCE | ATTR_MODE | ATTR_UID | ATTR_GID;
26932+ ia.ia_mode = h_isrc->i_mode;
26933+ ia.ia_uid = h_isrc->i_uid;
26934+ ia.ia_gid = h_isrc->i_gid;
26935+ sbits = !!(ia.ia_mode & (S_ISUID | S_ISGID));
26936+ au_cpup_attr_flags(h_path->dentry->d_inode, h_isrc);
26937+ err = vfsub_sio_notify_change(h_path, &ia);
26938+
26939+ /* is this nfs only? */
26940+ if (!err && sbits && au_test_nfs(h_path->dentry->d_sb)) {
26941+ ia.ia_valid = ATTR_FORCE | ATTR_MODE;
26942+ ia.ia_mode = h_isrc->i_mode;
26943+ err = vfsub_sio_notify_change(h_path, &ia);
26944+ }
26945+
26946+ return err;
26947+}
26948+
26949+#define AuCpdown_PARENT_OPQ 1
26950+#define AuCpdown_WHED (1 << 1)
26951+#define AuCpdown_MADE_DIR (1 << 2)
26952+#define AuCpdown_DIROPQ (1 << 3)
26953+#define au_ftest_cpdown(flags, name) ((flags) & AuCpdown_##name)
7f207e10
AM
26954+#define au_fset_cpdown(flags, name) \
26955+ do { (flags) |= AuCpdown_##name; } while (0)
26956+#define au_fclr_cpdown(flags, name) \
26957+ do { (flags) &= ~AuCpdown_##name; } while (0)
1facf9fc 26958+
26959+struct au_cpdown_dir_args {
26960+ struct dentry *parent;
26961+ unsigned int flags;
26962+};
26963+
26964+static int au_cpdown_dir_opq(struct dentry *dentry, aufs_bindex_t bdst,
26965+ struct au_cpdown_dir_args *a)
26966+{
26967+ int err;
26968+ struct dentry *opq_dentry;
26969+
26970+ opq_dentry = au_diropq_create(dentry, bdst);
26971+ err = PTR_ERR(opq_dentry);
26972+ if (IS_ERR(opq_dentry))
26973+ goto out;
26974+ dput(opq_dentry);
26975+ au_fset_cpdown(a->flags, DIROPQ);
26976+
4f0767ce 26977+out:
1facf9fc 26978+ return err;
26979+}
26980+
26981+static int au_cpdown_dir_wh(struct dentry *dentry, struct dentry *h_parent,
26982+ struct inode *dir, aufs_bindex_t bdst)
26983+{
26984+ int err;
26985+ struct path h_path;
26986+ struct au_branch *br;
26987+
26988+ br = au_sbr(dentry->d_sb, bdst);
26989+ h_path.dentry = au_wh_lkup(h_parent, &dentry->d_name, br);
26990+ err = PTR_ERR(h_path.dentry);
26991+ if (IS_ERR(h_path.dentry))
26992+ goto out;
26993+
26994+ err = 0;
26995+ if (h_path.dentry->d_inode) {
26996+ h_path.mnt = br->br_mnt;
26997+ err = au_wh_unlink_dentry(au_h_iptr(dir, bdst), &h_path,
26998+ dentry);
26999+ }
27000+ dput(h_path.dentry);
27001+
4f0767ce 27002+out:
1facf9fc 27003+ return err;
27004+}
27005+
27006+static int au_cpdown_dir(struct dentry *dentry, aufs_bindex_t bdst,
27007+ struct dentry *h_parent, void *arg)
27008+{
27009+ int err, rerr;
4a4d8108 27010+ aufs_bindex_t bopq, bstart;
1facf9fc 27011+ struct path h_path;
27012+ struct dentry *parent;
27013+ struct inode *h_dir, *h_inode, *inode, *dir;
27014+ struct au_cpdown_dir_args *args = arg;
27015+
27016+ bstart = au_dbstart(dentry);
27017+ /* dentry is di-locked */
27018+ parent = dget_parent(dentry);
27019+ dir = parent->d_inode;
27020+ h_dir = h_parent->d_inode;
27021+ AuDebugOn(h_dir != au_h_iptr(dir, bdst));
27022+ IMustLock(h_dir);
27023+
27024+ err = au_lkup_neg(dentry, bdst);
27025+ if (unlikely(err < 0))
27026+ goto out;
27027+ h_path.dentry = au_h_dptr(dentry, bdst);
27028+ h_path.mnt = au_sbr_mnt(dentry->d_sb, bdst);
27029+ err = vfsub_sio_mkdir(au_h_iptr(dir, bdst), &h_path,
27030+ S_IRWXU | S_IRUGO | S_IXUGO);
27031+ if (unlikely(err))
27032+ goto out_put;
27033+ au_fset_cpdown(args->flags, MADE_DIR);
27034+
1facf9fc 27035+ bopq = au_dbdiropq(dentry);
27036+ au_fclr_cpdown(args->flags, WHED);
27037+ au_fclr_cpdown(args->flags, DIROPQ);
27038+ if (au_dbwh(dentry) == bdst)
27039+ au_fset_cpdown(args->flags, WHED);
27040+ if (!au_ftest_cpdown(args->flags, PARENT_OPQ) && bopq <= bdst)
27041+ au_fset_cpdown(args->flags, PARENT_OPQ);
1facf9fc 27042+ h_inode = h_path.dentry->d_inode;
27043+ mutex_lock_nested(&h_inode->i_mutex, AuLsc_I_CHILD);
27044+ if (au_ftest_cpdown(args->flags, WHED)) {
27045+ err = au_cpdown_dir_opq(dentry, bdst, args);
27046+ if (unlikely(err)) {
27047+ mutex_unlock(&h_inode->i_mutex);
27048+ goto out_dir;
27049+ }
27050+ }
27051+
27052+ err = au_cpdown_attr(&h_path, au_h_dptr(dentry, bstart));
27053+ mutex_unlock(&h_inode->i_mutex);
27054+ if (unlikely(err))
27055+ goto out_opq;
27056+
27057+ if (au_ftest_cpdown(args->flags, WHED)) {
27058+ err = au_cpdown_dir_wh(dentry, h_parent, dir, bdst);
27059+ if (unlikely(err))
27060+ goto out_opq;
27061+ }
27062+
27063+ inode = dentry->d_inode;
27064+ if (au_ibend(inode) < bdst)
27065+ au_set_ibend(inode, bdst);
27066+ au_set_h_iptr(inode, bdst, au_igrab(h_inode),
27067+ au_hi_flags(inode, /*isdir*/1));
27068+ goto out; /* success */
27069+
27070+ /* revert */
4f0767ce 27071+out_opq:
1facf9fc 27072+ if (au_ftest_cpdown(args->flags, DIROPQ)) {
27073+ mutex_lock_nested(&h_inode->i_mutex, AuLsc_I_CHILD);
27074+ rerr = au_diropq_remove(dentry, bdst);
27075+ mutex_unlock(&h_inode->i_mutex);
27076+ if (unlikely(rerr)) {
27077+ AuIOErr("failed removing diropq for %.*s b%d (%d)\n",
27078+ AuDLNPair(dentry), bdst, rerr);
27079+ err = -EIO;
27080+ goto out;
27081+ }
27082+ }
4f0767ce 27083+out_dir:
1facf9fc 27084+ if (au_ftest_cpdown(args->flags, MADE_DIR)) {
27085+ rerr = vfsub_sio_rmdir(au_h_iptr(dir, bdst), &h_path);
27086+ if (unlikely(rerr)) {
27087+ AuIOErr("failed removing %.*s b%d (%d)\n",
27088+ AuDLNPair(dentry), bdst, rerr);
27089+ err = -EIO;
27090+ }
27091+ }
4f0767ce 27092+out_put:
1facf9fc 27093+ au_set_h_dptr(dentry, bdst, NULL);
27094+ if (au_dbend(dentry) == bdst)
27095+ au_update_dbend(dentry);
4f0767ce 27096+out:
1facf9fc 27097+ dput(parent);
27098+ return err;
27099+}
27100+
27101+int au_cpdown_dirs(struct dentry *dentry, aufs_bindex_t bdst)
27102+{
27103+ int err;
27104+ struct au_cpdown_dir_args args = {
27105+ .parent = dget_parent(dentry),
27106+ .flags = 0
27107+ };
27108+
27109+ err = au_cp_dirs(dentry, bdst, au_cpdown_dir, &args);
27110+ dput(args.parent);
27111+
27112+ return err;
27113+}
27114+
27115+/* ---------------------------------------------------------------------- */
27116+
27117+/* policies for create */
27118+
4a4d8108
AM
27119+static int au_wbr_nonopq(struct dentry *dentry, aufs_bindex_t bindex)
27120+{
27121+ int err, i, j, ndentry;
27122+ aufs_bindex_t bopq;
27123+ struct au_dcsub_pages dpages;
27124+ struct au_dpage *dpage;
27125+ struct dentry **dentries, *parent, *d;
27126+
27127+ err = au_dpages_init(&dpages, GFP_NOFS);
27128+ if (unlikely(err))
27129+ goto out;
27130+ parent = dget_parent(dentry);
027c5e7a 27131+ err = au_dcsub_pages_rev_aufs(&dpages, parent, /*do_include*/0);
4a4d8108
AM
27132+ if (unlikely(err))
27133+ goto out_free;
27134+
27135+ err = bindex;
27136+ for (i = 0; i < dpages.ndpage; i++) {
27137+ dpage = dpages.dpages + i;
27138+ dentries = dpage->dentries;
27139+ ndentry = dpage->ndentry;
27140+ for (j = 0; j < ndentry; j++) {
27141+ d = dentries[j];
27142+ di_read_lock_parent2(d, !AuLock_IR);
27143+ bopq = au_dbdiropq(d);
27144+ di_read_unlock(d, !AuLock_IR);
27145+ if (bopq >= 0 && bopq < err)
27146+ err = bopq;
27147+ }
27148+ }
27149+
27150+out_free:
27151+ dput(parent);
27152+ au_dpages_free(&dpages);
27153+out:
27154+ return err;
27155+}
27156+
1facf9fc 27157+static int au_wbr_bu(struct super_block *sb, aufs_bindex_t bindex)
27158+{
27159+ for (; bindex >= 0; bindex--)
27160+ if (!au_br_rdonly(au_sbr(sb, bindex)))
27161+ return bindex;
27162+ return -EROFS;
27163+}
27164+
27165+/* top down parent */
27166+static int au_wbr_create_tdp(struct dentry *dentry, int isdir __maybe_unused)
27167+{
27168+ int err;
27169+ aufs_bindex_t bstart, bindex;
27170+ struct super_block *sb;
27171+ struct dentry *parent, *h_parent;
27172+
27173+ sb = dentry->d_sb;
27174+ bstart = au_dbstart(dentry);
27175+ err = bstart;
27176+ if (!au_br_rdonly(au_sbr(sb, bstart)))
27177+ goto out;
27178+
27179+ err = -EROFS;
27180+ parent = dget_parent(dentry);
27181+ for (bindex = au_dbstart(parent); bindex < bstart; bindex++) {
27182+ h_parent = au_h_dptr(parent, bindex);
27183+ if (!h_parent || !h_parent->d_inode)
27184+ continue;
27185+
27186+ if (!au_br_rdonly(au_sbr(sb, bindex))) {
27187+ err = bindex;
27188+ break;
27189+ }
27190+ }
27191+ dput(parent);
27192+
27193+ /* bottom up here */
4a4d8108 27194+ if (unlikely(err < 0)) {
1facf9fc 27195+ err = au_wbr_bu(sb, bstart - 1);
4a4d8108
AM
27196+ if (err >= 0)
27197+ err = au_wbr_nonopq(dentry, err);
27198+ }
1facf9fc 27199+
4f0767ce 27200+out:
1facf9fc 27201+ AuDbg("b%d\n", err);
27202+ return err;
27203+}
27204+
27205+/* ---------------------------------------------------------------------- */
27206+
27207+/* an exception for the policy other than tdp */
27208+static int au_wbr_create_exp(struct dentry *dentry)
27209+{
27210+ int err;
27211+ aufs_bindex_t bwh, bdiropq;
27212+ struct dentry *parent;
27213+
27214+ err = -1;
27215+ bwh = au_dbwh(dentry);
27216+ parent = dget_parent(dentry);
27217+ bdiropq = au_dbdiropq(parent);
27218+ if (bwh >= 0) {
27219+ if (bdiropq >= 0)
27220+ err = min(bdiropq, bwh);
27221+ else
27222+ err = bwh;
27223+ AuDbg("%d\n", err);
27224+ } else if (bdiropq >= 0) {
27225+ err = bdiropq;
27226+ AuDbg("%d\n", err);
27227+ }
27228+ dput(parent);
27229+
4a4d8108
AM
27230+ if (err >= 0)
27231+ err = au_wbr_nonopq(dentry, err);
27232+
1facf9fc 27233+ if (err >= 0 && au_br_rdonly(au_sbr(dentry->d_sb, err)))
27234+ err = -1;
27235+
27236+ AuDbg("%d\n", err);
27237+ return err;
27238+}
27239+
27240+/* ---------------------------------------------------------------------- */
27241+
27242+/* round robin */
27243+static int au_wbr_create_init_rr(struct super_block *sb)
27244+{
27245+ int err;
27246+
27247+ err = au_wbr_bu(sb, au_sbend(sb));
27248+ atomic_set(&au_sbi(sb)->si_wbr_rr_next, -err); /* less important */
dece6358 27249+ /* smp_mb(); */
1facf9fc 27250+
27251+ AuDbg("b%d\n", err);
27252+ return err;
27253+}
27254+
27255+static int au_wbr_create_rr(struct dentry *dentry, int isdir)
27256+{
27257+ int err, nbr;
27258+ unsigned int u;
27259+ aufs_bindex_t bindex, bend;
27260+ struct super_block *sb;
27261+ atomic_t *next;
27262+
27263+ err = au_wbr_create_exp(dentry);
27264+ if (err >= 0)
27265+ goto out;
27266+
27267+ sb = dentry->d_sb;
27268+ next = &au_sbi(sb)->si_wbr_rr_next;
27269+ bend = au_sbend(sb);
27270+ nbr = bend + 1;
27271+ for (bindex = 0; bindex <= bend; bindex++) {
27272+ if (!isdir) {
27273+ err = atomic_dec_return(next) + 1;
27274+ /* modulo for 0 is meaningless */
27275+ if (unlikely(!err))
27276+ err = atomic_dec_return(next) + 1;
27277+ } else
27278+ err = atomic_read(next);
27279+ AuDbg("%d\n", err);
27280+ u = err;
27281+ err = u % nbr;
27282+ AuDbg("%d\n", err);
27283+ if (!au_br_rdonly(au_sbr(sb, err)))
27284+ break;
27285+ err = -EROFS;
27286+ }
27287+
4a4d8108
AM
27288+ if (err >= 0)
27289+ err = au_wbr_nonopq(dentry, err);
27290+
4f0767ce 27291+out:
1facf9fc 27292+ AuDbg("%d\n", err);
27293+ return err;
27294+}
27295+
27296+/* ---------------------------------------------------------------------- */
27297+
27298+/* most free space */
27299+static void au_mfs(struct dentry *dentry)
27300+{
27301+ struct super_block *sb;
27302+ struct au_branch *br;
27303+ struct au_wbr_mfs *mfs;
27304+ aufs_bindex_t bindex, bend;
27305+ int err;
27306+ unsigned long long b, bavail;
7f207e10 27307+ struct path h_path;
1facf9fc 27308+ /* reduce the stack usage */
27309+ struct kstatfs *st;
27310+
27311+ st = kmalloc(sizeof(*st), GFP_NOFS);
27312+ if (unlikely(!st)) {
27313+ AuWarn1("failed updating mfs(%d), ignored\n", -ENOMEM);
27314+ return;
27315+ }
27316+
27317+ bavail = 0;
27318+ sb = dentry->d_sb;
27319+ mfs = &au_sbi(sb)->si_wbr_mfs;
dece6358 27320+ MtxMustLock(&mfs->mfs_lock);
1facf9fc 27321+ mfs->mfs_bindex = -EROFS;
27322+ mfs->mfsrr_bytes = 0;
27323+ bend = au_sbend(sb);
27324+ for (bindex = 0; bindex <= bend; bindex++) {
27325+ br = au_sbr(sb, bindex);
27326+ if (au_br_rdonly(br))
27327+ continue;
27328+
27329+ /* sb->s_root for NFS is unreliable */
7f207e10
AM
27330+ h_path.mnt = br->br_mnt;
27331+ h_path.dentry = h_path.mnt->mnt_root;
27332+ err = vfs_statfs(&h_path, st);
1facf9fc 27333+ if (unlikely(err)) {
27334+ AuWarn1("failed statfs, b%d, %d\n", bindex, err);
27335+ continue;
27336+ }
27337+
27338+ /* when the available size is equal, select the lower one */
27339+ BUILD_BUG_ON(sizeof(b) < sizeof(st->f_bavail)
27340+ || sizeof(b) < sizeof(st->f_bsize));
27341+ b = st->f_bavail * st->f_bsize;
27342+ br->br_wbr->wbr_bytes = b;
27343+ if (b >= bavail) {
27344+ bavail = b;
27345+ mfs->mfs_bindex = bindex;
27346+ mfs->mfs_jiffy = jiffies;
27347+ }
27348+ }
27349+
27350+ mfs->mfsrr_bytes = bavail;
27351+ AuDbg("b%d\n", mfs->mfs_bindex);
27352+ kfree(st);
27353+}
27354+
27355+static int au_wbr_create_mfs(struct dentry *dentry, int isdir __maybe_unused)
27356+{
27357+ int err;
27358+ struct super_block *sb;
27359+ struct au_wbr_mfs *mfs;
27360+
27361+ err = au_wbr_create_exp(dentry);
27362+ if (err >= 0)
27363+ goto out;
27364+
27365+ sb = dentry->d_sb;
27366+ mfs = &au_sbi(sb)->si_wbr_mfs;
27367+ mutex_lock(&mfs->mfs_lock);
27368+ if (time_after(jiffies, mfs->mfs_jiffy + mfs->mfs_expire)
27369+ || mfs->mfs_bindex < 0
27370+ || au_br_rdonly(au_sbr(sb, mfs->mfs_bindex)))
27371+ au_mfs(dentry);
27372+ mutex_unlock(&mfs->mfs_lock);
27373+ err = mfs->mfs_bindex;
27374+
4a4d8108
AM
27375+ if (err >= 0)
27376+ err = au_wbr_nonopq(dentry, err);
27377+
4f0767ce 27378+out:
1facf9fc 27379+ AuDbg("b%d\n", err);
27380+ return err;
27381+}
27382+
27383+static int au_wbr_create_init_mfs(struct super_block *sb)
27384+{
27385+ struct au_wbr_mfs *mfs;
27386+
27387+ mfs = &au_sbi(sb)->si_wbr_mfs;
27388+ mutex_init(&mfs->mfs_lock);
27389+ mfs->mfs_jiffy = 0;
27390+ mfs->mfs_bindex = -EROFS;
27391+
27392+ return 0;
27393+}
27394+
27395+static int au_wbr_create_fin_mfs(struct super_block *sb __maybe_unused)
27396+{
27397+ mutex_destroy(&au_sbi(sb)->si_wbr_mfs.mfs_lock);
27398+ return 0;
27399+}
27400+
27401+/* ---------------------------------------------------------------------- */
27402+
27403+/* most free space and then round robin */
27404+static int au_wbr_create_mfsrr(struct dentry *dentry, int isdir)
27405+{
27406+ int err;
27407+ struct au_wbr_mfs *mfs;
27408+
27409+ err = au_wbr_create_mfs(dentry, isdir);
27410+ if (err >= 0) {
27411+ mfs = &au_sbi(dentry->d_sb)->si_wbr_mfs;
dece6358 27412+ mutex_lock(&mfs->mfs_lock);
1facf9fc 27413+ if (mfs->mfsrr_bytes < mfs->mfsrr_watermark)
27414+ err = au_wbr_create_rr(dentry, isdir);
dece6358 27415+ mutex_unlock(&mfs->mfs_lock);
1facf9fc 27416+ }
27417+
27418+ AuDbg("b%d\n", err);
27419+ return err;
27420+}
27421+
27422+static int au_wbr_create_init_mfsrr(struct super_block *sb)
27423+{
27424+ int err;
27425+
27426+ au_wbr_create_init_mfs(sb); /* ignore */
27427+ err = au_wbr_create_init_rr(sb);
27428+
27429+ return err;
27430+}
27431+
27432+/* ---------------------------------------------------------------------- */
27433+
27434+/* top down parent and most free space */
27435+static int au_wbr_create_pmfs(struct dentry *dentry, int isdir)
27436+{
27437+ int err, e2;
27438+ unsigned long long b;
27439+ aufs_bindex_t bindex, bstart, bend;
27440+ struct super_block *sb;
27441+ struct dentry *parent, *h_parent;
27442+ struct au_branch *br;
27443+
27444+ err = au_wbr_create_tdp(dentry, isdir);
27445+ if (unlikely(err < 0))
27446+ goto out;
27447+ parent = dget_parent(dentry);
27448+ bstart = au_dbstart(parent);
27449+ bend = au_dbtaildir(parent);
27450+ if (bstart == bend)
27451+ goto out_parent; /* success */
27452+
27453+ e2 = au_wbr_create_mfs(dentry, isdir);
27454+ if (e2 < 0)
27455+ goto out_parent; /* success */
27456+
27457+ /* when the available size is equal, select upper one */
27458+ sb = dentry->d_sb;
27459+ br = au_sbr(sb, err);
27460+ b = br->br_wbr->wbr_bytes;
27461+ AuDbg("b%d, %llu\n", err, b);
27462+
27463+ for (bindex = bstart; bindex <= bend; bindex++) {
27464+ h_parent = au_h_dptr(parent, bindex);
27465+ if (!h_parent || !h_parent->d_inode)
27466+ continue;
27467+
27468+ br = au_sbr(sb, bindex);
27469+ if (!au_br_rdonly(br) && br->br_wbr->wbr_bytes > b) {
27470+ b = br->br_wbr->wbr_bytes;
27471+ err = bindex;
27472+ AuDbg("b%d, %llu\n", err, b);
27473+ }
27474+ }
27475+
4a4d8108
AM
27476+ if (err >= 0)
27477+ err = au_wbr_nonopq(dentry, err);
27478+
4f0767ce 27479+out_parent:
1facf9fc 27480+ dput(parent);
4f0767ce 27481+out:
1facf9fc 27482+ AuDbg("b%d\n", err);
27483+ return err;
27484+}
27485+
27486+/* ---------------------------------------------------------------------- */
27487+
27488+/* policies for copyup */
27489+
27490+/* top down parent */
27491+static int au_wbr_copyup_tdp(struct dentry *dentry)
27492+{
27493+ return au_wbr_create_tdp(dentry, /*isdir, anything is ok*/0);
27494+}
27495+
27496+/* bottom up parent */
27497+static int au_wbr_copyup_bup(struct dentry *dentry)
27498+{
27499+ int err;
27500+ aufs_bindex_t bindex, bstart;
27501+ struct dentry *parent, *h_parent;
27502+ struct super_block *sb;
27503+
27504+ err = -EROFS;
27505+ sb = dentry->d_sb;
27506+ parent = dget_parent(dentry);
27507+ bstart = au_dbstart(parent);
27508+ for (bindex = au_dbstart(dentry); bindex >= bstart; bindex--) {
27509+ h_parent = au_h_dptr(parent, bindex);
27510+ if (!h_parent || !h_parent->d_inode)
27511+ continue;
27512+
27513+ if (!au_br_rdonly(au_sbr(sb, bindex))) {
27514+ err = bindex;
27515+ break;
27516+ }
27517+ }
27518+ dput(parent);
27519+
27520+ /* bottom up here */
27521+ if (unlikely(err < 0))
27522+ err = au_wbr_bu(sb, bstart - 1);
27523+
27524+ AuDbg("b%d\n", err);
27525+ return err;
27526+}
27527+
27528+/* bottom up */
27529+static int au_wbr_copyup_bu(struct dentry *dentry)
27530+{
27531+ int err;
4a4d8108 27532+ aufs_bindex_t bstart;
1facf9fc 27533+
4a4d8108
AM
27534+ bstart = au_dbstart(dentry);
27535+ err = au_wbr_bu(dentry->d_sb, bstart);
27536+ AuDbg("b%d\n", err);
27537+ if (err > bstart)
27538+ err = au_wbr_nonopq(dentry, err);
1facf9fc 27539+
27540+ AuDbg("b%d\n", err);
27541+ return err;
27542+}
27543+
27544+/* ---------------------------------------------------------------------- */
27545+
27546+struct au_wbr_copyup_operations au_wbr_copyup_ops[] = {
27547+ [AuWbrCopyup_TDP] = {
27548+ .copyup = au_wbr_copyup_tdp
27549+ },
27550+ [AuWbrCopyup_BUP] = {
27551+ .copyup = au_wbr_copyup_bup
27552+ },
27553+ [AuWbrCopyup_BU] = {
27554+ .copyup = au_wbr_copyup_bu
27555+ }
27556+};
27557+
27558+struct au_wbr_create_operations au_wbr_create_ops[] = {
27559+ [AuWbrCreate_TDP] = {
27560+ .create = au_wbr_create_tdp
27561+ },
27562+ [AuWbrCreate_RR] = {
27563+ .create = au_wbr_create_rr,
27564+ .init = au_wbr_create_init_rr
27565+ },
27566+ [AuWbrCreate_MFS] = {
27567+ .create = au_wbr_create_mfs,
27568+ .init = au_wbr_create_init_mfs,
27569+ .fin = au_wbr_create_fin_mfs
27570+ },
27571+ [AuWbrCreate_MFSV] = {
27572+ .create = au_wbr_create_mfs,
27573+ .init = au_wbr_create_init_mfs,
27574+ .fin = au_wbr_create_fin_mfs
27575+ },
27576+ [AuWbrCreate_MFSRR] = {
27577+ .create = au_wbr_create_mfsrr,
27578+ .init = au_wbr_create_init_mfsrr,
27579+ .fin = au_wbr_create_fin_mfs
27580+ },
27581+ [AuWbrCreate_MFSRRV] = {
27582+ .create = au_wbr_create_mfsrr,
27583+ .init = au_wbr_create_init_mfsrr,
27584+ .fin = au_wbr_create_fin_mfs
27585+ },
27586+ [AuWbrCreate_PMFS] = {
27587+ .create = au_wbr_create_pmfs,
27588+ .init = au_wbr_create_init_mfs,
27589+ .fin = au_wbr_create_fin_mfs
27590+ },
27591+ [AuWbrCreate_PMFSV] = {
27592+ .create = au_wbr_create_pmfs,
27593+ .init = au_wbr_create_init_mfs,
27594+ .fin = au_wbr_create_fin_mfs
27595+ }
27596+};
7f207e10
AM
27597diff -urN /usr/share/empty/fs/aufs/whout.c linux/fs/aufs/whout.c
27598--- /usr/share/empty/fs/aufs/whout.c 1970-01-01 01:00:00.000000000 +0100
7ce627cf 27599+++ linux/fs/aufs/whout.c 2012-05-22 09:06:08.870792417 +0200
f6c5ef8b 27600@@ -0,0 +1,1049 @@
1facf9fc 27601+/*
f6c5ef8b 27602+ * Copyright (C) 2005-2012 Junjiro R. Okajima
1facf9fc 27603+ *
27604+ * This program, aufs is free software; you can redistribute it and/or modify
27605+ * it under the terms of the GNU General Public License as published by
27606+ * the Free Software Foundation; either version 2 of the License, or
27607+ * (at your option) any later version.
dece6358
AM
27608+ *
27609+ * This program is distributed in the hope that it will be useful,
27610+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
27611+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
27612+ * GNU General Public License for more details.
27613+ *
27614+ * You should have received a copy of the GNU General Public License
27615+ * along with this program; if not, write to the Free Software
27616+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 27617+ */
27618+
27619+/*
27620+ * whiteout for logical deletion and opaque directory
27621+ */
27622+
1facf9fc 27623+#include "aufs.h"
27624+
27625+#define WH_MASK S_IRUGO
27626+
27627+/*
27628+ * If a directory contains this file, then it is opaque. We start with the
27629+ * .wh. flag so that it is blocked by lookup.
27630+ */
27631+static struct qstr diropq_name = {
27632+ .name = AUFS_WH_DIROPQ,
27633+ .len = sizeof(AUFS_WH_DIROPQ) - 1
27634+};
27635+
27636+/*
27637+ * generate whiteout name, which is NOT terminated by NULL.
27638+ * @name: original d_name.name
27639+ * @len: original d_name.len
27640+ * @wh: whiteout qstr
27641+ * returns zero when succeeds, otherwise error.
27642+ * succeeded value as wh->name should be freed by kfree().
27643+ */
27644+int au_wh_name_alloc(struct qstr *wh, const struct qstr *name)
27645+{
27646+ char *p;
27647+
27648+ if (unlikely(name->len > PATH_MAX - AUFS_WH_PFX_LEN))
27649+ return -ENAMETOOLONG;
27650+
27651+ wh->len = name->len + AUFS_WH_PFX_LEN;
27652+ p = kmalloc(wh->len, GFP_NOFS);
27653+ wh->name = p;
27654+ if (p) {
27655+ memcpy(p, AUFS_WH_PFX, AUFS_WH_PFX_LEN);
27656+ memcpy(p + AUFS_WH_PFX_LEN, name->name, name->len);
27657+ /* smp_mb(); */
27658+ return 0;
27659+ }
27660+ return -ENOMEM;
27661+}
27662+
27663+/* ---------------------------------------------------------------------- */
27664+
27665+/*
27666+ * test if the @wh_name exists under @h_parent.
27667+ * @try_sio specifies the necessary of super-io.
27668+ */
27669+int au_wh_test(struct dentry *h_parent, struct qstr *wh_name,
27670+ struct au_branch *br, int try_sio)
27671+{
27672+ int err;
27673+ struct dentry *wh_dentry;
1facf9fc 27674+
1facf9fc 27675+ if (!try_sio)
27676+ wh_dentry = au_lkup_one(wh_name, h_parent, br, /*nd*/NULL);
27677+ else
27678+ wh_dentry = au_sio_lkup_one(wh_name, h_parent, br);
27679+ err = PTR_ERR(wh_dentry);
27680+ if (IS_ERR(wh_dentry))
27681+ goto out;
27682+
27683+ err = 0;
27684+ if (!wh_dentry->d_inode)
27685+ goto out_wh; /* success */
27686+
27687+ err = 1;
27688+ if (S_ISREG(wh_dentry->d_inode->i_mode))
27689+ goto out_wh; /* success */
27690+
27691+ err = -EIO;
27692+ AuIOErr("%.*s Invalid whiteout entry type 0%o.\n",
27693+ AuDLNPair(wh_dentry), wh_dentry->d_inode->i_mode);
27694+
4f0767ce 27695+out_wh:
1facf9fc 27696+ dput(wh_dentry);
4f0767ce 27697+out:
1facf9fc 27698+ return err;
27699+}
27700+
27701+/*
27702+ * test if the @h_dentry sets opaque or not.
27703+ */
27704+int au_diropq_test(struct dentry *h_dentry, struct au_branch *br)
27705+{
27706+ int err;
27707+ struct inode *h_dir;
27708+
27709+ h_dir = h_dentry->d_inode;
27710+ err = au_wh_test(h_dentry, &diropq_name, br,
27711+ au_test_h_perm_sio(h_dir, MAY_EXEC));
27712+ return err;
27713+}
27714+
27715+/*
27716+ * returns a negative dentry whose name is unique and temporary.
27717+ */
27718+struct dentry *au_whtmp_lkup(struct dentry *h_parent, struct au_branch *br,
27719+ struct qstr *prefix)
27720+{
1facf9fc 27721+ struct dentry *dentry;
27722+ int i;
027c5e7a 27723+ char defname[NAME_MAX - AUFS_MAX_NAMELEN + DNAME_INLINE_LEN + 1],
4a4d8108 27724+ *name, *p;
027c5e7a 27725+ /* strict atomic_t is unnecessary here */
1facf9fc 27726+ static unsigned short cnt;
27727+ struct qstr qs;
27728+
4a4d8108
AM
27729+ BUILD_BUG_ON(sizeof(cnt) * 2 > AUFS_WH_TMP_LEN);
27730+
1facf9fc 27731+ name = defname;
027c5e7a
AM
27732+ qs.len = sizeof(defname) - DNAME_INLINE_LEN + prefix->len - 1;
27733+ if (unlikely(prefix->len > DNAME_INLINE_LEN)) {
1facf9fc 27734+ dentry = ERR_PTR(-ENAMETOOLONG);
4a4d8108 27735+ if (unlikely(qs.len > NAME_MAX))
1facf9fc 27736+ goto out;
27737+ dentry = ERR_PTR(-ENOMEM);
27738+ name = kmalloc(qs.len + 1, GFP_NOFS);
27739+ if (unlikely(!name))
27740+ goto out;
27741+ }
27742+
27743+ /* doubly whiteout-ed */
27744+ memcpy(name, AUFS_WH_PFX AUFS_WH_PFX, AUFS_WH_PFX_LEN * 2);
27745+ p = name + AUFS_WH_PFX_LEN * 2;
27746+ memcpy(p, prefix->name, prefix->len);
27747+ p += prefix->len;
27748+ *p++ = '.';
4a4d8108 27749+ AuDebugOn(name + qs.len + 1 - p <= AUFS_WH_TMP_LEN);
1facf9fc 27750+
27751+ qs.name = name;
27752+ for (i = 0; i < 3; i++) {
b752ccd1 27753+ sprintf(p, "%.*x", AUFS_WH_TMP_LEN, cnt++);
1facf9fc 27754+ dentry = au_sio_lkup_one(&qs, h_parent, br);
27755+ if (IS_ERR(dentry) || !dentry->d_inode)
27756+ goto out_name;
27757+ dput(dentry);
27758+ }
4a4d8108 27759+ /* pr_warning("could not get random name\n"); */
1facf9fc 27760+ dentry = ERR_PTR(-EEXIST);
27761+ AuDbg("%.*s\n", AuLNPair(&qs));
27762+ BUG();
27763+
4f0767ce 27764+out_name:
1facf9fc 27765+ if (name != defname)
27766+ kfree(name);
4f0767ce 27767+out:
4a4d8108 27768+ AuTraceErrPtr(dentry);
1facf9fc 27769+ return dentry;
1facf9fc 27770+}
27771+
27772+/*
27773+ * rename the @h_dentry on @br to the whiteouted temporary name.
27774+ */
27775+int au_whtmp_ren(struct dentry *h_dentry, struct au_branch *br)
27776+{
27777+ int err;
27778+ struct path h_path = {
27779+ .mnt = br->br_mnt
27780+ };
27781+ struct inode *h_dir;
27782+ struct dentry *h_parent;
27783+
27784+ h_parent = h_dentry->d_parent; /* dir inode is locked */
27785+ h_dir = h_parent->d_inode;
27786+ IMustLock(h_dir);
27787+
27788+ h_path.dentry = au_whtmp_lkup(h_parent, br, &h_dentry->d_name);
27789+ err = PTR_ERR(h_path.dentry);
27790+ if (IS_ERR(h_path.dentry))
27791+ goto out;
27792+
27793+ /* under the same dir, no need to lock_rename() */
27794+ err = vfsub_rename(h_dir, h_dentry, h_dir, &h_path);
27795+ AuTraceErr(err);
27796+ dput(h_path.dentry);
27797+
4f0767ce 27798+out:
4a4d8108 27799+ AuTraceErr(err);
1facf9fc 27800+ return err;
27801+}
27802+
27803+/* ---------------------------------------------------------------------- */
27804+/*
27805+ * functions for removing a whiteout
27806+ */
27807+
27808+static int do_unlink_wh(struct inode *h_dir, struct path *h_path)
27809+{
27810+ int force;
27811+
27812+ /*
27813+ * forces superio when the dir has a sticky bit.
27814+ * this may be a violation of unix fs semantics.
27815+ */
27816+ force = (h_dir->i_mode & S_ISVTX)
27817+ && h_path->dentry->d_inode->i_uid != current_fsuid();
27818+ return vfsub_unlink(h_dir, h_path, force);
27819+}
27820+
27821+int au_wh_unlink_dentry(struct inode *h_dir, struct path *h_path,
27822+ struct dentry *dentry)
27823+{
27824+ int err;
27825+
27826+ err = do_unlink_wh(h_dir, h_path);
27827+ if (!err && dentry)
27828+ au_set_dbwh(dentry, -1);
27829+
27830+ return err;
27831+}
27832+
27833+static int unlink_wh_name(struct dentry *h_parent, struct qstr *wh,
27834+ struct au_branch *br)
27835+{
27836+ int err;
27837+ struct path h_path = {
27838+ .mnt = br->br_mnt
27839+ };
27840+
27841+ err = 0;
27842+ h_path.dentry = au_lkup_one(wh, h_parent, br, /*nd*/NULL);
27843+ if (IS_ERR(h_path.dentry))
27844+ err = PTR_ERR(h_path.dentry);
27845+ else {
27846+ if (h_path.dentry->d_inode
27847+ && S_ISREG(h_path.dentry->d_inode->i_mode))
27848+ err = do_unlink_wh(h_parent->d_inode, &h_path);
27849+ dput(h_path.dentry);
27850+ }
27851+
27852+ return err;
27853+}
27854+
27855+/* ---------------------------------------------------------------------- */
27856+/*
27857+ * initialize/clean whiteout for a branch
27858+ */
27859+
27860+static void au_wh_clean(struct inode *h_dir, struct path *whpath,
27861+ const int isdir)
27862+{
27863+ int err;
27864+
27865+ if (!whpath->dentry->d_inode)
27866+ return;
27867+
27868+ err = mnt_want_write(whpath->mnt);
27869+ if (!err) {
27870+ if (isdir)
27871+ err = vfsub_rmdir(h_dir, whpath);
27872+ else
27873+ err = vfsub_unlink(h_dir, whpath, /*force*/0);
27874+ mnt_drop_write(whpath->mnt);
27875+ }
27876+ if (unlikely(err))
4a4d8108
AM
27877+ pr_warning("failed removing %.*s (%d), ignored.\n",
27878+ AuDLNPair(whpath->dentry), err);
1facf9fc 27879+}
27880+
27881+static int test_linkable(struct dentry *h_root)
27882+{
27883+ struct inode *h_dir = h_root->d_inode;
27884+
27885+ if (h_dir->i_op->link)
27886+ return 0;
27887+
4a4d8108
AM
27888+ pr_err("%.*s (%s) doesn't support link(2), use noplink and rw+nolwh\n",
27889+ AuDLNPair(h_root), au_sbtype(h_root->d_sb));
1facf9fc 27890+ return -ENOSYS;
27891+}
27892+
27893+/* todo: should this mkdir be done in /sbin/mount.aufs helper? */
27894+static int au_whdir(struct inode *h_dir, struct path *path)
27895+{
27896+ int err;
27897+
27898+ err = -EEXIST;
27899+ if (!path->dentry->d_inode) {
27900+ int mode = S_IRWXU;
27901+
27902+ if (au_test_nfs(path->dentry->d_sb))
27903+ mode |= S_IXUGO;
27904+ err = mnt_want_write(path->mnt);
27905+ if (!err) {
27906+ err = vfsub_mkdir(h_dir, path, mode);
27907+ mnt_drop_write(path->mnt);
27908+ }
27909+ } else if (S_ISDIR(path->dentry->d_inode->i_mode))
27910+ err = 0;
27911+ else
4a4d8108 27912+ pr_err("unknown %.*s exists\n", AuDLNPair(path->dentry));
1facf9fc 27913+
27914+ return err;
27915+}
27916+
27917+struct au_wh_base {
27918+ const struct qstr *name;
27919+ struct dentry *dentry;
27920+};
27921+
27922+static void au_wh_init_ro(struct inode *h_dir, struct au_wh_base base[],
27923+ struct path *h_path)
27924+{
27925+ h_path->dentry = base[AuBrWh_BASE].dentry;
27926+ au_wh_clean(h_dir, h_path, /*isdir*/0);
27927+ h_path->dentry = base[AuBrWh_PLINK].dentry;
27928+ au_wh_clean(h_dir, h_path, /*isdir*/1);
27929+ h_path->dentry = base[AuBrWh_ORPH].dentry;
27930+ au_wh_clean(h_dir, h_path, /*isdir*/1);
27931+}
27932+
27933+/*
27934+ * returns tri-state,
27935+ * minus: error, caller should print the mesage
27936+ * zero: succuess
27937+ * plus: error, caller should NOT print the mesage
27938+ */
27939+static int au_wh_init_rw_nolink(struct dentry *h_root, struct au_wbr *wbr,
27940+ int do_plink, struct au_wh_base base[],
27941+ struct path *h_path)
27942+{
27943+ int err;
27944+ struct inode *h_dir;
27945+
27946+ h_dir = h_root->d_inode;
27947+ h_path->dentry = base[AuBrWh_BASE].dentry;
27948+ au_wh_clean(h_dir, h_path, /*isdir*/0);
27949+ h_path->dentry = base[AuBrWh_PLINK].dentry;
27950+ if (do_plink) {
27951+ err = test_linkable(h_root);
27952+ if (unlikely(err)) {
27953+ err = 1;
27954+ goto out;
27955+ }
27956+
27957+ err = au_whdir(h_dir, h_path);
27958+ if (unlikely(err))
27959+ goto out;
27960+ wbr->wbr_plink = dget(base[AuBrWh_PLINK].dentry);
27961+ } else
27962+ au_wh_clean(h_dir, h_path, /*isdir*/1);
27963+ h_path->dentry = base[AuBrWh_ORPH].dentry;
27964+ err = au_whdir(h_dir, h_path);
27965+ if (unlikely(err))
27966+ goto out;
27967+ wbr->wbr_orph = dget(base[AuBrWh_ORPH].dentry);
27968+
4f0767ce 27969+out:
1facf9fc 27970+ return err;
27971+}
27972+
27973+/*
27974+ * for the moment, aufs supports the branch filesystem which does not support
27975+ * link(2). testing on FAT which does not support i_op->setattr() fully either,
27976+ * copyup failed. finally, such filesystem will not be used as the writable
27977+ * branch.
27978+ *
27979+ * returns tri-state, see above.
27980+ */
27981+static int au_wh_init_rw(struct dentry *h_root, struct au_wbr *wbr,
27982+ int do_plink, struct au_wh_base base[],
27983+ struct path *h_path)
27984+{
27985+ int err;
27986+ struct inode *h_dir;
27987+
1308ab2a 27988+ WbrWhMustWriteLock(wbr);
27989+
1facf9fc 27990+ err = test_linkable(h_root);
27991+ if (unlikely(err)) {
27992+ err = 1;
27993+ goto out;
27994+ }
27995+
27996+ /*
27997+ * todo: should this create be done in /sbin/mount.aufs helper?
27998+ */
27999+ err = -EEXIST;
28000+ h_dir = h_root->d_inode;
28001+ if (!base[AuBrWh_BASE].dentry->d_inode) {
28002+ err = mnt_want_write(h_path->mnt);
28003+ if (!err) {
28004+ h_path->dentry = base[AuBrWh_BASE].dentry;
28005+ err = vfsub_create(h_dir, h_path, WH_MASK);
28006+ mnt_drop_write(h_path->mnt);
28007+ }
28008+ } else if (S_ISREG(base[AuBrWh_BASE].dentry->d_inode->i_mode))
28009+ err = 0;
28010+ else
4a4d8108
AM
28011+ pr_err("unknown %.*s/%.*s exists\n",
28012+ AuDLNPair(h_root), AuDLNPair(base[AuBrWh_BASE].dentry));
1facf9fc 28013+ if (unlikely(err))
28014+ goto out;
28015+
28016+ h_path->dentry = base[AuBrWh_PLINK].dentry;
28017+ if (do_plink) {
28018+ err = au_whdir(h_dir, h_path);
28019+ if (unlikely(err))
28020+ goto out;
28021+ wbr->wbr_plink = dget(base[AuBrWh_PLINK].dentry);
28022+ } else
28023+ au_wh_clean(h_dir, h_path, /*isdir*/1);
28024+ wbr->wbr_whbase = dget(base[AuBrWh_BASE].dentry);
28025+
28026+ h_path->dentry = base[AuBrWh_ORPH].dentry;
28027+ err = au_whdir(h_dir, h_path);
28028+ if (unlikely(err))
28029+ goto out;
28030+ wbr->wbr_orph = dget(base[AuBrWh_ORPH].dentry);
28031+
4f0767ce 28032+out:
1facf9fc 28033+ return err;
28034+}
28035+
28036+/*
28037+ * initialize the whiteout base file/dir for @br.
28038+ */
28039+int au_wh_init(struct dentry *h_root, struct au_branch *br,
28040+ struct super_block *sb)
28041+{
28042+ int err, i;
28043+ const unsigned char do_plink
28044+ = !!au_opt_test(au_mntflags(sb), PLINK);
28045+ struct path path = {
28046+ .mnt = br->br_mnt
28047+ };
28048+ struct inode *h_dir;
28049+ struct au_wbr *wbr = br->br_wbr;
28050+ static const struct qstr base_name[] = {
28051+ [AuBrWh_BASE] = {
28052+ .name = AUFS_BASE_NAME,
28053+ .len = sizeof(AUFS_BASE_NAME) - 1
28054+ },
28055+ [AuBrWh_PLINK] = {
28056+ .name = AUFS_PLINKDIR_NAME,
28057+ .len = sizeof(AUFS_PLINKDIR_NAME) - 1
28058+ },
28059+ [AuBrWh_ORPH] = {
28060+ .name = AUFS_ORPHDIR_NAME,
28061+ .len = sizeof(AUFS_ORPHDIR_NAME) - 1
28062+ }
28063+ };
28064+ struct au_wh_base base[] = {
28065+ [AuBrWh_BASE] = {
28066+ .name = base_name + AuBrWh_BASE,
28067+ .dentry = NULL
28068+ },
28069+ [AuBrWh_PLINK] = {
28070+ .name = base_name + AuBrWh_PLINK,
28071+ .dentry = NULL
28072+ },
28073+ [AuBrWh_ORPH] = {
28074+ .name = base_name + AuBrWh_ORPH,
28075+ .dentry = NULL
28076+ }
28077+ };
28078+
1308ab2a 28079+ if (wbr)
28080+ WbrWhMustWriteLock(wbr);
1facf9fc 28081+
1facf9fc 28082+ for (i = 0; i < AuBrWh_Last; i++) {
28083+ /* doubly whiteouted */
28084+ struct dentry *d;
28085+
28086+ d = au_wh_lkup(h_root, (void *)base[i].name, br);
28087+ err = PTR_ERR(d);
28088+ if (IS_ERR(d))
28089+ goto out;
28090+
28091+ base[i].dentry = d;
28092+ AuDebugOn(wbr
28093+ && wbr->wbr_wh[i]
28094+ && wbr->wbr_wh[i] != base[i].dentry);
28095+ }
28096+
28097+ if (wbr)
28098+ for (i = 0; i < AuBrWh_Last; i++) {
28099+ dput(wbr->wbr_wh[i]);
28100+ wbr->wbr_wh[i] = NULL;
28101+ }
28102+
28103+ err = 0;
1e00d052 28104+ if (!au_br_writable(br->br_perm)) {
4a4d8108 28105+ h_dir = h_root->d_inode;
1facf9fc 28106+ au_wh_init_ro(h_dir, base, &path);
1e00d052 28107+ } else if (!au_br_wh_linkable(br->br_perm)) {
1facf9fc 28108+ err = au_wh_init_rw_nolink(h_root, wbr, do_plink, base, &path);
28109+ if (err > 0)
28110+ goto out;
28111+ else if (err)
28112+ goto out_err;
1e00d052 28113+ } else {
1facf9fc 28114+ err = au_wh_init_rw(h_root, wbr, do_plink, base, &path);
28115+ if (err > 0)
28116+ goto out;
28117+ else if (err)
28118+ goto out_err;
1facf9fc 28119+ }
28120+ goto out; /* success */
28121+
4f0767ce 28122+out_err:
4a4d8108
AM
28123+ pr_err("an error(%d) on the writable branch %.*s(%s)\n",
28124+ err, AuDLNPair(h_root), au_sbtype(h_root->d_sb));
4f0767ce 28125+out:
1facf9fc 28126+ for (i = 0; i < AuBrWh_Last; i++)
28127+ dput(base[i].dentry);
28128+ return err;
28129+}
28130+
28131+/* ---------------------------------------------------------------------- */
28132+/*
28133+ * whiteouts are all hard-linked usually.
28134+ * when its link count reaches a ceiling, we create a new whiteout base
28135+ * asynchronously.
28136+ */
28137+
28138+struct reinit_br_wh {
28139+ struct super_block *sb;
28140+ struct au_branch *br;
28141+};
28142+
28143+static void reinit_br_wh(void *arg)
28144+{
28145+ int err;
28146+ aufs_bindex_t bindex;
28147+ struct path h_path;
28148+ struct reinit_br_wh *a = arg;
28149+ struct au_wbr *wbr;
28150+ struct inode *dir;
28151+ struct dentry *h_root;
28152+ struct au_hinode *hdir;
28153+
28154+ err = 0;
28155+ wbr = a->br->br_wbr;
28156+ /* big aufs lock */
28157+ si_noflush_write_lock(a->sb);
28158+ if (!au_br_writable(a->br->br_perm))
28159+ goto out;
28160+ bindex = au_br_index(a->sb, a->br->br_id);
28161+ if (unlikely(bindex < 0))
28162+ goto out;
28163+
1308ab2a 28164+ di_read_lock_parent(a->sb->s_root, AuLock_IR);
1facf9fc 28165+ dir = a->sb->s_root->d_inode;
1facf9fc 28166+ hdir = au_hi(dir, bindex);
28167+ h_root = au_h_dptr(a->sb->s_root, bindex);
28168+
4a4d8108 28169+ au_hn_imtx_lock_nested(hdir, AuLsc_I_PARENT);
1facf9fc 28170+ wbr_wh_write_lock(wbr);
28171+ err = au_h_verify(wbr->wbr_whbase, au_opt_udba(a->sb), hdir->hi_inode,
28172+ h_root, a->br);
28173+ if (!err) {
28174+ err = mnt_want_write(a->br->br_mnt);
28175+ if (!err) {
28176+ h_path.dentry = wbr->wbr_whbase;
28177+ h_path.mnt = a->br->br_mnt;
28178+ err = vfsub_unlink(hdir->hi_inode, &h_path, /*force*/0);
28179+ mnt_drop_write(a->br->br_mnt);
28180+ }
28181+ } else {
4a4d8108
AM
28182+ pr_warning("%.*s is moved, ignored\n",
28183+ AuDLNPair(wbr->wbr_whbase));
1facf9fc 28184+ err = 0;
28185+ }
28186+ dput(wbr->wbr_whbase);
28187+ wbr->wbr_whbase = NULL;
28188+ if (!err)
28189+ err = au_wh_init(h_root, a->br, a->sb);
28190+ wbr_wh_write_unlock(wbr);
4a4d8108 28191+ au_hn_imtx_unlock(hdir);
1308ab2a 28192+ di_read_unlock(a->sb->s_root, AuLock_IR);
1facf9fc 28193+
4f0767ce 28194+out:
1facf9fc 28195+ if (wbr)
28196+ atomic_dec(&wbr->wbr_wh_running);
28197+ atomic_dec(&a->br->br_count);
1facf9fc 28198+ si_write_unlock(a->sb);
027c5e7a 28199+ au_nwt_done(&au_sbi(a->sb)->si_nowait);
1facf9fc 28200+ kfree(arg);
28201+ if (unlikely(err))
28202+ AuIOErr("err %d\n", err);
28203+}
28204+
28205+static void kick_reinit_br_wh(struct super_block *sb, struct au_branch *br)
28206+{
28207+ int do_dec, wkq_err;
28208+ struct reinit_br_wh *arg;
28209+
28210+ do_dec = 1;
28211+ if (atomic_inc_return(&br->br_wbr->wbr_wh_running) != 1)
28212+ goto out;
28213+
28214+ /* ignore ENOMEM */
28215+ arg = kmalloc(sizeof(*arg), GFP_NOFS);
28216+ if (arg) {
28217+ /*
28218+ * dec(wh_running), kfree(arg) and dec(br_count)
28219+ * in reinit function
28220+ */
28221+ arg->sb = sb;
28222+ arg->br = br;
28223+ atomic_inc(&br->br_count);
53392da6 28224+ wkq_err = au_wkq_nowait(reinit_br_wh, arg, sb, /*flags*/0);
1facf9fc 28225+ if (unlikely(wkq_err)) {
28226+ atomic_dec(&br->br_wbr->wbr_wh_running);
28227+ atomic_dec(&br->br_count);
28228+ kfree(arg);
28229+ }
28230+ do_dec = 0;
28231+ }
28232+
4f0767ce 28233+out:
1facf9fc 28234+ if (do_dec)
28235+ atomic_dec(&br->br_wbr->wbr_wh_running);
28236+}
28237+
28238+/* ---------------------------------------------------------------------- */
28239+
28240+/*
28241+ * create the whiteout @wh.
28242+ */
28243+static int link_or_create_wh(struct super_block *sb, aufs_bindex_t bindex,
28244+ struct dentry *wh)
28245+{
28246+ int err;
28247+ struct path h_path = {
28248+ .dentry = wh
28249+ };
28250+ struct au_branch *br;
28251+ struct au_wbr *wbr;
28252+ struct dentry *h_parent;
28253+ struct inode *h_dir;
28254+
28255+ h_parent = wh->d_parent; /* dir inode is locked */
28256+ h_dir = h_parent->d_inode;
28257+ IMustLock(h_dir);
28258+
28259+ br = au_sbr(sb, bindex);
28260+ h_path.mnt = br->br_mnt;
28261+ wbr = br->br_wbr;
28262+ wbr_wh_read_lock(wbr);
28263+ if (wbr->wbr_whbase) {
28264+ err = vfsub_link(wbr->wbr_whbase, h_dir, &h_path);
28265+ if (!err || err != -EMLINK)
28266+ goto out;
28267+
28268+ /* link count full. re-initialize br_whbase. */
28269+ kick_reinit_br_wh(sb, br);
28270+ }
28271+
28272+ /* return this error in this context */
28273+ err = vfsub_create(h_dir, &h_path, WH_MASK);
28274+
4f0767ce 28275+out:
1facf9fc 28276+ wbr_wh_read_unlock(wbr);
28277+ return err;
28278+}
28279+
28280+/* ---------------------------------------------------------------------- */
28281+
28282+/*
28283+ * create or remove the diropq.
28284+ */
28285+static struct dentry *do_diropq(struct dentry *dentry, aufs_bindex_t bindex,
28286+ unsigned int flags)
28287+{
28288+ struct dentry *opq_dentry, *h_dentry;
28289+ struct super_block *sb;
28290+ struct au_branch *br;
28291+ int err;
28292+
28293+ sb = dentry->d_sb;
28294+ br = au_sbr(sb, bindex);
28295+ h_dentry = au_h_dptr(dentry, bindex);
28296+ opq_dentry = au_lkup_one(&diropq_name, h_dentry, br, /*nd*/NULL);
28297+ if (IS_ERR(opq_dentry))
28298+ goto out;
28299+
28300+ if (au_ftest_diropq(flags, CREATE)) {
28301+ err = link_or_create_wh(sb, bindex, opq_dentry);
28302+ if (!err) {
28303+ au_set_dbdiropq(dentry, bindex);
28304+ goto out; /* success */
28305+ }
28306+ } else {
28307+ struct path tmp = {
28308+ .dentry = opq_dentry,
28309+ .mnt = br->br_mnt
28310+ };
28311+ err = do_unlink_wh(au_h_iptr(dentry->d_inode, bindex), &tmp);
28312+ if (!err)
28313+ au_set_dbdiropq(dentry, -1);
28314+ }
28315+ dput(opq_dentry);
28316+ opq_dentry = ERR_PTR(err);
28317+
4f0767ce 28318+out:
1facf9fc 28319+ return opq_dentry;
28320+}
28321+
28322+struct do_diropq_args {
28323+ struct dentry **errp;
28324+ struct dentry *dentry;
28325+ aufs_bindex_t bindex;
28326+ unsigned int flags;
28327+};
28328+
28329+static void call_do_diropq(void *args)
28330+{
28331+ struct do_diropq_args *a = args;
28332+ *a->errp = do_diropq(a->dentry, a->bindex, a->flags);
28333+}
28334+
28335+struct dentry *au_diropq_sio(struct dentry *dentry, aufs_bindex_t bindex,
28336+ unsigned int flags)
28337+{
28338+ struct dentry *diropq, *h_dentry;
28339+
28340+ h_dentry = au_h_dptr(dentry, bindex);
28341+ if (!au_test_h_perm_sio(h_dentry->d_inode, MAY_EXEC | MAY_WRITE))
28342+ diropq = do_diropq(dentry, bindex, flags);
28343+ else {
28344+ int wkq_err;
28345+ struct do_diropq_args args = {
28346+ .errp = &diropq,
28347+ .dentry = dentry,
28348+ .bindex = bindex,
28349+ .flags = flags
28350+ };
28351+
28352+ wkq_err = au_wkq_wait(call_do_diropq, &args);
28353+ if (unlikely(wkq_err))
28354+ diropq = ERR_PTR(wkq_err);
28355+ }
28356+
28357+ return diropq;
28358+}
28359+
28360+/* ---------------------------------------------------------------------- */
28361+
28362+/*
28363+ * lookup whiteout dentry.
28364+ * @h_parent: lower parent dentry which must exist and be locked
28365+ * @base_name: name of dentry which will be whiteouted
28366+ * returns dentry for whiteout.
28367+ */
28368+struct dentry *au_wh_lkup(struct dentry *h_parent, struct qstr *base_name,
28369+ struct au_branch *br)
28370+{
28371+ int err;
28372+ struct qstr wh_name;
28373+ struct dentry *wh_dentry;
28374+
28375+ err = au_wh_name_alloc(&wh_name, base_name);
28376+ wh_dentry = ERR_PTR(err);
28377+ if (!err) {
28378+ wh_dentry = au_lkup_one(&wh_name, h_parent, br, /*nd*/NULL);
28379+ kfree(wh_name.name);
28380+ }
28381+ return wh_dentry;
28382+}
28383+
28384+/*
28385+ * link/create a whiteout for @dentry on @bindex.
28386+ */
28387+struct dentry *au_wh_create(struct dentry *dentry, aufs_bindex_t bindex,
28388+ struct dentry *h_parent)
28389+{
28390+ struct dentry *wh_dentry;
28391+ struct super_block *sb;
28392+ int err;
28393+
28394+ sb = dentry->d_sb;
28395+ wh_dentry = au_wh_lkup(h_parent, &dentry->d_name, au_sbr(sb, bindex));
28396+ if (!IS_ERR(wh_dentry) && !wh_dentry->d_inode) {
28397+ err = link_or_create_wh(sb, bindex, wh_dentry);
28398+ if (!err)
28399+ au_set_dbwh(dentry, bindex);
28400+ else {
28401+ dput(wh_dentry);
28402+ wh_dentry = ERR_PTR(err);
28403+ }
28404+ }
28405+
28406+ return wh_dentry;
28407+}
28408+
28409+/* ---------------------------------------------------------------------- */
28410+
28411+/* Delete all whiteouts in this directory on branch bindex. */
28412+static int del_wh_children(struct dentry *h_dentry, struct au_nhash *whlist,
28413+ aufs_bindex_t bindex, struct au_branch *br)
28414+{
28415+ int err;
28416+ unsigned long ul, n;
28417+ struct qstr wh_name;
28418+ char *p;
28419+ struct hlist_head *head;
28420+ struct au_vdir_wh *tpos;
28421+ struct hlist_node *pos;
28422+ struct au_vdir_destr *str;
28423+
28424+ err = -ENOMEM;
4a4d8108 28425+ p = __getname_gfp(GFP_NOFS);
1facf9fc 28426+ wh_name.name = p;
28427+ if (unlikely(!wh_name.name))
28428+ goto out;
28429+
28430+ err = 0;
28431+ memcpy(p, AUFS_WH_PFX, AUFS_WH_PFX_LEN);
28432+ p += AUFS_WH_PFX_LEN;
28433+ n = whlist->nh_num;
28434+ head = whlist->nh_head;
28435+ for (ul = 0; !err && ul < n; ul++, head++) {
28436+ hlist_for_each_entry(tpos, pos, head, wh_hash) {
28437+ if (tpos->wh_bindex != bindex)
28438+ continue;
28439+
28440+ str = &tpos->wh_str;
28441+ if (str->len + AUFS_WH_PFX_LEN <= PATH_MAX) {
28442+ memcpy(p, str->name, str->len);
28443+ wh_name.len = AUFS_WH_PFX_LEN + str->len;
28444+ err = unlink_wh_name(h_dentry, &wh_name, br);
28445+ if (!err)
28446+ continue;
28447+ break;
28448+ }
28449+ AuIOErr("whiteout name too long %.*s\n",
28450+ str->len, str->name);
28451+ err = -EIO;
28452+ break;
28453+ }
28454+ }
28455+ __putname(wh_name.name);
28456+
4f0767ce 28457+out:
1facf9fc 28458+ return err;
28459+}
28460+
28461+struct del_wh_children_args {
28462+ int *errp;
28463+ struct dentry *h_dentry;
1308ab2a 28464+ struct au_nhash *whlist;
1facf9fc 28465+ aufs_bindex_t bindex;
28466+ struct au_branch *br;
28467+};
28468+
28469+static void call_del_wh_children(void *args)
28470+{
28471+ struct del_wh_children_args *a = args;
1308ab2a 28472+ *a->errp = del_wh_children(a->h_dentry, a->whlist, a->bindex, a->br);
1facf9fc 28473+}
28474+
28475+/* ---------------------------------------------------------------------- */
28476+
28477+struct au_whtmp_rmdir *au_whtmp_rmdir_alloc(struct super_block *sb, gfp_t gfp)
28478+{
28479+ struct au_whtmp_rmdir *whtmp;
dece6358 28480+ int err;
1308ab2a 28481+ unsigned int rdhash;
dece6358
AM
28482+
28483+ SiMustAnyLock(sb);
1facf9fc 28484+
28485+ whtmp = kmalloc(sizeof(*whtmp), gfp);
dece6358
AM
28486+ if (unlikely(!whtmp)) {
28487+ whtmp = ERR_PTR(-ENOMEM);
1facf9fc 28488+ goto out;
dece6358 28489+ }
1facf9fc 28490+
28491+ whtmp->dir = NULL;
027c5e7a 28492+ whtmp->br = NULL;
1facf9fc 28493+ whtmp->wh_dentry = NULL;
1308ab2a 28494+ /* no estimation for dir size */
28495+ rdhash = au_sbi(sb)->si_rdhash;
28496+ if (!rdhash)
28497+ rdhash = AUFS_RDHASH_DEF;
28498+ err = au_nhash_alloc(&whtmp->whlist, rdhash, gfp);
28499+ if (unlikely(err)) {
28500+ kfree(whtmp);
28501+ whtmp = ERR_PTR(err);
28502+ }
dece6358 28503+
4f0767ce 28504+out:
dece6358 28505+ return whtmp;
1facf9fc 28506+}
28507+
28508+void au_whtmp_rmdir_free(struct au_whtmp_rmdir *whtmp)
28509+{
027c5e7a
AM
28510+ if (whtmp->br)
28511+ atomic_dec(&whtmp->br->br_count);
1facf9fc 28512+ dput(whtmp->wh_dentry);
28513+ iput(whtmp->dir);
dece6358 28514+ au_nhash_wh_free(&whtmp->whlist);
1facf9fc 28515+ kfree(whtmp);
28516+}
28517+
28518+/*
28519+ * rmdir the whiteouted temporary named dir @h_dentry.
28520+ * @whlist: whiteouted children.
28521+ */
28522+int au_whtmp_rmdir(struct inode *dir, aufs_bindex_t bindex,
28523+ struct dentry *wh_dentry, struct au_nhash *whlist)
28524+{
28525+ int err;
28526+ struct path h_tmp;
28527+ struct inode *wh_inode, *h_dir;
28528+ struct au_branch *br;
28529+
28530+ h_dir = wh_dentry->d_parent->d_inode; /* dir inode is locked */
28531+ IMustLock(h_dir);
28532+
28533+ br = au_sbr(dir->i_sb, bindex);
28534+ wh_inode = wh_dentry->d_inode;
28535+ mutex_lock_nested(&wh_inode->i_mutex, AuLsc_I_CHILD);
28536+
28537+ /*
28538+ * someone else might change some whiteouts while we were sleeping.
28539+ * it means this whlist may have an obsoleted entry.
28540+ */
28541+ if (!au_test_h_perm_sio(wh_inode, MAY_EXEC | MAY_WRITE))
28542+ err = del_wh_children(wh_dentry, whlist, bindex, br);
28543+ else {
28544+ int wkq_err;
28545+ struct del_wh_children_args args = {
28546+ .errp = &err,
28547+ .h_dentry = wh_dentry,
1308ab2a 28548+ .whlist = whlist,
1facf9fc 28549+ .bindex = bindex,
28550+ .br = br
28551+ };
28552+
28553+ wkq_err = au_wkq_wait(call_del_wh_children, &args);
28554+ if (unlikely(wkq_err))
28555+ err = wkq_err;
28556+ }
28557+ mutex_unlock(&wh_inode->i_mutex);
28558+
28559+ if (!err) {
28560+ h_tmp.dentry = wh_dentry;
28561+ h_tmp.mnt = br->br_mnt;
28562+ err = vfsub_rmdir(h_dir, &h_tmp);
1facf9fc 28563+ }
28564+
28565+ if (!err) {
28566+ if (au_ibstart(dir) == bindex) {
7f207e10 28567+ /* todo: dir->i_mutex is necessary */
1facf9fc 28568+ au_cpup_attr_timesizes(dir);
7f207e10 28569+ vfsub_drop_nlink(dir);
1facf9fc 28570+ }
28571+ return 0; /* success */
28572+ }
28573+
4a4d8108
AM
28574+ pr_warning("failed removing %.*s(%d), ignored\n",
28575+ AuDLNPair(wh_dentry), err);
1facf9fc 28576+ return err;
28577+}
28578+
28579+static void call_rmdir_whtmp(void *args)
28580+{
28581+ int err;
e49829fe 28582+ aufs_bindex_t bindex;
1facf9fc 28583+ struct au_whtmp_rmdir *a = args;
28584+ struct super_block *sb;
28585+ struct dentry *h_parent;
28586+ struct inode *h_dir;
1facf9fc 28587+ struct au_hinode *hdir;
28588+
28589+ /* rmdir by nfsd may cause deadlock with this i_mutex */
28590+ /* mutex_lock(&a->dir->i_mutex); */
e49829fe 28591+ err = -EROFS;
1facf9fc 28592+ sb = a->dir->i_sb;
e49829fe
JR
28593+ si_read_lock(sb, !AuLock_FLUSH);
28594+ if (!au_br_writable(a->br->br_perm))
28595+ goto out;
28596+ bindex = au_br_index(sb, a->br->br_id);
28597+ if (unlikely(bindex < 0))
1facf9fc 28598+ goto out;
28599+
28600+ err = -EIO;
1facf9fc 28601+ ii_write_lock_parent(a->dir);
28602+ h_parent = dget_parent(a->wh_dentry);
28603+ h_dir = h_parent->d_inode;
e49829fe 28604+ hdir = au_hi(a->dir, bindex);
4a4d8108 28605+ au_hn_imtx_lock_nested(hdir, AuLsc_I_PARENT);
e49829fe
JR
28606+ err = au_h_verify(a->wh_dentry, au_opt_udba(sb), h_dir, h_parent,
28607+ a->br);
1facf9fc 28608+ if (!err) {
e49829fe 28609+ err = mnt_want_write(a->br->br_mnt);
1facf9fc 28610+ if (!err) {
e49829fe 28611+ err = au_whtmp_rmdir(a->dir, bindex, a->wh_dentry,
dece6358 28612+ &a->whlist);
e49829fe 28613+ mnt_drop_write(a->br->br_mnt);
1facf9fc 28614+ }
28615+ }
4a4d8108 28616+ au_hn_imtx_unlock(hdir);
1facf9fc 28617+ dput(h_parent);
28618+ ii_write_unlock(a->dir);
28619+
4f0767ce 28620+out:
1facf9fc 28621+ /* mutex_unlock(&a->dir->i_mutex); */
1facf9fc 28622+ au_whtmp_rmdir_free(a);
027c5e7a
AM
28623+ si_read_unlock(sb);
28624+ au_nwt_done(&au_sbi(sb)->si_nowait);
1facf9fc 28625+ if (unlikely(err))
28626+ AuIOErr("err %d\n", err);
28627+}
28628+
28629+void au_whtmp_kick_rmdir(struct inode *dir, aufs_bindex_t bindex,
28630+ struct dentry *wh_dentry, struct au_whtmp_rmdir *args)
28631+{
28632+ int wkq_err;
e49829fe 28633+ struct super_block *sb;
1facf9fc 28634+
28635+ IMustLock(dir);
28636+
28637+ /* all post-process will be done in do_rmdir_whtmp(). */
e49829fe 28638+ sb = dir->i_sb;
1facf9fc 28639+ args->dir = au_igrab(dir);
e49829fe
JR
28640+ args->br = au_sbr(sb, bindex);
28641+ atomic_inc(&args->br->br_count);
1facf9fc 28642+ args->wh_dentry = dget(wh_dentry);
53392da6 28643+ wkq_err = au_wkq_nowait(call_rmdir_whtmp, args, sb, /*flags*/0);
1facf9fc 28644+ if (unlikely(wkq_err)) {
4a4d8108
AM
28645+ pr_warning("rmdir error %.*s (%d), ignored\n",
28646+ AuDLNPair(wh_dentry), wkq_err);
1facf9fc 28647+ au_whtmp_rmdir_free(args);
28648+ }
28649+}
7f207e10
AM
28650diff -urN /usr/share/empty/fs/aufs/whout.h linux/fs/aufs/whout.h
28651--- /usr/share/empty/fs/aufs/whout.h 1970-01-01 01:00:00.000000000 +0100
7ce627cf 28652+++ linux/fs/aufs/whout.h 2012-05-22 09:06:08.870792417 +0200
f6c5ef8b 28653@@ -0,0 +1,88 @@
1facf9fc 28654+/*
f6c5ef8b 28655+ * Copyright (C) 2005-2012 Junjiro R. Okajima
1facf9fc 28656+ *
28657+ * This program, aufs is free software; you can redistribute it and/or modify
28658+ * it under the terms of the GNU General Public License as published by
28659+ * the Free Software Foundation; either version 2 of the License, or
28660+ * (at your option) any later version.
dece6358
AM
28661+ *
28662+ * This program is distributed in the hope that it will be useful,
28663+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
28664+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
28665+ * GNU General Public License for more details.
28666+ *
28667+ * You should have received a copy of the GNU General Public License
28668+ * along with this program; if not, write to the Free Software
28669+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 28670+ */
28671+
28672+/*
28673+ * whiteout for logical deletion and opaque directory
28674+ */
28675+
28676+#ifndef __AUFS_WHOUT_H__
28677+#define __AUFS_WHOUT_H__
28678+
28679+#ifdef __KERNEL__
28680+
1facf9fc 28681+#include "dir.h"
28682+
28683+/* whout.c */
28684+int au_wh_name_alloc(struct qstr *wh, const struct qstr *name);
28685+struct au_branch;
28686+int au_wh_test(struct dentry *h_parent, struct qstr *wh_name,
28687+ struct au_branch *br, int try_sio);
28688+int au_diropq_test(struct dentry *h_dentry, struct au_branch *br);
28689+struct dentry *au_whtmp_lkup(struct dentry *h_parent, struct au_branch *br,
28690+ struct qstr *prefix);
28691+int au_whtmp_ren(struct dentry *h_dentry, struct au_branch *br);
28692+int au_wh_unlink_dentry(struct inode *h_dir, struct path *h_path,
28693+ struct dentry *dentry);
28694+int au_wh_init(struct dentry *h_parent, struct au_branch *br,
28695+ struct super_block *sb);
28696+
28697+/* diropq flags */
28698+#define AuDiropq_CREATE 1
28699+#define au_ftest_diropq(flags, name) ((flags) & AuDiropq_##name)
7f207e10
AM
28700+#define au_fset_diropq(flags, name) \
28701+ do { (flags) |= AuDiropq_##name; } while (0)
28702+#define au_fclr_diropq(flags, name) \
28703+ do { (flags) &= ~AuDiropq_##name; } while (0)
1facf9fc 28704+
28705+struct dentry *au_diropq_sio(struct dentry *dentry, aufs_bindex_t bindex,
28706+ unsigned int flags);
28707+struct dentry *au_wh_lkup(struct dentry *h_parent, struct qstr *base_name,
28708+ struct au_branch *br);
28709+struct dentry *au_wh_create(struct dentry *dentry, aufs_bindex_t bindex,
28710+ struct dentry *h_parent);
28711+
28712+/* real rmdir for the whiteout-ed dir */
28713+struct au_whtmp_rmdir {
28714+ struct inode *dir;
e49829fe 28715+ struct au_branch *br;
1facf9fc 28716+ struct dentry *wh_dentry;
dece6358 28717+ struct au_nhash whlist;
1facf9fc 28718+};
28719+
28720+struct au_whtmp_rmdir *au_whtmp_rmdir_alloc(struct super_block *sb, gfp_t gfp);
28721+void au_whtmp_rmdir_free(struct au_whtmp_rmdir *whtmp);
28722+int au_whtmp_rmdir(struct inode *dir, aufs_bindex_t bindex,
28723+ struct dentry *wh_dentry, struct au_nhash *whlist);
28724+void au_whtmp_kick_rmdir(struct inode *dir, aufs_bindex_t bindex,
28725+ struct dentry *wh_dentry, struct au_whtmp_rmdir *args);
28726+
28727+/* ---------------------------------------------------------------------- */
28728+
28729+static inline struct dentry *au_diropq_create(struct dentry *dentry,
28730+ aufs_bindex_t bindex)
28731+{
28732+ return au_diropq_sio(dentry, bindex, AuDiropq_CREATE);
28733+}
28734+
28735+static inline int au_diropq_remove(struct dentry *dentry, aufs_bindex_t bindex)
28736+{
28737+ return PTR_ERR(au_diropq_sio(dentry, bindex, !AuDiropq_CREATE));
28738+}
28739+
28740+#endif /* __KERNEL__ */
28741+#endif /* __AUFS_WHOUT_H__ */
7f207e10
AM
28742diff -urN /usr/share/empty/fs/aufs/wkq.c linux/fs/aufs/wkq.c
28743--- /usr/share/empty/fs/aufs/wkq.c 1970-01-01 01:00:00.000000000 +0100
7ce627cf 28744+++ linux/fs/aufs/wkq.c 2012-05-22 09:06:08.870792417 +0200
9dbd164d 28745@@ -0,0 +1,214 @@
1facf9fc 28746+/*
f6c5ef8b 28747+ * Copyright (C) 2005-2012 Junjiro R. Okajima
1facf9fc 28748+ *
28749+ * This program, aufs is free software; you can redistribute it and/or modify
28750+ * it under the terms of the GNU General Public License as published by
28751+ * the Free Software Foundation; either version 2 of the License, or
28752+ * (at your option) any later version.
dece6358
AM
28753+ *
28754+ * This program is distributed in the hope that it will be useful,
28755+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
28756+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
28757+ * GNU General Public License for more details.
28758+ *
28759+ * You should have received a copy of the GNU General Public License
28760+ * along with this program; if not, write to the Free Software
28761+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 28762+ */
28763+
28764+/*
28765+ * workqueue for asynchronous/super-io operations
28766+ * todo: try new dredential scheme
28767+ */
28768+
dece6358 28769+#include <linux/module.h>
1facf9fc 28770+#include "aufs.h"
28771+
9dbd164d 28772+/* internal workqueue named AUFS_WKQ_NAME */
b752ccd1 28773+
9dbd164d 28774+static struct workqueue_struct *au_wkq;
1facf9fc 28775+
28776+struct au_wkinfo {
28777+ struct work_struct wk;
7f207e10 28778+ struct kobject *kobj;
1facf9fc 28779+
28780+ unsigned int flags; /* see wkq.h */
28781+
28782+ au_wkq_func_t func;
28783+ void *args;
28784+
1facf9fc 28785+ struct completion *comp;
28786+};
28787+
28788+/* ---------------------------------------------------------------------- */
28789+
1facf9fc 28790+static void wkq_func(struct work_struct *wk)
28791+{
28792+ struct au_wkinfo *wkinfo = container_of(wk, struct au_wkinfo, wk);
28793+
7f207e10
AM
28794+ AuDebugOn(current_fsuid());
28795+ AuDebugOn(rlimit(RLIMIT_FSIZE) != RLIM_INFINITY);
28796+
1facf9fc 28797+ wkinfo->func(wkinfo->args);
1facf9fc 28798+ if (au_ftest_wkq(wkinfo->flags, WAIT))
28799+ complete(wkinfo->comp);
28800+ else {
7f207e10 28801+ kobject_put(wkinfo->kobj);
9dbd164d 28802+ module_put(THIS_MODULE); /* todo: ?? */
1facf9fc 28803+ kfree(wkinfo);
28804+ }
28805+}
28806+
28807+/*
28808+ * Since struct completion is large, try allocating it dynamically.
28809+ */
28810+#if defined(CONFIG_4KSTACKS) || defined(AuTest4KSTACKS)
28811+#define AuWkqCompDeclare(name) struct completion *comp = NULL
28812+
28813+static int au_wkq_comp_alloc(struct au_wkinfo *wkinfo, struct completion **comp)
28814+{
28815+ *comp = kmalloc(sizeof(**comp), GFP_NOFS);
28816+ if (*comp) {
28817+ init_completion(*comp);
28818+ wkinfo->comp = *comp;
28819+ return 0;
28820+ }
28821+ return -ENOMEM;
28822+}
28823+
28824+static void au_wkq_comp_free(struct completion *comp)
28825+{
28826+ kfree(comp);
28827+}
28828+
28829+#else
28830+
28831+/* no braces */
28832+#define AuWkqCompDeclare(name) \
28833+ DECLARE_COMPLETION_ONSTACK(_ ## name); \
28834+ struct completion *comp = &_ ## name
28835+
28836+static int au_wkq_comp_alloc(struct au_wkinfo *wkinfo, struct completion **comp)
28837+{
28838+ wkinfo->comp = *comp;
28839+ return 0;
28840+}
28841+
28842+static void au_wkq_comp_free(struct completion *comp __maybe_unused)
28843+{
28844+ /* empty */
28845+}
28846+#endif /* 4KSTACKS */
28847+
53392da6 28848+static void au_wkq_run(struct au_wkinfo *wkinfo)
1facf9fc 28849+{
53392da6
AM
28850+ if (au_ftest_wkq(wkinfo->flags, NEST)) {
28851+ if (au_wkq_test()) {
28852+ AuWarn1("wkq from wkq, due to a dead dir by UDBA?\n");
28853+ AuDebugOn(au_ftest_wkq(wkinfo->flags, WAIT));
28854+ }
28855+ } else
28856+ au_dbg_verify_kthread();
28857+
28858+ if (au_ftest_wkq(wkinfo->flags, WAIT)) {
a1f66529 28859+ INIT_WORK_ONSTACK(&wkinfo->wk, wkq_func);
9dbd164d 28860+ queue_work(au_wkq, &wkinfo->wk);
4a4d8108
AM
28861+ } else {
28862+ INIT_WORK(&wkinfo->wk, wkq_func);
28863+ schedule_work(&wkinfo->wk);
28864+ }
1facf9fc 28865+}
28866+
7f207e10
AM
28867+/*
28868+ * Be careful. It is easy to make deadlock happen.
28869+ * processA: lock, wkq and wait
28870+ * processB: wkq and wait, lock in wkq
28871+ * --> deadlock
28872+ */
b752ccd1 28873+int au_wkq_do_wait(unsigned int flags, au_wkq_func_t func, void *args)
1facf9fc 28874+{
28875+ int err;
28876+ AuWkqCompDeclare(comp);
28877+ struct au_wkinfo wkinfo = {
b752ccd1 28878+ .flags = flags,
1facf9fc 28879+ .func = func,
28880+ .args = args
28881+ };
28882+
28883+ err = au_wkq_comp_alloc(&wkinfo, &comp);
28884+ if (!err) {
53392da6 28885+ au_wkq_run(&wkinfo);
1facf9fc 28886+ /* no timeout, no interrupt */
28887+ wait_for_completion(wkinfo.comp);
28888+ au_wkq_comp_free(comp);
4a4d8108 28889+ destroy_work_on_stack(&wkinfo.wk);
1facf9fc 28890+ }
28891+
28892+ return err;
28893+
28894+}
28895+
027c5e7a
AM
28896+/*
28897+ * Note: dget/dput() in func for aufs dentries are not supported. It will be a
28898+ * problem in a concurrent umounting.
28899+ */
53392da6
AM
28900+int au_wkq_nowait(au_wkq_func_t func, void *args, struct super_block *sb,
28901+ unsigned int flags)
1facf9fc 28902+{
28903+ int err;
28904+ struct au_wkinfo *wkinfo;
28905+
28906+ atomic_inc(&au_sbi(sb)->si_nowait.nw_len);
28907+
28908+ /*
28909+ * wkq_func() must free this wkinfo.
28910+ * it highly depends upon the implementation of workqueue.
28911+ */
28912+ err = 0;
28913+ wkinfo = kmalloc(sizeof(*wkinfo), GFP_NOFS);
28914+ if (wkinfo) {
7f207e10 28915+ wkinfo->kobj = &au_sbi(sb)->si_kobj;
53392da6 28916+ wkinfo->flags = flags & ~AuWkq_WAIT;
1facf9fc 28917+ wkinfo->func = func;
28918+ wkinfo->args = args;
28919+ wkinfo->comp = NULL;
7f207e10 28920+ kobject_get(wkinfo->kobj);
9dbd164d 28921+ __module_get(THIS_MODULE); /* todo: ?? */
1facf9fc 28922+
53392da6 28923+ au_wkq_run(wkinfo);
1facf9fc 28924+ } else {
28925+ err = -ENOMEM;
e49829fe 28926+ au_nwt_done(&au_sbi(sb)->si_nowait);
1facf9fc 28927+ }
28928+
28929+ return err;
28930+}
28931+
28932+/* ---------------------------------------------------------------------- */
28933+
28934+void au_nwt_init(struct au_nowait_tasks *nwt)
28935+{
28936+ atomic_set(&nwt->nw_len, 0);
4a4d8108 28937+ /* smp_mb(); */ /* atomic_set */
1facf9fc 28938+ init_waitqueue_head(&nwt->nw_wq);
28939+}
28940+
28941+void au_wkq_fin(void)
28942+{
9dbd164d 28943+ destroy_workqueue(au_wkq);
1facf9fc 28944+}
28945+
28946+int __init au_wkq_init(void)
28947+{
9dbd164d 28948+ int err;
b752ccd1
AM
28949+
28950+ err = 0;
9dbd164d
AM
28951+ BUILD_BUG_ON(!WQ_RESCUER);
28952+ au_wkq = alloc_workqueue(AUFS_WKQ_NAME, !WQ_RESCUER, WQ_DFL_ACTIVE);
28953+ if (IS_ERR(au_wkq))
28954+ err = PTR_ERR(au_wkq);
28955+ else if (!au_wkq)
28956+ err = -ENOMEM;
b752ccd1
AM
28957+
28958+ return err;
1facf9fc 28959+}
7f207e10
AM
28960diff -urN /usr/share/empty/fs/aufs/wkq.h linux/fs/aufs/wkq.h
28961--- /usr/share/empty/fs/aufs/wkq.h 1970-01-01 01:00:00.000000000 +0100
7ce627cf 28962+++ linux/fs/aufs/wkq.h 2012-05-22 09:06:08.870792417 +0200
f6c5ef8b 28963@@ -0,0 +1,92 @@
1facf9fc 28964+/*
f6c5ef8b 28965+ * Copyright (C) 2005-2012 Junjiro R. Okajima
1facf9fc 28966+ *
28967+ * This program, aufs is free software; you can redistribute it and/or modify
28968+ * it under the terms of the GNU General Public License as published by
28969+ * the Free Software Foundation; either version 2 of the License, or
28970+ * (at your option) any later version.
dece6358
AM
28971+ *
28972+ * This program is distributed in the hope that it will be useful,
28973+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
28974+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
28975+ * GNU General Public License for more details.
28976+ *
28977+ * You should have received a copy of the GNU General Public License
28978+ * along with this program; if not, write to the Free Software
28979+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 28980+ */
28981+
28982+/*
28983+ * workqueue for asynchronous/super-io operations
28984+ * todo: try new credentials management scheme
28985+ */
28986+
28987+#ifndef __AUFS_WKQ_H__
28988+#define __AUFS_WKQ_H__
28989+
28990+#ifdef __KERNEL__
28991+
dece6358
AM
28992+struct super_block;
28993+
1facf9fc 28994+/* ---------------------------------------------------------------------- */
28995+
28996+/*
28997+ * in the next operation, wait for the 'nowait' tasks in system-wide workqueue
28998+ */
28999+struct au_nowait_tasks {
29000+ atomic_t nw_len;
29001+ wait_queue_head_t nw_wq;
29002+};
29003+
29004+/* ---------------------------------------------------------------------- */
29005+
29006+typedef void (*au_wkq_func_t)(void *args);
29007+
29008+/* wkq flags */
29009+#define AuWkq_WAIT 1
9dbd164d 29010+#define AuWkq_NEST (1 << 1)
1facf9fc 29011+#define au_ftest_wkq(flags, name) ((flags) & AuWkq_##name)
7f207e10
AM
29012+#define au_fset_wkq(flags, name) \
29013+ do { (flags) |= AuWkq_##name; } while (0)
29014+#define au_fclr_wkq(flags, name) \
29015+ do { (flags) &= ~AuWkq_##name; } while (0)
1facf9fc 29016+
9dbd164d
AM
29017+#ifndef CONFIG_AUFS_HNOTIFY
29018+#undef AuWkq_NEST
29019+#define AuWkq_NEST 0
29020+#endif
29021+
1facf9fc 29022+/* wkq.c */
b752ccd1 29023+int au_wkq_do_wait(unsigned int flags, au_wkq_func_t func, void *args);
53392da6
AM
29024+int au_wkq_nowait(au_wkq_func_t func, void *args, struct super_block *sb,
29025+ unsigned int flags);
1facf9fc 29026+void au_nwt_init(struct au_nowait_tasks *nwt);
29027+int __init au_wkq_init(void);
29028+void au_wkq_fin(void);
29029+
29030+/* ---------------------------------------------------------------------- */
29031+
53392da6
AM
29032+static inline int au_wkq_test(void)
29033+{
29034+ return current->flags & PF_WQ_WORKER;
29035+}
29036+
b752ccd1 29037+static inline int au_wkq_wait(au_wkq_func_t func, void *args)
1facf9fc 29038+{
b752ccd1 29039+ return au_wkq_do_wait(AuWkq_WAIT, func, args);
1facf9fc 29040+}
29041+
29042+static inline void au_nwt_done(struct au_nowait_tasks *nwt)
29043+{
e49829fe 29044+ if (atomic_dec_and_test(&nwt->nw_len))
1facf9fc 29045+ wake_up_all(&nwt->nw_wq);
29046+}
29047+
29048+static inline int au_nwt_flush(struct au_nowait_tasks *nwt)
29049+{
29050+ wait_event(nwt->nw_wq, !atomic_read(&nwt->nw_len));
29051+ return 0;
29052+}
29053+
29054+#endif /* __KERNEL__ */
29055+#endif /* __AUFS_WKQ_H__ */
7f207e10
AM
29056diff -urN /usr/share/empty/fs/aufs/xino.c linux/fs/aufs/xino.c
29057--- /usr/share/empty/fs/aufs/xino.c 1970-01-01 01:00:00.000000000 +0100
7ce627cf 29058+++ linux/fs/aufs/xino.c 2012-05-22 09:06:08.874125894 +0200
f6c5ef8b 29059@@ -0,0 +1,1264 @@
1facf9fc 29060+/*
f6c5ef8b 29061+ * Copyright (C) 2005-2012 Junjiro R. Okajima
1facf9fc 29062+ *
29063+ * This program, aufs is free software; you can redistribute it and/or modify
29064+ * it under the terms of the GNU General Public License as published by
29065+ * the Free Software Foundation; either version 2 of the License, or
29066+ * (at your option) any later version.
dece6358
AM
29067+ *
29068+ * This program is distributed in the hope that it will be useful,
29069+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
29070+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
29071+ * GNU General Public License for more details.
29072+ *
29073+ * You should have received a copy of the GNU General Public License
29074+ * along with this program; if not, write to the Free Software
29075+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 29076+ */
29077+
29078+/*
29079+ * external inode number translation table and bitmap
29080+ */
29081+
29082+#include <linux/seq_file.h>
1facf9fc 29083+#include "aufs.h"
29084+
9dbd164d 29085+/* todo: unnecessary to support mmap_sem since kernel-space? */
b752ccd1 29086+ssize_t xino_fread(au_readf_t func, struct file *file, void *kbuf, size_t size,
1facf9fc 29087+ loff_t *pos)
29088+{
29089+ ssize_t err;
29090+ mm_segment_t oldfs;
b752ccd1
AM
29091+ union {
29092+ void *k;
29093+ char __user *u;
29094+ } buf;
1facf9fc 29095+
b752ccd1 29096+ buf.k = kbuf;
1facf9fc 29097+ oldfs = get_fs();
29098+ set_fs(KERNEL_DS);
29099+ do {
29100+ /* todo: signal_pending? */
b752ccd1 29101+ err = func(file, buf.u, size, pos);
1facf9fc 29102+ } while (err == -EAGAIN || err == -EINTR);
29103+ set_fs(oldfs);
29104+
29105+#if 0 /* reserved for future use */
29106+ if (err > 0)
29107+ fsnotify_access(file->f_dentry);
29108+#endif
29109+
29110+ return err;
29111+}
29112+
29113+/* ---------------------------------------------------------------------- */
29114+
b752ccd1 29115+static ssize_t do_xino_fwrite(au_writef_t func, struct file *file, void *kbuf,
1facf9fc 29116+ size_t size, loff_t *pos)
29117+{
29118+ ssize_t err;
29119+ mm_segment_t oldfs;
b752ccd1
AM
29120+ union {
29121+ void *k;
29122+ const char __user *u;
29123+ } buf;
1facf9fc 29124+
b752ccd1 29125+ buf.k = kbuf;
1facf9fc 29126+ oldfs = get_fs();
29127+ set_fs(KERNEL_DS);
1facf9fc 29128+ do {
29129+ /* todo: signal_pending? */
b752ccd1 29130+ err = func(file, buf.u, size, pos);
1facf9fc 29131+ } while (err == -EAGAIN || err == -EINTR);
1facf9fc 29132+ set_fs(oldfs);
29133+
29134+#if 0 /* reserved for future use */
29135+ if (err > 0)
29136+ fsnotify_modify(file->f_dentry);
29137+#endif
29138+
29139+ return err;
29140+}
29141+
29142+struct do_xino_fwrite_args {
29143+ ssize_t *errp;
29144+ au_writef_t func;
29145+ struct file *file;
29146+ void *buf;
29147+ size_t size;
29148+ loff_t *pos;
29149+};
29150+
29151+static void call_do_xino_fwrite(void *args)
29152+{
29153+ struct do_xino_fwrite_args *a = args;
29154+ *a->errp = do_xino_fwrite(a->func, a->file, a->buf, a->size, a->pos);
29155+}
29156+
29157+ssize_t xino_fwrite(au_writef_t func, struct file *file, void *buf, size_t size,
29158+ loff_t *pos)
29159+{
29160+ ssize_t err;
29161+
29162+ /* todo: signal block and no wkq? */
b752ccd1
AM
29163+ if (rlimit(RLIMIT_FSIZE) == RLIM_INFINITY) {
29164+ lockdep_off();
29165+ err = do_xino_fwrite(func, file, buf, size, pos);
29166+ lockdep_on();
29167+ } else {
29168+ /*
29169+ * it breaks RLIMIT_FSIZE and normal user's limit,
29170+ * users should care about quota and real 'filesystem full.'
29171+ */
1facf9fc 29172+ int wkq_err;
29173+ struct do_xino_fwrite_args args = {
29174+ .errp = &err,
29175+ .func = func,
29176+ .file = file,
29177+ .buf = buf,
29178+ .size = size,
29179+ .pos = pos
29180+ };
29181+
29182+ wkq_err = au_wkq_wait(call_do_xino_fwrite, &args);
29183+ if (unlikely(wkq_err))
29184+ err = wkq_err;
b752ccd1 29185+ }
1facf9fc 29186+
29187+ return err;
29188+}
29189+
29190+/* ---------------------------------------------------------------------- */
29191+
29192+/*
29193+ * create a new xinofile at the same place/path as @base_file.
29194+ */
29195+struct file *au_xino_create2(struct file *base_file, struct file *copy_src)
29196+{
29197+ struct file *file;
4a4d8108 29198+ struct dentry *base, *parent;
1facf9fc 29199+ struct inode *dir;
29200+ struct qstr *name;
1308ab2a 29201+ struct path path;
4a4d8108 29202+ int err;
1facf9fc 29203+
29204+ base = base_file->f_dentry;
29205+ parent = base->d_parent; /* dir inode is locked */
29206+ dir = parent->d_inode;
29207+ IMustLock(dir);
29208+
29209+ file = ERR_PTR(-EINVAL);
29210+ name = &base->d_name;
4a4d8108
AM
29211+ path.dentry = vfsub_lookup_one_len(name->name, parent, name->len);
29212+ if (IS_ERR(path.dentry)) {
29213+ file = (void *)path.dentry;
29214+ pr_err("%.*s lookup err %ld\n",
29215+ AuLNPair(name), PTR_ERR(path.dentry));
1facf9fc 29216+ goto out;
29217+ }
29218+
29219+ /* no need to mnt_want_write() since we call dentry_open() later */
4a4d8108 29220+ err = vfs_create(dir, path.dentry, S_IRUGO | S_IWUGO, NULL);
1facf9fc 29221+ if (unlikely(err)) {
29222+ file = ERR_PTR(err);
4a4d8108 29223+ pr_err("%.*s create err %d\n", AuLNPair(name), err);
1facf9fc 29224+ goto out_dput;
29225+ }
29226+
1308ab2a 29227+ path.mnt = base_file->f_vfsmnt;
4a4d8108 29228+ file = vfsub_dentry_open(&path,
7f207e10 29229+ O_RDWR | O_CREAT | O_EXCL | O_LARGEFILE
2cbb1c4b 29230+ /* | __FMODE_NONOTIFY */);
1facf9fc 29231+ if (IS_ERR(file)) {
4a4d8108 29232+ pr_err("%.*s open err %ld\n", AuLNPair(name), PTR_ERR(file));
1facf9fc 29233+ goto out_dput;
29234+ }
29235+
29236+ err = vfsub_unlink(dir, &file->f_path, /*force*/0);
29237+ if (unlikely(err)) {
4a4d8108 29238+ pr_err("%.*s unlink err %d\n", AuLNPair(name), err);
1facf9fc 29239+ goto out_fput;
29240+ }
29241+
29242+ if (copy_src) {
29243+ /* no one can touch copy_src xino */
29244+ err = au_copy_file(file, copy_src,
29245+ i_size_read(copy_src->f_dentry->d_inode));
29246+ if (unlikely(err)) {
4a4d8108 29247+ pr_err("%.*s copy err %d\n", AuLNPair(name), err);
1facf9fc 29248+ goto out_fput;
29249+ }
29250+ }
29251+ goto out_dput; /* success */
29252+
4f0767ce 29253+out_fput:
1facf9fc 29254+ fput(file);
29255+ file = ERR_PTR(err);
4f0767ce 29256+out_dput:
4a4d8108 29257+ dput(path.dentry);
4f0767ce 29258+out:
1facf9fc 29259+ return file;
29260+}
29261+
29262+struct au_xino_lock_dir {
29263+ struct au_hinode *hdir;
29264+ struct dentry *parent;
29265+ struct mutex *mtx;
29266+};
29267+
29268+static void au_xino_lock_dir(struct super_block *sb, struct file *xino,
29269+ struct au_xino_lock_dir *ldir)
29270+{
29271+ aufs_bindex_t brid, bindex;
29272+
29273+ ldir->hdir = NULL;
29274+ bindex = -1;
29275+ brid = au_xino_brid(sb);
29276+ if (brid >= 0)
29277+ bindex = au_br_index(sb, brid);
29278+ if (bindex >= 0) {
29279+ ldir->hdir = au_hi(sb->s_root->d_inode, bindex);
4a4d8108 29280+ au_hn_imtx_lock_nested(ldir->hdir, AuLsc_I_PARENT);
1facf9fc 29281+ } else {
29282+ ldir->parent = dget_parent(xino->f_dentry);
29283+ ldir->mtx = &ldir->parent->d_inode->i_mutex;
29284+ mutex_lock_nested(ldir->mtx, AuLsc_I_PARENT);
29285+ }
29286+}
29287+
29288+static void au_xino_unlock_dir(struct au_xino_lock_dir *ldir)
29289+{
29290+ if (ldir->hdir)
4a4d8108 29291+ au_hn_imtx_unlock(ldir->hdir);
1facf9fc 29292+ else {
29293+ mutex_unlock(ldir->mtx);
29294+ dput(ldir->parent);
29295+ }
29296+}
29297+
29298+/* ---------------------------------------------------------------------- */
29299+
29300+/* trucate xino files asynchronously */
29301+
29302+int au_xino_trunc(struct super_block *sb, aufs_bindex_t bindex)
29303+{
29304+ int err;
29305+ aufs_bindex_t bi, bend;
29306+ struct au_branch *br;
29307+ struct file *new_xino, *file;
29308+ struct super_block *h_sb;
29309+ struct au_xino_lock_dir ldir;
29310+
29311+ err = -EINVAL;
29312+ bend = au_sbend(sb);
29313+ if (unlikely(bindex < 0 || bend < bindex))
29314+ goto out;
29315+ br = au_sbr(sb, bindex);
29316+ file = br->br_xino.xi_file;
29317+ if (!file)
29318+ goto out;
29319+
29320+ au_xino_lock_dir(sb, file, &ldir);
29321+ /* mnt_want_write() is unnecessary here */
29322+ new_xino = au_xino_create2(file, file);
29323+ au_xino_unlock_dir(&ldir);
29324+ err = PTR_ERR(new_xino);
29325+ if (IS_ERR(new_xino))
29326+ goto out;
29327+ err = 0;
29328+ fput(file);
29329+ br->br_xino.xi_file = new_xino;
29330+
29331+ h_sb = br->br_mnt->mnt_sb;
29332+ for (bi = 0; bi <= bend; bi++) {
29333+ if (unlikely(bi == bindex))
29334+ continue;
29335+ br = au_sbr(sb, bi);
29336+ if (br->br_mnt->mnt_sb != h_sb)
29337+ continue;
29338+
29339+ fput(br->br_xino.xi_file);
29340+ br->br_xino.xi_file = new_xino;
29341+ get_file(new_xino);
29342+ }
29343+
4f0767ce 29344+out:
1facf9fc 29345+ return err;
29346+}
29347+
29348+struct xino_do_trunc_args {
29349+ struct super_block *sb;
29350+ struct au_branch *br;
29351+};
29352+
29353+static void xino_do_trunc(void *_args)
29354+{
29355+ struct xino_do_trunc_args *args = _args;
29356+ struct super_block *sb;
29357+ struct au_branch *br;
29358+ struct inode *dir;
29359+ int err;
29360+ aufs_bindex_t bindex;
29361+
29362+ err = 0;
29363+ sb = args->sb;
29364+ dir = sb->s_root->d_inode;
29365+ br = args->br;
29366+
29367+ si_noflush_write_lock(sb);
29368+ ii_read_lock_parent(dir);
29369+ bindex = au_br_index(sb, br->br_id);
29370+ err = au_xino_trunc(sb, bindex);
dece6358
AM
29371+ if (!err
29372+ && br->br_xino.xi_file->f_dentry->d_inode->i_blocks
1facf9fc 29373+ >= br->br_xino_upper)
29374+ br->br_xino_upper += AUFS_XINO_TRUNC_STEP;
29375+
1facf9fc 29376+ ii_read_unlock(dir);
29377+ if (unlikely(err))
4a4d8108 29378+ pr_warning("err b%d, (%d)\n", bindex, err);
1facf9fc 29379+ atomic_dec(&br->br_xino_running);
29380+ atomic_dec(&br->br_count);
1facf9fc 29381+ si_write_unlock(sb);
027c5e7a 29382+ au_nwt_done(&au_sbi(sb)->si_nowait);
1facf9fc 29383+ kfree(args);
29384+}
29385+
29386+static void xino_try_trunc(struct super_block *sb, struct au_branch *br)
29387+{
29388+ struct xino_do_trunc_args *args;
29389+ int wkq_err;
29390+
29391+ if (br->br_xino.xi_file->f_dentry->d_inode->i_blocks
29392+ < br->br_xino_upper)
29393+ return;
29394+
29395+ if (atomic_inc_return(&br->br_xino_running) > 1)
29396+ goto out;
29397+
29398+ /* lock and kfree() will be called in trunc_xino() */
29399+ args = kmalloc(sizeof(*args), GFP_NOFS);
29400+ if (unlikely(!args)) {
29401+ AuErr1("no memory\n");
29402+ goto out_args;
29403+ }
29404+
e49829fe 29405+ atomic_inc(&br->br_count);
1facf9fc 29406+ args->sb = sb;
29407+ args->br = br;
53392da6 29408+ wkq_err = au_wkq_nowait(xino_do_trunc, args, sb, /*flags*/0);
1facf9fc 29409+ if (!wkq_err)
29410+ return; /* success */
29411+
4a4d8108 29412+ pr_err("wkq %d\n", wkq_err);
e49829fe 29413+ atomic_dec(&br->br_count);
1facf9fc 29414+
4f0767ce 29415+out_args:
1facf9fc 29416+ kfree(args);
4f0767ce 29417+out:
e49829fe 29418+ atomic_dec(&br->br_xino_running);
1facf9fc 29419+}
29420+
29421+/* ---------------------------------------------------------------------- */
29422+
29423+static int au_xino_do_write(au_writef_t write, struct file *file,
29424+ ino_t h_ino, ino_t ino)
29425+{
29426+ loff_t pos;
29427+ ssize_t sz;
29428+
29429+ pos = h_ino;
29430+ if (unlikely(au_loff_max / sizeof(ino) - 1 < pos)) {
29431+ AuIOErr1("too large hi%lu\n", (unsigned long)h_ino);
29432+ return -EFBIG;
29433+ }
29434+ pos *= sizeof(ino);
29435+ sz = xino_fwrite(write, file, &ino, sizeof(ino), &pos);
29436+ if (sz == sizeof(ino))
29437+ return 0; /* success */
29438+
29439+ AuIOErr("write failed (%zd)\n", sz);
29440+ return -EIO;
29441+}
29442+
29443+/*
29444+ * write @ino to the xinofile for the specified branch{@sb, @bindex}
29445+ * at the position of @h_ino.
29446+ * even if @ino is zero, it is written to the xinofile and means no entry.
29447+ * if the size of the xino file on a specific filesystem exceeds the watermark,
29448+ * try truncating it.
29449+ */
29450+int au_xino_write(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino,
29451+ ino_t ino)
29452+{
29453+ int err;
29454+ unsigned int mnt_flags;
29455+ struct au_branch *br;
29456+
29457+ BUILD_BUG_ON(sizeof(long long) != sizeof(au_loff_max)
29458+ || ((loff_t)-1) > 0);
dece6358 29459+ SiMustAnyLock(sb);
1facf9fc 29460+
29461+ mnt_flags = au_mntflags(sb);
29462+ if (!au_opt_test(mnt_flags, XINO))
29463+ return 0;
29464+
29465+ br = au_sbr(sb, bindex);
29466+ err = au_xino_do_write(au_sbi(sb)->si_xwrite, br->br_xino.xi_file,
29467+ h_ino, ino);
29468+ if (!err) {
29469+ if (au_opt_test(mnt_flags, TRUNC_XINO)
29470+ && au_test_fs_trunc_xino(br->br_mnt->mnt_sb))
29471+ xino_try_trunc(sb, br);
29472+ return 0; /* success */
29473+ }
29474+
29475+ AuIOErr("write failed (%d)\n", err);
29476+ return -EIO;
29477+}
29478+
29479+/* ---------------------------------------------------------------------- */
29480+
29481+/* aufs inode number bitmap */
29482+
29483+static const int page_bits = (int)PAGE_SIZE * BITS_PER_BYTE;
29484+static ino_t xib_calc_ino(unsigned long pindex, int bit)
29485+{
29486+ ino_t ino;
29487+
29488+ AuDebugOn(bit < 0 || page_bits <= bit);
29489+ ino = AUFS_FIRST_INO + pindex * page_bits + bit;
29490+ return ino;
29491+}
29492+
29493+static void xib_calc_bit(ino_t ino, unsigned long *pindex, int *bit)
29494+{
29495+ AuDebugOn(ino < AUFS_FIRST_INO);
29496+ ino -= AUFS_FIRST_INO;
29497+ *pindex = ino / page_bits;
29498+ *bit = ino % page_bits;
29499+}
29500+
29501+static int xib_pindex(struct super_block *sb, unsigned long pindex)
29502+{
29503+ int err;
29504+ loff_t pos;
29505+ ssize_t sz;
29506+ struct au_sbinfo *sbinfo;
29507+ struct file *xib;
29508+ unsigned long *p;
29509+
29510+ sbinfo = au_sbi(sb);
29511+ MtxMustLock(&sbinfo->si_xib_mtx);
29512+ AuDebugOn(pindex > ULONG_MAX / PAGE_SIZE
29513+ || !au_opt_test(sbinfo->si_mntflags, XINO));
29514+
29515+ if (pindex == sbinfo->si_xib_last_pindex)
29516+ return 0;
29517+
29518+ xib = sbinfo->si_xib;
29519+ p = sbinfo->si_xib_buf;
29520+ pos = sbinfo->si_xib_last_pindex;
29521+ pos *= PAGE_SIZE;
29522+ sz = xino_fwrite(sbinfo->si_xwrite, xib, p, PAGE_SIZE, &pos);
29523+ if (unlikely(sz != PAGE_SIZE))
29524+ goto out;
29525+
29526+ pos = pindex;
29527+ pos *= PAGE_SIZE;
29528+ if (i_size_read(xib->f_dentry->d_inode) >= pos + PAGE_SIZE)
29529+ sz = xino_fread(sbinfo->si_xread, xib, p, PAGE_SIZE, &pos);
29530+ else {
29531+ memset(p, 0, PAGE_SIZE);
29532+ sz = xino_fwrite(sbinfo->si_xwrite, xib, p, PAGE_SIZE, &pos);
29533+ }
29534+ if (sz == PAGE_SIZE) {
29535+ sbinfo->si_xib_last_pindex = pindex;
29536+ return 0; /* success */
29537+ }
29538+
4f0767ce 29539+out:
b752ccd1
AM
29540+ AuIOErr1("write failed (%zd)\n", sz);
29541+ err = sz;
29542+ if (sz >= 0)
29543+ err = -EIO;
29544+ return err;
29545+}
29546+
29547+/* ---------------------------------------------------------------------- */
29548+
29549+static void au_xib_clear_bit(struct inode *inode)
29550+{
29551+ int err, bit;
29552+ unsigned long pindex;
29553+ struct super_block *sb;
29554+ struct au_sbinfo *sbinfo;
29555+
29556+ AuDebugOn(inode->i_nlink);
29557+
29558+ sb = inode->i_sb;
29559+ xib_calc_bit(inode->i_ino, &pindex, &bit);
29560+ AuDebugOn(page_bits <= bit);
29561+ sbinfo = au_sbi(sb);
29562+ mutex_lock(&sbinfo->si_xib_mtx);
29563+ err = xib_pindex(sb, pindex);
29564+ if (!err) {
29565+ clear_bit(bit, sbinfo->si_xib_buf);
29566+ sbinfo->si_xib_next_bit = bit;
29567+ }
29568+ mutex_unlock(&sbinfo->si_xib_mtx);
29569+}
29570+
29571+/* for s_op->delete_inode() */
29572+void au_xino_delete_inode(struct inode *inode, const int unlinked)
29573+{
29574+ int err;
29575+ unsigned int mnt_flags;
29576+ aufs_bindex_t bindex, bend, bi;
29577+ unsigned char try_trunc;
29578+ struct au_iinfo *iinfo;
29579+ struct super_block *sb;
29580+ struct au_hinode *hi;
29581+ struct inode *h_inode;
29582+ struct au_branch *br;
29583+ au_writef_t xwrite;
29584+
29585+ sb = inode->i_sb;
29586+ mnt_flags = au_mntflags(sb);
29587+ if (!au_opt_test(mnt_flags, XINO)
29588+ || inode->i_ino == AUFS_ROOT_INO)
29589+ return;
29590+
29591+ if (unlinked) {
29592+ au_xigen_inc(inode);
29593+ au_xib_clear_bit(inode);
29594+ }
29595+
29596+ iinfo = au_ii(inode);
29597+ if (!iinfo)
29598+ return;
1facf9fc 29599+
b752ccd1
AM
29600+ bindex = iinfo->ii_bstart;
29601+ if (bindex < 0)
29602+ return;
1facf9fc 29603+
b752ccd1
AM
29604+ xwrite = au_sbi(sb)->si_xwrite;
29605+ try_trunc = !!au_opt_test(mnt_flags, TRUNC_XINO);
29606+ hi = iinfo->ii_hinode + bindex;
29607+ bend = iinfo->ii_bend;
29608+ for (; bindex <= bend; bindex++, hi++) {
29609+ h_inode = hi->hi_inode;
29610+ if (!h_inode
29611+ || (!unlinked && h_inode->i_nlink))
29612+ continue;
1facf9fc 29613+
b752ccd1
AM
29614+ /* inode may not be revalidated */
29615+ bi = au_br_index(sb, hi->hi_id);
29616+ if (bi < 0)
29617+ continue;
1facf9fc 29618+
b752ccd1
AM
29619+ br = au_sbr(sb, bi);
29620+ err = au_xino_do_write(xwrite, br->br_xino.xi_file,
29621+ h_inode->i_ino, /*ino*/0);
29622+ if (!err && try_trunc
29623+ && au_test_fs_trunc_xino(br->br_mnt->mnt_sb))
29624+ xino_try_trunc(sb, br);
1facf9fc 29625+ }
1facf9fc 29626+}
29627+
29628+/* get an unused inode number from bitmap */
29629+ino_t au_xino_new_ino(struct super_block *sb)
29630+{
29631+ ino_t ino;
29632+ unsigned long *p, pindex, ul, pend;
29633+ struct au_sbinfo *sbinfo;
29634+ struct file *file;
29635+ int free_bit, err;
29636+
29637+ if (!au_opt_test(au_mntflags(sb), XINO))
29638+ return iunique(sb, AUFS_FIRST_INO);
29639+
29640+ sbinfo = au_sbi(sb);
29641+ mutex_lock(&sbinfo->si_xib_mtx);
29642+ p = sbinfo->si_xib_buf;
29643+ free_bit = sbinfo->si_xib_next_bit;
29644+ if (free_bit < page_bits && !test_bit(free_bit, p))
29645+ goto out; /* success */
29646+ free_bit = find_first_zero_bit(p, page_bits);
29647+ if (free_bit < page_bits)
29648+ goto out; /* success */
29649+
29650+ pindex = sbinfo->si_xib_last_pindex;
29651+ for (ul = pindex - 1; ul < ULONG_MAX; ul--) {
29652+ err = xib_pindex(sb, ul);
29653+ if (unlikely(err))
29654+ goto out_err;
29655+ free_bit = find_first_zero_bit(p, page_bits);
29656+ if (free_bit < page_bits)
29657+ goto out; /* success */
29658+ }
29659+
29660+ file = sbinfo->si_xib;
29661+ pend = i_size_read(file->f_dentry->d_inode) / PAGE_SIZE;
29662+ for (ul = pindex + 1; ul <= pend; ul++) {
29663+ err = xib_pindex(sb, ul);
29664+ if (unlikely(err))
29665+ goto out_err;
29666+ free_bit = find_first_zero_bit(p, page_bits);
29667+ if (free_bit < page_bits)
29668+ goto out; /* success */
29669+ }
29670+ BUG();
29671+
4f0767ce 29672+out:
1facf9fc 29673+ set_bit(free_bit, p);
7f207e10 29674+ sbinfo->si_xib_next_bit = free_bit + 1;
1facf9fc 29675+ pindex = sbinfo->si_xib_last_pindex;
29676+ mutex_unlock(&sbinfo->si_xib_mtx);
29677+ ino = xib_calc_ino(pindex, free_bit);
29678+ AuDbg("i%lu\n", (unsigned long)ino);
29679+ return ino;
4f0767ce 29680+out_err:
1facf9fc 29681+ mutex_unlock(&sbinfo->si_xib_mtx);
29682+ AuDbg("i0\n");
29683+ return 0;
29684+}
29685+
29686+/*
29687+ * read @ino from xinofile for the specified branch{@sb, @bindex}
29688+ * at the position of @h_ino.
29689+ * if @ino does not exist and @do_new is true, get new one.
29690+ */
29691+int au_xino_read(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino,
29692+ ino_t *ino)
29693+{
29694+ int err;
29695+ ssize_t sz;
29696+ loff_t pos;
29697+ struct file *file;
29698+ struct au_sbinfo *sbinfo;
29699+
29700+ *ino = 0;
29701+ if (!au_opt_test(au_mntflags(sb), XINO))
29702+ return 0; /* no xino */
29703+
29704+ err = 0;
29705+ sbinfo = au_sbi(sb);
29706+ pos = h_ino;
29707+ if (unlikely(au_loff_max / sizeof(*ino) - 1 < pos)) {
29708+ AuIOErr1("too large hi%lu\n", (unsigned long)h_ino);
29709+ return -EFBIG;
29710+ }
29711+ pos *= sizeof(*ino);
29712+
29713+ file = au_sbr(sb, bindex)->br_xino.xi_file;
29714+ if (i_size_read(file->f_dentry->d_inode) < pos + sizeof(*ino))
29715+ return 0; /* no ino */
29716+
29717+ sz = xino_fread(sbinfo->si_xread, file, ino, sizeof(*ino), &pos);
29718+ if (sz == sizeof(*ino))
29719+ return 0; /* success */
29720+
29721+ err = sz;
29722+ if (unlikely(sz >= 0)) {
29723+ err = -EIO;
29724+ AuIOErr("xino read error (%zd)\n", sz);
29725+ }
29726+
29727+ return err;
29728+}
29729+
29730+/* ---------------------------------------------------------------------- */
29731+
29732+/* create and set a new xino file */
29733+
29734+struct file *au_xino_create(struct super_block *sb, char *fname, int silent)
29735+{
29736+ struct file *file;
29737+ struct dentry *h_parent, *d;
29738+ struct inode *h_dir;
29739+ int err;
29740+
29741+ /*
29742+ * at mount-time, and the xino file is the default path,
4a4d8108 29743+ * hnotify is disabled so we have no notify events to ignore.
1facf9fc 29744+ * when a user specified the xino, we cannot get au_hdir to be ignored.
29745+ */
7f207e10 29746+ file = vfsub_filp_open(fname, O_RDWR | O_CREAT | O_EXCL | O_LARGEFILE
2cbb1c4b 29747+ /* | __FMODE_NONOTIFY */,
1facf9fc 29748+ S_IRUGO | S_IWUGO);
29749+ if (IS_ERR(file)) {
29750+ if (!silent)
4a4d8108 29751+ pr_err("open %s(%ld)\n", fname, PTR_ERR(file));
1facf9fc 29752+ return file;
29753+ }
29754+
29755+ /* keep file count */
29756+ h_parent = dget_parent(file->f_dentry);
29757+ h_dir = h_parent->d_inode;
29758+ mutex_lock_nested(&h_dir->i_mutex, AuLsc_I_PARENT);
29759+ /* mnt_want_write() is unnecessary here */
29760+ err = vfsub_unlink(h_dir, &file->f_path, /*force*/0);
29761+ mutex_unlock(&h_dir->i_mutex);
29762+ dput(h_parent);
29763+ if (unlikely(err)) {
29764+ if (!silent)
4a4d8108 29765+ pr_err("unlink %s(%d)\n", fname, err);
1facf9fc 29766+ goto out;
29767+ }
29768+
29769+ err = -EINVAL;
29770+ d = file->f_dentry;
29771+ if (unlikely(sb == d->d_sb)) {
29772+ if (!silent)
4a4d8108 29773+ pr_err("%s must be outside\n", fname);
1facf9fc 29774+ goto out;
29775+ }
29776+ if (unlikely(au_test_fs_bad_xino(d->d_sb))) {
29777+ if (!silent)
4a4d8108
AM
29778+ pr_err("xino doesn't support %s(%s)\n",
29779+ fname, au_sbtype(d->d_sb));
1facf9fc 29780+ goto out;
29781+ }
29782+ return file; /* success */
29783+
4f0767ce 29784+out:
1facf9fc 29785+ fput(file);
29786+ file = ERR_PTR(err);
29787+ return file;
29788+}
29789+
29790+/*
29791+ * find another branch who is on the same filesystem of the specified
29792+ * branch{@btgt}. search until @bend.
29793+ */
29794+static int is_sb_shared(struct super_block *sb, aufs_bindex_t btgt,
29795+ aufs_bindex_t bend)
29796+{
29797+ aufs_bindex_t bindex;
29798+ struct super_block *tgt_sb = au_sbr_sb(sb, btgt);
29799+
29800+ for (bindex = 0; bindex < btgt; bindex++)
29801+ if (unlikely(tgt_sb == au_sbr_sb(sb, bindex)))
29802+ return bindex;
29803+ for (bindex++; bindex <= bend; bindex++)
29804+ if (unlikely(tgt_sb == au_sbr_sb(sb, bindex)))
29805+ return bindex;
29806+ return -1;
29807+}
29808+
29809+/* ---------------------------------------------------------------------- */
29810+
29811+/*
29812+ * initialize the xinofile for the specified branch @br
29813+ * at the place/path where @base_file indicates.
29814+ * test whether another branch is on the same filesystem or not,
29815+ * if @do_test is true.
29816+ */
29817+int au_xino_br(struct super_block *sb, struct au_branch *br, ino_t h_ino,
29818+ struct file *base_file, int do_test)
29819+{
29820+ int err;
29821+ ino_t ino;
29822+ aufs_bindex_t bend, bindex;
29823+ struct au_branch *shared_br, *b;
29824+ struct file *file;
29825+ struct super_block *tgt_sb;
29826+
29827+ shared_br = NULL;
29828+ bend = au_sbend(sb);
29829+ if (do_test) {
29830+ tgt_sb = br->br_mnt->mnt_sb;
29831+ for (bindex = 0; bindex <= bend; bindex++) {
29832+ b = au_sbr(sb, bindex);
29833+ if (tgt_sb == b->br_mnt->mnt_sb) {
29834+ shared_br = b;
29835+ break;
29836+ }
29837+ }
29838+ }
29839+
29840+ if (!shared_br || !shared_br->br_xino.xi_file) {
29841+ struct au_xino_lock_dir ldir;
29842+
29843+ au_xino_lock_dir(sb, base_file, &ldir);
29844+ /* mnt_want_write() is unnecessary here */
29845+ file = au_xino_create2(base_file, NULL);
29846+ au_xino_unlock_dir(&ldir);
29847+ err = PTR_ERR(file);
29848+ if (IS_ERR(file))
29849+ goto out;
29850+ br->br_xino.xi_file = file;
29851+ } else {
29852+ br->br_xino.xi_file = shared_br->br_xino.xi_file;
29853+ get_file(br->br_xino.xi_file);
29854+ }
29855+
29856+ ino = AUFS_ROOT_INO;
29857+ err = au_xino_do_write(au_sbi(sb)->si_xwrite, br->br_xino.xi_file,
29858+ h_ino, ino);
b752ccd1
AM
29859+ if (unlikely(err)) {
29860+ fput(br->br_xino.xi_file);
29861+ br->br_xino.xi_file = NULL;
29862+ }
1facf9fc 29863+
4f0767ce 29864+out:
1facf9fc 29865+ return err;
29866+}
29867+
29868+/* ---------------------------------------------------------------------- */
29869+
29870+/* trucate a xino bitmap file */
29871+
29872+/* todo: slow */
29873+static int do_xib_restore(struct super_block *sb, struct file *file, void *page)
29874+{
29875+ int err, bit;
29876+ ssize_t sz;
29877+ unsigned long pindex;
29878+ loff_t pos, pend;
29879+ struct au_sbinfo *sbinfo;
29880+ au_readf_t func;
29881+ ino_t *ino;
29882+ unsigned long *p;
29883+
29884+ err = 0;
29885+ sbinfo = au_sbi(sb);
dece6358 29886+ MtxMustLock(&sbinfo->si_xib_mtx);
1facf9fc 29887+ p = sbinfo->si_xib_buf;
29888+ func = sbinfo->si_xread;
29889+ pend = i_size_read(file->f_dentry->d_inode);
29890+ pos = 0;
29891+ while (pos < pend) {
29892+ sz = xino_fread(func, file, page, PAGE_SIZE, &pos);
29893+ err = sz;
29894+ if (unlikely(sz <= 0))
29895+ goto out;
29896+
29897+ err = 0;
29898+ for (ino = page; sz > 0; ino++, sz -= sizeof(ino)) {
29899+ if (unlikely(*ino < AUFS_FIRST_INO))
29900+ continue;
29901+
29902+ xib_calc_bit(*ino, &pindex, &bit);
29903+ AuDebugOn(page_bits <= bit);
29904+ err = xib_pindex(sb, pindex);
29905+ if (!err)
29906+ set_bit(bit, p);
29907+ else
29908+ goto out;
29909+ }
29910+ }
29911+
4f0767ce 29912+out:
1facf9fc 29913+ return err;
29914+}
29915+
29916+static int xib_restore(struct super_block *sb)
29917+{
29918+ int err;
29919+ aufs_bindex_t bindex, bend;
29920+ void *page;
29921+
29922+ err = -ENOMEM;
29923+ page = (void *)__get_free_page(GFP_NOFS);
29924+ if (unlikely(!page))
29925+ goto out;
29926+
29927+ err = 0;
29928+ bend = au_sbend(sb);
29929+ for (bindex = 0; !err && bindex <= bend; bindex++)
29930+ if (!bindex || is_sb_shared(sb, bindex, bindex - 1) < 0)
29931+ err = do_xib_restore
29932+ (sb, au_sbr(sb, bindex)->br_xino.xi_file, page);
29933+ else
29934+ AuDbg("b%d\n", bindex);
29935+ free_page((unsigned long)page);
29936+
4f0767ce 29937+out:
1facf9fc 29938+ return err;
29939+}
29940+
29941+int au_xib_trunc(struct super_block *sb)
29942+{
29943+ int err;
29944+ ssize_t sz;
29945+ loff_t pos;
29946+ struct au_xino_lock_dir ldir;
29947+ struct au_sbinfo *sbinfo;
29948+ unsigned long *p;
29949+ struct file *file;
29950+
dece6358
AM
29951+ SiMustWriteLock(sb);
29952+
1facf9fc 29953+ err = 0;
29954+ sbinfo = au_sbi(sb);
29955+ if (!au_opt_test(sbinfo->si_mntflags, XINO))
29956+ goto out;
29957+
29958+ file = sbinfo->si_xib;
29959+ if (i_size_read(file->f_dentry->d_inode) <= PAGE_SIZE)
29960+ goto out;
29961+
29962+ au_xino_lock_dir(sb, file, &ldir);
29963+ /* mnt_want_write() is unnecessary here */
29964+ file = au_xino_create2(sbinfo->si_xib, NULL);
29965+ au_xino_unlock_dir(&ldir);
29966+ err = PTR_ERR(file);
29967+ if (IS_ERR(file))
29968+ goto out;
29969+ fput(sbinfo->si_xib);
29970+ sbinfo->si_xib = file;
29971+
29972+ p = sbinfo->si_xib_buf;
29973+ memset(p, 0, PAGE_SIZE);
29974+ pos = 0;
29975+ sz = xino_fwrite(sbinfo->si_xwrite, sbinfo->si_xib, p, PAGE_SIZE, &pos);
29976+ if (unlikely(sz != PAGE_SIZE)) {
29977+ err = sz;
29978+ AuIOErr("err %d\n", err);
29979+ if (sz >= 0)
29980+ err = -EIO;
29981+ goto out;
29982+ }
29983+
29984+ mutex_lock(&sbinfo->si_xib_mtx);
29985+ /* mnt_want_write() is unnecessary here */
29986+ err = xib_restore(sb);
29987+ mutex_unlock(&sbinfo->si_xib_mtx);
29988+
29989+out:
29990+ return err;
29991+}
29992+
29993+/* ---------------------------------------------------------------------- */
29994+
29995+/*
29996+ * xino mount option handlers
29997+ */
29998+static au_readf_t find_readf(struct file *h_file)
29999+{
30000+ const struct file_operations *fop = h_file->f_op;
30001+
30002+ if (fop) {
30003+ if (fop->read)
30004+ return fop->read;
30005+ if (fop->aio_read)
30006+ return do_sync_read;
30007+ }
30008+ return ERR_PTR(-ENOSYS);
30009+}
30010+
30011+static au_writef_t find_writef(struct file *h_file)
30012+{
30013+ const struct file_operations *fop = h_file->f_op;
30014+
30015+ if (fop) {
30016+ if (fop->write)
30017+ return fop->write;
30018+ if (fop->aio_write)
30019+ return do_sync_write;
30020+ }
30021+ return ERR_PTR(-ENOSYS);
30022+}
30023+
30024+/* xino bitmap */
30025+static void xino_clear_xib(struct super_block *sb)
30026+{
30027+ struct au_sbinfo *sbinfo;
30028+
dece6358
AM
30029+ SiMustWriteLock(sb);
30030+
1facf9fc 30031+ sbinfo = au_sbi(sb);
30032+ sbinfo->si_xread = NULL;
30033+ sbinfo->si_xwrite = NULL;
30034+ if (sbinfo->si_xib)
30035+ fput(sbinfo->si_xib);
30036+ sbinfo->si_xib = NULL;
30037+ free_page((unsigned long)sbinfo->si_xib_buf);
30038+ sbinfo->si_xib_buf = NULL;
30039+}
30040+
30041+static int au_xino_set_xib(struct super_block *sb, struct file *base)
30042+{
30043+ int err;
30044+ loff_t pos;
30045+ struct au_sbinfo *sbinfo;
30046+ struct file *file;
30047+
dece6358
AM
30048+ SiMustWriteLock(sb);
30049+
1facf9fc 30050+ sbinfo = au_sbi(sb);
30051+ file = au_xino_create2(base, sbinfo->si_xib);
30052+ err = PTR_ERR(file);
30053+ if (IS_ERR(file))
30054+ goto out;
30055+ if (sbinfo->si_xib)
30056+ fput(sbinfo->si_xib);
30057+ sbinfo->si_xib = file;
30058+ sbinfo->si_xread = find_readf(file);
30059+ sbinfo->si_xwrite = find_writef(file);
30060+
30061+ err = -ENOMEM;
30062+ if (!sbinfo->si_xib_buf)
30063+ sbinfo->si_xib_buf = (void *)get_zeroed_page(GFP_NOFS);
30064+ if (unlikely(!sbinfo->si_xib_buf))
30065+ goto out_unset;
30066+
30067+ sbinfo->si_xib_last_pindex = 0;
30068+ sbinfo->si_xib_next_bit = 0;
30069+ if (i_size_read(file->f_dentry->d_inode) < PAGE_SIZE) {
30070+ pos = 0;
30071+ err = xino_fwrite(sbinfo->si_xwrite, file, sbinfo->si_xib_buf,
30072+ PAGE_SIZE, &pos);
30073+ if (unlikely(err != PAGE_SIZE))
30074+ goto out_free;
30075+ }
30076+ err = 0;
30077+ goto out; /* success */
30078+
4f0767ce 30079+out_free:
1facf9fc 30080+ free_page((unsigned long)sbinfo->si_xib_buf);
b752ccd1
AM
30081+ sbinfo->si_xib_buf = NULL;
30082+ if (err >= 0)
30083+ err = -EIO;
4f0767ce 30084+out_unset:
b752ccd1
AM
30085+ fput(sbinfo->si_xib);
30086+ sbinfo->si_xib = NULL;
30087+ sbinfo->si_xread = NULL;
30088+ sbinfo->si_xwrite = NULL;
4f0767ce 30089+out:
b752ccd1 30090+ return err;
1facf9fc 30091+}
30092+
b752ccd1
AM
30093+/* xino for each branch */
30094+static void xino_clear_br(struct super_block *sb)
30095+{
30096+ aufs_bindex_t bindex, bend;
30097+ struct au_branch *br;
1facf9fc 30098+
b752ccd1
AM
30099+ bend = au_sbend(sb);
30100+ for (bindex = 0; bindex <= bend; bindex++) {
30101+ br = au_sbr(sb, bindex);
30102+ if (!br || !br->br_xino.xi_file)
30103+ continue;
30104+
30105+ fput(br->br_xino.xi_file);
30106+ br->br_xino.xi_file = NULL;
30107+ }
30108+}
30109+
30110+static int au_xino_set_br(struct super_block *sb, struct file *base)
1facf9fc 30111+{
30112+ int err;
b752ccd1
AM
30113+ ino_t ino;
30114+ aufs_bindex_t bindex, bend, bshared;
30115+ struct {
30116+ struct file *old, *new;
30117+ } *fpair, *p;
30118+ struct au_branch *br;
30119+ struct inode *inode;
30120+ au_writef_t writef;
1facf9fc 30121+
b752ccd1
AM
30122+ SiMustWriteLock(sb);
30123+
30124+ err = -ENOMEM;
30125+ bend = au_sbend(sb);
30126+ fpair = kcalloc(bend + 1, sizeof(*fpair), GFP_NOFS);
30127+ if (unlikely(!fpair))
1facf9fc 30128+ goto out;
30129+
b752ccd1
AM
30130+ inode = sb->s_root->d_inode;
30131+ ino = AUFS_ROOT_INO;
30132+ writef = au_sbi(sb)->si_xwrite;
30133+ for (bindex = 0, p = fpair; bindex <= bend; bindex++, p++) {
30134+ br = au_sbr(sb, bindex);
30135+ bshared = is_sb_shared(sb, bindex, bindex - 1);
30136+ if (bshared >= 0) {
30137+ /* shared xino */
30138+ *p = fpair[bshared];
30139+ get_file(p->new);
30140+ }
30141+
30142+ if (!p->new) {
30143+ /* new xino */
30144+ p->old = br->br_xino.xi_file;
30145+ p->new = au_xino_create2(base, br->br_xino.xi_file);
30146+ err = PTR_ERR(p->new);
30147+ if (IS_ERR(p->new)) {
30148+ p->new = NULL;
30149+ goto out_pair;
30150+ }
30151+ }
30152+
30153+ err = au_xino_do_write(writef, p->new,
30154+ au_h_iptr(inode, bindex)->i_ino, ino);
30155+ if (unlikely(err))
30156+ goto out_pair;
30157+ }
30158+
30159+ for (bindex = 0, p = fpair; bindex <= bend; bindex++, p++) {
30160+ br = au_sbr(sb, bindex);
30161+ if (br->br_xino.xi_file)
30162+ fput(br->br_xino.xi_file);
30163+ get_file(p->new);
30164+ br->br_xino.xi_file = p->new;
30165+ }
1facf9fc 30166+
4f0767ce 30167+out_pair:
b752ccd1
AM
30168+ for (bindex = 0, p = fpair; bindex <= bend; bindex++, p++)
30169+ if (p->new)
30170+ fput(p->new);
30171+ else
30172+ break;
30173+ kfree(fpair);
4f0767ce 30174+out:
1facf9fc 30175+ return err;
30176+}
b752ccd1
AM
30177+
30178+void au_xino_clr(struct super_block *sb)
30179+{
30180+ struct au_sbinfo *sbinfo;
30181+
30182+ au_xigen_clr(sb);
30183+ xino_clear_xib(sb);
30184+ xino_clear_br(sb);
30185+ sbinfo = au_sbi(sb);
30186+ /* lvalue, do not call au_mntflags() */
30187+ au_opt_clr(sbinfo->si_mntflags, XINO);
30188+}
30189+
30190+int au_xino_set(struct super_block *sb, struct au_opt_xino *xino, int remount)
30191+{
30192+ int err, skip;
30193+ struct dentry *parent, *cur_parent;
30194+ struct qstr *dname, *cur_name;
30195+ struct file *cur_xino;
30196+ struct inode *dir;
30197+ struct au_sbinfo *sbinfo;
30198+
30199+ SiMustWriteLock(sb);
30200+
30201+ err = 0;
30202+ sbinfo = au_sbi(sb);
30203+ parent = dget_parent(xino->file->f_dentry);
30204+ if (remount) {
30205+ skip = 0;
30206+ dname = &xino->file->f_dentry->d_name;
30207+ cur_xino = sbinfo->si_xib;
30208+ if (cur_xino) {
30209+ cur_parent = dget_parent(cur_xino->f_dentry);
30210+ cur_name = &cur_xino->f_dentry->d_name;
30211+ skip = (cur_parent == parent
30212+ && dname->len == cur_name->len
30213+ && !memcmp(dname->name, cur_name->name,
30214+ dname->len));
30215+ dput(cur_parent);
30216+ }
30217+ if (skip)
30218+ goto out;
30219+ }
30220+
30221+ au_opt_set(sbinfo->si_mntflags, XINO);
30222+ dir = parent->d_inode;
30223+ mutex_lock_nested(&dir->i_mutex, AuLsc_I_PARENT);
30224+ /* mnt_want_write() is unnecessary here */
30225+ err = au_xino_set_xib(sb, xino->file);
30226+ if (!err)
30227+ err = au_xigen_set(sb, xino->file);
30228+ if (!err)
30229+ err = au_xino_set_br(sb, xino->file);
30230+ mutex_unlock(&dir->i_mutex);
30231+ if (!err)
30232+ goto out; /* success */
30233+
30234+ /* reset all */
30235+ AuIOErr("failed creating xino(%d).\n", err);
30236+
4f0767ce 30237+out:
b752ccd1
AM
30238+ dput(parent);
30239+ return err;
30240+}
30241+
30242+/* ---------------------------------------------------------------------- */
30243+
30244+/*
30245+ * create a xinofile at the default place/path.
30246+ */
30247+struct file *au_xino_def(struct super_block *sb)
30248+{
30249+ struct file *file;
30250+ char *page, *p;
30251+ struct au_branch *br;
30252+ struct super_block *h_sb;
30253+ struct path path;
30254+ aufs_bindex_t bend, bindex, bwr;
30255+
30256+ br = NULL;
30257+ bend = au_sbend(sb);
30258+ bwr = -1;
30259+ for (bindex = 0; bindex <= bend; bindex++) {
30260+ br = au_sbr(sb, bindex);
30261+ if (au_br_writable(br->br_perm)
30262+ && !au_test_fs_bad_xino(br->br_mnt->mnt_sb)) {
30263+ bwr = bindex;
30264+ break;
30265+ }
30266+ }
30267+
7f207e10
AM
30268+ if (bwr >= 0) {
30269+ file = ERR_PTR(-ENOMEM);
30270+ page = __getname_gfp(GFP_NOFS);
30271+ if (unlikely(!page))
30272+ goto out;
30273+ path.mnt = br->br_mnt;
30274+ path.dentry = au_h_dptr(sb->s_root, bwr);
30275+ p = d_path(&path, page, PATH_MAX - sizeof(AUFS_XINO_FNAME));
30276+ file = (void *)p;
30277+ if (!IS_ERR(p)) {
30278+ strcat(p, "/" AUFS_XINO_FNAME);
30279+ AuDbg("%s\n", p);
30280+ file = au_xino_create(sb, p, /*silent*/0);
30281+ if (!IS_ERR(file))
30282+ au_xino_brid_set(sb, br->br_id);
30283+ }
30284+ __putname(page);
30285+ } else {
30286+ file = au_xino_create(sb, AUFS_XINO_DEFPATH, /*silent*/0);
30287+ if (IS_ERR(file))
30288+ goto out;
30289+ h_sb = file->f_dentry->d_sb;
30290+ if (unlikely(au_test_fs_bad_xino(h_sb))) {
30291+ pr_err("xino doesn't support %s(%s)\n",
30292+ AUFS_XINO_DEFPATH, au_sbtype(h_sb));
30293+ fput(file);
30294+ file = ERR_PTR(-EINVAL);
30295+ }
30296+ if (!IS_ERR(file))
30297+ au_xino_brid_set(sb, -1);
30298+ }
0c5527e5 30299+
7f207e10
AM
30300+out:
30301+ return file;
30302+}
30303+
30304+/* ---------------------------------------------------------------------- */
30305+
30306+int au_xino_path(struct seq_file *seq, struct file *file)
30307+{
30308+ int err;
30309+
30310+ err = au_seq_path(seq, &file->f_path);
30311+ if (unlikely(err < 0))
30312+ goto out;
30313+
30314+ err = 0;
30315+#define Deleted "\\040(deleted)"
30316+ seq->count -= sizeof(Deleted) - 1;
30317+ AuDebugOn(memcmp(seq->buf + seq->count, Deleted,
30318+ sizeof(Deleted) - 1));
30319+#undef Deleted
30320+
30321+out:
30322+ return err;
30323+}
30324diff -urN /usr/share/empty/include/linux/aufs_type.h linux/include/linux/aufs_type.h
30325--- /usr/share/empty/include/linux/aufs_type.h 1970-01-01 01:00:00.000000000 +0100
7ce627cf 30326+++ linux/include/linux/aufs_type.h 2012-05-23 12:07:43.277739181 +0200
f6c5ef8b 30327@@ -0,0 +1,233 @@
7f207e10 30328+/*
f6c5ef8b 30329+ * Copyright (C) 2005-2012 Junjiro R. Okajima
7f207e10
AM
30330+ *
30331+ * This program, aufs is free software; you can redistribute it and/or modify
30332+ * it under the terms of the GNU General Public License as published by
30333+ * the Free Software Foundation; either version 2 of the License, or
30334+ * (at your option) any later version.
30335+ *
30336+ * This program is distributed in the hope that it will be useful,
30337+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
30338+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
30339+ * GNU General Public License for more details.
30340+ *
30341+ * You should have received a copy of the GNU General Public License
30342+ * along with this program; if not, write to the Free Software
30343+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
30344+ */
30345+
30346+#ifndef __AUFS_TYPE_H__
30347+#define __AUFS_TYPE_H__
30348+
f6c5ef8b
AM
30349+#define AUFS_NAME "aufs"
30350+
9dbd164d 30351+#ifdef __KERNEL__
f6c5ef8b
AM
30352+/*
30353+ * define it before including all other headers.
30354+ * sched.h may use pr_* macros before defining "current", so define the
30355+ * no-current version first, and re-define later.
30356+ */
30357+#define pr_fmt(fmt) AUFS_NAME " %s:%d: " fmt, __func__, __LINE__
30358+#include <linux/sched.h>
30359+#undef pr_fmt
30360+#define pr_fmt(fmt) AUFS_NAME " %s:%d:%s[%d]: " fmt, \
30361+ __func__, __LINE__, current->comm, current->pid
9dbd164d
AM
30362+#else
30363+#include <stdint.h>
30364+#include <sys/types.h>
f6c5ef8b 30365+#endif /* __KERNEL__ */
7f207e10 30366+
f6c5ef8b
AM
30367+#include <linux/limits.h>
30368+
7ce627cf 30369+#define AUFS_VERSION "3.4-20120521"
7f207e10
AM
30370+
30371+/* todo? move this to linux-2.6.19/include/magic.h */
30372+#define AUFS_SUPER_MAGIC ('a' << 24 | 'u' << 16 | 'f' << 8 | 's')
30373+
30374+/* ---------------------------------------------------------------------- */
30375+
30376+#ifdef CONFIG_AUFS_BRANCH_MAX_127
9dbd164d 30377+typedef int8_t aufs_bindex_t;
7f207e10
AM
30378+#define AUFS_BRANCH_MAX 127
30379+#else
9dbd164d 30380+typedef int16_t aufs_bindex_t;
7f207e10
AM
30381+#ifdef CONFIG_AUFS_BRANCH_MAX_511
30382+#define AUFS_BRANCH_MAX 511
30383+#elif defined(CONFIG_AUFS_BRANCH_MAX_1023)
30384+#define AUFS_BRANCH_MAX 1023
30385+#elif defined(CONFIG_AUFS_BRANCH_MAX_32767)
30386+#define AUFS_BRANCH_MAX 32767
30387+#endif
30388+#endif
30389+
30390+#ifdef __KERNEL__
30391+#ifndef AUFS_BRANCH_MAX
30392+#error unknown CONFIG_AUFS_BRANCH_MAX value
30393+#endif
30394+#endif /* __KERNEL__ */
30395+
30396+/* ---------------------------------------------------------------------- */
30397+
7f207e10
AM
30398+#define AUFS_FSTYPE AUFS_NAME
30399+
30400+#define AUFS_ROOT_INO 2
30401+#define AUFS_FIRST_INO 11
30402+
30403+#define AUFS_WH_PFX ".wh."
30404+#define AUFS_WH_PFX_LEN ((int)sizeof(AUFS_WH_PFX) - 1)
30405+#define AUFS_WH_TMP_LEN 4
30406+/* a limit for rmdir/rename a dir */
30407+#define AUFS_MAX_NAMELEN (NAME_MAX \
30408+ - AUFS_WH_PFX_LEN * 2 /* doubly whiteouted */\
30409+ - 1 /* dot */\
30410+ - AUFS_WH_TMP_LEN) /* hex */
30411+#define AUFS_XINO_FNAME "." AUFS_NAME ".xino"
30412+#define AUFS_XINO_DEFPATH "/tmp/" AUFS_XINO_FNAME
30413+#define AUFS_XINO_TRUNC_INIT 64 /* blocks */
30414+#define AUFS_XINO_TRUNC_STEP 4 /* blocks */
30415+#define AUFS_DIRWH_DEF 3
30416+#define AUFS_RDCACHE_DEF 10 /* seconds */
027c5e7a 30417+#define AUFS_RDCACHE_MAX 3600 /* seconds */
7f207e10
AM
30418+#define AUFS_RDBLK_DEF 512 /* bytes */
30419+#define AUFS_RDHASH_DEF 32
30420+#define AUFS_WKQ_NAME AUFS_NAME "d"
027c5e7a
AM
30421+#define AUFS_MFS_DEF_SEC 30 /* seconds */
30422+#define AUFS_MFS_MAX_SEC 3600 /* seconds */
7f207e10
AM
30423+#define AUFS_PLINK_WARN 100 /* number of plinks */
30424+
30425+/* pseudo-link maintenace under /proc */
30426+#define AUFS_PLINK_MAINT_NAME "plink_maint"
30427+#define AUFS_PLINK_MAINT_DIR "fs/" AUFS_NAME
30428+#define AUFS_PLINK_MAINT_PATH AUFS_PLINK_MAINT_DIR "/" AUFS_PLINK_MAINT_NAME
30429+
30430+#define AUFS_DIROPQ_NAME AUFS_WH_PFX ".opq" /* whiteouted doubly */
30431+#define AUFS_WH_DIROPQ AUFS_WH_PFX AUFS_DIROPQ_NAME
30432+
30433+#define AUFS_BASE_NAME AUFS_WH_PFX AUFS_NAME
30434+#define AUFS_PLINKDIR_NAME AUFS_WH_PFX "plnk"
30435+#define AUFS_ORPHDIR_NAME AUFS_WH_PFX "orph"
30436+
30437+/* doubly whiteouted */
30438+#define AUFS_WH_BASE AUFS_WH_PFX AUFS_BASE_NAME
30439+#define AUFS_WH_PLINKDIR AUFS_WH_PFX AUFS_PLINKDIR_NAME
30440+#define AUFS_WH_ORPHDIR AUFS_WH_PFX AUFS_ORPHDIR_NAME
30441+
1e00d052 30442+/* branch permissions and attributes */
7f207e10
AM
30443+#define AUFS_BRPERM_RW "rw"
30444+#define AUFS_BRPERM_RO "ro"
30445+#define AUFS_BRPERM_RR "rr"
1e00d052
AM
30446+#define AUFS_BRRATTR_WH "wh"
30447+#define AUFS_BRWATTR_NLWH "nolwh"
7f207e10
AM
30448+
30449+/* ---------------------------------------------------------------------- */
30450+
30451+/* ioctl */
30452+enum {
30453+ /* readdir in userspace */
30454+ AuCtl_RDU,
30455+ AuCtl_RDU_INO,
30456+
30457+ /* pathconf wrapper */
027c5e7a
AM
30458+ AuCtl_WBR_FD,
30459+
30460+ /* busy inode */
30461+ AuCtl_IBUSY
7f207e10
AM
30462+};
30463+
30464+/* borrowed from linux/include/linux/kernel.h */
30465+#ifndef ALIGN
30466+#define ALIGN(x, a) __ALIGN_MASK(x, (typeof(x))(a)-1)
30467+#define __ALIGN_MASK(x, mask) (((x)+(mask))&~(mask))
30468+#endif
30469+
30470+/* borrowed from linux/include/linux/compiler-gcc3.h */
30471+#ifndef __aligned
30472+#define __aligned(x) __attribute__((aligned(x)))
53392da6
AM
30473+#endif
30474+
30475+#ifdef __KERNEL__
30476+#ifndef __packed
7f207e10
AM
30477+#define __packed __attribute__((packed))
30478+#endif
53392da6 30479+#endif
7f207e10
AM
30480+
30481+struct au_rdu_cookie {
9dbd164d
AM
30482+ uint64_t h_pos;
30483+ int16_t bindex;
30484+ uint8_t flags;
30485+ uint8_t pad;
30486+ uint32_t generation;
7f207e10
AM
30487+} __aligned(8);
30488+
30489+struct au_rdu_ent {
9dbd164d
AM
30490+ uint64_t ino;
30491+ int16_t bindex;
30492+ uint8_t type;
30493+ uint8_t nlen;
30494+ uint8_t wh;
7f207e10
AM
30495+ char name[0];
30496+} __aligned(8);
30497+
30498+static inline int au_rdu_len(int nlen)
30499+{
30500+ /* include the terminating NULL */
30501+ return ALIGN(sizeof(struct au_rdu_ent) + nlen + 1,
9dbd164d 30502+ sizeof(uint64_t));
7f207e10
AM
30503+}
30504+
30505+union au_rdu_ent_ul {
30506+ struct au_rdu_ent __user *e;
9dbd164d 30507+ uint64_t ul;
7f207e10
AM
30508+};
30509+
30510+enum {
30511+ AufsCtlRduV_SZ,
30512+ AufsCtlRduV_End
30513+};
30514+
30515+struct aufs_rdu {
30516+ /* input */
30517+ union {
9dbd164d
AM
30518+ uint64_t sz; /* AuCtl_RDU */
30519+ uint64_t nent; /* AuCtl_RDU_INO */
7f207e10
AM
30520+ };
30521+ union au_rdu_ent_ul ent;
9dbd164d 30522+ uint16_t verify[AufsCtlRduV_End];
7f207e10
AM
30523+
30524+ /* input/output */
9dbd164d 30525+ uint32_t blk;
7f207e10
AM
30526+
30527+ /* output */
30528+ union au_rdu_ent_ul tail;
30529+ /* number of entries which were added in a single call */
9dbd164d
AM
30530+ uint64_t rent;
30531+ uint8_t full;
30532+ uint8_t shwh;
7f207e10
AM
30533+
30534+ struct au_rdu_cookie cookie;
30535+} __aligned(8);
30536+
1e00d052
AM
30537+/* ---------------------------------------------------------------------- */
30538+
30539+struct aufs_wbr_fd {
9dbd164d
AM
30540+ uint32_t oflags;
30541+ int16_t brid;
1e00d052
AM
30542+} __aligned(8);
30543+
30544+/* ---------------------------------------------------------------------- */
30545+
027c5e7a 30546+struct aufs_ibusy {
9dbd164d
AM
30547+ uint64_t ino, h_ino;
30548+ int16_t bindex;
027c5e7a
AM
30549+} __aligned(8);
30550+
1e00d052
AM
30551+/* ---------------------------------------------------------------------- */
30552+
7f207e10
AM
30553+#define AuCtlType 'A'
30554+#define AUFS_CTL_RDU _IOWR(AuCtlType, AuCtl_RDU, struct aufs_rdu)
30555+#define AUFS_CTL_RDU_INO _IOWR(AuCtlType, AuCtl_RDU_INO, struct aufs_rdu)
1e00d052
AM
30556+#define AUFS_CTL_WBR_FD _IOW(AuCtlType, AuCtl_WBR_FD, \
30557+ struct aufs_wbr_fd)
027c5e7a 30558+#define AUFS_CTL_IBUSY _IOWR(AuCtlType, AuCtl_IBUSY, struct aufs_ibusy)
7f207e10
AM
30559+
30560+#endif /* __AUFS_TYPE_H__ */
9dbd164d 30561
This page took 6.280023 seconds and 4 git commands to generate.