]> git.pld-linux.org Git - packages/kernel.git/blame - kernel-aufs3.patch
- updated vserver patch to patch-3.6.10-vs2.3.4.5.diff
[packages/kernel.git] / kernel-aufs3.patch
CommitLineData
b4510431 1aufs3.6 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
b4510431 25index fa21760..ee029e3 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
b4510431 36aufs3.6 base patch
7f207e10 37
0c3ec466 38diff --git a/fs/inode.c b/fs/inode.c
b4510431 39index ac8d904..7b2c8fa 100644
0c3ec466
AM
40--- a/fs/inode.c
41+++ b/fs/inode.c
42@@ -1491,7 +1491,7 @@ static int relatime_need_update(struct vfsmount *mnt, struct inode *inode,
43 * This does the actual work of updating an inodes time or version. Must have
44 * had called mnt_want_write() before calling this.
45 */
46-static int update_time(struct inode *inode, struct timespec *time, int flags)
47+int update_time(struct inode *inode, struct timespec *time, int flags)
48 {
49 if (inode->i_op->update_time)
50 return inode->i_op->update_time(inode, time, flags);
7f207e10 51diff --git a/fs/splice.c b/fs/splice.c
b4510431 52index 41514dd..663b402 100644
7f207e10
AM
53--- a/fs/splice.c
54+++ b/fs/splice.c
b4510431 55@@ -1093,8 +1093,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);
b4510431 66@@ -1121,9 +1121,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);
0c3ec466 79diff --git a/include/linux/fs.h b/include/linux/fs.h
b4510431 80index aa11047..9116d2e 100644
0c3ec466
AM
81--- a/include/linux/fs.h
82+++ b/include/linux/fs.h
b4510431 83@@ -2741,6 +2741,7 @@ extern int inode_change_ok(const struct inode *, struct iattr *);
0c3ec466
AM
84 extern int inode_newsize_ok(const struct inode *, loff_t offset);
85 extern void setattr_copy(struct inode *inode, const struct iattr *attr);
86
87+extern int update_time(struct inode *, struct timespec *, int);
88 extern int file_update_time(struct file *file);
89
90 extern int generic_show_options(struct seq_file *m, struct dentry *root);
1e00d052 91diff --git a/include/linux/splice.h b/include/linux/splice.h
2dfbb274 92index 09a545a..1ac5727 100644
1e00d052
AM
93--- a/include/linux/splice.h
94+++ b/include/linux/splice.h
2dfbb274 95@@ -91,4 +91,10 @@ extern void splice_shrink_spd(struct splice_pipe_desc *);
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
b4510431 106aufs3.6 standalone patch
7f207e10
AM
107
108diff --git a/fs/file_table.c b/fs/file_table.c
b4510431 109index 701985e..a9fe741 100644
7f207e10
AM
110--- a/fs/file_table.c
111+++ b/fs/file_table.c
b4510431 112@@ -37,6 +37,7 @@ struct files_stat_struct files_stat = {
0c3ec466
AM
113 };
114
115 DEFINE_LGLOCK(files_lglock);
116+EXPORT_SYMBOL(files_lglock);
117
118 /* SLAB cache for file structures */
119 static struct kmem_cache *filp_cachep __read_mostly;
b4510431 120@@ -509,6 +510,8 @@ void file_sb_list_del(struct file *file)
7f207e10
AM
121 }
122 }
123
124+EXPORT_SYMBOL(file_sb_list_del);
1facf9fc 125+
7f207e10
AM
126 #ifdef CONFIG_SMP
127
128 /*
1e00d052 129diff --git a/fs/inode.c b/fs/inode.c
b4510431 130index 7b2c8fa..0c4318d 100644
1e00d052
AM
131--- a/fs/inode.c
132+++ b/fs/inode.c
92d182d2 133@@ -56,6 +56,7 @@ static struct hlist_head *inode_hashtable __read_mostly;
4b3da204 134 static __cacheline_aligned_in_smp DEFINE_SPINLOCK(inode_hash_lock);
2cbb1c4b
JR
135
136 __cacheline_aligned_in_smp DEFINE_SPINLOCK(inode_sb_list_lock);
2cbb1c4b 137+EXPORT_SYMBOL(inode_sb_list_lock);
7f207e10
AM
138
139 /*
4b3da204 140 * Empty aops. Can be used for the cases where the user does not
0c3ec466
AM
141@@ -1507,6 +1508,7 @@ int update_time(struct inode *inode, struct timespec *time, int flags)
142 mark_inode_dirty_sync(inode);
143 return 0;
144 }
145+EXPORT_SYMBOL(update_time);
146
147 /**
148 * touch_atime - update the access time
7f207e10 149diff --git a/fs/namespace.c b/fs/namespace.c
b4510431 150index 7bdf790..5b85c4c 100644
7f207e10
AM
151--- a/fs/namespace.c
152+++ b/fs/namespace.c
0c3ec466
AM
153@@ -50,6 +50,7 @@ EXPORT_SYMBOL_GPL(fs_kobj);
154 * tree or hash is modified or when a vfsmount structure is modified.
155 */
156 DEFINE_BRLOCK(vfsmount_lock);
157+EXPORT_SYMBOL(vfsmount_lock);
158
159 static inline unsigned long hash(struct vfsmount *mnt, struct dentry *dentry)
160 {
b4510431 161@@ -1401,6 +1402,7 @@ int iterate_mounts(int (*f)(struct vfsmount *, void *), void *arg,
7f207e10
AM
162 }
163 return 0;
164 }
165+EXPORT_SYMBOL(iterate_mounts);
166
7eafdf33 167 static void cleanup_group_ids(struct mount *mnt, struct mount *end)
7f207e10
AM
168 {
169diff --git a/fs/notify/group.c b/fs/notify/group.c
1e00d052 170index 63fc294..6f4adca 100644
7f207e10
AM
171--- a/fs/notify/group.c
172+++ b/fs/notify/group.c
173@@ -22,6 +22,7 @@
174 #include <linux/srcu.h>
175 #include <linux/rculist.h>
176 #include <linux/wait.h>
177+#include <linux/module.h>
178
179 #include <linux/fsnotify_backend.h>
180 #include "fsnotify.h"
181@@ -70,6 +71,7 @@ void fsnotify_put_group(struct fsnotify_group *group)
182 if (atomic_dec_and_test(&group->refcnt))
183 fsnotify_destroy_group(group);
184 }
185+EXPORT_SYMBOL(fsnotify_put_group);
186
187 /*
188 * Create a new fsnotify_group and hold a reference for the group returned.
189@@ -102,3 +104,4 @@ struct fsnotify_group *fsnotify_alloc_group(const struct fsnotify_ops *ops)
190
191 return group;
192 }
193+EXPORT_SYMBOL(fsnotify_alloc_group);
194diff --git a/fs/notify/mark.c b/fs/notify/mark.c
7eafdf33 195index f104d56..54f36db 100644
7f207e10
AM
196--- a/fs/notify/mark.c
197+++ b/fs/notify/mark.c
2cbb1c4b 198@@ -112,6 +112,7 @@ void fsnotify_put_mark(struct fsnotify_mark *mark)
7f207e10
AM
199 if (atomic_dec_and_test(&mark->refcnt))
200 mark->free_mark(mark);
201 }
202+EXPORT_SYMBOL(fsnotify_put_mark);
203
204 /*
205 * Any time a mark is getting freed we end up here.
7eafdf33 206@@ -191,6 +192,7 @@ void fsnotify_destroy_mark(struct fsnotify_mark *mark)
7f207e10
AM
207 if (unlikely(atomic_dec_and_test(&group->num_marks)))
208 fsnotify_final_destroy_group(group);
209 }
210+EXPORT_SYMBOL(fsnotify_destroy_mark);
211
212 void fsnotify_set_mark_mask_locked(struct fsnotify_mark *mark, __u32 mask)
213 {
7eafdf33 214@@ -278,6 +280,7 @@ err:
7f207e10
AM
215
216 return ret;
217 }
218+EXPORT_SYMBOL(fsnotify_add_mark);
219
220 /*
221 * clear any marks in a group in which mark->flags & flags is true
7eafdf33 222@@ -333,6 +336,7 @@ void fsnotify_init_mark(struct fsnotify_mark *mark,
7f207e10
AM
223 atomic_set(&mark->refcnt, 1);
224 mark->free_mark = free_mark;
225 }
226+EXPORT_SYMBOL(fsnotify_init_mark);
227
228 static int fsnotify_mark_destroy(void *ignored)
229 {
230diff --git a/fs/open.c b/fs/open.c
b4510431 231index e1f2cdb..2804cd6 100644
7f207e10
AM
232--- a/fs/open.c
233+++ b/fs/open.c
234@@ -60,6 +60,7 @@ int do_truncate(struct dentry *dentry, loff_t length, unsigned int time_attrs,
235 mutex_unlock(&dentry->d_inode->i_mutex);
236 return ret;
237 }
238+EXPORT_SYMBOL(do_truncate);
239
240 static long do_sys_truncate(const char __user *pathname, loff_t length)
241 {
242diff --git a/fs/splice.c b/fs/splice.c
b4510431 243index 663b402..51e1deb 100644
7f207e10
AM
244--- a/fs/splice.c
245+++ b/fs/splice.c
b4510431 246@@ -1117,6 +1117,7 @@ long do_splice_from(struct pipe_inode_info *pipe, struct file *out,
7f207e10
AM
247
248 return splice_write(pipe, out, ppos, len, flags);
249 }
250+EXPORT_SYMBOL(do_splice_from);
251
252 /*
253 * Attempt to initiate a splice from a file to a pipe.
b4510431 254@@ -1143,6 +1144,7 @@ long do_splice_to(struct file *in, loff_t *ppos,
7f207e10
AM
255
256 return splice_read(in, ppos, pipe, len, flags);
257 }
258+EXPORT_SYMBOL(do_splice_to);
259
260 /**
261 * splice_direct_to_actor - splices data directly between two non-pipes
262diff --git a/security/commoncap.c b/security/commoncap.c
0c3ec466 263index 6dbae46..9f4f29a 100644
7f207e10
AM
264--- a/security/commoncap.c
265+++ b/security/commoncap.c
0c3ec466 266@@ -979,9 +979,11 @@ int cap_mmap_addr(unsigned long addr)
94337f0d 267 }
7f207e10
AM
268 return ret;
269 }
0c3ec466
AM
270+EXPORT_SYMBOL(cap_mmap_addr);
271
272 int cap_mmap_file(struct file *file, unsigned long reqprot,
273 unsigned long prot, unsigned long flags)
274 {
275 return 0;
276 }
277+EXPORT_SYMBOL(cap_mmap_file);
7f207e10 278diff --git a/security/device_cgroup.c b/security/device_cgroup.c
0c3ec466 279index 442204c..e644a1c 100644
7f207e10
AM
280--- a/security/device_cgroup.c
281+++ b/security/device_cgroup.c
f6c5ef8b
AM
282@@ -7,6 +7,7 @@
283 #include <linux/device_cgroup.h>
284 #include <linux/cgroup.h>
285 #include <linux/ctype.h>
286+#include <linux/export.h>
287 #include <linux/list.h>
288 #include <linux/uaccess.h>
289 #include <linux/seq_file.h>
0c3ec466 290@@ -493,6 +494,7 @@ found:
7f207e10
AM
291
292 return -EPERM;
293 }
2cbb1c4b 294+EXPORT_SYMBOL(__devcgroup_inode_permission);
7f207e10
AM
295
296 int devcgroup_inode_mknod(int mode, dev_t dev)
297 {
298diff --git a/security/security.c b/security/security.c
2dfbb274 299index 860aeb3..ffb57bf 100644
7f207e10
AM
300--- a/security/security.c
301+++ b/security/security.c
2dfbb274 302@@ -384,6 +384,7 @@ int security_path_rmdir(struct path *dir, struct dentry *dentry)
7f207e10
AM
303 return 0;
304 return security_ops->path_rmdir(dir, dentry);
305 }
306+EXPORT_SYMBOL(security_path_rmdir);
307
308 int security_path_unlink(struct path *dir, struct dentry *dentry)
309 {
2dfbb274 310@@ -400,6 +401,7 @@ int security_path_symlink(struct path *dir, struct dentry *dentry,
7f207e10
AM
311 return 0;
312 return security_ops->path_symlink(dir, dentry, old_name);
313 }
314+EXPORT_SYMBOL(security_path_symlink);
315
316 int security_path_link(struct dentry *old_dentry, struct path *new_dir,
317 struct dentry *new_dentry)
2dfbb274 318@@ -408,6 +410,7 @@ int security_path_link(struct dentry *old_dentry, struct path *new_dir,
7f207e10
AM
319 return 0;
320 return security_ops->path_link(old_dentry, new_dir, new_dentry);
321 }
322+EXPORT_SYMBOL(security_path_link);
323
324 int security_path_rename(struct path *old_dir, struct dentry *old_dentry,
325 struct path *new_dir, struct dentry *new_dentry)
2dfbb274 326@@ -426,6 +429,7 @@ int security_path_truncate(struct path *path)
7f207e10
AM
327 return 0;
328 return security_ops->path_truncate(path);
329 }
330+EXPORT_SYMBOL(security_path_truncate);
331
7eafdf33
AM
332 int security_path_chmod(struct path *path, umode_t mode)
333 {
2dfbb274 334@@ -433,6 +437,7 @@ int security_path_chmod(struct path *path, umode_t mode)
7f207e10 335 return 0;
7eafdf33 336 return security_ops->path_chmod(path, mode);
7f207e10
AM
337 }
338+EXPORT_SYMBOL(security_path_chmod);
339
340 int security_path_chown(struct path *path, uid_t uid, gid_t gid)
341 {
2dfbb274 342@@ -440,6 +445,7 @@ int security_path_chown(struct path *path, uid_t uid, gid_t gid)
7f207e10
AM
343 return 0;
344 return security_ops->path_chown(path, uid, gid);
345 }
346+EXPORT_SYMBOL(security_path_chown);
347
348 int security_path_chroot(struct path *path)
349 {
2dfbb274 350@@ -516,6 +522,7 @@ int security_inode_readlink(struct dentry *dentry)
7f207e10
AM
351 return 0;
352 return security_ops->inode_readlink(dentry);
353 }
354+EXPORT_SYMBOL(security_inode_readlink);
355
356 int security_inode_follow_link(struct dentry *dentry, struct nameidata *nd)
357 {
2dfbb274 358@@ -530,6 +537,7 @@ int security_inode_permission(struct inode *inode, int mask)
7f207e10 359 return 0;
1e00d052 360 return security_ops->inode_permission(inode, mask);
7f207e10
AM
361 }
362+EXPORT_SYMBOL(security_inode_permission);
363
1e00d052 364 int security_inode_setattr(struct dentry *dentry, struct iattr *attr)
7f207e10 365 {
2dfbb274 366@@ -645,6 +653,7 @@ int security_file_permission(struct file *file, int mask)
7f207e10
AM
367
368 return fsnotify_perm(file, mask);
369 }
370+EXPORT_SYMBOL(security_file_permission);
371
372 int security_file_alloc(struct file *file)
373 {
2dfbb274 374@@ -705,6 +714,7 @@ int security_mmap_file(struct file *file, unsigned long prot,
7f207e10
AM
375 return ret;
376 return ima_file_mmap(file, prot);
377 }
0c3ec466 378+EXPORT_SYMBOL(security_mmap_file);
7f207e10 379
0c3ec466
AM
380 int security_mmap_addr(unsigned long addr)
381 {
7f207e10
AM
382diff -urN /usr/share/empty/Documentation/ABI/testing/debugfs-aufs linux/Documentation/ABI/testing/debugfs-aufs
383--- /usr/share/empty/Documentation/ABI/testing/debugfs-aufs 1970-01-01 01:00:00.000000000 +0100
2dfbb274 384+++ linux/Documentation/ABI/testing/debugfs-aufs 2012-08-26 08:39:00.753841216 +0200
7f207e10
AM
385@@ -0,0 +1,37 @@
386+What: /debug/aufs/si_<id>/
387+Date: March 2009
388+Contact: J. R. Okajima <hooanon05@yahoo.co.jp>
389+Description:
390+ Under /debug/aufs, a directory named si_<id> is created
391+ per aufs mount, where <id> is a unique id generated
392+ internally.
1facf9fc 393+
7f207e10
AM
394+What: /debug/aufs/si_<id>/xib
395+Date: March 2009
396+Contact: J. R. Okajima <hooanon05@yahoo.co.jp>
397+Description:
398+ It shows the consumed blocks by xib (External Inode Number
399+ Bitmap), its block size and file size.
400+ When the aufs mount option 'noxino' is specified, it
401+ will be empty. About XINO files, see the aufs manual.
402+
403+What: /debug/aufs/si_<id>/xino0, xino1 ... xinoN
404+Date: March 2009
405+Contact: J. R. Okajima <hooanon05@yahoo.co.jp>
406+Description:
407+ It shows the consumed blocks by xino (External Inode Number
408+ Translation Table), its link count, block size and file
409+ size.
410+ When the aufs mount option 'noxino' is specified, it
411+ will be empty. About XINO files, see the aufs manual.
412+
413+What: /debug/aufs/si_<id>/xigen
414+Date: March 2009
415+Contact: J. R. Okajima <hooanon05@yahoo.co.jp>
416+Description:
417+ It shows the consumed blocks by xigen (External Inode
418+ Generation Table), its block size and file size.
419+ If CONFIG_AUFS_EXPORT is disabled, this entry will not
420+ be created.
421+ When the aufs mount option 'noxino' is specified, it
422+ will be empty. About XINO files, see the aufs manual.
423diff -urN /usr/share/empty/Documentation/ABI/testing/sysfs-aufs linux/Documentation/ABI/testing/sysfs-aufs
424--- /usr/share/empty/Documentation/ABI/testing/sysfs-aufs 1970-01-01 01:00:00.000000000 +0100
2dfbb274 425+++ linux/Documentation/ABI/testing/sysfs-aufs 2012-08-26 08:39:00.753841216 +0200
7f207e10
AM
426@@ -0,0 +1,24 @@
427+What: /sys/fs/aufs/si_<id>/
428+Date: March 2009
429+Contact: J. R. Okajima <hooanon05@yahoo.co.jp>
430+Description:
431+ Under /sys/fs/aufs, a directory named si_<id> is created
432+ per aufs mount, where <id> is a unique id generated
433+ internally.
434+
435+What: /sys/fs/aufs/si_<id>/br0, br1 ... brN
436+Date: March 2009
437+Contact: J. R. Okajima <hooanon05@yahoo.co.jp>
438+Description:
439+ It shows the abolute path of a member directory (which
440+ is called branch) in aufs, and its permission.
441+
442+What: /sys/fs/aufs/si_<id>/xi_path
443+Date: March 2009
444+Contact: J. R. Okajima <hooanon05@yahoo.co.jp>
445+Description:
446+ It shows the abolute path of XINO (External Inode Number
447+ Bitmap, Translation Table and Generation Table) file
448+ even if it is the default path.
449+ When the aufs mount option 'noxino' is specified, it
450+ will be empty. About XINO files, see the aufs manual.
53392da6
AM
451diff -urN /usr/share/empty/Documentation/filesystems/aufs/design/01intro.txt linux/Documentation/filesystems/aufs/design/01intro.txt
452--- /usr/share/empty/Documentation/filesystems/aufs/design/01intro.txt 1970-01-01 01:00:00.000000000 +0100
2dfbb274 453+++ linux/Documentation/filesystems/aufs/design/01intro.txt 2012-08-26 08:39:00.757174634 +0200
53392da6
AM
454@@ -0,0 +1,162 @@
455+
456+# Copyright (C) 2005-2011 Junjiro R. Okajima
457+#
458+# This program is free software; you can redistribute it and/or modify
459+# it under the terms of the GNU General Public License as published by
460+# the Free Software Foundation; either version 2 of the License, or
461+# (at your option) any later version.
462+#
463+# This program is distributed in the hope that it will be useful,
464+# but WITHOUT ANY WARRANTY; without even the implied warranty of
465+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
466+# GNU General Public License for more details.
467+#
468+# You should have received a copy of the GNU General Public License
469+# along with this program; if not, write to the Free Software
470+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
471+
472+Introduction
473+----------------------------------------
474+
475+aufs [ei ju: ef es] | [a u f s]
476+1. abbrev. for "advanced multi-layered unification filesystem".
477+2. abbrev. for "another unionfs".
478+3. abbrev. for "auf das" in German which means "on the" in English.
479+ Ex. "Butter aufs Brot"(G) means "butter onto bread"(E).
480+ But "Filesystem aufs Filesystem" is hard to understand.
481+
482+AUFS is a filesystem with features:
483+- multi layered stackable unification filesystem, the member directory
484+ is called as a branch.
485+- branch permission and attribute, 'readonly', 'real-readonly',
486+ 'readwrite', 'whiteout-able', 'link-able whiteout' and their
487+ combination.
488+- internal "file copy-on-write".
489+- logical deletion, whiteout.
490+- dynamic branch manipulation, adding, deleting and changing permission.
491+- allow bypassing aufs, user's direct branch access.
492+- external inode number translation table and bitmap which maintains the
493+ persistent aufs inode number.
494+- seekable directory, including NFS readdir.
495+- file mapping, mmap and sharing pages.
496+- pseudo-link, hardlink over branches.
497+- loopback mounted filesystem as a branch.
498+- several policies to select one among multiple writable branches.
499+- revert a single systemcall when an error occurs in aufs.
500+- and more...
501+
502+
503+Multi Layered Stackable Unification Filesystem
504+----------------------------------------------------------------------
505+Most people already knows what it is.
506+It is a filesystem which unifies several directories and provides a
507+merged single directory. When users access a file, the access will be
508+passed/re-directed/converted (sorry, I am not sure which English word is
509+correct) to the real file on the member filesystem. The member
510+filesystem is called 'lower filesystem' or 'branch' and has a mode
511+'readonly' and 'readwrite.' And the deletion for a file on the lower
512+readonly branch is handled by creating 'whiteout' on the upper writable
513+branch.
514+
515+On LKML, there have been discussions about UnionMount (Jan Blunck,
516+Bharata B Rao and Valerie Aurora) and Unionfs (Erez Zadok). They took
517+different approaches to implement the merged-view.
518+The former tries putting it into VFS, and the latter implements as a
519+separate filesystem.
520+(If I misunderstand about these implementations, please let me know and
521+I shall correct it. Because it is a long time ago when I read their
522+source files last time).
523+
524+UnionMount's approach will be able to small, but may be hard to share
525+branches between several UnionMount since the whiteout in it is
526+implemented in the inode on branch filesystem and always
527+shared. According to Bharata's post, readdir does not seems to be
528+finished yet.
529+There are several missing features known in this implementations such as
530+- for users, the inode number may change silently. eg. copy-up.
531+- link(2) may break by copy-up.
532+- read(2) may get an obsoleted filedata (fstat(2) too).
533+- fcntl(F_SETLK) may be broken by copy-up.
534+- unnecessary copy-up may happen, for example mmap(MAP_PRIVATE) after
535+ open(O_RDWR).
536+
537+Unionfs has a longer history. When I started implementing a stacking filesystem
538+(Aug 2005), it already existed. It has virtual super_block, inode,
539+dentry and file objects and they have an array pointing lower same kind
540+objects. After contributing many patches for Unionfs, I re-started my
541+project AUFS (Jun 2006).
542+
543+In AUFS, the structure of filesystem resembles to Unionfs, but I
544+implemented my own ideas, approaches and enhancements and it became
545+totally different one.
546+
547+Comparing DM snapshot and fs based implementation
548+- the number of bytes to be copied between devices is much smaller.
549+- the type of filesystem must be one and only.
550+- the fs must be writable, no readonly fs, even for the lower original
551+ device. so the compression fs will not be usable. but if we use
552+ loopback mount, we may address this issue.
553+ for instance,
554+ mount /cdrom/squashfs.img /sq
555+ losetup /sq/ext2.img
556+ losetup /somewhere/cow
557+ dmsetup "snapshot /dev/loop0 /dev/loop1 ..."
558+- it will be difficult (or needs more operations) to extract the
559+ difference between the original device and COW.
560+- DM snapshot-merge may help a lot when users try merging. in the
561+ fs-layer union, users will use rsync(1).
562+
563+
564+Several characters/aspects of aufs
565+----------------------------------------------------------------------
566+
567+Aufs has several characters or aspects.
568+1. a filesystem, callee of VFS helper
569+2. sub-VFS, caller of VFS helper for branches
570+3. a virtual filesystem which maintains persistent inode number
571+4. reader/writer of files on branches such like an application
572+
573+1. Callee of VFS Helper
574+As an ordinary linux filesystem, aufs is a callee of VFS. For instance,
575+unlink(2) from an application reaches sys_unlink() kernel function and
576+then vfs_unlink() is called. vfs_unlink() is one of VFS helper and it
577+calls filesystem specific unlink operation. Actually aufs implements the
578+unlink operation but it behaves like a redirector.
579+
580+2. Caller of VFS Helper for Branches
581+aufs_unlink() passes the unlink request to the branch filesystem as if
582+it were called from VFS. So the called unlink operation of the branch
583+filesystem acts as usual. As a caller of VFS helper, aufs should handle
584+every necessary pre/post operation for the branch filesystem.
585+- acquire the lock for the parent dir on a branch
586+- lookup in a branch
587+- revalidate dentry on a branch
588+- mnt_want_write() for a branch
589+- vfs_unlink() for a branch
590+- mnt_drop_write() for a branch
591+- release the lock on a branch
592+
593+3. Persistent Inode Number
594+One of the most important issue for a filesystem is to maintain inode
595+numbers. This is particularly important to support exporting a
596+filesystem via NFS. Aufs is a virtual filesystem which doesn't have a
597+backend block device for its own. But some storage is necessary to
598+maintain inode number. It may be a large space and may not suit to keep
599+in memory. Aufs rents some space from its first writable branch
600+filesystem (by default) and creates file(s) on it. These files are
601+created by aufs internally and removed soon (currently) keeping opened.
602+Note: Because these files are removed, they are totally gone after
603+ unmounting aufs. It means the inode numbers are not persistent
604+ across unmount or reboot. I have a plan to make them really
605+ persistent which will be important for aufs on NFS server.
606+
607+4. Read/Write Files Internally (copy-on-write)
608+Because a branch can be readonly, when you write a file on it, aufs will
609+"copy-up" it to the upper writable branch internally. And then write the
610+originally requested thing to the file. Generally kernel doesn't
611+open/read/write file actively. In aufs, even a single write may cause a
612+internal "file copy". This behaviour is very similar to cp(1) command.
613+
614+Some people may think it is better to pass such work to user space
615+helper, instead of doing in kernel space. Actually I am still thinking
616+about it. But currently I have implemented it in kernel space.
617diff -urN /usr/share/empty/Documentation/filesystems/aufs/design/02struct.txt linux/Documentation/filesystems/aufs/design/02struct.txt
618--- /usr/share/empty/Documentation/filesystems/aufs/design/02struct.txt 1970-01-01 01:00:00.000000000 +0100
2dfbb274 619+++ linux/Documentation/filesystems/aufs/design/02struct.txt 2012-08-26 08:39:00.757174634 +0200
53392da6
AM
620@@ -0,0 +1,226 @@
621+
622+# Copyright (C) 2005-2011 Junjiro R. Okajima
623+#
624+# This program is free software; you can redistribute it and/or modify
625+# it under the terms of the GNU General Public License as published by
626+# the Free Software Foundation; either version 2 of the License, or
627+# (at your option) any later version.
628+#
629+# This program is distributed in the hope that it will be useful,
630+# but WITHOUT ANY WARRANTY; without even the implied warranty of
631+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
632+# GNU General Public License for more details.
633+#
634+# You should have received a copy of the GNU General Public License
635+# along with this program; if not, write to the Free Software
636+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
637+
638+Basic Aufs Internal Structure
639+
640+Superblock/Inode/Dentry/File Objects
641+----------------------------------------------------------------------
642+As like an ordinary filesystem, aufs has its own
643+superblock/inode/dentry/file objects. All these objects have a
644+dynamically allocated array and store the same kind of pointers to the
645+lower filesystem, branch.
646+For example, when you build a union with one readwrite branch and one
647+readonly, mounted /au, /rw and /ro respectively.
648+- /au = /rw + /ro
649+- /ro/fileA exists but /rw/fileA
650+
651+Aufs lookup operation finds /ro/fileA and gets dentry for that. These
652+pointers are stored in a aufs dentry. The array in aufs dentry will be,
653+- [0] = NULL
654+- [1] = /ro/fileA
655+
656+This style of an array is essentially same to the aufs
657+superblock/inode/dentry/file objects.
658+
659+Because aufs supports manipulating branches, ie. add/delete/change
660+dynamically, these objects has its own generation. When branches are
661+changed, the generation in aufs superblock is incremented. And a
662+generation in other object are compared when it is accessed.
663+When a generation in other objects are obsoleted, aufs refreshes the
664+internal array.
665+
666+
667+Superblock
668+----------------------------------------------------------------------
669+Additionally aufs superblock has some data for policies to select one
670+among multiple writable branches, XIB files, pseudo-links and kobject.
671+See below in detail.
672+About the policies which supports copy-down a directory, see policy.txt
673+too.
674+
675+
676+Branch and XINO(External Inode Number Translation Table)
677+----------------------------------------------------------------------
678+Every branch has its own xino (external inode number translation table)
679+file. The xino file is created and unlinked by aufs internally. When two
680+members of a union exist on the same filesystem, they share the single
681+xino file.
682+The struct of a xino file is simple, just a sequence of aufs inode
683+numbers which is indexed by the lower inode number.
684+In the above sample, assume the inode number of /ro/fileA is i111 and
685+aufs assigns the inode number i999 for fileA. Then aufs writes 999 as
686+4(8) bytes at 111 * 4(8) bytes offset in the xino file.
687+
688+When the inode numbers are not contiguous, the xino file will be sparse
689+which has a hole in it and doesn't consume as much disk space as it
690+might appear. If your branch filesystem consumes disk space for such
691+holes, then you should specify 'xino=' option at mounting aufs.
692+
693+Also a writable branch has three kinds of "whiteout bases". All these
694+are existed when the branch is joined to aufs and the names are
695+whiteout-ed doubly, so that users will never see their names in aufs
696+hierarchy.
697+1. a regular file which will be linked to all whiteouts.
698+2. a directory to store a pseudo-link.
699+3. a directory to store an "orphan-ed" file temporary.
700+
701+1. Whiteout Base
702+ When you remove a file on a readonly branch, aufs handles it as a
703+ logical deletion and creates a whiteout on the upper writable branch
704+ as a hardlink of this file in order not to consume inode on the
705+ writable branch.
706+2. Pseudo-link Dir
707+ See below, Pseudo-link.
708+3. Step-Parent Dir
709+ When "fileC" exists on the lower readonly branch only and it is
710+ opened and removed with its parent dir, and then user writes
711+ something into it, then aufs copies-up fileC to this
712+ directory. Because there is no other dir to store fileC. After
713+ creating a file under this dir, the file is unlinked.
714+
715+Because aufs supports manipulating branches, ie. add/delete/change
716+dynamically, a branch has its own id. When the branch order changes, aufs
717+finds the new index by searching the branch id.
718+
719+
720+Pseudo-link
721+----------------------------------------------------------------------
722+Assume "fileA" exists on the lower readonly branch only and it is
723+hardlinked to "fileB" on the branch. When you write something to fileA,
724+aufs copies-up it to the upper writable branch. Additionally aufs
725+creates a hardlink under the Pseudo-link Directory of the writable
726+branch. The inode of a pseudo-link is kept in aufs super_block as a
727+simple list. If fileB is read after unlinking fileA, aufs returns
728+filedata from the pseudo-link instead of the lower readonly
729+branch. Because the pseudo-link is based upon the inode, to keep the
730+inode number by xino (see above) is important.
731+
732+All the hardlinks under the Pseudo-link Directory of the writable branch
733+should be restored in a proper location later. Aufs provides a utility
734+to do this. The userspace helpers executed at remounting and unmounting
735+aufs by default.
736+During this utility is running, it puts aufs into the pseudo-link
737+maintenance mode. In this mode, only the process which began the
738+maintenance mode (and its child processes) is allowed to operate in
739+aufs. Some other processes which are not related to the pseudo-link will
740+be allowed to run too, but the rest have to return an error or wait
741+until the maintenance mode ends. If a process already acquires an inode
742+mutex (in VFS), it has to return an error.
743+
744+
745+XIB(external inode number bitmap)
746+----------------------------------------------------------------------
747+Addition to the xino file per a branch, aufs has an external inode number
748+bitmap in a superblock object. It is also a file such like a xino file.
749+It is a simple bitmap to mark whether the aufs inode number is in-use or
750+not.
751+To reduce the file I/O, aufs prepares a single memory page to cache xib.
752+
753+Aufs implements a feature to truncate/refresh both of xino and xib to
754+reduce the number of consumed disk blocks for these files.
755+
756+
757+Virtual or Vertical Dir, and Readdir in Userspace
758+----------------------------------------------------------------------
759+In order to support multiple layers (branches), aufs readdir operation
760+constructs a virtual dir block on memory. For readdir, aufs calls
761+vfs_readdir() internally for each dir on branches, merges their entries
762+with eliminating the whiteout-ed ones, and sets it to file (dir)
763+object. So the file object has its entry list until it is closed. The
764+entry list will be updated when the file position is zero and becomes
765+old. This decision is made in aufs automatically.
766+
767+The dynamically allocated memory block for the name of entries has a
768+unit of 512 bytes (by default) and stores the names contiguously (no
769+padding). Another block for each entry is handled by kmem_cache too.
770+During building dir blocks, aufs creates hash list and judging whether
771+the entry is whiteouted by its upper branch or already listed.
772+The merged result is cached in the corresponding inode object and
773+maintained by a customizable life-time option.
774+
775+Some people may call it can be a security hole or invite DoS attack
776+since the opened and once readdir-ed dir (file object) holds its entry
777+list and becomes a pressure for system memory. But I'd say it is similar
778+to files under /proc or /sys. The virtual files in them also holds a
779+memory page (generally) while they are opened. When an idea to reduce
780+memory for them is introduced, it will be applied to aufs too.
781+For those who really hate this situation, I've developed readdir(3)
782+library which operates this merging in userspace. You just need to set
783+LD_PRELOAD environment variable, and aufs will not consume no memory in
784+kernel space for readdir(3).
785+
786+
787+Workqueue
788+----------------------------------------------------------------------
789+Aufs sometimes requires privilege access to a branch. For instance,
790+in copy-up/down operation. When a user process is going to make changes
791+to a file which exists in the lower readonly branch only, and the mode
792+of one of ancestor directories may not be writable by a user
793+process. Here aufs copy-up the file with its ancestors and they may
794+require privilege to set its owner/group/mode/etc.
795+This is a typical case of a application character of aufs (see
796+Introduction).
797+
798+Aufs uses workqueue synchronously for this case. It creates its own
799+workqueue. The workqueue is a kernel thread and has privilege. Aufs
800+passes the request to call mkdir or write (for example), and wait for
801+its completion. This approach solves a problem of a signal handler
802+simply.
803+If aufs didn't adopt the workqueue and changed the privilege of the
804+process, and if the mkdir/write call arises SIGXFSZ or other signal,
805+then the user process might gain a privilege or the generated core file
806+was owned by a superuser.
807+
808+Also aufs uses the system global workqueue ("events" kernel thread) too
809+for asynchronous tasks, such like handling inotify/fsnotify, re-creating a
810+whiteout base and etc. This is unrelated to a privilege.
811+Most of aufs operation tries acquiring a rw_semaphore for aufs
812+superblock at the beginning, at the same time waits for the completion
813+of all queued asynchronous tasks.
814+
815+
816+Whiteout
817+----------------------------------------------------------------------
818+The whiteout in aufs is very similar to Unionfs's. That is represented
819+by its filename. UnionMount takes an approach of a file mode, but I am
820+afraid several utilities (find(1) or something) will have to support it.
821+
822+Basically the whiteout represents "logical deletion" which stops aufs to
823+lookup further, but also it represents "dir is opaque" which also stop
824+lookup.
825+
826+In aufs, rmdir(2) and rename(2) for dir uses whiteout alternatively.
827+In order to make several functions in a single systemcall to be
828+revertible, aufs adopts an approach to rename a directory to a temporary
829+unique whiteouted name.
830+For example, in rename(2) dir where the target dir already existed, aufs
831+renames the target dir to a temporary unique whiteouted name before the
832+actual rename on a branch and then handles other actions (make it opaque,
833+update the attributes, etc). If an error happens in these actions, aufs
834+simply renames the whiteouted name back and returns an error. If all are
835+succeeded, aufs registers a function to remove the whiteouted unique
836+temporary name completely and asynchronously to the system global
837+workqueue.
838+
839+
840+Copy-up
841+----------------------------------------------------------------------
842+It is a well-known feature or concept.
843+When user modifies a file on a readonly branch, aufs operate "copy-up"
844+internally and makes change to the new file on the upper writable branch.
845+When the trigger systemcall does not update the timestamps of the parent
846+dir, aufs reverts it after copy-up.
847diff -urN /usr/share/empty/Documentation/filesystems/aufs/design/03lookup.txt linux/Documentation/filesystems/aufs/design/03lookup.txt
848--- /usr/share/empty/Documentation/filesystems/aufs/design/03lookup.txt 1970-01-01 01:00:00.000000000 +0100
2dfbb274 849+++ linux/Documentation/filesystems/aufs/design/03lookup.txt 2012-08-26 08:39:00.757174634 +0200
53392da6
AM
850@@ -0,0 +1,106 @@
851+
852+# Copyright (C) 2005-2011 Junjiro R. Okajima
853+#
854+# This program is free software; you can redistribute it and/or modify
855+# it under the terms of the GNU General Public License as published by
856+# the Free Software Foundation; either version 2 of the License, or
857+# (at your option) any later version.
858+#
859+# This program is distributed in the hope that it will be useful,
860+# but WITHOUT ANY WARRANTY; without even the implied warranty of
861+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
862+# GNU General Public License for more details.
863+#
864+# You should have received a copy of the GNU General Public License
865+# along with this program; if not, write to the Free Software
866+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
867+
868+Lookup in a Branch
869+----------------------------------------------------------------------
870+Since aufs has a character of sub-VFS (see Introduction), it operates
871+lookup for branches as VFS does. It may be a heavy work. Generally
872+speaking struct nameidata is a bigger structure and includes many
873+information. But almost all lookup operation in aufs is the simplest
874+case, ie. lookup only an entry directly connected to its parent. Digging
875+down the directory hierarchy is unnecessary.
876+
877+VFS has a function lookup_one_len() for that use, but it is not usable
878+for a branch filesystem which requires struct nameidata. So aufs
879+implements a simple lookup wrapper function. When a branch filesystem
880+allows NULL as nameidata, it calls lookup_one_len(). Otherwise it builds
881+a simplest nameidata and calls lookup_hash().
882+Here aufs applies "a principle in NFSD", ie. if the filesystem supports
883+NFS-export, then it has to support NULL as a nameidata parameter for
884+->create(), ->lookup() and ->d_revalidate(). So the lookup wrapper in
885+aufs tests if ->s_export_op in the branch is NULL or not.
886+
887+When a branch is a remote filesystem, aufs basically trusts its
888+->d_revalidate(), also aufs forces the hardest revalidate tests for
889+them.
890+For d_revalidate, aufs implements three levels of revalidate tests. See
891+"Revalidate Dentry and UDBA" in detail.
892+
893+
894+Loopback Mount
895+----------------------------------------------------------------------
896+Basically aufs supports any type of filesystem and block device for a
897+branch (actually there are some exceptions). But it is prohibited to add
898+a loopback mounted one whose backend file exists in a filesystem which is
899+already added to aufs. The reason is to protect aufs from a recursive
900+lookup. If it was allowed, the aufs lookup operation might re-enter a
901+lookup for the loopback mounted branch in the same context, and will
902+cause a deadlock.
903+
904+
905+Revalidate Dentry and UDBA (User's Direct Branch Access)
906+----------------------------------------------------------------------
907+Generally VFS helpers re-validate a dentry as a part of lookup.
908+0. digging down the directory hierarchy.
909+1. lock the parent dir by its i_mutex.
910+2. lookup the final (child) entry.
911+3. revalidate it.
912+4. call the actual operation (create, unlink, etc.)
913+5. unlock the parent dir
914+
915+If the filesystem implements its ->d_revalidate() (step 3), then it is
916+called. Actually aufs implements it and checks the dentry on a branch is
917+still valid.
918+But it is not enough. Because aufs has to release the lock for the
919+parent dir on a branch at the end of ->lookup() (step 2) and
920+->d_revalidate() (step 3) while the i_mutex of the aufs dir is still
921+held by VFS.
922+If the file on a branch is changed directly, eg. bypassing aufs, after
923+aufs released the lock, then the subsequent operation may cause
924+something unpleasant result.
925+
926+This situation is a result of VFS architecture, ->lookup() and
927+->d_revalidate() is separated. But I never say it is wrong. It is a good
928+design from VFS's point of view. It is just not suitable for sub-VFS
929+character in aufs.
930+
931+Aufs supports such case by three level of revalidation which is
932+selectable by user.
933+1. Simple Revalidate
934+ Addition to the native flow in VFS's, confirm the child-parent
935+ relationship on the branch just after locking the parent dir on the
936+ branch in the "actual operation" (step 4). When this validation
937+ fails, aufs returns EBUSY. ->d_revalidate() (step 3) in aufs still
938+ checks the validation of the dentry on branches.
939+2. Monitor Changes Internally by Inotify/Fsnotify
940+ Addition to above, in the "actual operation" (step 4) aufs re-lookup
941+ the dentry on the branch, and returns EBUSY if it finds different
942+ dentry.
943+ Additionally, aufs sets the inotify/fsnotify watch for every dir on branches
944+ during it is in cache. When the event is notified, aufs registers a
945+ function to kernel 'events' thread by schedule_work(). And the
946+ function sets some special status to the cached aufs dentry and inode
947+ private data. If they are not cached, then aufs has nothing to
948+ do. When the same file is accessed through aufs (step 0-3) later,
949+ aufs will detect the status and refresh all necessary data.
950+ In this mode, aufs has to ignore the event which is fired by aufs
951+ itself.
952+3. No Extra Validation
953+ This is the simplest test and doesn't add any additional revalidation
954+ test, and skip therevalidatin in step 4. It is useful and improves
955+ aufs performance when system surely hide the aufs branches from user,
956+ by over-mounting something (or another method).
957diff -urN /usr/share/empty/Documentation/filesystems/aufs/design/04branch.txt linux/Documentation/filesystems/aufs/design/04branch.txt
958--- /usr/share/empty/Documentation/filesystems/aufs/design/04branch.txt 1970-01-01 01:00:00.000000000 +0100
2dfbb274 959+++ linux/Documentation/filesystems/aufs/design/04branch.txt 2012-08-26 08:39:00.757174634 +0200
53392da6
AM
960@@ -0,0 +1,76 @@
961+
962+# Copyright (C) 2005-2011 Junjiro R. Okajima
963+#
964+# This program is free software; you can redistribute it and/or modify
965+# it under the terms of the GNU General Public License as published by
966+# the Free Software Foundation; either version 2 of the License, or
967+# (at your option) any later version.
968+#
969+# This program is distributed in the hope that it will be useful,
970+# but WITHOUT ANY WARRANTY; without even the implied warranty of
971+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
972+# GNU General Public License for more details.
973+#
974+# You should have received a copy of the GNU General Public License
975+# along with this program; if not, write to the Free Software
976+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
977+
978+Branch Manipulation
979+
980+Since aufs supports dynamic branch manipulation, ie. add/remove a branch
981+and changing its permission/attribute, there are a lot of works to do.
982+
983+
984+Add a Branch
985+----------------------------------------------------------------------
986+o Confirm the adding dir exists outside of aufs, including loopback
987+ mount.
988+- and other various attributes...
989+o Initialize the xino file and whiteout bases if necessary.
990+ See struct.txt.
991+
992+o Check the owner/group/mode of the directory
993+ When the owner/group/mode of the adding directory differs from the
994+ existing branch, aufs issues a warning because it may impose a
995+ security risk.
996+ For example, when a upper writable branch has a world writable empty
997+ top directory, a malicious user can create any files on the writable
998+ branch directly, like copy-up and modify manually. If something like
999+ /etc/{passwd,shadow} exists on the lower readonly branch but the upper
1000+ writable branch, and the writable branch is world-writable, then a
1001+ malicious guy may create /etc/passwd on the writable branch directly
1002+ and the infected file will be valid in aufs.
1003+ I am afraid it can be a security issue, but nothing to do except
1004+ producing a warning.
1005+
1006+
1007+Delete a Branch
1008+----------------------------------------------------------------------
1009+o Confirm the deleting branch is not busy
1010+ To be general, there is one merit to adopt "remount" interface to
1011+ manipulate branches. It is to discard caches. At deleting a branch,
1012+ aufs checks the still cached (and connected) dentries and inodes. If
1013+ there are any, then they are all in-use. An inode without its
1014+ corresponding dentry can be alive alone (for example, inotify/fsnotify case).
1015+
1016+ For the cached one, aufs checks whether the same named entry exists on
1017+ other branches.
1018+ If the cached one is a directory, because aufs provides a merged view
1019+ to users, as long as one dir is left on any branch aufs can show the
1020+ dir to users. In this case, the branch can be removed from aufs.
1021+ Otherwise aufs rejects deleting the branch.
1022+
1023+ If any file on the deleting branch is opened by aufs, then aufs
1024+ rejects deleting.
1025+
1026+
1027+Modify the Permission of a Branch
1028+----------------------------------------------------------------------
1029+o Re-initialize or remove the xino file and whiteout bases if necessary.
1030+ See struct.txt.
1031+
1032+o rw --> ro: Confirm the modifying branch is not busy
1033+ Aufs rejects the request if any of these conditions are true.
1034+ - a file on the branch is mmap-ed.
1035+ - a regular file on the branch is opened for write and there is no
1036+ same named entry on the upper branch.
1037diff -urN /usr/share/empty/Documentation/filesystems/aufs/design/05wbr_policy.txt linux/Documentation/filesystems/aufs/design/05wbr_policy.txt
1038--- /usr/share/empty/Documentation/filesystems/aufs/design/05wbr_policy.txt 1970-01-01 01:00:00.000000000 +0100
2dfbb274 1039+++ linux/Documentation/filesystems/aufs/design/05wbr_policy.txt 2012-08-26 08:39:00.757174634 +0200
53392da6
AM
1040@@ -0,0 +1,65 @@
1041+
1042+# Copyright (C) 2005-2011 Junjiro R. Okajima
1043+#
1044+# This program is free software; you can redistribute it and/or modify
1045+# it under the terms of the GNU General Public License as published by
1046+# the Free Software Foundation; either version 2 of the License, or
1047+# (at your option) any later version.
1048+#
1049+# This program is distributed in the hope that it will be useful,
1050+# but WITHOUT ANY WARRANTY; without even the implied warranty of
1051+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1052+# GNU General Public License for more details.
1053+#
1054+# You should have received a copy of the GNU General Public License
1055+# along with this program; if not, write to the Free Software
1056+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1057+
1058+Policies to Select One among Multiple Writable Branches
1059+----------------------------------------------------------------------
1060+When the number of writable branch is more than one, aufs has to decide
1061+the target branch for file creation or copy-up. By default, the highest
1062+writable branch which has the parent (or ancestor) dir of the target
1063+file is chosen (top-down-parent policy).
1064+By user's request, aufs implements some other policies to select the
1065+writable branch, for file creation two policies, round-robin and
1066+most-free-space policies. For copy-up three policies, top-down-parent,
1067+bottom-up-parent and bottom-up policies.
1068+
1069+As expected, the round-robin policy selects the branch in circular. When
1070+you have two writable branches and creates 10 new files, 5 files will be
1071+created for each branch. mkdir(2) systemcall is an exception. When you
1072+create 10 new directories, all will be created on the same branch.
1073+And the most-free-space policy selects the one which has most free
1074+space among the writable branches. The amount of free space will be
1075+checked by aufs internally, and users can specify its time interval.
1076+
1077+The policies for copy-up is more simple,
1078+top-down-parent is equivalent to the same named on in create policy,
1079+bottom-up-parent selects the writable branch where the parent dir
1080+exists and the nearest upper one from the copyup-source,
1081+bottom-up selects the nearest upper writable branch from the
1082+copyup-source, regardless the existence of the parent dir.
1083+
1084+There are some rules or exceptions to apply these policies.
1085+- If there is a readonly branch above the policy-selected branch and
1086+ the parent dir is marked as opaque (a variation of whiteout), or the
1087+ target (creating) file is whiteout-ed on the upper readonly branch,
1088+ then the result of the policy is ignored and the target file will be
1089+ created on the nearest upper writable branch than the readonly branch.
1090+- If there is a writable branch above the policy-selected branch and
1091+ the parent dir is marked as opaque or the target file is whiteouted
1092+ on the branch, then the result of the policy is ignored and the target
1093+ file will be created on the highest one among the upper writable
1094+ branches who has diropq or whiteout. In case of whiteout, aufs removes
1095+ it as usual.
1096+- link(2) and rename(2) systemcalls are exceptions in every policy.
1097+ They try selecting the branch where the source exists as possible
1098+ since copyup a large file will take long time. If it can't be,
1099+ ie. the branch where the source exists is readonly, then they will
1100+ follow the copyup policy.
1101+- There is an exception for rename(2) when the target exists.
1102+ If the rename target exists, aufs compares the index of the branches
1103+ where the source and the target exists and selects the higher
1104+ one. If the selected branch is readonly, then aufs follows the
1105+ copyup policy.
1106diff -urN /usr/share/empty/Documentation/filesystems/aufs/design/06mmap.txt linux/Documentation/filesystems/aufs/design/06mmap.txt
1107--- /usr/share/empty/Documentation/filesystems/aufs/design/06mmap.txt 1970-01-01 01:00:00.000000000 +0100
2dfbb274 1108+++ linux/Documentation/filesystems/aufs/design/06mmap.txt 2012-08-26 08:39:00.757174634 +0200
53392da6
AM
1109@@ -0,0 +1,47 @@
1110+
1111+# Copyright (C) 2005-2011 Junjiro R. Okajima
1112+#
1113+# This program is free software; you can redistribute it and/or modify
1114+# it under the terms of the GNU General Public License as published by
1115+# the Free Software Foundation; either version 2 of the License, or
1116+# (at your option) any later version.
1117+#
1118+# This program is distributed in the hope that it will be useful,
1119+# but WITHOUT ANY WARRANTY; without even the implied warranty of
1120+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1121+# GNU General Public License for more details.
1122+#
1123+# You should have received a copy of the GNU General Public License
1124+# along with this program; if not, write to the Free Software
1125+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1126+
1127+mmap(2) -- File Memory Mapping
1128+----------------------------------------------------------------------
1129+In aufs, the file-mapped pages are handled by a branch fs directly, no
1130+interaction with aufs. It means aufs_mmap() calls the branch fs's
1131+->mmap().
1132+This approach is simple and good, but there is one problem.
1133+Under /proc, several entries show the mmap-ped files by its path (with
1134+device and inode number), and the printed path will be the path on the
1135+branch fs's instead of virtual aufs's.
1136+This is not a problem in most cases, but some utilities lsof(1) (and its
1137+user) may expect the path on aufs.
1138+
1139+To address this issue, aufs adds a new member called vm_prfile in struct
1140+vm_area_struct (and struct vm_region). The original vm_file points to
1141+the file on the branch fs in order to handle everything correctly as
1142+usual. The new vm_prfile points to a virtual file in aufs, and the
1143+show-functions in procfs refers to vm_prfile if it is set.
1144+Also we need to maintain several other places where touching vm_file
1145+such like
1146+- fork()/clone() copies vma and the reference count of vm_file is
1147+ incremented.
1148+- merging vma maintains the ref count too.
1149+
1150+This is not a good approach. It just faking the printed path. But it
1151+leaves all behaviour around f_mapping unchanged. This is surely an
1152+advantage.
1153+Actually aufs had adopted another complicated approach which calls
1154+generic_file_mmap() and handles struct vm_operations_struct. In this
1155+approach, aufs met a hard problem and I could not solve it without
1156+switching the approach.
1157diff -urN /usr/share/empty/Documentation/filesystems/aufs/design/07export.txt linux/Documentation/filesystems/aufs/design/07export.txt
1158--- /usr/share/empty/Documentation/filesystems/aufs/design/07export.txt 1970-01-01 01:00:00.000000000 +0100
2dfbb274 1159+++ linux/Documentation/filesystems/aufs/design/07export.txt 2012-08-26 08:39:00.757174634 +0200
53392da6
AM
1160@@ -0,0 +1,59 @@
1161+
1162+# Copyright (C) 2005-2011 Junjiro R. Okajima
1163+#
1164+# This program is free software; you can redistribute it and/or modify
1165+# it under the terms of the GNU General Public License as published by
1166+# the Free Software Foundation; either version 2 of the License, or
1167+# (at your option) any later version.
1168+#
1169+# This program is distributed in the hope that it will be useful,
1170+# but WITHOUT ANY WARRANTY; without even the implied warranty of
1171+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1172+# GNU General Public License for more details.
1173+#
1174+# You should have received a copy of the GNU General Public License
1175+# along with this program; if not, write to the Free Software
1176+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1177+
1178+Export Aufs via NFS
1179+----------------------------------------------------------------------
1180+Here is an approach.
1181+- like xino/xib, add a new file 'xigen' which stores aufs inode
1182+ generation.
1183+- iget_locked(): initialize aufs inode generation for a new inode, and
1184+ store it in xigen file.
1185+- destroy_inode(): increment aufs inode generation and store it in xigen
1186+ file. it is necessary even if it is not unlinked, because any data of
1187+ inode may be changed by UDBA.
1188+- encode_fh(): for a root dir, simply return FILEID_ROOT. otherwise
1189+ build file handle by
1190+ + branch id (4 bytes)
1191+ + superblock generation (4 bytes)
1192+ + inode number (4 or 8 bytes)
1193+ + parent dir inode number (4 or 8 bytes)
1194+ + inode generation (4 bytes))
1195+ + return value of exportfs_encode_fh() for the parent on a branch (4
1196+ bytes)
1197+ + file handle for a branch (by exportfs_encode_fh())
1198+- fh_to_dentry():
1199+ + find the index of a branch from its id in handle, and check it is
1200+ still exist in aufs.
1201+ + 1st level: get the inode number from handle and search it in cache.
1202+ + 2nd level: if not found, get the parent inode number from handle and
1203+ search it in cache. and then open the parent dir, find the matching
1204+ inode number by vfs_readdir() and get its name, and call
1205+ lookup_one_len() for the target dentry.
1206+ + 3rd level: if the parent dir is not cached, call
1207+ exportfs_decode_fh() for a branch and get the parent on a branch,
1208+ build a pathname of it, convert it a pathname in aufs, call
1209+ path_lookup(). now aufs gets a parent dir dentry, then handle it as
1210+ the 2nd level.
1211+ + to open the dir, aufs needs struct vfsmount. aufs keeps vfsmount
1212+ for every branch, but not itself. to get this, (currently) aufs
1213+ searches in current->nsproxy->mnt_ns list. it may not be a good
1214+ idea, but I didn't get other approach.
1215+ + test the generation of the gotten inode.
1216+- every inode operation: they may get EBUSY due to UDBA. in this case,
1217+ convert it into ESTALE for NFSD.
1218+- readdir(): call lockdep_on/off() because filldir in NFSD calls
1219+ lookup_one_len(), vfs_getattr(), encode_fh() and others.
1220diff -urN /usr/share/empty/Documentation/filesystems/aufs/design/08shwh.txt linux/Documentation/filesystems/aufs/design/08shwh.txt
1221--- /usr/share/empty/Documentation/filesystems/aufs/design/08shwh.txt 1970-01-01 01:00:00.000000000 +0100
2dfbb274 1222+++ linux/Documentation/filesystems/aufs/design/08shwh.txt 2012-08-26 08:39:00.757174634 +0200
53392da6
AM
1223@@ -0,0 +1,53 @@
1224+
1225+# Copyright (C) 2005-2011 Junjiro R. Okajima
1226+#
1227+# This program is free software; you can redistribute it and/or modify
1228+# it under the terms of the GNU General Public License as published by
1229+# the Free Software Foundation; either version 2 of the License, or
1230+# (at your option) any later version.
1231+#
1232+# This program is distributed in the hope that it will be useful,
1233+# but WITHOUT ANY WARRANTY; without even the implied warranty of
1234+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1235+# GNU General Public License for more details.
1236+#
1237+# You should have received a copy of the GNU General Public License
1238+# along with this program; if not, write to the Free Software
1239+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1240+
1241+Show Whiteout Mode (shwh)
1242+----------------------------------------------------------------------
1243+Generally aufs hides the name of whiteouts. But in some cases, to show
1244+them is very useful for users. For instance, creating a new middle layer
1245+(branch) by merging existing layers.
1246+
1247+(borrowing aufs1 HOW-TO from a user, Michael Towers)
1248+When you have three branches,
1249+- Bottom: 'system', squashfs (underlying base system), read-only
1250+- Middle: 'mods', squashfs, read-only
1251+- Top: 'overlay', ram (tmpfs), read-write
1252+
1253+The top layer is loaded at boot time and saved at shutdown, to preserve
1254+the changes made to the system during the session.
1255+When larger changes have been made, or smaller changes have accumulated,
1256+the size of the saved top layer data grows. At this point, it would be
1257+nice to be able to merge the two overlay branches ('mods' and 'overlay')
1258+and rewrite the 'mods' squashfs, clearing the top layer and thus
1259+restoring save and load speed.
1260+
1261+This merging is simplified by the use of another aufs mount, of just the
1262+two overlay branches using the 'shwh' option.
1263+# mount -t aufs -o ro,shwh,br:/livesys/overlay=ro+wh:/livesys/mods=rr+wh \
1264+ aufs /livesys/merge_union
1265+
1266+A merged view of these two branches is then available at
1267+/livesys/merge_union, and the new feature is that the whiteouts are
1268+visible!
1269+Note that in 'shwh' mode the aufs mount must be 'ro', which will disable
1270+writing to all branches. Also the default mode for all branches is 'ro'.
1271+It is now possible to save the combined contents of the two overlay
1272+branches to a new squashfs, e.g.:
1273+# mksquashfs /livesys/merge_union /path/to/newmods.squash
1274+
1275+This new squashfs archive can be stored on the boot device and the
1276+initramfs will use it to replace the old one at the next boot.
1277diff -urN /usr/share/empty/Documentation/filesystems/aufs/design/10dynop.txt linux/Documentation/filesystems/aufs/design/10dynop.txt
1278--- /usr/share/empty/Documentation/filesystems/aufs/design/10dynop.txt 1970-01-01 01:00:00.000000000 +0100
2dfbb274 1279+++ linux/Documentation/filesystems/aufs/design/10dynop.txt 2012-08-26 08:39:00.757174634 +0200
53392da6
AM
1280@@ -0,0 +1,47 @@
1281+
1282+# Copyright (C) 2010-2011 Junjiro R. Okajima
1283+#
1284+# This program is free software; you can redistribute it and/or modify
1285+# it under the terms of the GNU General Public License as published by
1286+# the Free Software Foundation; either version 2 of the License, or
1287+# (at your option) any later version.
1288+#
1289+# This program is distributed in the hope that it will be useful,
1290+# but WITHOUT ANY WARRANTY; without even the implied warranty of
1291+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1292+# GNU General Public License for more details.
1293+#
1294+# You should have received a copy of the GNU General Public License
1295+# along with this program; if not, write to the Free Software
1296+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1297+
1298+Dynamically customizable FS operations
1299+----------------------------------------------------------------------
1300+Generally FS operations (struct inode_operations, struct
1301+address_space_operations, struct file_operations, etc.) are defined as
1302+"static const", but it never means that FS have only one set of
1303+operation. Some FS have multiple sets of them. For instance, ext2 has
1304+three sets, one for XIP, for NOBH, and for normal.
1305+Since aufs overrides and redirects these operations, sometimes aufs has
1306+to change its behaviour according to the branch FS type. More imporantly
1307+VFS acts differently if a function (member in the struct) is set or
1308+not. It means aufs should have several sets of operations and select one
1309+among them according to the branch FS definition.
1310+
1311+In order to solve this problem and not to affect the behavour of VFS,
1312+aufs defines these operations dynamically. For instance, aufs defines
1313+aio_read function for struct file_operations, but it may not be set to
1314+the file_operations. When the branch FS doesn't have it, aufs doesn't
1315+set it to its file_operations while the function definition itself is
1316+still alive. So the behaviour of io_submit(2) will not change, and it
1317+will return an error when aio_read is not defined.
1318+
1319+The lifetime of these dynamically generated operation object is
1320+maintained by aufs branch object. When the branch is removed from aufs,
1321+the reference counter of the object is decremented. When it reaches
1322+zero, the dynamically generated operation object will be freed.
1323+
1324+This approach is designed to support AIO (io_submit), Direcit I/O and
1325+XIP mainly.
1326+Currently this approach is applied to file_operations and
1327+vm_operations_struct for regular files only.
1328diff -urN /usr/share/empty/Documentation/filesystems/aufs/design/99plan.txt linux/Documentation/filesystems/aufs/design/99plan.txt
1329--- /usr/share/empty/Documentation/filesystems/aufs/design/99plan.txt 1970-01-01 01:00:00.000000000 +0100
2dfbb274 1330+++ linux/Documentation/filesystems/aufs/design/99plan.txt 2012-08-26 08:39:00.757174634 +0200
53392da6
AM
1331@@ -0,0 +1,96 @@
1332+
1333+# Copyright (C) 2005-2011 Junjiro R. Okajima
1334+#
1335+# This program is free software; you can redistribute it and/or modify
1336+# it under the terms of the GNU General Public License as published by
1337+# the Free Software Foundation; either version 2 of the License, or
1338+# (at your option) any later version.
1339+#
1340+# This program is distributed in the hope that it will be useful,
1341+# but WITHOUT ANY WARRANTY; without even the implied warranty of
1342+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1343+# GNU General Public License for more details.
1344+#
1345+# You should have received a copy of the GNU General Public License
1346+# along with this program; if not, write to the Free Software
1347+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1348+
1349+Plan
1350+
1351+Restoring some features which was implemented in aufs1.
1352+They were dropped in aufs2 in order to make source files simpler and
1353+easier to be reviewed.
1354+
1355+
1356+Test Only the Highest One for the Directory Permission (dirperm1 option)
1357+----------------------------------------------------------------------
1358+Let's try case study.
1359+- aufs has two branches, upper readwrite and lower readonly.
1360+ /au = /rw + /ro
1361+- "dirA" exists under /ro, but /rw. and its mode is 0700.
1362+- user invoked "chmod a+rx /au/dirA"
1363+- then "dirA" becomes world readable?
1364+
1365+In this case, /ro/dirA is still 0700 since it exists in readonly branch,
1366+or it may be a natively readonly filesystem. If aufs respects the lower
1367+branch, it should not respond readdir request from other users. But user
1368+allowed it by chmod. Should really aufs rejects showing the entries
1369+under /ro/dirA?
1370+
1371+To be honest, I don't have a best solution for this case. So I
1372+implemented 'dirperm1' and 'nodirperm1' option in aufs1, and leave it to
1373+users.
1374+When dirperm1 is specified, aufs checks only the highest one for the
1375+directory permission, and shows the entries. Otherwise, as usual, checks
1376+every dir existing on all branches and rejects the request.
1377+
1378+As a side effect, dirperm1 option improves the performance of aufs
1379+because the number of permission check is reduced.
1380+
1381+
1382+Being Another Aufs's Readonly Branch (robr)
1383+----------------------------------------------------------------------
1384+Aufs1 allows aufs to be another aufs's readonly branch.
1385+This feature was developed by a user's request. But it may not be used
1386+currecnly.
1387+
1388+
1389+Copy-up on Open (coo=)
1390+----------------------------------------------------------------------
1391+By default the internal copy-up is executed when it is really necessary.
1392+It is not done when a file is opened for writing, but when write(2) is
1393+done. Users who have many (over 100) branches want to know and analyse
1394+when and what file is copied-up. To insert a new upper branch which
1395+contains such files only may improve the performance of aufs.
1396+
1397+Aufs1 implemented "coo=none | leaf | all" option.
1398+
1399+
1400+Refresh the Opened File (refrof)
1401+----------------------------------------------------------------------
1402+This option is implemented in aufs1 but incomplete.
1403+
1404+When user reads from a file, he expects to get its latest filedata
1405+generally. If the file is removed and a new same named file is created,
1406+the content he gets is unchanged, ie. the unlinked filedata.
1407+
1408+Let's try case study again.
1409+- aufs has two branches.
1410+ /au = /rw + /ro
1411+- "fileA" exists under /ro, but /rw.
1412+- user opened "/au/fileA".
1413+- he or someone else inserts a branch (/new) between /rw and /ro.
1414+ /au = /rw + /new + /ro
1415+- the new branch has "fileA".
1416+- user reads from the opened "fileA"
1417+- which filedata should aufs return, from /ro or /new?
1418+
1419+Some people says it has to be "from /ro" and it is a semantics of Unix.
1420+The others say it should be "from /new" because the file is not removed
1421+and it is equivalent to the case of someone else modifies the file.
1422+
1423+Here again I don't have a best and final answer. I got an idea to
1424+implement 'refrof' and 'norefrof' option. When 'refrof' (REFResh the
1425+Opened File) is specified (by default), aufs returns the filedata from
1426+/new.
1427+Otherwise from /new.
1428diff -urN /usr/share/empty/Documentation/filesystems/aufs/README linux/Documentation/filesystems/aufs/README
1429--- /usr/share/empty/Documentation/filesystems/aufs/README 1970-01-01 01:00:00.000000000 +0100
b4510431
AM
1430+++ linux/Documentation/filesystems/aufs/README 2012-10-05 20:51:16.675326257 +0200
1431@@ -0,0 +1,332 @@
53392da6
AM
1432+
1433+Aufs3 -- advanced multi layered unification filesystem version 3.x
1434+http://aufs.sf.net
1435+Junjiro R. Okajima
1436+
1437+
1438+0. Introduction
1439+----------------------------------------
1440+In the early days, aufs was entirely re-designed and re-implemented
1441+Unionfs Version 1.x series. After many original ideas, approaches,
1442+improvements and implementations, it becomes totally different from
1443+Unionfs while keeping the basic features.
1444+Recently, Unionfs Version 2.x series begin taking some of the same
1445+approaches to aufs1's.
1446+Unionfs is being developed by Professor Erez Zadok at Stony Brook
1447+University and his team.
1448+
1449+Aufs3 supports linux-3.0 and later.
1450+If you want older kernel version support, try aufs2-2.6.git or
1451+aufs2-standalone.git repository, aufs1 from CVS on SourceForge.
1452+
1453+Note: it becomes clear that "Aufs was rejected. Let's give it up."
1454+According to Christoph Hellwig, linux rejects all union-type filesystems
1455+but UnionMount.
1456+<http://marc.info/?l=linux-kernel&m=123938533724484&w=2>
1457+
1458+
1459+1. Features
1460+----------------------------------------
1461+- unite several directories into a single virtual filesystem. The member
1462+ directory is called as a branch.
1463+- you can specify the permission flags to the branch, which are 'readonly',
1464+ 'readwrite' and 'whiteout-able.'
1465+- by upper writable branch, internal copyup and whiteout, files/dirs on
1466+ readonly branch are modifiable logically.
1467+- dynamic branch manipulation, add, del.
1468+- etc...
1469+
1470+Also there are many enhancements in aufs1, such as:
1471+- readdir(3) in userspace.
1472+- keep inode number by external inode number table
1473+- keep the timestamps of file/dir in internal copyup operation
1474+- seekable directory, supporting NFS readdir.
1475+- whiteout is hardlinked in order to reduce the consumption of inodes
1476+ on branch
1477+- do not copyup, nor create a whiteout when it is unnecessary
1478+- revert a single systemcall when an error occurs in aufs
1479+- remount interface instead of ioctl
1480+- maintain /etc/mtab by an external command, /sbin/mount.aufs.
1481+- loopback mounted filesystem as a branch
1482+- kernel thread for removing the dir who has a plenty of whiteouts
1483+- support copyup sparse file (a file which has a 'hole' in it)
1484+- default permission flags for branches
1485+- selectable permission flags for ro branch, whether whiteout can
1486+ exist or not
1487+- export via NFS.
1488+- support <sysfs>/fs/aufs and <debugfs>/aufs.
1489+- support multiple writable branches, some policies to select one
1490+ among multiple writable branches.
1491+- a new semantics for link(2) and rename(2) to support multiple
1492+ writable branches.
1493+- no glibc changes are required.
1494+- pseudo hardlink (hardlink over branches)
1495+- allow a direct access manually to a file on branch, e.g. bypassing aufs.
1496+ including NFS or remote filesystem branch.
1497+- userspace wrapper for pathconf(3)/fpathconf(3) with _PC_LINK_MAX.
1498+- and more...
1499+
1500+Currently these features are dropped temporary from aufs3.
1501+See design/08plan.txt in detail.
1502+- test only the highest one for the directory permission (dirperm1)
1503+- copyup on open (coo=)
1504+- nested mount, i.e. aufs as readonly no-whiteout branch of another aufs
1505+ (robr)
1506+- statistics of aufs thread (/sys/fs/aufs/stat)
1507+- delegation mode (dlgt)
1508+ a delegation of the internal branch access to support task I/O
1509+ accounting, which also supports Linux Security Modules (LSM) mainly
1510+ for Suse AppArmor.
1511+- intent.open/create (file open in a single lookup)
1512+
1513+Features or just an idea in the future (see also design/*.txt),
1514+- reorder the branch index without del/re-add.
1515+- permanent xino files for NFSD
1516+- an option for refreshing the opened files after add/del branches
1517+- 'move' policy for copy-up between two writable branches, after
1518+ checking free space.
1519+- light version, without branch manipulation. (unnecessary?)
1520+- copyup in userspace
1521+- inotify in userspace
1522+- readv/writev
1523+- xattr, acl
1524+
1525+
1526+2. Download
1527+----------------------------------------
1e00d052
AM
1528+There were three GIT trees for aufs3, aufs3-linux.git,
1529+aufs3-standalone.git, and aufs-util.git. Note that there is no "3" in
1530+"aufs-util.git."
1531+While the aufs-util is always necessary, you need either of aufs3-linux
1532+or aufs3-standalone.
1533+
1534+The aufs3-linux tree includes the whole linux mainline GIT tree,
1535+git://git.kernel.org/.../torvalds/linux.git.
1536+And you cannot select CONFIG_AUFS_FS=m for this version, eg. you cannot
b4510431 1537+build aufs3 as an external kernel module.
1e00d052
AM
1538+
1539+On the other hand, the aufs3-standalone tree has only aufs source files
53392da6
AM
1540+and necessary patches, and you can select CONFIG_AUFS_FS=m.
1541+
1542+You will find GIT branches whose name is in form of "aufs3.x" where "x"
1543+represents the linux kernel version, "linux-3.x". For instance,
1e00d052
AM
1544+"aufs3.0" is for linux-3.0. For latest "linux-3.x-rcN", use
1545+"aufs3.x-rcN" branch.
1546+
1547+o aufs3-linux tree
1548+$ git clone --reference /your/linux/git/tree \
1549+ git://aufs.git.sourceforge.net/gitroot/aufs/aufs3-linux.git \
1550+ aufs3-linux.git
1551+- if you don't have linux GIT tree, then remove "--reference ..."
1552+$ cd aufs3-linux.git
1553+$ git checkout origin/aufs3.0
53392da6
AM
1554+
1555+o aufs3-standalone tree
1556+$ git clone git://aufs.git.sourceforge.net/gitroot/aufs/aufs3-standalone.git \
1557+ aufs3-standalone.git
1558+$ cd aufs3-standalone.git
1559+$ git checkout origin/aufs3.0
1560+
1561+o aufs-util tree
1562+$ git clone git://aufs.git.sourceforge.net/gitroot/aufs/aufs-util.git \
1563+ aufs-util.git
1564+$ cd aufs-util.git
1565+$ git checkout origin/aufs3.0
1566+
9dbd164d
AM
1567+Note: The 3.x-rcN branch is to be used with `rc' kernel versions ONLY.
1568+The minor version number, 'x' in '3.x', of aufs may not always
1569+follow the minor version number of the kernel.
1570+Because changes in the kernel that cause the use of a new
1571+minor version number do not always require changes to aufs-util.
1572+
1573+Since aufs-util has its own minor version number, you may not be
1574+able to find a GIT branch in aufs-util for your kernel's
1575+exact minor version number.
1576+In this case, you should git-checkout the branch for the
53392da6 1577+nearest lower number.
9dbd164d
AM
1578+
1579+For (an unreleased) example:
1580+If you are using "linux-3.10" and the "aufs3.10" branch
7eafdf33 1581+does not exist in aufs-util repository, then "aufs3.9", "aufs3.8"
9dbd164d
AM
1582+or something numerically smaller is the branch for your kernel.
1583+
53392da6
AM
1584+Also you can view all branches by
1585+ $ git branch -a
1586+
1587+
1588+3. Configuration and Compilation
1589+----------------------------------------
1590+Make sure you have git-checkout'ed the correct branch.
1591+
1e00d052
AM
1592+For aufs3-linux tree,
1593+- enable CONFIG_EXPERIMENTAL and CONFIG_AUFS_FS.
1594+- set other aufs configurations if necessary.
1595+
53392da6
AM
1596+For aufs3-standalone tree,
1597+There are several ways to build.
1598+
1599+1.
1600+- apply ./aufs3-kbuild.patch to your kernel source files.
1601+- apply ./aufs3-base.patch too.
1602+- apply ./aufs3-proc_map.patch too, if you want to make /proc/PID/maps (and
1603+ others including lsof(1)) show the file path on aufs instead of the
1604+ path on the branch fs.
1605+- apply ./aufs3-standalone.patch too, if you have a plan to set
1606+ CONFIG_AUFS_FS=m. otherwise you don't need ./aufs3-standalone.patch.
1607+- copy ./{Documentation,fs,include/linux/aufs_type.h} files to your
b4510431 1608+ kernel source tree. Never copy $PWD/include/linux/Kbuild.
53392da6
AM
1609+- enable CONFIG_EXPERIMENTAL and CONFIG_AUFS_FS, you can select either
1610+ =m or =y.
1611+- and build your kernel as usual.
1612+- install the built kernel.
7eafdf33
AM
1613+- install the header files too by "make headers_install" to the
1614+ directory where you specify. By default, it is $PWD/usr.
b4510431 1615+ "make help" shows a brief note for headers_install.
53392da6
AM
1616+- and reboot your system.
1617+
1618+2.
1619+- module only (CONFIG_AUFS_FS=m).
1620+- apply ./aufs3-base.patch to your kernel source files.
1621+- apply ./aufs3-proc_map.patch too to your kernel source files,
1622+ if you want to make /proc/PID/maps (and others including lsof(1)) show
1623+ the file path on aufs instead of the path on the branch fs.
1624+- apply ./aufs3-standalone.patch too.
1625+- build your kernel, don't forget "make headers_install", and reboot.
1626+- edit ./config.mk and set other aufs configurations if necessary.
b4510431 1627+ Note: You should read $PWD/fs/aufs/Kconfig carefully which describes
53392da6
AM
1628+ every aufs configurations.
1629+- build the module by simple "make".
1630+- you can specify ${KDIR} make variable which points to your kernel
1631+ source tree.
1632+- install the files
1633+ + run "make install" to install the aufs module, or copy the built
b4510431
AM
1634+ $PWD/aufs.ko to /lib/modules/... and run depmod -a (or reboot simply).
1635+ + run "make install_headers" (instead of headers_install) to install
1636+ the modified aufs header file (you can specify DESTDIR which is
1637+ available in aufs standalone version's Makefile only), or copy
1638+ $PWD/usr/include/linux/aufs_type.h to /usr/include/linux or wherever
1639+ you like manually. By default, the target directory is $PWD/usr.
53392da6
AM
1640+- no need to apply aufs3-kbuild.patch, nor copying source files to your
1641+ kernel source tree.
1642+
b4510431 1643+Note: The header file aufs_type.h is necessary to build aufs-util
53392da6
AM
1644+ as well as "make headers_install" in the kernel source tree.
1645+ headers_install is subject to be forgotten, but it is essentially
1646+ necessary, not only for building aufs-util.
1647+ You may not meet problems without headers_install in some older
1648+ version though.
1649+
1650+And then,
1651+- read README in aufs-util, build and install it
9dbd164d
AM
1652+- note that your distribution may contain an obsoleted version of
1653+ aufs_type.h in /usr/include/linux or something. When you build aufs
1654+ utilities, make sure that your compiler refers the correct aufs header
1655+ file which is built by "make headers_install."
53392da6
AM
1656+- if you want to use readdir(3) in userspace or pathconf(3) wrapper,
1657+ then run "make install_ulib" too. And refer to the aufs manual in
1658+ detail.
1659+
1660+
1661+4. Usage
1662+----------------------------------------
1663+At first, make sure aufs-util are installed, and please read the aufs
1664+manual, aufs.5 in aufs-util.git tree.
1665+$ man -l aufs.5
1666+
1667+And then,
1668+$ mkdir /tmp/rw /tmp/aufs
1669+# mount -t aufs -o br=/tmp/rw:${HOME} none /tmp/aufs
1670+
1671+Here is another example. The result is equivalent.
1672+# mount -t aufs -o br=/tmp/rw=rw:${HOME}=ro none /tmp/aufs
1673+ Or
1674+# mount -t aufs -o br:/tmp/rw none /tmp/aufs
1675+# mount -o remount,append:${HOME} /tmp/aufs
1676+
1677+Then, you can see whole tree of your home dir through /tmp/aufs. If
1678+you modify a file under /tmp/aufs, the one on your home directory is
1679+not affected, instead the same named file will be newly created under
1680+/tmp/rw. And all of your modification to a file will be applied to
1681+the one under /tmp/rw. This is called the file based Copy on Write
1682+(COW) method.
1683+Aufs mount options are described in aufs.5.
1684+If you run chroot or something and make your aufs as a root directory,
1685+then you need to customize the shutdown script. See the aufs manual in
1686+detail.
1687+
1688+Additionally, there are some sample usages of aufs which are a
1689+diskless system with network booting, and LiveCD over NFS.
1690+See sample dir in CVS tree on SourceForge.
1691+
1692+
1693+5. Contact
1694+----------------------------------------
1695+When you have any problems or strange behaviour in aufs, please let me
1696+know with:
1697+- /proc/mounts (instead of the output of mount(8))
1698+- /sys/module/aufs/*
1699+- /sys/fs/aufs/* (if you have them)
1700+- /debug/aufs/* (if you have them)
1701+- linux kernel version
1702+ if your kernel is not plain, for example modified by distributor,
1703+ the url where i can download its source is necessary too.
1704+- aufs version which was printed at loading the module or booting the
1705+ system, instead of the date you downloaded.
1706+- configuration (define/undefine CONFIG_AUFS_xxx)
1707+- kernel configuration or /proc/config.gz (if you have it)
1708+- behaviour which you think to be incorrect
1709+- actual operation, reproducible one is better
1710+- mailto: aufs-users at lists.sourceforge.net
1711+
1712+Usually, I don't watch the Public Areas(Bugs, Support Requests, Patches,
1713+and Feature Requests) on SourceForge. Please join and write to
1714+aufs-users ML.
1715+
1716+
1717+6. Acknowledgements
1718+----------------------------------------
1719+Thanks to everyone who have tried and are using aufs, whoever
1720+have reported a bug or any feedback.
1721+
1722+Especially donators:
1723+Tomas Matejicek(slax.org) made a donation (much more than once).
1724+ Since Apr 2010, Tomas M (the author of Slax and Linux Live
1725+ scripts) is making "doubling" donations.
1726+ Unfortunately I cannot list all of the donators, but I really
b4510431 1727+ appreciate.
53392da6
AM
1728+ It ends Aug 2010, but the ordinary donation URL is still available.
1729+ <http://sourceforge.net/donate/index.php?group_id=167503>
1730+Dai Itasaka made a donation (2007/8).
1731+Chuck Smith made a donation (2008/4, 10 and 12).
1732+Henk Schoneveld made a donation (2008/9).
1733+Chih-Wei Huang, ASUS, CTC donated Eee PC 4G (2008/10).
1734+Francois Dupoux made a donation (2008/11).
1735+Bruno Cesar Ribas and Luis Carlos Erpen de Bona, C3SL serves public
1736+ aufs2 GIT tree (2009/2).
1737+William Grant made a donation (2009/3).
1738+Patrick Lane made a donation (2009/4).
1739+The Mail Archive (mail-archive.com) made donations (2009/5).
1740+Nippy Networks (Ed Wildgoose) made a donation (2009/7).
1741+New Dream Network, LLC (www.dreamhost.com) made a donation (2009/11).
1742+Pavel Pronskiy made a donation (2011/2).
1743+Iridium and Inmarsat satellite phone retailer (www.mailasail.com), Nippy
1744+ Networks (Ed Wildgoose) made a donation for hardware (2011/3).
2dfbb274 1745+Max Lekomcev (DOM-TV project) made a donation (2011/7, 12 and 2012/3, 6).
1e00d052 1746+Sam Liddicott made a donation (2011/9).
53392da6
AM
1747+
1748+Thank you very much.
1749+Donations are always, including future donations, very important and
1750+helpful for me to keep on developing aufs.
1751+
1752+
1753+7.
1754+----------------------------------------
1755+If you are an experienced user, no explanation is needed. Aufs is
1756+just a linux filesystem.
1757+
1758+
1759+Enjoy!
1760+
1761+# Local variables: ;
1762+# mode: text;
1763+# End: ;
7f207e10
AM
1764diff -urN /usr/share/empty/fs/aufs/aufs.h linux/fs/aufs/aufs.h
1765--- /usr/share/empty/fs/aufs/aufs.h 1970-01-01 01:00:00.000000000 +0100
2dfbb274 1766+++ linux/fs/aufs/aufs.h 2012-08-26 08:39:00.757174634 +0200
2cbb1c4b 1767@@ -0,0 +1,60 @@
7f207e10 1768+/*
f6c5ef8b 1769+ * Copyright (C) 2005-2012 Junjiro R. Okajima
7f207e10
AM
1770+ *
1771+ * This program, aufs is free software; you can redistribute it and/or modify
1772+ * it under the terms of the GNU General Public License as published by
1773+ * the Free Software Foundation; either version 2 of the License, or
1774+ * (at your option) any later version.
1775+ *
1776+ * This program is distributed in the hope that it will be useful,
1777+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1778+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1779+ * GNU General Public License for more details.
1780+ *
1781+ * You should have received a copy of the GNU General Public License
1782+ * along with this program; if not, write to the Free Software
1783+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1784+ */
1785+
1786+/*
1787+ * all header files
1788+ */
1789+
1790+#ifndef __AUFS_H__
1791+#define __AUFS_H__
1792+
1793+#ifdef __KERNEL__
1794+
1795+#define AuStub(type, name, body, ...) \
1796+ static inline type name(__VA_ARGS__) { body; }
1797+
1798+#define AuStubVoid(name, ...) \
1799+ AuStub(void, name, , __VA_ARGS__)
1800+#define AuStubInt0(name, ...) \
1801+ AuStub(int, name, return 0, __VA_ARGS__)
1802+
1803+#include "debug.h"
1804+
1805+#include "branch.h"
1806+#include "cpup.h"
1807+#include "dcsub.h"
1808+#include "dbgaufs.h"
1809+#include "dentry.h"
1810+#include "dir.h"
1811+#include "dynop.h"
1812+#include "file.h"
1813+#include "fstype.h"
1814+#include "inode.h"
1815+#include "loop.h"
1816+#include "module.h"
7f207e10
AM
1817+#include "opts.h"
1818+#include "rwsem.h"
1819+#include "spl.h"
1820+#include "super.h"
1821+#include "sysaufs.h"
1822+#include "vfsub.h"
1823+#include "whout.h"
1824+#include "wkq.h"
1825+
1826+#endif /* __KERNEL__ */
1827+#endif /* __AUFS_H__ */
1828diff -urN /usr/share/empty/fs/aufs/branch.c linux/fs/aufs/branch.c
1829--- /usr/share/empty/fs/aufs/branch.c 1970-01-01 01:00:00.000000000 +0100
b4510431 1830+++ linux/fs/aufs/branch.c 2012-10-17 10:31:01.772481151 +0200
f6c5ef8b 1831@@ -0,0 +1,1169 @@
7f207e10 1832+/*
f6c5ef8b 1833+ * Copyright (C) 2005-2012 Junjiro R. Okajima
7f207e10
AM
1834+ *
1835+ * This program, aufs is free software; you can redistribute it and/or modify
1836+ * it under the terms of the GNU General Public License as published by
1837+ * the Free Software Foundation; either version 2 of the License, or
1838+ * (at your option) any later version.
1839+ *
1840+ * This program is distributed in the hope that it will be useful,
1841+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1842+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1843+ * GNU General Public License for more details.
1844+ *
1845+ * You should have received a copy of the GNU General Public License
1846+ * along with this program; if not, write to the Free Software
1847+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1848+ */
1849+
1850+/*
1851+ * branch management
1852+ */
1853+
027c5e7a 1854+#include <linux/compat.h>
7f207e10
AM
1855+#include <linux/statfs.h>
1856+#include "aufs.h"
1857+
1858+/*
1859+ * free a single branch
1facf9fc 1860+ */
1861+static void au_br_do_free(struct au_branch *br)
1862+{
1863+ int i;
1864+ struct au_wbr *wbr;
4a4d8108 1865+ struct au_dykey **key;
1facf9fc 1866+
027c5e7a
AM
1867+ au_hnotify_fin_br(br);
1868+
1facf9fc 1869+ if (br->br_xino.xi_file)
1870+ fput(br->br_xino.xi_file);
1871+ mutex_destroy(&br->br_xino.xi_nondir_mtx);
1872+
1873+ AuDebugOn(atomic_read(&br->br_count));
1874+
1875+ wbr = br->br_wbr;
1876+ if (wbr) {
1877+ for (i = 0; i < AuBrWh_Last; i++)
1878+ dput(wbr->wbr_wh[i]);
1879+ AuDebugOn(atomic_read(&wbr->wbr_wh_running));
dece6358 1880+ AuRwDestroy(&wbr->wbr_wh_rwsem);
1facf9fc 1881+ }
1882+
4a4d8108
AM
1883+ key = br->br_dykey;
1884+ for (i = 0; i < AuBrDynOp; i++, key++)
1885+ if (*key)
1886+ au_dy_put(*key);
1887+ else
1888+ break;
1889+
1facf9fc 1890+ mntput(br->br_mnt);
1facf9fc 1891+ kfree(wbr);
1892+ kfree(br);
1893+}
1894+
1895+/*
1896+ * frees all branches
1897+ */
1898+void au_br_free(struct au_sbinfo *sbinfo)
1899+{
1900+ aufs_bindex_t bmax;
1901+ struct au_branch **br;
1902+
dece6358
AM
1903+ AuRwMustWriteLock(&sbinfo->si_rwsem);
1904+
1facf9fc 1905+ bmax = sbinfo->si_bend + 1;
1906+ br = sbinfo->si_branch;
1907+ while (bmax--)
1908+ au_br_do_free(*br++);
1909+}
1910+
1911+/*
1912+ * find the index of a branch which is specified by @br_id.
1913+ */
1914+int au_br_index(struct super_block *sb, aufs_bindex_t br_id)
1915+{
1916+ aufs_bindex_t bindex, bend;
1917+
1918+ bend = au_sbend(sb);
1919+ for (bindex = 0; bindex <= bend; bindex++)
1920+ if (au_sbr_id(sb, bindex) == br_id)
1921+ return bindex;
1922+ return -1;
1923+}
1924+
1925+/* ---------------------------------------------------------------------- */
1926+
1927+/*
1928+ * add a branch
1929+ */
1930+
b752ccd1
AM
1931+static int test_overlap(struct super_block *sb, struct dentry *h_adding,
1932+ struct dentry *h_root)
1facf9fc 1933+{
b752ccd1
AM
1934+ if (unlikely(h_adding == h_root
1935+ || au_test_loopback_overlap(sb, h_adding)))
1facf9fc 1936+ return 1;
b752ccd1
AM
1937+ if (h_adding->d_sb != h_root->d_sb)
1938+ return 0;
1939+ return au_test_subdir(h_adding, h_root)
1940+ || au_test_subdir(h_root, h_adding);
1facf9fc 1941+}
1942+
1943+/*
1944+ * returns a newly allocated branch. @new_nbranch is a number of branches
1945+ * after adding a branch.
1946+ */
1947+static struct au_branch *au_br_alloc(struct super_block *sb, int new_nbranch,
1948+ int perm)
1949+{
1950+ struct au_branch *add_branch;
1951+ struct dentry *root;
4a4d8108 1952+ int err;
1facf9fc 1953+
4a4d8108 1954+ err = -ENOMEM;
1facf9fc 1955+ root = sb->s_root;
1956+ add_branch = kmalloc(sizeof(*add_branch), GFP_NOFS);
1957+ if (unlikely(!add_branch))
1958+ goto out;
1959+
027c5e7a
AM
1960+ err = au_hnotify_init_br(add_branch, perm);
1961+ if (unlikely(err))
1962+ goto out_br;
1963+
1facf9fc 1964+ add_branch->br_wbr = NULL;
1965+ if (au_br_writable(perm)) {
1966+ /* may be freed separately at changing the branch permission */
1967+ add_branch->br_wbr = kmalloc(sizeof(*add_branch->br_wbr),
1968+ GFP_NOFS);
1969+ if (unlikely(!add_branch->br_wbr))
027c5e7a 1970+ goto out_hnotify;
1facf9fc 1971+ }
1972+
4a4d8108
AM
1973+ err = au_sbr_realloc(au_sbi(sb), new_nbranch);
1974+ if (!err)
1975+ err = au_di_realloc(au_di(root), new_nbranch);
1976+ if (!err)
1977+ err = au_ii_realloc(au_ii(root->d_inode), new_nbranch);
1978+ if (!err)
1979+ return add_branch; /* success */
1facf9fc 1980+
1facf9fc 1981+ kfree(add_branch->br_wbr);
4a4d8108 1982+
027c5e7a
AM
1983+out_hnotify:
1984+ au_hnotify_fin_br(add_branch);
4f0767ce 1985+out_br:
1facf9fc 1986+ kfree(add_branch);
4f0767ce 1987+out:
4a4d8108 1988+ return ERR_PTR(err);
1facf9fc 1989+}
1990+
1991+/*
1992+ * test if the branch permission is legal or not.
1993+ */
1994+static int test_br(struct inode *inode, int brperm, char *path)
1995+{
1996+ int err;
1997+
4a4d8108
AM
1998+ err = (au_br_writable(brperm) && IS_RDONLY(inode));
1999+ if (!err)
2000+ goto out;
1facf9fc 2001+
4a4d8108
AM
2002+ err = -EINVAL;
2003+ pr_err("write permission for readonly mount or inode, %s\n", path);
2004+
4f0767ce 2005+out:
1facf9fc 2006+ return err;
2007+}
2008+
2009+/*
2010+ * returns:
2011+ * 0: success, the caller will add it
2012+ * plus: success, it is already unified, the caller should ignore it
2013+ * minus: error
2014+ */
2015+static int test_add(struct super_block *sb, struct au_opt_add *add, int remount)
2016+{
2017+ int err;
2018+ aufs_bindex_t bend, bindex;
2019+ struct dentry *root;
2020+ struct inode *inode, *h_inode;
2021+
2022+ root = sb->s_root;
2023+ bend = au_sbend(sb);
2024+ if (unlikely(bend >= 0
2025+ && au_find_dbindex(root, add->path.dentry) >= 0)) {
2026+ err = 1;
2027+ if (!remount) {
2028+ err = -EINVAL;
4a4d8108 2029+ pr_err("%s duplicated\n", add->pathname);
1facf9fc 2030+ }
2031+ goto out;
2032+ }
2033+
2034+ err = -ENOSPC; /* -E2BIG; */
2035+ if (unlikely(AUFS_BRANCH_MAX <= add->bindex
2036+ || AUFS_BRANCH_MAX - 1 <= bend)) {
4a4d8108 2037+ pr_err("number of branches exceeded %s\n", add->pathname);
1facf9fc 2038+ goto out;
2039+ }
2040+
2041+ err = -EDOM;
2042+ if (unlikely(add->bindex < 0 || bend + 1 < add->bindex)) {
4a4d8108 2043+ pr_err("bad index %d\n", add->bindex);
1facf9fc 2044+ goto out;
2045+ }
2046+
2047+ inode = add->path.dentry->d_inode;
2048+ err = -ENOENT;
2049+ if (unlikely(!inode->i_nlink)) {
4a4d8108 2050+ pr_err("no existence %s\n", add->pathname);
1facf9fc 2051+ goto out;
2052+ }
2053+
2054+ err = -EINVAL;
2055+ if (unlikely(inode->i_sb == sb)) {
4a4d8108 2056+ pr_err("%s must be outside\n", add->pathname);
1facf9fc 2057+ goto out;
2058+ }
2059+
2060+ if (unlikely(au_test_fs_unsuppoted(inode->i_sb))) {
4a4d8108
AM
2061+ pr_err("unsupported filesystem, %s (%s)\n",
2062+ add->pathname, au_sbtype(inode->i_sb));
1facf9fc 2063+ goto out;
2064+ }
2065+
2066+ err = test_br(add->path.dentry->d_inode, add->perm, add->pathname);
2067+ if (unlikely(err))
2068+ goto out;
2069+
2070+ if (bend < 0)
2071+ return 0; /* success */
2072+
2073+ err = -EINVAL;
2074+ for (bindex = 0; bindex <= bend; bindex++)
2075+ if (unlikely(test_overlap(sb, add->path.dentry,
2076+ au_h_dptr(root, bindex)))) {
4a4d8108 2077+ pr_err("%s is overlapped\n", add->pathname);
1facf9fc 2078+ goto out;
2079+ }
2080+
2081+ err = 0;
2082+ if (au_opt_test(au_mntflags(sb), WARN_PERM)) {
2083+ h_inode = au_h_dptr(root, 0)->d_inode;
2084+ if ((h_inode->i_mode & S_IALLUGO) != (inode->i_mode & S_IALLUGO)
0c3ec466
AM
2085+ || !uid_eq(h_inode->i_uid, inode->i_uid)
2086+ || !gid_eq(h_inode->i_gid, inode->i_gid))
2087+ pr_warn("uid/gid/perm %s %u/%u/0%o, %u/%u/0%o\n",
2088+ add->pathname,
2089+ i_uid_read(inode), i_gid_read(inode),
2090+ (inode->i_mode & S_IALLUGO),
2091+ i_uid_read(h_inode), i_gid_read(h_inode),
2092+ (h_inode->i_mode & S_IALLUGO));
1facf9fc 2093+ }
2094+
4f0767ce 2095+out:
1facf9fc 2096+ return err;
2097+}
2098+
2099+/*
2100+ * initialize or clean the whiteouts for an adding branch
2101+ */
2102+static int au_br_init_wh(struct super_block *sb, struct au_branch *br,
2103+ int new_perm, struct dentry *h_root)
2104+{
2105+ int err, old_perm;
2106+ aufs_bindex_t bindex;
2107+ struct mutex *h_mtx;
2108+ struct au_wbr *wbr;
2109+ struct au_hinode *hdir;
2110+
2111+ wbr = br->br_wbr;
2112+ old_perm = br->br_perm;
2113+ br->br_perm = new_perm;
2114+ hdir = NULL;
2115+ h_mtx = NULL;
2116+ bindex = au_br_index(sb, br->br_id);
2117+ if (0 <= bindex) {
2118+ hdir = au_hi(sb->s_root->d_inode, bindex);
4a4d8108 2119+ au_hn_imtx_lock_nested(hdir, AuLsc_I_PARENT);
1facf9fc 2120+ } else {
2121+ h_mtx = &h_root->d_inode->i_mutex;
2122+ mutex_lock_nested(h_mtx, AuLsc_I_PARENT);
2123+ }
2124+ if (!wbr)
2125+ err = au_wh_init(h_root, br, sb);
2126+ else {
2127+ wbr_wh_write_lock(wbr);
2128+ err = au_wh_init(h_root, br, sb);
2129+ wbr_wh_write_unlock(wbr);
2130+ }
2131+ if (hdir)
4a4d8108 2132+ au_hn_imtx_unlock(hdir);
1facf9fc 2133+ else
2134+ mutex_unlock(h_mtx);
2135+ br->br_perm = old_perm;
2136+
2137+ if (!err && wbr && !au_br_writable(new_perm)) {
2138+ kfree(wbr);
2139+ br->br_wbr = NULL;
2140+ }
2141+
2142+ return err;
2143+}
2144+
2145+static int au_wbr_init(struct au_branch *br, struct super_block *sb,
2146+ int perm, struct path *path)
2147+{
2148+ int err;
4a4d8108 2149+ struct kstatfs kst;
1facf9fc 2150+ struct au_wbr *wbr;
4a4d8108 2151+ struct dentry *h_dentry;
1facf9fc 2152+
2153+ wbr = br->br_wbr;
dece6358 2154+ au_rw_init(&wbr->wbr_wh_rwsem);
1facf9fc 2155+ memset(wbr->wbr_wh, 0, sizeof(wbr->wbr_wh));
2156+ atomic_set(&wbr->wbr_wh_running, 0);
2157+ wbr->wbr_bytes = 0;
2158+
4a4d8108
AM
2159+ /*
2160+ * a limit for rmdir/rename a dir
2161+ * cf. AUFS_MAX_NAMELEN in include/linux/aufs_type.h
2162+ */
7f207e10 2163+ err = vfs_statfs(path, &kst);
4a4d8108
AM
2164+ if (unlikely(err))
2165+ goto out;
2166+ err = -EINVAL;
7f207e10 2167+ h_dentry = path->dentry;
4a4d8108
AM
2168+ if (kst.f_namelen >= NAME_MAX)
2169+ err = au_br_init_wh(sb, br, perm, h_dentry);
2170+ else
2171+ pr_err("%.*s(%s), unsupported namelen %ld\n",
2172+ AuDLNPair(h_dentry), au_sbtype(h_dentry->d_sb),
2173+ kst.f_namelen);
1facf9fc 2174+
4f0767ce 2175+out:
1facf9fc 2176+ return err;
2177+}
2178+
2179+/* intialize a new branch */
2180+static int au_br_init(struct au_branch *br, struct super_block *sb,
2181+ struct au_opt_add *add)
2182+{
2183+ int err;
2184+
2185+ err = 0;
2186+ memset(&br->br_xino, 0, sizeof(br->br_xino));
2187+ mutex_init(&br->br_xino.xi_nondir_mtx);
2188+ br->br_perm = add->perm;
2189+ br->br_mnt = add->path.mnt; /* set first, mntget() later */
4a4d8108
AM
2190+ spin_lock_init(&br->br_dykey_lock);
2191+ memset(br->br_dykey, 0, sizeof(br->br_dykey));
1facf9fc 2192+ atomic_set(&br->br_count, 0);
2193+ br->br_xino_upper = AUFS_XINO_TRUNC_INIT;
2194+ atomic_set(&br->br_xino_running, 0);
2195+ br->br_id = au_new_br_id(sb);
7f207e10 2196+ AuDebugOn(br->br_id < 0);
1facf9fc 2197+
2198+ if (au_br_writable(add->perm)) {
2199+ err = au_wbr_init(br, sb, add->perm, &add->path);
2200+ if (unlikely(err))
b752ccd1 2201+ goto out_err;
1facf9fc 2202+ }
2203+
2204+ if (au_opt_test(au_mntflags(sb), XINO)) {
2205+ err = au_xino_br(sb, br, add->path.dentry->d_inode->i_ino,
2206+ au_sbr(sb, 0)->br_xino.xi_file, /*do_test*/1);
2207+ if (unlikely(err)) {
2208+ AuDebugOn(br->br_xino.xi_file);
b752ccd1 2209+ goto out_err;
1facf9fc 2210+ }
2211+ }
2212+
2213+ sysaufs_br_init(br);
2214+ mntget(add->path.mnt);
b752ccd1 2215+ goto out; /* success */
1facf9fc 2216+
4f0767ce 2217+out_err:
b752ccd1 2218+ br->br_mnt = NULL;
4f0767ce 2219+out:
1facf9fc 2220+ return err;
2221+}
2222+
2223+static void au_br_do_add_brp(struct au_sbinfo *sbinfo, aufs_bindex_t bindex,
2224+ struct au_branch *br, aufs_bindex_t bend,
2225+ aufs_bindex_t amount)
2226+{
2227+ struct au_branch **brp;
2228+
dece6358
AM
2229+ AuRwMustWriteLock(&sbinfo->si_rwsem);
2230+
1facf9fc 2231+ brp = sbinfo->si_branch + bindex;
2232+ memmove(brp + 1, brp, sizeof(*brp) * amount);
2233+ *brp = br;
2234+ sbinfo->si_bend++;
2235+ if (unlikely(bend < 0))
2236+ sbinfo->si_bend = 0;
2237+}
2238+
2239+static void au_br_do_add_hdp(struct au_dinfo *dinfo, aufs_bindex_t bindex,
2240+ aufs_bindex_t bend, aufs_bindex_t amount)
2241+{
2242+ struct au_hdentry *hdp;
2243+
1308ab2a 2244+ AuRwMustWriteLock(&dinfo->di_rwsem);
2245+
1facf9fc 2246+ hdp = dinfo->di_hdentry + bindex;
2247+ memmove(hdp + 1, hdp, sizeof(*hdp) * amount);
2248+ au_h_dentry_init(hdp);
2249+ dinfo->di_bend++;
2250+ if (unlikely(bend < 0))
2251+ dinfo->di_bstart = 0;
2252+}
2253+
2254+static void au_br_do_add_hip(struct au_iinfo *iinfo, aufs_bindex_t bindex,
2255+ aufs_bindex_t bend, aufs_bindex_t amount)
2256+{
2257+ struct au_hinode *hip;
2258+
1308ab2a 2259+ AuRwMustWriteLock(&iinfo->ii_rwsem);
2260+
1facf9fc 2261+ hip = iinfo->ii_hinode + bindex;
2262+ memmove(hip + 1, hip, sizeof(*hip) * amount);
2263+ hip->hi_inode = NULL;
4a4d8108 2264+ au_hn_init(hip);
1facf9fc 2265+ iinfo->ii_bend++;
2266+ if (unlikely(bend < 0))
2267+ iinfo->ii_bstart = 0;
2268+}
2269+
2270+static void au_br_do_add(struct super_block *sb, struct dentry *h_dentry,
2271+ struct au_branch *br, aufs_bindex_t bindex)
2272+{
2273+ struct dentry *root;
2274+ struct inode *root_inode;
2275+ aufs_bindex_t bend, amount;
2276+
2277+ root = sb->s_root;
2278+ root_inode = root->d_inode;
1facf9fc 2279+ bend = au_sbend(sb);
2280+ amount = bend + 1 - bindex;
53392da6 2281+ au_sbilist_lock();
1facf9fc 2282+ au_br_do_add_brp(au_sbi(sb), bindex, br, bend, amount);
2283+ au_br_do_add_hdp(au_di(root), bindex, bend, amount);
2284+ au_br_do_add_hip(au_ii(root_inode), bindex, bend, amount);
2285+ au_set_h_dptr(root, bindex, dget(h_dentry));
2286+ au_set_h_iptr(root_inode, bindex, au_igrab(h_dentry->d_inode),
2287+ /*flags*/0);
53392da6 2288+ au_sbilist_unlock();
1facf9fc 2289+}
2290+
2291+int au_br_add(struct super_block *sb, struct au_opt_add *add, int remount)
2292+{
2293+ int err;
1facf9fc 2294+ aufs_bindex_t bend, add_bindex;
2295+ struct dentry *root, *h_dentry;
2296+ struct inode *root_inode;
2297+ struct au_branch *add_branch;
2298+
2299+ root = sb->s_root;
2300+ root_inode = root->d_inode;
2301+ IMustLock(root_inode);
2302+ err = test_add(sb, add, remount);
2303+ if (unlikely(err < 0))
2304+ goto out;
2305+ if (err) {
2306+ err = 0;
2307+ goto out; /* success */
2308+ }
2309+
2310+ bend = au_sbend(sb);
2311+ add_branch = au_br_alloc(sb, bend + 2, add->perm);
2312+ err = PTR_ERR(add_branch);
2313+ if (IS_ERR(add_branch))
2314+ goto out;
2315+
2316+ err = au_br_init(add_branch, sb, add);
2317+ if (unlikely(err)) {
2318+ au_br_do_free(add_branch);
2319+ goto out;
2320+ }
2321+
2322+ add_bindex = add->bindex;
2323+ h_dentry = add->path.dentry;
2324+ if (!remount)
2325+ au_br_do_add(sb, h_dentry, add_branch, add_bindex);
2326+ else {
2327+ sysaufs_brs_del(sb, add_bindex);
2328+ au_br_do_add(sb, h_dentry, add_branch, add_bindex);
2329+ sysaufs_brs_add(sb, add_bindex);
2330+ }
2331+
1308ab2a 2332+ if (!add_bindex) {
1facf9fc 2333+ au_cpup_attr_all(root_inode, /*force*/1);
1308ab2a 2334+ sb->s_maxbytes = h_dentry->d_sb->s_maxbytes;
2335+ } else
1facf9fc 2336+ au_add_nlink(root_inode, h_dentry->d_inode);
1facf9fc 2337+
2338+ /*
4a4d8108 2339+ * this test/set prevents aufs from handling unnecesary notify events
027c5e7a 2340+ * of xino files, in case of re-adding a writable branch which was
1facf9fc 2341+ * once detached from aufs.
2342+ */
2343+ if (au_xino_brid(sb) < 0
2344+ && au_br_writable(add_branch->br_perm)
2345+ && !au_test_fs_bad_xino(h_dentry->d_sb)
2346+ && add_branch->br_xino.xi_file
2347+ && add_branch->br_xino.xi_file->f_dentry->d_parent == h_dentry)
2348+ au_xino_brid_set(sb, add_branch->br_id);
2349+
4f0767ce 2350+out:
1facf9fc 2351+ return err;
2352+}
2353+
2354+/* ---------------------------------------------------------------------- */
2355+
2356+/*
2357+ * delete a branch
2358+ */
2359+
2360+/* to show the line number, do not make it inlined function */
4a4d8108 2361+#define AuVerbose(do_info, fmt, ...) do { \
1facf9fc 2362+ if (do_info) \
4a4d8108 2363+ pr_info(fmt, ##__VA_ARGS__); \
1facf9fc 2364+} while (0)
2365+
027c5e7a
AM
2366+static int au_test_ibusy(struct inode *inode, aufs_bindex_t bstart,
2367+ aufs_bindex_t bend)
2368+{
2369+ return (inode && !S_ISDIR(inode->i_mode)) || bstart == bend;
2370+}
2371+
2372+static int au_test_dbusy(struct dentry *dentry, aufs_bindex_t bstart,
2373+ aufs_bindex_t bend)
2374+{
2375+ return au_test_ibusy(dentry->d_inode, bstart, bend);
2376+}
2377+
1facf9fc 2378+/*
2379+ * test if the branch is deletable or not.
2380+ */
2381+static int test_dentry_busy(struct dentry *root, aufs_bindex_t bindex,
b752ccd1 2382+ unsigned int sigen, const unsigned int verbose)
1facf9fc 2383+{
2384+ int err, i, j, ndentry;
2385+ aufs_bindex_t bstart, bend;
1facf9fc 2386+ struct au_dcsub_pages dpages;
2387+ struct au_dpage *dpage;
2388+ struct dentry *d;
1facf9fc 2389+
2390+ err = au_dpages_init(&dpages, GFP_NOFS);
2391+ if (unlikely(err))
2392+ goto out;
2393+ err = au_dcsub_pages(&dpages, root, NULL, NULL);
2394+ if (unlikely(err))
2395+ goto out_dpages;
2396+
1facf9fc 2397+ for (i = 0; !err && i < dpages.ndpage; i++) {
2398+ dpage = dpages.dpages + i;
2399+ ndentry = dpage->ndentry;
2400+ for (j = 0; !err && j < ndentry; j++) {
2401+ d = dpage->dentries[j];
027c5e7a
AM
2402+ AuDebugOn(!d->d_count);
2403+ if (!au_digen_test(d, sigen)) {
1facf9fc 2404+ di_read_lock_child(d, AuLock_IR);
027c5e7a
AM
2405+ if (unlikely(au_dbrange_test(d))) {
2406+ di_read_unlock(d, AuLock_IR);
2407+ continue;
2408+ }
2409+ } else {
1facf9fc 2410+ di_write_lock_child(d);
027c5e7a
AM
2411+ if (unlikely(au_dbrange_test(d))) {
2412+ di_write_unlock(d);
2413+ continue;
2414+ }
1facf9fc 2415+ err = au_reval_dpath(d, sigen);
2416+ if (!err)
2417+ di_downgrade_lock(d, AuLock_IR);
2418+ else {
2419+ di_write_unlock(d);
2420+ break;
2421+ }
2422+ }
2423+
027c5e7a 2424+ /* AuDbgDentry(d); */
1facf9fc 2425+ bstart = au_dbstart(d);
2426+ bend = au_dbend(d);
2427+ if (bstart <= bindex
2428+ && bindex <= bend
2429+ && au_h_dptr(d, bindex)
027c5e7a 2430+ && au_test_dbusy(d, bstart, bend)) {
1facf9fc 2431+ err = -EBUSY;
2432+ AuVerbose(verbose, "busy %.*s\n", AuDLNPair(d));
027c5e7a 2433+ AuDbgDentry(d);
1facf9fc 2434+ }
2435+ di_read_unlock(d, AuLock_IR);
2436+ }
2437+ }
2438+
4f0767ce 2439+out_dpages:
1facf9fc 2440+ au_dpages_free(&dpages);
4f0767ce 2441+out:
1facf9fc 2442+ return err;
2443+}
2444+
2445+static int test_inode_busy(struct super_block *sb, aufs_bindex_t bindex,
b752ccd1 2446+ unsigned int sigen, const unsigned int verbose)
1facf9fc 2447+{
2448+ int err;
7f207e10
AM
2449+ unsigned long long max, ull;
2450+ struct inode *i, **array;
1facf9fc 2451+ aufs_bindex_t bstart, bend;
1facf9fc 2452+
7f207e10
AM
2453+ array = au_iarray_alloc(sb, &max);
2454+ err = PTR_ERR(array);
2455+ if (IS_ERR(array))
2456+ goto out;
2457+
1facf9fc 2458+ err = 0;
7f207e10
AM
2459+ AuDbg("b%d\n", bindex);
2460+ for (ull = 0; !err && ull < max; ull++) {
2461+ i = array[ull];
2462+ if (i->i_ino == AUFS_ROOT_INO)
1facf9fc 2463+ continue;
2464+
7f207e10 2465+ /* AuDbgInode(i); */
1facf9fc 2466+ if (au_iigen(i) == sigen)
2467+ ii_read_lock_child(i);
2468+ else {
2469+ ii_write_lock_child(i);
027c5e7a
AM
2470+ err = au_refresh_hinode_self(i);
2471+ au_iigen_dec(i);
1facf9fc 2472+ if (!err)
2473+ ii_downgrade_lock(i);
2474+ else {
2475+ ii_write_unlock(i);
2476+ break;
2477+ }
2478+ }
2479+
2480+ bstart = au_ibstart(i);
2481+ bend = au_ibend(i);
2482+ if (bstart <= bindex
2483+ && bindex <= bend
2484+ && au_h_iptr(i, bindex)
027c5e7a 2485+ && au_test_ibusy(i, bstart, bend)) {
1facf9fc 2486+ err = -EBUSY;
2487+ AuVerbose(verbose, "busy i%lu\n", i->i_ino);
7f207e10 2488+ AuDbgInode(i);
1facf9fc 2489+ }
2490+ ii_read_unlock(i);
2491+ }
7f207e10 2492+ au_iarray_free(array, max);
1facf9fc 2493+
7f207e10 2494+out:
1facf9fc 2495+ return err;
2496+}
2497+
b752ccd1
AM
2498+static int test_children_busy(struct dentry *root, aufs_bindex_t bindex,
2499+ const unsigned int verbose)
1facf9fc 2500+{
2501+ int err;
2502+ unsigned int sigen;
2503+
2504+ sigen = au_sigen(root->d_sb);
2505+ DiMustNoWaiters(root);
2506+ IiMustNoWaiters(root->d_inode);
2507+ di_write_unlock(root);
b752ccd1 2508+ err = test_dentry_busy(root, bindex, sigen, verbose);
1facf9fc 2509+ if (!err)
b752ccd1 2510+ err = test_inode_busy(root->d_sb, bindex, sigen, verbose);
1facf9fc 2511+ di_write_lock_child(root); /* aufs_write_lock() calls ..._child() */
2512+
2513+ return err;
2514+}
2515+
2516+static void au_br_do_del_brp(struct au_sbinfo *sbinfo,
2517+ const aufs_bindex_t bindex,
2518+ const aufs_bindex_t bend)
2519+{
2520+ struct au_branch **brp, **p;
2521+
dece6358
AM
2522+ AuRwMustWriteLock(&sbinfo->si_rwsem);
2523+
1facf9fc 2524+ brp = sbinfo->si_branch + bindex;
2525+ if (bindex < bend)
2526+ memmove(brp, brp + 1, sizeof(*brp) * (bend - bindex));
2527+ sbinfo->si_branch[0 + bend] = NULL;
2528+ sbinfo->si_bend--;
2529+
53392da6 2530+ p = krealloc(sbinfo->si_branch, sizeof(*p) * bend, AuGFP_SBILIST);
1facf9fc 2531+ if (p)
2532+ sbinfo->si_branch = p;
4a4d8108 2533+ /* harmless error */
1facf9fc 2534+}
2535+
2536+static void au_br_do_del_hdp(struct au_dinfo *dinfo, const aufs_bindex_t bindex,
2537+ const aufs_bindex_t bend)
2538+{
2539+ struct au_hdentry *hdp, *p;
2540+
1308ab2a 2541+ AuRwMustWriteLock(&dinfo->di_rwsem);
2542+
4a4d8108 2543+ hdp = dinfo->di_hdentry;
1facf9fc 2544+ if (bindex < bend)
4a4d8108
AM
2545+ memmove(hdp + bindex, hdp + bindex + 1,
2546+ sizeof(*hdp) * (bend - bindex));
2547+ hdp[0 + bend].hd_dentry = NULL;
1facf9fc 2548+ dinfo->di_bend--;
2549+
53392da6 2550+ p = krealloc(hdp, sizeof(*p) * bend, AuGFP_SBILIST);
1facf9fc 2551+ if (p)
2552+ dinfo->di_hdentry = p;
4a4d8108 2553+ /* harmless error */
1facf9fc 2554+}
2555+
2556+static void au_br_do_del_hip(struct au_iinfo *iinfo, const aufs_bindex_t bindex,
2557+ const aufs_bindex_t bend)
2558+{
2559+ struct au_hinode *hip, *p;
2560+
1308ab2a 2561+ AuRwMustWriteLock(&iinfo->ii_rwsem);
2562+
1facf9fc 2563+ hip = iinfo->ii_hinode + bindex;
2564+ if (bindex < bend)
2565+ memmove(hip, hip + 1, sizeof(*hip) * (bend - bindex));
2566+ iinfo->ii_hinode[0 + bend].hi_inode = NULL;
4a4d8108 2567+ au_hn_init(iinfo->ii_hinode + bend);
1facf9fc 2568+ iinfo->ii_bend--;
2569+
53392da6 2570+ p = krealloc(iinfo->ii_hinode, sizeof(*p) * bend, AuGFP_SBILIST);
1facf9fc 2571+ if (p)
2572+ iinfo->ii_hinode = p;
4a4d8108 2573+ /* harmless error */
1facf9fc 2574+}
2575+
2576+static void au_br_do_del(struct super_block *sb, aufs_bindex_t bindex,
2577+ struct au_branch *br)
2578+{
2579+ aufs_bindex_t bend;
2580+ struct au_sbinfo *sbinfo;
53392da6
AM
2581+ struct dentry *root, *h_root;
2582+ struct inode *inode, *h_inode;
2583+ struct au_hinode *hinode;
1facf9fc 2584+
dece6358
AM
2585+ SiMustWriteLock(sb);
2586+
1facf9fc 2587+ root = sb->s_root;
2588+ inode = root->d_inode;
1facf9fc 2589+ sbinfo = au_sbi(sb);
2590+ bend = sbinfo->si_bend;
2591+
53392da6
AM
2592+ h_root = au_h_dptr(root, bindex);
2593+ hinode = au_hi(inode, bindex);
2594+ h_inode = au_igrab(hinode->hi_inode);
2595+ au_hiput(hinode);
1facf9fc 2596+
53392da6 2597+ au_sbilist_lock();
1facf9fc 2598+ au_br_do_del_brp(sbinfo, bindex, bend);
2599+ au_br_do_del_hdp(au_di(root), bindex, bend);
2600+ au_br_do_del_hip(au_ii(inode), bindex, bend);
53392da6
AM
2601+ au_sbilist_unlock();
2602+
2603+ dput(h_root);
2604+ iput(h_inode);
2605+ au_br_do_free(br);
1facf9fc 2606+}
2607+
2608+int au_br_del(struct super_block *sb, struct au_opt_del *del, int remount)
2609+{
2610+ int err, rerr, i;
2611+ unsigned int mnt_flags;
2612+ aufs_bindex_t bindex, bend, br_id;
2613+ unsigned char do_wh, verbose;
2614+ struct au_branch *br;
2615+ struct au_wbr *wbr;
2616+
2617+ err = 0;
2618+ bindex = au_find_dbindex(sb->s_root, del->h_path.dentry);
2619+ if (bindex < 0) {
2620+ if (remount)
2621+ goto out; /* success */
2622+ err = -ENOENT;
4a4d8108 2623+ pr_err("%s no such branch\n", del->pathname);
1facf9fc 2624+ goto out;
2625+ }
2626+ AuDbg("bindex b%d\n", bindex);
2627+
2628+ err = -EBUSY;
2629+ mnt_flags = au_mntflags(sb);
2630+ verbose = !!au_opt_test(mnt_flags, VERBOSE);
2631+ bend = au_sbend(sb);
2632+ if (unlikely(!bend)) {
2633+ AuVerbose(verbose, "no more branches left\n");
2634+ goto out;
2635+ }
2636+ br = au_sbr(sb, bindex);
2637+ i = atomic_read(&br->br_count);
2638+ if (unlikely(i)) {
2639+ AuVerbose(verbose, "%d file(s) opened\n", i);
e49829fe 2640+ goto out;
1facf9fc 2641+ }
2642+
2643+ wbr = br->br_wbr;
2644+ do_wh = wbr && (wbr->wbr_whbase || wbr->wbr_plink || wbr->wbr_orph);
2645+ if (do_wh) {
1308ab2a 2646+ /* instead of WbrWhMustWriteLock(wbr) */
2647+ SiMustWriteLock(sb);
1facf9fc 2648+ for (i = 0; i < AuBrWh_Last; i++) {
2649+ dput(wbr->wbr_wh[i]);
2650+ wbr->wbr_wh[i] = NULL;
2651+ }
2652+ }
2653+
b752ccd1 2654+ err = test_children_busy(sb->s_root, bindex, verbose);
1facf9fc 2655+ if (unlikely(err)) {
2656+ if (do_wh)
2657+ goto out_wh;
2658+ goto out;
2659+ }
2660+
2661+ err = 0;
2662+ br_id = br->br_id;
2663+ if (!remount)
2664+ au_br_do_del(sb, bindex, br);
2665+ else {
2666+ sysaufs_brs_del(sb, bindex);
2667+ au_br_do_del(sb, bindex, br);
2668+ sysaufs_brs_add(sb, bindex);
2669+ }
2670+
1308ab2a 2671+ if (!bindex) {
1facf9fc 2672+ au_cpup_attr_all(sb->s_root->d_inode, /*force*/1);
1308ab2a 2673+ sb->s_maxbytes = au_sbr_sb(sb, 0)->s_maxbytes;
2674+ } else
1facf9fc 2675+ au_sub_nlink(sb->s_root->d_inode, del->h_path.dentry->d_inode);
2676+ if (au_opt_test(mnt_flags, PLINK))
2677+ au_plink_half_refresh(sb, br_id);
2678+
b752ccd1 2679+ if (au_xino_brid(sb) == br_id)
1facf9fc 2680+ au_xino_brid_set(sb, -1);
2681+ goto out; /* success */
2682+
4f0767ce 2683+out_wh:
1facf9fc 2684+ /* revert */
2685+ rerr = au_br_init_wh(sb, br, br->br_perm, del->h_path.dentry);
2686+ if (rerr)
0c3ec466
AM
2687+ pr_warn("failed re-creating base whiteout, %s. (%d)\n",
2688+ del->pathname, rerr);
4f0767ce 2689+out:
1facf9fc 2690+ return err;
2691+}
2692+
2693+/* ---------------------------------------------------------------------- */
2694+
027c5e7a
AM
2695+static int au_ibusy(struct super_block *sb, struct aufs_ibusy __user *arg)
2696+{
2697+ int err;
2698+ aufs_bindex_t bstart, bend;
2699+ struct aufs_ibusy ibusy;
2700+ struct inode *inode, *h_inode;
2701+
2702+ err = -EPERM;
2703+ if (unlikely(!capable(CAP_SYS_ADMIN)))
2704+ goto out;
2705+
2706+ err = copy_from_user(&ibusy, arg, sizeof(ibusy));
2707+ if (!err)
2708+ err = !access_ok(VERIFY_WRITE, &arg->h_ino, sizeof(arg->h_ino));
2709+ if (unlikely(err)) {
2710+ err = -EFAULT;
2711+ AuTraceErr(err);
2712+ goto out;
2713+ }
2714+
2715+ err = -EINVAL;
2716+ si_read_lock(sb, AuLock_FLUSH);
2717+ if (unlikely(ibusy.bindex < 0 || ibusy.bindex > au_sbend(sb)))
2718+ goto out_unlock;
2719+
2720+ err = 0;
2721+ ibusy.h_ino = 0; /* invalid */
2722+ inode = ilookup(sb, ibusy.ino);
2723+ if (!inode
2724+ || inode->i_ino == AUFS_ROOT_INO
2725+ || is_bad_inode(inode))
2726+ goto out_unlock;
2727+
2728+ ii_read_lock_child(inode);
2729+ bstart = au_ibstart(inode);
2730+ bend = au_ibend(inode);
2731+ if (bstart <= ibusy.bindex && ibusy.bindex <= bend) {
2732+ h_inode = au_h_iptr(inode, ibusy.bindex);
2733+ if (h_inode && au_test_ibusy(inode, bstart, bend))
2734+ ibusy.h_ino = h_inode->i_ino;
2735+ }
2736+ ii_read_unlock(inode);
2737+ iput(inode);
2738+
2739+out_unlock:
2740+ si_read_unlock(sb);
2741+ if (!err) {
2742+ err = __put_user(ibusy.h_ino, &arg->h_ino);
2743+ if (unlikely(err)) {
2744+ err = -EFAULT;
2745+ AuTraceErr(err);
2746+ }
2747+ }
2748+out:
2749+ return err;
2750+}
2751+
2752+long au_ibusy_ioctl(struct file *file, unsigned long arg)
2753+{
2754+ return au_ibusy(file->f_dentry->d_sb, (void __user *)arg);
2755+}
2756+
2757+#ifdef CONFIG_COMPAT
2758+long au_ibusy_compat_ioctl(struct file *file, unsigned long arg)
2759+{
2760+ return au_ibusy(file->f_dentry->d_sb, compat_ptr(arg));
2761+}
2762+#endif
2763+
2764+/* ---------------------------------------------------------------------- */
2765+
1facf9fc 2766+/*
2767+ * change a branch permission
2768+ */
2769+
dece6358
AM
2770+static void au_warn_ima(void)
2771+{
2772+#ifdef CONFIG_IMA
1308ab2a 2773+ /* since it doesn't support mark_files_ro() */
027c5e7a 2774+ AuWarn1("RW -> RO makes IMA to produce wrong message\n");
dece6358
AM
2775+#endif
2776+}
2777+
1facf9fc 2778+static int do_need_sigen_inc(int a, int b)
2779+{
2780+ return au_br_whable(a) && !au_br_whable(b);
2781+}
2782+
2783+static int need_sigen_inc(int old, int new)
2784+{
2785+ return do_need_sigen_inc(old, new)
2786+ || do_need_sigen_inc(new, old);
2787+}
2788+
7f207e10
AM
2789+static unsigned long long au_farray_cb(void *a,
2790+ unsigned long long max __maybe_unused,
2791+ void *arg)
2792+{
2793+ unsigned long long n;
2794+ struct file **p, *f;
2795+ struct super_block *sb = arg;
2796+
2797+ n = 0;
2798+ p = a;
0c3ec466 2799+ lg_global_lock(&files_lglock);
7f207e10
AM
2800+ do_file_list_for_each_entry(sb, f) {
2801+ if (au_fi(f)
027c5e7a 2802+ && file_count(f)
7f207e10
AM
2803+ && !special_file(f->f_dentry->d_inode->i_mode)) {
2804+ get_file(f);
2805+ *p++ = f;
2806+ n++;
2807+ AuDebugOn(n > max);
2808+ }
2809+ } while_file_list_for_each_entry;
0c3ec466 2810+ lg_global_unlock(&files_lglock);
7f207e10
AM
2811+
2812+ return n;
2813+}
2814+
2815+static struct file **au_farray_alloc(struct super_block *sb,
2816+ unsigned long long *max)
2817+{
2818+ *max = atomic_long_read(&au_sbi(sb)->si_nfiles);
2819+ return au_array_alloc(max, au_farray_cb, sb);
2820+}
2821+
2822+static void au_farray_free(struct file **a, unsigned long long max)
2823+{
2824+ unsigned long long ull;
2825+
2826+ for (ull = 0; ull < max; ull++)
2827+ if (a[ull])
2828+ fput(a[ull]);
2829+ au_array_free(a);
2830+}
2831+
1facf9fc 2832+static int au_br_mod_files_ro(struct super_block *sb, aufs_bindex_t bindex)
2833+{
7f207e10 2834+ int err, do_warn;
027c5e7a 2835+ unsigned int mnt_flags;
7f207e10 2836+ unsigned long long ull, max;
e49829fe 2837+ aufs_bindex_t br_id;
027c5e7a 2838+ unsigned char verbose;
7f207e10 2839+ struct file *file, *hf, **array;
e49829fe
JR
2840+ struct inode *inode;
2841+ struct au_hfile *hfile;
1facf9fc 2842+
027c5e7a
AM
2843+ mnt_flags = au_mntflags(sb);
2844+ verbose = !!au_opt_test(mnt_flags, VERBOSE);
2845+
7f207e10
AM
2846+ array = au_farray_alloc(sb, &max);
2847+ err = PTR_ERR(array);
2848+ if (IS_ERR(array))
1facf9fc 2849+ goto out;
2850+
7f207e10 2851+ do_warn = 0;
e49829fe 2852+ br_id = au_sbr_id(sb, bindex);
7f207e10
AM
2853+ for (ull = 0; ull < max; ull++) {
2854+ file = array[ull];
1facf9fc 2855+
7f207e10 2856+ /* AuDbg("%.*s\n", AuDLNPair(file->f_dentry)); */
1facf9fc 2857+ fi_read_lock(file);
2858+ if (unlikely(au_test_mmapped(file))) {
2859+ err = -EBUSY;
027c5e7a
AM
2860+ AuVerbose(verbose, "mmapped %.*s\n",
2861+ AuDLNPair(file->f_dentry));
7f207e10 2862+ AuDbgFile(file);
1facf9fc 2863+ FiMustNoWaiters(file);
2864+ fi_read_unlock(file);
7f207e10 2865+ goto out_array;
1facf9fc 2866+ }
2867+
027c5e7a 2868+ inode = file->f_dentry->d_inode;
e49829fe
JR
2869+ hfile = &au_fi(file)->fi_htop;
2870+ hf = hfile->hf_file;
2871+ if (!S_ISREG(inode->i_mode)
1facf9fc 2872+ || !(file->f_mode & FMODE_WRITE)
e49829fe 2873+ || hfile->hf_br->br_id != br_id
7f207e10
AM
2874+ || !(hf->f_mode & FMODE_WRITE))
2875+ array[ull] = NULL;
2876+ else {
2877+ do_warn = 1;
2878+ get_file(file);
1facf9fc 2879+ }
2880+
1facf9fc 2881+ FiMustNoWaiters(file);
2882+ fi_read_unlock(file);
7f207e10
AM
2883+ fput(file);
2884+ }
1facf9fc 2885+
2886+ err = 0;
7f207e10 2887+ if (do_warn)
dece6358 2888+ au_warn_ima();
7f207e10
AM
2889+
2890+ for (ull = 0; ull < max; ull++) {
2891+ file = array[ull];
2892+ if (!file)
2893+ continue;
2894+
1facf9fc 2895+ /* todo: already flushed? */
2896+ /* cf. fs/super.c:mark_files_ro() */
7f207e10
AM
2897+ /* fi_read_lock(file); */
2898+ hfile = &au_fi(file)->fi_htop;
2899+ hf = hfile->hf_file;
2900+ /* fi_read_unlock(file); */
027c5e7a 2901+ spin_lock(&hf->f_lock);
1facf9fc 2902+ hf->f_mode &= ~FMODE_WRITE;
027c5e7a 2903+ spin_unlock(&hf->f_lock);
1facf9fc 2904+ if (!file_check_writeable(hf)) {
2905+ file_release_write(hf);
b4510431 2906+ vfsub_mnt_drop_write(hf->f_vfsmnt);
1facf9fc 2907+ }
2908+ }
2909+
7f207e10
AM
2910+out_array:
2911+ au_farray_free(array, max);
4f0767ce 2912+out:
7f207e10 2913+ AuTraceErr(err);
1facf9fc 2914+ return err;
2915+}
2916+
2917+int au_br_mod(struct super_block *sb, struct au_opt_mod *mod, int remount,
7f207e10 2918+ int *do_refresh)
1facf9fc 2919+{
2920+ int err, rerr;
2921+ aufs_bindex_t bindex;
1308ab2a 2922+ struct path path;
1facf9fc 2923+ struct dentry *root;
2924+ struct au_branch *br;
2925+
2926+ root = sb->s_root;
1facf9fc 2927+ bindex = au_find_dbindex(root, mod->h_root);
2928+ if (bindex < 0) {
2929+ if (remount)
2930+ return 0; /* success */
2931+ err = -ENOENT;
4a4d8108 2932+ pr_err("%s no such branch\n", mod->path);
1facf9fc 2933+ goto out;
2934+ }
2935+ AuDbg("bindex b%d\n", bindex);
2936+
2937+ err = test_br(mod->h_root->d_inode, mod->perm, mod->path);
2938+ if (unlikely(err))
2939+ goto out;
2940+
2941+ br = au_sbr(sb, bindex);
2942+ if (br->br_perm == mod->perm)
2943+ return 0; /* success */
2944+
2945+ if (au_br_writable(br->br_perm)) {
2946+ /* remove whiteout base */
2947+ err = au_br_init_wh(sb, br, mod->perm, mod->h_root);
2948+ if (unlikely(err))
2949+ goto out;
2950+
2951+ if (!au_br_writable(mod->perm)) {
2952+ /* rw --> ro, file might be mmapped */
2953+ DiMustNoWaiters(root);
2954+ IiMustNoWaiters(root->d_inode);
2955+ di_write_unlock(root);
2956+ err = au_br_mod_files_ro(sb, bindex);
2957+ /* aufs_write_lock() calls ..._child() */
2958+ di_write_lock_child(root);
2959+
2960+ if (unlikely(err)) {
2961+ rerr = -ENOMEM;
2962+ br->br_wbr = kmalloc(sizeof(*br->br_wbr),
2963+ GFP_NOFS);
1308ab2a 2964+ if (br->br_wbr) {
2965+ path.mnt = br->br_mnt;
2966+ path.dentry = mod->h_root;
2967+ rerr = au_wbr_init(br, sb, br->br_perm,
2968+ &path);
2969+ }
1facf9fc 2970+ if (unlikely(rerr)) {
2971+ AuIOErr("nested error %d (%d)\n",
2972+ rerr, err);
2973+ br->br_perm = mod->perm;
2974+ }
2975+ }
2976+ }
2977+ } else if (au_br_writable(mod->perm)) {
2978+ /* ro --> rw */
2979+ err = -ENOMEM;
2980+ br->br_wbr = kmalloc(sizeof(*br->br_wbr), GFP_NOFS);
2981+ if (br->br_wbr) {
1308ab2a 2982+ path.mnt = br->br_mnt;
2983+ path.dentry = mod->h_root;
1facf9fc 2984+ err = au_wbr_init(br, sb, mod->perm, &path);
2985+ if (unlikely(err)) {
2986+ kfree(br->br_wbr);
2987+ br->br_wbr = NULL;
2988+ }
2989+ }
2990+ }
2991+
2992+ if (!err) {
7f207e10 2993+ *do_refresh |= need_sigen_inc(br->br_perm, mod->perm);
1facf9fc 2994+ br->br_perm = mod->perm;
2995+ }
2996+
4f0767ce 2997+out:
7f207e10 2998+ AuTraceErr(err);
1facf9fc 2999+ return err;
3000+}
7f207e10
AM
3001diff -urN /usr/share/empty/fs/aufs/branch.h linux/fs/aufs/branch.h
3002--- /usr/share/empty/fs/aufs/branch.h 1970-01-01 01:00:00.000000000 +0100
2dfbb274 3003+++ linux/fs/aufs/branch.h 2012-08-26 08:39:00.757174634 +0200
f6c5ef8b 3004@@ -0,0 +1,230 @@
1facf9fc 3005+/*
f6c5ef8b 3006+ * Copyright (C) 2005-2012 Junjiro R. Okajima
1facf9fc 3007+ *
3008+ * This program, aufs is free software; you can redistribute it and/or modify
3009+ * it under the terms of the GNU General Public License as published by
3010+ * the Free Software Foundation; either version 2 of the License, or
3011+ * (at your option) any later version.
dece6358
AM
3012+ *
3013+ * This program is distributed in the hope that it will be useful,
3014+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
3015+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
3016+ * GNU General Public License for more details.
3017+ *
3018+ * You should have received a copy of the GNU General Public License
3019+ * along with this program; if not, write to the Free Software
3020+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 3021+ */
3022+
3023+/*
3024+ * branch filesystems and xino for them
3025+ */
3026+
3027+#ifndef __AUFS_BRANCH_H__
3028+#define __AUFS_BRANCH_H__
3029+
3030+#ifdef __KERNEL__
3031+
1facf9fc 3032+#include <linux/mount.h>
4a4d8108 3033+#include "dynop.h"
1facf9fc 3034+#include "rwsem.h"
3035+#include "super.h"
3036+
3037+/* ---------------------------------------------------------------------- */
3038+
3039+/* a xino file */
3040+struct au_xino_file {
3041+ struct file *xi_file;
3042+ struct mutex xi_nondir_mtx;
3043+
3044+ /* todo: make xino files an array to support huge inode number */
3045+
3046+#ifdef CONFIG_DEBUG_FS
3047+ struct dentry *xi_dbgaufs;
3048+#endif
3049+};
3050+
3051+/* members for writable branch only */
3052+enum {AuBrWh_BASE, AuBrWh_PLINK, AuBrWh_ORPH, AuBrWh_Last};
3053+struct au_wbr {
dece6358 3054+ struct au_rwsem wbr_wh_rwsem;
1facf9fc 3055+ struct dentry *wbr_wh[AuBrWh_Last];
4a4d8108 3056+ atomic_t wbr_wh_running;
1facf9fc 3057+#define wbr_whbase wbr_wh[AuBrWh_BASE] /* whiteout base */
3058+#define wbr_plink wbr_wh[AuBrWh_PLINK] /* pseudo-link dir */
3059+#define wbr_orph wbr_wh[AuBrWh_ORPH] /* dir for orphans */
3060+
3061+ /* mfs mode */
3062+ unsigned long long wbr_bytes;
3063+};
3064+
4a4d8108
AM
3065+/* ext2 has 3 types of operations at least, ext3 has 4 */
3066+#define AuBrDynOp (AuDyLast * 4)
3067+
1facf9fc 3068+/* protected by superblock rwsem */
3069+struct au_branch {
3070+ struct au_xino_file br_xino;
3071+
3072+ aufs_bindex_t br_id;
3073+
3074+ int br_perm;
3075+ struct vfsmount *br_mnt;
4a4d8108
AM
3076+ spinlock_t br_dykey_lock;
3077+ struct au_dykey *br_dykey[AuBrDynOp];
1facf9fc 3078+ atomic_t br_count;
3079+
3080+ struct au_wbr *br_wbr;
3081+
3082+ /* xino truncation */
3083+ blkcnt_t br_xino_upper; /* watermark in blocks */
3084+ atomic_t br_xino_running;
3085+
027c5e7a
AM
3086+#ifdef CONFIG_AUFS_HFSNOTIFY
3087+ struct fsnotify_group *br_hfsn_group;
3088+ struct fsnotify_ops br_hfsn_ops;
3089+#endif
3090+
1facf9fc 3091+#ifdef CONFIG_SYSFS
3092+ /* an entry under sysfs per mount-point */
3093+ char br_name[8];
3094+ struct attribute br_attr;
3095+#endif
3096+};
3097+
3098+/* ---------------------------------------------------------------------- */
3099+
1e00d052
AM
3100+/* branch permissions and attributes */
3101+#define AuBrPerm_RW 1 /* writable, hardlinkable wh */
3102+#define AuBrPerm_RO (1 << 1) /* readonly */
3103+#define AuBrPerm_RR (1 << 2) /* natively readonly */
3104+#define AuBrPerm_Mask (AuBrPerm_RW | AuBrPerm_RO | AuBrPerm_RR)
1facf9fc 3105+
1e00d052 3106+#define AuBrRAttr_WH (1 << 3) /* whiteout-able */
1facf9fc 3107+
1e00d052 3108+#define AuBrWAttr_NoLinkWH (1 << 4) /* un-hardlinkable whiteouts */
1facf9fc 3109+
3110+static inline int au_br_writable(int brperm)
3111+{
1e00d052 3112+ return brperm & AuBrPerm_RW;
1facf9fc 3113+}
3114+
3115+static inline int au_br_whable(int brperm)
3116+{
1e00d052
AM
3117+ return brperm & (AuBrPerm_RW | AuBrRAttr_WH);
3118+}
3119+
3120+static inline int au_br_wh_linkable(int brperm)
3121+{
3122+ return !(brperm & AuBrWAttr_NoLinkWH);
1facf9fc 3123+}
3124+
3125+static inline int au_br_rdonly(struct au_branch *br)
3126+{
3127+ return ((br->br_mnt->mnt_sb->s_flags & MS_RDONLY)
3128+ || !au_br_writable(br->br_perm))
3129+ ? -EROFS : 0;
3130+}
3131+
4a4d8108 3132+static inline int au_br_hnotifyable(int brperm __maybe_unused)
1facf9fc 3133+{
4a4d8108 3134+#ifdef CONFIG_AUFS_HNOTIFY
1e00d052 3135+ return !(brperm & AuBrPerm_RR);
1facf9fc 3136+#else
3137+ return 0;
3138+#endif
3139+}
3140+
3141+/* ---------------------------------------------------------------------- */
3142+
3143+/* branch.c */
3144+struct au_sbinfo;
3145+void au_br_free(struct au_sbinfo *sinfo);
3146+int au_br_index(struct super_block *sb, aufs_bindex_t br_id);
3147+struct au_opt_add;
3148+int au_br_add(struct super_block *sb, struct au_opt_add *add, int remount);
3149+struct au_opt_del;
3150+int au_br_del(struct super_block *sb, struct au_opt_del *del, int remount);
027c5e7a
AM
3151+long au_ibusy_ioctl(struct file *file, unsigned long arg);
3152+#ifdef CONFIG_COMPAT
3153+long au_ibusy_compat_ioctl(struct file *file, unsigned long arg);
3154+#endif
1facf9fc 3155+struct au_opt_mod;
3156+int au_br_mod(struct super_block *sb, struct au_opt_mod *mod, int remount,
7f207e10 3157+ int *do_refresh);
1facf9fc 3158+
3159+/* xino.c */
3160+static const loff_t au_loff_max = LLONG_MAX;
3161+
3162+int au_xib_trunc(struct super_block *sb);
3163+ssize_t xino_fread(au_readf_t func, struct file *file, void *buf, size_t size,
3164+ loff_t *pos);
3165+ssize_t xino_fwrite(au_writef_t func, struct file *file, void *buf, size_t size,
3166+ loff_t *pos);
3167+struct file *au_xino_create2(struct file *base_file, struct file *copy_src);
3168+struct file *au_xino_create(struct super_block *sb, char *fname, int silent);
3169+ino_t au_xino_new_ino(struct super_block *sb);
b752ccd1 3170+void au_xino_delete_inode(struct inode *inode, const int unlinked);
1facf9fc 3171+int au_xino_write(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino,
3172+ ino_t ino);
3173+int au_xino_read(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino,
3174+ ino_t *ino);
3175+int au_xino_br(struct super_block *sb, struct au_branch *br, ino_t hino,
3176+ struct file *base_file, int do_test);
3177+int au_xino_trunc(struct super_block *sb, aufs_bindex_t bindex);
3178+
3179+struct au_opt_xino;
3180+int au_xino_set(struct super_block *sb, struct au_opt_xino *xino, int remount);
3181+void au_xino_clr(struct super_block *sb);
3182+struct file *au_xino_def(struct super_block *sb);
3183+int au_xino_path(struct seq_file *seq, struct file *file);
3184+
3185+/* ---------------------------------------------------------------------- */
3186+
3187+/* Superblock to branch */
3188+static inline
3189+aufs_bindex_t au_sbr_id(struct super_block *sb, aufs_bindex_t bindex)
3190+{
3191+ return au_sbr(sb, bindex)->br_id;
3192+}
3193+
3194+static inline
3195+struct vfsmount *au_sbr_mnt(struct super_block *sb, aufs_bindex_t bindex)
3196+{
3197+ return au_sbr(sb, bindex)->br_mnt;
3198+}
3199+
3200+static inline
3201+struct super_block *au_sbr_sb(struct super_block *sb, aufs_bindex_t bindex)
3202+{
3203+ return au_sbr_mnt(sb, bindex)->mnt_sb;
3204+}
3205+
3206+static inline void au_sbr_put(struct super_block *sb, aufs_bindex_t bindex)
3207+{
e49829fe 3208+ atomic_dec(&au_sbr(sb, bindex)->br_count);
1facf9fc 3209+}
3210+
3211+static inline int au_sbr_perm(struct super_block *sb, aufs_bindex_t bindex)
3212+{
3213+ return au_sbr(sb, bindex)->br_perm;
3214+}
3215+
3216+static inline int au_sbr_whable(struct super_block *sb, aufs_bindex_t bindex)
3217+{
3218+ return au_br_whable(au_sbr_perm(sb, bindex));
3219+}
3220+
3221+/* ---------------------------------------------------------------------- */
3222+
3223+/*
3224+ * wbr_wh_read_lock, wbr_wh_write_lock
3225+ * wbr_wh_read_unlock, wbr_wh_write_unlock, wbr_wh_downgrade_lock
3226+ */
3227+AuSimpleRwsemFuncs(wbr_wh, struct au_wbr *wbr, &wbr->wbr_wh_rwsem);
3228+
dece6358
AM
3229+#define WbrWhMustNoWaiters(wbr) AuRwMustNoWaiters(&wbr->wbr_wh_rwsem)
3230+#define WbrWhMustAnyLock(wbr) AuRwMustAnyLock(&wbr->wbr_wh_rwsem)
3231+#define WbrWhMustWriteLock(wbr) AuRwMustWriteLock(&wbr->wbr_wh_rwsem)
3232+
1facf9fc 3233+#endif /* __KERNEL__ */
3234+#endif /* __AUFS_BRANCH_H__ */
7f207e10
AM
3235diff -urN /usr/share/empty/fs/aufs/conf.mk linux/fs/aufs/conf.mk
3236--- /usr/share/empty/fs/aufs/conf.mk 1970-01-01 01:00:00.000000000 +0100
2dfbb274 3237+++ linux/fs/aufs/conf.mk 2012-08-26 08:39:00.757174634 +0200
2cbb1c4b 3238@@ -0,0 +1,38 @@
4a4d8108
AM
3239+
3240+AuConfStr = CONFIG_AUFS_FS=${CONFIG_AUFS_FS}
3241+
3242+define AuConf
3243+ifdef ${1}
3244+AuConfStr += ${1}=${${1}}
3245+endif
3246+endef
3247+
b752ccd1 3248+AuConfAll = BRANCH_MAX_127 BRANCH_MAX_511 BRANCH_MAX_1023 BRANCH_MAX_32767 \
e49829fe 3249+ SBILIST \
7f207e10 3250+ HNOTIFY HFSNOTIFY \
4a4d8108
AM
3251+ EXPORT INO_T_64 \
3252+ RDU \
2cbb1c4b 3253+ PROC_MAP \
4a4d8108
AM
3254+ SP_IATTR \
3255+ SHWH \
3256+ BR_RAMFS \
3257+ BR_FUSE POLL \
3258+ BR_HFSPLUS \
3259+ BDEV_LOOP \
b752ccd1
AM
3260+ DEBUG MAGIC_SYSRQ
3261+$(foreach i, ${AuConfAll}, \
4a4d8108
AM
3262+ $(eval $(call AuConf,CONFIG_AUFS_${i})))
3263+
3264+AuConfName = ${obj}/conf.str
3265+${AuConfName}.tmp: FORCE
3266+ @echo ${AuConfStr} | tr ' ' '\n' | sed -e 's/^/"/' -e 's/$$/\\n"/' > $@
3267+${AuConfName}: ${AuConfName}.tmp
3268+ @diff -q $< $@ > /dev/null 2>&1 || { \
3269+ echo ' GEN ' $@; \
3270+ cp -p $< $@; \
3271+ }
3272+FORCE:
3273+clean-files += ${AuConfName} ${AuConfName}.tmp
3274+${obj}/sysfs.o: ${AuConfName}
b752ccd1
AM
3275+
3276+-include ${srctree}/${src}/conf_priv.mk
7f207e10
AM
3277diff -urN /usr/share/empty/fs/aufs/cpup.c linux/fs/aufs/cpup.c
3278--- /usr/share/empty/fs/aufs/cpup.c 1970-01-01 01:00:00.000000000 +0100
b4510431
AM
3279+++ linux/fs/aufs/cpup.c 2012-10-17 10:31:01.772481151 +0200
3280@@ -0,0 +1,1085 @@
1facf9fc 3281+/*
f6c5ef8b 3282+ * Copyright (C) 2005-2012 Junjiro R. Okajima
1facf9fc 3283+ *
3284+ * This program, aufs is free software; you can redistribute it and/or modify
3285+ * it under the terms of the GNU General Public License as published by
3286+ * the Free Software Foundation; either version 2 of the License, or
3287+ * (at your option) any later version.
dece6358
AM
3288+ *
3289+ * This program is distributed in the hope that it will be useful,
3290+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
3291+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
3292+ * GNU General Public License for more details.
3293+ *
3294+ * You should have received a copy of the GNU General Public License
3295+ * along with this program; if not, write to the Free Software
3296+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 3297+ */
3298+
3299+/*
3300+ * copy-up functions, see wbr_policy.c for copy-down
3301+ */
3302+
3303+#include <linux/fs_stack.h>
dece6358 3304+#include <linux/mm.h>
1facf9fc 3305+#include "aufs.h"
3306+
3307+void au_cpup_attr_flags(struct inode *dst, struct inode *src)
3308+{
3309+ const unsigned int mask = S_DEAD | S_SWAPFILE | S_PRIVATE
3310+ | S_NOATIME | S_NOCMTIME;
3311+
3312+ dst->i_flags |= src->i_flags & ~mask;
3313+ if (au_test_fs_notime(dst->i_sb))
3314+ dst->i_flags |= S_NOATIME | S_NOCMTIME;
3315+}
3316+
3317+void au_cpup_attr_timesizes(struct inode *inode)
3318+{
3319+ struct inode *h_inode;
3320+
3321+ h_inode = au_h_iptr(inode, au_ibstart(inode));
3322+ fsstack_copy_attr_times(inode, h_inode);
4a4d8108 3323+ fsstack_copy_inode_size(inode, h_inode);
1facf9fc 3324+}
3325+
3326+void au_cpup_attr_nlink(struct inode *inode, int force)
3327+{
3328+ struct inode *h_inode;
3329+ struct super_block *sb;
3330+ aufs_bindex_t bindex, bend;
3331+
3332+ sb = inode->i_sb;
3333+ bindex = au_ibstart(inode);
3334+ h_inode = au_h_iptr(inode, bindex);
3335+ if (!force
3336+ && !S_ISDIR(h_inode->i_mode)
3337+ && au_opt_test(au_mntflags(sb), PLINK)
3338+ && au_plink_test(inode))
3339+ return;
3340+
7eafdf33
AM
3341+ /*
3342+ * 0 can happen in revalidating.
3343+ * h_inode->i_mutex is not held, but it is harmless since once i_nlink
3344+ * reaches 0, it will never become positive.
3345+ */
92d182d2 3346+ set_nlink(inode, h_inode->i_nlink);
1facf9fc 3347+
3348+ /*
3349+ * fewer nlink makes find(1) noisy, but larger nlink doesn't.
3350+ * it may includes whplink directory.
3351+ */
3352+ if (S_ISDIR(h_inode->i_mode)) {
3353+ bend = au_ibend(inode);
3354+ for (bindex++; bindex <= bend; bindex++) {
3355+ h_inode = au_h_iptr(inode, bindex);
3356+ if (h_inode)
3357+ au_add_nlink(inode, h_inode);
3358+ }
3359+ }
3360+}
3361+
3362+void au_cpup_attr_changeable(struct inode *inode)
3363+{
3364+ struct inode *h_inode;
3365+
3366+ h_inode = au_h_iptr(inode, au_ibstart(inode));
3367+ inode->i_mode = h_inode->i_mode;
3368+ inode->i_uid = h_inode->i_uid;
3369+ inode->i_gid = h_inode->i_gid;
3370+ au_cpup_attr_timesizes(inode);
3371+ au_cpup_attr_flags(inode, h_inode);
3372+}
3373+
3374+void au_cpup_igen(struct inode *inode, struct inode *h_inode)
3375+{
3376+ struct au_iinfo *iinfo = au_ii(inode);
3377+
1308ab2a 3378+ IiMustWriteLock(inode);
3379+
1facf9fc 3380+ iinfo->ii_higen = h_inode->i_generation;
3381+ iinfo->ii_hsb1 = h_inode->i_sb;
3382+}
3383+
3384+void au_cpup_attr_all(struct inode *inode, int force)
3385+{
3386+ struct inode *h_inode;
3387+
3388+ h_inode = au_h_iptr(inode, au_ibstart(inode));
3389+ au_cpup_attr_changeable(inode);
3390+ if (inode->i_nlink > 0)
3391+ au_cpup_attr_nlink(inode, force);
3392+ inode->i_rdev = h_inode->i_rdev;
3393+ inode->i_blkbits = h_inode->i_blkbits;
3394+ au_cpup_igen(inode, h_inode);
3395+}
3396+
3397+/* ---------------------------------------------------------------------- */
3398+
3399+/* Note: dt_dentry and dt_h_dentry are not dget/dput-ed */
3400+
3401+/* keep the timestamps of the parent dir when cpup */
3402+void au_dtime_store(struct au_dtime *dt, struct dentry *dentry,
3403+ struct path *h_path)
3404+{
3405+ struct inode *h_inode;
3406+
3407+ dt->dt_dentry = dentry;
3408+ dt->dt_h_path = *h_path;
3409+ h_inode = h_path->dentry->d_inode;
3410+ dt->dt_atime = h_inode->i_atime;
3411+ dt->dt_mtime = h_inode->i_mtime;
3412+ /* smp_mb(); */
3413+}
3414+
3415+void au_dtime_revert(struct au_dtime *dt)
3416+{
3417+ struct iattr attr;
3418+ int err;
3419+
3420+ attr.ia_atime = dt->dt_atime;
3421+ attr.ia_mtime = dt->dt_mtime;
3422+ attr.ia_valid = ATTR_FORCE | ATTR_MTIME | ATTR_MTIME_SET
3423+ | ATTR_ATIME | ATTR_ATIME_SET;
3424+
3425+ err = vfsub_notify_change(&dt->dt_h_path, &attr);
3426+ if (unlikely(err))
0c3ec466 3427+ pr_warn("restoring timestamps failed(%d). ignored\n", err);
1facf9fc 3428+}
3429+
3430+/* ---------------------------------------------------------------------- */
3431+
3432+static noinline_for_stack
3433+int cpup_iattr(struct dentry *dst, aufs_bindex_t bindex, struct dentry *h_src)
3434+{
3435+ int err, sbits;
3436+ struct iattr ia;
3437+ struct path h_path;
1308ab2a 3438+ struct inode *h_isrc, *h_idst;
1facf9fc 3439+
3440+ h_path.dentry = au_h_dptr(dst, bindex);
1308ab2a 3441+ h_idst = h_path.dentry->d_inode;
1facf9fc 3442+ h_path.mnt = au_sbr_mnt(dst->d_sb, bindex);
3443+ h_isrc = h_src->d_inode;
1308ab2a 3444+ ia.ia_valid = ATTR_FORCE | ATTR_UID | ATTR_GID
1facf9fc 3445+ | ATTR_ATIME | ATTR_MTIME
3446+ | ATTR_ATIME_SET | ATTR_MTIME_SET;
1facf9fc 3447+ ia.ia_uid = h_isrc->i_uid;
3448+ ia.ia_gid = h_isrc->i_gid;
3449+ ia.ia_atime = h_isrc->i_atime;
3450+ ia.ia_mtime = h_isrc->i_mtime;
1308ab2a 3451+ if (h_idst->i_mode != h_isrc->i_mode
3452+ && !S_ISLNK(h_idst->i_mode)) {
3453+ ia.ia_valid |= ATTR_MODE;
3454+ ia.ia_mode = h_isrc->i_mode;
3455+ }
3456+ sbits = !!(h_isrc->i_mode & (S_ISUID | S_ISGID));
3457+ au_cpup_attr_flags(h_idst, h_isrc);
1facf9fc 3458+ err = vfsub_notify_change(&h_path, &ia);
3459+
3460+ /* is this nfs only? */
3461+ if (!err && sbits && au_test_nfs(h_path.dentry->d_sb)) {
3462+ ia.ia_valid = ATTR_FORCE | ATTR_MODE;
3463+ ia.ia_mode = h_isrc->i_mode;
3464+ err = vfsub_notify_change(&h_path, &ia);
3465+ }
3466+
3467+ return err;
3468+}
3469+
3470+/* ---------------------------------------------------------------------- */
3471+
3472+static int au_do_copy_file(struct file *dst, struct file *src, loff_t len,
3473+ char *buf, unsigned long blksize)
3474+{
3475+ int err;
3476+ size_t sz, rbytes, wbytes;
3477+ unsigned char all_zero;
3478+ char *p, *zp;
3479+ struct mutex *h_mtx;
3480+ /* reduce stack usage */
3481+ struct iattr *ia;
3482+
3483+ zp = page_address(ZERO_PAGE(0));
3484+ if (unlikely(!zp))
3485+ return -ENOMEM; /* possible? */
3486+
3487+ err = 0;
3488+ all_zero = 0;
3489+ while (len) {
3490+ AuDbg("len %lld\n", len);
3491+ sz = blksize;
3492+ if (len < blksize)
3493+ sz = len;
3494+
3495+ rbytes = 0;
3496+ /* todo: signal_pending? */
3497+ while (!rbytes || err == -EAGAIN || err == -EINTR) {
3498+ rbytes = vfsub_read_k(src, buf, sz, &src->f_pos);
3499+ err = rbytes;
3500+ }
3501+ if (unlikely(err < 0))
3502+ break;
3503+
3504+ all_zero = 0;
3505+ if (len >= rbytes && rbytes == blksize)
3506+ all_zero = !memcmp(buf, zp, rbytes);
3507+ if (!all_zero) {
3508+ wbytes = rbytes;
3509+ p = buf;
3510+ while (wbytes) {
3511+ size_t b;
3512+
3513+ b = vfsub_write_k(dst, p, wbytes, &dst->f_pos);
3514+ err = b;
3515+ /* todo: signal_pending? */
3516+ if (unlikely(err == -EAGAIN || err == -EINTR))
3517+ continue;
3518+ if (unlikely(err < 0))
3519+ break;
3520+ wbytes -= b;
3521+ p += b;
3522+ }
3523+ } else {
3524+ loff_t res;
3525+
3526+ AuLabel(hole);
3527+ res = vfsub_llseek(dst, rbytes, SEEK_CUR);
3528+ err = res;
3529+ if (unlikely(res < 0))
3530+ break;
3531+ }
3532+ len -= rbytes;
3533+ err = 0;
3534+ }
3535+
3536+ /* the last block may be a hole */
3537+ if (!err && all_zero) {
3538+ AuLabel(last hole);
3539+
3540+ err = 1;
3541+ if (au_test_nfs(dst->f_dentry->d_sb)) {
3542+ /* nfs requires this step to make last hole */
3543+ /* is this only nfs? */
3544+ do {
3545+ /* todo: signal_pending? */
3546+ err = vfsub_write_k(dst, "\0", 1, &dst->f_pos);
3547+ } while (err == -EAGAIN || err == -EINTR);
3548+ if (err == 1)
3549+ dst->f_pos--;
3550+ }
3551+
3552+ if (err == 1) {
3553+ ia = (void *)buf;
3554+ ia->ia_size = dst->f_pos;
3555+ ia->ia_valid = ATTR_SIZE | ATTR_FILE;
3556+ ia->ia_file = dst;
3557+ h_mtx = &dst->f_dentry->d_inode->i_mutex;
3558+ mutex_lock_nested(h_mtx, AuLsc_I_CHILD2);
3559+ err = vfsub_notify_change(&dst->f_path, ia);
3560+ mutex_unlock(h_mtx);
3561+ }
3562+ }
3563+
3564+ return err;
3565+}
3566+
3567+int au_copy_file(struct file *dst, struct file *src, loff_t len)
3568+{
3569+ int err;
3570+ unsigned long blksize;
3571+ unsigned char do_kfree;
3572+ char *buf;
3573+
3574+ err = -ENOMEM;
3575+ blksize = dst->f_dentry->d_sb->s_blocksize;
3576+ if (!blksize || PAGE_SIZE < blksize)
3577+ blksize = PAGE_SIZE;
3578+ AuDbg("blksize %lu\n", blksize);
3579+ do_kfree = (blksize != PAGE_SIZE && blksize >= sizeof(struct iattr *));
3580+ if (do_kfree)
3581+ buf = kmalloc(blksize, GFP_NOFS);
3582+ else
3583+ buf = (void *)__get_free_page(GFP_NOFS);
3584+ if (unlikely(!buf))
3585+ goto out;
3586+
3587+ if (len > (1 << 22))
3588+ AuDbg("copying a large file %lld\n", (long long)len);
3589+
3590+ src->f_pos = 0;
3591+ dst->f_pos = 0;
3592+ err = au_do_copy_file(dst, src, len, buf, blksize);
3593+ if (do_kfree)
3594+ kfree(buf);
3595+ else
3596+ free_page((unsigned long)buf);
3597+
4f0767ce 3598+out:
1facf9fc 3599+ return err;
3600+}
3601+
3602+/*
3603+ * to support a sparse file which is opened with O_APPEND,
3604+ * we need to close the file.
3605+ */
3606+static int au_cp_regular(struct dentry *dentry, aufs_bindex_t bdst,
4a4d8108 3607+ aufs_bindex_t bsrc, loff_t len)
1facf9fc 3608+{
3609+ int err, i;
3610+ enum { SRC, DST };
3611+ struct {
3612+ aufs_bindex_t bindex;
3613+ unsigned int flags;
3614+ struct dentry *dentry;
3615+ struct file *file;
3616+ void *label, *label_file;
3617+ } *f, file[] = {
3618+ {
3619+ .bindex = bsrc,
3620+ .flags = O_RDONLY | O_NOATIME | O_LARGEFILE,
3621+ .file = NULL,
3622+ .label = &&out,
3623+ .label_file = &&out_src
3624+ },
3625+ {
3626+ .bindex = bdst,
3627+ .flags = O_WRONLY | O_NOATIME | O_LARGEFILE,
3628+ .file = NULL,
3629+ .label = &&out_src,
3630+ .label_file = &&out_dst
3631+ }
3632+ };
3633+ struct super_block *sb;
3634+
3635+ /* bsrc branch can be ro/rw. */
3636+ sb = dentry->d_sb;
3637+ f = file;
3638+ for (i = 0; i < 2; i++, f++) {
3639+ f->dentry = au_h_dptr(dentry, f->bindex);
3640+ f->file = au_h_open(dentry, f->bindex, f->flags, /*file*/NULL);
3641+ err = PTR_ERR(f->file);
3642+ if (IS_ERR(f->file))
3643+ goto *f->label;
3644+ err = -EINVAL;
3645+ if (unlikely(!f->file->f_op))
3646+ goto *f->label_file;
3647+ }
3648+
3649+ /* try stopping to update while we copyup */
3650+ IMustLock(file[SRC].dentry->d_inode);
3651+ err = au_copy_file(file[DST].file, file[SRC].file, len);
3652+
4f0767ce 3653+out_dst:
1facf9fc 3654+ fput(file[DST].file);
3655+ au_sbr_put(sb, file[DST].bindex);
4f0767ce 3656+out_src:
1facf9fc 3657+ fput(file[SRC].file);
3658+ au_sbr_put(sb, file[SRC].bindex);
4f0767ce 3659+out:
1facf9fc 3660+ return err;
3661+}
3662+
3663+static int au_do_cpup_regular(struct dentry *dentry, aufs_bindex_t bdst,
3664+ aufs_bindex_t bsrc, loff_t len,
3665+ struct inode *h_dir, struct path *h_path)
3666+{
3667+ int err, rerr;
3668+ loff_t l;
3669+
3670+ err = 0;
3671+ l = i_size_read(au_h_iptr(dentry->d_inode, bsrc));
3672+ if (len == -1 || l < len)
3673+ len = l;
3674+ if (len)
3675+ err = au_cp_regular(dentry, bdst, bsrc, len);
3676+ if (!err)
3677+ goto out; /* success */
3678+
3679+ rerr = vfsub_unlink(h_dir, h_path, /*force*/0);
3680+ if (rerr) {
3681+ AuIOErr("failed unlinking cpup-ed %.*s(%d, %d)\n",
3682+ AuDLNPair(h_path->dentry), err, rerr);
3683+ err = -EIO;
3684+ }
3685+
4f0767ce 3686+out:
1facf9fc 3687+ return err;
3688+}
3689+
3690+static int au_do_cpup_symlink(struct path *h_path, struct dentry *h_src,
3691+ struct inode *h_dir)
3692+{
3693+ int err, symlen;
3694+ mm_segment_t old_fs;
b752ccd1
AM
3695+ union {
3696+ char *k;
3697+ char __user *u;
3698+ } sym;
1facf9fc 3699+
3700+ err = -ENOSYS;
3701+ if (unlikely(!h_src->d_inode->i_op->readlink))
3702+ goto out;
3703+
3704+ err = -ENOMEM;
b752ccd1
AM
3705+ sym.k = __getname_gfp(GFP_NOFS);
3706+ if (unlikely(!sym.k))
1facf9fc 3707+ goto out;
3708+
9dbd164d 3709+ /* unnecessary to support mmap_sem since symlink is not mmap-able */
1facf9fc 3710+ old_fs = get_fs();
3711+ set_fs(KERNEL_DS);
b752ccd1 3712+ symlen = h_src->d_inode->i_op->readlink(h_src, sym.u, PATH_MAX);
1facf9fc 3713+ err = symlen;
3714+ set_fs(old_fs);
3715+
3716+ if (symlen > 0) {
b752ccd1
AM
3717+ sym.k[symlen] = 0;
3718+ err = vfsub_symlink(h_dir, h_path, sym.k);
1facf9fc 3719+ }
b752ccd1 3720+ __putname(sym.k);
1facf9fc 3721+
4f0767ce 3722+out:
1facf9fc 3723+ return err;
3724+}
3725+
3726+/* return with the lower dst inode is locked */
3727+static noinline_for_stack
3728+int cpup_entry(struct dentry *dentry, aufs_bindex_t bdst,
3729+ aufs_bindex_t bsrc, loff_t len, unsigned int flags,
3730+ struct dentry *dst_parent)
3731+{
3732+ int err;
3733+ umode_t mode;
3734+ unsigned int mnt_flags;
3735+ unsigned char isdir;
3736+ const unsigned char do_dt = !!au_ftest_cpup(flags, DTIME);
3737+ struct au_dtime dt;
3738+ struct path h_path;
3739+ struct dentry *h_src, *h_dst, *h_parent;
3740+ struct inode *h_inode, *h_dir;
3741+ struct super_block *sb;
3742+
3743+ /* bsrc branch can be ro/rw. */
3744+ h_src = au_h_dptr(dentry, bsrc);
3745+ h_inode = h_src->d_inode;
3746+ AuDebugOn(h_inode != au_h_iptr(dentry->d_inode, bsrc));
3747+
3748+ /* try stopping to be referenced while we are creating */
3749+ h_dst = au_h_dptr(dentry, bdst);
3750+ h_parent = h_dst->d_parent; /* dir inode is locked */
3751+ h_dir = h_parent->d_inode;
3752+ IMustLock(h_dir);
3753+ AuDebugOn(h_parent != h_dst->d_parent);
3754+
3755+ sb = dentry->d_sb;
3756+ h_path.mnt = au_sbr_mnt(sb, bdst);
3757+ if (do_dt) {
3758+ h_path.dentry = h_parent;
3759+ au_dtime_store(&dt, dst_parent, &h_path);
3760+ }
3761+ h_path.dentry = h_dst;
3762+
3763+ isdir = 0;
3764+ mode = h_inode->i_mode;
3765+ switch (mode & S_IFMT) {
3766+ case S_IFREG:
3767+ /* try stopping to update while we are referencing */
3768+ IMustLock(h_inode);
b4510431
AM
3769+ err = vfsub_create(h_dir, &h_path, mode | S_IWUSR,
3770+ /*want_excl*/true);
1facf9fc 3771+ if (!err)
3772+ err = au_do_cpup_regular
3773+ (dentry, bdst, bsrc, len,
3774+ au_h_iptr(dst_parent->d_inode, bdst), &h_path);
3775+ break;
3776+ case S_IFDIR:
3777+ isdir = 1;
3778+ err = vfsub_mkdir(h_dir, &h_path, mode);
3779+ if (!err) {
3780+ /*
3781+ * strange behaviour from the users view,
3782+ * particularry setattr case
3783+ */
3784+ if (au_ibstart(dst_parent->d_inode) == bdst)
3785+ au_cpup_attr_nlink(dst_parent->d_inode,
3786+ /*force*/1);
3787+ au_cpup_attr_nlink(dentry->d_inode, /*force*/1);
3788+ }
3789+ break;
3790+ case S_IFLNK:
3791+ err = au_do_cpup_symlink(&h_path, h_src, h_dir);
3792+ break;
3793+ case S_IFCHR:
3794+ case S_IFBLK:
3795+ AuDebugOn(!capable(CAP_MKNOD));
3796+ /*FALLTHROUGH*/
3797+ case S_IFIFO:
3798+ case S_IFSOCK:
3799+ err = vfsub_mknod(h_dir, &h_path, mode, h_inode->i_rdev);
3800+ break;
3801+ default:
3802+ AuIOErr("Unknown inode type 0%o\n", mode);
3803+ err = -EIO;
3804+ }
3805+
3806+ mnt_flags = au_mntflags(sb);
3807+ if (!au_opt_test(mnt_flags, UDBA_NONE)
3808+ && !isdir
3809+ && au_opt_test(mnt_flags, XINO)
3810+ && h_inode->i_nlink == 1
3811+ /* todo: unnecessary? */
3812+ /* && dentry->d_inode->i_nlink == 1 */
3813+ && bdst < bsrc
3814+ && !au_ftest_cpup(flags, KEEPLINO))
1308ab2a 3815+ au_xino_write(sb, bsrc, h_inode->i_ino, /*ino*/0);
1facf9fc 3816+ /* ignore this error */
3817+
3818+ if (do_dt)
3819+ au_dtime_revert(&dt);
3820+ return err;
3821+}
3822+
3823+/*
3824+ * copyup the @dentry from @bsrc to @bdst.
3825+ * the caller must set the both of lower dentries.
3826+ * @len is for truncating when it is -1 copyup the entire file.
3827+ * in link/rename cases, @dst_parent may be different from the real one.
3828+ */
3829+static int au_cpup_single(struct dentry *dentry, aufs_bindex_t bdst,
3830+ aufs_bindex_t bsrc, loff_t len, unsigned int flags,
3831+ struct dentry *dst_parent)
3832+{
3833+ int err, rerr;
3834+ aufs_bindex_t old_ibstart;
3835+ unsigned char isdir, plink;
3836+ struct au_dtime dt;
3837+ struct path h_path;
3838+ struct dentry *h_src, *h_dst, *h_parent;
3839+ struct inode *dst_inode, *h_dir, *inode;
3840+ struct super_block *sb;
3841+
3842+ AuDebugOn(bsrc <= bdst);
3843+
3844+ sb = dentry->d_sb;
3845+ h_path.mnt = au_sbr_mnt(sb, bdst);
3846+ h_dst = au_h_dptr(dentry, bdst);
3847+ h_parent = h_dst->d_parent; /* dir inode is locked */
3848+ h_dir = h_parent->d_inode;
3849+ IMustLock(h_dir);
3850+
3851+ h_src = au_h_dptr(dentry, bsrc);
3852+ inode = dentry->d_inode;
3853+
3854+ if (!dst_parent)
3855+ dst_parent = dget_parent(dentry);
3856+ else
3857+ dget(dst_parent);
3858+
3859+ plink = !!au_opt_test(au_mntflags(sb), PLINK);
3860+ dst_inode = au_h_iptr(inode, bdst);
3861+ if (dst_inode) {
3862+ if (unlikely(!plink)) {
3863+ err = -EIO;
027c5e7a
AM
3864+ AuIOErr("hi%lu(i%lu) exists on b%d "
3865+ "but plink is disabled\n",
3866+ dst_inode->i_ino, inode->i_ino, bdst);
1facf9fc 3867+ goto out;
3868+ }
3869+
3870+ if (dst_inode->i_nlink) {
3871+ const int do_dt = au_ftest_cpup(flags, DTIME);
3872+
3873+ h_src = au_plink_lkup(inode, bdst);
3874+ err = PTR_ERR(h_src);
3875+ if (IS_ERR(h_src))
3876+ goto out;
3877+ if (unlikely(!h_src->d_inode)) {
3878+ err = -EIO;
3879+ AuIOErr("i%lu exists on a upper branch "
027c5e7a
AM
3880+ "but not pseudo-linked\n",
3881+ inode->i_ino);
1facf9fc 3882+ dput(h_src);
3883+ goto out;
3884+ }
3885+
3886+ if (do_dt) {
3887+ h_path.dentry = h_parent;
3888+ au_dtime_store(&dt, dst_parent, &h_path);
3889+ }
3890+ h_path.dentry = h_dst;
3891+ err = vfsub_link(h_src, h_dir, &h_path);
3892+ if (do_dt)
3893+ au_dtime_revert(&dt);
3894+ dput(h_src);
3895+ goto out;
3896+ } else
3897+ /* todo: cpup_wh_file? */
3898+ /* udba work */
4a4d8108 3899+ au_update_ibrange(inode, /*do_put_zero*/1);
1facf9fc 3900+ }
3901+
3902+ old_ibstart = au_ibstart(inode);
3903+ err = cpup_entry(dentry, bdst, bsrc, len, flags, dst_parent);
3904+ if (unlikely(err))
3905+ goto out;
3906+ dst_inode = h_dst->d_inode;
3907+ mutex_lock_nested(&dst_inode->i_mutex, AuLsc_I_CHILD2);
3908+
3909+ err = cpup_iattr(dentry, bdst, h_src);
3910+ isdir = S_ISDIR(dst_inode->i_mode);
3911+ if (!err) {
4a4d8108
AM
3912+ if (bdst < old_ibstart) {
3913+ if (S_ISREG(inode->i_mode)) {
3914+ err = au_dy_iaop(inode, bdst, dst_inode);
3915+ if (unlikely(err))
3916+ goto out_rev;
3917+ }
1facf9fc 3918+ au_set_ibstart(inode, bdst);
4a4d8108 3919+ }
1facf9fc 3920+ au_set_h_iptr(inode, bdst, au_igrab(dst_inode),
3921+ au_hi_flags(inode, isdir));
3922+ mutex_unlock(&dst_inode->i_mutex);
3923+ if (!isdir
3924+ && h_src->d_inode->i_nlink > 1
3925+ && plink)
3926+ au_plink_append(inode, bdst, h_dst);
3927+ goto out; /* success */
3928+ }
3929+
3930+ /* revert */
4a4d8108 3931+out_rev:
1facf9fc 3932+ h_path.dentry = h_parent;
3933+ mutex_unlock(&dst_inode->i_mutex);
3934+ au_dtime_store(&dt, dst_parent, &h_path);
3935+ h_path.dentry = h_dst;
3936+ if (!isdir)
3937+ rerr = vfsub_unlink(h_dir, &h_path, /*force*/0);
3938+ else
3939+ rerr = vfsub_rmdir(h_dir, &h_path);
3940+ au_dtime_revert(&dt);
3941+ if (rerr) {
3942+ AuIOErr("failed removing broken entry(%d, %d)\n", err, rerr);
3943+ err = -EIO;
3944+ }
3945+
4f0767ce 3946+out:
1facf9fc 3947+ dput(dst_parent);
3948+ return err;
3949+}
3950+
3951+struct au_cpup_single_args {
3952+ int *errp;
3953+ struct dentry *dentry;
3954+ aufs_bindex_t bdst, bsrc;
3955+ loff_t len;
3956+ unsigned int flags;
3957+ struct dentry *dst_parent;
3958+};
3959+
3960+static void au_call_cpup_single(void *args)
3961+{
3962+ struct au_cpup_single_args *a = args;
3963+ *a->errp = au_cpup_single(a->dentry, a->bdst, a->bsrc, a->len,
3964+ a->flags, a->dst_parent);
3965+}
3966+
53392da6
AM
3967+/*
3968+ * prevent SIGXFSZ in copy-up.
3969+ * testing CAP_MKNOD is for generic fs,
3970+ * but CAP_FSETID is for xfs only, currently.
3971+ */
3972+static int au_cpup_sio_test(struct super_block *sb, umode_t mode)
3973+{
3974+ int do_sio;
3975+
3976+ do_sio = 0;
3977+ if (!au_wkq_test()
3978+ && (!au_sbi(sb)->si_plink_maint_pid
3979+ || au_plink_maint(sb, AuLock_NOPLM))) {
3980+ switch (mode & S_IFMT) {
3981+ case S_IFREG:
3982+ /* no condition about RLIMIT_FSIZE and the file size */
3983+ do_sio = 1;
3984+ break;
3985+ case S_IFCHR:
3986+ case S_IFBLK:
3987+ do_sio = !capable(CAP_MKNOD);
3988+ break;
3989+ }
3990+ if (!do_sio)
3991+ do_sio = ((mode & (S_ISUID | S_ISGID))
3992+ && !capable(CAP_FSETID));
3993+ }
3994+
3995+ return do_sio;
3996+}
3997+
1facf9fc 3998+int au_sio_cpup_single(struct dentry *dentry, aufs_bindex_t bdst,
3999+ aufs_bindex_t bsrc, loff_t len, unsigned int flags,
4000+ struct dentry *dst_parent)
4001+{
4002+ int err, wkq_err;
1facf9fc 4003+ struct dentry *h_dentry;
4004+
4005+ h_dentry = au_h_dptr(dentry, bsrc);
53392da6 4006+ if (!au_cpup_sio_test(dentry->d_sb, h_dentry->d_inode->i_mode))
1facf9fc 4007+ err = au_cpup_single(dentry, bdst, bsrc, len, flags,
4008+ dst_parent);
4009+ else {
4010+ struct au_cpup_single_args args = {
4011+ .errp = &err,
4012+ .dentry = dentry,
4013+ .bdst = bdst,
4014+ .bsrc = bsrc,
4015+ .len = len,
4016+ .flags = flags,
4017+ .dst_parent = dst_parent
4018+ };
4019+ wkq_err = au_wkq_wait(au_call_cpup_single, &args);
4020+ if (unlikely(wkq_err))
4021+ err = wkq_err;
4022+ }
4023+
4024+ return err;
4025+}
4026+
4027+/*
4028+ * copyup the @dentry from the first active lower branch to @bdst,
4029+ * using au_cpup_single().
4030+ */
4031+static int au_cpup_simple(struct dentry *dentry, aufs_bindex_t bdst, loff_t len,
4032+ unsigned int flags)
4033+{
4034+ int err;
4035+ aufs_bindex_t bsrc, bend;
4036+
4037+ bend = au_dbend(dentry);
4038+ for (bsrc = bdst + 1; bsrc <= bend; bsrc++)
4039+ if (au_h_dptr(dentry, bsrc))
4040+ break;
4041+
4042+ err = au_lkup_neg(dentry, bdst);
4043+ if (!err) {
4044+ err = au_cpup_single(dentry, bdst, bsrc, len, flags, NULL);
4045+ if (!err)
4046+ return 0; /* success */
4047+
4048+ /* revert */
4049+ au_set_h_dptr(dentry, bdst, NULL);
4050+ au_set_dbstart(dentry, bsrc);
4051+ }
4052+
4053+ return err;
4054+}
4055+
4056+struct au_cpup_simple_args {
4057+ int *errp;
4058+ struct dentry *dentry;
4059+ aufs_bindex_t bdst;
4060+ loff_t len;
4061+ unsigned int flags;
4062+};
4063+
4064+static void au_call_cpup_simple(void *args)
4065+{
4066+ struct au_cpup_simple_args *a = args;
4067+ *a->errp = au_cpup_simple(a->dentry, a->bdst, a->len, a->flags);
4068+}
4069+
4070+int au_sio_cpup_simple(struct dentry *dentry, aufs_bindex_t bdst, loff_t len,
4071+ unsigned int flags)
4072+{
4073+ int err, wkq_err;
1facf9fc 4074+ struct dentry *parent;
4075+ struct inode *h_dir;
4076+
4077+ parent = dget_parent(dentry);
4078+ h_dir = au_h_iptr(parent->d_inode, bdst);
53392da6
AM
4079+ if (!au_test_h_perm_sio(h_dir, MAY_EXEC | MAY_WRITE)
4080+ && !au_cpup_sio_test(dentry->d_sb, dentry->d_inode->i_mode))
1facf9fc 4081+ err = au_cpup_simple(dentry, bdst, len, flags);
4082+ else {
4083+ struct au_cpup_simple_args args = {
4084+ .errp = &err,
4085+ .dentry = dentry,
4086+ .bdst = bdst,
4087+ .len = len,
4088+ .flags = flags
4089+ };
4090+ wkq_err = au_wkq_wait(au_call_cpup_simple, &args);
4091+ if (unlikely(wkq_err))
4092+ err = wkq_err;
4093+ }
4094+
4095+ dput(parent);
4096+ return err;
4097+}
4098+
4099+/* ---------------------------------------------------------------------- */
4100+
4101+/*
4102+ * copyup the deleted file for writing.
4103+ */
4104+static int au_do_cpup_wh(struct dentry *dentry, aufs_bindex_t bdst,
4105+ struct dentry *wh_dentry, struct file *file,
4106+ loff_t len)
4107+{
4108+ int err;
4109+ aufs_bindex_t bstart;
4110+ struct au_dinfo *dinfo;
4111+ struct dentry *h_d_dst, *h_d_start;
4a4d8108 4112+ struct au_hdentry *hdp;
1facf9fc 4113+
4114+ dinfo = au_di(dentry);
1308ab2a 4115+ AuRwMustWriteLock(&dinfo->di_rwsem);
4116+
1facf9fc 4117+ bstart = dinfo->di_bstart;
4a4d8108
AM
4118+ hdp = dinfo->di_hdentry;
4119+ h_d_dst = hdp[0 + bdst].hd_dentry;
1facf9fc 4120+ dinfo->di_bstart = bdst;
4a4d8108 4121+ hdp[0 + bdst].hd_dentry = wh_dentry;
027c5e7a
AM
4122+ if (file) {
4123+ h_d_start = hdp[0 + bstart].hd_dentry;
4a4d8108 4124+ hdp[0 + bstart].hd_dentry = au_hf_top(file)->f_dentry;
027c5e7a 4125+ }
1facf9fc 4126+ err = au_cpup_single(dentry, bdst, bstart, len, !AuCpup_DTIME,
4127+ /*h_parent*/NULL);
027c5e7a
AM
4128+ if (file) {
4129+ if (!err)
4130+ err = au_reopen_nondir(file);
4a4d8108 4131+ hdp[0 + bstart].hd_dentry = h_d_start;
1facf9fc 4132+ }
4a4d8108 4133+ hdp[0 + bdst].hd_dentry = h_d_dst;
1facf9fc 4134+ dinfo->di_bstart = bstart;
4135+
4136+ return err;
4137+}
4138+
4139+static int au_cpup_wh(struct dentry *dentry, aufs_bindex_t bdst, loff_t len,
4140+ struct file *file)
4141+{
4142+ int err;
4143+ struct au_dtime dt;
4144+ struct dentry *parent, *h_parent, *wh_dentry;
4145+ struct au_branch *br;
4146+ struct path h_path;
4147+
4148+ br = au_sbr(dentry->d_sb, bdst);
4149+ parent = dget_parent(dentry);
4150+ h_parent = au_h_dptr(parent, bdst);
4151+ wh_dentry = au_whtmp_lkup(h_parent, br, &dentry->d_name);
4152+ err = PTR_ERR(wh_dentry);
4153+ if (IS_ERR(wh_dentry))
4154+ goto out;
4155+
4156+ h_path.dentry = h_parent;
4157+ h_path.mnt = br->br_mnt;
4158+ au_dtime_store(&dt, parent, &h_path);
4159+ err = au_do_cpup_wh(dentry, bdst, wh_dentry, file, len);
4160+ if (unlikely(err))
4161+ goto out_wh;
4162+
4163+ dget(wh_dentry);
4164+ h_path.dentry = wh_dentry;
4a4d8108
AM
4165+ if (!S_ISDIR(wh_dentry->d_inode->i_mode))
4166+ err = vfsub_unlink(h_parent->d_inode, &h_path, /*force*/0);
4167+ else
4168+ err = vfsub_rmdir(h_parent->d_inode, &h_path);
1facf9fc 4169+ if (unlikely(err)) {
4170+ AuIOErr("failed remove copied-up tmp file %.*s(%d)\n",
4171+ AuDLNPair(wh_dentry), err);
4172+ err = -EIO;
4173+ }
4174+ au_dtime_revert(&dt);
4175+ au_set_hi_wh(dentry->d_inode, bdst, wh_dentry);
4176+
4f0767ce 4177+out_wh:
1facf9fc 4178+ dput(wh_dentry);
4f0767ce 4179+out:
1facf9fc 4180+ dput(parent);
4181+ return err;
4182+}
4183+
4184+struct au_cpup_wh_args {
4185+ int *errp;
4186+ struct dentry *dentry;
4187+ aufs_bindex_t bdst;
4188+ loff_t len;
4189+ struct file *file;
4190+};
4191+
4192+static void au_call_cpup_wh(void *args)
4193+{
4194+ struct au_cpup_wh_args *a = args;
4195+ *a->errp = au_cpup_wh(a->dentry, a->bdst, a->len, a->file);
4196+}
4197+
4198+int au_sio_cpup_wh(struct dentry *dentry, aufs_bindex_t bdst, loff_t len,
4199+ struct file *file)
4200+{
4201+ int err, wkq_err;
4202+ struct dentry *parent, *h_orph, *h_parent, *h_dentry;
4203+ struct inode *dir, *h_dir, *h_tmpdir, *h_inode;
4204+ struct au_wbr *wbr;
4205+
4206+ parent = dget_parent(dentry);
4207+ dir = parent->d_inode;
4208+ h_orph = NULL;
4209+ h_parent = NULL;
4210+ h_dir = au_igrab(au_h_iptr(dir, bdst));
4211+ h_tmpdir = h_dir;
4212+ if (!h_dir->i_nlink) {
4213+ wbr = au_sbr(dentry->d_sb, bdst)->br_wbr;
4214+ h_orph = wbr->wbr_orph;
4215+
4216+ h_parent = dget(au_h_dptr(parent, bdst));
1facf9fc 4217+ au_set_h_dptr(parent, bdst, dget(h_orph));
4218+ h_tmpdir = h_orph->d_inode;
1facf9fc 4219+ au_set_h_iptr(dir, bdst, au_igrab(h_tmpdir), /*flags*/0);
4220+
4221+ /* this temporary unlock is safe */
4222+ if (file)
4a4d8108 4223+ h_dentry = au_hf_top(file)->f_dentry;
1facf9fc 4224+ else
4225+ h_dentry = au_h_dptr(dentry, au_dbstart(dentry));
4226+ h_inode = h_dentry->d_inode;
4227+ IMustLock(h_inode);
4228+ mutex_unlock(&h_inode->i_mutex);
dece6358 4229+ mutex_lock_nested(&h_tmpdir->i_mutex, AuLsc_I_PARENT3);
1facf9fc 4230+ mutex_lock_nested(&h_inode->i_mutex, AuLsc_I_CHILD);
4a4d8108 4231+ /* todo: au_h_open_pre()? */
1facf9fc 4232+ }
4233+
53392da6
AM
4234+ if (!au_test_h_perm_sio(h_tmpdir, MAY_EXEC | MAY_WRITE)
4235+ && !au_cpup_sio_test(dentry->d_sb, dentry->d_inode->i_mode))
1facf9fc 4236+ err = au_cpup_wh(dentry, bdst, len, file);
4237+ else {
4238+ struct au_cpup_wh_args args = {
4239+ .errp = &err,
4240+ .dentry = dentry,
4241+ .bdst = bdst,
4242+ .len = len,
4243+ .file = file
4244+ };
4245+ wkq_err = au_wkq_wait(au_call_cpup_wh, &args);
4246+ if (unlikely(wkq_err))
4247+ err = wkq_err;
4248+ }
4249+
4250+ if (h_orph) {
4251+ mutex_unlock(&h_tmpdir->i_mutex);
4a4d8108 4252+ /* todo: au_h_open_post()? */
1facf9fc 4253+ au_set_h_iptr(dir, bdst, au_igrab(h_dir), /*flags*/0);
1facf9fc 4254+ au_set_h_dptr(parent, bdst, h_parent);
4255+ }
4256+ iput(h_dir);
4257+ dput(parent);
4258+
4259+ return err;
4260+}
4261+
4262+/* ---------------------------------------------------------------------- */
4263+
4264+/*
4265+ * generic routine for both of copy-up and copy-down.
4266+ */
4267+/* cf. revalidate function in file.c */
4268+int au_cp_dirs(struct dentry *dentry, aufs_bindex_t bdst,
4269+ int (*cp)(struct dentry *dentry, aufs_bindex_t bdst,
4270+ struct dentry *h_parent, void *arg),
4271+ void *arg)
4272+{
4273+ int err;
4274+ struct au_pin pin;
4275+ struct dentry *d, *parent, *h_parent, *real_parent;
4276+
4277+ err = 0;
4278+ parent = dget_parent(dentry);
4279+ if (IS_ROOT(parent))
4280+ goto out;
4281+
4282+ au_pin_init(&pin, dentry, bdst, AuLsc_DI_PARENT2, AuLsc_I_PARENT2,
4283+ au_opt_udba(dentry->d_sb), AuPin_MNT_WRITE);
4284+
4285+ /* do not use au_dpage */
4286+ real_parent = parent;
4287+ while (1) {
4288+ dput(parent);
4289+ parent = dget_parent(dentry);
4290+ h_parent = au_h_dptr(parent, bdst);
4291+ if (h_parent)
4292+ goto out; /* success */
4293+
4294+ /* find top dir which is necessary to cpup */
4295+ do {
4296+ d = parent;
4297+ dput(parent);
4298+ parent = dget_parent(d);
4299+ di_read_lock_parent3(parent, !AuLock_IR);
4300+ h_parent = au_h_dptr(parent, bdst);
4301+ di_read_unlock(parent, !AuLock_IR);
4302+ } while (!h_parent);
4303+
4304+ if (d != real_parent)
4305+ di_write_lock_child3(d);
4306+
4307+ /* somebody else might create while we were sleeping */
4308+ if (!au_h_dptr(d, bdst) || !au_h_dptr(d, bdst)->d_inode) {
4309+ if (au_h_dptr(d, bdst))
4310+ au_update_dbstart(d);
4311+
4312+ au_pin_set_dentry(&pin, d);
4313+ err = au_do_pin(&pin);
4314+ if (!err) {
4315+ err = cp(d, bdst, h_parent, arg);
4316+ au_unpin(&pin);
4317+ }
4318+ }
4319+
4320+ if (d != real_parent)
4321+ di_write_unlock(d);
4322+ if (unlikely(err))
4323+ break;
4324+ }
4325+
4f0767ce 4326+out:
1facf9fc 4327+ dput(parent);
4328+ return err;
4329+}
4330+
4331+static int au_cpup_dir(struct dentry *dentry, aufs_bindex_t bdst,
4332+ struct dentry *h_parent __maybe_unused ,
4333+ void *arg __maybe_unused)
4334+{
4335+ return au_sio_cpup_simple(dentry, bdst, -1, AuCpup_DTIME);
4336+}
4337+
4338+int au_cpup_dirs(struct dentry *dentry, aufs_bindex_t bdst)
4339+{
4340+ return au_cp_dirs(dentry, bdst, au_cpup_dir, NULL);
4341+}
4342+
4343+int au_test_and_cpup_dirs(struct dentry *dentry, aufs_bindex_t bdst)
4344+{
4345+ int err;
4346+ struct dentry *parent;
4347+ struct inode *dir;
4348+
4349+ parent = dget_parent(dentry);
4350+ dir = parent->d_inode;
4351+ err = 0;
4352+ if (au_h_iptr(dir, bdst))
4353+ goto out;
4354+
4355+ di_read_unlock(parent, AuLock_IR);
4356+ di_write_lock_parent(parent);
4357+ /* someone else might change our inode while we were sleeping */
4358+ if (!au_h_iptr(dir, bdst))
4359+ err = au_cpup_dirs(dentry, bdst);
4360+ di_downgrade_lock(parent, AuLock_IR);
4361+
4f0767ce 4362+out:
1facf9fc 4363+ dput(parent);
4364+ return err;
4365+}
7f207e10
AM
4366diff -urN /usr/share/empty/fs/aufs/cpup.h linux/fs/aufs/cpup.h
4367--- /usr/share/empty/fs/aufs/cpup.h 1970-01-01 01:00:00.000000000 +0100
2dfbb274 4368+++ linux/fs/aufs/cpup.h 2012-08-26 08:39:00.757174634 +0200
f6c5ef8b 4369@@ -0,0 +1,81 @@
1facf9fc 4370+/*
f6c5ef8b 4371+ * Copyright (C) 2005-2012 Junjiro R. Okajima
1facf9fc 4372+ *
4373+ * This program, aufs is free software; you can redistribute it and/or modify
4374+ * it under the terms of the GNU General Public License as published by
4375+ * the Free Software Foundation; either version 2 of the License, or
4376+ * (at your option) any later version.
dece6358
AM
4377+ *
4378+ * This program is distributed in the hope that it will be useful,
4379+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
4380+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
4381+ * GNU General Public License for more details.
4382+ *
4383+ * You should have received a copy of the GNU General Public License
4384+ * along with this program; if not, write to the Free Software
4385+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 4386+ */
4387+
4388+/*
4389+ * copy-up/down functions
4390+ */
4391+
4392+#ifndef __AUFS_CPUP_H__
4393+#define __AUFS_CPUP_H__
4394+
4395+#ifdef __KERNEL__
4396+
dece6358 4397+#include <linux/path.h>
1facf9fc 4398+
dece6358
AM
4399+struct inode;
4400+struct file;
4401+
1facf9fc 4402+void au_cpup_attr_flags(struct inode *dst, struct inode *src);
4403+void au_cpup_attr_timesizes(struct inode *inode);
4404+void au_cpup_attr_nlink(struct inode *inode, int force);
4405+void au_cpup_attr_changeable(struct inode *inode);
4406+void au_cpup_igen(struct inode *inode, struct inode *h_inode);
4407+void au_cpup_attr_all(struct inode *inode, int force);
4408+
4409+/* ---------------------------------------------------------------------- */
4410+
4411+/* cpup flags */
4412+#define AuCpup_DTIME 1 /* do dtime_store/revert */
4413+#define AuCpup_KEEPLINO (1 << 1) /* do not clear the lower xino,
4414+ for link(2) */
4415+#define au_ftest_cpup(flags, name) ((flags) & AuCpup_##name)
7f207e10
AM
4416+#define au_fset_cpup(flags, name) \
4417+ do { (flags) |= AuCpup_##name; } while (0)
4418+#define au_fclr_cpup(flags, name) \
4419+ do { (flags) &= ~AuCpup_##name; } while (0)
1facf9fc 4420+
4421+int au_copy_file(struct file *dst, struct file *src, loff_t len);
4422+int au_sio_cpup_single(struct dentry *dentry, aufs_bindex_t bdst,
4423+ aufs_bindex_t bsrc, loff_t len, unsigned int flags,
4424+ struct dentry *dst_parent);
4425+int au_sio_cpup_simple(struct dentry *dentry, aufs_bindex_t bdst, loff_t len,
4426+ unsigned int flags);
4427+int au_sio_cpup_wh(struct dentry *dentry, aufs_bindex_t bdst, loff_t len,
4428+ struct file *file);
4429+
4430+int au_cp_dirs(struct dentry *dentry, aufs_bindex_t bdst,
4431+ int (*cp)(struct dentry *dentry, aufs_bindex_t bdst,
4432+ struct dentry *h_parent, void *arg),
4433+ void *arg);
4434+int au_cpup_dirs(struct dentry *dentry, aufs_bindex_t bdst);
4435+int au_test_and_cpup_dirs(struct dentry *dentry, aufs_bindex_t bdst);
4436+
4437+/* ---------------------------------------------------------------------- */
4438+
4439+/* keep timestamps when copyup */
4440+struct au_dtime {
4441+ struct dentry *dt_dentry;
4442+ struct path dt_h_path;
4443+ struct timespec dt_atime, dt_mtime;
4444+};
4445+void au_dtime_store(struct au_dtime *dt, struct dentry *dentry,
4446+ struct path *h_path);
4447+void au_dtime_revert(struct au_dtime *dt);
4448+
4449+#endif /* __KERNEL__ */
4450+#endif /* __AUFS_CPUP_H__ */
7f207e10
AM
4451diff -urN /usr/share/empty/fs/aufs/dbgaufs.c linux/fs/aufs/dbgaufs.c
4452--- /usr/share/empty/fs/aufs/dbgaufs.c 1970-01-01 01:00:00.000000000 +0100
2dfbb274 4453+++ linux/fs/aufs/dbgaufs.c 2012-08-26 08:39:00.757174634 +0200
4a4d8108 4454@@ -0,0 +1,334 @@
1facf9fc 4455+/*
f6c5ef8b 4456+ * Copyright (C) 2005-2012 Junjiro R. Okajima
1facf9fc 4457+ *
4458+ * This program, aufs is free software; you can redistribute it and/or modify
4459+ * it under the terms of the GNU General Public License as published by
4460+ * the Free Software Foundation; either version 2 of the License, or
4461+ * (at your option) any later version.
dece6358
AM
4462+ *
4463+ * This program is distributed in the hope that it will be useful,
4464+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
4465+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
4466+ * GNU General Public License for more details.
4467+ *
4468+ * You should have received a copy of the GNU General Public License
4469+ * along with this program; if not, write to the Free Software
4470+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 4471+ */
4472+
4473+/*
4474+ * debugfs interface
4475+ */
4476+
4477+#include <linux/debugfs.h>
4478+#include "aufs.h"
4479+
4480+#ifndef CONFIG_SYSFS
4481+#error DEBUG_FS depends upon SYSFS
4482+#endif
4483+
4484+static struct dentry *dbgaufs;
4485+static const mode_t dbgaufs_mode = S_IRUSR | S_IRGRP | S_IROTH;
4486+
4487+/* 20 is max digits length of ulong 64 */
4488+struct dbgaufs_arg {
4489+ int n;
4490+ char a[20 * 4];
4491+};
4492+
4493+/*
4494+ * common function for all XINO files
4495+ */
4496+static int dbgaufs_xi_release(struct inode *inode __maybe_unused,
4497+ struct file *file)
4498+{
4499+ kfree(file->private_data);
4500+ return 0;
4501+}
4502+
4503+static int dbgaufs_xi_open(struct file *xf, struct file *file, int do_fcnt)
4504+{
4505+ int err;
4506+ struct kstat st;
4507+ struct dbgaufs_arg *p;
4508+
4509+ err = -ENOMEM;
4510+ p = kmalloc(sizeof(*p), GFP_NOFS);
4511+ if (unlikely(!p))
4512+ goto out;
4513+
4514+ err = 0;
4515+ p->n = 0;
4516+ file->private_data = p;
4517+ if (!xf)
4518+ goto out;
4519+
4520+ err = vfs_getattr(xf->f_vfsmnt, xf->f_dentry, &st);
4521+ if (!err) {
4522+ if (do_fcnt)
4523+ p->n = snprintf
4524+ (p->a, sizeof(p->a), "%ld, %llux%lu %lld\n",
4525+ (long)file_count(xf), st.blocks, st.blksize,
4526+ (long long)st.size);
4527+ else
4528+ p->n = snprintf(p->a, sizeof(p->a), "%llux%lu %lld\n",
4529+ st.blocks, st.blksize,
4530+ (long long)st.size);
4531+ AuDebugOn(p->n >= sizeof(p->a));
4532+ } else {
4533+ p->n = snprintf(p->a, sizeof(p->a), "err %d\n", err);
4534+ err = 0;
4535+ }
4536+
4f0767ce 4537+out:
1facf9fc 4538+ return err;
4539+
4540+}
4541+
4542+static ssize_t dbgaufs_xi_read(struct file *file, char __user *buf,
4543+ size_t count, loff_t *ppos)
4544+{
4545+ struct dbgaufs_arg *p;
4546+
4547+ p = file->private_data;
4548+ return simple_read_from_buffer(buf, count, ppos, p->a, p->n);
4549+}
4550+
4551+/* ---------------------------------------------------------------------- */
4552+
4553+static int dbgaufs_xib_open(struct inode *inode, struct file *file)
4554+{
4555+ int err;
4556+ struct au_sbinfo *sbinfo;
4557+ struct super_block *sb;
4558+
4559+ sbinfo = inode->i_private;
4560+ sb = sbinfo->si_sb;
4561+ si_noflush_read_lock(sb);
4562+ err = dbgaufs_xi_open(sbinfo->si_xib, file, /*do_fcnt*/0);
4563+ si_read_unlock(sb);
4564+ return err;
4565+}
4566+
4567+static const struct file_operations dbgaufs_xib_fop = {
4a4d8108 4568+ .owner = THIS_MODULE,
1facf9fc 4569+ .open = dbgaufs_xib_open,
4570+ .release = dbgaufs_xi_release,
4571+ .read = dbgaufs_xi_read
4572+};
4573+
4574+/* ---------------------------------------------------------------------- */
4575+
4576+#define DbgaufsXi_PREFIX "xi"
4577+
4578+static int dbgaufs_xino_open(struct inode *inode, struct file *file)
4579+{
4580+ int err;
4581+ long l;
4582+ struct au_sbinfo *sbinfo;
4583+ struct super_block *sb;
4584+ struct file *xf;
4585+ struct qstr *name;
4586+
4587+ err = -ENOENT;
4588+ xf = NULL;
4589+ name = &file->f_dentry->d_name;
4590+ if (unlikely(name->len < sizeof(DbgaufsXi_PREFIX)
4591+ || memcmp(name->name, DbgaufsXi_PREFIX,
4592+ sizeof(DbgaufsXi_PREFIX) - 1)))
4593+ goto out;
9dbd164d 4594+ err = kstrtol(name->name + sizeof(DbgaufsXi_PREFIX) - 1, 10, &l);
1facf9fc 4595+ if (unlikely(err))
4596+ goto out;
4597+
4598+ sbinfo = inode->i_private;
4599+ sb = sbinfo->si_sb;
4600+ si_noflush_read_lock(sb);
4601+ if (l <= au_sbend(sb)) {
4602+ xf = au_sbr(sb, (aufs_bindex_t)l)->br_xino.xi_file;
4603+ err = dbgaufs_xi_open(xf, file, /*do_fcnt*/1);
4604+ } else
4605+ err = -ENOENT;
4606+ si_read_unlock(sb);
4607+
4f0767ce 4608+out:
1facf9fc 4609+ return err;
4610+}
4611+
4612+static const struct file_operations dbgaufs_xino_fop = {
4a4d8108 4613+ .owner = THIS_MODULE,
1facf9fc 4614+ .open = dbgaufs_xino_open,
4615+ .release = dbgaufs_xi_release,
4616+ .read = dbgaufs_xi_read
4617+};
4618+
4619+void dbgaufs_brs_del(struct super_block *sb, aufs_bindex_t bindex)
4620+{
4621+ aufs_bindex_t bend;
4622+ struct au_branch *br;
4623+ struct au_xino_file *xi;
4624+
4625+ if (!au_sbi(sb)->si_dbgaufs)
4626+ return;
4627+
4628+ bend = au_sbend(sb);
4629+ for (; bindex <= bend; bindex++) {
4630+ br = au_sbr(sb, bindex);
4631+ xi = &br->br_xino;
4632+ if (xi->xi_dbgaufs) {
4633+ debugfs_remove(xi->xi_dbgaufs);
4634+ xi->xi_dbgaufs = NULL;
4635+ }
4636+ }
4637+}
4638+
4639+void dbgaufs_brs_add(struct super_block *sb, aufs_bindex_t bindex)
4640+{
4641+ struct au_sbinfo *sbinfo;
4642+ struct dentry *parent;
4643+ struct au_branch *br;
4644+ struct au_xino_file *xi;
4645+ aufs_bindex_t bend;
4646+ char name[sizeof(DbgaufsXi_PREFIX) + 5]; /* "xi" bindex NULL */
4647+
4648+ sbinfo = au_sbi(sb);
4649+ parent = sbinfo->si_dbgaufs;
4650+ if (!parent)
4651+ return;
4652+
4653+ bend = au_sbend(sb);
4654+ for (; bindex <= bend; bindex++) {
4655+ snprintf(name, sizeof(name), DbgaufsXi_PREFIX "%d", bindex);
4656+ br = au_sbr(sb, bindex);
4657+ xi = &br->br_xino;
4658+ AuDebugOn(xi->xi_dbgaufs);
4659+ xi->xi_dbgaufs = debugfs_create_file(name, dbgaufs_mode, parent,
4660+ sbinfo, &dbgaufs_xino_fop);
4661+ /* ignore an error */
4662+ if (unlikely(!xi->xi_dbgaufs))
4663+ AuWarn1("failed %s under debugfs\n", name);
4664+ }
4665+}
4666+
4667+/* ---------------------------------------------------------------------- */
4668+
4669+#ifdef CONFIG_AUFS_EXPORT
4670+static int dbgaufs_xigen_open(struct inode *inode, struct file *file)
4671+{
4672+ int err;
4673+ struct au_sbinfo *sbinfo;
4674+ struct super_block *sb;
4675+
4676+ sbinfo = inode->i_private;
4677+ sb = sbinfo->si_sb;
4678+ si_noflush_read_lock(sb);
4679+ err = dbgaufs_xi_open(sbinfo->si_xigen, file, /*do_fcnt*/0);
4680+ si_read_unlock(sb);
4681+ return err;
4682+}
4683+
4684+static const struct file_operations dbgaufs_xigen_fop = {
4a4d8108 4685+ .owner = THIS_MODULE,
1facf9fc 4686+ .open = dbgaufs_xigen_open,
4687+ .release = dbgaufs_xi_release,
4688+ .read = dbgaufs_xi_read
4689+};
4690+
4691+static int dbgaufs_xigen_init(struct au_sbinfo *sbinfo)
4692+{
4693+ int err;
4694+
dece6358
AM
4695+ /*
4696+ * This function is a dynamic '__init' fucntion actually,
4697+ * so the tiny check for si_rwsem is unnecessary.
4698+ */
4699+ /* AuRwMustWriteLock(&sbinfo->si_rwsem); */
4700+
1facf9fc 4701+ err = -EIO;
4702+ sbinfo->si_dbgaufs_xigen = debugfs_create_file
4703+ ("xigen", dbgaufs_mode, sbinfo->si_dbgaufs, sbinfo,
4704+ &dbgaufs_xigen_fop);
4705+ if (sbinfo->si_dbgaufs_xigen)
4706+ err = 0;
4707+
4708+ return err;
4709+}
4710+#else
4711+static int dbgaufs_xigen_init(struct au_sbinfo *sbinfo)
4712+{
4713+ return 0;
4714+}
4715+#endif /* CONFIG_AUFS_EXPORT */
4716+
4717+/* ---------------------------------------------------------------------- */
4718+
4719+void dbgaufs_si_fin(struct au_sbinfo *sbinfo)
4720+{
dece6358
AM
4721+ /*
4722+ * This function is a dynamic '__init' fucntion actually,
4723+ * so the tiny check for si_rwsem is unnecessary.
4724+ */
4725+ /* AuRwMustWriteLock(&sbinfo->si_rwsem); */
4726+
1facf9fc 4727+ debugfs_remove_recursive(sbinfo->si_dbgaufs);
4728+ sbinfo->si_dbgaufs = NULL;
4729+ kobject_put(&sbinfo->si_kobj);
4730+}
4731+
4732+int dbgaufs_si_init(struct au_sbinfo *sbinfo)
4733+{
4734+ int err;
4735+ char name[SysaufsSiNameLen];
4736+
dece6358
AM
4737+ /*
4738+ * This function is a dynamic '__init' fucntion actually,
4739+ * so the tiny check for si_rwsem is unnecessary.
4740+ */
4741+ /* AuRwMustWriteLock(&sbinfo->si_rwsem); */
4742+
1facf9fc 4743+ err = -ENOENT;
4744+ if (!dbgaufs) {
4745+ AuErr1("/debug/aufs is uninitialized\n");
4746+ goto out;
4747+ }
4748+
4749+ err = -EIO;
4750+ sysaufs_name(sbinfo, name);
4751+ sbinfo->si_dbgaufs = debugfs_create_dir(name, dbgaufs);
4752+ if (unlikely(!sbinfo->si_dbgaufs))
4753+ goto out;
4754+ kobject_get(&sbinfo->si_kobj);
4755+
4756+ sbinfo->si_dbgaufs_xib = debugfs_create_file
4757+ ("xib", dbgaufs_mode, sbinfo->si_dbgaufs, sbinfo,
4758+ &dbgaufs_xib_fop);
4759+ if (unlikely(!sbinfo->si_dbgaufs_xib))
4760+ goto out_dir;
4761+
4762+ err = dbgaufs_xigen_init(sbinfo);
4763+ if (!err)
4764+ goto out; /* success */
4765+
4f0767ce 4766+out_dir:
1facf9fc 4767+ dbgaufs_si_fin(sbinfo);
4f0767ce 4768+out:
1facf9fc 4769+ return err;
4770+}
4771+
4772+/* ---------------------------------------------------------------------- */
4773+
4774+void dbgaufs_fin(void)
4775+{
4776+ debugfs_remove(dbgaufs);
4777+}
4778+
4779+int __init dbgaufs_init(void)
4780+{
4781+ int err;
4782+
4783+ err = -EIO;
4784+ dbgaufs = debugfs_create_dir(AUFS_NAME, NULL);
4785+ if (dbgaufs)
4786+ err = 0;
4787+ return err;
4788+}
7f207e10
AM
4789diff -urN /usr/share/empty/fs/aufs/dbgaufs.h linux/fs/aufs/dbgaufs.h
4790--- /usr/share/empty/fs/aufs/dbgaufs.h 1970-01-01 01:00:00.000000000 +0100
2dfbb274 4791+++ linux/fs/aufs/dbgaufs.h 2012-08-26 08:39:00.757174634 +0200
f6c5ef8b 4792@@ -0,0 +1,49 @@
1facf9fc 4793+/*
f6c5ef8b 4794+ * Copyright (C) 2005-2012 Junjiro R. Okajima
1facf9fc 4795+ *
4796+ * This program, aufs is free software; you can redistribute it and/or modify
4797+ * it under the terms of the GNU General Public License as published by
4798+ * the Free Software Foundation; either version 2 of the License, or
4799+ * (at your option) any later version.
dece6358
AM
4800+ *
4801+ * This program is distributed in the hope that it will be useful,
4802+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
4803+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
4804+ * GNU General Public License for more details.
4805+ *
4806+ * You should have received a copy of the GNU General Public License
4807+ * along with this program; if not, write to the Free Software
4808+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 4809+ */
4810+
4811+/*
4812+ * debugfs interface
4813+ */
4814+
4815+#ifndef __DBGAUFS_H__
4816+#define __DBGAUFS_H__
4817+
4818+#ifdef __KERNEL__
4819+
dece6358 4820+struct super_block;
1facf9fc 4821+struct au_sbinfo;
dece6358 4822+
1facf9fc 4823+#ifdef CONFIG_DEBUG_FS
4824+/* dbgaufs.c */
4825+void dbgaufs_brs_del(struct super_block *sb, aufs_bindex_t bindex);
4826+void dbgaufs_brs_add(struct super_block *sb, aufs_bindex_t bindex);
4827+void dbgaufs_si_fin(struct au_sbinfo *sbinfo);
4828+int dbgaufs_si_init(struct au_sbinfo *sbinfo);
4829+void dbgaufs_fin(void);
4830+int __init dbgaufs_init(void);
1facf9fc 4831+#else
4a4d8108
AM
4832+AuStubVoid(dbgaufs_brs_del, struct super_block *sb, aufs_bindex_t bindex)
4833+AuStubVoid(dbgaufs_brs_add, struct super_block *sb, aufs_bindex_t bindex)
4834+AuStubVoid(dbgaufs_si_fin, struct au_sbinfo *sbinfo)
4835+AuStubInt0(dbgaufs_si_init, struct au_sbinfo *sbinfo)
4836+AuStubVoid(dbgaufs_fin, void)
4837+AuStubInt0(__init dbgaufs_init, void)
1facf9fc 4838+#endif /* CONFIG_DEBUG_FS */
4839+
4840+#endif /* __KERNEL__ */
4841+#endif /* __DBGAUFS_H__ */
7f207e10
AM
4842diff -urN /usr/share/empty/fs/aufs/dcsub.c linux/fs/aufs/dcsub.c
4843--- /usr/share/empty/fs/aufs/dcsub.c 1970-01-01 01:00:00.000000000 +0100
2dfbb274 4844+++ linux/fs/aufs/dcsub.c 2012-08-26 08:39:00.757174634 +0200
027c5e7a 4845@@ -0,0 +1,243 @@
1facf9fc 4846+/*
f6c5ef8b 4847+ * Copyright (C) 2005-2012 Junjiro R. Okajima
1facf9fc 4848+ *
4849+ * This program, aufs is free software; you can redistribute it and/or modify
4850+ * it under the terms of the GNU General Public License as published by
4851+ * the Free Software Foundation; either version 2 of the License, or
4852+ * (at your option) any later version.
dece6358
AM
4853+ *
4854+ * This program is distributed in the hope that it will be useful,
4855+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
4856+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
4857+ * GNU General Public License for more details.
4858+ *
4859+ * You should have received a copy of the GNU General Public License
4860+ * along with this program; if not, write to the Free Software
4861+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 4862+ */
4863+
4864+/*
4865+ * sub-routines for dentry cache
4866+ */
4867+
4868+#include "aufs.h"
4869+
4870+static void au_dpage_free(struct au_dpage *dpage)
4871+{
4872+ int i;
4873+ struct dentry **p;
4874+
4875+ p = dpage->dentries;
4876+ for (i = 0; i < dpage->ndentry; i++)
4877+ dput(*p++);
4878+ free_page((unsigned long)dpage->dentries);
4879+}
4880+
4881+int au_dpages_init(struct au_dcsub_pages *dpages, gfp_t gfp)
4882+{
4883+ int err;
4884+ void *p;
4885+
4886+ err = -ENOMEM;
4887+ dpages->dpages = kmalloc(sizeof(*dpages->dpages), gfp);
4888+ if (unlikely(!dpages->dpages))
4889+ goto out;
4890+
4891+ p = (void *)__get_free_page(gfp);
4892+ if (unlikely(!p))
4893+ goto out_dpages;
4894+
4895+ dpages->dpages[0].ndentry = 0;
4896+ dpages->dpages[0].dentries = p;
4897+ dpages->ndpage = 1;
4898+ return 0; /* success */
4899+
4f0767ce 4900+out_dpages:
1facf9fc 4901+ kfree(dpages->dpages);
4f0767ce 4902+out:
1facf9fc 4903+ return err;
4904+}
4905+
4906+void au_dpages_free(struct au_dcsub_pages *dpages)
4907+{
4908+ int i;
4909+ struct au_dpage *p;
4910+
4911+ p = dpages->dpages;
4912+ for (i = 0; i < dpages->ndpage; i++)
4913+ au_dpage_free(p++);
4914+ kfree(dpages->dpages);
4915+}
4916+
4917+static int au_dpages_append(struct au_dcsub_pages *dpages,
4918+ struct dentry *dentry, gfp_t gfp)
4919+{
4920+ int err, sz;
4921+ struct au_dpage *dpage;
4922+ void *p;
4923+
4924+ dpage = dpages->dpages + dpages->ndpage - 1;
4925+ sz = PAGE_SIZE / sizeof(dentry);
4926+ if (unlikely(dpage->ndentry >= sz)) {
4927+ AuLabel(new dpage);
4928+ err = -ENOMEM;
4929+ sz = dpages->ndpage * sizeof(*dpages->dpages);
4930+ p = au_kzrealloc(dpages->dpages, sz,
4931+ sz + sizeof(*dpages->dpages), gfp);
4932+ if (unlikely(!p))
4933+ goto out;
4934+
4935+ dpages->dpages = p;
4936+ dpage = dpages->dpages + dpages->ndpage;
4937+ p = (void *)__get_free_page(gfp);
4938+ if (unlikely(!p))
4939+ goto out;
4940+
4941+ dpage->ndentry = 0;
4942+ dpage->dentries = p;
4943+ dpages->ndpage++;
4944+ }
4945+
027c5e7a
AM
4946+ AuDebugOn(!dentry->d_count);
4947+ dpage->dentries[dpage->ndentry++] = dget_dlock(dentry);
1facf9fc 4948+ return 0; /* success */
4949+
4f0767ce 4950+out:
1facf9fc 4951+ return err;
4952+}
4953+
4954+int au_dcsub_pages(struct au_dcsub_pages *dpages, struct dentry *root,
4955+ au_dpages_test test, void *arg)
4956+{
4957+ int err;
027c5e7a 4958+ struct dentry *this_parent;
1facf9fc 4959+ struct list_head *next;
4960+ struct super_block *sb = root->d_sb;
4961+
4962+ err = 0;
027c5e7a
AM
4963+ write_seqlock(&rename_lock);
4964+ this_parent = root;
4965+ spin_lock(&this_parent->d_lock);
4f0767ce 4966+repeat:
1facf9fc 4967+ next = this_parent->d_subdirs.next;
4f0767ce 4968+resume:
1facf9fc 4969+ if (this_parent->d_sb == sb
4970+ && !IS_ROOT(this_parent)
027c5e7a
AM
4971+ && au_di(this_parent)
4972+ && this_parent->d_count
1facf9fc 4973+ && (!test || test(this_parent, arg))) {
4974+ err = au_dpages_append(dpages, this_parent, GFP_ATOMIC);
4975+ if (unlikely(err))
4976+ goto out;
4977+ }
4978+
4979+ while (next != &this_parent->d_subdirs) {
4980+ struct list_head *tmp = next;
4981+ struct dentry *dentry = list_entry(tmp, struct dentry,
4982+ d_u.d_child);
027c5e7a 4983+
1facf9fc 4984+ next = tmp->next;
027c5e7a
AM
4985+ spin_lock_nested(&dentry->d_lock, DENTRY_D_LOCK_NESTED);
4986+ if (dentry->d_count) {
4987+ if (!list_empty(&dentry->d_subdirs)) {
4988+ spin_unlock(&this_parent->d_lock);
4989+ spin_release(&dentry->d_lock.dep_map, 1,
4990+ _RET_IP_);
4991+ this_parent = dentry;
4992+ spin_acquire(&this_parent->d_lock.dep_map, 0, 1,
4993+ _RET_IP_);
4994+ goto repeat;
4995+ }
4996+ if (dentry->d_sb == sb
4997+ && au_di(dentry)
4998+ && (!test || test(dentry, arg)))
4999+ err = au_dpages_append(dpages, dentry,
5000+ GFP_ATOMIC);
1facf9fc 5001+ }
027c5e7a
AM
5002+ spin_unlock(&dentry->d_lock);
5003+ if (unlikely(err))
5004+ goto out;
1facf9fc 5005+ }
5006+
5007+ if (this_parent != root) {
027c5e7a
AM
5008+ struct dentry *tmp;
5009+ struct dentry *child;
5010+
5011+ tmp = this_parent->d_parent;
5012+ rcu_read_lock();
5013+ spin_unlock(&this_parent->d_lock);
5014+ child = this_parent;
5015+ this_parent = tmp;
5016+ spin_lock(&this_parent->d_lock);
5017+ rcu_read_unlock();
5018+ next = child->d_u.d_child.next;
1facf9fc 5019+ goto resume;
5020+ }
027c5e7a 5021+
4f0767ce 5022+out:
027c5e7a
AM
5023+ spin_unlock(&this_parent->d_lock);
5024+ write_sequnlock(&rename_lock);
1facf9fc 5025+ return err;
5026+}
5027+
5028+int au_dcsub_pages_rev(struct au_dcsub_pages *dpages, struct dentry *dentry,
5029+ int do_include, au_dpages_test test, void *arg)
5030+{
5031+ int err;
5032+
5033+ err = 0;
027c5e7a
AM
5034+ write_seqlock(&rename_lock);
5035+ spin_lock(&dentry->d_lock);
5036+ if (do_include
5037+ && dentry->d_count
5038+ && (!test || test(dentry, arg)))
1facf9fc 5039+ err = au_dpages_append(dpages, dentry, GFP_ATOMIC);
027c5e7a
AM
5040+ spin_unlock(&dentry->d_lock);
5041+ if (unlikely(err))
5042+ goto out;
5043+
5044+ /*
5045+ * vfsmount_lock is unnecessary since this is a traverse in a single
5046+ * mount
5047+ */
1facf9fc 5048+ while (!IS_ROOT(dentry)) {
027c5e7a
AM
5049+ dentry = dentry->d_parent; /* rename_lock is locked */
5050+ spin_lock(&dentry->d_lock);
5051+ if (dentry->d_count
5052+ && (!test || test(dentry, arg)))
1facf9fc 5053+ err = au_dpages_append(dpages, dentry, GFP_ATOMIC);
027c5e7a
AM
5054+ spin_unlock(&dentry->d_lock);
5055+ if (unlikely(err))
5056+ break;
1facf9fc 5057+ }
5058+
4f0767ce 5059+out:
027c5e7a 5060+ write_sequnlock(&rename_lock);
1facf9fc 5061+ return err;
5062+}
5063+
027c5e7a
AM
5064+static inline int au_dcsub_dpages_aufs(struct dentry *dentry, void *arg)
5065+{
5066+ return au_di(dentry) && dentry->d_sb == arg;
5067+}
5068+
5069+int au_dcsub_pages_rev_aufs(struct au_dcsub_pages *dpages,
5070+ struct dentry *dentry, int do_include)
5071+{
5072+ return au_dcsub_pages_rev(dpages, dentry, do_include,
5073+ au_dcsub_dpages_aufs, dentry->d_sb);
5074+}
5075+
4a4d8108 5076+int au_test_subdir(struct dentry *d1, struct dentry *d2)
1facf9fc 5077+{
4a4d8108
AM
5078+ struct path path[2] = {
5079+ {
5080+ .dentry = d1
5081+ },
5082+ {
5083+ .dentry = d2
5084+ }
5085+ };
1facf9fc 5086+
4a4d8108 5087+ return path_is_under(path + 0, path + 1);
1facf9fc 5088+}
7f207e10
AM
5089diff -urN /usr/share/empty/fs/aufs/dcsub.h linux/fs/aufs/dcsub.h
5090--- /usr/share/empty/fs/aufs/dcsub.h 1970-01-01 01:00:00.000000000 +0100
2dfbb274 5091+++ linux/fs/aufs/dcsub.h 2012-08-26 08:39:00.757174634 +0200
f6c5ef8b 5092@@ -0,0 +1,94 @@
1facf9fc 5093+/*
f6c5ef8b 5094+ * Copyright (C) 2005-2012 Junjiro R. Okajima
1facf9fc 5095+ *
5096+ * This program, aufs is free software; you can redistribute it and/or modify
5097+ * it under the terms of the GNU General Public License as published by
5098+ * the Free Software Foundation; either version 2 of the License, or
5099+ * (at your option) any later version.
dece6358
AM
5100+ *
5101+ * This program is distributed in the hope that it will be useful,
5102+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
5103+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
5104+ * GNU General Public License for more details.
5105+ *
5106+ * You should have received a copy of the GNU General Public License
5107+ * along with this program; if not, write to the Free Software
5108+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 5109+ */
5110+
5111+/*
5112+ * sub-routines for dentry cache
5113+ */
5114+
5115+#ifndef __AUFS_DCSUB_H__
5116+#define __AUFS_DCSUB_H__
5117+
5118+#ifdef __KERNEL__
5119+
7f207e10 5120+#include <linux/dcache.h>
027c5e7a 5121+#include <linux/fs.h>
dece6358
AM
5122+
5123+struct dentry;
1facf9fc 5124+
5125+struct au_dpage {
5126+ int ndentry;
5127+ struct dentry **dentries;
5128+};
5129+
5130+struct au_dcsub_pages {
5131+ int ndpage;
5132+ struct au_dpage *dpages;
5133+};
5134+
5135+/* ---------------------------------------------------------------------- */
5136+
7f207e10 5137+/* dcsub.c */
1facf9fc 5138+int au_dpages_init(struct au_dcsub_pages *dpages, gfp_t gfp);
5139+void au_dpages_free(struct au_dcsub_pages *dpages);
5140+typedef int (*au_dpages_test)(struct dentry *dentry, void *arg);
5141+int au_dcsub_pages(struct au_dcsub_pages *dpages, struct dentry *root,
5142+ au_dpages_test test, void *arg);
5143+int au_dcsub_pages_rev(struct au_dcsub_pages *dpages, struct dentry *dentry,
5144+ int do_include, au_dpages_test test, void *arg);
027c5e7a
AM
5145+int au_dcsub_pages_rev_aufs(struct au_dcsub_pages *dpages,
5146+ struct dentry *dentry, int do_include);
4a4d8108 5147+int au_test_subdir(struct dentry *d1, struct dentry *d2);
1facf9fc 5148+
7f207e10
AM
5149+/* ---------------------------------------------------------------------- */
5150+
027c5e7a
AM
5151+static inline int au_d_hashed_positive(struct dentry *d)
5152+{
5153+ int err;
5154+ struct inode *inode = d->d_inode;
5155+ err = 0;
5156+ if (unlikely(d_unhashed(d) || !inode || !inode->i_nlink))
5157+ err = -ENOENT;
5158+ return err;
5159+}
5160+
5161+static inline int au_d_alive(struct dentry *d)
5162+{
5163+ int err;
5164+ struct inode *inode;
5165+ err = 0;
5166+ if (!IS_ROOT(d))
5167+ err = au_d_hashed_positive(d);
5168+ else {
5169+ inode = d->d_inode;
5170+ if (unlikely(d_unlinked(d) || !inode || !inode->i_nlink))
5171+ err = -ENOENT;
5172+ }
5173+ return err;
5174+}
5175+
5176+static inline int au_alive_dir(struct dentry *d)
7f207e10 5177+{
027c5e7a
AM
5178+ int err;
5179+ err = au_d_alive(d);
5180+ if (unlikely(err || IS_DEADDIR(d->d_inode)))
5181+ err = -ENOENT;
5182+ return err;
7f207e10
AM
5183+}
5184+
1facf9fc 5185+#endif /* __KERNEL__ */
5186+#endif /* __AUFS_DCSUB_H__ */
7f207e10
AM
5187diff -urN /usr/share/empty/fs/aufs/debug.c linux/fs/aufs/debug.c
5188--- /usr/share/empty/fs/aufs/debug.c 1970-01-01 01:00:00.000000000 +0100
b4510431
AM
5189+++ linux/fs/aufs/debug.c 2012-10-17 10:31:01.772481151 +0200
5190@@ -0,0 +1,490 @@
1facf9fc 5191+/*
f6c5ef8b 5192+ * Copyright (C) 2005-2012 Junjiro R. Okajima
1facf9fc 5193+ *
5194+ * This program, aufs is free software; you can redistribute it and/or modify
5195+ * it under the terms of the GNU General Public License as published by
5196+ * the Free Software Foundation; either version 2 of the License, or
5197+ * (at your option) any later version.
dece6358
AM
5198+ *
5199+ * This program is distributed in the hope that it will be useful,
5200+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
5201+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
5202+ * GNU General Public License for more details.
5203+ *
5204+ * You should have received a copy of the GNU General Public License
5205+ * along with this program; if not, write to the Free Software
5206+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 5207+ */
5208+
5209+/*
5210+ * debug print functions
5211+ */
5212+
7f207e10 5213+#include <linux/vt_kern.h>
1facf9fc 5214+#include "aufs.h"
5215+
5216+int aufs_debug;
5217+MODULE_PARM_DESC(debug, "debug print");
5218+module_param_named(debug, aufs_debug, int, S_IRUGO | S_IWUSR | S_IWGRP);
5219+
5220+char *au_plevel = KERN_DEBUG;
e49829fe
JR
5221+#define dpri(fmt, ...) do { \
5222+ if ((au_plevel \
5223+ && strcmp(au_plevel, KERN_DEBUG)) \
5224+ || au_debug_test()) \
5225+ printk("%s" fmt, au_plevel, ##__VA_ARGS__); \
1facf9fc 5226+} while (0)
5227+
5228+/* ---------------------------------------------------------------------- */
5229+
5230+void au_dpri_whlist(struct au_nhash *whlist)
5231+{
5232+ unsigned long ul, n;
5233+ struct hlist_head *head;
5234+ struct au_vdir_wh *tpos;
5235+ struct hlist_node *pos;
5236+
5237+ n = whlist->nh_num;
5238+ head = whlist->nh_head;
5239+ for (ul = 0; ul < n; ul++) {
5240+ hlist_for_each_entry(tpos, pos, head, wh_hash)
5241+ dpri("b%d, %.*s, %d\n",
5242+ tpos->wh_bindex,
5243+ tpos->wh_str.len, tpos->wh_str.name,
5244+ tpos->wh_str.len);
5245+ head++;
5246+ }
5247+}
5248+
5249+void au_dpri_vdir(struct au_vdir *vdir)
5250+{
5251+ unsigned long ul;
5252+ union au_vdir_deblk_p p;
5253+ unsigned char *o;
5254+
5255+ if (!vdir || IS_ERR(vdir)) {
5256+ dpri("err %ld\n", PTR_ERR(vdir));
5257+ return;
5258+ }
5259+
5260+ dpri("deblk %u, nblk %lu, deblk %p, last{%lu, %p}, ver %lu\n",
5261+ vdir->vd_deblk_sz, vdir->vd_nblk, vdir->vd_deblk,
5262+ vdir->vd_last.ul, vdir->vd_last.p.deblk, vdir->vd_version);
5263+ for (ul = 0; ul < vdir->vd_nblk; ul++) {
5264+ p.deblk = vdir->vd_deblk[ul];
5265+ o = p.deblk;
5266+ dpri("[%lu]: %p\n", ul, o);
5267+ }
5268+}
5269+
53392da6 5270+static int do_pri_inode(aufs_bindex_t bindex, struct inode *inode, int hn,
1facf9fc 5271+ struct dentry *wh)
5272+{
5273+ char *n = NULL;
5274+ int l = 0;
5275+
5276+ if (!inode || IS_ERR(inode)) {
5277+ dpri("i%d: err %ld\n", bindex, PTR_ERR(inode));
5278+ return -1;
5279+ }
5280+
5281+ /* the type of i_blocks depends upon CONFIG_LSF */
5282+ BUILD_BUG_ON(sizeof(inode->i_blocks) != sizeof(unsigned long)
5283+ && sizeof(inode->i_blocks) != sizeof(u64));
5284+ if (wh) {
5285+ n = (void *)wh->d_name.name;
5286+ l = wh->d_name.len;
5287+ }
5288+
53392da6
AM
5289+ dpri("i%d: %p, i%lu, %s, cnt %d, nl %u, 0%o, sz %llu, blk %llu,"
5290+ " hn %d, ct %lld, np %lu, st 0x%lx, f 0x%x, v %llu, g %x%s%.*s\n",
5291+ bindex, inode,
1facf9fc 5292+ inode->i_ino, inode->i_sb ? au_sbtype(inode->i_sb) : "??",
5293+ atomic_read(&inode->i_count), inode->i_nlink, inode->i_mode,
5294+ i_size_read(inode), (unsigned long long)inode->i_blocks,
53392da6 5295+ hn, (long long)timespec_to_ns(&inode->i_ctime) & 0x0ffff,
1facf9fc 5296+ inode->i_mapping ? inode->i_mapping->nrpages : 0,
b752ccd1
AM
5297+ inode->i_state, inode->i_flags, inode->i_version,
5298+ inode->i_generation,
1facf9fc 5299+ l ? ", wh " : "", l, n);
5300+ return 0;
5301+}
5302+
5303+void au_dpri_inode(struct inode *inode)
5304+{
5305+ struct au_iinfo *iinfo;
5306+ aufs_bindex_t bindex;
53392da6 5307+ int err, hn;
1facf9fc 5308+
53392da6 5309+ err = do_pri_inode(-1, inode, -1, NULL);
1facf9fc 5310+ if (err || !au_test_aufs(inode->i_sb))
5311+ return;
5312+
5313+ iinfo = au_ii(inode);
5314+ if (!iinfo)
5315+ return;
5316+ dpri("i-1: bstart %d, bend %d, gen %d\n",
5317+ iinfo->ii_bstart, iinfo->ii_bend, au_iigen(inode));
5318+ if (iinfo->ii_bstart < 0)
5319+ return;
53392da6
AM
5320+ hn = 0;
5321+ for (bindex = iinfo->ii_bstart; bindex <= iinfo->ii_bend; bindex++) {
5322+ hn = !!au_hn(iinfo->ii_hinode + bindex);
5323+ do_pri_inode(bindex, iinfo->ii_hinode[0 + bindex].hi_inode, hn,
1facf9fc 5324+ iinfo->ii_hinode[0 + bindex].hi_whdentry);
53392da6 5325+ }
1facf9fc 5326+}
5327+
2cbb1c4b
JR
5328+void au_dpri_dalias(struct inode *inode)
5329+{
5330+ struct dentry *d;
b4510431 5331+ struct hlist_node *p;
2cbb1c4b
JR
5332+
5333+ spin_lock(&inode->i_lock);
b4510431 5334+ hlist_for_each_entry(d, p, &inode->i_dentry, d_alias)
2cbb1c4b
JR
5335+ au_dpri_dentry(d);
5336+ spin_unlock(&inode->i_lock);
5337+}
5338+
1facf9fc 5339+static int do_pri_dentry(aufs_bindex_t bindex, struct dentry *dentry)
5340+{
5341+ struct dentry *wh = NULL;
53392da6 5342+ int hn;
1facf9fc 5343+
5344+ if (!dentry || IS_ERR(dentry)) {
5345+ dpri("d%d: err %ld\n", bindex, PTR_ERR(dentry));
5346+ return -1;
5347+ }
5348+ /* do not call dget_parent() here */
027c5e7a 5349+ /* note: access d_xxx without d_lock */
1facf9fc 5350+ dpri("d%d: %.*s?/%.*s, %s, cnt %d, flags 0x%x\n",
5351+ bindex,
5352+ AuDLNPair(dentry->d_parent), AuDLNPair(dentry),
5353+ dentry->d_sb ? au_sbtype(dentry->d_sb) : "??",
027c5e7a 5354+ dentry->d_count, dentry->d_flags);
53392da6 5355+ hn = -1;
1facf9fc 5356+ if (bindex >= 0 && dentry->d_inode && au_test_aufs(dentry->d_sb)) {
5357+ struct au_iinfo *iinfo = au_ii(dentry->d_inode);
53392da6
AM
5358+ if (iinfo) {
5359+ hn = !!au_hn(iinfo->ii_hinode + bindex);
1facf9fc 5360+ wh = iinfo->ii_hinode[0 + bindex].hi_whdentry;
53392da6 5361+ }
1facf9fc 5362+ }
53392da6 5363+ do_pri_inode(bindex, dentry->d_inode, hn, wh);
1facf9fc 5364+ return 0;
5365+}
5366+
5367+void au_dpri_dentry(struct dentry *dentry)
5368+{
5369+ struct au_dinfo *dinfo;
5370+ aufs_bindex_t bindex;
5371+ int err;
4a4d8108 5372+ struct au_hdentry *hdp;
1facf9fc 5373+
5374+ err = do_pri_dentry(-1, dentry);
5375+ if (err || !au_test_aufs(dentry->d_sb))
5376+ return;
5377+
5378+ dinfo = au_di(dentry);
5379+ if (!dinfo)
5380+ return;
5381+ dpri("d-1: bstart %d, bend %d, bwh %d, bdiropq %d, gen %d\n",
5382+ dinfo->di_bstart, dinfo->di_bend,
5383+ dinfo->di_bwh, dinfo->di_bdiropq, au_digen(dentry));
5384+ if (dinfo->di_bstart < 0)
5385+ return;
4a4d8108 5386+ hdp = dinfo->di_hdentry;
1facf9fc 5387+ for (bindex = dinfo->di_bstart; bindex <= dinfo->di_bend; bindex++)
4a4d8108 5388+ do_pri_dentry(bindex, hdp[0 + bindex].hd_dentry);
1facf9fc 5389+}
5390+
5391+static int do_pri_file(aufs_bindex_t bindex, struct file *file)
5392+{
5393+ char a[32];
5394+
5395+ if (!file || IS_ERR(file)) {
5396+ dpri("f%d: err %ld\n", bindex, PTR_ERR(file));
5397+ return -1;
5398+ }
5399+ a[0] = 0;
5400+ if (bindex < 0
5401+ && file->f_dentry
5402+ && au_test_aufs(file->f_dentry->d_sb)
5403+ && au_fi(file))
e49829fe 5404+ snprintf(a, sizeof(a), ", gen %d, mmapped %d",
2cbb1c4b 5405+ au_figen(file), atomic_read(&au_fi(file)->fi_mmapped));
b752ccd1 5406+ dpri("f%d: mode 0x%x, flags 0%o, cnt %ld, v %llu, pos %llu%s\n",
1facf9fc 5407+ bindex, file->f_mode, file->f_flags, (long)file_count(file),
b752ccd1 5408+ file->f_version, file->f_pos, a);
1facf9fc 5409+ if (file->f_dentry)
5410+ do_pri_dentry(bindex, file->f_dentry);
5411+ return 0;
5412+}
5413+
5414+void au_dpri_file(struct file *file)
5415+{
5416+ struct au_finfo *finfo;
4a4d8108
AM
5417+ struct au_fidir *fidir;
5418+ struct au_hfile *hfile;
1facf9fc 5419+ aufs_bindex_t bindex;
5420+ int err;
5421+
5422+ err = do_pri_file(-1, file);
5423+ if (err || !file->f_dentry || !au_test_aufs(file->f_dentry->d_sb))
5424+ return;
5425+
5426+ finfo = au_fi(file);
5427+ if (!finfo)
5428+ return;
4a4d8108 5429+ if (finfo->fi_btop < 0)
1facf9fc 5430+ return;
4a4d8108
AM
5431+ fidir = finfo->fi_hdir;
5432+ if (!fidir)
5433+ do_pri_file(finfo->fi_btop, finfo->fi_htop.hf_file);
5434+ else
e49829fe
JR
5435+ for (bindex = finfo->fi_btop;
5436+ bindex >= 0 && bindex <= fidir->fd_bbot;
4a4d8108
AM
5437+ bindex++) {
5438+ hfile = fidir->fd_hfile + bindex;
5439+ do_pri_file(bindex, hfile ? hfile->hf_file : NULL);
5440+ }
1facf9fc 5441+}
5442+
5443+static int do_pri_br(aufs_bindex_t bindex, struct au_branch *br)
5444+{
5445+ struct vfsmount *mnt;
5446+ struct super_block *sb;
5447+
5448+ if (!br || IS_ERR(br))
5449+ goto out;
5450+ mnt = br->br_mnt;
5451+ if (!mnt || IS_ERR(mnt))
5452+ goto out;
5453+ sb = mnt->mnt_sb;
5454+ if (!sb || IS_ERR(sb))
5455+ goto out;
5456+
1e00d052 5457+ dpri("s%d: {perm 0x%x, id %d, cnt %d, wbr %p}, "
b752ccd1 5458+ "%s, dev 0x%02x%02x, flags 0x%lx, cnt %d, active %d, "
1facf9fc 5459+ "xino %d\n",
1e00d052
AM
5460+ bindex, br->br_perm, br->br_id, atomic_read(&br->br_count),
5461+ br->br_wbr, au_sbtype(sb), MAJOR(sb->s_dev), MINOR(sb->s_dev),
b752ccd1 5462+ sb->s_flags, sb->s_count,
1facf9fc 5463+ atomic_read(&sb->s_active), !!br->br_xino.xi_file);
5464+ return 0;
5465+
4f0767ce 5466+out:
1facf9fc 5467+ dpri("s%d: err %ld\n", bindex, PTR_ERR(br));
5468+ return -1;
5469+}
5470+
5471+void au_dpri_sb(struct super_block *sb)
5472+{
5473+ struct au_sbinfo *sbinfo;
5474+ aufs_bindex_t bindex;
5475+ int err;
5476+ /* to reuduce stack size */
5477+ struct {
5478+ struct vfsmount mnt;
5479+ struct au_branch fake;
5480+ } *a;
5481+
5482+ /* this function can be called from magic sysrq */
5483+ a = kzalloc(sizeof(*a), GFP_ATOMIC);
5484+ if (unlikely(!a)) {
5485+ dpri("no memory\n");
5486+ return;
5487+ }
5488+
5489+ a->mnt.mnt_sb = sb;
5490+ a->fake.br_perm = 0;
5491+ a->fake.br_mnt = &a->mnt;
5492+ a->fake.br_xino.xi_file = NULL;
5493+ atomic_set(&a->fake.br_count, 0);
5494+ smp_mb(); /* atomic_set */
5495+ err = do_pri_br(-1, &a->fake);
5496+ kfree(a);
5497+ dpri("dev 0x%x\n", sb->s_dev);
5498+ if (err || !au_test_aufs(sb))
5499+ return;
5500+
5501+ sbinfo = au_sbi(sb);
5502+ if (!sbinfo)
5503+ return;
5504+ dpri("nw %d, gen %u, kobj %d\n",
5505+ atomic_read(&sbinfo->si_nowait.nw_len), sbinfo->si_generation,
5506+ atomic_read(&sbinfo->si_kobj.kref.refcount));
5507+ for (bindex = 0; bindex <= sbinfo->si_bend; bindex++)
5508+ do_pri_br(bindex, sbinfo->si_branch[0 + bindex]);
5509+}
5510+
5511+/* ---------------------------------------------------------------------- */
5512+
5513+void au_dbg_sleep_jiffy(int jiffy)
5514+{
5515+ while (jiffy)
5516+ jiffy = schedule_timeout_uninterruptible(jiffy);
5517+}
5518+
5519+void au_dbg_iattr(struct iattr *ia)
5520+{
5521+#define AuBit(name) if (ia->ia_valid & ATTR_ ## name) \
5522+ dpri(#name "\n")
5523+ AuBit(MODE);
5524+ AuBit(UID);
5525+ AuBit(GID);
5526+ AuBit(SIZE);
5527+ AuBit(ATIME);
5528+ AuBit(MTIME);
5529+ AuBit(CTIME);
5530+ AuBit(ATIME_SET);
5531+ AuBit(MTIME_SET);
5532+ AuBit(FORCE);
5533+ AuBit(ATTR_FLAG);
5534+ AuBit(KILL_SUID);
5535+ AuBit(KILL_SGID);
5536+ AuBit(FILE);
5537+ AuBit(KILL_PRIV);
5538+ AuBit(OPEN);
5539+ AuBit(TIMES_SET);
5540+#undef AuBit
5541+ dpri("ia_file %p\n", ia->ia_file);
5542+}
5543+
5544+/* ---------------------------------------------------------------------- */
5545+
027c5e7a
AM
5546+void __au_dbg_verify_dinode(struct dentry *dentry, const char *func, int line)
5547+{
5548+ struct inode *h_inode, *inode = dentry->d_inode;
5549+ struct dentry *h_dentry;
5550+ aufs_bindex_t bindex, bend, bi;
5551+
5552+ if (!inode /* || au_di(dentry)->di_lsc == AuLsc_DI_TMP */)
5553+ return;
5554+
5555+ bend = au_dbend(dentry);
5556+ bi = au_ibend(inode);
5557+ if (bi < bend)
5558+ bend = bi;
5559+ bindex = au_dbstart(dentry);
5560+ bi = au_ibstart(inode);
5561+ if (bi > bindex)
5562+ bindex = bi;
5563+
5564+ for (; bindex <= bend; bindex++) {
5565+ h_dentry = au_h_dptr(dentry, bindex);
5566+ if (!h_dentry)
5567+ continue;
5568+ h_inode = au_h_iptr(inode, bindex);
5569+ if (unlikely(h_inode != h_dentry->d_inode)) {
5570+ int old = au_debug_test();
5571+ if (!old)
5572+ au_debug(1);
5573+ AuDbg("b%d, %s:%d\n", bindex, func, line);
5574+ AuDbgDentry(dentry);
5575+ AuDbgInode(inode);
5576+ if (!old)
5577+ au_debug(0);
5578+ BUG();
5579+ }
5580+ }
5581+}
5582+
1facf9fc 5583+void au_dbg_verify_dir_parent(struct dentry *dentry, unsigned int sigen)
5584+{
5585+ struct dentry *parent;
5586+
5587+ parent = dget_parent(dentry);
027c5e7a
AM
5588+ AuDebugOn(!S_ISDIR(dentry->d_inode->i_mode));
5589+ AuDebugOn(IS_ROOT(dentry));
5590+ AuDebugOn(au_digen_test(parent, sigen));
1facf9fc 5591+ dput(parent);
5592+}
5593+
5594+void au_dbg_verify_nondir_parent(struct dentry *dentry, unsigned int sigen)
5595+{
5596+ struct dentry *parent;
027c5e7a 5597+ struct inode *inode;
1facf9fc 5598+
5599+ parent = dget_parent(dentry);
027c5e7a
AM
5600+ inode = dentry->d_inode;
5601+ AuDebugOn(inode && S_ISDIR(dentry->d_inode->i_mode));
5602+ AuDebugOn(au_digen_test(parent, sigen));
1facf9fc 5603+ dput(parent);
5604+}
5605+
5606+void au_dbg_verify_gen(struct dentry *parent, unsigned int sigen)
5607+{
5608+ int err, i, j;
5609+ struct au_dcsub_pages dpages;
5610+ struct au_dpage *dpage;
5611+ struct dentry **dentries;
5612+
5613+ err = au_dpages_init(&dpages, GFP_NOFS);
5614+ AuDebugOn(err);
027c5e7a 5615+ err = au_dcsub_pages_rev_aufs(&dpages, parent, /*do_include*/1);
1facf9fc 5616+ AuDebugOn(err);
5617+ for (i = dpages.ndpage - 1; !err && i >= 0; i--) {
5618+ dpage = dpages.dpages + i;
5619+ dentries = dpage->dentries;
5620+ for (j = dpage->ndentry - 1; !err && j >= 0; j--)
027c5e7a 5621+ AuDebugOn(au_digen_test(dentries[j], sigen));
1facf9fc 5622+ }
5623+ au_dpages_free(&dpages);
5624+}
5625+
1facf9fc 5626+void au_dbg_verify_kthread(void)
5627+{
53392da6 5628+ if (au_wkq_test()) {
1facf9fc 5629+ au_dbg_blocked();
1e00d052
AM
5630+ /*
5631+ * It may be recursive, but udba=notify between two aufs mounts,
5632+ * where a single ro branch is shared, is not a problem.
5633+ */
5634+ /* WARN_ON(1); */
1facf9fc 5635+ }
5636+}
5637+
5638+/* ---------------------------------------------------------------------- */
5639+
5640+void au_debug_sbinfo_init(struct au_sbinfo *sbinfo __maybe_unused)
5641+{
5642+#ifdef AuForceNoPlink
5643+ au_opt_clr(sbinfo->si_mntflags, PLINK);
5644+#endif
5645+#ifdef AuForceNoXino
5646+ au_opt_clr(sbinfo->si_mntflags, XINO);
5647+#endif
5648+#ifdef AuForceNoRefrof
5649+ au_opt_clr(sbinfo->si_mntflags, REFROF);
5650+#endif
4a4d8108
AM
5651+#ifdef AuForceHnotify
5652+ au_opt_set_udba(sbinfo->si_mntflags, UDBA_HNOTIFY);
1facf9fc 5653+#endif
1308ab2a 5654+#ifdef AuForceRd0
5655+ sbinfo->si_rdblk = 0;
5656+ sbinfo->si_rdhash = 0;
5657+#endif
1facf9fc 5658+}
5659+
5660+int __init au_debug_init(void)
5661+{
5662+ aufs_bindex_t bindex;
5663+ struct au_vdir_destr destr;
5664+
5665+ bindex = -1;
5666+ AuDebugOn(bindex >= 0);
5667+
5668+ destr.len = -1;
5669+ AuDebugOn(destr.len < NAME_MAX);
5670+
5671+#ifdef CONFIG_4KSTACKS
0c3ec466 5672+ pr_warn("CONFIG_4KSTACKS is defined.\n");
1facf9fc 5673+#endif
5674+
5675+#ifdef AuForceNoBrs
5676+ sysaufs_brs = 0;
5677+#endif
5678+
5679+ return 0;
5680+}
7f207e10
AM
5681diff -urN /usr/share/empty/fs/aufs/debug.h linux/fs/aufs/debug.h
5682--- /usr/share/empty/fs/aufs/debug.h 1970-01-01 01:00:00.000000000 +0100
2dfbb274 5683+++ linux/fs/aufs/debug.h 2012-08-26 08:39:00.757174634 +0200
92d182d2 5684@@ -0,0 +1,242 @@
1facf9fc 5685+/*
f6c5ef8b 5686+ * Copyright (C) 2005-2012 Junjiro R. Okajima
1facf9fc 5687+ *
5688+ * This program, aufs is free software; you can redistribute it and/or modify
5689+ * it under the terms of the GNU General Public License as published by
5690+ * the Free Software Foundation; either version 2 of the License, or
5691+ * (at your option) any later version.
dece6358
AM
5692+ *
5693+ * This program is distributed in the hope that it will be useful,
5694+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
5695+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
5696+ * GNU General Public License for more details.
5697+ *
5698+ * You should have received a copy of the GNU General Public License
5699+ * along with this program; if not, write to the Free Software
5700+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 5701+ */
5702+
5703+/*
5704+ * debug print functions
5705+ */
5706+
5707+#ifndef __AUFS_DEBUG_H__
5708+#define __AUFS_DEBUG_H__
5709+
5710+#ifdef __KERNEL__
5711+
4a4d8108
AM
5712+#include <linux/module.h>
5713+#include <linux/kallsyms.h>
1facf9fc 5714+#include <linux/sysrq.h>
4a4d8108 5715+
1facf9fc 5716+#ifdef CONFIG_AUFS_DEBUG
5717+#define AuDebugOn(a) BUG_ON(a)
5718+
5719+/* module parameter */
5720+extern int aufs_debug;
5721+static inline void au_debug(int n)
5722+{
5723+ aufs_debug = n;
5724+ smp_mb();
5725+}
5726+
5727+static inline int au_debug_test(void)
5728+{
5729+ return aufs_debug;
5730+}
5731+#else
5732+#define AuDebugOn(a) do {} while (0)
4a4d8108
AM
5733+AuStubVoid(au_debug, int n)
5734+AuStubInt0(au_debug_test, void)
1facf9fc 5735+#endif /* CONFIG_AUFS_DEBUG */
5736+
5737+/* ---------------------------------------------------------------------- */
5738+
5739+/* debug print */
5740+
4a4d8108 5741+#define AuDbg(fmt, ...) do { \
1facf9fc 5742+ if (au_debug_test()) \
4a4d8108 5743+ pr_debug("DEBUG: " fmt, ##__VA_ARGS__); \
1facf9fc 5744+} while (0)
4a4d8108
AM
5745+#define AuLabel(l) AuDbg(#l "\n")
5746+#define AuIOErr(fmt, ...) pr_err("I/O Error, " fmt, ##__VA_ARGS__)
5747+#define AuWarn1(fmt, ...) do { \
1facf9fc 5748+ static unsigned char _c; \
5749+ if (!_c++) \
0c3ec466 5750+ pr_warn(fmt, ##__VA_ARGS__); \
1facf9fc 5751+} while (0)
5752+
4a4d8108 5753+#define AuErr1(fmt, ...) do { \
1facf9fc 5754+ static unsigned char _c; \
5755+ if (!_c++) \
4a4d8108 5756+ pr_err(fmt, ##__VA_ARGS__); \
1facf9fc 5757+} while (0)
5758+
4a4d8108 5759+#define AuIOErr1(fmt, ...) do { \
1facf9fc 5760+ static unsigned char _c; \
5761+ if (!_c++) \
4a4d8108 5762+ AuIOErr(fmt, ##__VA_ARGS__); \
1facf9fc 5763+} while (0)
5764+
5765+#define AuUnsupportMsg "This operation is not supported." \
5766+ " Please report this application to aufs-users ML."
4a4d8108
AM
5767+#define AuUnsupport(fmt, ...) do { \
5768+ pr_err(AuUnsupportMsg "\n" fmt, ##__VA_ARGS__); \
1facf9fc 5769+ dump_stack(); \
5770+} while (0)
5771+
5772+#define AuTraceErr(e) do { \
5773+ if (unlikely((e) < 0)) \
5774+ AuDbg("err %d\n", (int)(e)); \
5775+} while (0)
5776+
5777+#define AuTraceErrPtr(p) do { \
5778+ if (IS_ERR(p)) \
5779+ AuDbg("err %ld\n", PTR_ERR(p)); \
5780+} while (0)
5781+
5782+/* dirty macros for debug print, use with "%.*s" and caution */
5783+#define AuLNPair(qstr) (qstr)->len, (qstr)->name
5784+#define AuDLNPair(d) AuLNPair(&(d)->d_name)
5785+
5786+/* ---------------------------------------------------------------------- */
5787+
5788+struct au_sbinfo;
5789+struct au_finfo;
dece6358 5790+struct dentry;
1facf9fc 5791+#ifdef CONFIG_AUFS_DEBUG
5792+extern char *au_plevel;
5793+struct au_nhash;
5794+void au_dpri_whlist(struct au_nhash *whlist);
5795+struct au_vdir;
5796+void au_dpri_vdir(struct au_vdir *vdir);
dece6358 5797+struct inode;
1facf9fc 5798+void au_dpri_inode(struct inode *inode);
2cbb1c4b 5799+void au_dpri_dalias(struct inode *inode);
1facf9fc 5800+void au_dpri_dentry(struct dentry *dentry);
dece6358 5801+struct file;
1facf9fc 5802+void au_dpri_file(struct file *filp);
dece6358 5803+struct super_block;
1facf9fc 5804+void au_dpri_sb(struct super_block *sb);
5805+
5806+void au_dbg_sleep_jiffy(int jiffy);
dece6358 5807+struct iattr;
1facf9fc 5808+void au_dbg_iattr(struct iattr *ia);
5809+
027c5e7a
AM
5810+#define au_dbg_verify_dinode(d) __au_dbg_verify_dinode(d, __func__, __LINE__)
5811+void __au_dbg_verify_dinode(struct dentry *dentry, const char *func, int line);
1facf9fc 5812+void au_dbg_verify_dir_parent(struct dentry *dentry, unsigned int sigen);
5813+void au_dbg_verify_nondir_parent(struct dentry *dentry, unsigned int sigen);
5814+void au_dbg_verify_gen(struct dentry *parent, unsigned int sigen);
1facf9fc 5815+void au_dbg_verify_kthread(void);
5816+
5817+int __init au_debug_init(void);
5818+void au_debug_sbinfo_init(struct au_sbinfo *sbinfo);
5819+#define AuDbgWhlist(w) do { \
5820+ AuDbg(#w "\n"); \
5821+ au_dpri_whlist(w); \
5822+} while (0)
5823+
5824+#define AuDbgVdir(v) do { \
5825+ AuDbg(#v "\n"); \
5826+ au_dpri_vdir(v); \
5827+} while (0)
5828+
5829+#define AuDbgInode(i) do { \
5830+ AuDbg(#i "\n"); \
5831+ au_dpri_inode(i); \
5832+} while (0)
5833+
2cbb1c4b
JR
5834+#define AuDbgDAlias(i) do { \
5835+ AuDbg(#i "\n"); \
5836+ au_dpri_dalias(i); \
5837+} while (0)
5838+
1facf9fc 5839+#define AuDbgDentry(d) do { \
5840+ AuDbg(#d "\n"); \
5841+ au_dpri_dentry(d); \
5842+} while (0)
5843+
5844+#define AuDbgFile(f) do { \
5845+ AuDbg(#f "\n"); \
5846+ au_dpri_file(f); \
5847+} while (0)
5848+
5849+#define AuDbgSb(sb) do { \
5850+ AuDbg(#sb "\n"); \
5851+ au_dpri_sb(sb); \
5852+} while (0)
5853+
5854+#define AuDbgSleep(sec) do { \
5855+ AuDbg("sleep %d sec\n", sec); \
5856+ ssleep(sec); \
5857+} while (0)
5858+
5859+#define AuDbgSleepJiffy(jiffy) do { \
5860+ AuDbg("sleep %d jiffies\n", jiffy); \
5861+ au_dbg_sleep_jiffy(jiffy); \
5862+} while (0)
5863+
5864+#define AuDbgIAttr(ia) do { \
5865+ AuDbg("ia_valid 0x%x\n", (ia)->ia_valid); \
5866+ au_dbg_iattr(ia); \
5867+} while (0)
4a4d8108
AM
5868+
5869+#define AuDbgSym(addr) do { \
5870+ char sym[KSYM_SYMBOL_LEN]; \
5871+ sprint_symbol(sym, (unsigned long)addr); \
5872+ AuDbg("%s\n", sym); \
5873+} while (0)
5874+
5875+#define AuInfoSym(addr) do { \
5876+ char sym[KSYM_SYMBOL_LEN]; \
5877+ sprint_symbol(sym, (unsigned long)addr); \
5878+ AuInfo("%s\n", sym); \
5879+} while (0)
1facf9fc 5880+#else
027c5e7a 5881+AuStubVoid(au_dbg_verify_dinode, struct dentry *dentry)
4a4d8108
AM
5882+AuStubVoid(au_dbg_verify_dir_parent, struct dentry *dentry, unsigned int sigen)
5883+AuStubVoid(au_dbg_verify_nondir_parent, struct dentry *dentry,
5884+ unsigned int sigen)
5885+AuStubVoid(au_dbg_verify_gen, struct dentry *parent, unsigned int sigen)
5886+AuStubVoid(au_dbg_verify_kthread, void)
5887+AuStubInt0(__init au_debug_init, void)
5888+AuStubVoid(au_debug_sbinfo_init, struct au_sbinfo *sbinfo)
1facf9fc 5889+
1facf9fc 5890+#define AuDbgWhlist(w) do {} while (0)
5891+#define AuDbgVdir(v) do {} while (0)
5892+#define AuDbgInode(i) do {} while (0)
2cbb1c4b 5893+#define AuDbgDAlias(i) do {} while (0)
1facf9fc 5894+#define AuDbgDentry(d) do {} while (0)
5895+#define AuDbgFile(f) do {} while (0)
5896+#define AuDbgSb(sb) do {} while (0)
5897+#define AuDbgSleep(sec) do {} while (0)
5898+#define AuDbgSleepJiffy(jiffy) do {} while (0)
5899+#define AuDbgIAttr(ia) do {} while (0)
4a4d8108
AM
5900+#define AuDbgSym(addr) do {} while (0)
5901+#define AuInfoSym(addr) do {} while (0)
1facf9fc 5902+#endif /* CONFIG_AUFS_DEBUG */
5903+
5904+/* ---------------------------------------------------------------------- */
5905+
5906+#ifdef CONFIG_AUFS_MAGIC_SYSRQ
5907+int __init au_sysrq_init(void);
5908+void au_sysrq_fin(void);
5909+
5910+#ifdef CONFIG_HW_CONSOLE
5911+#define au_dbg_blocked() do { \
5912+ WARN_ON(1); \
0c5527e5 5913+ handle_sysrq('w'); \
1facf9fc 5914+} while (0)
5915+#else
4a4d8108 5916+AuStubVoid(au_dbg_blocked, void)
1facf9fc 5917+#endif
5918+
5919+#else
4a4d8108
AM
5920+AuStubInt0(__init au_sysrq_init, void)
5921+AuStubVoid(au_sysrq_fin, void)
5922+AuStubVoid(au_dbg_blocked, void)
1facf9fc 5923+#endif /* CONFIG_AUFS_MAGIC_SYSRQ */
5924+
5925+#endif /* __KERNEL__ */
5926+#endif /* __AUFS_DEBUG_H__ */
7f207e10
AM
5927diff -urN /usr/share/empty/fs/aufs/dentry.c linux/fs/aufs/dentry.c
5928--- /usr/share/empty/fs/aufs/dentry.c 1970-01-01 01:00:00.000000000 +0100
b4510431
AM
5929+++ linux/fs/aufs/dentry.c 2012-10-17 10:31:01.772481151 +0200
5930@@ -0,0 +1,1063 @@
1facf9fc 5931+/*
f6c5ef8b 5932+ * Copyright (C) 2005-2012 Junjiro R. Okajima
1facf9fc 5933+ *
5934+ * This program, aufs is free software; you can redistribute it and/or modify
5935+ * it under the terms of the GNU General Public License as published by
5936+ * the Free Software Foundation; either version 2 of the License, or
5937+ * (at your option) any later version.
dece6358
AM
5938+ *
5939+ * This program is distributed in the hope that it will be useful,
5940+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
5941+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
5942+ * GNU General Public License for more details.
5943+ *
5944+ * You should have received a copy of the GNU General Public License
5945+ * along with this program; if not, write to the Free Software
5946+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 5947+ */
5948+
5949+/*
5950+ * lookup and dentry operations
5951+ */
5952+
dece6358 5953+#include <linux/namei.h>
1facf9fc 5954+#include "aufs.h"
5955+
1facf9fc 5956+#define AuLkup_ALLOW_NEG 1
5957+#define au_ftest_lkup(flags, name) ((flags) & AuLkup_##name)
7f207e10
AM
5958+#define au_fset_lkup(flags, name) \
5959+ do { (flags) |= AuLkup_##name; } while (0)
5960+#define au_fclr_lkup(flags, name) \
5961+ do { (flags) &= ~AuLkup_##name; } while (0)
1facf9fc 5962+
5963+struct au_do_lookup_args {
5964+ unsigned int flags;
5965+ mode_t type;
b4510431 5966+ unsigned int nd_flags;
1facf9fc 5967+};
5968+
5969+/*
5970+ * returns positive/negative dentry, NULL or an error.
5971+ * NULL means whiteout-ed or not-found.
5972+ */
5973+static struct dentry*
5974+au_do_lookup(struct dentry *h_parent, struct dentry *dentry,
5975+ aufs_bindex_t bindex, struct qstr *wh_name,
5976+ struct au_do_lookup_args *args)
5977+{
5978+ struct dentry *h_dentry;
5979+ struct inode *h_inode, *inode;
1facf9fc 5980+ struct au_branch *br;
5981+ int wh_found, opq;
5982+ unsigned char wh_able;
5983+ const unsigned char allow_neg = !!au_ftest_lkup(args->flags, ALLOW_NEG);
5984+
1facf9fc 5985+ wh_found = 0;
5986+ br = au_sbr(dentry->d_sb, bindex);
5987+ wh_able = !!au_br_whable(br->br_perm);
5988+ if (wh_able)
5989+ wh_found = au_wh_test(h_parent, wh_name, br, /*try_sio*/0);
5990+ h_dentry = ERR_PTR(wh_found);
5991+ if (!wh_found)
5992+ goto real_lookup;
5993+ if (unlikely(wh_found < 0))
5994+ goto out;
5995+
5996+ /* We found a whiteout */
5997+ /* au_set_dbend(dentry, bindex); */
5998+ au_set_dbwh(dentry, bindex);
5999+ if (!allow_neg)
6000+ return NULL; /* success */
6001+
4f0767ce 6002+real_lookup:
b4510431 6003+ h_dentry = vfsub_lkup_one(&dentry->d_name, h_parent);
1facf9fc 6004+ if (IS_ERR(h_dentry))
6005+ goto out;
6006+
6007+ h_inode = h_dentry->d_inode;
6008+ if (!h_inode) {
6009+ if (!allow_neg)
6010+ goto out_neg;
6011+ } else if (wh_found
6012+ || (args->type && args->type != (h_inode->i_mode & S_IFMT)))
6013+ goto out_neg;
6014+
6015+ if (au_dbend(dentry) <= bindex)
6016+ au_set_dbend(dentry, bindex);
6017+ if (au_dbstart(dentry) < 0 || bindex < au_dbstart(dentry))
6018+ au_set_dbstart(dentry, bindex);
6019+ au_set_h_dptr(dentry, bindex, h_dentry);
6020+
6021+ inode = dentry->d_inode;
6022+ if (!h_inode || !S_ISDIR(h_inode->i_mode) || !wh_able
6023+ || (inode && !S_ISDIR(inode->i_mode)))
6024+ goto out; /* success */
6025+
6026+ mutex_lock_nested(&h_inode->i_mutex, AuLsc_I_CHILD);
6027+ opq = au_diropq_test(h_dentry, br);
6028+ mutex_unlock(&h_inode->i_mutex);
6029+ if (opq > 0)
6030+ au_set_dbdiropq(dentry, bindex);
6031+ else if (unlikely(opq < 0)) {
6032+ au_set_h_dptr(dentry, bindex, NULL);
6033+ h_dentry = ERR_PTR(opq);
6034+ }
6035+ goto out;
6036+
4f0767ce 6037+out_neg:
1facf9fc 6038+ dput(h_dentry);
6039+ h_dentry = NULL;
4f0767ce 6040+out:
1facf9fc 6041+ return h_dentry;
6042+}
6043+
dece6358
AM
6044+static int au_test_shwh(struct super_block *sb, const struct qstr *name)
6045+{
6046+ if (unlikely(!au_opt_test(au_mntflags(sb), SHWH)
6047+ && !strncmp(name->name, AUFS_WH_PFX, AUFS_WH_PFX_LEN)))
6048+ return -EPERM;
6049+ return 0;
6050+}
6051+
1facf9fc 6052+/*
6053+ * returns the number of lower positive dentries,
6054+ * otherwise an error.
6055+ * can be called at unlinking with @type is zero.
6056+ */
6057+int au_lkup_dentry(struct dentry *dentry, aufs_bindex_t bstart, mode_t type,
b4510431 6058+ unsigned int flags)
1facf9fc 6059+{
6060+ int npositive, err;
6061+ aufs_bindex_t bindex, btail, bdiropq;
6062+ unsigned char isdir;
6063+ struct qstr whname;
6064+ struct au_do_lookup_args args = {
b4510431
AM
6065+ .flags = 0,
6066+ .type = type,
6067+ .nd_flags = flags
1facf9fc 6068+ };
6069+ const struct qstr *name = &dentry->d_name;
6070+ struct dentry *parent;
6071+ struct inode *inode;
6072+
dece6358
AM
6073+ err = au_test_shwh(dentry->d_sb, name);
6074+ if (unlikely(err))
1facf9fc 6075+ goto out;
6076+
6077+ err = au_wh_name_alloc(&whname, name);
6078+ if (unlikely(err))
6079+ goto out;
6080+
6081+ inode = dentry->d_inode;
6082+ isdir = !!(inode && S_ISDIR(inode->i_mode));
6083+ if (!type)
6084+ au_fset_lkup(args.flags, ALLOW_NEG);
6085+
6086+ npositive = 0;
4a4d8108 6087+ parent = dget_parent(dentry);
1facf9fc 6088+ btail = au_dbtaildir(parent);
6089+ for (bindex = bstart; bindex <= btail; bindex++) {
6090+ struct dentry *h_parent, *h_dentry;
6091+ struct inode *h_inode, *h_dir;
6092+
6093+ h_dentry = au_h_dptr(dentry, bindex);
6094+ if (h_dentry) {
6095+ if (h_dentry->d_inode)
6096+ npositive++;
6097+ if (type != S_IFDIR)
6098+ break;
6099+ continue;
6100+ }
6101+ h_parent = au_h_dptr(parent, bindex);
6102+ if (!h_parent)
6103+ continue;
6104+ h_dir = h_parent->d_inode;
6105+ if (!h_dir || !S_ISDIR(h_dir->i_mode))
6106+ continue;
6107+
6108+ mutex_lock_nested(&h_dir->i_mutex, AuLsc_I_PARENT);
6109+ h_dentry = au_do_lookup(h_parent, dentry, bindex, &whname,
6110+ &args);
6111+ mutex_unlock(&h_dir->i_mutex);
6112+ err = PTR_ERR(h_dentry);
6113+ if (IS_ERR(h_dentry))
4a4d8108 6114+ goto out_parent;
1facf9fc 6115+ au_fclr_lkup(args.flags, ALLOW_NEG);
6116+
6117+ if (au_dbwh(dentry) >= 0)
6118+ break;
6119+ if (!h_dentry)
6120+ continue;
6121+ h_inode = h_dentry->d_inode;
6122+ if (!h_inode)
6123+ continue;
6124+ npositive++;
6125+ if (!args.type)
6126+ args.type = h_inode->i_mode & S_IFMT;
6127+ if (args.type != S_IFDIR)
6128+ break;
6129+ else if (isdir) {
6130+ /* the type of lower may be different */
6131+ bdiropq = au_dbdiropq(dentry);
6132+ if (bdiropq >= 0 && bdiropq <= bindex)
6133+ break;
6134+ }
6135+ }
6136+
6137+ if (npositive) {
6138+ AuLabel(positive);
6139+ au_update_dbstart(dentry);
6140+ }
6141+ err = npositive;
6142+ if (unlikely(!au_opt_test(au_mntflags(dentry->d_sb), UDBA_NONE)
027c5e7a 6143+ && au_dbstart(dentry) < 0)) {
1facf9fc 6144+ err = -EIO;
027c5e7a
AM
6145+ AuIOErr("both of real entry and whiteout found, %.*s, err %d\n",
6146+ AuDLNPair(dentry), err);
6147+ }
1facf9fc 6148+
4f0767ce 6149+out_parent:
4a4d8108 6150+ dput(parent);
1facf9fc 6151+ kfree(whname.name);
4f0767ce 6152+out:
1facf9fc 6153+ return err;
6154+}
6155+
6156+struct dentry *au_sio_lkup_one(struct qstr *name, struct dentry *parent,
6157+ struct au_branch *br)
6158+{
6159+ struct dentry *dentry;
6160+ int wkq_err;
6161+
6162+ if (!au_test_h_perm_sio(parent->d_inode, MAY_EXEC))
b4510431 6163+ dentry = vfsub_lkup_one(name, parent);
1facf9fc 6164+ else {
b4510431
AM
6165+ struct vfsub_lkup_one_args args = {
6166+ .errp = &dentry,
6167+ .name = name,
6168+ .parent = parent
1facf9fc 6169+ };
6170+
b4510431 6171+ wkq_err = au_wkq_wait(vfsub_call_lkup_one, &args);
1facf9fc 6172+ if (unlikely(wkq_err))
6173+ dentry = ERR_PTR(wkq_err);
6174+ }
6175+
6176+ return dentry;
6177+}
6178+
6179+/*
6180+ * lookup @dentry on @bindex which should be negative.
6181+ */
6182+int au_lkup_neg(struct dentry *dentry, aufs_bindex_t bindex)
6183+{
6184+ int err;
6185+ struct dentry *parent, *h_parent, *h_dentry;
1facf9fc 6186+
1facf9fc 6187+ parent = dget_parent(dentry);
6188+ h_parent = au_h_dptr(parent, bindex);
4a4d8108 6189+ h_dentry = au_sio_lkup_one(&dentry->d_name, h_parent,
1facf9fc 6190+ au_sbr(dentry->d_sb, bindex));
6191+ err = PTR_ERR(h_dentry);
6192+ if (IS_ERR(h_dentry))
6193+ goto out;
6194+ if (unlikely(h_dentry->d_inode)) {
6195+ err = -EIO;
027c5e7a
AM
6196+ AuIOErr("%.*s should be negative on b%d.\n",
6197+ AuDLNPair(h_dentry), bindex);
1facf9fc 6198+ dput(h_dentry);
6199+ goto out;
6200+ }
6201+
4a4d8108 6202+ err = 0;
1facf9fc 6203+ if (bindex < au_dbstart(dentry))
6204+ au_set_dbstart(dentry, bindex);
6205+ if (au_dbend(dentry) < bindex)
6206+ au_set_dbend(dentry, bindex);
6207+ au_set_h_dptr(dentry, bindex, h_dentry);
1facf9fc 6208+
4f0767ce 6209+out:
1facf9fc 6210+ dput(parent);
6211+ return err;
6212+}
6213+
6214+/* ---------------------------------------------------------------------- */
6215+
6216+/* subset of struct inode */
6217+struct au_iattr {
6218+ unsigned long i_ino;
6219+ /* unsigned int i_nlink; */
0c3ec466
AM
6220+ kuid_t i_uid;
6221+ kgid_t i_gid;
1facf9fc 6222+ u64 i_version;
6223+/*
6224+ loff_t i_size;
6225+ blkcnt_t i_blocks;
6226+*/
6227+ umode_t i_mode;
6228+};
6229+
6230+static void au_iattr_save(struct au_iattr *ia, struct inode *h_inode)
6231+{
6232+ ia->i_ino = h_inode->i_ino;
6233+ /* ia->i_nlink = h_inode->i_nlink; */
6234+ ia->i_uid = h_inode->i_uid;
6235+ ia->i_gid = h_inode->i_gid;
6236+ ia->i_version = h_inode->i_version;
6237+/*
6238+ ia->i_size = h_inode->i_size;
6239+ ia->i_blocks = h_inode->i_blocks;
6240+*/
6241+ ia->i_mode = (h_inode->i_mode & S_IFMT);
6242+}
6243+
6244+static int au_iattr_test(struct au_iattr *ia, struct inode *h_inode)
6245+{
6246+ return ia->i_ino != h_inode->i_ino
6247+ /* || ia->i_nlink != h_inode->i_nlink */
0c3ec466 6248+ || !uid_eq(ia->i_uid, h_inode->i_uid)
2dfbb274 6249+ || !gid_eq(ia->i_gid, h_inode->i_gid)
1facf9fc 6250+ || ia->i_version != h_inode->i_version
6251+/*
6252+ || ia->i_size != h_inode->i_size
6253+ || ia->i_blocks != h_inode->i_blocks
6254+*/
6255+ || ia->i_mode != (h_inode->i_mode & S_IFMT);
6256+}
6257+
6258+static int au_h_verify_dentry(struct dentry *h_dentry, struct dentry *h_parent,
6259+ struct au_branch *br)
6260+{
6261+ int err;
6262+ struct au_iattr ia;
6263+ struct inode *h_inode;
6264+ struct dentry *h_d;
6265+ struct super_block *h_sb;
6266+
6267+ err = 0;
6268+ memset(&ia, -1, sizeof(ia));
6269+ h_sb = h_dentry->d_sb;
6270+ h_inode = h_dentry->d_inode;
6271+ if (h_inode)
6272+ au_iattr_save(&ia, h_inode);
6273+ else if (au_test_nfs(h_sb) || au_test_fuse(h_sb))
6274+ /* nfs d_revalidate may return 0 for negative dentry */
6275+ /* fuse d_revalidate always return 0 for negative dentry */
6276+ goto out;
6277+
6278+ /* main purpose is namei.c:cached_lookup() and d_revalidate */
b4510431 6279+ h_d = vfsub_lkup_one(&h_dentry->d_name, h_parent);
1facf9fc 6280+ err = PTR_ERR(h_d);
6281+ if (IS_ERR(h_d))
6282+ goto out;
6283+
6284+ err = 0;
6285+ if (unlikely(h_d != h_dentry
6286+ || h_d->d_inode != h_inode
6287+ || (h_inode && au_iattr_test(&ia, h_inode))))
6288+ err = au_busy_or_stale();
6289+ dput(h_d);
6290+
4f0767ce 6291+out:
1facf9fc 6292+ AuTraceErr(err);
6293+ return err;
6294+}
6295+
6296+int au_h_verify(struct dentry *h_dentry, unsigned int udba, struct inode *h_dir,
6297+ struct dentry *h_parent, struct au_branch *br)
6298+{
6299+ int err;
6300+
6301+ err = 0;
027c5e7a
AM
6302+ if (udba == AuOpt_UDBA_REVAL
6303+ && !au_test_fs_remote(h_dentry->d_sb)) {
1facf9fc 6304+ IMustLock(h_dir);
6305+ err = (h_dentry->d_parent->d_inode != h_dir);
027c5e7a 6306+ } else if (udba != AuOpt_UDBA_NONE)
1facf9fc 6307+ err = au_h_verify_dentry(h_dentry, h_parent, br);
6308+
6309+ return err;
6310+}
6311+
6312+/* ---------------------------------------------------------------------- */
6313+
027c5e7a 6314+static int au_do_refresh_hdentry(struct dentry *dentry, struct dentry *parent)
1facf9fc 6315+{
027c5e7a 6316+ int err;
1facf9fc 6317+ aufs_bindex_t new_bindex, bindex, bend, bwh, bdiropq;
027c5e7a
AM
6318+ struct au_hdentry tmp, *p, *q;
6319+ struct au_dinfo *dinfo;
6320+ struct super_block *sb;
1facf9fc 6321+
027c5e7a 6322+ DiMustWriteLock(dentry);
1308ab2a 6323+
027c5e7a
AM
6324+ sb = dentry->d_sb;
6325+ dinfo = au_di(dentry);
1facf9fc 6326+ bend = dinfo->di_bend;
6327+ bwh = dinfo->di_bwh;
6328+ bdiropq = dinfo->di_bdiropq;
027c5e7a 6329+ p = dinfo->di_hdentry + dinfo->di_bstart;
1facf9fc 6330+ for (bindex = dinfo->di_bstart; bindex <= bend; bindex++, p++) {
027c5e7a 6331+ if (!p->hd_dentry)
1facf9fc 6332+ continue;
6333+
027c5e7a
AM
6334+ new_bindex = au_br_index(sb, p->hd_id);
6335+ if (new_bindex == bindex)
1facf9fc 6336+ continue;
1facf9fc 6337+
1facf9fc 6338+ if (dinfo->di_bwh == bindex)
6339+ bwh = new_bindex;
6340+ if (dinfo->di_bdiropq == bindex)
6341+ bdiropq = new_bindex;
6342+ if (new_bindex < 0) {
6343+ au_hdput(p);
6344+ p->hd_dentry = NULL;
6345+ continue;
6346+ }
6347+
6348+ /* swap two lower dentries, and loop again */
6349+ q = dinfo->di_hdentry + new_bindex;
6350+ tmp = *q;
6351+ *q = *p;
6352+ *p = tmp;
6353+ if (tmp.hd_dentry) {
6354+ bindex--;
6355+ p--;
6356+ }
6357+ }
6358+
1facf9fc 6359+ dinfo->di_bwh = -1;
6360+ if (bwh >= 0 && bwh <= au_sbend(sb) && au_sbr_whable(sb, bwh))
6361+ dinfo->di_bwh = bwh;
6362+
6363+ dinfo->di_bdiropq = -1;
6364+ if (bdiropq >= 0
6365+ && bdiropq <= au_sbend(sb)
6366+ && au_sbr_whable(sb, bdiropq))
6367+ dinfo->di_bdiropq = bdiropq;
6368+
027c5e7a
AM
6369+ err = -EIO;
6370+ dinfo->di_bstart = -1;
6371+ dinfo->di_bend = -1;
1facf9fc 6372+ bend = au_dbend(parent);
6373+ p = dinfo->di_hdentry;
6374+ for (bindex = 0; bindex <= bend; bindex++, p++)
6375+ if (p->hd_dentry) {
6376+ dinfo->di_bstart = bindex;
6377+ break;
6378+ }
6379+
027c5e7a
AM
6380+ if (dinfo->di_bstart >= 0) {
6381+ p = dinfo->di_hdentry + bend;
6382+ for (bindex = bend; bindex >= 0; bindex--, p--)
6383+ if (p->hd_dentry) {
6384+ dinfo->di_bend = bindex;
6385+ err = 0;
6386+ break;
6387+ }
6388+ }
6389+
6390+ return err;
1facf9fc 6391+}
6392+
027c5e7a 6393+static void au_do_hide(struct dentry *dentry)
1facf9fc 6394+{
027c5e7a 6395+ struct inode *inode;
1facf9fc 6396+
027c5e7a
AM
6397+ inode = dentry->d_inode;
6398+ if (inode) {
6399+ if (!S_ISDIR(inode->i_mode)) {
6400+ if (inode->i_nlink && !d_unhashed(dentry))
6401+ drop_nlink(inode);
6402+ } else {
6403+ clear_nlink(inode);
6404+ /* stop next lookup */
6405+ inode->i_flags |= S_DEAD;
6406+ }
6407+ smp_mb(); /* necessary? */
6408+ }
6409+ d_drop(dentry);
6410+}
1308ab2a 6411+
027c5e7a
AM
6412+static int au_hide_children(struct dentry *parent)
6413+{
6414+ int err, i, j, ndentry;
6415+ struct au_dcsub_pages dpages;
6416+ struct au_dpage *dpage;
6417+ struct dentry *dentry;
1facf9fc 6418+
027c5e7a 6419+ err = au_dpages_init(&dpages, GFP_NOFS);
1facf9fc 6420+ if (unlikely(err))
6421+ goto out;
027c5e7a
AM
6422+ err = au_dcsub_pages(&dpages, parent, NULL, NULL);
6423+ if (unlikely(err))
6424+ goto out_dpages;
1facf9fc 6425+
027c5e7a
AM
6426+ /* in reverse order */
6427+ for (i = dpages.ndpage - 1; i >= 0; i--) {
6428+ dpage = dpages.dpages + i;
6429+ ndentry = dpage->ndentry;
6430+ for (j = ndentry - 1; j >= 0; j--) {
6431+ dentry = dpage->dentries[j];
6432+ if (dentry != parent)
6433+ au_do_hide(dentry);
6434+ }
6435+ }
1facf9fc 6436+
027c5e7a
AM
6437+out_dpages:
6438+ au_dpages_free(&dpages);
4f0767ce 6439+out:
027c5e7a 6440+ return err;
1facf9fc 6441+}
6442+
027c5e7a 6443+static void au_hide(struct dentry *dentry)
1facf9fc 6444+{
027c5e7a
AM
6445+ int err;
6446+ struct inode *inode;
1facf9fc 6447+
027c5e7a
AM
6448+ AuDbgDentry(dentry);
6449+ inode = dentry->d_inode;
6450+ if (inode && S_ISDIR(inode->i_mode)) {
6451+ /* shrink_dcache_parent(dentry); */
6452+ err = au_hide_children(dentry);
6453+ if (unlikely(err))
6454+ AuIOErr("%.*s, failed hiding children, ignored %d\n",
6455+ AuDLNPair(dentry), err);
6456+ }
6457+ au_do_hide(dentry);
6458+}
1facf9fc 6459+
027c5e7a
AM
6460+/*
6461+ * By adding a dirty branch, a cached dentry may be affected in various ways.
6462+ *
6463+ * a dirty branch is added
6464+ * - on the top of layers
6465+ * - in the middle of layers
6466+ * - to the bottom of layers
6467+ *
6468+ * on the added branch there exists
6469+ * - a whiteout
6470+ * - a diropq
6471+ * - a same named entry
6472+ * + exist
6473+ * * negative --> positive
6474+ * * positive --> positive
6475+ * - type is unchanged
6476+ * - type is changed
6477+ * + doesn't exist
6478+ * * negative --> negative
6479+ * * positive --> negative (rejected by au_br_del() for non-dir case)
6480+ * - none
6481+ */
6482+static int au_refresh_by_dinfo(struct dentry *dentry, struct au_dinfo *dinfo,
6483+ struct au_dinfo *tmp)
6484+{
6485+ int err;
6486+ aufs_bindex_t bindex, bend;
6487+ struct {
6488+ struct dentry *dentry;
6489+ struct inode *inode;
6490+ mode_t mode;
6491+ } orig_h, tmp_h;
6492+ struct au_hdentry *hd;
6493+ struct inode *inode, *h_inode;
6494+ struct dentry *h_dentry;
6495+
6496+ err = 0;
6497+ AuDebugOn(dinfo->di_bstart < 0);
6498+ orig_h.dentry = dinfo->di_hdentry[dinfo->di_bstart].hd_dentry;
6499+ orig_h.inode = orig_h.dentry->d_inode;
6500+ orig_h.mode = 0;
6501+ if (orig_h.inode)
6502+ orig_h.mode = orig_h.inode->i_mode & S_IFMT;
6503+ memset(&tmp_h, 0, sizeof(tmp_h));
6504+ if (tmp->di_bstart >= 0) {
6505+ tmp_h.dentry = tmp->di_hdentry[tmp->di_bstart].hd_dentry;
6506+ tmp_h.inode = tmp_h.dentry->d_inode;
6507+ if (tmp_h.inode)
6508+ tmp_h.mode = tmp_h.inode->i_mode & S_IFMT;
6509+ }
6510+
6511+ inode = dentry->d_inode;
6512+ if (!orig_h.inode) {
6513+ AuDbg("nagative originally\n");
6514+ if (inode) {
6515+ au_hide(dentry);
6516+ goto out;
6517+ }
6518+ AuDebugOn(inode);
6519+ AuDebugOn(dinfo->di_bstart != dinfo->di_bend);
6520+ AuDebugOn(dinfo->di_bdiropq != -1);
6521+
6522+ if (!tmp_h.inode) {
6523+ AuDbg("negative --> negative\n");
6524+ /* should have only one negative lower */
6525+ if (tmp->di_bstart >= 0
6526+ && tmp->di_bstart < dinfo->di_bstart) {
6527+ AuDebugOn(tmp->di_bstart != tmp->di_bend);
6528+ AuDebugOn(dinfo->di_bstart != dinfo->di_bend);
6529+ au_set_h_dptr(dentry, dinfo->di_bstart, NULL);
6530+ au_di_cp(dinfo, tmp);
6531+ hd = tmp->di_hdentry + tmp->di_bstart;
6532+ au_set_h_dptr(dentry, tmp->di_bstart,
6533+ dget(hd->hd_dentry));
6534+ }
6535+ au_dbg_verify_dinode(dentry);
6536+ } else {
6537+ AuDbg("negative --> positive\n");
6538+ /*
6539+ * similar to the behaviour of creating with bypassing
6540+ * aufs.
6541+ * unhash it in order to force an error in the
6542+ * succeeding create operation.
6543+ * we should not set S_DEAD here.
6544+ */
6545+ d_drop(dentry);
6546+ /* au_di_swap(tmp, dinfo); */
6547+ au_dbg_verify_dinode(dentry);
6548+ }
6549+ } else {
6550+ AuDbg("positive originally\n");
6551+ /* inode may be NULL */
6552+ AuDebugOn(inode && (inode->i_mode & S_IFMT) != orig_h.mode);
6553+ if (!tmp_h.inode) {
6554+ AuDbg("positive --> negative\n");
6555+ /* or bypassing aufs */
6556+ au_hide(dentry);
6557+ if (tmp->di_bwh >= 0 && tmp->di_bwh <= dinfo->di_bstart)
6558+ dinfo->di_bwh = tmp->di_bwh;
6559+ if (inode)
6560+ err = au_refresh_hinode_self(inode);
6561+ au_dbg_verify_dinode(dentry);
6562+ } else if (orig_h.mode == tmp_h.mode) {
6563+ AuDbg("positive --> positive, same type\n");
6564+ if (!S_ISDIR(orig_h.mode)
6565+ && dinfo->di_bstart > tmp->di_bstart) {
6566+ /*
6567+ * similar to the behaviour of removing and
6568+ * creating.
6569+ */
6570+ au_hide(dentry);
6571+ if (inode)
6572+ err = au_refresh_hinode_self(inode);
6573+ au_dbg_verify_dinode(dentry);
6574+ } else {
6575+ /* fill empty slots */
6576+ if (dinfo->di_bstart > tmp->di_bstart)
6577+ dinfo->di_bstart = tmp->di_bstart;
6578+ if (dinfo->di_bend < tmp->di_bend)
6579+ dinfo->di_bend = tmp->di_bend;
6580+ dinfo->di_bwh = tmp->di_bwh;
6581+ dinfo->di_bdiropq = tmp->di_bdiropq;
6582+ hd = tmp->di_hdentry;
6583+ bend = dinfo->di_bend;
6584+ for (bindex = tmp->di_bstart; bindex <= bend;
6585+ bindex++) {
6586+ if (au_h_dptr(dentry, bindex))
6587+ continue;
6588+ h_dentry = hd[bindex].hd_dentry;
6589+ if (!h_dentry)
6590+ continue;
6591+ h_inode = h_dentry->d_inode;
6592+ AuDebugOn(!h_inode);
6593+ AuDebugOn(orig_h.mode
6594+ != (h_inode->i_mode
6595+ & S_IFMT));
6596+ au_set_h_dptr(dentry, bindex,
6597+ dget(h_dentry));
6598+ }
6599+ err = au_refresh_hinode(inode, dentry);
6600+ au_dbg_verify_dinode(dentry);
6601+ }
6602+ } else {
6603+ AuDbg("positive --> positive, different type\n");
6604+ /* similar to the behaviour of removing and creating */
6605+ au_hide(dentry);
6606+ if (inode)
6607+ err = au_refresh_hinode_self(inode);
6608+ au_dbg_verify_dinode(dentry);
6609+ }
6610+ }
6611+
6612+out:
6613+ return err;
6614+}
6615+
6616+int au_refresh_dentry(struct dentry *dentry, struct dentry *parent)
6617+{
6618+ int err, ebrange;
6619+ unsigned int sigen;
6620+ struct au_dinfo *dinfo, *tmp;
6621+ struct super_block *sb;
6622+ struct inode *inode;
6623+
6624+ DiMustWriteLock(dentry);
6625+ AuDebugOn(IS_ROOT(dentry));
6626+ AuDebugOn(!parent->d_inode);
6627+
6628+ sb = dentry->d_sb;
6629+ inode = dentry->d_inode;
6630+ sigen = au_sigen(sb);
6631+ err = au_digen_test(parent, sigen);
6632+ if (unlikely(err))
6633+ goto out;
6634+
6635+ dinfo = au_di(dentry);
6636+ err = au_di_realloc(dinfo, au_sbend(sb) + 1);
6637+ if (unlikely(err))
6638+ goto out;
6639+ ebrange = au_dbrange_test(dentry);
6640+ if (!ebrange)
6641+ ebrange = au_do_refresh_hdentry(dentry, parent);
6642+
6643+ if (d_unhashed(dentry) || ebrange) {
6644+ AuDebugOn(au_dbstart(dentry) < 0 && au_dbend(dentry) >= 0);
6645+ if (inode)
6646+ err = au_refresh_hinode_self(inode);
6647+ au_dbg_verify_dinode(dentry);
6648+ if (!err)
6649+ goto out_dgen; /* success */
6650+ goto out;
6651+ }
6652+
6653+ /* temporary dinfo */
6654+ AuDbgDentry(dentry);
6655+ err = -ENOMEM;
6656+ tmp = au_di_alloc(sb, AuLsc_DI_TMP);
6657+ if (unlikely(!tmp))
6658+ goto out;
6659+ au_di_swap(tmp, dinfo);
6660+ /* returns the number of positive dentries */
6661+ /*
6662+ * if current working dir is removed, it returns an error.
6663+ * but the dentry is legal.
6664+ */
b4510431 6665+ err = au_lkup_dentry(dentry, /*bstart*/0, /*type*/0, /*flags*/0);
027c5e7a
AM
6666+ AuDbgDentry(dentry);
6667+ au_di_swap(tmp, dinfo);
6668+ if (err == -ENOENT)
6669+ err = 0;
6670+ if (err >= 0) {
6671+ /* compare/refresh by dinfo */
6672+ AuDbgDentry(dentry);
6673+ err = au_refresh_by_dinfo(dentry, dinfo, tmp);
6674+ au_dbg_verify_dinode(dentry);
6675+ AuTraceErr(err);
6676+ }
6677+ au_rw_write_unlock(&tmp->di_rwsem);
6678+ au_di_free(tmp);
6679+ if (unlikely(err))
6680+ goto out;
6681+
6682+out_dgen:
6683+ au_update_digen(dentry);
6684+out:
6685+ if (unlikely(err && !(dentry->d_flags & DCACHE_NFSFS_RENAMED))) {
6686+ AuIOErr("failed refreshing %.*s, %d\n",
6687+ AuDLNPair(dentry), err);
6688+ AuDbgDentry(dentry);
6689+ }
6690+ AuTraceErr(err);
6691+ return err;
6692+}
6693+
b4510431
AM
6694+static int au_do_h_d_reval(struct dentry *h_dentry, unsigned int flags,
6695+ struct dentry *dentry, aufs_bindex_t bindex)
027c5e7a
AM
6696+{
6697+ int err, valid;
027c5e7a
AM
6698+
6699+ err = 0;
6700+ if (!(h_dentry->d_flags & DCACHE_OP_REVALIDATE))
6701+ goto out;
027c5e7a
AM
6702+
6703+ AuDbg("b%d\n", bindex);
b4510431
AM
6704+ /*
6705+ * gave up supporting LOOKUP_CREATE/OPEN for lower fs,
6706+ * due to whiteout and branch permission.
6707+ */
6708+ flags &= ~(/*LOOKUP_PARENT |*/ LOOKUP_OPEN | LOOKUP_CREATE
6709+ | LOOKUP_FOLLOW | LOOKUP_EXCL);
6710+ /* it may return tri-state */
6711+ valid = h_dentry->d_op->d_revalidate(h_dentry, flags);
1facf9fc 6712+
6713+ if (unlikely(valid < 0))
6714+ err = valid;
6715+ else if (!valid)
6716+ err = -EINVAL;
6717+
4f0767ce 6718+out:
1facf9fc 6719+ AuTraceErr(err);
6720+ return err;
6721+}
6722+
6723+/* todo: remove this */
6724+static int h_d_revalidate(struct dentry *dentry, struct inode *inode,
b4510431 6725+ unsigned int flags, int do_udba)
1facf9fc 6726+{
6727+ int err;
6728+ umode_t mode, h_mode;
6729+ aufs_bindex_t bindex, btail, bstart, ibs, ibe;
6730+ unsigned char plus, unhashed, is_root, h_plus;
4a4d8108 6731+ struct inode *h_inode, *h_cached_inode;
1facf9fc 6732+ struct dentry *h_dentry;
6733+ struct qstr *name, *h_name;
6734+
6735+ err = 0;
6736+ plus = 0;
6737+ mode = 0;
1facf9fc 6738+ ibs = -1;
6739+ ibe = -1;
6740+ unhashed = !!d_unhashed(dentry);
6741+ is_root = !!IS_ROOT(dentry);
6742+ name = &dentry->d_name;
6743+
6744+ /*
7f207e10
AM
6745+ * Theoretically, REVAL test should be unnecessary in case of
6746+ * {FS,I}NOTIFY.
6747+ * But {fs,i}notify doesn't fire some necessary events,
1facf9fc 6748+ * IN_ATTRIB for atime/nlink/pageio
6749+ * IN_DELETE for NFS dentry
6750+ * Let's do REVAL test too.
6751+ */
6752+ if (do_udba && inode) {
6753+ mode = (inode->i_mode & S_IFMT);
6754+ plus = (inode->i_nlink > 0);
1facf9fc 6755+ ibs = au_ibstart(inode);
6756+ ibe = au_ibend(inode);
6757+ }
6758+
6759+ bstart = au_dbstart(dentry);
6760+ btail = bstart;
6761+ if (inode && S_ISDIR(inode->i_mode))
6762+ btail = au_dbtaildir(dentry);
6763+ for (bindex = bstart; bindex <= btail; bindex++) {
6764+ h_dentry = au_h_dptr(dentry, bindex);
6765+ if (!h_dentry)
6766+ continue;
6767+
6768+ AuDbg("b%d, %.*s\n", bindex, AuDLNPair(h_dentry));
027c5e7a 6769+ spin_lock(&h_dentry->d_lock);
1facf9fc 6770+ h_name = &h_dentry->d_name;
6771+ if (unlikely(do_udba
6772+ && !is_root
6773+ && (unhashed != !!d_unhashed(h_dentry)
6774+ || name->len != h_name->len
6775+ || memcmp(name->name, h_name->name, name->len))
6776+ )) {
6777+ AuDbg("unhash 0x%x 0x%x, %.*s %.*s\n",
6778+ unhashed, d_unhashed(h_dentry),
6779+ AuDLNPair(dentry), AuDLNPair(h_dentry));
027c5e7a 6780+ spin_unlock(&h_dentry->d_lock);
1facf9fc 6781+ goto err;
6782+ }
027c5e7a 6783+ spin_unlock(&h_dentry->d_lock);
1facf9fc 6784+
b4510431 6785+ err = au_do_h_d_reval(h_dentry, flags, dentry, bindex);
1facf9fc 6786+ if (unlikely(err))
6787+ /* do not goto err, to keep the errno */
6788+ break;
6789+
6790+ /* todo: plink too? */
6791+ if (!do_udba)
6792+ continue;
6793+
6794+ /* UDBA tests */
6795+ h_inode = h_dentry->d_inode;
6796+ if (unlikely(!!inode != !!h_inode))
6797+ goto err;
6798+
6799+ h_plus = plus;
6800+ h_mode = mode;
6801+ h_cached_inode = h_inode;
6802+ if (h_inode) {
6803+ h_mode = (h_inode->i_mode & S_IFMT);
6804+ h_plus = (h_inode->i_nlink > 0);
6805+ }
6806+ if (inode && ibs <= bindex && bindex <= ibe)
6807+ h_cached_inode = au_h_iptr(inode, bindex);
6808+
6809+ if (unlikely(plus != h_plus
6810+ || mode != h_mode
6811+ || h_cached_inode != h_inode))
6812+ goto err;
6813+ continue;
6814+
6815+ err:
6816+ err = -EINVAL;
6817+ break;
6818+ }
6819+
6820+ return err;
6821+}
6822+
027c5e7a 6823+/* todo: consolidate with do_refresh() and au_reval_for_attr() */
1facf9fc 6824+static int simple_reval_dpath(struct dentry *dentry, unsigned int sigen)
6825+{
6826+ int err;
6827+ struct dentry *parent;
1facf9fc 6828+
027c5e7a 6829+ if (!au_digen_test(dentry, sigen))
1facf9fc 6830+ return 0;
6831+
6832+ parent = dget_parent(dentry);
6833+ di_read_lock_parent(parent, AuLock_IR);
027c5e7a 6834+ AuDebugOn(au_digen_test(parent, sigen));
1facf9fc 6835+ au_dbg_verify_gen(parent, sigen);
027c5e7a 6836+ err = au_refresh_dentry(dentry, parent);
1facf9fc 6837+ di_read_unlock(parent, AuLock_IR);
6838+ dput(parent);
027c5e7a 6839+ AuTraceErr(err);
1facf9fc 6840+ return err;
6841+}
6842+
6843+int au_reval_dpath(struct dentry *dentry, unsigned int sigen)
6844+{
6845+ int err;
6846+ struct dentry *d, *parent;
6847+ struct inode *inode;
6848+
027c5e7a 6849+ if (!au_ftest_si(au_sbi(dentry->d_sb), FAILED_REFRESH_DIR))
1facf9fc 6850+ return simple_reval_dpath(dentry, sigen);
6851+
6852+ /* slow loop, keep it simple and stupid */
6853+ /* cf: au_cpup_dirs() */
6854+ err = 0;
6855+ parent = NULL;
027c5e7a 6856+ while (au_digen_test(dentry, sigen)) {
1facf9fc 6857+ d = dentry;
6858+ while (1) {
6859+ dput(parent);
6860+ parent = dget_parent(d);
027c5e7a 6861+ if (!au_digen_test(parent, sigen))
1facf9fc 6862+ break;
6863+ d = parent;
6864+ }
6865+
6866+ inode = d->d_inode;
6867+ if (d != dentry)
027c5e7a 6868+ di_write_lock_child2(d);
1facf9fc 6869+
6870+ /* someone might update our dentry while we were sleeping */
027c5e7a
AM
6871+ if (au_digen_test(d, sigen)) {
6872+ /*
6873+ * todo: consolidate with simple_reval_dpath(),
6874+ * do_refresh() and au_reval_for_attr().
6875+ */
1facf9fc 6876+ di_read_lock_parent(parent, AuLock_IR);
027c5e7a 6877+ err = au_refresh_dentry(d, parent);
1facf9fc 6878+ di_read_unlock(parent, AuLock_IR);
6879+ }
6880+
6881+ if (d != dentry)
6882+ di_write_unlock(d);
6883+ dput(parent);
6884+ if (unlikely(err))
6885+ break;
6886+ }
6887+
6888+ return err;
6889+}
6890+
6891+/*
6892+ * if valid returns 1, otherwise 0.
6893+ */
b4510431 6894+static int aufs_d_revalidate(struct dentry *dentry, unsigned int flags)
1facf9fc 6895+{
6896+ int valid, err;
6897+ unsigned int sigen;
6898+ unsigned char do_udba;
6899+ struct super_block *sb;
6900+ struct inode *inode;
6901+
027c5e7a 6902+ /* todo: support rcu-walk? */
b4510431 6903+ if (flags & LOOKUP_RCU)
027c5e7a
AM
6904+ return -ECHILD;
6905+
6906+ valid = 0;
6907+ if (unlikely(!au_di(dentry)))
6908+ goto out;
6909+
6910+ inode = dentry->d_inode;
6911+ if (inode && is_bad_inode(inode))
6912+ goto out;
6913+
e49829fe 6914+ valid = 1;
1facf9fc 6915+ sb = dentry->d_sb;
e49829fe
JR
6916+ /*
6917+ * todo: very ugly
6918+ * i_mutex of parent dir may be held,
6919+ * but we should not return 'invalid' due to busy.
6920+ */
6921+ err = aufs_read_lock(dentry, AuLock_FLUSH | AuLock_DW | AuLock_NOPLM);
6922+ if (unlikely(err)) {
6923+ valid = err;
027c5e7a 6924+ AuTraceErr(err);
e49829fe
JR
6925+ goto out;
6926+ }
027c5e7a
AM
6927+ if (unlikely(au_dbrange_test(dentry))) {
6928+ err = -EINVAL;
6929+ AuTraceErr(err);
6930+ goto out_dgrade;
1facf9fc 6931+ }
027c5e7a
AM
6932+
6933+ sigen = au_sigen(sb);
6934+ if (au_digen_test(dentry, sigen)) {
1facf9fc 6935+ AuDebugOn(IS_ROOT(dentry));
027c5e7a
AM
6936+ err = au_reval_dpath(dentry, sigen);
6937+ if (unlikely(err)) {
6938+ AuTraceErr(err);
1facf9fc 6939+ goto out_dgrade;
027c5e7a 6940+ }
1facf9fc 6941+ }
6942+ di_downgrade_lock(dentry, AuLock_IR);
6943+
1facf9fc 6944+ err = -EINVAL;
027c5e7a
AM
6945+ if (inode && (IS_DEADDIR(inode) || !inode->i_nlink))
6946+ goto out_inval;
6947+
1facf9fc 6948+ do_udba = !au_opt_test(au_mntflags(sb), UDBA_NONE);
6949+ if (do_udba && inode) {
6950+ aufs_bindex_t bstart = au_ibstart(inode);
027c5e7a 6951+ struct inode *h_inode;
1facf9fc 6952+
027c5e7a
AM
6953+ if (bstart >= 0) {
6954+ h_inode = au_h_iptr(inode, bstart);
6955+ if (h_inode && au_test_higen(inode, h_inode))
6956+ goto out_inval;
6957+ }
1facf9fc 6958+ }
6959+
b4510431 6960+ err = h_d_revalidate(dentry, inode, flags, do_udba);
027c5e7a 6961+ if (unlikely(!err && do_udba && au_dbstart(dentry) < 0)) {
1facf9fc 6962+ err = -EIO;
027c5e7a
AM
6963+ AuDbg("both of real entry and whiteout found, %.*s, err %d\n",
6964+ AuDLNPair(dentry), err);
6965+ }
e49829fe 6966+ goto out_inval;
1facf9fc 6967+
4f0767ce 6968+out_dgrade:
1facf9fc 6969+ di_downgrade_lock(dentry, AuLock_IR);
e49829fe 6970+out_inval:
1facf9fc 6971+ aufs_read_unlock(dentry, AuLock_IR);
6972+ AuTraceErr(err);
6973+ valid = !err;
e49829fe 6974+out:
027c5e7a 6975+ if (!valid) {
e49829fe 6976+ AuDbg("%.*s invalid, %d\n", AuDLNPair(dentry), valid);
027c5e7a
AM
6977+ d_drop(dentry);
6978+ }
1facf9fc 6979+ return valid;
6980+}
6981+
6982+static void aufs_d_release(struct dentry *dentry)
6983+{
027c5e7a 6984+ if (au_di(dentry)) {
4a4d8108
AM
6985+ au_di_fin(dentry);
6986+ au_hn_di_reinit(dentry);
1facf9fc 6987+ }
1facf9fc 6988+}
6989+
4a4d8108 6990+const struct dentry_operations aufs_dop = {
1facf9fc 6991+ .d_revalidate = aufs_d_revalidate,
6992+ .d_release = aufs_d_release
6993+};
7f207e10
AM
6994diff -urN /usr/share/empty/fs/aufs/dentry.h linux/fs/aufs/dentry.h
6995--- /usr/share/empty/fs/aufs/dentry.h 1970-01-01 01:00:00.000000000 +0100
b4510431
AM
6996+++ linux/fs/aufs/dentry.h 2012-10-17 10:31:01.772481151 +0200
6997@@ -0,0 +1,235 @@
1facf9fc 6998+/*
f6c5ef8b 6999+ * Copyright (C) 2005-2012 Junjiro R. Okajima
1facf9fc 7000+ *
7001+ * This program, aufs is free software; you can redistribute it and/or modify
7002+ * it under the terms of the GNU General Public License as published by
7003+ * the Free Software Foundation; either version 2 of the License, or
7004+ * (at your option) any later version.
dece6358
AM
7005+ *
7006+ * This program is distributed in the hope that it will be useful,
7007+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
7008+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
7009+ * GNU General Public License for more details.
7010+ *
7011+ * You should have received a copy of the GNU General Public License
7012+ * along with this program; if not, write to the Free Software
7013+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 7014+ */
7015+
7016+/*
7017+ * lookup and dentry operations
7018+ */
7019+
7020+#ifndef __AUFS_DENTRY_H__
7021+#define __AUFS_DENTRY_H__
7022+
7023+#ifdef __KERNEL__
7024+
dece6358 7025+#include <linux/dcache.h>
1facf9fc 7026+#include "rwsem.h"
7027+
1facf9fc 7028+struct au_hdentry {
7029+ struct dentry *hd_dentry;
027c5e7a 7030+ aufs_bindex_t hd_id;
1facf9fc 7031+};
7032+
7033+struct au_dinfo {
7034+ atomic_t di_generation;
7035+
dece6358 7036+ struct au_rwsem di_rwsem;
1facf9fc 7037+ aufs_bindex_t di_bstart, di_bend, di_bwh, di_bdiropq;
7038+ struct au_hdentry *di_hdentry;
4a4d8108 7039+} ____cacheline_aligned_in_smp;
1facf9fc 7040+
7041+/* ---------------------------------------------------------------------- */
7042+
7043+/* dentry.c */
4a4d8108 7044+extern const struct dentry_operations aufs_dop;
1facf9fc 7045+struct au_branch;
1facf9fc 7046+struct dentry *au_sio_lkup_one(struct qstr *name, struct dentry *parent,
7047+ struct au_branch *br);
7048+int au_h_verify(struct dentry *h_dentry, unsigned int udba, struct inode *h_dir,
7049+ struct dentry *h_parent, struct au_branch *br);
7050+
7051+int au_lkup_dentry(struct dentry *dentry, aufs_bindex_t bstart, mode_t type,
b4510431 7052+ unsigned int flags);
1facf9fc 7053+int au_lkup_neg(struct dentry *dentry, aufs_bindex_t bindex);
027c5e7a 7054+int au_refresh_dentry(struct dentry *dentry, struct dentry *parent);
1facf9fc 7055+int au_reval_dpath(struct dentry *dentry, unsigned int sigen);
7056+
7057+/* dinfo.c */
4a4d8108 7058+void au_di_init_once(void *_di);
027c5e7a
AM
7059+struct au_dinfo *au_di_alloc(struct super_block *sb, unsigned int lsc);
7060+void au_di_free(struct au_dinfo *dinfo);
7061+void au_di_swap(struct au_dinfo *a, struct au_dinfo *b);
7062+void au_di_cp(struct au_dinfo *dst, struct au_dinfo *src);
4a4d8108
AM
7063+int au_di_init(struct dentry *dentry);
7064+void au_di_fin(struct dentry *dentry);
1facf9fc 7065+int au_di_realloc(struct au_dinfo *dinfo, int nbr);
7066+
7067+void di_read_lock(struct dentry *d, int flags, unsigned int lsc);
7068+void di_read_unlock(struct dentry *d, int flags);
7069+void di_downgrade_lock(struct dentry *d, int flags);
7070+void di_write_lock(struct dentry *d, unsigned int lsc);
7071+void di_write_unlock(struct dentry *d);
7072+void di_write_lock2_child(struct dentry *d1, struct dentry *d2, int isdir);
7073+void di_write_lock2_parent(struct dentry *d1, struct dentry *d2, int isdir);
7074+void di_write_unlock2(struct dentry *d1, struct dentry *d2);
7075+
7076+struct dentry *au_h_dptr(struct dentry *dentry, aufs_bindex_t bindex);
2cbb1c4b 7077+struct dentry *au_h_d_alias(struct dentry *dentry, aufs_bindex_t bindex);
1facf9fc 7078+aufs_bindex_t au_dbtail(struct dentry *dentry);
7079+aufs_bindex_t au_dbtaildir(struct dentry *dentry);
7080+
7081+void au_set_h_dptr(struct dentry *dentry, aufs_bindex_t bindex,
7082+ struct dentry *h_dentry);
027c5e7a
AM
7083+int au_digen_test(struct dentry *dentry, unsigned int sigen);
7084+int au_dbrange_test(struct dentry *dentry);
1facf9fc 7085+void au_update_digen(struct dentry *dentry);
7086+void au_update_dbrange(struct dentry *dentry, int do_put_zero);
7087+void au_update_dbstart(struct dentry *dentry);
7088+void au_update_dbend(struct dentry *dentry);
7089+int au_find_dbindex(struct dentry *dentry, struct dentry *h_dentry);
7090+
7091+/* ---------------------------------------------------------------------- */
7092+
7093+static inline struct au_dinfo *au_di(struct dentry *dentry)
7094+{
7095+ return dentry->d_fsdata;
7096+}
7097+
7098+/* ---------------------------------------------------------------------- */
7099+
7100+/* lock subclass for dinfo */
7101+enum {
7102+ AuLsc_DI_CHILD, /* child first */
4a4d8108 7103+ AuLsc_DI_CHILD2, /* rename(2), link(2), and cpup at hnotify */
1facf9fc 7104+ AuLsc_DI_CHILD3, /* copyup dirs */
7105+ AuLsc_DI_PARENT,
7106+ AuLsc_DI_PARENT2,
027c5e7a
AM
7107+ AuLsc_DI_PARENT3,
7108+ AuLsc_DI_TMP /* temp for replacing dinfo */
1facf9fc 7109+};
7110+
7111+/*
7112+ * di_read_lock_child, di_write_lock_child,
7113+ * di_read_lock_child2, di_write_lock_child2,
7114+ * di_read_lock_child3, di_write_lock_child3,
7115+ * di_read_lock_parent, di_write_lock_parent,
7116+ * di_read_lock_parent2, di_write_lock_parent2,
7117+ * di_read_lock_parent3, di_write_lock_parent3,
7118+ */
7119+#define AuReadLockFunc(name, lsc) \
7120+static inline void di_read_lock_##name(struct dentry *d, int flags) \
7121+{ di_read_lock(d, flags, AuLsc_DI_##lsc); }
7122+
7123+#define AuWriteLockFunc(name, lsc) \
7124+static inline void di_write_lock_##name(struct dentry *d) \
7125+{ di_write_lock(d, AuLsc_DI_##lsc); }
7126+
7127+#define AuRWLockFuncs(name, lsc) \
7128+ AuReadLockFunc(name, lsc) \
7129+ AuWriteLockFunc(name, lsc)
7130+
7131+AuRWLockFuncs(child, CHILD);
7132+AuRWLockFuncs(child2, CHILD2);
7133+AuRWLockFuncs(child3, CHILD3);
7134+AuRWLockFuncs(parent, PARENT);
7135+AuRWLockFuncs(parent2, PARENT2);
7136+AuRWLockFuncs(parent3, PARENT3);
7137+
7138+#undef AuReadLockFunc
7139+#undef AuWriteLockFunc
7140+#undef AuRWLockFuncs
7141+
7142+#define DiMustNoWaiters(d) AuRwMustNoWaiters(&au_di(d)->di_rwsem)
dece6358
AM
7143+#define DiMustAnyLock(d) AuRwMustAnyLock(&au_di(d)->di_rwsem)
7144+#define DiMustWriteLock(d) AuRwMustWriteLock(&au_di(d)->di_rwsem)
1facf9fc 7145+
7146+/* ---------------------------------------------------------------------- */
7147+
7148+/* todo: memory barrier? */
7149+static inline unsigned int au_digen(struct dentry *d)
7150+{
7151+ return atomic_read(&au_di(d)->di_generation);
7152+}
7153+
7154+static inline void au_h_dentry_init(struct au_hdentry *hdentry)
7155+{
7156+ hdentry->hd_dentry = NULL;
7157+}
7158+
7159+static inline void au_hdput(struct au_hdentry *hd)
7160+{
4a4d8108
AM
7161+ if (hd)
7162+ dput(hd->hd_dentry);
1facf9fc 7163+}
7164+
7165+static inline aufs_bindex_t au_dbstart(struct dentry *dentry)
7166+{
1308ab2a 7167+ DiMustAnyLock(dentry);
1facf9fc 7168+ return au_di(dentry)->di_bstart;
7169+}
7170+
7171+static inline aufs_bindex_t au_dbend(struct dentry *dentry)
7172+{
1308ab2a 7173+ DiMustAnyLock(dentry);
1facf9fc 7174+ return au_di(dentry)->di_bend;
7175+}
7176+
7177+static inline aufs_bindex_t au_dbwh(struct dentry *dentry)
7178+{
1308ab2a 7179+ DiMustAnyLock(dentry);
1facf9fc 7180+ return au_di(dentry)->di_bwh;
7181+}
7182+
7183+static inline aufs_bindex_t au_dbdiropq(struct dentry *dentry)
7184+{
1308ab2a 7185+ DiMustAnyLock(dentry);
1facf9fc 7186+ return au_di(dentry)->di_bdiropq;
7187+}
7188+
7189+/* todo: hard/soft set? */
7190+static inline void au_set_dbstart(struct dentry *dentry, aufs_bindex_t bindex)
7191+{
1308ab2a 7192+ DiMustWriteLock(dentry);
1facf9fc 7193+ au_di(dentry)->di_bstart = bindex;
7194+}
7195+
7196+static inline void au_set_dbend(struct dentry *dentry, aufs_bindex_t bindex)
7197+{
1308ab2a 7198+ DiMustWriteLock(dentry);
1facf9fc 7199+ au_di(dentry)->di_bend = bindex;
7200+}
7201+
7202+static inline void au_set_dbwh(struct dentry *dentry, aufs_bindex_t bindex)
7203+{
1308ab2a 7204+ DiMustWriteLock(dentry);
1facf9fc 7205+ /* dbwh can be outside of bstart - bend range */
7206+ au_di(dentry)->di_bwh = bindex;
7207+}
7208+
7209+static inline void au_set_dbdiropq(struct dentry *dentry, aufs_bindex_t bindex)
7210+{
1308ab2a 7211+ DiMustWriteLock(dentry);
1facf9fc 7212+ au_di(dentry)->di_bdiropq = bindex;
7213+}
7214+
7215+/* ---------------------------------------------------------------------- */
7216+
4a4d8108 7217+#ifdef CONFIG_AUFS_HNOTIFY
1facf9fc 7218+static inline void au_digen_dec(struct dentry *d)
7219+{
e49829fe 7220+ atomic_dec(&au_di(d)->di_generation);
1facf9fc 7221+}
7222+
4a4d8108 7223+static inline void au_hn_di_reinit(struct dentry *dentry)
1facf9fc 7224+{
7225+ dentry->d_fsdata = NULL;
7226+}
7227+#else
4a4d8108
AM
7228+AuStubVoid(au_hn_di_reinit, struct dentry *dentry __maybe_unused)
7229+#endif /* CONFIG_AUFS_HNOTIFY */
1facf9fc 7230+
7231+#endif /* __KERNEL__ */
7232+#endif /* __AUFS_DENTRY_H__ */
7f207e10
AM
7233diff -urN /usr/share/empty/fs/aufs/dinfo.c linux/fs/aufs/dinfo.c
7234--- /usr/share/empty/fs/aufs/dinfo.c 1970-01-01 01:00:00.000000000 +0100
2dfbb274 7235+++ linux/fs/aufs/dinfo.c 2012-08-26 08:39:00.757174634 +0200
2cbb1c4b 7236@@ -0,0 +1,543 @@
1facf9fc 7237+/*
f6c5ef8b 7238+ * Copyright (C) 2005-2012 Junjiro R. Okajima
1facf9fc 7239+ *
7240+ * This program, aufs is free software; you can redistribute it and/or modify
7241+ * it under the terms of the GNU General Public License as published by
7242+ * the Free Software Foundation; either version 2 of the License, or
7243+ * (at your option) any later version.
dece6358
AM
7244+ *
7245+ * This program is distributed in the hope that it will be useful,
7246+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
7247+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
7248+ * GNU General Public License for more details.
7249+ *
7250+ * You should have received a copy of the GNU General Public License
7251+ * along with this program; if not, write to the Free Software
7252+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 7253+ */
7254+
7255+/*
7256+ * dentry private data
7257+ */
7258+
7259+#include "aufs.h"
7260+
e49829fe 7261+void au_di_init_once(void *_dinfo)
4a4d8108 7262+{
e49829fe
JR
7263+ struct au_dinfo *dinfo = _dinfo;
7264+ static struct lock_class_key aufs_di;
4a4d8108 7265+
e49829fe
JR
7266+ au_rw_init(&dinfo->di_rwsem);
7267+ au_rw_class(&dinfo->di_rwsem, &aufs_di);
4a4d8108
AM
7268+}
7269+
027c5e7a 7270+struct au_dinfo *au_di_alloc(struct super_block *sb, unsigned int lsc)
1facf9fc 7271+{
7272+ struct au_dinfo *dinfo;
027c5e7a 7273+ int nbr, i;
1facf9fc 7274+
7275+ dinfo = au_cache_alloc_dinfo();
7276+ if (unlikely(!dinfo))
7277+ goto out;
7278+
1facf9fc 7279+ nbr = au_sbend(sb) + 1;
7280+ if (nbr <= 0)
7281+ nbr = 1;
7282+ dinfo->di_hdentry = kcalloc(nbr, sizeof(*dinfo->di_hdentry), GFP_NOFS);
027c5e7a
AM
7283+ if (dinfo->di_hdentry) {
7284+ au_rw_write_lock_nested(&dinfo->di_rwsem, lsc);
7285+ dinfo->di_bstart = -1;
7286+ dinfo->di_bend = -1;
7287+ dinfo->di_bwh = -1;
7288+ dinfo->di_bdiropq = -1;
7289+ for (i = 0; i < nbr; i++)
7290+ dinfo->di_hdentry[i].hd_id = -1;
7291+ goto out;
7292+ }
1facf9fc 7293+
1facf9fc 7294+ au_cache_free_dinfo(dinfo);
027c5e7a
AM
7295+ dinfo = NULL;
7296+
4f0767ce 7297+out:
027c5e7a 7298+ return dinfo;
1facf9fc 7299+}
7300+
027c5e7a 7301+void au_di_free(struct au_dinfo *dinfo)
4a4d8108 7302+{
4a4d8108
AM
7303+ struct au_hdentry *p;
7304+ aufs_bindex_t bend, bindex;
7305+
7306+ /* dentry may not be revalidated */
027c5e7a 7307+ bindex = dinfo->di_bstart;
4a4d8108 7308+ if (bindex >= 0) {
027c5e7a
AM
7309+ bend = dinfo->di_bend;
7310+ p = dinfo->di_hdentry + bindex;
4a4d8108
AM
7311+ while (bindex++ <= bend)
7312+ au_hdput(p++);
7313+ }
027c5e7a
AM
7314+ kfree(dinfo->di_hdentry);
7315+ au_cache_free_dinfo(dinfo);
7316+}
7317+
7318+void au_di_swap(struct au_dinfo *a, struct au_dinfo *b)
7319+{
7320+ struct au_hdentry *p;
7321+ aufs_bindex_t bi;
7322+
7323+ AuRwMustWriteLock(&a->di_rwsem);
7324+ AuRwMustWriteLock(&b->di_rwsem);
7325+
7326+#define DiSwap(v, name) \
7327+ do { \
7328+ v = a->di_##name; \
7329+ a->di_##name = b->di_##name; \
7330+ b->di_##name = v; \
7331+ } while (0)
7332+
7333+ DiSwap(p, hdentry);
7334+ DiSwap(bi, bstart);
7335+ DiSwap(bi, bend);
7336+ DiSwap(bi, bwh);
7337+ DiSwap(bi, bdiropq);
7338+ /* smp_mb(); */
7339+
7340+#undef DiSwap
7341+}
7342+
7343+void au_di_cp(struct au_dinfo *dst, struct au_dinfo *src)
7344+{
7345+ AuRwMustWriteLock(&dst->di_rwsem);
7346+ AuRwMustWriteLock(&src->di_rwsem);
7347+
7348+ dst->di_bstart = src->di_bstart;
7349+ dst->di_bend = src->di_bend;
7350+ dst->di_bwh = src->di_bwh;
7351+ dst->di_bdiropq = src->di_bdiropq;
7352+ /* smp_mb(); */
7353+}
7354+
7355+int au_di_init(struct dentry *dentry)
7356+{
7357+ int err;
7358+ struct super_block *sb;
7359+ struct au_dinfo *dinfo;
7360+
7361+ err = 0;
7362+ sb = dentry->d_sb;
7363+ dinfo = au_di_alloc(sb, AuLsc_DI_CHILD);
7364+ if (dinfo) {
7365+ atomic_set(&dinfo->di_generation, au_sigen(sb));
7366+ /* smp_mb(); */ /* atomic_set */
7367+ dentry->d_fsdata = dinfo;
7368+ } else
7369+ err = -ENOMEM;
7370+
7371+ return err;
7372+}
7373+
7374+void au_di_fin(struct dentry *dentry)
7375+{
7376+ struct au_dinfo *dinfo;
7377+
7378+ dinfo = au_di(dentry);
7379+ AuRwDestroy(&dinfo->di_rwsem);
7380+ au_di_free(dinfo);
4a4d8108
AM
7381+}
7382+
1facf9fc 7383+int au_di_realloc(struct au_dinfo *dinfo, int nbr)
7384+{
7385+ int err, sz;
7386+ struct au_hdentry *hdp;
7387+
1308ab2a 7388+ AuRwMustWriteLock(&dinfo->di_rwsem);
7389+
1facf9fc 7390+ err = -ENOMEM;
7391+ sz = sizeof(*hdp) * (dinfo->di_bend + 1);
7392+ if (!sz)
7393+ sz = sizeof(*hdp);
7394+ hdp = au_kzrealloc(dinfo->di_hdentry, sz, sizeof(*hdp) * nbr, GFP_NOFS);
7395+ if (hdp) {
7396+ dinfo->di_hdentry = hdp;
7397+ err = 0;
7398+ }
7399+
7400+ return err;
7401+}
7402+
7403+/* ---------------------------------------------------------------------- */
7404+
7405+static void do_ii_write_lock(struct inode *inode, unsigned int lsc)
7406+{
7407+ switch (lsc) {
7408+ case AuLsc_DI_CHILD:
7409+ ii_write_lock_child(inode);
7410+ break;
7411+ case AuLsc_DI_CHILD2:
7412+ ii_write_lock_child2(inode);
7413+ break;
7414+ case AuLsc_DI_CHILD3:
7415+ ii_write_lock_child3(inode);
7416+ break;
7417+ case AuLsc_DI_PARENT:
7418+ ii_write_lock_parent(inode);
7419+ break;
7420+ case AuLsc_DI_PARENT2:
7421+ ii_write_lock_parent2(inode);
7422+ break;
7423+ case AuLsc_DI_PARENT3:
7424+ ii_write_lock_parent3(inode);
7425+ break;
7426+ default:
7427+ BUG();
7428+ }
7429+}
7430+
7431+static void do_ii_read_lock(struct inode *inode, unsigned int lsc)
7432+{
7433+ switch (lsc) {
7434+ case AuLsc_DI_CHILD:
7435+ ii_read_lock_child(inode);
7436+ break;
7437+ case AuLsc_DI_CHILD2:
7438+ ii_read_lock_child2(inode);
7439+ break;
7440+ case AuLsc_DI_CHILD3:
7441+ ii_read_lock_child3(inode);
7442+ break;
7443+ case AuLsc_DI_PARENT:
7444+ ii_read_lock_parent(inode);
7445+ break;
7446+ case AuLsc_DI_PARENT2:
7447+ ii_read_lock_parent2(inode);
7448+ break;
7449+ case AuLsc_DI_PARENT3:
7450+ ii_read_lock_parent3(inode);
7451+ break;
7452+ default:
7453+ BUG();
7454+ }
7455+}
7456+
7457+void di_read_lock(struct dentry *d, int flags, unsigned int lsc)
7458+{
dece6358 7459+ au_rw_read_lock_nested(&au_di(d)->di_rwsem, lsc);
1facf9fc 7460+ if (d->d_inode) {
7461+ if (au_ftest_lock(flags, IW))
7462+ do_ii_write_lock(d->d_inode, lsc);
7463+ else if (au_ftest_lock(flags, IR))
7464+ do_ii_read_lock(d->d_inode, lsc);
7465+ }
7466+}
7467+
7468+void di_read_unlock(struct dentry *d, int flags)
7469+{
7470+ if (d->d_inode) {
027c5e7a
AM
7471+ if (au_ftest_lock(flags, IW)) {
7472+ au_dbg_verify_dinode(d);
1facf9fc 7473+ ii_write_unlock(d->d_inode);
027c5e7a
AM
7474+ } else if (au_ftest_lock(flags, IR)) {
7475+ au_dbg_verify_dinode(d);
1facf9fc 7476+ ii_read_unlock(d->d_inode);
027c5e7a 7477+ }
1facf9fc 7478+ }
dece6358 7479+ au_rw_read_unlock(&au_di(d)->di_rwsem);
1facf9fc 7480+}
7481+
7482+void di_downgrade_lock(struct dentry *d, int flags)
7483+{
1facf9fc 7484+ if (d->d_inode && au_ftest_lock(flags, IR))
7485+ ii_downgrade_lock(d->d_inode);
dece6358 7486+ au_rw_dgrade_lock(&au_di(d)->di_rwsem);
1facf9fc 7487+}
7488+
7489+void di_write_lock(struct dentry *d, unsigned int lsc)
7490+{
dece6358 7491+ au_rw_write_lock_nested(&au_di(d)->di_rwsem, lsc);
1facf9fc 7492+ if (d->d_inode)
7493+ do_ii_write_lock(d->d_inode, lsc);
7494+}
7495+
7496+void di_write_unlock(struct dentry *d)
7497+{
027c5e7a 7498+ au_dbg_verify_dinode(d);
1facf9fc 7499+ if (d->d_inode)
7500+ ii_write_unlock(d->d_inode);
dece6358 7501+ au_rw_write_unlock(&au_di(d)->di_rwsem);
1facf9fc 7502+}
7503+
7504+void di_write_lock2_child(struct dentry *d1, struct dentry *d2, int isdir)
7505+{
7506+ AuDebugOn(d1 == d2
7507+ || d1->d_inode == d2->d_inode
7508+ || d1->d_sb != d2->d_sb);
7509+
7510+ if (isdir && au_test_subdir(d1, d2)) {
7511+ di_write_lock_child(d1);
7512+ di_write_lock_child2(d2);
7513+ } else {
7514+ /* there should be no races */
7515+ di_write_lock_child(d2);
7516+ di_write_lock_child2(d1);
7517+ }
7518+}
7519+
7520+void di_write_lock2_parent(struct dentry *d1, struct dentry *d2, int isdir)
7521+{
7522+ AuDebugOn(d1 == d2
7523+ || d1->d_inode == d2->d_inode
7524+ || d1->d_sb != d2->d_sb);
7525+
7526+ if (isdir && au_test_subdir(d1, d2)) {
7527+ di_write_lock_parent(d1);
7528+ di_write_lock_parent2(d2);
7529+ } else {
7530+ /* there should be no races */
7531+ di_write_lock_parent(d2);
7532+ di_write_lock_parent2(d1);
7533+ }
7534+}
7535+
7536+void di_write_unlock2(struct dentry *d1, struct dentry *d2)
7537+{
7538+ di_write_unlock(d1);
7539+ if (d1->d_inode == d2->d_inode)
dece6358 7540+ au_rw_write_unlock(&au_di(d2)->di_rwsem);
1facf9fc 7541+ else
7542+ di_write_unlock(d2);
7543+}
7544+
7545+/* ---------------------------------------------------------------------- */
7546+
7547+struct dentry *au_h_dptr(struct dentry *dentry, aufs_bindex_t bindex)
7548+{
7549+ struct dentry *d;
7550+
1308ab2a 7551+ DiMustAnyLock(dentry);
7552+
1facf9fc 7553+ if (au_dbstart(dentry) < 0 || bindex < au_dbstart(dentry))
7554+ return NULL;
7555+ AuDebugOn(bindex < 0);
7556+ d = au_di(dentry)->di_hdentry[0 + bindex].hd_dentry;
027c5e7a 7557+ AuDebugOn(d && d->d_count <= 0);
1facf9fc 7558+ return d;
7559+}
7560+
2cbb1c4b
JR
7561+/*
7562+ * extended version of au_h_dptr().
7563+ * returns a hashed and positive h_dentry in bindex, NULL, or error.
7564+ */
7565+struct dentry *au_h_d_alias(struct dentry *dentry, aufs_bindex_t bindex)
7566+{
7567+ struct dentry *h_dentry;
7568+ struct inode *inode, *h_inode;
7569+
7570+ inode = dentry->d_inode;
7571+ AuDebugOn(!inode);
7572+
7573+ h_dentry = NULL;
7574+ if (au_dbstart(dentry) <= bindex
7575+ && bindex <= au_dbend(dentry))
7576+ h_dentry = au_h_dptr(dentry, bindex);
7577+ if (h_dentry && !au_d_hashed_positive(h_dentry)) {
7578+ dget(h_dentry);
7579+ goto out; /* success */
7580+ }
7581+
7582+ AuDebugOn(bindex < au_ibstart(inode));
7583+ AuDebugOn(au_ibend(inode) < bindex);
7584+ h_inode = au_h_iptr(inode, bindex);
7585+ h_dentry = d_find_alias(h_inode);
7586+ if (h_dentry) {
7587+ if (!IS_ERR(h_dentry)) {
7588+ if (!au_d_hashed_positive(h_dentry))
7589+ goto out; /* success */
7590+ dput(h_dentry);
7591+ } else
7592+ goto out;
7593+ }
7594+
7595+ if (au_opt_test(au_mntflags(dentry->d_sb), PLINK)) {
7596+ h_dentry = au_plink_lkup(inode, bindex);
7597+ AuDebugOn(!h_dentry);
7598+ if (!IS_ERR(h_dentry)) {
7599+ if (!au_d_hashed_positive(h_dentry))
7600+ goto out; /* success */
7601+ dput(h_dentry);
7602+ h_dentry = NULL;
7603+ }
7604+ }
7605+
7606+out:
7607+ AuDbgDentry(h_dentry);
7608+ return h_dentry;
7609+}
7610+
1facf9fc 7611+aufs_bindex_t au_dbtail(struct dentry *dentry)
7612+{
7613+ aufs_bindex_t bend, bwh;
7614+
7615+ bend = au_dbend(dentry);
7616+ if (0 <= bend) {
7617+ bwh = au_dbwh(dentry);
7618+ if (!bwh)
7619+ return bwh;
7620+ if (0 < bwh && bwh < bend)
7621+ return bwh - 1;
7622+ }
7623+ return bend;
7624+}
7625+
7626+aufs_bindex_t au_dbtaildir(struct dentry *dentry)
7627+{
7628+ aufs_bindex_t bend, bopq;
7629+
7630+ bend = au_dbtail(dentry);
7631+ if (0 <= bend) {
7632+ bopq = au_dbdiropq(dentry);
7633+ if (0 <= bopq && bopq < bend)
7634+ bend = bopq;
7635+ }
7636+ return bend;
7637+}
7638+
7639+/* ---------------------------------------------------------------------- */
7640+
7641+void au_set_h_dptr(struct dentry *dentry, aufs_bindex_t bindex,
7642+ struct dentry *h_dentry)
7643+{
7644+ struct au_hdentry *hd = au_di(dentry)->di_hdentry + bindex;
027c5e7a 7645+ struct au_branch *br;
1facf9fc 7646+
1308ab2a 7647+ DiMustWriteLock(dentry);
7648+
4a4d8108 7649+ au_hdput(hd);
1facf9fc 7650+ hd->hd_dentry = h_dentry;
027c5e7a
AM
7651+ if (h_dentry) {
7652+ br = au_sbr(dentry->d_sb, bindex);
7653+ hd->hd_id = br->br_id;
7654+ }
7655+}
7656+
7657+int au_dbrange_test(struct dentry *dentry)
7658+{
7659+ int err;
7660+ aufs_bindex_t bstart, bend;
7661+
7662+ err = 0;
7663+ bstart = au_dbstart(dentry);
7664+ bend = au_dbend(dentry);
7665+ if (bstart >= 0)
7666+ AuDebugOn(bend < 0 && bstart > bend);
7667+ else {
7668+ err = -EIO;
7669+ AuDebugOn(bend >= 0);
7670+ }
7671+
7672+ return err;
7673+}
7674+
7675+int au_digen_test(struct dentry *dentry, unsigned int sigen)
7676+{
7677+ int err;
7678+
7679+ err = 0;
7680+ if (unlikely(au_digen(dentry) != sigen
7681+ || au_iigen_test(dentry->d_inode, sigen)))
7682+ err = -EIO;
7683+
7684+ return err;
1facf9fc 7685+}
7686+
7687+void au_update_digen(struct dentry *dentry)
7688+{
7689+ atomic_set(&au_di(dentry)->di_generation, au_sigen(dentry->d_sb));
7690+ /* smp_mb(); */ /* atomic_set */
7691+}
7692+
7693+void au_update_dbrange(struct dentry *dentry, int do_put_zero)
7694+{
7695+ struct au_dinfo *dinfo;
7696+ struct dentry *h_d;
4a4d8108 7697+ struct au_hdentry *hdp;
1facf9fc 7698+
1308ab2a 7699+ DiMustWriteLock(dentry);
7700+
1facf9fc 7701+ dinfo = au_di(dentry);
7702+ if (!dinfo || dinfo->di_bstart < 0)
7703+ return;
7704+
4a4d8108 7705+ hdp = dinfo->di_hdentry;
1facf9fc 7706+ if (do_put_zero) {
7707+ aufs_bindex_t bindex, bend;
7708+
7709+ bend = dinfo->di_bend;
7710+ for (bindex = dinfo->di_bstart; bindex <= bend; bindex++) {
4a4d8108 7711+ h_d = hdp[0 + bindex].hd_dentry;
1facf9fc 7712+ if (h_d && !h_d->d_inode)
7713+ au_set_h_dptr(dentry, bindex, NULL);
7714+ }
7715+ }
7716+
7717+ dinfo->di_bstart = -1;
7718+ while (++dinfo->di_bstart <= dinfo->di_bend)
4a4d8108 7719+ if (hdp[0 + dinfo->di_bstart].hd_dentry)
1facf9fc 7720+ break;
7721+ if (dinfo->di_bstart > dinfo->di_bend) {
7722+ dinfo->di_bstart = -1;
7723+ dinfo->di_bend = -1;
7724+ return;
7725+ }
7726+
7727+ dinfo->di_bend++;
7728+ while (0 <= --dinfo->di_bend)
4a4d8108 7729+ if (hdp[0 + dinfo->di_bend].hd_dentry)
1facf9fc 7730+ break;
7731+ AuDebugOn(dinfo->di_bstart > dinfo->di_bend || dinfo->di_bend < 0);
7732+}
7733+
7734+void au_update_dbstart(struct dentry *dentry)
7735+{
7736+ aufs_bindex_t bindex, bend;
7737+ struct dentry *h_dentry;
7738+
7739+ bend = au_dbend(dentry);
7740+ for (bindex = au_dbstart(dentry); bindex <= bend; bindex++) {
7741+ h_dentry = au_h_dptr(dentry, bindex);
7742+ if (!h_dentry)
7743+ continue;
7744+ if (h_dentry->d_inode) {
7745+ au_set_dbstart(dentry, bindex);
7746+ return;
7747+ }
7748+ au_set_h_dptr(dentry, bindex, NULL);
7749+ }
7750+}
7751+
7752+void au_update_dbend(struct dentry *dentry)
7753+{
7754+ aufs_bindex_t bindex, bstart;
7755+ struct dentry *h_dentry;
7756+
7757+ bstart = au_dbstart(dentry);
7f207e10 7758+ for (bindex = au_dbend(dentry); bindex >= bstart; bindex--) {
1facf9fc 7759+ h_dentry = au_h_dptr(dentry, bindex);
7760+ if (!h_dentry)
7761+ continue;
7762+ if (h_dentry->d_inode) {
7763+ au_set_dbend(dentry, bindex);
7764+ return;
7765+ }
7766+ au_set_h_dptr(dentry, bindex, NULL);
7767+ }
7768+}
7769+
7770+int au_find_dbindex(struct dentry *dentry, struct dentry *h_dentry)
7771+{
7772+ aufs_bindex_t bindex, bend;
7773+
7774+ bend = au_dbend(dentry);
7775+ for (bindex = au_dbstart(dentry); bindex <= bend; bindex++)
7776+ if (au_h_dptr(dentry, bindex) == h_dentry)
7777+ return bindex;
7778+ return -1;
7779+}
7f207e10
AM
7780diff -urN /usr/share/empty/fs/aufs/dir.c linux/fs/aufs/dir.c
7781--- /usr/share/empty/fs/aufs/dir.c 1970-01-01 01:00:00.000000000 +0100
b4510431
AM
7782+++ linux/fs/aufs/dir.c 2012-10-17 10:31:01.772481151 +0200
7783@@ -0,0 +1,633 @@
1facf9fc 7784+/*
f6c5ef8b 7785+ * Copyright (C) 2005-2012 Junjiro R. Okajima
1facf9fc 7786+ *
7787+ * This program, aufs is free software; you can redistribute it and/or modify
7788+ * it under the terms of the GNU General Public License as published by
7789+ * the Free Software Foundation; either version 2 of the License, or
7790+ * (at your option) any later version.
dece6358
AM
7791+ *
7792+ * This program is distributed in the hope that it will be useful,
7793+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
7794+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
7795+ * GNU General Public License for more details.
7796+ *
7797+ * You should have received a copy of the GNU General Public License
7798+ * along with this program; if not, write to the Free Software
7799+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 7800+ */
7801+
7802+/*
7803+ * directory operations
7804+ */
7805+
7806+#include <linux/fs_stack.h>
7807+#include "aufs.h"
7808+
7809+void au_add_nlink(struct inode *dir, struct inode *h_dir)
7810+{
9dbd164d
AM
7811+ unsigned int nlink;
7812+
1facf9fc 7813+ AuDebugOn(!S_ISDIR(dir->i_mode) || !S_ISDIR(h_dir->i_mode));
7814+
9dbd164d
AM
7815+ nlink = dir->i_nlink;
7816+ nlink += h_dir->i_nlink - 2;
1facf9fc 7817+ if (h_dir->i_nlink < 2)
9dbd164d 7818+ nlink += 2;
7eafdf33 7819+ /* 0 can happen in revaliding */
92d182d2 7820+ set_nlink(dir, nlink);
1facf9fc 7821+}
7822+
7823+void au_sub_nlink(struct inode *dir, struct inode *h_dir)
7824+{
9dbd164d
AM
7825+ unsigned int nlink;
7826+
1facf9fc 7827+ AuDebugOn(!S_ISDIR(dir->i_mode) || !S_ISDIR(h_dir->i_mode));
7828+
9dbd164d
AM
7829+ nlink = dir->i_nlink;
7830+ nlink -= h_dir->i_nlink - 2;
1facf9fc 7831+ if (h_dir->i_nlink < 2)
9dbd164d 7832+ nlink -= 2;
92d182d2 7833+ /* nlink == 0 means the branch-fs is broken */
9dbd164d 7834+ set_nlink(dir, nlink);
1facf9fc 7835+}
7836+
1308ab2a 7837+loff_t au_dir_size(struct file *file, struct dentry *dentry)
7838+{
7839+ loff_t sz;
7840+ aufs_bindex_t bindex, bend;
7841+ struct file *h_file;
7842+ struct dentry *h_dentry;
7843+
7844+ sz = 0;
7845+ if (file) {
7846+ AuDebugOn(!file->f_dentry);
7847+ AuDebugOn(!file->f_dentry->d_inode);
7848+ AuDebugOn(!S_ISDIR(file->f_dentry->d_inode->i_mode));
7849+
4a4d8108 7850+ bend = au_fbend_dir(file);
1308ab2a 7851+ for (bindex = au_fbstart(file);
7852+ bindex <= bend && sz < KMALLOC_MAX_SIZE;
7853+ bindex++) {
4a4d8108 7854+ h_file = au_hf_dir(file, bindex);
1308ab2a 7855+ if (h_file
7856+ && h_file->f_dentry
7857+ && h_file->f_dentry->d_inode)
7858+ sz += i_size_read(h_file->f_dentry->d_inode);
7859+ }
7860+ } else {
7861+ AuDebugOn(!dentry);
7862+ AuDebugOn(!dentry->d_inode);
7863+ AuDebugOn(!S_ISDIR(dentry->d_inode->i_mode));
7864+
7865+ bend = au_dbtaildir(dentry);
7866+ for (bindex = au_dbstart(dentry);
7867+ bindex <= bend && sz < KMALLOC_MAX_SIZE;
7868+ bindex++) {
7869+ h_dentry = au_h_dptr(dentry, bindex);
7870+ if (h_dentry && h_dentry->d_inode)
7871+ sz += i_size_read(h_dentry->d_inode);
7872+ }
7873+ }
7874+ if (sz < KMALLOC_MAX_SIZE)
7875+ sz = roundup_pow_of_two(sz);
7876+ if (sz > KMALLOC_MAX_SIZE)
7877+ sz = KMALLOC_MAX_SIZE;
7878+ else if (sz < NAME_MAX) {
7879+ BUILD_BUG_ON(AUFS_RDBLK_DEF < NAME_MAX);
7880+ sz = AUFS_RDBLK_DEF;
7881+ }
7882+ return sz;
7883+}
7884+
1facf9fc 7885+/* ---------------------------------------------------------------------- */
7886+
7887+static int reopen_dir(struct file *file)
7888+{
7889+ int err;
7890+ unsigned int flags;
7891+ aufs_bindex_t bindex, btail, bstart;
7892+ struct dentry *dentry, *h_dentry;
7893+ struct file *h_file;
7894+
7895+ /* open all lower dirs */
7896+ dentry = file->f_dentry;
7897+ bstart = au_dbstart(dentry);
7898+ for (bindex = au_fbstart(file); bindex < bstart; bindex++)
7899+ au_set_h_fptr(file, bindex, NULL);
7900+ au_set_fbstart(file, bstart);
7901+
7902+ btail = au_dbtaildir(dentry);
4a4d8108 7903+ for (bindex = au_fbend_dir(file); btail < bindex; bindex--)
1facf9fc 7904+ au_set_h_fptr(file, bindex, NULL);
4a4d8108 7905+ au_set_fbend_dir(file, btail);
1facf9fc 7906+
4a4d8108 7907+ flags = vfsub_file_flags(file);
1facf9fc 7908+ for (bindex = bstart; bindex <= btail; bindex++) {
7909+ h_dentry = au_h_dptr(dentry, bindex);
7910+ if (!h_dentry)
7911+ continue;
4a4d8108 7912+ h_file = au_hf_dir(file, bindex);
1facf9fc 7913+ if (h_file)
7914+ continue;
7915+
7916+ h_file = au_h_open(dentry, bindex, flags, file);
7917+ err = PTR_ERR(h_file);
7918+ if (IS_ERR(h_file))
7919+ goto out; /* close all? */
7920+ au_set_h_fptr(file, bindex, h_file);
7921+ }
7922+ au_update_figen(file);
7923+ /* todo: necessary? */
7924+ /* file->f_ra = h_file->f_ra; */
7925+ err = 0;
7926+
4f0767ce 7927+out:
1facf9fc 7928+ return err;
7929+}
7930+
7931+static int do_open_dir(struct file *file, int flags)
7932+{
7933+ int err;
7934+ aufs_bindex_t bindex, btail;
7935+ struct dentry *dentry, *h_dentry;
7936+ struct file *h_file;
7937+
1308ab2a 7938+ FiMustWriteLock(file);
7939+
1facf9fc 7940+ dentry = file->f_dentry;
027c5e7a
AM
7941+ err = au_alive_dir(dentry);
7942+ if (unlikely(err))
7943+ goto out;
7944+
1facf9fc 7945+ file->f_version = dentry->d_inode->i_version;
7946+ bindex = au_dbstart(dentry);
7947+ au_set_fbstart(file, bindex);
7948+ btail = au_dbtaildir(dentry);
4a4d8108 7949+ au_set_fbend_dir(file, btail);
1facf9fc 7950+ for (; !err && bindex <= btail; bindex++) {
7951+ h_dentry = au_h_dptr(dentry, bindex);
7952+ if (!h_dentry)
7953+ continue;
7954+
7955+ h_file = au_h_open(dentry, bindex, flags, file);
7956+ if (IS_ERR(h_file)) {
7957+ err = PTR_ERR(h_file);
7958+ break;
7959+ }
7960+ au_set_h_fptr(file, bindex, h_file);
7961+ }
7962+ au_update_figen(file);
7963+ /* todo: necessary? */
7964+ /* file->f_ra = h_file->f_ra; */
7965+ if (!err)
7966+ return 0; /* success */
7967+
7968+ /* close all */
7969+ for (bindex = au_fbstart(file); bindex <= btail; bindex++)
7970+ au_set_h_fptr(file, bindex, NULL);
7971+ au_set_fbstart(file, -1);
4a4d8108
AM
7972+ au_set_fbend_dir(file, -1);
7973+
027c5e7a 7974+out:
1facf9fc 7975+ return err;
7976+}
7977+
7978+static int aufs_open_dir(struct inode *inode __maybe_unused,
7979+ struct file *file)
7980+{
4a4d8108
AM
7981+ int err;
7982+ struct super_block *sb;
7983+ struct au_fidir *fidir;
7984+
7985+ err = -ENOMEM;
7986+ sb = file->f_dentry->d_sb;
7987+ si_read_lock(sb, AuLock_FLUSH);
e49829fe 7988+ fidir = au_fidir_alloc(sb);
4a4d8108
AM
7989+ if (fidir) {
7990+ err = au_do_open(file, do_open_dir, fidir);
7991+ if (unlikely(err))
7992+ kfree(fidir);
7993+ }
7994+ si_read_unlock(sb);
7995+ return err;
1facf9fc 7996+}
7997+
7998+static int aufs_release_dir(struct inode *inode __maybe_unused,
7999+ struct file *file)
8000+{
8001+ struct au_vdir *vdir_cache;
4a4d8108
AM
8002+ struct au_finfo *finfo;
8003+ struct au_fidir *fidir;
8004+ aufs_bindex_t bindex, bend;
1facf9fc 8005+
4a4d8108
AM
8006+ finfo = au_fi(file);
8007+ fidir = finfo->fi_hdir;
8008+ if (fidir) {
8009+ vdir_cache = fidir->fd_vdir_cache; /* lock-free */
8010+ if (vdir_cache)
8011+ au_vdir_free(vdir_cache);
8012+
8013+ bindex = finfo->fi_btop;
8014+ if (bindex >= 0) {
8015+ /*
8016+ * calls fput() instead of filp_close(),
8017+ * since no dnotify or lock for the lower file.
8018+ */
8019+ bend = fidir->fd_bbot;
8020+ for (; bindex <= bend; bindex++)
8021+ au_set_h_fptr(file, bindex, NULL);
8022+ }
8023+ kfree(fidir);
8024+ finfo->fi_hdir = NULL;
1facf9fc 8025+ }
1facf9fc 8026+ au_finfo_fin(file);
1facf9fc 8027+ return 0;
8028+}
8029+
8030+/* ---------------------------------------------------------------------- */
8031+
4a4d8108
AM
8032+static int au_do_flush_dir(struct file *file, fl_owner_t id)
8033+{
8034+ int err;
8035+ aufs_bindex_t bindex, bend;
8036+ struct file *h_file;
8037+
8038+ err = 0;
8039+ bend = au_fbend_dir(file);
8040+ for (bindex = au_fbstart(file); !err && bindex <= bend; bindex++) {
8041+ h_file = au_hf_dir(file, bindex);
8042+ if (h_file)
8043+ err = vfsub_flush(h_file, id);
8044+ }
8045+ return err;
8046+}
8047+
8048+static int aufs_flush_dir(struct file *file, fl_owner_t id)
8049+{
8050+ return au_do_flush(file, id, au_do_flush_dir);
8051+}
8052+
8053+/* ---------------------------------------------------------------------- */
8054+
1facf9fc 8055+static int au_do_fsync_dir_no_file(struct dentry *dentry, int datasync)
8056+{
8057+ int err;
8058+ aufs_bindex_t bend, bindex;
8059+ struct inode *inode;
8060+ struct super_block *sb;
8061+
8062+ err = 0;
8063+ sb = dentry->d_sb;
8064+ inode = dentry->d_inode;
8065+ IMustLock(inode);
8066+ bend = au_dbend(dentry);
8067+ for (bindex = au_dbstart(dentry); !err && bindex <= bend; bindex++) {
8068+ struct path h_path;
1facf9fc 8069+
8070+ if (au_test_ro(sb, bindex, inode))
8071+ continue;
8072+ h_path.dentry = au_h_dptr(dentry, bindex);
8073+ if (!h_path.dentry)
8074+ continue;
1facf9fc 8075+
1facf9fc 8076+ h_path.mnt = au_sbr_mnt(sb, bindex);
53392da6 8077+ err = vfsub_fsync(NULL, &h_path, datasync);
1facf9fc 8078+ }
8079+
8080+ return err;
8081+}
8082+
8083+static int au_do_fsync_dir(struct file *file, int datasync)
8084+{
8085+ int err;
8086+ aufs_bindex_t bend, bindex;
8087+ struct file *h_file;
8088+ struct super_block *sb;
8089+ struct inode *inode;
1facf9fc 8090+
8091+ err = au_reval_and_lock_fdi(file, reopen_dir, /*wlock*/1);
8092+ if (unlikely(err))
8093+ goto out;
8094+
8095+ sb = file->f_dentry->d_sb;
8096+ inode = file->f_dentry->d_inode;
4a4d8108 8097+ bend = au_fbend_dir(file);
1facf9fc 8098+ for (bindex = au_fbstart(file); !err && bindex <= bend; bindex++) {
4a4d8108 8099+ h_file = au_hf_dir(file, bindex);
1facf9fc 8100+ if (!h_file || au_test_ro(sb, bindex, inode))
8101+ continue;
8102+
53392da6 8103+ err = vfsub_fsync(h_file, &h_file->f_path, datasync);
1facf9fc 8104+ }
8105+
4f0767ce 8106+out:
1facf9fc 8107+ return err;
8108+}
8109+
8110+/*
8111+ * @file may be NULL
8112+ */
1e00d052
AM
8113+static int aufs_fsync_dir(struct file *file, loff_t start, loff_t end,
8114+ int datasync)
1facf9fc 8115+{
8116+ int err;
b752ccd1 8117+ struct dentry *dentry;
1facf9fc 8118+ struct super_block *sb;
1e00d052 8119+ struct mutex *mtx;
1facf9fc 8120+
8121+ err = 0;
1e00d052
AM
8122+ dentry = file->f_dentry;
8123+ mtx = &dentry->d_inode->i_mutex;
8124+ mutex_lock(mtx);
1facf9fc 8125+ sb = dentry->d_sb;
8126+ si_noflush_read_lock(sb);
8127+ if (file)
8128+ err = au_do_fsync_dir(file, datasync);
8129+ else {
8130+ di_write_lock_child(dentry);
8131+ err = au_do_fsync_dir_no_file(dentry, datasync);
8132+ }
8133+ au_cpup_attr_timesizes(dentry->d_inode);
8134+ di_write_unlock(dentry);
8135+ if (file)
8136+ fi_write_unlock(file);
8137+
8138+ si_read_unlock(sb);
1e00d052 8139+ mutex_unlock(mtx);
1facf9fc 8140+ return err;
8141+}
8142+
8143+/* ---------------------------------------------------------------------- */
8144+
8145+static int aufs_readdir(struct file *file, void *dirent, filldir_t filldir)
8146+{
8147+ int err;
8148+ struct dentry *dentry;
9dbd164d 8149+ struct inode *inode, *h_inode;
1facf9fc 8150+ struct super_block *sb;
8151+
8152+ dentry = file->f_dentry;
8153+ inode = dentry->d_inode;
8154+ IMustLock(inode);
8155+
8156+ sb = dentry->d_sb;
8157+ si_read_lock(sb, AuLock_FLUSH);
8158+ err = au_reval_and_lock_fdi(file, reopen_dir, /*wlock*/1);
8159+ if (unlikely(err))
8160+ goto out;
027c5e7a
AM
8161+ err = au_alive_dir(dentry);
8162+ if (!err)
8163+ err = au_vdir_init(file);
1facf9fc 8164+ di_downgrade_lock(dentry, AuLock_IR);
8165+ if (unlikely(err))
8166+ goto out_unlock;
8167+
9dbd164d 8168+ h_inode = au_h_iptr(inode, au_ibstart(inode));
b752ccd1 8169+ if (!au_test_nfsd()) {
1facf9fc 8170+ err = au_vdir_fill_de(file, dirent, filldir);
9dbd164d 8171+ fsstack_copy_attr_atime(inode, h_inode);
1facf9fc 8172+ } else {
8173+ /*
8174+ * nfsd filldir may call lookup_one_len(), vfs_getattr(),
8175+ * encode_fh() and others.
8176+ */
9dbd164d 8177+ atomic_inc(&h_inode->i_count);
1facf9fc 8178+ di_read_unlock(dentry, AuLock_IR);
8179+ si_read_unlock(sb);
1facf9fc 8180+ err = au_vdir_fill_de(file, dirent, filldir);
1facf9fc 8181+ fsstack_copy_attr_atime(inode, h_inode);
8182+ fi_write_unlock(file);
9dbd164d 8183+ iput(h_inode);
1facf9fc 8184+
8185+ AuTraceErr(err);
8186+ return err;
8187+ }
8188+
4f0767ce 8189+out_unlock:
1facf9fc 8190+ di_read_unlock(dentry, AuLock_IR);
8191+ fi_write_unlock(file);
4f0767ce 8192+out:
1facf9fc 8193+ si_read_unlock(sb);
8194+ return err;
8195+}
8196+
8197+/* ---------------------------------------------------------------------- */
8198+
8199+#define AuTestEmpty_WHONLY 1
dece6358
AM
8200+#define AuTestEmpty_CALLED (1 << 1)
8201+#define AuTestEmpty_SHWH (1 << 2)
1facf9fc 8202+#define au_ftest_testempty(flags, name) ((flags) & AuTestEmpty_##name)
7f207e10
AM
8203+#define au_fset_testempty(flags, name) \
8204+ do { (flags) |= AuTestEmpty_##name; } while (0)
8205+#define au_fclr_testempty(flags, name) \
8206+ do { (flags) &= ~AuTestEmpty_##name; } while (0)
1facf9fc 8207+
dece6358
AM
8208+#ifndef CONFIG_AUFS_SHWH
8209+#undef AuTestEmpty_SHWH
8210+#define AuTestEmpty_SHWH 0
8211+#endif
8212+
1facf9fc 8213+struct test_empty_arg {
1308ab2a 8214+ struct au_nhash *whlist;
1facf9fc 8215+ unsigned int flags;
8216+ int err;
8217+ aufs_bindex_t bindex;
8218+};
8219+
8220+static int test_empty_cb(void *__arg, const char *__name, int namelen,
dece6358
AM
8221+ loff_t offset __maybe_unused, u64 ino,
8222+ unsigned int d_type)
1facf9fc 8223+{
8224+ struct test_empty_arg *arg = __arg;
8225+ char *name = (void *)__name;
8226+
8227+ arg->err = 0;
8228+ au_fset_testempty(arg->flags, CALLED);
8229+ /* smp_mb(); */
8230+ if (name[0] == '.'
8231+ && (namelen == 1 || (name[1] == '.' && namelen == 2)))
8232+ goto out; /* success */
8233+
8234+ if (namelen <= AUFS_WH_PFX_LEN
8235+ || memcmp(name, AUFS_WH_PFX, AUFS_WH_PFX_LEN)) {
8236+ if (au_ftest_testempty(arg->flags, WHONLY)
1308ab2a 8237+ && !au_nhash_test_known_wh(arg->whlist, name, namelen))
1facf9fc 8238+ arg->err = -ENOTEMPTY;
8239+ goto out;
8240+ }
8241+
8242+ name += AUFS_WH_PFX_LEN;
8243+ namelen -= AUFS_WH_PFX_LEN;
1308ab2a 8244+ if (!au_nhash_test_known_wh(arg->whlist, name, namelen))
1facf9fc 8245+ arg->err = au_nhash_append_wh
1308ab2a 8246+ (arg->whlist, name, namelen, ino, d_type, arg->bindex,
dece6358 8247+ au_ftest_testempty(arg->flags, SHWH));
1facf9fc 8248+
4f0767ce 8249+out:
1facf9fc 8250+ /* smp_mb(); */
8251+ AuTraceErr(arg->err);
8252+ return arg->err;
8253+}
8254+
8255+static int do_test_empty(struct dentry *dentry, struct test_empty_arg *arg)
8256+{
8257+ int err;
8258+ struct file *h_file;
8259+
8260+ h_file = au_h_open(dentry, arg->bindex,
8261+ O_RDONLY | O_NONBLOCK | O_DIRECTORY | O_LARGEFILE,
8262+ /*file*/NULL);
8263+ err = PTR_ERR(h_file);
8264+ if (IS_ERR(h_file))
8265+ goto out;
8266+
8267+ err = 0;
8268+ if (!au_opt_test(au_mntflags(dentry->d_sb), UDBA_NONE)
8269+ && !h_file->f_dentry->d_inode->i_nlink)
8270+ goto out_put;
8271+
8272+ do {
8273+ arg->err = 0;
8274+ au_fclr_testempty(arg->flags, CALLED);
8275+ /* smp_mb(); */
8276+ err = vfsub_readdir(h_file, test_empty_cb, arg);
8277+ if (err >= 0)
8278+ err = arg->err;
8279+ } while (!err && au_ftest_testempty(arg->flags, CALLED));
8280+
4f0767ce 8281+out_put:
1facf9fc 8282+ fput(h_file);
8283+ au_sbr_put(dentry->d_sb, arg->bindex);
4f0767ce 8284+out:
1facf9fc 8285+ return err;
8286+}
8287+
8288+struct do_test_empty_args {
8289+ int *errp;
8290+ struct dentry *dentry;
8291+ struct test_empty_arg *arg;
8292+};
8293+
8294+static void call_do_test_empty(void *args)
8295+{
8296+ struct do_test_empty_args *a = args;
8297+ *a->errp = do_test_empty(a->dentry, a->arg);
8298+}
8299+
8300+static int sio_test_empty(struct dentry *dentry, struct test_empty_arg *arg)
8301+{
8302+ int err, wkq_err;
8303+ struct dentry *h_dentry;
8304+ struct inode *h_inode;
8305+
8306+ h_dentry = au_h_dptr(dentry, arg->bindex);
8307+ h_inode = h_dentry->d_inode;
53392da6 8308+ /* todo: i_mode changes anytime? */
1facf9fc 8309+ mutex_lock_nested(&h_inode->i_mutex, AuLsc_I_CHILD);
8310+ err = au_test_h_perm_sio(h_inode, MAY_EXEC | MAY_READ);
8311+ mutex_unlock(&h_inode->i_mutex);
8312+ if (!err)
8313+ err = do_test_empty(dentry, arg);
8314+ else {
8315+ struct do_test_empty_args args = {
8316+ .errp = &err,
8317+ .dentry = dentry,
8318+ .arg = arg
8319+ };
8320+ unsigned int flags = arg->flags;
8321+
8322+ wkq_err = au_wkq_wait(call_do_test_empty, &args);
8323+ if (unlikely(wkq_err))
8324+ err = wkq_err;
8325+ arg->flags = flags;
8326+ }
8327+
8328+ return err;
8329+}
8330+
8331+int au_test_empty_lower(struct dentry *dentry)
8332+{
8333+ int err;
1308ab2a 8334+ unsigned int rdhash;
1facf9fc 8335+ aufs_bindex_t bindex, bstart, btail;
1308ab2a 8336+ struct au_nhash whlist;
1facf9fc 8337+ struct test_empty_arg arg;
1facf9fc 8338+
dece6358
AM
8339+ SiMustAnyLock(dentry->d_sb);
8340+
1308ab2a 8341+ rdhash = au_sbi(dentry->d_sb)->si_rdhash;
8342+ if (!rdhash)
8343+ rdhash = au_rdhash_est(au_dir_size(/*file*/NULL, dentry));
8344+ err = au_nhash_alloc(&whlist, rdhash, GFP_NOFS);
dece6358 8345+ if (unlikely(err))
1facf9fc 8346+ goto out;
8347+
1facf9fc 8348+ arg.flags = 0;
1308ab2a 8349+ arg.whlist = &whlist;
8350+ bstart = au_dbstart(dentry);
dece6358
AM
8351+ if (au_opt_test(au_mntflags(dentry->d_sb), SHWH))
8352+ au_fset_testempty(arg.flags, SHWH);
1facf9fc 8353+ arg.bindex = bstart;
8354+ err = do_test_empty(dentry, &arg);
8355+ if (unlikely(err))
8356+ goto out_whlist;
8357+
8358+ au_fset_testempty(arg.flags, WHONLY);
8359+ btail = au_dbtaildir(dentry);
8360+ for (bindex = bstart + 1; !err && bindex <= btail; bindex++) {
8361+ struct dentry *h_dentry;
8362+
8363+ h_dentry = au_h_dptr(dentry, bindex);
8364+ if (h_dentry && h_dentry->d_inode) {
8365+ arg.bindex = bindex;
8366+ err = do_test_empty(dentry, &arg);
8367+ }
8368+ }
8369+
4f0767ce 8370+out_whlist:
1308ab2a 8371+ au_nhash_wh_free(&whlist);
4f0767ce 8372+out:
1facf9fc 8373+ return err;
8374+}
8375+
8376+int au_test_empty(struct dentry *dentry, struct au_nhash *whlist)
8377+{
8378+ int err;
8379+ struct test_empty_arg arg;
8380+ aufs_bindex_t bindex, btail;
8381+
8382+ err = 0;
1308ab2a 8383+ arg.whlist = whlist;
1facf9fc 8384+ arg.flags = AuTestEmpty_WHONLY;
dece6358
AM
8385+ if (au_opt_test(au_mntflags(dentry->d_sb), SHWH))
8386+ au_fset_testempty(arg.flags, SHWH);
1facf9fc 8387+ btail = au_dbtaildir(dentry);
8388+ for (bindex = au_dbstart(dentry); !err && bindex <= btail; bindex++) {
8389+ struct dentry *h_dentry;
8390+
8391+ h_dentry = au_h_dptr(dentry, bindex);
8392+ if (h_dentry && h_dentry->d_inode) {
8393+ arg.bindex = bindex;
8394+ err = sio_test_empty(dentry, &arg);
8395+ }
8396+ }
8397+
8398+ return err;
8399+}
8400+
8401+/* ---------------------------------------------------------------------- */
8402+
8403+const struct file_operations aufs_dir_fop = {
4a4d8108 8404+ .owner = THIS_MODULE,
027c5e7a 8405+ .llseek = default_llseek,
1facf9fc 8406+ .read = generic_read_dir,
8407+ .readdir = aufs_readdir,
8408+ .unlocked_ioctl = aufs_ioctl_dir,
b752ccd1
AM
8409+#ifdef CONFIG_COMPAT
8410+ .compat_ioctl = aufs_compat_ioctl_dir,
8411+#endif
1facf9fc 8412+ .open = aufs_open_dir,
8413+ .release = aufs_release_dir,
4a4d8108 8414+ .flush = aufs_flush_dir,
1facf9fc 8415+ .fsync = aufs_fsync_dir
8416+};
7f207e10
AM
8417diff -urN /usr/share/empty/fs/aufs/dir.h linux/fs/aufs/dir.h
8418--- /usr/share/empty/fs/aufs/dir.h 1970-01-01 01:00:00.000000000 +0100
2dfbb274 8419+++ linux/fs/aufs/dir.h 2012-08-26 08:39:00.760508065 +0200
f6c5ef8b 8420@@ -0,0 +1,137 @@
1facf9fc 8421+/*
f6c5ef8b 8422+ * Copyright (C) 2005-2012 Junjiro R. Okajima
1facf9fc 8423+ *
8424+ * This program, aufs is free software; you can redistribute it and/or modify
8425+ * it under the terms of the GNU General Public License as published by
8426+ * the Free Software Foundation; either version 2 of the License, or
8427+ * (at your option) any later version.
dece6358
AM
8428+ *
8429+ * This program is distributed in the hope that it will be useful,
8430+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
8431+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
8432+ * GNU General Public License for more details.
8433+ *
8434+ * You should have received a copy of the GNU General Public License
8435+ * along with this program; if not, write to the Free Software
8436+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 8437+ */
8438+
8439+/*
8440+ * directory operations
8441+ */
8442+
8443+#ifndef __AUFS_DIR_H__
8444+#define __AUFS_DIR_H__
8445+
8446+#ifdef __KERNEL__
8447+
8448+#include <linux/fs.h>
1facf9fc 8449+
8450+/* ---------------------------------------------------------------------- */
8451+
8452+/* need to be faster and smaller */
8453+
8454+struct au_nhash {
dece6358
AM
8455+ unsigned int nh_num;
8456+ struct hlist_head *nh_head;
1facf9fc 8457+};
8458+
8459+struct au_vdir_destr {
8460+ unsigned char len;
8461+ unsigned char name[0];
8462+} __packed;
8463+
8464+struct au_vdir_dehstr {
8465+ struct hlist_node hash;
8466+ struct au_vdir_destr *str;
4a4d8108 8467+} ____cacheline_aligned_in_smp;
1facf9fc 8468+
8469+struct au_vdir_de {
8470+ ino_t de_ino;
8471+ unsigned char de_type;
8472+ /* caution: packed */
8473+ struct au_vdir_destr de_str;
8474+} __packed;
8475+
8476+struct au_vdir_wh {
8477+ struct hlist_node wh_hash;
dece6358
AM
8478+#ifdef CONFIG_AUFS_SHWH
8479+ ino_t wh_ino;
1facf9fc 8480+ aufs_bindex_t wh_bindex;
dece6358
AM
8481+ unsigned char wh_type;
8482+#else
8483+ aufs_bindex_t wh_bindex;
8484+#endif
8485+ /* caution: packed */
1facf9fc 8486+ struct au_vdir_destr wh_str;
8487+} __packed;
8488+
8489+union au_vdir_deblk_p {
8490+ unsigned char *deblk;
8491+ struct au_vdir_de *de;
8492+};
8493+
8494+struct au_vdir {
8495+ unsigned char **vd_deblk;
8496+ unsigned long vd_nblk;
1facf9fc 8497+ struct {
8498+ unsigned long ul;
8499+ union au_vdir_deblk_p p;
8500+ } vd_last;
8501+
8502+ unsigned long vd_version;
dece6358 8503+ unsigned int vd_deblk_sz;
1facf9fc 8504+ unsigned long vd_jiffy;
4a4d8108 8505+} ____cacheline_aligned_in_smp;
1facf9fc 8506+
8507+/* ---------------------------------------------------------------------- */
8508+
8509+/* dir.c */
8510+extern const struct file_operations aufs_dir_fop;
8511+void au_add_nlink(struct inode *dir, struct inode *h_dir);
8512+void au_sub_nlink(struct inode *dir, struct inode *h_dir);
1308ab2a 8513+loff_t au_dir_size(struct file *file, struct dentry *dentry);
1facf9fc 8514+int au_test_empty_lower(struct dentry *dentry);
8515+int au_test_empty(struct dentry *dentry, struct au_nhash *whlist);
8516+
8517+/* vdir.c */
1308ab2a 8518+unsigned int au_rdhash_est(loff_t sz);
dece6358
AM
8519+int au_nhash_alloc(struct au_nhash *nhash, unsigned int num_hash, gfp_t gfp);
8520+void au_nhash_wh_free(struct au_nhash *whlist);
1facf9fc 8521+int au_nhash_test_longer_wh(struct au_nhash *whlist, aufs_bindex_t btgt,
8522+ int limit);
dece6358
AM
8523+int au_nhash_test_known_wh(struct au_nhash *whlist, char *name, int nlen);
8524+int au_nhash_append_wh(struct au_nhash *whlist, char *name, int nlen, ino_t ino,
8525+ unsigned int d_type, aufs_bindex_t bindex,
8526+ unsigned char shwh);
1facf9fc 8527+void au_vdir_free(struct au_vdir *vdir);
8528+int au_vdir_init(struct file *file);
8529+int au_vdir_fill_de(struct file *file, void *dirent, filldir_t filldir);
8530+
8531+/* ioctl.c */
8532+long aufs_ioctl_dir(struct file *file, unsigned int cmd, unsigned long arg);
8533+
1308ab2a 8534+#ifdef CONFIG_AUFS_RDU
8535+/* rdu.c */
8536+long au_rdu_ioctl(struct file *file, unsigned int cmd, unsigned long arg);
b752ccd1
AM
8537+#ifdef CONFIG_COMPAT
8538+long au_rdu_compat_ioctl(struct file *file, unsigned int cmd,
8539+ unsigned long arg);
8540+#endif
1308ab2a 8541+#else
8542+static inline long au_rdu_ioctl(struct file *file, unsigned int cmd,
8543+ unsigned long arg)
8544+{
8545+ return -EINVAL;
8546+}
b752ccd1
AM
8547+#ifdef CONFIG_COMPAT
8548+static inline long au_rdu_compat_ioctl(struct file *file, unsigned int cmd,
8549+ unsigned long arg)
8550+{
8551+ return -EINVAL;
8552+}
8553+#endif
1308ab2a 8554+#endif
8555+
1facf9fc 8556+#endif /* __KERNEL__ */
8557+#endif /* __AUFS_DIR_H__ */
7f207e10
AM
8558diff -urN /usr/share/empty/fs/aufs/dynop.c linux/fs/aufs/dynop.c
8559--- /usr/share/empty/fs/aufs/dynop.c 1970-01-01 01:00:00.000000000 +0100
b4510431
AM
8560+++ linux/fs/aufs/dynop.c 2012-10-17 10:31:01.772481151 +0200
8561@@ -0,0 +1,379 @@
1facf9fc 8562+/*
f6c5ef8b 8563+ * Copyright (C) 2010-2012 Junjiro R. Okajima
1facf9fc 8564+ *
8565+ * This program, aufs is free software; you can redistribute it and/or modify
8566+ * it under the terms of the GNU General Public License as published by
8567+ * the Free Software Foundation; either version 2 of the License, or
8568+ * (at your option) any later version.
dece6358
AM
8569+ *
8570+ * This program is distributed in the hope that it will be useful,
8571+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
8572+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
8573+ * GNU General Public License for more details.
8574+ *
8575+ * You should have received a copy of the GNU General Public License
8576+ * along with this program; if not, write to the Free Software
8577+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 8578+ */
8579+
8580+/*
4a4d8108 8581+ * dynamically customizable operations for regular files
1facf9fc 8582+ */
8583+
1facf9fc 8584+#include "aufs.h"
8585+
4a4d8108 8586+#define DyPrSym(key) AuDbgSym(key->dk_op.dy_hop)
1facf9fc 8587+
4a4d8108
AM
8588+/*
8589+ * How large will these lists be?
8590+ * Usually just a few elements, 20-30 at most for each, I guess.
8591+ */
8592+static struct au_splhead dynop[AuDyLast];
8593+
8594+static struct au_dykey *dy_gfind_get(struct au_splhead *spl, const void *h_op)
1facf9fc 8595+{
4a4d8108
AM
8596+ struct au_dykey *key, *tmp;
8597+ struct list_head *head;
1facf9fc 8598+
4a4d8108
AM
8599+ key = NULL;
8600+ head = &spl->head;
8601+ rcu_read_lock();
8602+ list_for_each_entry_rcu(tmp, head, dk_list)
8603+ if (tmp->dk_op.dy_hop == h_op) {
8604+ key = tmp;
8605+ kref_get(&key->dk_kref);
8606+ break;
8607+ }
8608+ rcu_read_unlock();
8609+
8610+ return key;
1facf9fc 8611+}
8612+
4a4d8108 8613+static struct au_dykey *dy_bradd(struct au_branch *br, struct au_dykey *key)
1facf9fc 8614+{
4a4d8108
AM
8615+ struct au_dykey **k, *found;
8616+ const void *h_op = key->dk_op.dy_hop;
8617+ int i;
1facf9fc 8618+
4a4d8108
AM
8619+ found = NULL;
8620+ k = br->br_dykey;
8621+ for (i = 0; i < AuBrDynOp; i++)
8622+ if (k[i]) {
8623+ if (k[i]->dk_op.dy_hop == h_op) {
8624+ found = k[i];
8625+ break;
8626+ }
8627+ } else
8628+ break;
8629+ if (!found) {
8630+ spin_lock(&br->br_dykey_lock);
8631+ for (; i < AuBrDynOp; i++)
8632+ if (k[i]) {
8633+ if (k[i]->dk_op.dy_hop == h_op) {
8634+ found = k[i];
8635+ break;
8636+ }
8637+ } else {
8638+ k[i] = key;
8639+ break;
8640+ }
8641+ spin_unlock(&br->br_dykey_lock);
8642+ BUG_ON(i == AuBrDynOp); /* expand the array */
8643+ }
8644+
8645+ return found;
1facf9fc 8646+}
8647+
4a4d8108
AM
8648+/* kref_get() if @key is already added */
8649+static struct au_dykey *dy_gadd(struct au_splhead *spl, struct au_dykey *key)
8650+{
8651+ struct au_dykey *tmp, *found;
8652+ struct list_head *head;
8653+ const void *h_op = key->dk_op.dy_hop;
1facf9fc 8654+
4a4d8108
AM
8655+ found = NULL;
8656+ head = &spl->head;
8657+ spin_lock(&spl->spin);
8658+ list_for_each_entry(tmp, head, dk_list)
8659+ if (tmp->dk_op.dy_hop == h_op) {
8660+ kref_get(&tmp->dk_kref);
8661+ found = tmp;
8662+ break;
8663+ }
8664+ if (!found)
8665+ list_add_rcu(&key->dk_list, head);
8666+ spin_unlock(&spl->spin);
1facf9fc 8667+
4a4d8108
AM
8668+ if (!found)
8669+ DyPrSym(key);
8670+ return found;
8671+}
8672+
8673+static void dy_free_rcu(struct rcu_head *rcu)
1facf9fc 8674+{
4a4d8108
AM
8675+ struct au_dykey *key;
8676+
8677+ key = container_of(rcu, struct au_dykey, dk_rcu);
8678+ DyPrSym(key);
8679+ kfree(key);
1facf9fc 8680+}
8681+
4a4d8108
AM
8682+static void dy_free(struct kref *kref)
8683+{
8684+ struct au_dykey *key;
8685+ struct au_splhead *spl;
1facf9fc 8686+
4a4d8108
AM
8687+ key = container_of(kref, struct au_dykey, dk_kref);
8688+ spl = dynop + key->dk_op.dy_type;
8689+ au_spl_del_rcu(&key->dk_list, spl);
8690+ call_rcu(&key->dk_rcu, dy_free_rcu);
8691+}
8692+
8693+void au_dy_put(struct au_dykey *key)
1facf9fc 8694+{
4a4d8108
AM
8695+ kref_put(&key->dk_kref, dy_free);
8696+}
1facf9fc 8697+
4a4d8108
AM
8698+/* ---------------------------------------------------------------------- */
8699+
8700+#define DyDbgSize(cnt, op) AuDebugOn(cnt != sizeof(op)/sizeof(void *))
8701+
8702+#ifdef CONFIG_AUFS_DEBUG
8703+#define DyDbgDeclare(cnt) unsigned int cnt = 0
4f0767ce 8704+#define DyDbgInc(cnt) do { cnt++; } while (0)
4a4d8108
AM
8705+#else
8706+#define DyDbgDeclare(cnt) do {} while (0)
8707+#define DyDbgInc(cnt) do {} while (0)
8708+#endif
8709+
8710+#define DySet(func, dst, src, h_op, h_sb) do { \
8711+ DyDbgInc(cnt); \
8712+ if (h_op->func) { \
8713+ if (src.func) \
8714+ dst.func = src.func; \
8715+ else \
8716+ AuDbg("%s %s\n", au_sbtype(h_sb), #func); \
8717+ } \
8718+} while (0)
8719+
8720+#define DySetForce(func, dst, src) do { \
8721+ AuDebugOn(!src.func); \
8722+ DyDbgInc(cnt); \
8723+ dst.func = src.func; \
8724+} while (0)
8725+
8726+#define DySetAop(func) \
8727+ DySet(func, dyaop->da_op, aufs_aop, h_aop, h_sb)
8728+#define DySetAopForce(func) \
8729+ DySetForce(func, dyaop->da_op, aufs_aop)
8730+
8731+static void dy_aop(struct au_dykey *key, const void *h_op,
8732+ struct super_block *h_sb __maybe_unused)
8733+{
8734+ struct au_dyaop *dyaop = (void *)key;
8735+ const struct address_space_operations *h_aop = h_op;
8736+ DyDbgDeclare(cnt);
8737+
8738+ AuDbg("%s\n", au_sbtype(h_sb));
8739+
8740+ DySetAop(writepage);
8741+ DySetAopForce(readpage); /* force */
4a4d8108
AM
8742+ DySetAop(writepages);
8743+ DySetAop(set_page_dirty);
8744+ DySetAop(readpages);
8745+ DySetAop(write_begin);
8746+ DySetAop(write_end);
8747+ DySetAop(bmap);
8748+ DySetAop(invalidatepage);
8749+ DySetAop(releasepage);
027c5e7a 8750+ DySetAop(freepage);
4a4d8108
AM
8751+ /* these two will be changed according to an aufs mount option */
8752+ DySetAop(direct_IO);
8753+ DySetAop(get_xip_mem);
8754+ DySetAop(migratepage);
8755+ DySetAop(launder_page);
8756+ DySetAop(is_partially_uptodate);
8757+ DySetAop(error_remove_page);
b4510431
AM
8758+ DySetAop(swap_activate);
8759+ DySetAop(swap_deactivate);
4a4d8108
AM
8760+
8761+ DyDbgSize(cnt, *h_aop);
8762+ dyaop->da_get_xip_mem = h_aop->get_xip_mem;
8763+}
8764+
4a4d8108
AM
8765+/* ---------------------------------------------------------------------- */
8766+
8767+static void dy_bug(struct kref *kref)
8768+{
8769+ BUG();
8770+}
8771+
8772+static struct au_dykey *dy_get(struct au_dynop *op, struct au_branch *br)
8773+{
8774+ struct au_dykey *key, *old;
8775+ struct au_splhead *spl;
b752ccd1 8776+ struct op {
4a4d8108 8777+ unsigned int sz;
b752ccd1
AM
8778+ void (*set)(struct au_dykey *key, const void *h_op,
8779+ struct super_block *h_sb __maybe_unused);
8780+ };
8781+ static const struct op a[] = {
4a4d8108
AM
8782+ [AuDy_AOP] = {
8783+ .sz = sizeof(struct au_dyaop),
b752ccd1 8784+ .set = dy_aop
4a4d8108 8785+ }
b752ccd1
AM
8786+ };
8787+ const struct op *p;
4a4d8108
AM
8788+
8789+ spl = dynop + op->dy_type;
8790+ key = dy_gfind_get(spl, op->dy_hop);
8791+ if (key)
8792+ goto out_add; /* success */
8793+
8794+ p = a + op->dy_type;
8795+ key = kzalloc(p->sz, GFP_NOFS);
8796+ if (unlikely(!key)) {
8797+ key = ERR_PTR(-ENOMEM);
8798+ goto out;
8799+ }
8800+
8801+ key->dk_op.dy_hop = op->dy_hop;
8802+ kref_init(&key->dk_kref);
b752ccd1 8803+ p->set(key, op->dy_hop, br->br_mnt->mnt_sb);
4a4d8108
AM
8804+ old = dy_gadd(spl, key);
8805+ if (old) {
8806+ kfree(key);
8807+ key = old;
8808+ }
8809+
8810+out_add:
8811+ old = dy_bradd(br, key);
8812+ if (old)
8813+ /* its ref-count should never be zero here */
8814+ kref_put(&key->dk_kref, dy_bug);
8815+out:
8816+ return key;
8817+}
8818+
8819+/* ---------------------------------------------------------------------- */
8820+/*
8821+ * Aufs prohibits O_DIRECT by defaut even if the branch supports it.
8822+ * This behaviour is neccessary to return an error from open(O_DIRECT) instead
8823+ * of the succeeding I/O. The dio mount option enables O_DIRECT and makes
8824+ * open(O_DIRECT) always succeed, but the succeeding I/O may return an error.
8825+ * See the aufs manual in detail.
8826+ *
8827+ * To keep this behaviour, aufs has to set NULL to ->get_xip_mem too, and the
8828+ * performance of fadvise() and madvise() may be affected.
8829+ */
8830+static void dy_adx(struct au_dyaop *dyaop, int do_dx)
8831+{
8832+ if (!do_dx) {
8833+ dyaop->da_op.direct_IO = NULL;
8834+ dyaop->da_op.get_xip_mem = NULL;
8835+ } else {
8836+ dyaop->da_op.direct_IO = aufs_aop.direct_IO;
8837+ dyaop->da_op.get_xip_mem = aufs_aop.get_xip_mem;
8838+ if (!dyaop->da_get_xip_mem)
8839+ dyaop->da_op.get_xip_mem = NULL;
8840+ }
8841+}
8842+
8843+static struct au_dyaop *dy_aget(struct au_branch *br,
8844+ const struct address_space_operations *h_aop,
8845+ int do_dx)
8846+{
8847+ struct au_dyaop *dyaop;
8848+ struct au_dynop op;
8849+
8850+ op.dy_type = AuDy_AOP;
8851+ op.dy_haop = h_aop;
8852+ dyaop = (void *)dy_get(&op, br);
8853+ if (IS_ERR(dyaop))
8854+ goto out;
8855+ dy_adx(dyaop, do_dx);
8856+
8857+out:
8858+ return dyaop;
8859+}
8860+
8861+int au_dy_iaop(struct inode *inode, aufs_bindex_t bindex,
8862+ struct inode *h_inode)
8863+{
8864+ int err, do_dx;
8865+ struct super_block *sb;
8866+ struct au_branch *br;
8867+ struct au_dyaop *dyaop;
8868+
8869+ AuDebugOn(!S_ISREG(h_inode->i_mode));
8870+ IiMustWriteLock(inode);
8871+
8872+ sb = inode->i_sb;
8873+ br = au_sbr(sb, bindex);
8874+ do_dx = !!au_opt_test(au_mntflags(sb), DIO);
8875+ dyaop = dy_aget(br, h_inode->i_mapping->a_ops, do_dx);
8876+ err = PTR_ERR(dyaop);
8877+ if (IS_ERR(dyaop))
8878+ /* unnecessary to call dy_fput() */
8879+ goto out;
8880+
8881+ err = 0;
8882+ inode->i_mapping->a_ops = &dyaop->da_op;
8883+
8884+out:
8885+ return err;
8886+}
8887+
b752ccd1
AM
8888+/*
8889+ * Is it safe to replace a_ops during the inode/file is in operation?
8890+ * Yes, I hope so.
8891+ */
8892+int au_dy_irefresh(struct inode *inode)
8893+{
8894+ int err;
8895+ aufs_bindex_t bstart;
8896+ struct inode *h_inode;
8897+
8898+ err = 0;
8899+ if (S_ISREG(inode->i_mode)) {
8900+ bstart = au_ibstart(inode);
8901+ h_inode = au_h_iptr(inode, bstart);
8902+ err = au_dy_iaop(inode, bstart, h_inode);
8903+ }
8904+ return err;
8905+}
8906+
4a4d8108
AM
8907+void au_dy_arefresh(int do_dx)
8908+{
8909+ struct au_splhead *spl;
8910+ struct list_head *head;
8911+ struct au_dykey *key;
8912+
8913+ spl = dynop + AuDy_AOP;
8914+ head = &spl->head;
8915+ spin_lock(&spl->spin);
8916+ list_for_each_entry(key, head, dk_list)
8917+ dy_adx((void *)key, do_dx);
8918+ spin_unlock(&spl->spin);
8919+}
8920+
4a4d8108
AM
8921+/* ---------------------------------------------------------------------- */
8922+
8923+void __init au_dy_init(void)
8924+{
8925+ int i;
8926+
8927+ /* make sure that 'struct au_dykey *' can be any type */
8928+ BUILD_BUG_ON(offsetof(struct au_dyaop, da_key));
4a4d8108
AM
8929+
8930+ for (i = 0; i < AuDyLast; i++)
8931+ au_spl_init(dynop + i);
8932+}
8933+
8934+void au_dy_fin(void)
8935+{
8936+ int i;
8937+
8938+ for (i = 0; i < AuDyLast; i++)
8939+ WARN_ON(!list_empty(&dynop[i].head));
8940+}
7f207e10
AM
8941diff -urN /usr/share/empty/fs/aufs/dynop.h linux/fs/aufs/dynop.h
8942--- /usr/share/empty/fs/aufs/dynop.h 1970-01-01 01:00:00.000000000 +0100
2dfbb274 8943+++ linux/fs/aufs/dynop.h 2012-08-26 08:39:00.760508065 +0200
f6c5ef8b 8944@@ -0,0 +1,76 @@
4a4d8108 8945+/*
f6c5ef8b 8946+ * Copyright (C) 2010-2012 Junjiro R. Okajima
4a4d8108
AM
8947+ *
8948+ * This program, aufs is free software; you can redistribute it and/or modify
8949+ * it under the terms of the GNU General Public License as published by
8950+ * the Free Software Foundation; either version 2 of the License, or
8951+ * (at your option) any later version.
8952+ *
8953+ * This program is distributed in the hope that it will be useful,
8954+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
8955+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
8956+ * GNU General Public License for more details.
8957+ *
8958+ * You should have received a copy of the GNU General Public License
8959+ * along with this program; if not, write to the Free Software
8960+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
8961+ */
8962+
8963+/*
8964+ * dynamically customizable operations (for regular files only)
8965+ */
8966+
8967+#ifndef __AUFS_DYNOP_H__
8968+#define __AUFS_DYNOP_H__
8969+
8970+#ifdef __KERNEL__
8971+
4a4d8108
AM
8972+#include "inode.h"
8973+
2cbb1c4b 8974+enum {AuDy_AOP, AuDyLast};
4a4d8108
AM
8975+
8976+struct au_dynop {
8977+ int dy_type;
8978+ union {
8979+ const void *dy_hop;
8980+ const struct address_space_operations *dy_haop;
4a4d8108
AM
8981+ };
8982+};
8983+
8984+struct au_dykey {
8985+ union {
8986+ struct list_head dk_list;
8987+ struct rcu_head dk_rcu;
8988+ };
8989+ struct au_dynop dk_op;
8990+
8991+ /*
8992+ * during I am in the branch local array, kref is gotten. when the
8993+ * branch is removed, kref is put.
8994+ */
8995+ struct kref dk_kref;
8996+};
8997+
8998+/* stop unioning since their sizes are very different from each other */
8999+struct au_dyaop {
9000+ struct au_dykey da_key;
9001+ struct address_space_operations da_op; /* not const */
9002+ int (*da_get_xip_mem)(struct address_space *, pgoff_t, int,
9003+ void **, unsigned long *);
9004+};
9005+
4a4d8108
AM
9006+/* ---------------------------------------------------------------------- */
9007+
9008+/* dynop.c */
9009+struct au_branch;
9010+void au_dy_put(struct au_dykey *key);
9011+int au_dy_iaop(struct inode *inode, aufs_bindex_t bindex,
9012+ struct inode *h_inode);
b752ccd1 9013+int au_dy_irefresh(struct inode *inode);
4a4d8108 9014+void au_dy_arefresh(int do_dio);
4a4d8108
AM
9015+
9016+void __init au_dy_init(void);
9017+void au_dy_fin(void);
9018+
4a4d8108
AM
9019+#endif /* __KERNEL__ */
9020+#endif /* __AUFS_DYNOP_H__ */
7f207e10
AM
9021diff -urN /usr/share/empty/fs/aufs/export.c linux/fs/aufs/export.c
9022--- /usr/share/empty/fs/aufs/export.c 1970-01-01 01:00:00.000000000 +0100
b4510431
AM
9023+++ linux/fs/aufs/export.c 2012-10-17 10:31:01.772481151 +0200
9024@@ -0,0 +1,811 @@
4a4d8108 9025+/*
f6c5ef8b 9026+ * Copyright (C) 2005-2012 Junjiro R. Okajima
4a4d8108
AM
9027+ *
9028+ * This program, aufs is free software; you can redistribute it and/or modify
9029+ * it under the terms of the GNU General Public License as published by
9030+ * the Free Software Foundation; either version 2 of the License, or
9031+ * (at your option) any later version.
9032+ *
9033+ * This program is distributed in the hope that it will be useful,
9034+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
9035+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
9036+ * GNU General Public License for more details.
9037+ *
9038+ * You should have received a copy of the GNU General Public License
9039+ * along with this program; if not, write to the Free Software
9040+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
9041+ */
9042+
9043+/*
9044+ * export via nfs
9045+ */
9046+
9047+#include <linux/exportfs.h>
7eafdf33 9048+#include <linux/fs_struct.h>
4a4d8108
AM
9049+#include <linux/namei.h>
9050+#include <linux/nsproxy.h>
9051+#include <linux/random.h>
9052+#include <linux/writeback.h>
7eafdf33 9053+#include "../fs/mount.h"
4a4d8108
AM
9054+#include "aufs.h"
9055+
9056+union conv {
9057+#ifdef CONFIG_AUFS_INO_T_64
9058+ __u32 a[2];
9059+#else
9060+ __u32 a[1];
9061+#endif
9062+ ino_t ino;
9063+};
9064+
9065+static ino_t decode_ino(__u32 *a)
9066+{
9067+ union conv u;
9068+
9069+ BUILD_BUG_ON(sizeof(u.ino) != sizeof(u.a));
9070+ u.a[0] = a[0];
9071+#ifdef CONFIG_AUFS_INO_T_64
9072+ u.a[1] = a[1];
9073+#endif
9074+ return u.ino;
9075+}
9076+
9077+static void encode_ino(__u32 *a, ino_t ino)
9078+{
9079+ union conv u;
9080+
9081+ u.ino = ino;
9082+ a[0] = u.a[0];
9083+#ifdef CONFIG_AUFS_INO_T_64
9084+ a[1] = u.a[1];
9085+#endif
9086+}
9087+
9088+/* NFS file handle */
9089+enum {
9090+ Fh_br_id,
9091+ Fh_sigen,
9092+#ifdef CONFIG_AUFS_INO_T_64
9093+ /* support 64bit inode number */
9094+ Fh_ino1,
9095+ Fh_ino2,
9096+ Fh_dir_ino1,
9097+ Fh_dir_ino2,
9098+#else
9099+ Fh_ino1,
9100+ Fh_dir_ino1,
9101+#endif
9102+ Fh_igen,
9103+ Fh_h_type,
9104+ Fh_tail,
9105+
9106+ Fh_ino = Fh_ino1,
9107+ Fh_dir_ino = Fh_dir_ino1
9108+};
9109+
9110+static int au_test_anon(struct dentry *dentry)
9111+{
027c5e7a 9112+ /* note: read d_flags without d_lock */
4a4d8108
AM
9113+ return !!(dentry->d_flags & DCACHE_DISCONNECTED);
9114+}
9115+
9116+/* ---------------------------------------------------------------------- */
9117+/* inode generation external table */
9118+
b752ccd1 9119+void au_xigen_inc(struct inode *inode)
4a4d8108 9120+{
4a4d8108
AM
9121+ loff_t pos;
9122+ ssize_t sz;
9123+ __u32 igen;
9124+ struct super_block *sb;
9125+ struct au_sbinfo *sbinfo;
9126+
4a4d8108 9127+ sb = inode->i_sb;
b752ccd1 9128+ AuDebugOn(!au_opt_test(au_mntflags(sb), XINO));
1facf9fc 9129+
b752ccd1 9130+ sbinfo = au_sbi(sb);
1facf9fc 9131+ pos = inode->i_ino;
9132+ pos *= sizeof(igen);
9133+ igen = inode->i_generation + 1;
1facf9fc 9134+ sz = xino_fwrite(sbinfo->si_xwrite, sbinfo->si_xigen, &igen,
9135+ sizeof(igen), &pos);
9136+ if (sz == sizeof(igen))
b752ccd1 9137+ return; /* success */
1facf9fc 9138+
b752ccd1 9139+ if (unlikely(sz >= 0))
1facf9fc 9140+ AuIOErr("xigen error (%zd)\n", sz);
1facf9fc 9141+}
9142+
9143+int au_xigen_new(struct inode *inode)
9144+{
9145+ int err;
9146+ loff_t pos;
9147+ ssize_t sz;
9148+ struct super_block *sb;
9149+ struct au_sbinfo *sbinfo;
9150+ struct file *file;
9151+
9152+ err = 0;
9153+ /* todo: dirty, at mount time */
9154+ if (inode->i_ino == AUFS_ROOT_INO)
9155+ goto out;
9156+ sb = inode->i_sb;
dece6358 9157+ SiMustAnyLock(sb);
1facf9fc 9158+ if (unlikely(!au_opt_test(au_mntflags(sb), XINO)))
9159+ goto out;
9160+
9161+ err = -EFBIG;
9162+ pos = inode->i_ino;
9163+ if (unlikely(au_loff_max / sizeof(inode->i_generation) - 1 < pos)) {
9164+ AuIOErr1("too large i%lld\n", pos);
9165+ goto out;
9166+ }
9167+ pos *= sizeof(inode->i_generation);
9168+
9169+ err = 0;
9170+ sbinfo = au_sbi(sb);
9171+ file = sbinfo->si_xigen;
9172+ BUG_ON(!file);
9173+
9174+ if (i_size_read(file->f_dentry->d_inode)
9175+ < pos + sizeof(inode->i_generation)) {
9176+ inode->i_generation = atomic_inc_return(&sbinfo->si_xigen_next);
9177+ sz = xino_fwrite(sbinfo->si_xwrite, file, &inode->i_generation,
9178+ sizeof(inode->i_generation), &pos);
9179+ } else
9180+ sz = xino_fread(sbinfo->si_xread, file, &inode->i_generation,
9181+ sizeof(inode->i_generation), &pos);
9182+ if (sz == sizeof(inode->i_generation))
9183+ goto out; /* success */
9184+
9185+ err = sz;
9186+ if (unlikely(sz >= 0)) {
9187+ err = -EIO;
9188+ AuIOErr("xigen error (%zd)\n", sz);
9189+ }
9190+
4f0767ce 9191+out:
1facf9fc 9192+ return err;
9193+}
9194+
9195+int au_xigen_set(struct super_block *sb, struct file *base)
9196+{
9197+ int err;
9198+ struct au_sbinfo *sbinfo;
9199+ struct file *file;
9200+
dece6358
AM
9201+ SiMustWriteLock(sb);
9202+
1facf9fc 9203+ sbinfo = au_sbi(sb);
9204+ file = au_xino_create2(base, sbinfo->si_xigen);
9205+ err = PTR_ERR(file);
9206+ if (IS_ERR(file))
9207+ goto out;
9208+ err = 0;
9209+ if (sbinfo->si_xigen)
9210+ fput(sbinfo->si_xigen);
9211+ sbinfo->si_xigen = file;
9212+
4f0767ce 9213+out:
1facf9fc 9214+ return err;
9215+}
9216+
9217+void au_xigen_clr(struct super_block *sb)
9218+{
9219+ struct au_sbinfo *sbinfo;
9220+
dece6358
AM
9221+ SiMustWriteLock(sb);
9222+
1facf9fc 9223+ sbinfo = au_sbi(sb);
9224+ if (sbinfo->si_xigen) {
9225+ fput(sbinfo->si_xigen);
9226+ sbinfo->si_xigen = NULL;
9227+ }
9228+}
9229+
9230+/* ---------------------------------------------------------------------- */
9231+
9232+static struct dentry *decode_by_ino(struct super_block *sb, ino_t ino,
9233+ ino_t dir_ino)
9234+{
9235+ struct dentry *dentry, *d;
9236+ struct inode *inode;
9237+ unsigned int sigen;
b4510431 9238+ struct hlist_node *p;
1facf9fc 9239+
9240+ dentry = NULL;
9241+ inode = ilookup(sb, ino);
9242+ if (!inode)
9243+ goto out;
9244+
9245+ dentry = ERR_PTR(-ESTALE);
9246+ sigen = au_sigen(sb);
9247+ if (unlikely(is_bad_inode(inode)
9248+ || IS_DEADDIR(inode)
9249+ || sigen != au_iigen(inode)))
9250+ goto out_iput;
9251+
9252+ dentry = NULL;
9253+ if (!dir_ino || S_ISDIR(inode->i_mode))
9254+ dentry = d_find_alias(inode);
9255+ else {
027c5e7a 9256+ spin_lock(&inode->i_lock);
b4510431 9257+ hlist_for_each_entry(d, p, &inode->i_dentry, d_alias) {
027c5e7a 9258+ spin_lock(&d->d_lock);
1facf9fc 9259+ if (!au_test_anon(d)
9260+ && d->d_parent->d_inode->i_ino == dir_ino) {
027c5e7a
AM
9261+ dentry = dget_dlock(d);
9262+ spin_unlock(&d->d_lock);
1facf9fc 9263+ break;
9264+ }
027c5e7a
AM
9265+ spin_unlock(&d->d_lock);
9266+ }
9267+ spin_unlock(&inode->i_lock);
1facf9fc 9268+ }
027c5e7a 9269+ if (unlikely(dentry && au_digen_test(dentry, sigen))) {
2cbb1c4b 9270+ /* need to refresh */
1facf9fc 9271+ dput(dentry);
2cbb1c4b 9272+ dentry = NULL;
1facf9fc 9273+ }
9274+
4f0767ce 9275+out_iput:
1facf9fc 9276+ iput(inode);
4f0767ce 9277+out:
2cbb1c4b 9278+ AuTraceErrPtr(dentry);
1facf9fc 9279+ return dentry;
9280+}
9281+
9282+/* ---------------------------------------------------------------------- */
9283+
9284+/* todo: dirty? */
9285+/* if exportfs_decode_fh() passed vfsmount*, we could be happy */
4a4d8108
AM
9286+
9287+struct au_compare_mnt_args {
9288+ /* input */
9289+ struct super_block *sb;
9290+
9291+ /* output */
9292+ struct vfsmount *mnt;
9293+};
9294+
9295+static int au_compare_mnt(struct vfsmount *mnt, void *arg)
9296+{
9297+ struct au_compare_mnt_args *a = arg;
9298+
9299+ if (mnt->mnt_sb != a->sb)
9300+ return 0;
9301+ a->mnt = mntget(mnt);
9302+ return 1;
9303+}
9304+
1facf9fc 9305+static struct vfsmount *au_mnt_get(struct super_block *sb)
9306+{
4a4d8108 9307+ int err;
7eafdf33 9308+ struct path root;
4a4d8108
AM
9309+ struct au_compare_mnt_args args = {
9310+ .sb = sb
9311+ };
1facf9fc 9312+
7eafdf33 9313+ get_fs_root(current->fs, &root);
0c3ec466 9314+ br_read_lock(&vfsmount_lock);
7eafdf33 9315+ err = iterate_mounts(au_compare_mnt, &args, root.mnt);
0c3ec466 9316+ br_read_unlock(&vfsmount_lock);
7eafdf33 9317+ path_put(&root);
4a4d8108
AM
9318+ AuDebugOn(!err);
9319+ AuDebugOn(!args.mnt);
9320+ return args.mnt;
1facf9fc 9321+}
9322+
9323+struct au_nfsd_si_lock {
4a4d8108 9324+ unsigned int sigen;
027c5e7a 9325+ aufs_bindex_t bindex, br_id;
1facf9fc 9326+ unsigned char force_lock;
9327+};
9328+
027c5e7a
AM
9329+static int si_nfsd_read_lock(struct super_block *sb,
9330+ struct au_nfsd_si_lock *nsi_lock)
1facf9fc 9331+{
027c5e7a 9332+ int err;
1facf9fc 9333+ aufs_bindex_t bindex;
9334+
9335+ si_read_lock(sb, AuLock_FLUSH);
9336+
9337+ /* branch id may be wrapped around */
027c5e7a 9338+ err = 0;
1facf9fc 9339+ bindex = au_br_index(sb, nsi_lock->br_id);
9340+ if (bindex >= 0 && nsi_lock->sigen + AUFS_BRANCH_MAX > au_sigen(sb))
9341+ goto out; /* success */
9342+
027c5e7a
AM
9343+ err = -ESTALE;
9344+ bindex = -1;
1facf9fc 9345+ if (!nsi_lock->force_lock)
9346+ si_read_unlock(sb);
1facf9fc 9347+
4f0767ce 9348+out:
027c5e7a
AM
9349+ nsi_lock->bindex = bindex;
9350+ return err;
1facf9fc 9351+}
9352+
9353+struct find_name_by_ino {
9354+ int called, found;
9355+ ino_t ino;
9356+ char *name;
9357+ int namelen;
9358+};
9359+
9360+static int
9361+find_name_by_ino(void *arg, const char *name, int namelen, loff_t offset,
9362+ u64 ino, unsigned int d_type)
9363+{
9364+ struct find_name_by_ino *a = arg;
9365+
9366+ a->called++;
9367+ if (a->ino != ino)
9368+ return 0;
9369+
9370+ memcpy(a->name, name, namelen);
9371+ a->namelen = namelen;
9372+ a->found = 1;
9373+ return 1;
9374+}
9375+
9376+static struct dentry *au_lkup_by_ino(struct path *path, ino_t ino,
9377+ struct au_nfsd_si_lock *nsi_lock)
9378+{
9379+ struct dentry *dentry, *parent;
9380+ struct file *file;
9381+ struct inode *dir;
9382+ struct find_name_by_ino arg;
9383+ int err;
9384+
9385+ parent = path->dentry;
9386+ if (nsi_lock)
9387+ si_read_unlock(parent->d_sb);
4a4d8108 9388+ file = vfsub_dentry_open(path, au_dir_roflags);
1facf9fc 9389+ dentry = (void *)file;
9390+ if (IS_ERR(file))
9391+ goto out;
9392+
9393+ dentry = ERR_PTR(-ENOMEM);
4a4d8108 9394+ arg.name = __getname_gfp(GFP_NOFS);
1facf9fc 9395+ if (unlikely(!arg.name))
9396+ goto out_file;
9397+ arg.ino = ino;
9398+ arg.found = 0;
9399+ do {
9400+ arg.called = 0;
9401+ /* smp_mb(); */
9402+ err = vfsub_readdir(file, find_name_by_ino, &arg);
9403+ } while (!err && !arg.found && arg.called);
9404+ dentry = ERR_PTR(err);
9405+ if (unlikely(err))
9406+ goto out_name;
9407+ dentry = ERR_PTR(-ENOENT);
9408+ if (!arg.found)
9409+ goto out_name;
9410+
b4510431 9411+ /* do not call vfsub_lkup_one() */
1facf9fc 9412+ dir = parent->d_inode;
9413+ mutex_lock(&dir->i_mutex);
9414+ dentry = vfsub_lookup_one_len(arg.name, parent, arg.namelen);
9415+ mutex_unlock(&dir->i_mutex);
9416+ AuTraceErrPtr(dentry);
9417+ if (IS_ERR(dentry))
9418+ goto out_name;
9419+ AuDebugOn(au_test_anon(dentry));
9420+ if (unlikely(!dentry->d_inode)) {
9421+ dput(dentry);
9422+ dentry = ERR_PTR(-ENOENT);
9423+ }
9424+
4f0767ce 9425+out_name:
1facf9fc 9426+ __putname(arg.name);
4f0767ce 9427+out_file:
1facf9fc 9428+ fput(file);
4f0767ce 9429+out:
1facf9fc 9430+ if (unlikely(nsi_lock
9431+ && si_nfsd_read_lock(parent->d_sb, nsi_lock) < 0))
9432+ if (!IS_ERR(dentry)) {
9433+ dput(dentry);
9434+ dentry = ERR_PTR(-ESTALE);
9435+ }
9436+ AuTraceErrPtr(dentry);
9437+ return dentry;
9438+}
9439+
9440+static struct dentry *decode_by_dir_ino(struct super_block *sb, ino_t ino,
9441+ ino_t dir_ino,
9442+ struct au_nfsd_si_lock *nsi_lock)
9443+{
9444+ struct dentry *dentry;
9445+ struct path path;
9446+
9447+ if (dir_ino != AUFS_ROOT_INO) {
9448+ path.dentry = decode_by_ino(sb, dir_ino, 0);
9449+ dentry = path.dentry;
9450+ if (!path.dentry || IS_ERR(path.dentry))
9451+ goto out;
9452+ AuDebugOn(au_test_anon(path.dentry));
9453+ } else
9454+ path.dentry = dget(sb->s_root);
9455+
9456+ path.mnt = au_mnt_get(sb);
9457+ dentry = au_lkup_by_ino(&path, ino, nsi_lock);
9458+ path_put(&path);
9459+
4f0767ce 9460+out:
1facf9fc 9461+ AuTraceErrPtr(dentry);
9462+ return dentry;
9463+}
9464+
9465+/* ---------------------------------------------------------------------- */
9466+
9467+static int h_acceptable(void *expv, struct dentry *dentry)
9468+{
9469+ return 1;
9470+}
9471+
9472+static char *au_build_path(struct dentry *h_parent, struct path *h_rootpath,
9473+ char *buf, int len, struct super_block *sb)
9474+{
9475+ char *p;
9476+ int n;
9477+ struct path path;
9478+
9479+ p = d_path(h_rootpath, buf, len);
9480+ if (IS_ERR(p))
9481+ goto out;
9482+ n = strlen(p);
9483+
9484+ path.mnt = h_rootpath->mnt;
9485+ path.dentry = h_parent;
9486+ p = d_path(&path, buf, len);
9487+ if (IS_ERR(p))
9488+ goto out;
9489+ if (n != 1)
9490+ p += n;
9491+
9492+ path.mnt = au_mnt_get(sb);
9493+ path.dentry = sb->s_root;
9494+ p = d_path(&path, buf, len - strlen(p));
9495+ mntput(path.mnt);
9496+ if (IS_ERR(p))
9497+ goto out;
9498+ if (n != 1)
9499+ p[strlen(p)] = '/';
9500+
4f0767ce 9501+out:
1facf9fc 9502+ AuTraceErrPtr(p);
9503+ return p;
9504+}
9505+
9506+static
027c5e7a
AM
9507+struct dentry *decode_by_path(struct super_block *sb, ino_t ino, __u32 *fh,
9508+ int fh_len, struct au_nfsd_si_lock *nsi_lock)
1facf9fc 9509+{
9510+ struct dentry *dentry, *h_parent, *root;
9511+ struct super_block *h_sb;
9512+ char *pathname, *p;
9513+ struct vfsmount *h_mnt;
9514+ struct au_branch *br;
9515+ int err;
9516+ struct path path;
9517+
027c5e7a 9518+ br = au_sbr(sb, nsi_lock->bindex);
1facf9fc 9519+ h_mnt = br->br_mnt;
9520+ h_sb = h_mnt->mnt_sb;
9521+ /* todo: call lower fh_to_dentry()? fh_to_parent()? */
9522+ h_parent = exportfs_decode_fh(h_mnt, (void *)(fh + Fh_tail),
9523+ fh_len - Fh_tail, fh[Fh_h_type],
9524+ h_acceptable, /*context*/NULL);
9525+ dentry = h_parent;
9526+ if (unlikely(!h_parent || IS_ERR(h_parent))) {
9527+ AuWarn1("%s decode_fh failed, %ld\n",
9528+ au_sbtype(h_sb), PTR_ERR(h_parent));
9529+ goto out;
9530+ }
9531+ dentry = NULL;
9532+ if (unlikely(au_test_anon(h_parent))) {
9533+ AuWarn1("%s decode_fh returned a disconnected dentry\n",
9534+ au_sbtype(h_sb));
9535+ goto out_h_parent;
9536+ }
9537+
9538+ dentry = ERR_PTR(-ENOMEM);
9539+ pathname = (void *)__get_free_page(GFP_NOFS);
9540+ if (unlikely(!pathname))
9541+ goto out_h_parent;
9542+
9543+ root = sb->s_root;
9544+ path.mnt = h_mnt;
9545+ di_read_lock_parent(root, !AuLock_IR);
027c5e7a 9546+ path.dentry = au_h_dptr(root, nsi_lock->bindex);
1facf9fc 9547+ di_read_unlock(root, !AuLock_IR);
9548+ p = au_build_path(h_parent, &path, pathname, PAGE_SIZE, sb);
9549+ dentry = (void *)p;
9550+ if (IS_ERR(p))
9551+ goto out_pathname;
9552+
9553+ si_read_unlock(sb);
9554+ err = vfsub_kern_path(p, LOOKUP_FOLLOW | LOOKUP_DIRECTORY, &path);
9555+ dentry = ERR_PTR(err);
9556+ if (unlikely(err))
9557+ goto out_relock;
9558+
9559+ dentry = ERR_PTR(-ENOENT);
9560+ AuDebugOn(au_test_anon(path.dentry));
9561+ if (unlikely(!path.dentry->d_inode))
9562+ goto out_path;
9563+
9564+ if (ino != path.dentry->d_inode->i_ino)
9565+ dentry = au_lkup_by_ino(&path, ino, /*nsi_lock*/NULL);
9566+ else
9567+ dentry = dget(path.dentry);
9568+
4f0767ce 9569+out_path:
1facf9fc 9570+ path_put(&path);
4f0767ce 9571+out_relock:
1facf9fc 9572+ if (unlikely(si_nfsd_read_lock(sb, nsi_lock) < 0))
9573+ if (!IS_ERR(dentry)) {
9574+ dput(dentry);
9575+ dentry = ERR_PTR(-ESTALE);
9576+ }
4f0767ce 9577+out_pathname:
1facf9fc 9578+ free_page((unsigned long)pathname);
4f0767ce 9579+out_h_parent:
1facf9fc 9580+ dput(h_parent);
4f0767ce 9581+out:
1facf9fc 9582+ AuTraceErrPtr(dentry);
9583+ return dentry;
9584+}
9585+
9586+/* ---------------------------------------------------------------------- */
9587+
9588+static struct dentry *
9589+aufs_fh_to_dentry(struct super_block *sb, struct fid *fid, int fh_len,
9590+ int fh_type)
9591+{
9592+ struct dentry *dentry;
9593+ __u32 *fh = fid->raw;
027c5e7a 9594+ struct au_branch *br;
1facf9fc 9595+ ino_t ino, dir_ino;
1facf9fc 9596+ struct au_nfsd_si_lock nsi_lock = {
1facf9fc 9597+ .force_lock = 0
9598+ };
9599+
1facf9fc 9600+ dentry = ERR_PTR(-ESTALE);
4a4d8108
AM
9601+ /* it should never happen, but the file handle is unreliable */
9602+ if (unlikely(fh_len < Fh_tail))
9603+ goto out;
9604+ nsi_lock.sigen = fh[Fh_sigen];
9605+ nsi_lock.br_id = fh[Fh_br_id];
9606+
1facf9fc 9607+ /* branch id may be wrapped around */
027c5e7a
AM
9608+ br = NULL;
9609+ if (unlikely(si_nfsd_read_lock(sb, &nsi_lock)))
1facf9fc 9610+ goto out;
9611+ nsi_lock.force_lock = 1;
9612+
9613+ /* is this inode still cached? */
9614+ ino = decode_ino(fh + Fh_ino);
4a4d8108
AM
9615+ /* it should never happen */
9616+ if (unlikely(ino == AUFS_ROOT_INO))
9617+ goto out;
9618+
1facf9fc 9619+ dir_ino = decode_ino(fh + Fh_dir_ino);
9620+ dentry = decode_by_ino(sb, ino, dir_ino);
9621+ if (IS_ERR(dentry))
9622+ goto out_unlock;
9623+ if (dentry)
9624+ goto accept;
9625+
9626+ /* is the parent dir cached? */
027c5e7a
AM
9627+ br = au_sbr(sb, nsi_lock.bindex);
9628+ atomic_inc(&br->br_count);
1facf9fc 9629+ dentry = decode_by_dir_ino(sb, ino, dir_ino, &nsi_lock);
9630+ if (IS_ERR(dentry))
9631+ goto out_unlock;
9632+ if (dentry)
9633+ goto accept;
9634+
9635+ /* lookup path */
027c5e7a 9636+ dentry = decode_by_path(sb, ino, fh, fh_len, &nsi_lock);
1facf9fc 9637+ if (IS_ERR(dentry))
9638+ goto out_unlock;
9639+ if (unlikely(!dentry))
9640+ /* todo?: make it ESTALE */
9641+ goto out_unlock;
9642+
4f0767ce 9643+accept:
027c5e7a
AM
9644+ if (!au_digen_test(dentry, au_sigen(sb))
9645+ && dentry->d_inode->i_generation == fh[Fh_igen])
1facf9fc 9646+ goto out_unlock; /* success */
9647+
9648+ dput(dentry);
9649+ dentry = ERR_PTR(-ESTALE);
4f0767ce 9650+out_unlock:
027c5e7a
AM
9651+ if (br)
9652+ atomic_dec(&br->br_count);
1facf9fc 9653+ si_read_unlock(sb);
4f0767ce 9654+out:
1facf9fc 9655+ AuTraceErrPtr(dentry);
9656+ return dentry;
9657+}
9658+
9659+#if 0 /* reserved for future use */
9660+/* support subtreecheck option */
9661+static struct dentry *aufs_fh_to_parent(struct super_block *sb, struct fid *fid,
9662+ int fh_len, int fh_type)
9663+{
9664+ struct dentry *parent;
9665+ __u32 *fh = fid->raw;
9666+ ino_t dir_ino;
9667+
9668+ dir_ino = decode_ino(fh + Fh_dir_ino);
9669+ parent = decode_by_ino(sb, dir_ino, 0);
9670+ if (IS_ERR(parent))
9671+ goto out;
9672+ if (!parent)
9673+ parent = decode_by_path(sb, au_br_index(sb, fh[Fh_br_id]),
9674+ dir_ino, fh, fh_len);
9675+
4f0767ce 9676+out:
1facf9fc 9677+ AuTraceErrPtr(parent);
9678+ return parent;
9679+}
9680+#endif
9681+
9682+/* ---------------------------------------------------------------------- */
9683+
0c3ec466
AM
9684+static int aufs_encode_fh(struct inode *inode, __u32 *fh, int *max_len,
9685+ struct inode *dir)
1facf9fc 9686+{
9687+ int err;
0c3ec466 9688+ aufs_bindex_t bindex;
1facf9fc 9689+ struct super_block *sb, *h_sb;
0c3ec466
AM
9690+ struct dentry *dentry, *parent, *h_parent;
9691+ struct inode *h_dir;
1facf9fc 9692+ struct au_branch *br;
9693+
1facf9fc 9694+ err = -ENOSPC;
9695+ if (unlikely(*max_len <= Fh_tail)) {
9696+ AuWarn1("NFSv2 client (max_len %d)?\n", *max_len);
9697+ goto out;
9698+ }
9699+
9700+ err = FILEID_ROOT;
0c3ec466
AM
9701+ if (inode->i_ino == AUFS_ROOT_INO) {
9702+ AuDebugOn(inode->i_ino != AUFS_ROOT_INO);
1facf9fc 9703+ goto out;
9704+ }
9705+
1facf9fc 9706+ h_parent = NULL;
0c3ec466
AM
9707+ sb = inode->i_sb;
9708+ err = si_read_lock(sb, AuLock_FLUSH);
027c5e7a
AM
9709+ if (unlikely(err))
9710+ goto out;
9711+
1facf9fc 9712+#ifdef CONFIG_AUFS_DEBUG
9713+ if (unlikely(!au_opt_test(au_mntflags(sb), XINO)))
9714+ AuWarn1("NFS-exporting requires xino\n");
9715+#endif
027c5e7a 9716+ err = -EIO;
0c3ec466
AM
9717+ parent = NULL;
9718+ ii_read_lock_child(inode);
9719+ bindex = au_ibstart(inode);
9720+ if (!dir) {
9721+ dentry = d_find_alias(inode);
9722+ if (unlikely(!dentry))
9723+ goto out_unlock;
9724+ AuDebugOn(au_test_anon(dentry));
9725+ parent = dget_parent(dentry);
9726+ dput(dentry);
9727+ if (unlikely(!parent))
9728+ goto out_unlock;
9729+ dir = parent->d_inode;
1facf9fc 9730+ }
0c3ec466
AM
9731+
9732+ ii_read_lock_parent(dir);
9733+ h_dir = au_h_iptr(dir, bindex);
9734+ ii_read_unlock(dir);
9735+ if (unlikely(!h_dir))
9736+ goto out_parent;
9737+ h_parent = d_find_alias(h_dir);
1facf9fc 9738+ if (unlikely(!h_parent))
0c3ec466 9739+ goto out_hparent;
1facf9fc 9740+
9741+ err = -EPERM;
9742+ br = au_sbr(sb, bindex);
9743+ h_sb = br->br_mnt->mnt_sb;
9744+ if (unlikely(!h_sb->s_export_op)) {
9745+ AuErr1("%s branch is not exportable\n", au_sbtype(h_sb));
0c3ec466 9746+ goto out_hparent;
1facf9fc 9747+ }
9748+
9749+ fh[Fh_br_id] = br->br_id;
9750+ fh[Fh_sigen] = au_sigen(sb);
9751+ encode_ino(fh + Fh_ino, inode->i_ino);
0c3ec466 9752+ encode_ino(fh + Fh_dir_ino, dir->i_ino);
1facf9fc 9753+ fh[Fh_igen] = inode->i_generation;
9754+
9755+ *max_len -= Fh_tail;
9756+ fh[Fh_h_type] = exportfs_encode_fh(h_parent, (void *)(fh + Fh_tail),
9757+ max_len,
9758+ /*connectable or subtreecheck*/0);
9759+ err = fh[Fh_h_type];
9760+ *max_len += Fh_tail;
9761+ /* todo: macros? */
9762+ if (err != 255)
9763+ err = 99;
9764+ else
9765+ AuWarn1("%s encode_fh failed\n", au_sbtype(h_sb));
9766+
0c3ec466 9767+out_hparent:
1facf9fc 9768+ dput(h_parent);
0c3ec466 9769+out_parent:
1facf9fc 9770+ dput(parent);
0c3ec466
AM
9771+out_unlock:
9772+ ii_read_unlock(inode);
9773+ si_read_unlock(sb);
4f0767ce 9774+out:
1facf9fc 9775+ if (unlikely(err < 0))
9776+ err = 255;
9777+ return err;
9778+}
9779+
9780+/* ---------------------------------------------------------------------- */
9781+
4a4d8108
AM
9782+static int aufs_commit_metadata(struct inode *inode)
9783+{
9784+ int err;
9785+ aufs_bindex_t bindex;
9786+ struct super_block *sb;
9787+ struct inode *h_inode;
9788+ int (*f)(struct inode *inode);
9789+
9790+ sb = inode->i_sb;
e49829fe 9791+ si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLMW);
4a4d8108
AM
9792+ ii_write_lock_child(inode);
9793+ bindex = au_ibstart(inode);
9794+ AuDebugOn(bindex < 0);
9795+ h_inode = au_h_iptr(inode, bindex);
9796+
9797+ f = h_inode->i_sb->s_export_op->commit_metadata;
9798+ if (f)
9799+ err = f(h_inode);
9800+ else {
9801+ struct writeback_control wbc = {
9802+ .sync_mode = WB_SYNC_ALL,
9803+ .nr_to_write = 0 /* metadata only */
9804+ };
9805+
9806+ err = sync_inode(h_inode, &wbc);
9807+ }
9808+
9809+ au_cpup_attr_timesizes(inode);
9810+ ii_write_unlock(inode);
9811+ si_read_unlock(sb);
9812+ return err;
9813+}
9814+
9815+/* ---------------------------------------------------------------------- */
9816+
1facf9fc 9817+static struct export_operations aufs_export_op = {
4a4d8108 9818+ .fh_to_dentry = aufs_fh_to_dentry,
1facf9fc 9819+ /* .fh_to_parent = aufs_fh_to_parent, */
4a4d8108
AM
9820+ .encode_fh = aufs_encode_fh,
9821+ .commit_metadata = aufs_commit_metadata
1facf9fc 9822+};
9823+
9824+void au_export_init(struct super_block *sb)
9825+{
9826+ struct au_sbinfo *sbinfo;
9827+ __u32 u;
9828+
9829+ sb->s_export_op = &aufs_export_op;
9830+ sbinfo = au_sbi(sb);
9831+ sbinfo->si_xigen = NULL;
9832+ get_random_bytes(&u, sizeof(u));
9833+ BUILD_BUG_ON(sizeof(u) != sizeof(int));
9834+ atomic_set(&sbinfo->si_xigen_next, u);
9835+}
7f207e10
AM
9836diff -urN /usr/share/empty/fs/aufs/file.c linux/fs/aufs/file.c
9837--- /usr/share/empty/fs/aufs/file.c 1970-01-01 01:00:00.000000000 +0100
b4510431
AM
9838+++ linux/fs/aufs/file.c 2012-10-17 10:31:01.772481151 +0200
9839@@ -0,0 +1,683 @@
1facf9fc 9840+/*
f6c5ef8b 9841+ * Copyright (C) 2005-2012 Junjiro R. Okajima
1facf9fc 9842+ *
9843+ * This program, aufs is free software; you can redistribute it and/or modify
9844+ * it under the terms of the GNU General Public License as published by
9845+ * the Free Software Foundation; either version 2 of the License, or
9846+ * (at your option) any later version.
dece6358
AM
9847+ *
9848+ * This program is distributed in the hope that it will be useful,
9849+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
9850+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
9851+ * GNU General Public License for more details.
9852+ *
9853+ * You should have received a copy of the GNU General Public License
9854+ * along with this program; if not, write to the Free Software
9855+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 9856+ */
9857+
9858+/*
4a4d8108 9859+ * handling file/dir, and address_space operation
1facf9fc 9860+ */
9861+
7eafdf33
AM
9862+#ifdef CONFIG_AUFS_DEBUG
9863+#include <linux/migrate.h>
9864+#endif
4a4d8108 9865+#include <linux/pagemap.h>
1facf9fc 9866+#include "aufs.h"
9867+
4a4d8108
AM
9868+/* drop flags for writing */
9869+unsigned int au_file_roflags(unsigned int flags)
9870+{
9871+ flags &= ~(O_WRONLY | O_RDWR | O_APPEND | O_CREAT | O_TRUNC);
9872+ flags |= O_RDONLY | O_NOATIME;
9873+ return flags;
9874+}
9875+
9876+/* common functions to regular file and dir */
9877+struct file *au_h_open(struct dentry *dentry, aufs_bindex_t bindex, int flags,
9878+ struct file *file)
1facf9fc 9879+{
1308ab2a 9880+ struct file *h_file;
4a4d8108
AM
9881+ struct dentry *h_dentry;
9882+ struct inode *h_inode;
9883+ struct super_block *sb;
9884+ struct au_branch *br;
9885+ struct path h_path;
9886+ int err, exec_flag;
1facf9fc 9887+
4a4d8108
AM
9888+ /* a race condition can happen between open and unlink/rmdir */
9889+ h_file = ERR_PTR(-ENOENT);
9890+ h_dentry = au_h_dptr(dentry, bindex);
b752ccd1 9891+ if (au_test_nfsd() && !h_dentry)
4a4d8108
AM
9892+ goto out;
9893+ h_inode = h_dentry->d_inode;
b752ccd1 9894+ if (au_test_nfsd() && !h_inode)
4a4d8108 9895+ goto out;
027c5e7a
AM
9896+ spin_lock(&h_dentry->d_lock);
9897+ err = (!d_unhashed(dentry) && d_unlinked(h_dentry))
9898+ || !h_inode
9899+ /* || !dentry->d_inode->i_nlink */
9900+ ;
9901+ spin_unlock(&h_dentry->d_lock);
9902+ if (unlikely(err))
4a4d8108 9903+ goto out;
1facf9fc 9904+
4a4d8108
AM
9905+ sb = dentry->d_sb;
9906+ br = au_sbr(sb, bindex);
9907+ h_file = ERR_PTR(-EACCES);
2cbb1c4b 9908+ exec_flag = flags & __FMODE_EXEC;
4a4d8108 9909+ if (exec_flag && (br->br_mnt->mnt_flags & MNT_NOEXEC))
027c5e7a 9910+ goto out;
1facf9fc 9911+
4a4d8108
AM
9912+ /* drop flags for writing */
9913+ if (au_test_ro(sb, bindex, dentry->d_inode))
9914+ flags = au_file_roflags(flags);
9915+ flags &= ~O_CREAT;
9916+ atomic_inc(&br->br_count);
9917+ h_path.dentry = h_dentry;
9918+ h_path.mnt = br->br_mnt;
9919+ if (!au_special_file(h_inode->i_mode))
9920+ h_file = vfsub_dentry_open(&h_path, flags);
9921+ else {
9922+ /* this block depends upon the configuration */
9923+ di_read_unlock(dentry, AuLock_IR);
9924+ fi_write_unlock(file);
9925+ si_read_unlock(sb);
9926+ h_file = vfsub_dentry_open(&h_path, flags);
9927+ si_noflush_read_lock(sb);
9928+ fi_write_lock(file);
9929+ di_read_lock_child(dentry, AuLock_IR);
dece6358 9930+ }
4a4d8108
AM
9931+ if (IS_ERR(h_file))
9932+ goto out_br;
dece6358 9933+
4a4d8108
AM
9934+ if (exec_flag) {
9935+ err = deny_write_access(h_file);
9936+ if (unlikely(err)) {
9937+ fput(h_file);
9938+ h_file = ERR_PTR(err);
9939+ goto out_br;
9940+ }
9941+ }
953406b4 9942+ fsnotify_open(h_file);
4a4d8108 9943+ goto out; /* success */
1facf9fc 9944+
4f0767ce 9945+out_br:
4a4d8108 9946+ atomic_dec(&br->br_count);
4f0767ce 9947+out:
4a4d8108
AM
9948+ return h_file;
9949+}
1308ab2a 9950+
4a4d8108
AM
9951+int au_do_open(struct file *file, int (*open)(struct file *file, int flags),
9952+ struct au_fidir *fidir)
1facf9fc 9953+{
dece6358 9954+ int err;
1facf9fc 9955+ struct dentry *dentry;
1308ab2a 9956+
4a4d8108
AM
9957+ err = au_finfo_init(file, fidir);
9958+ if (unlikely(err))
9959+ goto out;
1facf9fc 9960+
9961+ dentry = file->f_dentry;
4a4d8108
AM
9962+ di_read_lock_child(dentry, AuLock_IR);
9963+ err = open(file, vfsub_file_flags(file));
9964+ di_read_unlock(dentry, AuLock_IR);
1facf9fc 9965+
4a4d8108
AM
9966+ fi_write_unlock(file);
9967+ if (unlikely(err)) {
9968+ au_fi(file)->fi_hdir = NULL;
9969+ au_finfo_fin(file);
1308ab2a 9970+ }
4a4d8108 9971+
4f0767ce 9972+out:
1308ab2a 9973+ return err;
9974+}
dece6358 9975+
4a4d8108 9976+int au_reopen_nondir(struct file *file)
1308ab2a 9977+{
4a4d8108
AM
9978+ int err;
9979+ aufs_bindex_t bstart;
9980+ struct dentry *dentry;
9981+ struct file *h_file, *h_file_tmp;
1308ab2a 9982+
4a4d8108
AM
9983+ dentry = file->f_dentry;
9984+ AuDebugOn(au_special_file(dentry->d_inode->i_mode));
9985+ bstart = au_dbstart(dentry);
9986+ h_file_tmp = NULL;
9987+ if (au_fbstart(file) == bstart) {
9988+ h_file = au_hf_top(file);
9989+ if (file->f_mode == h_file->f_mode)
9990+ return 0; /* success */
9991+ h_file_tmp = h_file;
9992+ get_file(h_file_tmp);
9993+ au_set_h_fptr(file, bstart, NULL);
9994+ }
9995+ AuDebugOn(au_fi(file)->fi_hdir);
9996+ AuDebugOn(au_fbstart(file) < bstart);
1308ab2a 9997+
4a4d8108
AM
9998+ h_file = au_h_open(dentry, bstart, vfsub_file_flags(file) & ~O_TRUNC,
9999+ file);
10000+ err = PTR_ERR(h_file);
10001+ if (IS_ERR(h_file))
10002+ goto out; /* todo: close all? */
10003+
10004+ err = 0;
10005+ au_set_fbstart(file, bstart);
10006+ au_set_h_fptr(file, bstart, h_file);
10007+ au_update_figen(file);
10008+ /* todo: necessary? */
10009+ /* file->f_ra = h_file->f_ra; */
10010+
4f0767ce 10011+out:
4a4d8108
AM
10012+ if (h_file_tmp)
10013+ fput(h_file_tmp);
10014+ return err;
1facf9fc 10015+}
10016+
1308ab2a 10017+/* ---------------------------------------------------------------------- */
10018+
4a4d8108
AM
10019+static int au_reopen_wh(struct file *file, aufs_bindex_t btgt,
10020+ struct dentry *hi_wh)
1facf9fc 10021+{
4a4d8108
AM
10022+ int err;
10023+ aufs_bindex_t bstart;
10024+ struct au_dinfo *dinfo;
10025+ struct dentry *h_dentry;
10026+ struct au_hdentry *hdp;
1facf9fc 10027+
4a4d8108
AM
10028+ dinfo = au_di(file->f_dentry);
10029+ AuRwMustWriteLock(&dinfo->di_rwsem);
dece6358 10030+
4a4d8108
AM
10031+ bstart = dinfo->di_bstart;
10032+ dinfo->di_bstart = btgt;
10033+ hdp = dinfo->di_hdentry;
10034+ h_dentry = hdp[0 + btgt].hd_dentry;
10035+ hdp[0 + btgt].hd_dentry = hi_wh;
10036+ err = au_reopen_nondir(file);
10037+ hdp[0 + btgt].hd_dentry = h_dentry;
10038+ dinfo->di_bstart = bstart;
1facf9fc 10039+
1facf9fc 10040+ return err;
10041+}
10042+
4a4d8108
AM
10043+static int au_ready_to_write_wh(struct file *file, loff_t len,
10044+ aufs_bindex_t bcpup)
1facf9fc 10045+{
4a4d8108 10046+ int err;
027c5e7a
AM
10047+ struct inode *inode, *h_inode;
10048+ struct dentry *dentry, *h_dentry, *hi_wh;
1facf9fc 10049+
dece6358 10050+ dentry = file->f_dentry;
4a4d8108 10051+ au_update_dbstart(dentry);
dece6358 10052+ inode = dentry->d_inode;
027c5e7a
AM
10053+ h_inode = NULL;
10054+ if (au_dbstart(dentry) <= bcpup && au_dbend(dentry) >= bcpup) {
10055+ h_dentry = au_h_dptr(dentry, bcpup);
10056+ if (h_dentry)
10057+ h_inode = h_dentry->d_inode;
10058+ }
4a4d8108 10059+ hi_wh = au_hi_wh(inode, bcpup);
027c5e7a 10060+ if (!hi_wh && !h_inode)
4a4d8108
AM
10061+ err = au_sio_cpup_wh(dentry, bcpup, len, file);
10062+ else
10063+ /* already copied-up after unlink */
10064+ err = au_reopen_wh(file, bcpup, hi_wh);
1facf9fc 10065+
4a4d8108
AM
10066+ if (!err
10067+ && inode->i_nlink > 1
10068+ && au_opt_test(au_mntflags(dentry->d_sb), PLINK))
10069+ au_plink_append(inode, bcpup, au_h_dptr(dentry, bcpup));
1308ab2a 10070+
dece6358 10071+ return err;
1facf9fc 10072+}
10073+
4a4d8108
AM
10074+/*
10075+ * prepare the @file for writing.
10076+ */
10077+int au_ready_to_write(struct file *file, loff_t len, struct au_pin *pin)
1facf9fc 10078+{
4a4d8108 10079+ int err;
027c5e7a 10080+ aufs_bindex_t bstart, bcpup, dbstart;
4a4d8108
AM
10081+ struct dentry *dentry, *parent, *h_dentry;
10082+ struct inode *h_inode, *inode;
1facf9fc 10083+ struct super_block *sb;
4a4d8108 10084+ struct file *h_file;
1facf9fc 10085+
10086+ dentry = file->f_dentry;
1facf9fc 10087+ sb = dentry->d_sb;
4a4d8108
AM
10088+ inode = dentry->d_inode;
10089+ AuDebugOn(au_special_file(inode->i_mode));
10090+ bstart = au_fbstart(file);
10091+ err = au_test_ro(sb, bstart, inode);
10092+ if (!err && (au_hf_top(file)->f_mode & FMODE_WRITE)) {
10093+ err = au_pin(pin, dentry, bstart, AuOpt_UDBA_NONE, /*flags*/0);
1facf9fc 10094+ goto out;
4a4d8108 10095+ }
1facf9fc 10096+
027c5e7a 10097+ /* need to cpup or reopen */
4a4d8108
AM
10098+ parent = dget_parent(dentry);
10099+ di_write_lock_parent(parent);
10100+ err = AuWbrCopyup(au_sbi(sb), dentry);
10101+ bcpup = err;
10102+ if (unlikely(err < 0))
10103+ goto out_dgrade;
10104+ err = 0;
10105+
027c5e7a 10106+ if (!d_unhashed(dentry) && !au_h_dptr(parent, bcpup)) {
4a4d8108 10107+ err = au_cpup_dirs(dentry, bcpup);
1facf9fc 10108+ if (unlikely(err))
4a4d8108
AM
10109+ goto out_dgrade;
10110+ }
10111+
10112+ err = au_pin(pin, dentry, bcpup, AuOpt_UDBA_NONE,
10113+ AuPin_DI_LOCKED | AuPin_MNT_WRITE);
10114+ if (unlikely(err))
10115+ goto out_dgrade;
10116+
10117+ h_dentry = au_hf_top(file)->f_dentry;
10118+ h_inode = h_dentry->d_inode;
027c5e7a
AM
10119+ dbstart = au_dbstart(dentry);
10120+ if (dbstart <= bcpup) {
10121+ h_dentry = au_h_dptr(dentry, bcpup);
10122+ AuDebugOn(!h_dentry);
10123+ h_inode = h_dentry->d_inode;
10124+ AuDebugOn(!h_inode);
10125+ bstart = bcpup;
10126+ }
10127+
10128+ if (dbstart <= bcpup /* just reopen */
10129+ || !d_unhashed(dentry) /* copyup and reopen */
10130+ ) {
10131+ mutex_lock_nested(&h_inode->i_mutex, AuLsc_I_CHILD);
10132+ h_file = au_h_open_pre(dentry, bstart);
10133+ if (IS_ERR(h_file)) {
10134+ err = PTR_ERR(h_file);
10135+ h_file = NULL;
10136+ } else {
10137+ di_downgrade_lock(parent, AuLock_IR);
10138+ if (dbstart > bcpup)
10139+ err = au_sio_cpup_simple(dentry, bcpup, len,
10140+ AuCpup_DTIME);
10141+ if (!err)
10142+ err = au_reopen_nondir(file);
10143+ }
10144+ mutex_unlock(&h_inode->i_mutex);
10145+ au_h_open_post(dentry, bstart, h_file);
10146+ } else { /* copyup as wh and reopen */
10147+ /*
10148+ * since writable hfsplus branch is not supported,
10149+ * h_open_pre/post() are unnecessary.
10150+ */
10151+ mutex_lock_nested(&h_inode->i_mutex, AuLsc_I_CHILD);
4a4d8108
AM
10152+ err = au_ready_to_write_wh(file, len, bcpup);
10153+ di_downgrade_lock(parent, AuLock_IR);
027c5e7a 10154+ mutex_unlock(&h_inode->i_mutex);
4a4d8108 10155+ }
4a4d8108
AM
10156+
10157+ if (!err) {
10158+ au_pin_set_parent_lflag(pin, /*lflag*/0);
10159+ goto out_dput; /* success */
10160+ }
10161+ au_unpin(pin);
10162+ goto out_unlock;
1facf9fc 10163+
4f0767ce 10164+out_dgrade:
4a4d8108 10165+ di_downgrade_lock(parent, AuLock_IR);
4f0767ce 10166+out_unlock:
4a4d8108 10167+ di_read_unlock(parent, AuLock_IR);
4f0767ce 10168+out_dput:
4a4d8108 10169+ dput(parent);
4f0767ce 10170+out:
1facf9fc 10171+ return err;
10172+}
10173+
4a4d8108
AM
10174+/* ---------------------------------------------------------------------- */
10175+
10176+int au_do_flush(struct file *file, fl_owner_t id,
10177+ int (*flush)(struct file *file, fl_owner_t id))
1facf9fc 10178+{
4a4d8108 10179+ int err;
1308ab2a 10180+ struct dentry *dentry;
1facf9fc 10181+ struct super_block *sb;
4a4d8108 10182+ struct inode *inode;
1facf9fc 10183+
1facf9fc 10184+ dentry = file->f_dentry;
10185+ sb = dentry->d_sb;
dece6358 10186+ inode = dentry->d_inode;
4a4d8108
AM
10187+ si_noflush_read_lock(sb);
10188+ fi_read_lock(file);
b752ccd1 10189+ ii_read_lock_child(inode);
1facf9fc 10190+
4a4d8108
AM
10191+ err = flush(file, id);
10192+ au_cpup_attr_timesizes(inode);
1facf9fc 10193+
b752ccd1 10194+ ii_read_unlock(inode);
4a4d8108 10195+ fi_read_unlock(file);
1308ab2a 10196+ si_read_unlock(sb);
dece6358 10197+ return err;
1facf9fc 10198+}
10199+
4a4d8108
AM
10200+/* ---------------------------------------------------------------------- */
10201+
10202+static int au_file_refresh_by_inode(struct file *file, int *need_reopen)
1facf9fc 10203+{
4a4d8108
AM
10204+ int err;
10205+ aufs_bindex_t bstart;
10206+ struct au_pin pin;
10207+ struct au_finfo *finfo;
10208+ struct dentry *dentry, *parent, *hi_wh;
10209+ struct inode *inode;
1facf9fc 10210+ struct super_block *sb;
10211+
4a4d8108
AM
10212+ FiMustWriteLock(file);
10213+
10214+ err = 0;
10215+ finfo = au_fi(file);
1308ab2a 10216+ dentry = file->f_dentry;
10217+ sb = dentry->d_sb;
4a4d8108
AM
10218+ inode = dentry->d_inode;
10219+ bstart = au_ibstart(inode);
027c5e7a 10220+ if (bstart == finfo->fi_btop || IS_ROOT(dentry))
1308ab2a 10221+ goto out;
dece6358 10222+
4a4d8108
AM
10223+ parent = dget_parent(dentry);
10224+ if (au_test_ro(sb, bstart, inode)) {
10225+ di_read_lock_parent(parent, !AuLock_IR);
10226+ err = AuWbrCopyup(au_sbi(sb), dentry);
10227+ bstart = err;
10228+ di_read_unlock(parent, !AuLock_IR);
10229+ if (unlikely(err < 0))
10230+ goto out_parent;
10231+ err = 0;
1facf9fc 10232+ }
1facf9fc 10233+
4a4d8108
AM
10234+ di_read_lock_parent(parent, AuLock_IR);
10235+ hi_wh = au_hi_wh(inode, bstart);
7f207e10
AM
10236+ if (!S_ISDIR(inode->i_mode)
10237+ && au_opt_test(au_mntflags(sb), PLINK)
4a4d8108
AM
10238+ && au_plink_test(inode)
10239+ && !d_unhashed(dentry)) {
10240+ err = au_test_and_cpup_dirs(dentry, bstart);
10241+ if (unlikely(err))
10242+ goto out_unlock;
10243+
10244+ /* always superio. */
10245+ err = au_pin(&pin, dentry, bstart, AuOpt_UDBA_NONE,
10246+ AuPin_DI_LOCKED | AuPin_MNT_WRITE);
10247+ if (!err)
10248+ err = au_sio_cpup_simple(dentry, bstart, -1,
10249+ AuCpup_DTIME);
10250+ au_unpin(&pin);
10251+ } else if (hi_wh) {
10252+ /* already copied-up after unlink */
10253+ err = au_reopen_wh(file, bstart, hi_wh);
10254+ *need_reopen = 0;
10255+ }
1facf9fc 10256+
4f0767ce 10257+out_unlock:
4a4d8108 10258+ di_read_unlock(parent, AuLock_IR);
4f0767ce 10259+out_parent:
4a4d8108 10260+ dput(parent);
4f0767ce 10261+out:
1308ab2a 10262+ return err;
dece6358 10263+}
1facf9fc 10264+
4a4d8108 10265+static void au_do_refresh_dir(struct file *file)
dece6358 10266+{
4a4d8108
AM
10267+ aufs_bindex_t bindex, bend, new_bindex, brid;
10268+ struct au_hfile *p, tmp, *q;
10269+ struct au_finfo *finfo;
1308ab2a 10270+ struct super_block *sb;
4a4d8108 10271+ struct au_fidir *fidir;
1facf9fc 10272+
4a4d8108 10273+ FiMustWriteLock(file);
1facf9fc 10274+
4a4d8108
AM
10275+ sb = file->f_dentry->d_sb;
10276+ finfo = au_fi(file);
10277+ fidir = finfo->fi_hdir;
10278+ AuDebugOn(!fidir);
10279+ p = fidir->fd_hfile + finfo->fi_btop;
10280+ brid = p->hf_br->br_id;
10281+ bend = fidir->fd_bbot;
10282+ for (bindex = finfo->fi_btop; bindex <= bend; bindex++, p++) {
10283+ if (!p->hf_file)
10284+ continue;
1308ab2a 10285+
4a4d8108
AM
10286+ new_bindex = au_br_index(sb, p->hf_br->br_id);
10287+ if (new_bindex == bindex)
10288+ continue;
10289+ if (new_bindex < 0) {
10290+ au_set_h_fptr(file, bindex, NULL);
10291+ continue;
10292+ }
1308ab2a 10293+
4a4d8108
AM
10294+ /* swap two lower inode, and loop again */
10295+ q = fidir->fd_hfile + new_bindex;
10296+ tmp = *q;
10297+ *q = *p;
10298+ *p = tmp;
10299+ if (tmp.hf_file) {
10300+ bindex--;
10301+ p--;
10302+ }
10303+ }
1308ab2a 10304+
4a4d8108 10305+ p = fidir->fd_hfile;
027c5e7a 10306+ if (!au_test_mmapped(file) && !d_unlinked(file->f_dentry)) {
4a4d8108
AM
10307+ bend = au_sbend(sb);
10308+ for (finfo->fi_btop = 0; finfo->fi_btop <= bend;
10309+ finfo->fi_btop++, p++)
10310+ if (p->hf_file) {
10311+ if (p->hf_file->f_dentry
10312+ && p->hf_file->f_dentry->d_inode)
10313+ break;
10314+ else
10315+ au_hfput(p, file);
10316+ }
10317+ } else {
10318+ bend = au_br_index(sb, brid);
10319+ for (finfo->fi_btop = 0; finfo->fi_btop < bend;
10320+ finfo->fi_btop++, p++)
10321+ if (p->hf_file)
10322+ au_hfput(p, file);
10323+ bend = au_sbend(sb);
10324+ }
1308ab2a 10325+
4a4d8108
AM
10326+ p = fidir->fd_hfile + bend;
10327+ for (fidir->fd_bbot = bend; fidir->fd_bbot >= finfo->fi_btop;
10328+ fidir->fd_bbot--, p--)
10329+ if (p->hf_file) {
10330+ if (p->hf_file->f_dentry
10331+ && p->hf_file->f_dentry->d_inode)
10332+ break;
10333+ else
10334+ au_hfput(p, file);
10335+ }
10336+ AuDebugOn(fidir->fd_bbot < finfo->fi_btop);
1308ab2a 10337+}
10338+
4a4d8108
AM
10339+/*
10340+ * after branch manipulating, refresh the file.
10341+ */
10342+static int refresh_file(struct file *file, int (*reopen)(struct file *file))
1facf9fc 10343+{
4a4d8108
AM
10344+ int err, need_reopen;
10345+ aufs_bindex_t bend, bindex;
10346+ struct dentry *dentry;
1308ab2a 10347+ struct au_finfo *finfo;
4a4d8108 10348+ struct au_hfile *hfile;
1facf9fc 10349+
4a4d8108 10350+ dentry = file->f_dentry;
1308ab2a 10351+ finfo = au_fi(file);
4a4d8108
AM
10352+ if (!finfo->fi_hdir) {
10353+ hfile = &finfo->fi_htop;
10354+ AuDebugOn(!hfile->hf_file);
10355+ bindex = au_br_index(dentry->d_sb, hfile->hf_br->br_id);
10356+ AuDebugOn(bindex < 0);
10357+ if (bindex != finfo->fi_btop)
10358+ au_set_fbstart(file, bindex);
10359+ } else {
10360+ err = au_fidir_realloc(finfo, au_sbend(dentry->d_sb) + 1);
10361+ if (unlikely(err))
10362+ goto out;
10363+ au_do_refresh_dir(file);
10364+ }
1facf9fc 10365+
4a4d8108
AM
10366+ err = 0;
10367+ need_reopen = 1;
10368+ if (!au_test_mmapped(file))
10369+ err = au_file_refresh_by_inode(file, &need_reopen);
027c5e7a 10370+ if (!err && need_reopen && !d_unlinked(dentry))
4a4d8108
AM
10371+ err = reopen(file);
10372+ if (!err) {
10373+ au_update_figen(file);
10374+ goto out; /* success */
10375+ }
10376+
10377+ /* error, close all lower files */
10378+ if (finfo->fi_hdir) {
10379+ bend = au_fbend_dir(file);
10380+ for (bindex = au_fbstart(file); bindex <= bend; bindex++)
10381+ au_set_h_fptr(file, bindex, NULL);
10382+ }
1facf9fc 10383+
4f0767ce 10384+out:
1facf9fc 10385+ return err;
10386+}
10387+
4a4d8108
AM
10388+/* common function to regular file and dir */
10389+int au_reval_and_lock_fdi(struct file *file, int (*reopen)(struct file *file),
10390+ int wlock)
dece6358 10391+{
1308ab2a 10392+ int err;
4a4d8108
AM
10393+ unsigned int sigen, figen;
10394+ aufs_bindex_t bstart;
10395+ unsigned char pseudo_link;
10396+ struct dentry *dentry;
10397+ struct inode *inode;
1facf9fc 10398+
4a4d8108
AM
10399+ err = 0;
10400+ dentry = file->f_dentry;
10401+ inode = dentry->d_inode;
10402+ AuDebugOn(au_special_file(inode->i_mode));
10403+ sigen = au_sigen(dentry->d_sb);
10404+ fi_write_lock(file);
10405+ figen = au_figen(file);
10406+ di_write_lock_child(dentry);
10407+ bstart = au_dbstart(dentry);
10408+ pseudo_link = (bstart != au_ibstart(inode));
10409+ if (sigen == figen && !pseudo_link && au_fbstart(file) == bstart) {
10410+ if (!wlock) {
10411+ di_downgrade_lock(dentry, AuLock_IR);
10412+ fi_downgrade_lock(file);
10413+ }
10414+ goto out; /* success */
10415+ }
dece6358 10416+
4a4d8108 10417+ AuDbg("sigen %d, figen %d\n", sigen, figen);
027c5e7a 10418+ if (au_digen_test(dentry, sigen)) {
4a4d8108 10419+ err = au_reval_dpath(dentry, sigen);
027c5e7a 10420+ AuDebugOn(!err && au_digen_test(dentry, sigen));
4a4d8108 10421+ }
dece6358 10422+
027c5e7a
AM
10423+ if (!err)
10424+ err = refresh_file(file, reopen);
4a4d8108
AM
10425+ if (!err) {
10426+ if (!wlock) {
10427+ di_downgrade_lock(dentry, AuLock_IR);
10428+ fi_downgrade_lock(file);
10429+ }
10430+ } else {
10431+ di_write_unlock(dentry);
10432+ fi_write_unlock(file);
10433+ }
1facf9fc 10434+
4f0767ce 10435+out:
1308ab2a 10436+ return err;
10437+}
1facf9fc 10438+
4a4d8108
AM
10439+/* ---------------------------------------------------------------------- */
10440+
10441+/* cf. aufs_nopage() */
10442+/* for madvise(2) */
10443+static int aufs_readpage(struct file *file __maybe_unused, struct page *page)
1308ab2a 10444+{
4a4d8108
AM
10445+ unlock_page(page);
10446+ return 0;
10447+}
1facf9fc 10448+
4a4d8108
AM
10449+/* it will never be called, but necessary to support O_DIRECT */
10450+static ssize_t aufs_direct_IO(int rw, struct kiocb *iocb,
10451+ const struct iovec *iov, loff_t offset,
10452+ unsigned long nr_segs)
10453+{ BUG(); return 0; }
1facf9fc 10454+
4a4d8108
AM
10455+/*
10456+ * it will never be called, but madvise and fadvise behaves differently
10457+ * when get_xip_mem is defined
10458+ */
10459+static int aufs_get_xip_mem(struct address_space *mapping, pgoff_t pgoff,
10460+ int create, void **kmem, unsigned long *pfn)
10461+{ BUG(); return 0; }
1facf9fc 10462+
4a4d8108
AM
10463+/* they will never be called. */
10464+#ifdef CONFIG_AUFS_DEBUG
10465+static int aufs_write_begin(struct file *file, struct address_space *mapping,
10466+ loff_t pos, unsigned len, unsigned flags,
10467+ struct page **pagep, void **fsdata)
10468+{ AuUnsupport(); return 0; }
10469+static int aufs_write_end(struct file *file, struct address_space *mapping,
10470+ loff_t pos, unsigned len, unsigned copied,
10471+ struct page *page, void *fsdata)
10472+{ AuUnsupport(); return 0; }
10473+static int aufs_writepage(struct page *page, struct writeback_control *wbc)
10474+{ AuUnsupport(); return 0; }
1308ab2a 10475+
4a4d8108
AM
10476+static int aufs_set_page_dirty(struct page *page)
10477+{ AuUnsupport(); return 0; }
10478+static void aufs_invalidatepage(struct page *page, unsigned long offset)
10479+{ AuUnsupport(); }
10480+static int aufs_releasepage(struct page *page, gfp_t gfp)
10481+{ AuUnsupport(); return 0; }
10482+static int aufs_migratepage(struct address_space *mapping, struct page *newpage,
7eafdf33 10483+ struct page *page, enum migrate_mode mode)
4a4d8108
AM
10484+{ AuUnsupport(); return 0; }
10485+static int aufs_launder_page(struct page *page)
10486+{ AuUnsupport(); return 0; }
10487+static int aufs_is_partially_uptodate(struct page *page,
10488+ read_descriptor_t *desc,
10489+ unsigned long from)
10490+{ AuUnsupport(); return 0; }
10491+static int aufs_error_remove_page(struct address_space *mapping,
10492+ struct page *page)
10493+{ AuUnsupport(); return 0; }
b4510431
AM
10494+static int aufs_swap_activate(struct swap_info_struct *sis, struct file *file,
10495+ sector_t *span)
10496+{ AuUnsupport(); return 0; }
10497+static void aufs_swap_deactivate(struct file *file)
10498+{ AuUnsupport(); }
4a4d8108
AM
10499+#endif /* CONFIG_AUFS_DEBUG */
10500+
10501+const struct address_space_operations aufs_aop = {
10502+ .readpage = aufs_readpage,
10503+ .direct_IO = aufs_direct_IO,
10504+ .get_xip_mem = aufs_get_xip_mem,
10505+#ifdef CONFIG_AUFS_DEBUG
10506+ .writepage = aufs_writepage,
4a4d8108
AM
10507+ /* no writepages, because of writepage */
10508+ .set_page_dirty = aufs_set_page_dirty,
10509+ /* no readpages, because of readpage */
10510+ .write_begin = aufs_write_begin,
10511+ .write_end = aufs_write_end,
10512+ /* no bmap, no block device */
10513+ .invalidatepage = aufs_invalidatepage,
10514+ .releasepage = aufs_releasepage,
10515+ .migratepage = aufs_migratepage,
10516+ .launder_page = aufs_launder_page,
10517+ .is_partially_uptodate = aufs_is_partially_uptodate,
b4510431
AM
10518+ .error_remove_page = aufs_error_remove_page,
10519+ .swap_activate = aufs_swap_activate,
10520+ .swap_deactivate = aufs_swap_deactivate
4a4d8108 10521+#endif /* CONFIG_AUFS_DEBUG */
dece6358 10522+};
7f207e10
AM
10523diff -urN /usr/share/empty/fs/aufs/file.h linux/fs/aufs/file.h
10524--- /usr/share/empty/fs/aufs/file.h 1970-01-01 01:00:00.000000000 +0100
2dfbb274
AM
10525+++ linux/fs/aufs/file.h 2012-08-26 08:39:00.760508065 +0200
10526@@ -0,0 +1,298 @@
4a4d8108 10527+/*
f6c5ef8b 10528+ * Copyright (C) 2005-2012 Junjiro R. Okajima
4a4d8108
AM
10529+ *
10530+ * This program, aufs is free software; you can redistribute it and/or modify
10531+ * it under the terms of the GNU General Public License as published by
10532+ * the Free Software Foundation; either version 2 of the License, or
10533+ * (at your option) any later version.
10534+ *
10535+ * This program is distributed in the hope that it will be useful,
10536+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
10537+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10538+ * GNU General Public License for more details.
10539+ *
10540+ * You should have received a copy of the GNU General Public License
10541+ * along with this program; if not, write to the Free Software
10542+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
10543+ */
1facf9fc 10544+
4a4d8108
AM
10545+/*
10546+ * file operations
10547+ */
1facf9fc 10548+
4a4d8108
AM
10549+#ifndef __AUFS_FILE_H__
10550+#define __AUFS_FILE_H__
1facf9fc 10551+
4a4d8108 10552+#ifdef __KERNEL__
1facf9fc 10553+
2cbb1c4b 10554+#include <linux/file.h>
4a4d8108
AM
10555+#include <linux/fs.h>
10556+#include <linux/poll.h>
4a4d8108 10557+#include "rwsem.h"
1facf9fc 10558+
4a4d8108
AM
10559+struct au_branch;
10560+struct au_hfile {
10561+ struct file *hf_file;
10562+ struct au_branch *hf_br;
10563+};
1facf9fc 10564+
4a4d8108
AM
10565+struct au_vdir;
10566+struct au_fidir {
10567+ aufs_bindex_t fd_bbot;
10568+ aufs_bindex_t fd_nent;
10569+ struct au_vdir *fd_vdir_cache;
10570+ struct au_hfile fd_hfile[];
10571+};
1facf9fc 10572+
4a4d8108 10573+static inline int au_fidir_sz(int nent)
dece6358 10574+{
4f0767ce
JR
10575+ AuDebugOn(nent < 0);
10576+ return sizeof(struct au_fidir) + sizeof(struct au_hfile) * nent;
4a4d8108 10577+}
1facf9fc 10578+
4a4d8108
AM
10579+struct au_finfo {
10580+ atomic_t fi_generation;
dece6358 10581+
4a4d8108
AM
10582+ struct au_rwsem fi_rwsem;
10583+ aufs_bindex_t fi_btop;
10584+
10585+ /* do not union them */
10586+ struct { /* for non-dir */
10587+ struct au_hfile fi_htop;
2cbb1c4b 10588+ atomic_t fi_mmapped;
4a4d8108
AM
10589+ };
10590+ struct au_fidir *fi_hdir; /* for dir only */
10591+} ____cacheline_aligned_in_smp;
1facf9fc 10592+
4a4d8108 10593+/* ---------------------------------------------------------------------- */
1facf9fc 10594+
4a4d8108
AM
10595+/* file.c */
10596+extern const struct address_space_operations aufs_aop;
10597+unsigned int au_file_roflags(unsigned int flags);
10598+struct file *au_h_open(struct dentry *dentry, aufs_bindex_t bindex, int flags,
10599+ struct file *file);
10600+int au_do_open(struct file *file, int (*open)(struct file *file, int flags),
10601+ struct au_fidir *fidir);
10602+int au_reopen_nondir(struct file *file);
10603+struct au_pin;
10604+int au_ready_to_write(struct file *file, loff_t len, struct au_pin *pin);
10605+int au_reval_and_lock_fdi(struct file *file, int (*reopen)(struct file *file),
10606+ int wlock);
10607+int au_do_flush(struct file *file, fl_owner_t id,
10608+ int (*flush)(struct file *file, fl_owner_t id));
1facf9fc 10609+
4a4d8108
AM
10610+/* poll.c */
10611+#ifdef CONFIG_AUFS_POLL
10612+unsigned int aufs_poll(struct file *file, poll_table *wait);
10613+#endif
1facf9fc 10614+
4a4d8108
AM
10615+#ifdef CONFIG_AUFS_BR_HFSPLUS
10616+/* hfsplus.c */
10617+struct file *au_h_open_pre(struct dentry *dentry, aufs_bindex_t bindex);
10618+void au_h_open_post(struct dentry *dentry, aufs_bindex_t bindex,
10619+ struct file *h_file);
10620+#else
10621+static inline
10622+struct file *au_h_open_pre(struct dentry *dentry, aufs_bindex_t bindex)
dece6358 10623+{
4a4d8108
AM
10624+ return NULL;
10625+}
1facf9fc 10626+
4a4d8108
AM
10627+AuStubVoid(au_h_open_post, struct dentry *dentry, aufs_bindex_t bindex,
10628+ struct file *h_file);
10629+#endif
1facf9fc 10630+
4a4d8108
AM
10631+/* f_op.c */
10632+extern const struct file_operations aufs_file_fop;
4a4d8108
AM
10633+int au_do_open_nondir(struct file *file, int flags);
10634+int aufs_release_nondir(struct inode *inode __maybe_unused, struct file *file);
10635+
10636+#ifdef CONFIG_AUFS_SP_IATTR
10637+/* f_op_sp.c */
10638+int au_special_file(umode_t mode);
10639+void au_init_special_fop(struct inode *inode, umode_t mode, dev_t rdev);
10640+#else
10641+AuStubInt0(au_special_file, umode_t mode)
10642+static inline void au_init_special_fop(struct inode *inode, umode_t mode,
10643+ dev_t rdev)
10644+{
10645+ init_special_inode(inode, mode, rdev);
10646+}
10647+#endif
1facf9fc 10648+
4a4d8108
AM
10649+/* finfo.c */
10650+void au_hfput(struct au_hfile *hf, struct file *file);
10651+void au_set_h_fptr(struct file *file, aufs_bindex_t bindex,
10652+ struct file *h_file);
1facf9fc 10653+
4a4d8108 10654+void au_update_figen(struct file *file);
4a4d8108
AM
10655+struct au_fidir *au_fidir_alloc(struct super_block *sb);
10656+int au_fidir_realloc(struct au_finfo *finfo, int nbr);
1facf9fc 10657+
4a4d8108
AM
10658+void au_fi_init_once(void *_fi);
10659+void au_finfo_fin(struct file *file);
10660+int au_finfo_init(struct file *file, struct au_fidir *fidir);
1facf9fc 10661+
4a4d8108
AM
10662+/* ioctl.c */
10663+long aufs_ioctl_nondir(struct file *file, unsigned int cmd, unsigned long arg);
b752ccd1
AM
10664+#ifdef CONFIG_COMPAT
10665+long aufs_compat_ioctl_dir(struct file *file, unsigned int cmd,
10666+ unsigned long arg);
10667+#endif
1facf9fc 10668+
4a4d8108 10669+/* ---------------------------------------------------------------------- */
1facf9fc 10670+
4a4d8108
AM
10671+static inline struct au_finfo *au_fi(struct file *file)
10672+{
10673+ return file->private_data;
10674+}
1facf9fc 10675+
4a4d8108 10676+/* ---------------------------------------------------------------------- */
1facf9fc 10677+
4a4d8108
AM
10678+/*
10679+ * fi_read_lock, fi_write_lock,
10680+ * fi_read_unlock, fi_write_unlock, fi_downgrade_lock
10681+ */
10682+AuSimpleRwsemFuncs(fi, struct file *f, &au_fi(f)->fi_rwsem);
1308ab2a 10683+
4a4d8108
AM
10684+#define FiMustNoWaiters(f) AuRwMustNoWaiters(&au_fi(f)->fi_rwsem)
10685+#define FiMustAnyLock(f) AuRwMustAnyLock(&au_fi(f)->fi_rwsem)
10686+#define FiMustWriteLock(f) AuRwMustWriteLock(&au_fi(f)->fi_rwsem)
1facf9fc 10687+
1308ab2a 10688+/* ---------------------------------------------------------------------- */
10689+
4a4d8108
AM
10690+/* todo: hard/soft set? */
10691+static inline aufs_bindex_t au_fbstart(struct file *file)
dece6358 10692+{
4a4d8108
AM
10693+ FiMustAnyLock(file);
10694+ return au_fi(file)->fi_btop;
10695+}
dece6358 10696+
4a4d8108
AM
10697+static inline aufs_bindex_t au_fbend_dir(struct file *file)
10698+{
10699+ FiMustAnyLock(file);
10700+ AuDebugOn(!au_fi(file)->fi_hdir);
10701+ return au_fi(file)->fi_hdir->fd_bbot;
10702+}
1facf9fc 10703+
4a4d8108
AM
10704+static inline struct au_vdir *au_fvdir_cache(struct file *file)
10705+{
10706+ FiMustAnyLock(file);
10707+ AuDebugOn(!au_fi(file)->fi_hdir);
10708+ return au_fi(file)->fi_hdir->fd_vdir_cache;
10709+}
1facf9fc 10710+
4a4d8108
AM
10711+static inline void au_set_fbstart(struct file *file, aufs_bindex_t bindex)
10712+{
10713+ FiMustWriteLock(file);
10714+ au_fi(file)->fi_btop = bindex;
10715+}
1facf9fc 10716+
4a4d8108
AM
10717+static inline void au_set_fbend_dir(struct file *file, aufs_bindex_t bindex)
10718+{
10719+ FiMustWriteLock(file);
10720+ AuDebugOn(!au_fi(file)->fi_hdir);
10721+ au_fi(file)->fi_hdir->fd_bbot = bindex;
10722+}
1308ab2a 10723+
4a4d8108
AM
10724+static inline void au_set_fvdir_cache(struct file *file,
10725+ struct au_vdir *vdir_cache)
10726+{
10727+ FiMustWriteLock(file);
10728+ AuDebugOn(!au_fi(file)->fi_hdir);
10729+ au_fi(file)->fi_hdir->fd_vdir_cache = vdir_cache;
10730+}
dece6358 10731+
4a4d8108
AM
10732+static inline struct file *au_hf_top(struct file *file)
10733+{
10734+ FiMustAnyLock(file);
10735+ AuDebugOn(au_fi(file)->fi_hdir);
10736+ return au_fi(file)->fi_htop.hf_file;
10737+}
1facf9fc 10738+
4a4d8108
AM
10739+static inline struct file *au_hf_dir(struct file *file, aufs_bindex_t bindex)
10740+{
10741+ FiMustAnyLock(file);
10742+ AuDebugOn(!au_fi(file)->fi_hdir);
10743+ return au_fi(file)->fi_hdir->fd_hfile[0 + bindex].hf_file;
dece6358
AM
10744+}
10745+
4a4d8108
AM
10746+/* todo: memory barrier? */
10747+static inline unsigned int au_figen(struct file *f)
dece6358 10748+{
4a4d8108
AM
10749+ return atomic_read(&au_fi(f)->fi_generation);
10750+}
dece6358 10751+
2cbb1c4b
JR
10752+static inline void au_set_mmapped(struct file *f)
10753+{
10754+ if (atomic_inc_return(&au_fi(f)->fi_mmapped))
10755+ return;
0c3ec466 10756+ pr_warn("fi_mmapped wrapped around\n");
2cbb1c4b
JR
10757+ while (!atomic_inc_return(&au_fi(f)->fi_mmapped))
10758+ ;
10759+}
10760+
10761+static inline void au_unset_mmapped(struct file *f)
10762+{
10763+ atomic_dec(&au_fi(f)->fi_mmapped);
10764+}
10765+
4a4d8108
AM
10766+static inline int au_test_mmapped(struct file *f)
10767+{
2cbb1c4b
JR
10768+ return atomic_read(&au_fi(f)->fi_mmapped);
10769+}
10770+
10771+/* customize vma->vm_file */
10772+
10773+static inline void au_do_vm_file_reset(struct vm_area_struct *vma,
10774+ struct file *file)
10775+{
53392da6
AM
10776+ struct file *f;
10777+
10778+ f = vma->vm_file;
2cbb1c4b
JR
10779+ get_file(file);
10780+ vma->vm_file = file;
53392da6 10781+ fput(f);
2cbb1c4b
JR
10782+}
10783+
10784+#ifdef CONFIG_MMU
10785+#define AuDbgVmRegion(file, vma) do {} while (0)
10786+
10787+static inline void au_vm_file_reset(struct vm_area_struct *vma,
10788+ struct file *file)
10789+{
10790+ au_do_vm_file_reset(vma, file);
10791+}
10792+#else
10793+#define AuDbgVmRegion(file, vma) \
10794+ AuDebugOn((vma)->vm_region && (vma)->vm_region->vm_file != (file))
10795+
10796+static inline void au_vm_file_reset(struct vm_area_struct *vma,
10797+ struct file *file)
10798+{
53392da6
AM
10799+ struct file *f;
10800+
2cbb1c4b 10801+ au_do_vm_file_reset(vma, file);
53392da6 10802+ f = vma->vm_region->vm_file;
2cbb1c4b
JR
10803+ get_file(file);
10804+ vma->vm_region->vm_file = file;
53392da6 10805+ fput(f);
2cbb1c4b
JR
10806+}
10807+#endif /* CONFIG_MMU */
10808+
10809+/* handle vma->vm_prfile */
10810+static inline void au_vm_prfile_set(struct vm_area_struct *vma,
10811+ struct file *file)
10812+{
10813+#ifdef CONFIG_AUFS_PROC_MAP
10814+ get_file(file);
10815+ vma->vm_prfile = file;
10816+#ifndef CONFIG_MMU
10817+ get_file(file);
10818+ vma->vm_region->vm_prfile = file;
10819+#endif
10820+#endif
4a4d8108 10821+}
1308ab2a 10822+
4a4d8108
AM
10823+#endif /* __KERNEL__ */
10824+#endif /* __AUFS_FILE_H__ */
7f207e10
AM
10825diff -urN /usr/share/empty/fs/aufs/finfo.c linux/fs/aufs/finfo.c
10826--- /usr/share/empty/fs/aufs/finfo.c 1970-01-01 01:00:00.000000000 +0100
2dfbb274 10827+++ linux/fs/aufs/finfo.c 2012-08-26 08:39:00.760508065 +0200
f6c5ef8b 10828@@ -0,0 +1,156 @@
4a4d8108 10829+/*
f6c5ef8b 10830+ * Copyright (C) 2005-2012 Junjiro R. Okajima
4a4d8108
AM
10831+ *
10832+ * This program, aufs is free software; you can redistribute it and/or modify
10833+ * it under the terms of the GNU General Public License as published by
10834+ * the Free Software Foundation; either version 2 of the License, or
10835+ * (at your option) any later version.
10836+ *
10837+ * This program is distributed in the hope that it will be useful,
10838+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
10839+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10840+ * GNU General Public License for more details.
10841+ *
10842+ * You should have received a copy of the GNU General Public License
10843+ * along with this program; if not, write to the Free Software
10844+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
10845+ */
1308ab2a 10846+
4a4d8108
AM
10847+/*
10848+ * file private data
10849+ */
1facf9fc 10850+
4a4d8108 10851+#include "aufs.h"
1facf9fc 10852+
4a4d8108
AM
10853+void au_hfput(struct au_hfile *hf, struct file *file)
10854+{
10855+ /* todo: direct access f_flags */
2cbb1c4b 10856+ if (vfsub_file_flags(file) & __FMODE_EXEC)
4a4d8108
AM
10857+ allow_write_access(hf->hf_file);
10858+ fput(hf->hf_file);
10859+ hf->hf_file = NULL;
e49829fe 10860+ atomic_dec(&hf->hf_br->br_count);
4a4d8108
AM
10861+ hf->hf_br = NULL;
10862+}
1facf9fc 10863+
4a4d8108
AM
10864+void au_set_h_fptr(struct file *file, aufs_bindex_t bindex, struct file *val)
10865+{
10866+ struct au_finfo *finfo = au_fi(file);
10867+ struct au_hfile *hf;
10868+ struct au_fidir *fidir;
10869+
10870+ fidir = finfo->fi_hdir;
10871+ if (!fidir) {
10872+ AuDebugOn(finfo->fi_btop != bindex);
10873+ hf = &finfo->fi_htop;
10874+ } else
10875+ hf = fidir->fd_hfile + bindex;
10876+
10877+ if (hf && hf->hf_file)
10878+ au_hfput(hf, file);
10879+ if (val) {
10880+ FiMustWriteLock(file);
10881+ hf->hf_file = val;
10882+ hf->hf_br = au_sbr(file->f_dentry->d_sb, bindex);
1308ab2a 10883+ }
4a4d8108 10884+}
1facf9fc 10885+
4a4d8108
AM
10886+void au_update_figen(struct file *file)
10887+{
10888+ atomic_set(&au_fi(file)->fi_generation, au_digen(file->f_dentry));
10889+ /* smp_mb(); */ /* atomic_set */
1facf9fc 10890+}
10891+
4a4d8108
AM
10892+/* ---------------------------------------------------------------------- */
10893+
4a4d8108
AM
10894+struct au_fidir *au_fidir_alloc(struct super_block *sb)
10895+{
10896+ struct au_fidir *fidir;
10897+ int nbr;
10898+
10899+ nbr = au_sbend(sb) + 1;
10900+ if (nbr < 2)
10901+ nbr = 2; /* initial allocate for 2 branches */
10902+ fidir = kzalloc(au_fidir_sz(nbr), GFP_NOFS);
10903+ if (fidir) {
10904+ fidir->fd_bbot = -1;
10905+ fidir->fd_nent = nbr;
10906+ fidir->fd_vdir_cache = NULL;
10907+ }
10908+
10909+ return fidir;
10910+}
10911+
10912+int au_fidir_realloc(struct au_finfo *finfo, int nbr)
10913+{
10914+ int err;
10915+ struct au_fidir *fidir, *p;
10916+
10917+ AuRwMustWriteLock(&finfo->fi_rwsem);
10918+ fidir = finfo->fi_hdir;
10919+ AuDebugOn(!fidir);
10920+
10921+ err = -ENOMEM;
10922+ p = au_kzrealloc(fidir, au_fidir_sz(fidir->fd_nent), au_fidir_sz(nbr),
10923+ GFP_NOFS);
10924+ if (p) {
10925+ p->fd_nent = nbr;
10926+ finfo->fi_hdir = p;
10927+ err = 0;
10928+ }
1facf9fc 10929+
dece6358 10930+ return err;
1facf9fc 10931+}
1308ab2a 10932+
10933+/* ---------------------------------------------------------------------- */
10934+
4a4d8108 10935+void au_finfo_fin(struct file *file)
1308ab2a 10936+{
4a4d8108
AM
10937+ struct au_finfo *finfo;
10938+
7f207e10
AM
10939+ au_nfiles_dec(file->f_dentry->d_sb);
10940+
4a4d8108
AM
10941+ finfo = au_fi(file);
10942+ AuDebugOn(finfo->fi_hdir);
10943+ AuRwDestroy(&finfo->fi_rwsem);
10944+ au_cache_free_finfo(finfo);
1308ab2a 10945+}
1308ab2a 10946+
e49829fe 10947+void au_fi_init_once(void *_finfo)
4a4d8108 10948+{
e49829fe 10949+ struct au_finfo *finfo = _finfo;
2cbb1c4b 10950+ static struct lock_class_key aufs_fi;
1308ab2a 10951+
e49829fe
JR
10952+ au_rw_init(&finfo->fi_rwsem);
10953+ au_rw_class(&finfo->fi_rwsem, &aufs_fi);
4a4d8108 10954+}
1308ab2a 10955+
4a4d8108
AM
10956+int au_finfo_init(struct file *file, struct au_fidir *fidir)
10957+{
9dbd164d 10958+ int err, lc_idx;
4a4d8108
AM
10959+ struct au_finfo *finfo;
10960+ struct dentry *dentry;
10961+
10962+ err = -ENOMEM;
10963+ dentry = file->f_dentry;
10964+ finfo = au_cache_alloc_finfo();
10965+ if (unlikely(!finfo))
10966+ goto out;
10967+
10968+ err = 0;
7f207e10 10969+ au_nfiles_inc(dentry->d_sb);
9dbd164d
AM
10970+ lc_idx = AuLcNonDir_FIINFO;
10971+ if (fidir)
10972+ lc_idx = AuLcDir_FIINFO;
10973+ au_rw_class(&finfo->fi_rwsem, au_lc_key + lc_idx);
4a4d8108
AM
10974+ au_rw_write_lock(&finfo->fi_rwsem);
10975+ finfo->fi_btop = -1;
10976+ finfo->fi_hdir = fidir;
10977+ atomic_set(&finfo->fi_generation, au_digen(dentry));
10978+ /* smp_mb(); */ /* atomic_set */
10979+
10980+ file->private_data = finfo;
10981+
10982+out:
10983+ return err;
10984+}
7f207e10
AM
10985diff -urN /usr/share/empty/fs/aufs/f_op.c linux/fs/aufs/f_op.c
10986--- /usr/share/empty/fs/aufs/f_op.c 1970-01-01 01:00:00.000000000 +0100
b4510431
AM
10987+++ linux/fs/aufs/f_op.c 2012-10-17 10:31:01.772481151 +0200
10988@@ -0,0 +1,724 @@
dece6358 10989+/*
f6c5ef8b 10990+ * Copyright (C) 2005-2012 Junjiro R. Okajima
dece6358
AM
10991+ *
10992+ * This program, aufs is free software; you can redistribute it and/or modify
10993+ * it under the terms of the GNU General Public License as published by
10994+ * the Free Software Foundation; either version 2 of the License, or
10995+ * (at your option) any later version.
10996+ *
10997+ * This program is distributed in the hope that it will be useful,
10998+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
10999+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11000+ * GNU General Public License for more details.
11001+ *
11002+ * You should have received a copy of the GNU General Public License
11003+ * along with this program; if not, write to the Free Software
11004+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
11005+ */
1facf9fc 11006+
11007+/*
4a4d8108 11008+ * file and vm operations
1facf9fc 11009+ */
dece6358 11010+
4a4d8108
AM
11011+#include <linux/fs_stack.h>
11012+#include <linux/mman.h>
4a4d8108 11013+#include <linux/security.h>
dece6358
AM
11014+#include "aufs.h"
11015+
4a4d8108 11016+int au_do_open_nondir(struct file *file, int flags)
1facf9fc 11017+{
4a4d8108
AM
11018+ int err;
11019+ aufs_bindex_t bindex;
11020+ struct file *h_file;
11021+ struct dentry *dentry;
11022+ struct au_finfo *finfo;
11023+
11024+ FiMustWriteLock(file);
11025+
4a4d8108 11026+ dentry = file->f_dentry;
027c5e7a
AM
11027+ err = au_d_alive(dentry);
11028+ if (unlikely(err))
11029+ goto out;
11030+
4a4d8108
AM
11031+ finfo = au_fi(file);
11032+ memset(&finfo->fi_htop, 0, sizeof(finfo->fi_htop));
2cbb1c4b 11033+ atomic_set(&finfo->fi_mmapped, 0);
4a4d8108
AM
11034+ bindex = au_dbstart(dentry);
11035+ h_file = au_h_open(dentry, bindex, flags, file);
11036+ if (IS_ERR(h_file))
11037+ err = PTR_ERR(h_file);
11038+ else {
11039+ au_set_fbstart(file, bindex);
11040+ au_set_h_fptr(file, bindex, h_file);
11041+ au_update_figen(file);
11042+ /* todo: necessary? */
11043+ /* file->f_ra = h_file->f_ra; */
11044+ }
027c5e7a
AM
11045+
11046+out:
4a4d8108 11047+ return err;
1facf9fc 11048+}
11049+
4a4d8108
AM
11050+static int aufs_open_nondir(struct inode *inode __maybe_unused,
11051+ struct file *file)
1facf9fc 11052+{
4a4d8108 11053+ int err;
1308ab2a 11054+ struct super_block *sb;
1facf9fc 11055+
2cbb1c4b 11056+ AuDbg("%.*s, f_flags 0x%x, f_mode 0x%x\n",
4a4d8108
AM
11057+ AuDLNPair(file->f_dentry), vfsub_file_flags(file),
11058+ file->f_mode);
1facf9fc 11059+
4a4d8108
AM
11060+ sb = file->f_dentry->d_sb;
11061+ si_read_lock(sb, AuLock_FLUSH);
11062+ err = au_do_open(file, au_do_open_nondir, /*fidir*/NULL);
11063+ si_read_unlock(sb);
11064+ return err;
11065+}
1facf9fc 11066+
4a4d8108
AM
11067+int aufs_release_nondir(struct inode *inode __maybe_unused, struct file *file)
11068+{
11069+ struct au_finfo *finfo;
11070+ aufs_bindex_t bindex;
1facf9fc 11071+
4a4d8108
AM
11072+ finfo = au_fi(file);
11073+ bindex = finfo->fi_btop;
b4510431 11074+ if (bindex >= 0)
4a4d8108 11075+ au_set_h_fptr(file, bindex, NULL);
7f207e10 11076+
4a4d8108
AM
11077+ au_finfo_fin(file);
11078+ return 0;
1facf9fc 11079+}
11080+
4a4d8108
AM
11081+/* ---------------------------------------------------------------------- */
11082+
11083+static int au_do_flush_nondir(struct file *file, fl_owner_t id)
dece6358 11084+{
1308ab2a 11085+ int err;
4a4d8108
AM
11086+ struct file *h_file;
11087+
11088+ err = 0;
11089+ h_file = au_hf_top(file);
11090+ if (h_file)
11091+ err = vfsub_flush(h_file, id);
11092+ return err;
11093+}
11094+
11095+static int aufs_flush_nondir(struct file *file, fl_owner_t id)
11096+{
11097+ return au_do_flush(file, id, au_do_flush_nondir);
11098+}
11099+
11100+/* ---------------------------------------------------------------------- */
9dbd164d
AM
11101+/*
11102+ * read and write functions acquire [fdi]_rwsem once, but release before
11103+ * mmap_sem. This is because to stop a race condition between mmap(2).
11104+ * Releasing these aufs-rwsem should be safe, no branch-mamagement (by keeping
11105+ * si_rwsem), no harmful copy-up should happen. Actually copy-up may happen in
11106+ * read functions after [fdi]_rwsem are released, but it should be harmless.
11107+ */
4a4d8108
AM
11108+
11109+static ssize_t aufs_read(struct file *file, char __user *buf, size_t count,
11110+ loff_t *ppos)
11111+{
11112+ ssize_t err;
dece6358 11113+ struct dentry *dentry;
4a4d8108 11114+ struct file *h_file;
dece6358 11115+ struct super_block *sb;
1facf9fc 11116+
dece6358
AM
11117+ dentry = file->f_dentry;
11118+ sb = dentry->d_sb;
e49829fe 11119+ si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLMW);
4a4d8108 11120+ err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/0);
dece6358
AM
11121+ if (unlikely(err))
11122+ goto out;
1facf9fc 11123+
4a4d8108 11124+ h_file = au_hf_top(file);
9dbd164d
AM
11125+ get_file(h_file);
11126+ di_read_unlock(dentry, AuLock_IR);
11127+ fi_read_unlock(file);
11128+
11129+ /* filedata may be obsoleted by concurrent copyup, but no problem */
4a4d8108
AM
11130+ err = vfsub_read_u(h_file, buf, count, ppos);
11131+ /* todo: necessary? */
11132+ /* file->f_ra = h_file->f_ra; */
9dbd164d 11133+ /* update without lock, I don't think it a problem */
4a4d8108 11134+ fsstack_copy_attr_atime(dentry->d_inode, h_file->f_dentry->d_inode);
9dbd164d 11135+ fput(h_file);
1308ab2a 11136+
4f0767ce 11137+out:
dece6358
AM
11138+ si_read_unlock(sb);
11139+ return err;
11140+}
1facf9fc 11141+
e49829fe
JR
11142+/*
11143+ * todo: very ugly
11144+ * it locks both of i_mutex and si_rwsem for read in safe.
11145+ * if the plink maintenance mode continues forever (that is the problem),
11146+ * may loop forever.
11147+ */
11148+static void au_mtx_and_read_lock(struct inode *inode)
11149+{
11150+ int err;
11151+ struct super_block *sb = inode->i_sb;
11152+
11153+ while (1) {
11154+ mutex_lock(&inode->i_mutex);
11155+ err = si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLM);
11156+ if (!err)
11157+ break;
11158+ mutex_unlock(&inode->i_mutex);
11159+ si_read_lock(sb, AuLock_NOPLMW);
11160+ si_read_unlock(sb);
11161+ }
11162+}
11163+
4a4d8108
AM
11164+static ssize_t aufs_write(struct file *file, const char __user *ubuf,
11165+ size_t count, loff_t *ppos)
dece6358 11166+{
4a4d8108
AM
11167+ ssize_t err;
11168+ struct au_pin pin;
dece6358 11169+ struct dentry *dentry;
9dbd164d 11170+ struct super_block *sb;
4a4d8108 11171+ struct inode *inode;
4a4d8108
AM
11172+ struct file *h_file;
11173+ char __user *buf = (char __user *)ubuf;
1facf9fc 11174+
dece6358 11175+ dentry = file->f_dentry;
9dbd164d 11176+ sb = dentry->d_sb;
4a4d8108 11177+ inode = dentry->d_inode;
e49829fe 11178+ au_mtx_and_read_lock(inode);
1facf9fc 11179+
4a4d8108
AM
11180+ err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/1);
11181+ if (unlikely(err))
11182+ goto out;
1facf9fc 11183+
4a4d8108
AM
11184+ err = au_ready_to_write(file, -1, &pin);
11185+ di_downgrade_lock(dentry, AuLock_IR);
9dbd164d
AM
11186+ if (unlikely(err)) {
11187+ di_read_unlock(dentry, AuLock_IR);
11188+ fi_write_unlock(file);
11189+ goto out;
11190+ }
1facf9fc 11191+
4a4d8108 11192+ h_file = au_hf_top(file);
9dbd164d 11193+ get_file(h_file);
4a4d8108 11194+ au_unpin(&pin);
9dbd164d
AM
11195+ di_read_unlock(dentry, AuLock_IR);
11196+ fi_write_unlock(file);
11197+
4a4d8108 11198+ err = vfsub_write_u(h_file, buf, count, ppos);
9dbd164d 11199+ ii_write_lock_child(inode);
4a4d8108
AM
11200+ au_cpup_attr_timesizes(inode);
11201+ inode->i_mode = h_file->f_dentry->d_inode->i_mode;
9dbd164d
AM
11202+ ii_write_unlock(inode);
11203+ fput(h_file);
1facf9fc 11204+
4f0767ce 11205+out:
9dbd164d 11206+ si_read_unlock(sb);
4a4d8108 11207+ mutex_unlock(&inode->i_mutex);
dece6358
AM
11208+ return err;
11209+}
1facf9fc 11210+
4a4d8108
AM
11211+static ssize_t au_do_aio(struct file *h_file, int rw, struct kiocb *kio,
11212+ const struct iovec *iov, unsigned long nv, loff_t pos)
dece6358 11213+{
4a4d8108
AM
11214+ ssize_t err;
11215+ struct file *file;
11216+ ssize_t (*func)(struct kiocb *, const struct iovec *, unsigned long,
11217+ loff_t);
1facf9fc 11218+
4a4d8108
AM
11219+ err = security_file_permission(h_file, rw);
11220+ if (unlikely(err))
11221+ goto out;
1facf9fc 11222+
4a4d8108
AM
11223+ err = -ENOSYS;
11224+ func = NULL;
11225+ if (rw == MAY_READ)
11226+ func = h_file->f_op->aio_read;
11227+ else if (rw == MAY_WRITE)
11228+ func = h_file->f_op->aio_write;
11229+ if (func) {
11230+ file = kio->ki_filp;
11231+ kio->ki_filp = h_file;
2cbb1c4b 11232+ lockdep_off();
4a4d8108 11233+ err = func(kio, iov, nv, pos);
2cbb1c4b 11234+ lockdep_on();
4a4d8108
AM
11235+ kio->ki_filp = file;
11236+ } else
11237+ /* currently there is no such fs */
11238+ WARN_ON_ONCE(1);
1facf9fc 11239+
4f0767ce 11240+out:
dece6358
AM
11241+ return err;
11242+}
1facf9fc 11243+
4a4d8108
AM
11244+static ssize_t aufs_aio_read(struct kiocb *kio, const struct iovec *iov,
11245+ unsigned long nv, loff_t pos)
1facf9fc 11246+{
4a4d8108
AM
11247+ ssize_t err;
11248+ struct file *file, *h_file;
11249+ struct dentry *dentry;
dece6358 11250+ struct super_block *sb;
1facf9fc 11251+
4a4d8108 11252+ file = kio->ki_filp;
dece6358 11253+ dentry = file->f_dentry;
1308ab2a 11254+ sb = dentry->d_sb;
e49829fe 11255+ si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLMW);
4a4d8108
AM
11256+ err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/0);
11257+ if (unlikely(err))
11258+ goto out;
11259+
11260+ h_file = au_hf_top(file);
9dbd164d
AM
11261+ get_file(h_file);
11262+ di_read_unlock(dentry, AuLock_IR);
11263+ fi_read_unlock(file);
11264+
4a4d8108
AM
11265+ err = au_do_aio(h_file, MAY_READ, kio, iov, nv, pos);
11266+ /* todo: necessary? */
11267+ /* file->f_ra = h_file->f_ra; */
9dbd164d 11268+ /* update without lock, I don't think it a problem */
4a4d8108 11269+ fsstack_copy_attr_atime(dentry->d_inode, h_file->f_dentry->d_inode);
9dbd164d 11270+ fput(h_file);
1facf9fc 11271+
4f0767ce 11272+out:
4a4d8108 11273+ si_read_unlock(sb);
1308ab2a 11274+ return err;
11275+}
1facf9fc 11276+
4a4d8108
AM
11277+static ssize_t aufs_aio_write(struct kiocb *kio, const struct iovec *iov,
11278+ unsigned long nv, loff_t pos)
1308ab2a 11279+{
4a4d8108
AM
11280+ ssize_t err;
11281+ struct au_pin pin;
11282+ struct dentry *dentry;
11283+ struct inode *inode;
4a4d8108 11284+ struct file *file, *h_file;
9dbd164d 11285+ struct super_block *sb;
1308ab2a 11286+
4a4d8108 11287+ file = kio->ki_filp;
1308ab2a 11288+ dentry = file->f_dentry;
9dbd164d 11289+ sb = dentry->d_sb;
1308ab2a 11290+ inode = dentry->d_inode;
e49829fe
JR
11291+ au_mtx_and_read_lock(inode);
11292+
4a4d8108
AM
11293+ err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/1);
11294+ if (unlikely(err))
1308ab2a 11295+ goto out;
1facf9fc 11296+
4a4d8108
AM
11297+ err = au_ready_to_write(file, -1, &pin);
11298+ di_downgrade_lock(dentry, AuLock_IR);
9dbd164d
AM
11299+ if (unlikely(err)) {
11300+ di_read_unlock(dentry, AuLock_IR);
11301+ fi_write_unlock(file);
11302+ goto out;
11303+ }
1facf9fc 11304+
4a4d8108 11305+ h_file = au_hf_top(file);
9dbd164d
AM
11306+ get_file(h_file);
11307+ au_unpin(&pin);
11308+ di_read_unlock(dentry, AuLock_IR);
11309+ fi_write_unlock(file);
11310+
4a4d8108 11311+ err = au_do_aio(h_file, MAY_WRITE, kio, iov, nv, pos);
9dbd164d 11312+ ii_write_lock_child(inode);
4a4d8108
AM
11313+ au_cpup_attr_timesizes(inode);
11314+ inode->i_mode = h_file->f_dentry->d_inode->i_mode;
9dbd164d
AM
11315+ ii_write_unlock(inode);
11316+ fput(h_file);
1facf9fc 11317+
4f0767ce 11318+out:
9dbd164d 11319+ si_read_unlock(sb);
4a4d8108 11320+ mutex_unlock(&inode->i_mutex);
dece6358 11321+ return err;
1facf9fc 11322+}
11323+
4a4d8108
AM
11324+static ssize_t aufs_splice_read(struct file *file, loff_t *ppos,
11325+ struct pipe_inode_info *pipe, size_t len,
11326+ unsigned int flags)
1facf9fc 11327+{
4a4d8108
AM
11328+ ssize_t err;
11329+ struct file *h_file;
11330+ struct dentry *dentry;
dece6358 11331+ struct super_block *sb;
1facf9fc 11332+
dece6358 11333+ dentry = file->f_dentry;
dece6358 11334+ sb = dentry->d_sb;
e49829fe 11335+ si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLMW);
4a4d8108
AM
11336+ err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/0);
11337+ if (unlikely(err))
dece6358 11338+ goto out;
1facf9fc 11339+
4a4d8108
AM
11340+ err = -EINVAL;
11341+ h_file = au_hf_top(file);
9dbd164d 11342+ get_file(h_file);
4a4d8108 11343+ if (au_test_loopback_kthread()) {
87a755f4
AM
11344+ au_warn_loopback(h_file->f_dentry->d_sb);
11345+ if (file->f_mapping != h_file->f_mapping) {
11346+ file->f_mapping = h_file->f_mapping;
11347+ smp_mb(); /* unnecessary? */
11348+ }
1308ab2a 11349+ }
9dbd164d
AM
11350+ di_read_unlock(dentry, AuLock_IR);
11351+ fi_read_unlock(file);
11352+
4a4d8108
AM
11353+ err = vfsub_splice_to(h_file, ppos, pipe, len, flags);
11354+ /* todo: necessasry? */
11355+ /* file->f_ra = h_file->f_ra; */
9dbd164d 11356+ /* update without lock, I don't think it a problem */
4a4d8108 11357+ fsstack_copy_attr_atime(dentry->d_inode, h_file->f_dentry->d_inode);
9dbd164d 11358+ fput(h_file);
1facf9fc 11359+
4f0767ce 11360+out:
4a4d8108 11361+ si_read_unlock(sb);
dece6358 11362+ return err;
1facf9fc 11363+}
11364+
4a4d8108
AM
11365+static ssize_t
11366+aufs_splice_write(struct pipe_inode_info *pipe, struct file *file, loff_t *ppos,
11367+ size_t len, unsigned int flags)
1facf9fc 11368+{
4a4d8108
AM
11369+ ssize_t err;
11370+ struct au_pin pin;
11371+ struct dentry *dentry;
11372+ struct inode *inode;
4a4d8108 11373+ struct file *h_file;
9dbd164d 11374+ struct super_block *sb;
1facf9fc 11375+
4a4d8108 11376+ dentry = file->f_dentry;
9dbd164d 11377+ sb = dentry->d_sb;
4a4d8108 11378+ inode = dentry->d_inode;
e49829fe 11379+ au_mtx_and_read_lock(inode);
9dbd164d 11380+
4a4d8108
AM
11381+ err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/1);
11382+ if (unlikely(err))
11383+ goto out;
1facf9fc 11384+
4a4d8108
AM
11385+ err = au_ready_to_write(file, -1, &pin);
11386+ di_downgrade_lock(dentry, AuLock_IR);
9dbd164d
AM
11387+ if (unlikely(err)) {
11388+ di_read_unlock(dentry, AuLock_IR);
11389+ fi_write_unlock(file);
11390+ goto out;
11391+ }
1facf9fc 11392+
4a4d8108 11393+ h_file = au_hf_top(file);
9dbd164d 11394+ get_file(h_file);
4a4d8108 11395+ au_unpin(&pin);
9dbd164d
AM
11396+ di_read_unlock(dentry, AuLock_IR);
11397+ fi_write_unlock(file);
11398+
4a4d8108 11399+ err = vfsub_splice_from(pipe, h_file, ppos, len, flags);
9dbd164d 11400+ ii_write_lock_child(inode);
4a4d8108
AM
11401+ au_cpup_attr_timesizes(inode);
11402+ inode->i_mode = h_file->f_dentry->d_inode->i_mode;
9dbd164d
AM
11403+ ii_write_unlock(inode);
11404+ fput(h_file);
1facf9fc 11405+
4f0767ce 11406+out:
9dbd164d 11407+ si_read_unlock(sb);
4a4d8108
AM
11408+ mutex_unlock(&inode->i_mutex);
11409+ return err;
11410+}
1facf9fc 11411+
4a4d8108
AM
11412+/* ---------------------------------------------------------------------- */
11413+
9dbd164d
AM
11414+/*
11415+ * The locking order around current->mmap_sem.
11416+ * - in most and regular cases
11417+ * file I/O syscall -- aufs_read() or something
11418+ * -- si_rwsem for read -- mmap_sem
11419+ * (Note that [fdi]i_rwsem are released before mmap_sem).
11420+ * - in mmap case
11421+ * mmap(2) -- mmap_sem -- aufs_mmap() -- si_rwsem for read -- [fdi]i_rwsem
11422+ * This AB-BA order is definitly bad, but is not a problem since "si_rwsem for
11423+ * read" allows muliple processes to acquire it and [fdi]i_rwsem are not held in
11424+ * file I/O. Aufs needs to stop lockdep in aufs_mmap() though.
11425+ * It means that when aufs acquires si_rwsem for write, the process should never
11426+ * acquire mmap_sem.
11427+ *
11428+ * Actually aufs_readdir() holds [fdi]i_rwsem before mmap_sem, but this is not a
11429+ * problem either since any directory is not able to be mmap-ed.
11430+ * The similar scenario is applied to aufs_readlink() too.
11431+ */
11432+
2dfbb274
AM
11433+/* cf. linux/include/linux/mman.h: calc_vm_prot_bits() */
11434+#define AuConv_VM_PROT(f, b) _calc_vm_trans(f, VM_##b, PROT_##b)
11435+
11436+static unsigned long au_arch_prot_conv(unsigned long flags)
11437+{
11438+ /* currently ppc64 only */
11439+#ifdef CONFIG_PPC64
11440+ /* cf. linux/arch/powerpc/include/asm/mman.h */
11441+ AuDebugOn(arch_calc_vm_prot_bits(-1) != VM_SAO);
11442+ return AuConv_VM_PROT(flags, SAO);
11443+#else
11444+ AuDebugOn(arch_calc_vm_prot_bits(-1));
11445+ return 0;
11446+#endif
11447+}
11448+
11449+static unsigned long au_prot_conv(unsigned long flags)
11450+{
11451+ return AuConv_VM_PROT(flags, READ)
11452+ | AuConv_VM_PROT(flags, WRITE)
11453+ | AuConv_VM_PROT(flags, EXEC)
11454+ | au_arch_prot_conv(flags);
11455+}
11456+
11457+/* cf. linux/include/linux/mman.h: calc_vm_flag_bits() */
11458+#define AuConv_VM_MAP(f, b) _calc_vm_trans(f, VM_##b, MAP_##b)
11459+
11460+static unsigned long au_flag_conv(unsigned long flags)
11461+{
11462+ return AuConv_VM_MAP(flags, GROWSDOWN)
11463+ | AuConv_VM_MAP(flags, DENYWRITE)
11464+ | AuConv_VM_MAP(flags, EXECUTABLE)
11465+ | AuConv_VM_MAP(flags, LOCKED);
11466+}
11467+
9dbd164d 11468+static int aufs_mmap(struct file *file, struct vm_area_struct *vma)
dece6358 11469+{
4a4d8108
AM
11470+ int err;
11471+ aufs_bindex_t bstart;
11472+ const unsigned char wlock
9dbd164d 11473+ = (file->f_mode & FMODE_WRITE) && (vma->vm_flags & VM_SHARED);
4a4d8108
AM
11474+ struct dentry *dentry;
11475+ struct super_block *sb;
9dbd164d
AM
11476+ struct file *h_file;
11477+ struct au_branch *br;
11478+ struct au_pin pin;
11479+
11480+ AuDbgVmRegion(file, vma);
1308ab2a 11481+
4a4d8108
AM
11482+ dentry = file->f_dentry;
11483+ sb = dentry->d_sb;
9dbd164d 11484+ lockdep_off();
e49829fe 11485+ si_read_lock(sb, AuLock_NOPLMW);
4a4d8108
AM
11486+ err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/1);
11487+ if (unlikely(err))
11488+ goto out;
11489+
4a4d8108 11490+ if (wlock) {
4a4d8108
AM
11491+ err = au_ready_to_write(file, -1, &pin);
11492+ di_write_unlock(dentry);
9dbd164d
AM
11493+ if (unlikely(err)) {
11494+ fi_write_unlock(file);
11495+ goto out;
11496+ }
4a4d8108
AM
11497+ au_unpin(&pin);
11498+ } else
11499+ di_write_unlock(dentry);
9dbd164d 11500+
4a4d8108 11501+ bstart = au_fbstart(file);
9dbd164d
AM
11502+ br = au_sbr(sb, bstart);
11503+ h_file = au_hf_top(file);
11504+ get_file(h_file);
2cbb1c4b 11505+ au_set_mmapped(file);
4a4d8108 11506+ fi_write_unlock(file);
9dbd164d 11507+ lockdep_on();
1308ab2a 11508+
9dbd164d 11509+ au_vm_file_reset(vma, h_file);
2dfbb274
AM
11510+ err = security_mmap_file(h_file, au_prot_conv(vma->vm_flags),
11511+ au_flag_conv(vma->vm_flags));
9dbd164d
AM
11512+ if (!err)
11513+ err = h_file->f_op->mmap(h_file, vma);
2cbb1c4b
JR
11514+ if (unlikely(err))
11515+ goto out_reset;
4a4d8108 11516+
2cbb1c4b 11517+ au_vm_prfile_set(vma, file);
4a4d8108 11518+ /* update without lock, I don't think it a problem */
2cbb1c4b 11519+ fsstack_copy_attr_atime(file->f_dentry->d_inode,
9dbd164d 11520+ h_file->f_dentry->d_inode);
2cbb1c4b 11521+ goto out_fput; /* success */
4a4d8108 11522+
2cbb1c4b
JR
11523+out_reset:
11524+ au_unset_mmapped(file);
11525+ au_vm_file_reset(vma, file);
11526+out_fput:
9dbd164d
AM
11527+ fput(h_file);
11528+ lockdep_off();
4f0767ce 11529+out:
9dbd164d
AM
11530+ si_read_unlock(sb);
11531+ lockdep_on();
11532+ AuTraceErr(err);
4a4d8108
AM
11533+ return err;
11534+}
11535+
11536+/* ---------------------------------------------------------------------- */
11537+
1e00d052
AM
11538+static int aufs_fsync_nondir(struct file *file, loff_t start, loff_t end,
11539+ int datasync)
4a4d8108
AM
11540+{
11541+ int err;
11542+ struct au_pin pin;
b752ccd1 11543+ struct dentry *dentry;
4a4d8108
AM
11544+ struct inode *inode;
11545+ struct file *h_file;
11546+ struct super_block *sb;
11547+
b752ccd1 11548+ dentry = file->f_dentry;
4a4d8108 11549+ inode = dentry->d_inode;
4a4d8108 11550+ sb = dentry->d_sb;
1e00d052 11551+ mutex_lock(&inode->i_mutex);
e49829fe
JR
11552+ err = si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLM);
11553+ if (unlikely(err))
11554+ goto out;
4a4d8108
AM
11555+
11556+ err = 0; /* -EBADF; */ /* posix? */
11557+ if (unlikely(!(file->f_mode & FMODE_WRITE)))
e49829fe 11558+ goto out_si;
4a4d8108
AM
11559+ err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/1);
11560+ if (unlikely(err))
e49829fe 11561+ goto out_si;
4a4d8108
AM
11562+
11563+ err = au_ready_to_write(file, -1, &pin);
11564+ di_downgrade_lock(dentry, AuLock_IR);
11565+ if (unlikely(err))
11566+ goto out_unlock;
11567+ au_unpin(&pin);
11568+
11569+ err = -EINVAL;
11570+ h_file = au_hf_top(file);
53392da6
AM
11571+ err = vfsub_fsync(h_file, &h_file->f_path, datasync);
11572+ au_cpup_attr_timesizes(inode);
4a4d8108 11573+
4f0767ce 11574+out_unlock:
4a4d8108 11575+ di_read_unlock(dentry, AuLock_IR);
1308ab2a 11576+ fi_write_unlock(file);
e49829fe 11577+out_si:
953406b4 11578+ si_read_unlock(sb);
e49829fe 11579+out:
1e00d052 11580+ mutex_unlock(&inode->i_mutex);
4a4d8108 11581+ return err;
dece6358
AM
11582+}
11583+
4a4d8108
AM
11584+/* no one supports this operation, currently */
11585+#if 0
11586+static int aufs_aio_fsync_nondir(struct kiocb *kio, int datasync)
dece6358 11587+{
4a4d8108
AM
11588+ int err;
11589+ struct au_pin pin;
1308ab2a 11590+ struct dentry *dentry;
4a4d8108
AM
11591+ struct inode *inode;
11592+ struct file *file, *h_file;
1308ab2a 11593+
4a4d8108 11594+ file = kio->ki_filp;
1308ab2a 11595+ dentry = file->f_dentry;
4a4d8108 11596+ inode = dentry->d_inode;
e49829fe 11597+ au_mtx_and_read_lock(inode);
4a4d8108
AM
11598+
11599+ err = 0; /* -EBADF; */ /* posix? */
11600+ if (unlikely(!(file->f_mode & FMODE_WRITE)))
11601+ goto out;
11602+ err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/1);
11603+ if (unlikely(err))
1308ab2a 11604+ goto out;
11605+
4a4d8108
AM
11606+ err = au_ready_to_write(file, -1, &pin);
11607+ di_downgrade_lock(dentry, AuLock_IR);
11608+ if (unlikely(err))
11609+ goto out_unlock;
11610+ au_unpin(&pin);
1308ab2a 11611+
4a4d8108
AM
11612+ err = -ENOSYS;
11613+ h_file = au_hf_top(file);
11614+ if (h_file->f_op && h_file->f_op->aio_fsync) {
11615+ struct dentry *h_d;
11616+ struct mutex *h_mtx;
1308ab2a 11617+
4a4d8108
AM
11618+ h_d = h_file->f_dentry;
11619+ h_mtx = &h_d->d_inode->i_mutex;
11620+ if (!is_sync_kiocb(kio)) {
11621+ get_file(h_file);
11622+ fput(file);
11623+ }
11624+ kio->ki_filp = h_file;
11625+ err = h_file->f_op->aio_fsync(kio, datasync);
11626+ mutex_lock_nested(h_mtx, AuLsc_I_CHILD);
11627+ if (!err)
11628+ vfsub_update_h_iattr(&h_file->f_path, /*did*/NULL);
11629+ /*ignore*/
11630+ au_cpup_attr_timesizes(inode);
11631+ mutex_unlock(h_mtx);
11632+ }
1308ab2a 11633+
4f0767ce 11634+out_unlock:
4a4d8108
AM
11635+ di_read_unlock(dentry, AuLock_IR);
11636+ fi_write_unlock(file);
4f0767ce 11637+out:
e49829fe 11638+ si_read_unlock(inode->sb);
4a4d8108
AM
11639+ mutex_unlock(&inode->i_mutex);
11640+ return err;
dece6358 11641+}
4a4d8108 11642+#endif
dece6358 11643+
4a4d8108 11644+static int aufs_fasync(int fd, struct file *file, int flag)
dece6358 11645+{
4a4d8108
AM
11646+ int err;
11647+ struct file *h_file;
11648+ struct dentry *dentry;
11649+ struct super_block *sb;
1308ab2a 11650+
4a4d8108
AM
11651+ dentry = file->f_dentry;
11652+ sb = dentry->d_sb;
e49829fe 11653+ si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLMW);
4a4d8108
AM
11654+ err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/0);
11655+ if (unlikely(err))
11656+ goto out;
11657+
11658+ h_file = au_hf_top(file);
11659+ if (h_file->f_op && h_file->f_op->fasync)
11660+ err = h_file->f_op->fasync(fd, h_file, flag);
11661+
11662+ di_read_unlock(dentry, AuLock_IR);
11663+ fi_read_unlock(file);
1308ab2a 11664+
4f0767ce 11665+out:
4a4d8108 11666+ si_read_unlock(sb);
1308ab2a 11667+ return err;
dece6358 11668+}
4a4d8108
AM
11669+
11670+/* ---------------------------------------------------------------------- */
11671+
11672+/* no one supports this operation, currently */
11673+#if 0
11674+static ssize_t aufs_sendpage(struct file *file, struct page *page, int offset,
11675+ size_t len, loff_t *pos , int more)
11676+{
11677+}
11678+#endif
11679+
11680+/* ---------------------------------------------------------------------- */
11681+
11682+const struct file_operations aufs_file_fop = {
11683+ .owner = THIS_MODULE,
2cbb1c4b 11684+
027c5e7a 11685+ .llseek = default_llseek,
4a4d8108
AM
11686+
11687+ .read = aufs_read,
11688+ .write = aufs_write,
11689+ .aio_read = aufs_aio_read,
11690+ .aio_write = aufs_aio_write,
11691+#ifdef CONFIG_AUFS_POLL
11692+ .poll = aufs_poll,
11693+#endif
11694+ .unlocked_ioctl = aufs_ioctl_nondir,
b752ccd1
AM
11695+#ifdef CONFIG_COMPAT
11696+ .compat_ioctl = aufs_ioctl_nondir, /* same */
11697+#endif
4a4d8108
AM
11698+ .mmap = aufs_mmap,
11699+ .open = aufs_open_nondir,
11700+ .flush = aufs_flush_nondir,
11701+ .release = aufs_release_nondir,
11702+ .fsync = aufs_fsync_nondir,
11703+ /* .aio_fsync = aufs_aio_fsync_nondir, */
11704+ .fasync = aufs_fasync,
11705+ /* .sendpage = aufs_sendpage, */
11706+ .splice_write = aufs_splice_write,
11707+ .splice_read = aufs_splice_read,
11708+#if 0
11709+ .aio_splice_write = aufs_aio_splice_write,
11710+ .aio_splice_read = aufs_aio_splice_read
11711+#endif
11712+};
7f207e10
AM
11713diff -urN /usr/share/empty/fs/aufs/f_op_sp.c linux/fs/aufs/f_op_sp.c
11714--- /usr/share/empty/fs/aufs/f_op_sp.c 1970-01-01 01:00:00.000000000 +0100
2dfbb274 11715+++ linux/fs/aufs/f_op_sp.c 2012-08-26 08:39:00.760508065 +0200
0c3ec466 11716@@ -0,0 +1,295 @@
1308ab2a 11717+/*
f6c5ef8b 11718+ * Copyright (C) 2005-2012 Junjiro R. Okajima
1308ab2a 11719+ *
11720+ * This program, aufs is free software; you can redistribute it and/or modify
11721+ * it under the terms of the GNU General Public License as published by
11722+ * the Free Software Foundation; either version 2 of the License, or
11723+ * (at your option) any later version.
11724+ *
11725+ * This program is distributed in the hope that it will be useful,
11726+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
11727+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11728+ * GNU General Public License for more details.
11729+ *
11730+ * You should have received a copy of the GNU General Public License
11731+ * along with this program; if not, write to the Free Software
11732+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
11733+ */
dece6358 11734+
1308ab2a 11735+/*
4a4d8108
AM
11736+ * file operations for special files.
11737+ * while they exist in aufs virtually,
11738+ * their file I/O is handled out of aufs.
1308ab2a 11739+ */
11740+
4a4d8108 11741+#include "aufs.h"
1308ab2a 11742+
4a4d8108
AM
11743+static ssize_t aufs_aio_read_sp(struct kiocb *kio, const struct iovec *iov,
11744+ unsigned long nv, loff_t pos)
dece6358 11745+{
4a4d8108
AM
11746+ ssize_t err;
11747+ aufs_bindex_t bstart;
11748+ unsigned char wbr;
11749+ struct file *file, *h_file;
11750+ struct super_block *sb;
1308ab2a 11751+
4a4d8108
AM
11752+ file = kio->ki_filp;
11753+ sb = file->f_dentry->d_sb;
11754+ si_read_lock(sb, AuLock_FLUSH);
11755+ fi_read_lock(file);
11756+ bstart = au_fbstart(file);
11757+ h_file = au_hf_top(file);
11758+ fi_read_unlock(file);
11759+ wbr = !!au_br_writable(au_sbr(sb, bstart)->br_perm);
11760+ si_read_unlock(sb);
11761+
11762+ /* do not change the file in kio */
11763+ AuDebugOn(!h_file->f_op || !h_file->f_op->aio_read);
11764+ err = h_file->f_op->aio_read(kio, iov, nv, pos);
11765+ if (err > 0 && wbr)
11766+ file_accessed(h_file);
11767+
11768+ return err;
11769+}
11770+
11771+static ssize_t aufs_aio_write_sp(struct kiocb *kio, const struct iovec *iov,
11772+ unsigned long nv, loff_t pos)
11773+{
11774+ ssize_t err;
11775+ aufs_bindex_t bstart;
11776+ unsigned char wbr;
11777+ struct super_block *sb;
11778+ struct file *file, *h_file;
11779+
11780+ file = kio->ki_filp;
11781+ sb = file->f_dentry->d_sb;
11782+ si_read_lock(sb, AuLock_FLUSH);
11783+ fi_read_lock(file);
11784+ bstart = au_fbstart(file);
11785+ h_file = au_hf_top(file);
11786+ fi_read_unlock(file);
11787+ wbr = !!au_br_writable(au_sbr(sb, bstart)->br_perm);
11788+ si_read_unlock(sb);
11789+
11790+ /* do not change the file in kio */
11791+ AuDebugOn(!h_file->f_op || !h_file->f_op->aio_write);
11792+ err = h_file->f_op->aio_write(kio, iov, nv, pos);
4a4d8108
AM
11793+ return err;
11794+}
11795+
11796+/* ---------------------------------------------------------------------- */
11797+
11798+static int aufs_release_sp(struct inode *inode, struct file *file)
11799+{
11800+ int err;
11801+ struct file *h_file;
11802+
11803+ fi_read_lock(file);
11804+ h_file = au_hf_top(file);
11805+ fi_read_unlock(file);
11806+ /* close this fifo in aufs */
11807+ err = h_file->f_op->release(inode, file); /* ignore */
11808+ aufs_release_nondir(inode, file); /* ignore */
11809+ return err;
11810+}
11811+
11812+/* ---------------------------------------------------------------------- */
11813+
11814+/* currently, support only FIFO */
4f0767ce
JR
11815+enum {
11816+ AuSp_FIFO, AuSp_FIFO_R, AuSp_FIFO_W, AuSp_FIFO_RW,
11817+ /* AuSp_SOCK, AuSp_CHR, AuSp_BLK, */
11818+ AuSp_Last
11819+};
4a4d8108
AM
11820+static int aufs_open_sp(struct inode *inode, struct file *file);
11821+static struct au_sp_fop {
11822+ int done;
11823+ struct file_operations fop; /* not 'const' */
11824+ spinlock_t spin;
11825+} au_sp_fop[AuSp_Last] = {
11826+ [AuSp_FIFO] = {
11827+ .fop = {
11828+ .owner = THIS_MODULE,
11829+ .open = aufs_open_sp
11830+ }
11831+ }
11832+};
11833+
11834+static void au_init_fop_sp(struct file *file)
11835+{
11836+ struct au_sp_fop *p;
11837+ int i;
11838+ struct file *h_file;
11839+
11840+ p = au_sp_fop;
11841+ if (unlikely(!p->done)) {
11842+ /* initialize first time only */
11843+ static DEFINE_SPINLOCK(spin);
11844+
11845+ spin_lock(&spin);
11846+ if (!p->done) {
11847+ BUILD_BUG_ON(sizeof(au_sp_fop)/sizeof(*au_sp_fop)
11848+ != AuSp_Last);
11849+ for (i = 0; i < AuSp_Last; i++)
11850+ spin_lock_init(&p[i].spin);
11851+ p->done = 1;
11852+ }
11853+ spin_unlock(&spin);
11854+ }
11855+
11856+ switch (file->f_mode & (FMODE_READ | FMODE_WRITE)) {
11857+ case FMODE_READ:
11858+ i = AuSp_FIFO_R;
11859+ break;
11860+ case FMODE_WRITE:
11861+ i = AuSp_FIFO_W;
11862+ break;
11863+ case FMODE_READ | FMODE_WRITE:
11864+ i = AuSp_FIFO_RW;
11865+ break;
11866+ default:
11867+ BUG();
11868+ }
11869+
11870+ p += i;
11871+ if (unlikely(!p->done)) {
11872+ /* initialize first time only */
11873+ h_file = au_hf_top(file);
11874+ spin_lock(&p->spin);
11875+ if (!p->done) {
11876+ p->fop = *h_file->f_op;
11877+ p->fop.owner = THIS_MODULE;
11878+ if (p->fop.aio_read)
11879+ p->fop.aio_read = aufs_aio_read_sp;
11880+ if (p->fop.aio_write)
11881+ p->fop.aio_write = aufs_aio_write_sp;
11882+ p->fop.release = aufs_release_sp;
11883+ p->done = 1;
11884+ }
11885+ spin_unlock(&p->spin);
11886+ }
11887+ file->f_op = &p->fop;
11888+}
11889+
11890+static int au_cpup_sp(struct dentry *dentry)
11891+{
11892+ int err;
11893+ aufs_bindex_t bcpup;
11894+ struct au_pin pin;
11895+ struct au_wr_dir_args wr_dir_args = {
11896+ .force_btgt = -1,
11897+ .flags = 0
11898+ };
11899+
11900+ AuDbg("%.*s\n", AuDLNPair(dentry));
11901+
11902+ di_read_unlock(dentry, AuLock_IR);
11903+ di_write_lock_child(dentry);
11904+ err = au_wr_dir(dentry, /*src_dentry*/NULL, &wr_dir_args);
11905+ if (unlikely(err < 0))
11906+ goto out;
11907+ bcpup = err;
11908+ err = 0;
11909+ if (bcpup == au_dbstart(dentry))
11910+ goto out; /* success */
11911+
11912+ err = au_pin(&pin, dentry, bcpup, au_opt_udba(dentry->d_sb),
11913+ AuPin_MNT_WRITE);
11914+ if (!err) {
11915+ err = au_sio_cpup_simple(dentry, bcpup, -1, AuCpup_DTIME);
11916+ au_unpin(&pin);
11917+ }
11918+
4f0767ce 11919+out:
4a4d8108
AM
11920+ di_downgrade_lock(dentry, AuLock_IR);
11921+ return err;
11922+}
11923+
11924+static int au_do_open_sp(struct file *file, int flags)
11925+{
11926+ int err;
11927+ struct dentry *dentry;
11928+ struct super_block *sb;
11929+ struct file *h_file;
11930+ struct inode *h_inode;
11931+
11932+ dentry = file->f_dentry;
11933+ AuDbg("%.*s\n", AuDLNPair(dentry));
11934+
11935+ /*
11936+ * try copying-up.
11937+ * operate on the ro branch is not an error.
11938+ */
11939+ au_cpup_sp(dentry); /* ignore */
11940+
11941+ /* prepare h_file */
11942+ err = au_do_open_nondir(file, vfsub_file_flags(file));
11943+ if (unlikely(err))
11944+ goto out;
11945+
11946+ sb = dentry->d_sb;
11947+ h_file = au_hf_top(file);
11948+ h_inode = h_file->f_dentry->d_inode;
11949+ di_read_unlock(dentry, AuLock_IR);
11950+ fi_write_unlock(file);
11951+ si_read_unlock(sb);
11952+ /* open this fifo in aufs */
11953+ err = h_inode->i_fop->open(file->f_dentry->d_inode, file);
11954+ si_noflush_read_lock(sb);
11955+ fi_write_lock(file);
11956+ di_read_lock_child(dentry, AuLock_IR);
11957+ if (!err)
11958+ au_init_fop_sp(file);
4a4d8108 11959+
4f0767ce 11960+out:
4a4d8108
AM
11961+ return err;
11962+}
11963+
11964+static int aufs_open_sp(struct inode *inode, struct file *file)
11965+{
11966+ int err;
11967+ struct super_block *sb;
11968+
11969+ sb = file->f_dentry->d_sb;
11970+ si_read_lock(sb, AuLock_FLUSH);
11971+ err = au_do_open(file, au_do_open_sp, /*fidir*/NULL);
11972+ si_read_unlock(sb);
11973+ return err;
11974+}
11975+
11976+/* ---------------------------------------------------------------------- */
11977+
11978+void au_init_special_fop(struct inode *inode, umode_t mode, dev_t rdev)
11979+{
11980+ init_special_inode(inode, mode, rdev);
11981+
11982+ switch (mode & S_IFMT) {
11983+ case S_IFIFO:
11984+ inode->i_fop = &au_sp_fop[AuSp_FIFO].fop;
11985+ /*FALLTHROUGH*/
11986+ case S_IFCHR:
11987+ case S_IFBLK:
11988+ case S_IFSOCK:
11989+ break;
11990+ default:
11991+ AuDebugOn(1);
11992+ }
11993+}
11994+
11995+int au_special_file(umode_t mode)
11996+{
11997+ int ret;
11998+
11999+ ret = 0;
12000+ switch (mode & S_IFMT) {
12001+ case S_IFIFO:
12002+#if 0
12003+ case S_IFCHR:
12004+ case S_IFBLK:
12005+ case S_IFSOCK:
12006+#endif
12007+ ret = 1;
12008+ }
12009+
12010+ return ret;
12011+}
7f207e10
AM
12012diff -urN /usr/share/empty/fs/aufs/fstype.h linux/fs/aufs/fstype.h
12013--- /usr/share/empty/fs/aufs/fstype.h 1970-01-01 01:00:00.000000000 +0100
b4510431
AM
12014+++ linux/fs/aufs/fstype.h 2012-10-17 10:31:01.772481151 +0200
12015@@ -0,0 +1,481 @@
4a4d8108 12016+/*
f6c5ef8b 12017+ * Copyright (C) 2005-2012 Junjiro R. Okajima
4a4d8108
AM
12018+ *
12019+ * This program, aufs is free software; you can redistribute it and/or modify
12020+ * it under the terms of the GNU General Public License as published by
12021+ * the Free Software Foundation; either version 2 of the License, or
12022+ * (at your option) any later version.
12023+ *
12024+ * This program is distributed in the hope that it will be useful,
12025+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
12026+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12027+ * GNU General Public License for more details.
12028+ *
12029+ * You should have received a copy of the GNU General Public License
12030+ * along with this program; if not, write to the Free Software
12031+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
12032+ */
12033+
12034+/*
12035+ * judging filesystem type
12036+ */
12037+
12038+#ifndef __AUFS_FSTYPE_H__
12039+#define __AUFS_FSTYPE_H__
12040+
12041+#ifdef __KERNEL__
12042+
12043+#include <linux/fs.h>
12044+#include <linux/magic.h>
12045+#include <linux/romfs_fs.h>
4a4d8108
AM
12046+
12047+static inline int au_test_aufs(struct super_block *sb)
12048+{
12049+ return sb->s_magic == AUFS_SUPER_MAGIC;
12050+}
12051+
12052+static inline const char *au_sbtype(struct super_block *sb)
12053+{
12054+ return sb->s_type->name;
12055+}
1308ab2a 12056+
12057+static inline int au_test_iso9660(struct super_block *sb __maybe_unused)
12058+{
12059+#if defined(CONFIG_ROMFS_FS) || defined(CONFIG_ROMFS_FS_MODULE)
12060+ return sb->s_magic == ROMFS_MAGIC;
dece6358
AM
12061+#else
12062+ return 0;
12063+#endif
12064+}
12065+
1308ab2a 12066+static inline int au_test_romfs(struct super_block *sb __maybe_unused)
dece6358 12067+{
1308ab2a 12068+#if defined(CONFIG_ISO9660_FS) || defined(CONFIG_ISO9660_FS_MODULE)
12069+ return sb->s_magic == ISOFS_SUPER_MAGIC;
dece6358
AM
12070+#else
12071+ return 0;
12072+#endif
12073+}
12074+
1308ab2a 12075+static inline int au_test_cramfs(struct super_block *sb __maybe_unused)
dece6358 12076+{
1308ab2a 12077+#if defined(CONFIG_CRAMFS) || defined(CONFIG_CRAMFS_MODULE)
12078+ return sb->s_magic == CRAMFS_MAGIC;
12079+#endif
12080+ return 0;
12081+}
12082+
12083+static inline int au_test_nfs(struct super_block *sb __maybe_unused)
12084+{
12085+#if defined(CONFIG_NFS_FS) || defined(CONFIG_NFS_FS_MODULE)
12086+ return sb->s_magic == NFS_SUPER_MAGIC;
dece6358
AM
12087+#else
12088+ return 0;
12089+#endif
12090+}
12091+
1308ab2a 12092+static inline int au_test_fuse(struct super_block *sb __maybe_unused)
dece6358 12093+{
1308ab2a 12094+#if defined(CONFIG_FUSE_FS) || defined(CONFIG_FUSE_FS_MODULE)
12095+ return sb->s_magic == FUSE_SUPER_MAGIC;
dece6358
AM
12096+#else
12097+ return 0;
12098+#endif
12099+}
12100+
1308ab2a 12101+static inline int au_test_xfs(struct super_block *sb __maybe_unused)
dece6358 12102+{
1308ab2a 12103+#if defined(CONFIG_XFS_FS) || defined(CONFIG_XFS_FS_MODULE)
12104+ return sb->s_magic == XFS_SB_MAGIC;
dece6358
AM
12105+#else
12106+ return 0;
12107+#endif
12108+}
12109+
1308ab2a 12110+static inline int au_test_tmpfs(struct super_block *sb __maybe_unused)
dece6358 12111+{
1308ab2a 12112+#ifdef CONFIG_TMPFS
12113+ return sb->s_magic == TMPFS_MAGIC;
12114+#else
12115+ return 0;
dece6358 12116+#endif
dece6358
AM
12117+}
12118+
1308ab2a 12119+static inline int au_test_ecryptfs(struct super_block *sb __maybe_unused)
1facf9fc 12120+{
1308ab2a 12121+#if defined(CONFIG_ECRYPT_FS) || defined(CONFIG_ECRYPT_FS_MODULE)
12122+ return !strcmp(au_sbtype(sb), "ecryptfs");
12123+#else
12124+ return 0;
12125+#endif
1facf9fc 12126+}
12127+
1308ab2a 12128+static inline int au_test_smbfs(struct super_block *sb __maybe_unused)
1facf9fc 12129+{
1308ab2a 12130+#if defined(CONFIG_SMB_FS) || defined(CONFIG_SMB_FS_MODULE)
12131+ return sb->s_magic == SMB_SUPER_MAGIC;
12132+#else
12133+ return 0;
1facf9fc 12134+#endif
1facf9fc 12135+}
12136+
1308ab2a 12137+static inline int au_test_ocfs2(struct super_block *sb __maybe_unused)
1facf9fc 12138+{
1308ab2a 12139+#if defined(CONFIG_OCFS2_FS) || defined(CONFIG_OCFS2_FS_MODULE)
12140+ return sb->s_magic == OCFS2_SUPER_MAGIC;
12141+#else
12142+ return 0;
12143+#endif
1facf9fc 12144+}
12145+
1308ab2a 12146+static inline int au_test_ocfs2_dlmfs(struct super_block *sb __maybe_unused)
1facf9fc 12147+{
1308ab2a 12148+#if defined(CONFIG_OCFS2_FS_O2CB) || defined(CONFIG_OCFS2_FS_O2CB_MODULE)
12149+ return sb->s_magic == DLMFS_MAGIC;
12150+#else
12151+ return 0;
12152+#endif
1facf9fc 12153+}
12154+
1308ab2a 12155+static inline int au_test_coda(struct super_block *sb __maybe_unused)
1facf9fc 12156+{
1308ab2a 12157+#if defined(CONFIG_CODA_FS) || defined(CONFIG_CODA_FS_MODULE)
12158+ return sb->s_magic == CODA_SUPER_MAGIC;
12159+#else
12160+ return 0;
12161+#endif
12162+}
12163+
12164+static inline int au_test_v9fs(struct super_block *sb __maybe_unused)
12165+{
12166+#if defined(CONFIG_9P_FS) || defined(CONFIG_9P_FS_MODULE)
12167+ return sb->s_magic == V9FS_MAGIC;
12168+#else
12169+ return 0;
12170+#endif
12171+}
12172+
12173+static inline int au_test_ext4(struct super_block *sb __maybe_unused)
12174+{
12175+#if defined(CONFIG_EXT4DEV_FS) || defined(CONFIG_EXT4DEV_FS_MODULE)
12176+ return sb->s_magic == EXT4_SUPER_MAGIC;
12177+#else
12178+ return 0;
12179+#endif
12180+}
12181+
12182+static inline int au_test_sysv(struct super_block *sb __maybe_unused)
12183+{
12184+#if defined(CONFIG_SYSV_FS) || defined(CONFIG_SYSV_FS_MODULE)
12185+ return !strcmp(au_sbtype(sb), "sysv");
12186+#else
12187+ return 0;
12188+#endif
12189+}
12190+
12191+static inline int au_test_ramfs(struct super_block *sb)
12192+{
12193+ return sb->s_magic == RAMFS_MAGIC;
12194+}
12195+
12196+static inline int au_test_ubifs(struct super_block *sb __maybe_unused)
12197+{
12198+#if defined(CONFIG_UBIFS_FS) || defined(CONFIG_UBIFS_FS_MODULE)
12199+ return sb->s_magic == UBIFS_SUPER_MAGIC;
12200+#else
12201+ return 0;
12202+#endif
12203+}
12204+
12205+static inline int au_test_procfs(struct super_block *sb __maybe_unused)
12206+{
12207+#ifdef CONFIG_PROC_FS
12208+ return sb->s_magic == PROC_SUPER_MAGIC;
12209+#else
12210+ return 0;
12211+#endif
12212+}
12213+
12214+static inline int au_test_sysfs(struct super_block *sb __maybe_unused)
12215+{
12216+#ifdef CONFIG_SYSFS
12217+ return sb->s_magic == SYSFS_MAGIC;
12218+#else
12219+ return 0;
12220+#endif
12221+}
12222+
12223+static inline int au_test_configfs(struct super_block *sb __maybe_unused)
12224+{
12225+#if defined(CONFIG_CONFIGFS_FS) || defined(CONFIG_CONFIGFS_FS_MODULE)
12226+ return sb->s_magic == CONFIGFS_MAGIC;
12227+#else
12228+ return 0;
12229+#endif
12230+}
12231+
12232+static inline int au_test_minix(struct super_block *sb __maybe_unused)
12233+{
12234+#if defined(CONFIG_MINIX_FS) || defined(CONFIG_MINIX_FS_MODULE)
12235+ return sb->s_magic == MINIX3_SUPER_MAGIC
12236+ || sb->s_magic == MINIX2_SUPER_MAGIC
12237+ || sb->s_magic == MINIX2_SUPER_MAGIC2
12238+ || sb->s_magic == MINIX_SUPER_MAGIC
12239+ || sb->s_magic == MINIX_SUPER_MAGIC2;
12240+#else
12241+ return 0;
12242+#endif
12243+}
12244+
12245+static inline int au_test_cifs(struct super_block *sb __maybe_unused)
12246+{
12247+#if defined(CONFIG_CIFS_FS) || defined(CONFIGCIFS_FS_MODULE)
12248+ return sb->s_magic == CIFS_MAGIC_NUMBER;
12249+#else
12250+ return 0;
12251+#endif
12252+}
12253+
12254+static inline int au_test_fat(struct super_block *sb __maybe_unused)
12255+{
12256+#if defined(CONFIG_FAT_FS) || defined(CONFIG_FAT_FS_MODULE)
12257+ return sb->s_magic == MSDOS_SUPER_MAGIC;
12258+#else
12259+ return 0;
12260+#endif
12261+}
12262+
12263+static inline int au_test_msdos(struct super_block *sb)
12264+{
12265+ return au_test_fat(sb);
12266+}
12267+
12268+static inline int au_test_vfat(struct super_block *sb)
12269+{
12270+ return au_test_fat(sb);
12271+}
12272+
12273+static inline int au_test_securityfs(struct super_block *sb __maybe_unused)
12274+{
12275+#ifdef CONFIG_SECURITYFS
12276+ return sb->s_magic == SECURITYFS_MAGIC;
12277+#else
12278+ return 0;
12279+#endif
12280+}
12281+
12282+static inline int au_test_squashfs(struct super_block *sb __maybe_unused)
12283+{
12284+#if defined(CONFIG_SQUASHFS) || defined(CONFIG_SQUASHFS_MODULE)
12285+ return sb->s_magic == SQUASHFS_MAGIC;
12286+#else
12287+ return 0;
12288+#endif
12289+}
12290+
12291+static inline int au_test_btrfs(struct super_block *sb __maybe_unused)
12292+{
12293+#if defined(CONFIG_BTRFS_FS) || defined(CONFIG_BTRFS_FS_MODULE)
12294+ return sb->s_magic == BTRFS_SUPER_MAGIC;
12295+#else
12296+ return 0;
12297+#endif
12298+}
12299+
12300+static inline int au_test_xenfs(struct super_block *sb __maybe_unused)
12301+{
12302+#if defined(CONFIG_XENFS) || defined(CONFIG_XENFS_MODULE)
12303+ return sb->s_magic == XENFS_SUPER_MAGIC;
12304+#else
12305+ return 0;
12306+#endif
12307+}
12308+
12309+static inline int au_test_debugfs(struct super_block *sb __maybe_unused)
12310+{
12311+#ifdef CONFIG_DEBUG_FS
12312+ return sb->s_magic == DEBUGFS_MAGIC;
12313+#else
12314+ return 0;
12315+#endif
12316+}
12317+
12318+static inline int au_test_nilfs(struct super_block *sb __maybe_unused)
12319+{
12320+#if defined(CONFIG_NILFS) || defined(CONFIG_NILFS_MODULE)
12321+ return sb->s_magic == NILFS_SUPER_MAGIC;
12322+#else
12323+ return 0;
12324+#endif
12325+}
12326+
4a4d8108
AM
12327+static inline int au_test_hfsplus(struct super_block *sb __maybe_unused)
12328+{
12329+#if defined(CONFIG_HFSPLUS_FS) || defined(CONFIG_HFSPLUS_FS_MODULE)
12330+ return sb->s_magic == HFSPLUS_SUPER_MAGIC;
12331+#else
12332+ return 0;
12333+#endif
12334+}
12335+
1308ab2a 12336+/* ---------------------------------------------------------------------- */
12337+/*
12338+ * they can't be an aufs branch.
12339+ */
12340+static inline int au_test_fs_unsuppoted(struct super_block *sb)
12341+{
12342+ return
12343+#ifndef CONFIG_AUFS_BR_RAMFS
12344+ au_test_ramfs(sb) ||
12345+#endif
12346+ au_test_procfs(sb)
12347+ || au_test_sysfs(sb)
12348+ || au_test_configfs(sb)
12349+ || au_test_debugfs(sb)
12350+ || au_test_securityfs(sb)
12351+ || au_test_xenfs(sb)
12352+ || au_test_ecryptfs(sb)
12353+ /* || !strcmp(au_sbtype(sb), "unionfs") */
12354+ || au_test_aufs(sb); /* will be supported in next version */
12355+}
12356+
1308ab2a 12357+static inline int au_test_fs_remote(struct super_block *sb)
12358+{
12359+ return !au_test_tmpfs(sb)
12360+#ifdef CONFIG_AUFS_BR_RAMFS
12361+ && !au_test_ramfs(sb)
12362+#endif
12363+ && !(sb->s_type->fs_flags & FS_REQUIRES_DEV);
12364+}
12365+
12366+/* ---------------------------------------------------------------------- */
12367+
12368+/*
12369+ * Note: these functions (below) are created after reading ->getattr() in all
12370+ * filesystems under linux/fs. it means we have to do so in every update...
12371+ */
12372+
12373+/*
12374+ * some filesystems require getattr to refresh the inode attributes before
12375+ * referencing.
12376+ * in most cases, we can rely on the inode attribute in NFS (or every remote fs)
12377+ * and leave the work for d_revalidate()
12378+ */
12379+static inline int au_test_fs_refresh_iattr(struct super_block *sb)
12380+{
12381+ return au_test_nfs(sb)
12382+ || au_test_fuse(sb)
12383+ /* || au_test_smbfs(sb) */ /* untested */
12384+ /* || au_test_ocfs2(sb) */ /* untested */
12385+ /* || au_test_btrfs(sb) */ /* untested */
12386+ /* || au_test_coda(sb) */ /* untested */
12387+ /* || au_test_v9fs(sb) */ /* untested */
12388+ ;
12389+}
12390+
12391+/*
12392+ * filesystems which don't maintain i_size or i_blocks.
12393+ */
12394+static inline int au_test_fs_bad_iattr_size(struct super_block *sb)
12395+{
12396+ return au_test_xfs(sb)
4a4d8108
AM
12397+ || au_test_btrfs(sb)
12398+ || au_test_ubifs(sb)
12399+ || au_test_hfsplus(sb) /* maintained, but incorrect */
1308ab2a 12400+ /* || au_test_ext4(sb) */ /* untested */
12401+ /* || au_test_ocfs2(sb) */ /* untested */
12402+ /* || au_test_ocfs2_dlmfs(sb) */ /* untested */
12403+ /* || au_test_sysv(sb) */ /* untested */
1308ab2a 12404+ /* || au_test_minix(sb) */ /* untested */
12405+ ;
12406+}
12407+
12408+/*
12409+ * filesystems which don't store the correct value in some of their inode
12410+ * attributes.
12411+ */
12412+static inline int au_test_fs_bad_iattr(struct super_block *sb)
12413+{
12414+ return au_test_fs_bad_iattr_size(sb)
12415+ /* || au_test_cifs(sb) */ /* untested */
12416+ || au_test_fat(sb)
12417+ || au_test_msdos(sb)
12418+ || au_test_vfat(sb);
1facf9fc 12419+}
12420+
12421+/* they don't check i_nlink in link(2) */
12422+static inline int au_test_fs_no_limit_nlink(struct super_block *sb)
12423+{
12424+ return au_test_tmpfs(sb)
12425+#ifdef CONFIG_AUFS_BR_RAMFS
12426+ || au_test_ramfs(sb)
12427+#endif
4a4d8108
AM
12428+ || au_test_ubifs(sb)
12429+ || au_test_btrfs(sb)
12430+ || au_test_hfsplus(sb);
1facf9fc 12431+}
12432+
12433+/*
12434+ * filesystems which sets S_NOATIME and S_NOCMTIME.
12435+ */
12436+static inline int au_test_fs_notime(struct super_block *sb)
12437+{
12438+ return au_test_nfs(sb)
12439+ || au_test_fuse(sb)
dece6358 12440+ || au_test_ubifs(sb)
1facf9fc 12441+ /* || au_test_cifs(sb) */ /* untested */
1facf9fc 12442+ ;
12443+}
12444+
12445+/*
12446+ * filesystems which requires replacing i_mapping.
12447+ */
12448+static inline int au_test_fs_bad_mapping(struct super_block *sb)
12449+{
dece6358
AM
12450+ return au_test_fuse(sb)
12451+ || au_test_ubifs(sb);
1facf9fc 12452+}
12453+
12454+/* temporary support for i#1 in cramfs */
12455+static inline int au_test_fs_unique_ino(struct inode *inode)
12456+{
12457+ if (au_test_cramfs(inode->i_sb))
12458+ return inode->i_ino != 1;
12459+ return 1;
12460+}
12461+
12462+/* ---------------------------------------------------------------------- */
12463+
12464+/*
12465+ * the filesystem where the xino files placed must support i/o after unlink and
12466+ * maintain i_size and i_blocks.
12467+ */
12468+static inline int au_test_fs_bad_xino(struct super_block *sb)
12469+{
12470+ return au_test_fs_remote(sb)
12471+ || au_test_fs_bad_iattr_size(sb)
1facf9fc 12472+ /* don't want unnecessary work for xino */
12473+ || au_test_aufs(sb)
1308ab2a 12474+ || au_test_ecryptfs(sb)
12475+ || au_test_nilfs(sb);
1facf9fc 12476+}
12477+
12478+static inline int au_test_fs_trunc_xino(struct super_block *sb)
12479+{
12480+ return au_test_tmpfs(sb)
12481+ || au_test_ramfs(sb);
12482+}
12483+
12484+/*
12485+ * test if the @sb is real-readonly.
12486+ */
12487+static inline int au_test_fs_rr(struct super_block *sb)
12488+{
12489+ return au_test_squashfs(sb)
12490+ || au_test_iso9660(sb)
12491+ || au_test_cramfs(sb)
12492+ || au_test_romfs(sb);
12493+}
12494+
12495+#endif /* __KERNEL__ */
12496+#endif /* __AUFS_FSTYPE_H__ */
7f207e10
AM
12497diff -urN /usr/share/empty/fs/aufs/hfsnotify.c linux/fs/aufs/hfsnotify.c
12498--- /usr/share/empty/fs/aufs/hfsnotify.c 1970-01-01 01:00:00.000000000 +0100
2dfbb274 12499+++ linux/fs/aufs/hfsnotify.c 2012-08-26 08:39:00.760508065 +0200
0c3ec466 12500@@ -0,0 +1,257 @@
1facf9fc 12501+/*
f6c5ef8b 12502+ * Copyright (C) 2005-2012 Junjiro R. Okajima
1facf9fc 12503+ *
12504+ * This program, aufs is free software; you can redistribute it and/or modify
12505+ * it under the terms of the GNU General Public License as published by
12506+ * the Free Software Foundation; either version 2 of the License, or
12507+ * (at your option) any later version.
dece6358
AM
12508+ *
12509+ * This program is distributed in the hope that it will be useful,
12510+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
12511+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12512+ * GNU General Public License for more details.
12513+ *
12514+ * You should have received a copy of the GNU General Public License
12515+ * along with this program; if not, write to the Free Software
12516+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 12517+ */
12518+
12519+/*
4a4d8108 12520+ * fsnotify for the lower directories
1facf9fc 12521+ */
12522+
12523+#include "aufs.h"
12524+
4a4d8108
AM
12525+/* FS_IN_IGNORED is unnecessary */
12526+static const __u32 AuHfsnMask = (FS_MOVED_TO | FS_MOVED_FROM | FS_DELETE
12527+ | FS_CREATE | FS_EVENT_ON_CHILD);
7f207e10 12528+static DECLARE_WAIT_QUEUE_HEAD(au_hfsn_wq);
7eafdf33 12529+static __cacheline_aligned_in_smp atomic64_t au_hfsn_ifree = ATOMIC64_INIT(0);
1facf9fc 12530+
0c5527e5 12531+static void au_hfsn_free_mark(struct fsnotify_mark *mark)
1facf9fc 12532+{
0c5527e5
AM
12533+ struct au_hnotify *hn = container_of(mark, struct au_hnotify,
12534+ hn_mark);
4a4d8108 12535+ AuDbg("here\n");
7eafdf33
AM
12536+ au_cache_free_hnotify(hn);
12537+ smp_mb__before_atomic_dec();
12538+ atomic64_dec(&au_hfsn_ifree);
12539+ wake_up(&au_hfsn_wq);
4a4d8108 12540+}
1facf9fc 12541+
027c5e7a 12542+static int au_hfsn_alloc(struct au_hinode *hinode)
4a4d8108 12543+{
027c5e7a
AM
12544+ struct au_hnotify *hn;
12545+ struct super_block *sb;
12546+ struct au_branch *br;
0c5527e5 12547+ struct fsnotify_mark *mark;
027c5e7a 12548+ aufs_bindex_t bindex;
1facf9fc 12549+
027c5e7a
AM
12550+ hn = hinode->hi_notify;
12551+ sb = hn->hn_aufs_inode->i_sb;
12552+ bindex = au_br_index(sb, hinode->hi_id);
12553+ br = au_sbr(sb, bindex);
0c5527e5
AM
12554+ mark = &hn->hn_mark;
12555+ fsnotify_init_mark(mark, au_hfsn_free_mark);
12556+ mark->mask = AuHfsnMask;
7f207e10
AM
12557+ /*
12558+ * by udba rename or rmdir, aufs assign a new inode to the known
12559+ * h_inode, so specify 1 to allow dups.
12560+ */
027c5e7a
AM
12561+ return fsnotify_add_mark(mark, br->br_hfsn_group, hinode->hi_inode,
12562+ /*mnt*/NULL, /*allow_dups*/1);
1facf9fc 12563+}
12564+
7eafdf33 12565+static int au_hfsn_free(struct au_hinode *hinode, struct au_hnotify *hn)
1facf9fc 12566+{
0c5527e5 12567+ struct fsnotify_mark *mark;
7eafdf33
AM
12568+ unsigned long long ull;
12569+
12570+ ull = atomic64_inc_return(&au_hfsn_ifree);
12571+ BUG_ON(!ull);
953406b4 12572+
0c5527e5
AM
12573+ mark = &hn->hn_mark;
12574+ fsnotify_destroy_mark(mark);
12575+ fsnotify_put_mark(mark);
7f207e10 12576+
7eafdf33
AM
12577+ /* free hn by myself */
12578+ return 0;
1facf9fc 12579+}
12580+
12581+/* ---------------------------------------------------------------------- */
12582+
4a4d8108 12583+static void au_hfsn_ctl(struct au_hinode *hinode, int do_set)
1facf9fc 12584+{
0c5527e5 12585+ struct fsnotify_mark *mark;
1facf9fc 12586+
0c5527e5
AM
12587+ mark = &hinode->hi_notify->hn_mark;
12588+ spin_lock(&mark->lock);
1facf9fc 12589+ if (do_set) {
0c5527e5
AM
12590+ AuDebugOn(mark->mask & AuHfsnMask);
12591+ mark->mask |= AuHfsnMask;
1facf9fc 12592+ } else {
0c5527e5
AM
12593+ AuDebugOn(!(mark->mask & AuHfsnMask));
12594+ mark->mask &= ~AuHfsnMask;
1facf9fc 12595+ }
0c5527e5 12596+ spin_unlock(&mark->lock);
4a4d8108 12597+ /* fsnotify_recalc_inode_mask(hinode->hi_inode); */
1facf9fc 12598+}
12599+
4a4d8108 12600+/* ---------------------------------------------------------------------- */
1facf9fc 12601+
4a4d8108
AM
12602+/* #define AuDbgHnotify */
12603+#ifdef AuDbgHnotify
12604+static char *au_hfsn_name(u32 mask)
12605+{
12606+#ifdef CONFIG_AUFS_DEBUG
12607+#define test_ret(flag) if (mask & flag) \
12608+ return #flag;
12609+ test_ret(FS_ACCESS);
12610+ test_ret(FS_MODIFY);
12611+ test_ret(FS_ATTRIB);
12612+ test_ret(FS_CLOSE_WRITE);
12613+ test_ret(FS_CLOSE_NOWRITE);
12614+ test_ret(FS_OPEN);
12615+ test_ret(FS_MOVED_FROM);
12616+ test_ret(FS_MOVED_TO);
12617+ test_ret(FS_CREATE);
12618+ test_ret(FS_DELETE);
12619+ test_ret(FS_DELETE_SELF);
12620+ test_ret(FS_MOVE_SELF);
12621+ test_ret(FS_UNMOUNT);
12622+ test_ret(FS_Q_OVERFLOW);
12623+ test_ret(FS_IN_IGNORED);
12624+ test_ret(FS_IN_ISDIR);
12625+ test_ret(FS_IN_ONESHOT);
12626+ test_ret(FS_EVENT_ON_CHILD);
12627+ return "";
12628+#undef test_ret
12629+#else
12630+ return "??";
12631+#endif
1facf9fc 12632+}
4a4d8108 12633+#endif
1facf9fc 12634+
12635+/* ---------------------------------------------------------------------- */
12636+
4a4d8108 12637+static int au_hfsn_handle_event(struct fsnotify_group *group,
0c5527e5
AM
12638+ struct fsnotify_mark *inode_mark,
12639+ struct fsnotify_mark *vfsmount_mark,
4a4d8108 12640+ struct fsnotify_event *event)
1facf9fc 12641+{
12642+ int err;
4a4d8108
AM
12643+ struct au_hnotify *hnotify;
12644+ struct inode *h_dir, *h_inode;
12645+ __u32 mask;
0c3ec466 12646+ struct qstr h_child_qstr = QSTR_INIT(event->file_name, event->name_len);
4a4d8108
AM
12647+
12648+ AuDebugOn(event->data_type != FSNOTIFY_EVENT_INODE);
1facf9fc 12649+
12650+ err = 0;
0c5527e5 12651+ /* if FS_UNMOUNT happens, there must be another bug */
4a4d8108
AM
12652+ mask = event->mask;
12653+ AuDebugOn(mask & FS_UNMOUNT);
0c5527e5 12654+ if (mask & (FS_IN_IGNORED | FS_UNMOUNT))
1facf9fc 12655+ goto out;
1facf9fc 12656+
4a4d8108
AM
12657+ h_dir = event->to_tell;
12658+ h_inode = event->inode;
12659+#ifdef AuDbgHnotify
12660+ au_debug(1);
12661+ if (1 || h_child_qstr.len != sizeof(AUFS_XINO_FNAME) - 1
12662+ || strncmp(h_child_qstr.name, AUFS_XINO_FNAME, h_child_qstr.len)) {
12663+ AuDbg("i%lu, mask 0x%x %s, hcname %.*s, hi%lu\n",
12664+ h_dir->i_ino, mask, au_hfsn_name(mask),
12665+ AuLNPair(&h_child_qstr), h_inode ? h_inode->i_ino : 0);
12666+ /* WARN_ON(1); */
1facf9fc 12667+ }
4a4d8108 12668+ au_debug(0);
1facf9fc 12669+#endif
4a4d8108 12670+
0c5527e5
AM
12671+ AuDebugOn(!inode_mark);
12672+ hnotify = container_of(inode_mark, struct au_hnotify, hn_mark);
12673+ err = au_hnotify(h_dir, hnotify, mask, &h_child_qstr, h_inode);
1facf9fc 12674+
4a4d8108
AM
12675+out:
12676+ return err;
12677+}
1facf9fc 12678+
027c5e7a 12679+/* isn't it waste to ask every registered 'group'? */
7f207e10 12680+/* copied from linux/fs/notify/inotify/inotify_fsnotiry.c */
4a4d8108 12681+/* it should be exported to modules */
7f207e10
AM
12682+static bool au_hfsn_should_send_event(struct fsnotify_group *group,
12683+ struct inode *h_inode,
0c5527e5
AM
12684+ struct fsnotify_mark *inode_mark,
12685+ struct fsnotify_mark *vfsmount_mark,
12686+ __u32 mask, void *data, int data_type)
4a4d8108 12687+{
4a4d8108 12688+ mask = (mask & ~FS_EVENT_ON_CHILD);
7f207e10 12689+ return inode_mark->mask & mask;
4a4d8108
AM
12690+}
12691+
12692+static struct fsnotify_ops au_hfsn_ops = {
12693+ .should_send_event = au_hfsn_should_send_event,
12694+ .handle_event = au_hfsn_handle_event
12695+};
12696+
12697+/* ---------------------------------------------------------------------- */
12698+
027c5e7a
AM
12699+static void au_hfsn_fin_br(struct au_branch *br)
12700+{
12701+ if (br->br_hfsn_group)
12702+ fsnotify_put_group(br->br_hfsn_group);
12703+}
12704+
12705+static int au_hfsn_init_br(struct au_branch *br, int perm)
12706+{
12707+ br->br_hfsn_group = NULL;
12708+ br->br_hfsn_ops = au_hfsn_ops;
12709+ return 0;
12710+}
12711+
12712+static int au_hfsn_reset_br(unsigned int udba, struct au_branch *br, int perm)
4a4d8108
AM
12713+{
12714+ int err;
1facf9fc 12715+
4a4d8108 12716+ err = 0;
027c5e7a
AM
12717+ if (udba != AuOpt_UDBA_HNOTIFY
12718+ || !au_br_hnotifyable(perm)) {
12719+ au_hfsn_fin_br(br);
12720+ br->br_hfsn_group = NULL;
12721+ goto out;
12722+ }
12723+
12724+ if (br->br_hfsn_group)
12725+ goto out;
12726+
12727+ br->br_hfsn_group = fsnotify_alloc_group(&br->br_hfsn_ops);
12728+ if (IS_ERR(br->br_hfsn_group)) {
12729+ err = PTR_ERR(br->br_hfsn_group);
0c5527e5 12730+ pr_err("fsnotify_alloc_group() failed, %d\n", err);
027c5e7a 12731+ br->br_hfsn_group = NULL;
4a4d8108 12732+ }
1facf9fc 12733+
027c5e7a 12734+out:
1facf9fc 12735+ AuTraceErr(err);
12736+ return err;
12737+}
12738+
7eafdf33
AM
12739+/* ---------------------------------------------------------------------- */
12740+
12741+static void au_hfsn_fin(void)
12742+{
12743+ AuDbg("au_hfsn_ifree %lld\n", (long long)atomic64_read(&au_hfsn_ifree));
12744+ wait_event(au_hfsn_wq, !atomic64_read(&au_hfsn_ifree));
12745+}
12746+
4a4d8108
AM
12747+const struct au_hnotify_op au_hnotify_op = {
12748+ .ctl = au_hfsn_ctl,
12749+ .alloc = au_hfsn_alloc,
12750+ .free = au_hfsn_free,
1facf9fc 12751+
7eafdf33
AM
12752+ .fin = au_hfsn_fin,
12753+
027c5e7a
AM
12754+ .reset_br = au_hfsn_reset_br,
12755+ .fin_br = au_hfsn_fin_br,
12756+ .init_br = au_hfsn_init_br
4a4d8108 12757+};
7f207e10
AM
12758diff -urN /usr/share/empty/fs/aufs/hfsplus.c linux/fs/aufs/hfsplus.c
12759--- /usr/share/empty/fs/aufs/hfsplus.c 1970-01-01 01:00:00.000000000 +0100
2dfbb274 12760+++ linux/fs/aufs/hfsplus.c 2012-08-26 08:39:00.760508065 +0200
f6c5ef8b 12761@@ -0,0 +1,57 @@
4a4d8108 12762+/*
f6c5ef8b 12763+ * Copyright (C) 2010-2012 Junjiro R. Okajima
4a4d8108
AM
12764+ *
12765+ * This program, aufs is free software; you can redistribute it and/or modify
12766+ * it under the terms of the GNU General Public License as published by
12767+ * the Free Software Foundation; either version 2 of the License, or
12768+ * (at your option) any later version.
12769+ *
12770+ * This program is distributed in the hope that it will be useful,
12771+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
12772+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12773+ * GNU General Public License for more details.
12774+ *
12775+ * You should have received a copy of the GNU General Public License
12776+ * along with this program; if not, write to the Free Software
12777+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
12778+ */
1facf9fc 12779+
4a4d8108
AM
12780+/*
12781+ * special support for filesystems which aqucires an inode mutex
12782+ * at final closing a file, eg, hfsplus.
12783+ *
12784+ * This trick is very simple and stupid, just to open the file before really
12785+ * neceeary open to tell hfsplus that this is not the final closing.
12786+ * The caller should call au_h_open_pre() after acquiring the inode mutex,
12787+ * and au_h_open_post() after releasing it.
12788+ */
1facf9fc 12789+
4a4d8108 12790+#include "aufs.h"
1facf9fc 12791+
4a4d8108
AM
12792+struct file *au_h_open_pre(struct dentry *dentry, aufs_bindex_t bindex)
12793+{
12794+ struct file *h_file;
12795+ struct dentry *h_dentry;
1facf9fc 12796+
4a4d8108
AM
12797+ h_dentry = au_h_dptr(dentry, bindex);
12798+ AuDebugOn(!h_dentry);
12799+ AuDebugOn(!h_dentry->d_inode);
12800+ IMustLock(h_dentry->d_inode);
12801+
12802+ h_file = NULL;
12803+ if (au_test_hfsplus(h_dentry->d_sb)
12804+ && S_ISREG(h_dentry->d_inode->i_mode))
12805+ h_file = au_h_open(dentry, bindex,
12806+ O_RDONLY | O_NOATIME | O_LARGEFILE,
12807+ /*file*/NULL);
12808+ return h_file;
1facf9fc 12809+}
12810+
4a4d8108
AM
12811+void au_h_open_post(struct dentry *dentry, aufs_bindex_t bindex,
12812+ struct file *h_file)
12813+{
12814+ if (h_file) {
12815+ fput(h_file);
12816+ au_sbr_put(dentry->d_sb, bindex);
12817+ }
12818+}
7f207e10
AM
12819diff -urN /usr/share/empty/fs/aufs/hnotify.c linux/fs/aufs/hnotify.c
12820--- /usr/share/empty/fs/aufs/hnotify.c 1970-01-01 01:00:00.000000000 +0100
b4510431
AM
12821+++ linux/fs/aufs/hnotify.c 2012-10-17 10:31:01.772481151 +0200
12822@@ -0,0 +1,713 @@
e49829fe 12823+/*
f6c5ef8b 12824+ * Copyright (C) 2005-2012 Junjiro R. Okajima
e49829fe
JR
12825+ *
12826+ * This program, aufs is free software; you can redistribute it and/or modify
12827+ * it under the terms of the GNU General Public License as published by
12828+ * the Free Software Foundation; either version 2 of the License, or
12829+ * (at your option) any later version.
12830+ *
12831+ * This program is distributed in the hope that it will be useful,
12832+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
12833+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12834+ * GNU General Public License for more details.
12835+ *
12836+ * You should have received a copy of the GNU General Public License
12837+ * along with this program; if not, write to the Free Software
12838+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
12839+ */
12840+
12841+/*
7f207e10 12842+ * abstraction to notify the direct changes on lower directories
e49829fe
JR
12843+ */
12844+
12845+#include "aufs.h"
12846+
027c5e7a 12847+int au_hn_alloc(struct au_hinode *hinode, struct inode *inode)
e49829fe
JR
12848+{
12849+ int err;
7f207e10 12850+ struct au_hnotify *hn;
1facf9fc 12851+
4a4d8108
AM
12852+ err = -ENOMEM;
12853+ hn = au_cache_alloc_hnotify();
12854+ if (hn) {
12855+ hn->hn_aufs_inode = inode;
027c5e7a
AM
12856+ hinode->hi_notify = hn;
12857+ err = au_hnotify_op.alloc(hinode);
12858+ AuTraceErr(err);
12859+ if (unlikely(err)) {
12860+ hinode->hi_notify = NULL;
4a4d8108
AM
12861+ au_cache_free_hnotify(hn);
12862+ /*
12863+ * The upper dir was removed by udba, but the same named
12864+ * dir left. In this case, aufs assignes a new inode
12865+ * number and set the monitor again.
12866+ * For the lower dir, the old monitnor is still left.
12867+ */
12868+ if (err == -EEXIST)
12869+ err = 0;
12870+ }
1308ab2a 12871+ }
1308ab2a 12872+
027c5e7a 12873+ AuTraceErr(err);
1308ab2a 12874+ return err;
dece6358 12875+}
1facf9fc 12876+
4a4d8108 12877+void au_hn_free(struct au_hinode *hinode)
dece6358 12878+{
4a4d8108 12879+ struct au_hnotify *hn;
1facf9fc 12880+
4a4d8108
AM
12881+ hn = hinode->hi_notify;
12882+ if (hn) {
4a4d8108 12883+ hinode->hi_notify = NULL;
7eafdf33
AM
12884+ if (au_hnotify_op.free(hinode, hn))
12885+ au_cache_free_hnotify(hn);
4a4d8108
AM
12886+ }
12887+}
dece6358 12888+
4a4d8108 12889+/* ---------------------------------------------------------------------- */
dece6358 12890+
4a4d8108
AM
12891+void au_hn_ctl(struct au_hinode *hinode, int do_set)
12892+{
12893+ if (hinode->hi_notify)
12894+ au_hnotify_op.ctl(hinode, do_set);
12895+}
12896+
12897+void au_hn_reset(struct inode *inode, unsigned int flags)
12898+{
12899+ aufs_bindex_t bindex, bend;
12900+ struct inode *hi;
12901+ struct dentry *iwhdentry;
1facf9fc 12902+
1308ab2a 12903+ bend = au_ibend(inode);
4a4d8108
AM
12904+ for (bindex = au_ibstart(inode); bindex <= bend; bindex++) {
12905+ hi = au_h_iptr(inode, bindex);
12906+ if (!hi)
12907+ continue;
1308ab2a 12908+
4a4d8108
AM
12909+ /* mutex_lock_nested(&hi->i_mutex, AuLsc_I_CHILD); */
12910+ iwhdentry = au_hi_wh(inode, bindex);
12911+ if (iwhdentry)
12912+ dget(iwhdentry);
12913+ au_igrab(hi);
12914+ au_set_h_iptr(inode, bindex, NULL, 0);
12915+ au_set_h_iptr(inode, bindex, au_igrab(hi),
12916+ flags & ~AuHi_XINO);
12917+ iput(hi);
12918+ dput(iwhdentry);
12919+ /* mutex_unlock(&hi->i_mutex); */
1facf9fc 12920+ }
1facf9fc 12921+}
12922+
1308ab2a 12923+/* ---------------------------------------------------------------------- */
1facf9fc 12924+
4a4d8108 12925+static int hn_xino(struct inode *inode, struct inode *h_inode)
1facf9fc 12926+{
4a4d8108
AM
12927+ int err;
12928+ aufs_bindex_t bindex, bend, bfound, bstart;
12929+ struct inode *h_i;
1facf9fc 12930+
4a4d8108
AM
12931+ err = 0;
12932+ if (unlikely(inode->i_ino == AUFS_ROOT_INO)) {
0c3ec466 12933+ pr_warn("branch root dir was changed\n");
4a4d8108
AM
12934+ goto out;
12935+ }
1facf9fc 12936+
4a4d8108
AM
12937+ bfound = -1;
12938+ bend = au_ibend(inode);
12939+ bstart = au_ibstart(inode);
12940+#if 0 /* reserved for future use */
12941+ if (bindex == bend) {
12942+ /* keep this ino in rename case */
12943+ goto out;
12944+ }
12945+#endif
12946+ for (bindex = bstart; bindex <= bend; bindex++)
12947+ if (au_h_iptr(inode, bindex) == h_inode) {
12948+ bfound = bindex;
12949+ break;
12950+ }
12951+ if (bfound < 0)
1308ab2a 12952+ goto out;
1facf9fc 12953+
4a4d8108
AM
12954+ for (bindex = bstart; bindex <= bend; bindex++) {
12955+ h_i = au_h_iptr(inode, bindex);
12956+ if (!h_i)
12957+ continue;
1facf9fc 12958+
4a4d8108
AM
12959+ err = au_xino_write(inode->i_sb, bindex, h_i->i_ino, /*ino*/0);
12960+ /* ignore this error */
12961+ /* bad action? */
1facf9fc 12962+ }
1facf9fc 12963+
4a4d8108 12964+ /* children inode number will be broken */
1facf9fc 12965+
4f0767ce 12966+out:
4a4d8108
AM
12967+ AuTraceErr(err);
12968+ return err;
1facf9fc 12969+}
12970+
4a4d8108 12971+static int hn_gen_tree(struct dentry *dentry)
1facf9fc 12972+{
4a4d8108
AM
12973+ int err, i, j, ndentry;
12974+ struct au_dcsub_pages dpages;
12975+ struct au_dpage *dpage;
12976+ struct dentry **dentries;
1facf9fc 12977+
4a4d8108
AM
12978+ err = au_dpages_init(&dpages, GFP_NOFS);
12979+ if (unlikely(err))
12980+ goto out;
12981+ err = au_dcsub_pages(&dpages, dentry, NULL, NULL);
12982+ if (unlikely(err))
12983+ goto out_dpages;
1facf9fc 12984+
4a4d8108
AM
12985+ for (i = 0; i < dpages.ndpage; i++) {
12986+ dpage = dpages.dpages + i;
12987+ dentries = dpage->dentries;
12988+ ndentry = dpage->ndentry;
12989+ for (j = 0; j < ndentry; j++) {
12990+ struct dentry *d;
12991+
12992+ d = dentries[j];
12993+ if (IS_ROOT(d))
12994+ continue;
12995+
4a4d8108
AM
12996+ au_digen_dec(d);
12997+ if (d->d_inode)
12998+ /* todo: reset children xino?
12999+ cached children only? */
13000+ au_iigen_dec(d->d_inode);
1308ab2a 13001+ }
dece6358 13002+ }
1facf9fc 13003+
4f0767ce 13004+out_dpages:
4a4d8108 13005+ au_dpages_free(&dpages);
dece6358 13006+
027c5e7a 13007+#if 0
4a4d8108
AM
13008+ /* discard children */
13009+ dentry_unhash(dentry);
13010+ dput(dentry);
027c5e7a 13011+#endif
4f0767ce 13012+out:
dece6358
AM
13013+ return err;
13014+}
13015+
1308ab2a 13016+/*
4a4d8108 13017+ * return 0 if processed.
1308ab2a 13018+ */
4a4d8108
AM
13019+static int hn_gen_by_inode(char *name, unsigned int nlen, struct inode *inode,
13020+ const unsigned int isdir)
dece6358 13021+{
1308ab2a 13022+ int err;
4a4d8108
AM
13023+ struct dentry *d;
13024+ struct qstr *dname;
b4510431 13025+ struct hlist_node *p;
1facf9fc 13026+
4a4d8108
AM
13027+ err = 1;
13028+ if (unlikely(inode->i_ino == AUFS_ROOT_INO)) {
0c3ec466 13029+ pr_warn("branch root dir was changed\n");
4a4d8108
AM
13030+ err = 0;
13031+ goto out;
13032+ }
dece6358 13033+
4a4d8108
AM
13034+ if (!isdir) {
13035+ AuDebugOn(!name);
13036+ au_iigen_dec(inode);
027c5e7a 13037+ spin_lock(&inode->i_lock);
b4510431 13038+ hlist_for_each_entry(d, p, &inode->i_dentry, d_alias) {
027c5e7a 13039+ spin_lock(&d->d_lock);
4a4d8108
AM
13040+ dname = &d->d_name;
13041+ if (dname->len != nlen
027c5e7a
AM
13042+ && memcmp(dname->name, name, nlen)) {
13043+ spin_unlock(&d->d_lock);
4a4d8108 13044+ continue;
027c5e7a 13045+ }
4a4d8108 13046+ err = 0;
4a4d8108
AM
13047+ au_digen_dec(d);
13048+ spin_unlock(&d->d_lock);
13049+ break;
1facf9fc 13050+ }
027c5e7a 13051+ spin_unlock(&inode->i_lock);
1308ab2a 13052+ } else {
027c5e7a 13053+ au_fset_si(au_sbi(inode->i_sb), FAILED_REFRESH_DIR);
4a4d8108
AM
13054+ d = d_find_alias(inode);
13055+ if (!d) {
13056+ au_iigen_dec(inode);
13057+ goto out;
13058+ }
1facf9fc 13059+
027c5e7a 13060+ spin_lock(&d->d_lock);
4a4d8108 13061+ dname = &d->d_name;
027c5e7a
AM
13062+ if (dname->len == nlen && !memcmp(dname->name, name, nlen)) {
13063+ spin_unlock(&d->d_lock);
4a4d8108 13064+ err = hn_gen_tree(d);
027c5e7a
AM
13065+ spin_lock(&d->d_lock);
13066+ }
13067+ spin_unlock(&d->d_lock);
4a4d8108
AM
13068+ dput(d);
13069+ }
1facf9fc 13070+
4f0767ce 13071+out:
4a4d8108 13072+ AuTraceErr(err);
1308ab2a 13073+ return err;
13074+}
dece6358 13075+
4a4d8108 13076+static int hn_gen_by_name(struct dentry *dentry, const unsigned int isdir)
1facf9fc 13077+{
4a4d8108
AM
13078+ int err;
13079+ struct inode *inode;
1facf9fc 13080+
4a4d8108
AM
13081+ inode = dentry->d_inode;
13082+ if (IS_ROOT(dentry)
13083+ /* || (inode && inode->i_ino == AUFS_ROOT_INO) */
13084+ ) {
0c3ec466 13085+ pr_warn("branch root dir was changed\n");
4a4d8108
AM
13086+ return 0;
13087+ }
1308ab2a 13088+
4a4d8108
AM
13089+ err = 0;
13090+ if (!isdir) {
4a4d8108
AM
13091+ au_digen_dec(dentry);
13092+ if (inode)
13093+ au_iigen_dec(inode);
13094+ } else {
027c5e7a 13095+ au_fset_si(au_sbi(dentry->d_sb), FAILED_REFRESH_DIR);
4a4d8108
AM
13096+ if (inode)
13097+ err = hn_gen_tree(dentry);
13098+ }
13099+
13100+ AuTraceErr(err);
13101+ return err;
1facf9fc 13102+}
13103+
4a4d8108 13104+/* ---------------------------------------------------------------------- */
1facf9fc 13105+
4a4d8108
AM
13106+/* hnotify job flags */
13107+#define AuHnJob_XINO0 1
13108+#define AuHnJob_GEN (1 << 1)
13109+#define AuHnJob_DIRENT (1 << 2)
13110+#define AuHnJob_ISDIR (1 << 3)
13111+#define AuHnJob_TRYXINO0 (1 << 4)
13112+#define AuHnJob_MNTPNT (1 << 5)
13113+#define au_ftest_hnjob(flags, name) ((flags) & AuHnJob_##name)
7f207e10
AM
13114+#define au_fset_hnjob(flags, name) \
13115+ do { (flags) |= AuHnJob_##name; } while (0)
13116+#define au_fclr_hnjob(flags, name) \
13117+ do { (flags) &= ~AuHnJob_##name; } while (0)
1facf9fc 13118+
4a4d8108
AM
13119+enum {
13120+ AuHn_CHILD,
13121+ AuHn_PARENT,
13122+ AuHnLast
13123+};
1facf9fc 13124+
4a4d8108
AM
13125+struct au_hnotify_args {
13126+ struct inode *h_dir, *dir, *h_child_inode;
13127+ u32 mask;
13128+ unsigned int flags[AuHnLast];
13129+ unsigned int h_child_nlen;
13130+ char h_child_name[];
13131+};
1facf9fc 13132+
4a4d8108
AM
13133+struct hn_job_args {
13134+ unsigned int flags;
13135+ struct inode *inode, *h_inode, *dir, *h_dir;
13136+ struct dentry *dentry;
13137+ char *h_name;
13138+ int h_nlen;
13139+};
1308ab2a 13140+
4a4d8108
AM
13141+static int hn_job(struct hn_job_args *a)
13142+{
13143+ const unsigned int isdir = au_ftest_hnjob(a->flags, ISDIR);
1308ab2a 13144+
4a4d8108
AM
13145+ /* reset xino */
13146+ if (au_ftest_hnjob(a->flags, XINO0) && a->inode)
13147+ hn_xino(a->inode, a->h_inode); /* ignore this error */
1308ab2a 13148+
4a4d8108
AM
13149+ if (au_ftest_hnjob(a->flags, TRYXINO0)
13150+ && a->inode
13151+ && a->h_inode) {
13152+ mutex_lock_nested(&a->h_inode->i_mutex, AuLsc_I_CHILD);
13153+ if (!a->h_inode->i_nlink)
13154+ hn_xino(a->inode, a->h_inode); /* ignore this error */
13155+ mutex_unlock(&a->h_inode->i_mutex);
1308ab2a 13156+ }
1facf9fc 13157+
4a4d8108
AM
13158+ /* make the generation obsolete */
13159+ if (au_ftest_hnjob(a->flags, GEN)) {
13160+ int err = -1;
13161+ if (a->inode)
13162+ err = hn_gen_by_inode(a->h_name, a->h_nlen, a->inode,
13163+ isdir);
13164+ if (err && a->dentry)
13165+ hn_gen_by_name(a->dentry, isdir);
13166+ /* ignore this error */
1facf9fc 13167+ }
1facf9fc 13168+
4a4d8108
AM
13169+ /* make dir entries obsolete */
13170+ if (au_ftest_hnjob(a->flags, DIRENT) && a->inode) {
13171+ struct au_vdir *vdir;
1facf9fc 13172+
4a4d8108
AM
13173+ vdir = au_ivdir(a->inode);
13174+ if (vdir)
13175+ vdir->vd_jiffy = 0;
13176+ /* IMustLock(a->inode); */
13177+ /* a->inode->i_version++; */
13178+ }
1facf9fc 13179+
4a4d8108
AM
13180+ /* can do nothing but warn */
13181+ if (au_ftest_hnjob(a->flags, MNTPNT)
13182+ && a->dentry
13183+ && d_mountpoint(a->dentry))
0c3ec466
AM
13184+ pr_warn("mount-point %.*s is removed or renamed\n",
13185+ AuDLNPair(a->dentry));
1facf9fc 13186+
4a4d8108 13187+ return 0;
1308ab2a 13188+}
1facf9fc 13189+
1308ab2a 13190+/* ---------------------------------------------------------------------- */
1facf9fc 13191+
4a4d8108
AM
13192+static struct dentry *lookup_wlock_by_name(char *name, unsigned int nlen,
13193+ struct inode *dir)
1308ab2a 13194+{
4a4d8108
AM
13195+ struct dentry *dentry, *d, *parent;
13196+ struct qstr *dname;
1308ab2a 13197+
4a4d8108
AM
13198+ parent = d_find_alias(dir);
13199+ if (!parent)
13200+ return NULL;
1308ab2a 13201+
4a4d8108 13202+ dentry = NULL;
027c5e7a 13203+ spin_lock(&parent->d_lock);
4a4d8108
AM
13204+ list_for_each_entry(d, &parent->d_subdirs, d_u.d_child) {
13205+ /* AuDbg("%.*s\n", AuDLNPair(d)); */
027c5e7a 13206+ spin_lock_nested(&d->d_lock, DENTRY_D_LOCK_NESTED);
4a4d8108
AM
13207+ dname = &d->d_name;
13208+ if (dname->len != nlen || memcmp(dname->name, name, nlen))
027c5e7a
AM
13209+ goto cont_unlock;
13210+ if (au_di(d))
13211+ au_digen_dec(d);
13212+ else
13213+ goto cont_unlock;
13214+ if (d->d_count) {
13215+ dentry = dget_dlock(d);
4a4d8108 13216+ spin_unlock(&d->d_lock);
027c5e7a 13217+ break;
dece6358 13218+ }
1facf9fc 13219+
027c5e7a
AM
13220+ cont_unlock:
13221+ spin_unlock(&d->d_lock);
1308ab2a 13222+ }
027c5e7a 13223+ spin_unlock(&parent->d_lock);
4a4d8108 13224+ dput(parent);
1facf9fc 13225+
4a4d8108
AM
13226+ if (dentry)
13227+ di_write_lock_child(dentry);
1308ab2a 13228+
4a4d8108
AM
13229+ return dentry;
13230+}
dece6358 13231+
4a4d8108
AM
13232+static struct inode *lookup_wlock_by_ino(struct super_block *sb,
13233+ aufs_bindex_t bindex, ino_t h_ino)
13234+{
13235+ struct inode *inode;
13236+ ino_t ino;
13237+ int err;
13238+
13239+ inode = NULL;
13240+ err = au_xino_read(sb, bindex, h_ino, &ino);
13241+ if (!err && ino)
13242+ inode = ilookup(sb, ino);
13243+ if (!inode)
13244+ goto out;
13245+
13246+ if (unlikely(inode->i_ino == AUFS_ROOT_INO)) {
0c3ec466 13247+ pr_warn("wrong root branch\n");
4a4d8108
AM
13248+ iput(inode);
13249+ inode = NULL;
13250+ goto out;
1308ab2a 13251+ }
13252+
4a4d8108 13253+ ii_write_lock_child(inode);
1308ab2a 13254+
4f0767ce 13255+out:
4a4d8108 13256+ return inode;
dece6358
AM
13257+}
13258+
4a4d8108 13259+static void au_hn_bh(void *_args)
1facf9fc 13260+{
4a4d8108
AM
13261+ struct au_hnotify_args *a = _args;
13262+ struct super_block *sb;
13263+ aufs_bindex_t bindex, bend, bfound;
13264+ unsigned char xino, try_iput;
1facf9fc 13265+ int err;
1308ab2a 13266+ struct inode *inode;
4a4d8108
AM
13267+ ino_t h_ino;
13268+ struct hn_job_args args;
13269+ struct dentry *dentry;
13270+ struct au_sbinfo *sbinfo;
1facf9fc 13271+
4a4d8108
AM
13272+ AuDebugOn(!_args);
13273+ AuDebugOn(!a->h_dir);
13274+ AuDebugOn(!a->dir);
13275+ AuDebugOn(!a->mask);
13276+ AuDbg("mask 0x%x, i%lu, hi%lu, hci%lu\n",
13277+ a->mask, a->dir->i_ino, a->h_dir->i_ino,
13278+ a->h_child_inode ? a->h_child_inode->i_ino : 0);
1facf9fc 13279+
4a4d8108
AM
13280+ inode = NULL;
13281+ dentry = NULL;
13282+ /*
13283+ * do not lock a->dir->i_mutex here
13284+ * because of d_revalidate() may cause a deadlock.
13285+ */
13286+ sb = a->dir->i_sb;
13287+ AuDebugOn(!sb);
13288+ sbinfo = au_sbi(sb);
13289+ AuDebugOn(!sbinfo);
7f207e10 13290+ si_write_lock(sb, AuLock_NOPLMW);
1facf9fc 13291+
4a4d8108
AM
13292+ ii_read_lock_parent(a->dir);
13293+ bfound = -1;
13294+ bend = au_ibend(a->dir);
13295+ for (bindex = au_ibstart(a->dir); bindex <= bend; bindex++)
13296+ if (au_h_iptr(a->dir, bindex) == a->h_dir) {
13297+ bfound = bindex;
13298+ break;
13299+ }
13300+ ii_read_unlock(a->dir);
13301+ if (unlikely(bfound < 0))
13302+ goto out;
1facf9fc 13303+
4a4d8108
AM
13304+ xino = !!au_opt_test(au_mntflags(sb), XINO);
13305+ h_ino = 0;
13306+ if (a->h_child_inode)
13307+ h_ino = a->h_child_inode->i_ino;
1facf9fc 13308+
4a4d8108
AM
13309+ if (a->h_child_nlen
13310+ && (au_ftest_hnjob(a->flags[AuHn_CHILD], GEN)
13311+ || au_ftest_hnjob(a->flags[AuHn_CHILD], MNTPNT)))
13312+ dentry = lookup_wlock_by_name(a->h_child_name, a->h_child_nlen,
13313+ a->dir);
13314+ try_iput = 0;
13315+ if (dentry)
13316+ inode = dentry->d_inode;
13317+ if (xino && !inode && h_ino
13318+ && (au_ftest_hnjob(a->flags[AuHn_CHILD], XINO0)
13319+ || au_ftest_hnjob(a->flags[AuHn_CHILD], TRYXINO0)
13320+ || au_ftest_hnjob(a->flags[AuHn_CHILD], GEN))) {
13321+ inode = lookup_wlock_by_ino(sb, bfound, h_ino);
13322+ try_iput = 1;
13323+ }
1facf9fc 13324+
4a4d8108
AM
13325+ args.flags = a->flags[AuHn_CHILD];
13326+ args.dentry = dentry;
13327+ args.inode = inode;
13328+ args.h_inode = a->h_child_inode;
13329+ args.dir = a->dir;
13330+ args.h_dir = a->h_dir;
13331+ args.h_name = a->h_child_name;
13332+ args.h_nlen = a->h_child_nlen;
13333+ err = hn_job(&args);
13334+ if (dentry) {
027c5e7a 13335+ if (au_di(dentry))
4a4d8108
AM
13336+ di_write_unlock(dentry);
13337+ dput(dentry);
13338+ }
13339+ if (inode && try_iput) {
13340+ ii_write_unlock(inode);
13341+ iput(inode);
13342+ }
1facf9fc 13343+
4a4d8108
AM
13344+ ii_write_lock_parent(a->dir);
13345+ args.flags = a->flags[AuHn_PARENT];
13346+ args.dentry = NULL;
13347+ args.inode = a->dir;
13348+ args.h_inode = a->h_dir;
13349+ args.dir = NULL;
13350+ args.h_dir = NULL;
13351+ args.h_name = NULL;
13352+ args.h_nlen = 0;
13353+ err = hn_job(&args);
13354+ ii_write_unlock(a->dir);
1facf9fc 13355+
4f0767ce 13356+out:
4a4d8108
AM
13357+ iput(a->h_child_inode);
13358+ iput(a->h_dir);
13359+ iput(a->dir);
027c5e7a
AM
13360+ si_write_unlock(sb);
13361+ au_nwt_done(&sbinfo->si_nowait);
1308ab2a 13362+ kfree(a);
dece6358 13363+}
1facf9fc 13364+
4a4d8108
AM
13365+/* ---------------------------------------------------------------------- */
13366+
13367+int au_hnotify(struct inode *h_dir, struct au_hnotify *hnotify, u32 mask,
13368+ struct qstr *h_child_qstr, struct inode *h_child_inode)
dece6358 13369+{
4a4d8108 13370+ int err, len;
53392da6 13371+ unsigned int flags[AuHnLast], f;
4a4d8108
AM
13372+ unsigned char isdir, isroot, wh;
13373+ struct inode *dir;
13374+ struct au_hnotify_args *args;
13375+ char *p, *h_child_name;
dece6358 13376+
1308ab2a 13377+ err = 0;
4a4d8108
AM
13378+ AuDebugOn(!hnotify || !hnotify->hn_aufs_inode);
13379+ dir = igrab(hnotify->hn_aufs_inode);
13380+ if (!dir)
13381+ goto out;
1facf9fc 13382+
4a4d8108
AM
13383+ isroot = (dir->i_ino == AUFS_ROOT_INO);
13384+ wh = 0;
13385+ h_child_name = (void *)h_child_qstr->name;
13386+ len = h_child_qstr->len;
13387+ if (h_child_name) {
13388+ if (len > AUFS_WH_PFX_LEN
13389+ && !memcmp(h_child_name, AUFS_WH_PFX, AUFS_WH_PFX_LEN)) {
13390+ h_child_name += AUFS_WH_PFX_LEN;
13391+ len -= AUFS_WH_PFX_LEN;
13392+ wh = 1;
13393+ }
1facf9fc 13394+ }
dece6358 13395+
4a4d8108
AM
13396+ isdir = 0;
13397+ if (h_child_inode)
13398+ isdir = !!S_ISDIR(h_child_inode->i_mode);
13399+ flags[AuHn_PARENT] = AuHnJob_ISDIR;
13400+ flags[AuHn_CHILD] = 0;
13401+ if (isdir)
13402+ flags[AuHn_CHILD] = AuHnJob_ISDIR;
13403+ au_fset_hnjob(flags[AuHn_PARENT], DIRENT);
13404+ au_fset_hnjob(flags[AuHn_CHILD], GEN);
13405+ switch (mask & FS_EVENTS_POSS_ON_CHILD) {
13406+ case FS_MOVED_FROM:
13407+ case FS_MOVED_TO:
13408+ au_fset_hnjob(flags[AuHn_CHILD], XINO0);
13409+ au_fset_hnjob(flags[AuHn_CHILD], MNTPNT);
13410+ /*FALLTHROUGH*/
13411+ case FS_CREATE:
13412+ AuDebugOn(!h_child_name || !h_child_inode);
13413+ break;
1facf9fc 13414+
4a4d8108
AM
13415+ case FS_DELETE:
13416+ /*
13417+ * aufs never be able to get this child inode.
13418+ * revalidation should be in d_revalidate()
13419+ * by checking i_nlink, i_generation or d_unhashed().
13420+ */
13421+ AuDebugOn(!h_child_name);
13422+ au_fset_hnjob(flags[AuHn_CHILD], TRYXINO0);
13423+ au_fset_hnjob(flags[AuHn_CHILD], MNTPNT);
13424+ break;
dece6358 13425+
4a4d8108
AM
13426+ default:
13427+ AuDebugOn(1);
13428+ }
1308ab2a 13429+
4a4d8108
AM
13430+ if (wh)
13431+ h_child_inode = NULL;
1308ab2a 13432+
4a4d8108
AM
13433+ err = -ENOMEM;
13434+ /* iput() and kfree() will be called in au_hnotify() */
4a4d8108 13435+ args = kmalloc(sizeof(*args) + len + 1, GFP_NOFS);
4a4d8108
AM
13436+ if (unlikely(!args)) {
13437+ AuErr1("no memory\n");
13438+ iput(dir);
13439+ goto out;
13440+ }
13441+ args->flags[AuHn_PARENT] = flags[AuHn_PARENT];
13442+ args->flags[AuHn_CHILD] = flags[AuHn_CHILD];
13443+ args->mask = mask;
13444+ args->dir = dir;
13445+ args->h_dir = igrab(h_dir);
13446+ if (h_child_inode)
13447+ h_child_inode = igrab(h_child_inode); /* can be NULL */
13448+ args->h_child_inode = h_child_inode;
13449+ args->h_child_nlen = len;
13450+ if (len) {
13451+ p = (void *)args;
13452+ p += sizeof(*args);
13453+ memcpy(p, h_child_name, len);
13454+ p[len] = 0;
1308ab2a 13455+ }
1308ab2a 13456+
53392da6
AM
13457+ f = 0;
13458+ if (!dir->i_nlink)
13459+ f = AuWkq_NEST;
13460+ err = au_wkq_nowait(au_hn_bh, args, dir->i_sb, f);
4a4d8108
AM
13461+ if (unlikely(err)) {
13462+ pr_err("wkq %d\n", err);
13463+ iput(args->h_child_inode);
13464+ iput(args->h_dir);
13465+ iput(args->dir);
13466+ kfree(args);
1facf9fc 13467+ }
1facf9fc 13468+
4a4d8108 13469+out:
1facf9fc 13470+ return err;
13471+}
13472+
027c5e7a
AM
13473+/* ---------------------------------------------------------------------- */
13474+
13475+int au_hnotify_reset_br(unsigned int udba, struct au_branch *br, int perm)
13476+{
13477+ int err;
13478+
13479+ AuDebugOn(!(udba & AuOptMask_UDBA));
13480+
13481+ err = 0;
13482+ if (au_hnotify_op.reset_br)
13483+ err = au_hnotify_op.reset_br(udba, br, perm);
13484+
13485+ return err;
13486+}
13487+
13488+int au_hnotify_init_br(struct au_branch *br, int perm)
13489+{
13490+ int err;
13491+
13492+ err = 0;
13493+ if (au_hnotify_op.init_br)
13494+ err = au_hnotify_op.init_br(br, perm);
13495+
13496+ return err;
13497+}
13498+
13499+void au_hnotify_fin_br(struct au_branch *br)
13500+{
13501+ if (au_hnotify_op.fin_br)
13502+ au_hnotify_op.fin_br(br);
13503+}
13504+
4a4d8108
AM
13505+static void au_hn_destroy_cache(void)
13506+{
13507+ kmem_cache_destroy(au_cachep[AuCache_HNOTIFY]);
13508+ au_cachep[AuCache_HNOTIFY] = NULL;
13509+}
1308ab2a 13510+
4a4d8108 13511+int __init au_hnotify_init(void)
1facf9fc 13512+{
1308ab2a 13513+ int err;
1308ab2a 13514+
4a4d8108
AM
13515+ err = -ENOMEM;
13516+ au_cachep[AuCache_HNOTIFY] = AuCache(au_hnotify);
13517+ if (au_cachep[AuCache_HNOTIFY]) {
027c5e7a
AM
13518+ err = 0;
13519+ if (au_hnotify_op.init)
13520+ err = au_hnotify_op.init();
4a4d8108
AM
13521+ if (unlikely(err))
13522+ au_hn_destroy_cache();
1308ab2a 13523+ }
1308ab2a 13524+ AuTraceErr(err);
4a4d8108 13525+ return err;
1308ab2a 13526+}
13527+
4a4d8108 13528+void au_hnotify_fin(void)
1308ab2a 13529+{
027c5e7a
AM
13530+ if (au_hnotify_op.fin)
13531+ au_hnotify_op.fin();
4a4d8108
AM
13532+ /* cf. au_cache_fin() */
13533+ if (au_cachep[AuCache_HNOTIFY])
13534+ au_hn_destroy_cache();
dece6358 13535+}
7f207e10
AM
13536diff -urN /usr/share/empty/fs/aufs/iinfo.c linux/fs/aufs/iinfo.c
13537--- /usr/share/empty/fs/aufs/iinfo.c 1970-01-01 01:00:00.000000000 +0100
2dfbb274 13538+++ linux/fs/aufs/iinfo.c 2012-08-26 08:39:00.760508065 +0200
027c5e7a 13539@@ -0,0 +1,264 @@
dece6358 13540+/*
f6c5ef8b 13541+ * Copyright (C) 2005-2012 Junjiro R. Okajima
dece6358
AM
13542+ *
13543+ * This program, aufs is free software; you can redistribute it and/or modify
13544+ * it under the terms of the GNU General Public License as published by
13545+ * the Free Software Foundation; either version 2 of the License, or
13546+ * (at your option) any later version.
13547+ *
13548+ * This program is distributed in the hope that it will be useful,
13549+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
13550+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13551+ * GNU General Public License for more details.
13552+ *
13553+ * You should have received a copy of the GNU General Public License
13554+ * along with this program; if not, write to the Free Software
13555+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
13556+ */
1facf9fc 13557+
dece6358 13558+/*
4a4d8108 13559+ * inode private data
dece6358 13560+ */
1facf9fc 13561+
1308ab2a 13562+#include "aufs.h"
1facf9fc 13563+
4a4d8108 13564+struct inode *au_h_iptr(struct inode *inode, aufs_bindex_t bindex)
1308ab2a 13565+{
4a4d8108 13566+ struct inode *h_inode;
1facf9fc 13567+
4a4d8108 13568+ IiMustAnyLock(inode);
1facf9fc 13569+
4a4d8108
AM
13570+ h_inode = au_ii(inode)->ii_hinode[0 + bindex].hi_inode;
13571+ AuDebugOn(h_inode && atomic_read(&h_inode->i_count) <= 0);
13572+ return h_inode;
13573+}
1facf9fc 13574+
4a4d8108
AM
13575+/* todo: hard/soft set? */
13576+void au_hiput(struct au_hinode *hinode)
13577+{
13578+ au_hn_free(hinode);
13579+ dput(hinode->hi_whdentry);
13580+ iput(hinode->hi_inode);
13581+}
1facf9fc 13582+
4a4d8108
AM
13583+unsigned int au_hi_flags(struct inode *inode, int isdir)
13584+{
13585+ unsigned int flags;
13586+ const unsigned int mnt_flags = au_mntflags(inode->i_sb);
1facf9fc 13587+
4a4d8108
AM
13588+ flags = 0;
13589+ if (au_opt_test(mnt_flags, XINO))
13590+ au_fset_hi(flags, XINO);
13591+ if (isdir && au_opt_test(mnt_flags, UDBA_HNOTIFY))
13592+ au_fset_hi(flags, HNOTIFY);
13593+ return flags;
1facf9fc 13594+}
13595+
4a4d8108
AM
13596+void au_set_h_iptr(struct inode *inode, aufs_bindex_t bindex,
13597+ struct inode *h_inode, unsigned int flags)
1308ab2a 13598+{
4a4d8108
AM
13599+ struct au_hinode *hinode;
13600+ struct inode *hi;
13601+ struct au_iinfo *iinfo = au_ii(inode);
1facf9fc 13602+
4a4d8108 13603+ IiMustWriteLock(inode);
dece6358 13604+
4a4d8108
AM
13605+ hinode = iinfo->ii_hinode + bindex;
13606+ hi = hinode->hi_inode;
13607+ AuDebugOn(h_inode && atomic_read(&h_inode->i_count) <= 0);
13608+
13609+ if (hi)
13610+ au_hiput(hinode);
13611+ hinode->hi_inode = h_inode;
13612+ if (h_inode) {
13613+ int err;
13614+ struct super_block *sb = inode->i_sb;
13615+ struct au_branch *br;
13616+
027c5e7a
AM
13617+ AuDebugOn(inode->i_mode
13618+ && (h_inode->i_mode & S_IFMT)
13619+ != (inode->i_mode & S_IFMT));
4a4d8108
AM
13620+ if (bindex == iinfo->ii_bstart)
13621+ au_cpup_igen(inode, h_inode);
13622+ br = au_sbr(sb, bindex);
13623+ hinode->hi_id = br->br_id;
13624+ if (au_ftest_hi(flags, XINO)) {
13625+ err = au_xino_write(sb, bindex, h_inode->i_ino,
13626+ inode->i_ino);
13627+ if (unlikely(err))
13628+ AuIOErr1("failed au_xino_write() %d\n", err);
13629+ }
13630+
13631+ if (au_ftest_hi(flags, HNOTIFY)
13632+ && au_br_hnotifyable(br->br_perm)) {
027c5e7a 13633+ err = au_hn_alloc(hinode, inode);
4a4d8108
AM
13634+ if (unlikely(err))
13635+ AuIOErr1("au_hn_alloc() %d\n", err);
1308ab2a 13636+ }
13637+ }
4a4d8108 13638+}
dece6358 13639+
4a4d8108
AM
13640+void au_set_hi_wh(struct inode *inode, aufs_bindex_t bindex,
13641+ struct dentry *h_wh)
13642+{
13643+ struct au_hinode *hinode;
dece6358 13644+
4a4d8108
AM
13645+ IiMustWriteLock(inode);
13646+
13647+ hinode = au_ii(inode)->ii_hinode + bindex;
13648+ AuDebugOn(hinode->hi_whdentry);
13649+ hinode->hi_whdentry = h_wh;
1facf9fc 13650+}
13651+
4a4d8108 13652+void au_update_iigen(struct inode *inode)
1308ab2a 13653+{
4a4d8108
AM
13654+ atomic_set(&au_ii(inode)->ii_generation, au_sigen(inode->i_sb));
13655+ /* smp_mb(); */ /* atomic_set */
13656+}
1facf9fc 13657+
4a4d8108
AM
13658+/* it may be called at remount time, too */
13659+void au_update_ibrange(struct inode *inode, int do_put_zero)
13660+{
13661+ struct au_iinfo *iinfo;
027c5e7a 13662+ aufs_bindex_t bindex, bend;
1facf9fc 13663+
4a4d8108 13664+ iinfo = au_ii(inode);
027c5e7a 13665+ if (!iinfo)
4a4d8108 13666+ return;
1facf9fc 13667+
4a4d8108 13668+ IiMustWriteLock(inode);
1facf9fc 13669+
027c5e7a 13670+ if (do_put_zero && iinfo->ii_bstart >= 0) {
4a4d8108
AM
13671+ for (bindex = iinfo->ii_bstart; bindex <= iinfo->ii_bend;
13672+ bindex++) {
13673+ struct inode *h_i;
1facf9fc 13674+
4a4d8108 13675+ h_i = iinfo->ii_hinode[0 + bindex].hi_inode;
027c5e7a
AM
13676+ if (h_i && !h_i->i_nlink)
13677+ au_set_h_iptr(inode, bindex, NULL, 0);
13678+ }
4a4d8108
AM
13679+ }
13680+
027c5e7a
AM
13681+ iinfo->ii_bstart = -1;
13682+ iinfo->ii_bend = -1;
13683+ bend = au_sbend(inode->i_sb);
13684+ for (bindex = 0; bindex <= bend; bindex++)
13685+ if (iinfo->ii_hinode[0 + bindex].hi_inode) {
13686+ iinfo->ii_bstart = bindex;
4a4d8108 13687+ break;
027c5e7a
AM
13688+ }
13689+ if (iinfo->ii_bstart >= 0)
13690+ for (bindex = bend; bindex >= iinfo->ii_bstart; bindex--)
13691+ if (iinfo->ii_hinode[0 + bindex].hi_inode) {
13692+ iinfo->ii_bend = bindex;
13693+ break;
13694+ }
13695+ AuDebugOn(iinfo->ii_bstart > iinfo->ii_bend);
1308ab2a 13696+}
1facf9fc 13697+
dece6358 13698+/* ---------------------------------------------------------------------- */
1facf9fc 13699+
4a4d8108 13700+void au_icntnr_init_once(void *_c)
dece6358 13701+{
4a4d8108
AM
13702+ struct au_icntnr *c = _c;
13703+ struct au_iinfo *iinfo = &c->iinfo;
e49829fe 13704+ static struct lock_class_key aufs_ii;
1facf9fc 13705+
4a4d8108 13706+ au_rw_init(&iinfo->ii_rwsem);
e49829fe 13707+ au_rw_class(&iinfo->ii_rwsem, &aufs_ii);
4a4d8108
AM
13708+ inode_init_once(&c->vfs_inode);
13709+}
1facf9fc 13710+
4a4d8108
AM
13711+int au_iinfo_init(struct inode *inode)
13712+{
13713+ struct au_iinfo *iinfo;
13714+ struct super_block *sb;
13715+ int nbr, i;
1facf9fc 13716+
4a4d8108
AM
13717+ sb = inode->i_sb;
13718+ iinfo = &(container_of(inode, struct au_icntnr, vfs_inode)->iinfo);
13719+ nbr = au_sbend(sb) + 1;
13720+ if (unlikely(nbr <= 0))
13721+ nbr = 1;
13722+ iinfo->ii_hinode = kcalloc(nbr, sizeof(*iinfo->ii_hinode), GFP_NOFS);
13723+ if (iinfo->ii_hinode) {
7f207e10 13724+ au_ninodes_inc(sb);
4a4d8108
AM
13725+ for (i = 0; i < nbr; i++)
13726+ iinfo->ii_hinode[i].hi_id = -1;
1facf9fc 13727+
4a4d8108
AM
13728+ atomic_set(&iinfo->ii_generation, au_sigen(sb));
13729+ /* smp_mb(); */ /* atomic_set */
13730+ iinfo->ii_bstart = -1;
13731+ iinfo->ii_bend = -1;
13732+ iinfo->ii_vdir = NULL;
13733+ return 0;
1308ab2a 13734+ }
4a4d8108
AM
13735+ return -ENOMEM;
13736+}
1facf9fc 13737+
4a4d8108
AM
13738+int au_ii_realloc(struct au_iinfo *iinfo, int nbr)
13739+{
13740+ int err, sz;
13741+ struct au_hinode *hip;
1facf9fc 13742+
4a4d8108
AM
13743+ AuRwMustWriteLock(&iinfo->ii_rwsem);
13744+
13745+ err = -ENOMEM;
13746+ sz = sizeof(*hip) * (iinfo->ii_bend + 1);
13747+ if (!sz)
13748+ sz = sizeof(*hip);
13749+ hip = au_kzrealloc(iinfo->ii_hinode, sz, sizeof(*hip) * nbr, GFP_NOFS);
13750+ if (hip) {
13751+ iinfo->ii_hinode = hip;
13752+ err = 0;
1308ab2a 13753+ }
4a4d8108 13754+
1308ab2a 13755+ return err;
1facf9fc 13756+}
13757+
4a4d8108 13758+void au_iinfo_fin(struct inode *inode)
1facf9fc 13759+{
4a4d8108
AM
13760+ struct au_iinfo *iinfo;
13761+ struct au_hinode *hi;
13762+ struct super_block *sb;
b752ccd1
AM
13763+ aufs_bindex_t bindex, bend;
13764+ const unsigned char unlinked = !inode->i_nlink;
1308ab2a 13765+
4a4d8108
AM
13766+ iinfo = au_ii(inode);
13767+ /* bad_inode case */
13768+ if (!iinfo)
13769+ return;
1308ab2a 13770+
b752ccd1 13771+ sb = inode->i_sb;
7f207e10 13772+ au_ninodes_dec(sb);
b752ccd1
AM
13773+ if (si_pid_test(sb))
13774+ au_xino_delete_inode(inode, unlinked);
13775+ else {
13776+ /*
13777+ * it is safe to hide the dependency between sbinfo and
13778+ * sb->s_umount.
13779+ */
13780+ lockdep_off();
13781+ si_noflush_read_lock(sb);
13782+ au_xino_delete_inode(inode, unlinked);
13783+ si_read_unlock(sb);
13784+ lockdep_on();
13785+ }
13786+
4a4d8108
AM
13787+ if (iinfo->ii_vdir)
13788+ au_vdir_free(iinfo->ii_vdir);
1308ab2a 13789+
b752ccd1
AM
13790+ bindex = iinfo->ii_bstart;
13791+ if (bindex >= 0) {
13792+ hi = iinfo->ii_hinode + bindex;
4a4d8108 13793+ bend = iinfo->ii_bend;
b752ccd1
AM
13794+ while (bindex++ <= bend) {
13795+ if (hi->hi_inode)
4a4d8108 13796+ au_hiput(hi);
4a4d8108
AM
13797+ hi++;
13798+ }
13799+ }
4a4d8108 13800+ kfree(iinfo->ii_hinode);
027c5e7a 13801+ iinfo->ii_hinode = NULL;
4a4d8108 13802+ AuRwDestroy(&iinfo->ii_rwsem);
dece6358 13803+}
7f207e10
AM
13804diff -urN /usr/share/empty/fs/aufs/inode.c linux/fs/aufs/inode.c
13805--- /usr/share/empty/fs/aufs/inode.c 1970-01-01 01:00:00.000000000 +0100
2dfbb274
AM
13806+++ linux/fs/aufs/inode.c 2012-08-26 08:39:00.760508065 +0200
13807@@ -0,0 +1,478 @@
4a4d8108 13808+/*
f6c5ef8b 13809+ * Copyright (C) 2005-2012 Junjiro R. Okajima
4a4d8108
AM
13810+ *
13811+ * This program, aufs is free software; you can redistribute it and/or modify
13812+ * it under the terms of the GNU General Public License as published by
13813+ * the Free Software Foundation; either version 2 of the License, or
13814+ * (at your option) any later version.
13815+ *
13816+ * This program is distributed in the hope that it will be useful,
13817+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
13818+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13819+ * GNU General Public License for more details.
13820+ *
13821+ * You should have received a copy of the GNU General Public License
13822+ * along with this program; if not, write to the Free Software
13823+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
13824+ */
1facf9fc 13825+
4a4d8108
AM
13826+/*
13827+ * inode functions
13828+ */
1facf9fc 13829+
4a4d8108 13830+#include "aufs.h"
1308ab2a 13831+
4a4d8108
AM
13832+struct inode *au_igrab(struct inode *inode)
13833+{
13834+ if (inode) {
13835+ AuDebugOn(!atomic_read(&inode->i_count));
027c5e7a 13836+ ihold(inode);
1facf9fc 13837+ }
4a4d8108
AM
13838+ return inode;
13839+}
1facf9fc 13840+
4a4d8108
AM
13841+static void au_refresh_hinode_attr(struct inode *inode, int do_version)
13842+{
13843+ au_cpup_attr_all(inode, /*force*/0);
13844+ au_update_iigen(inode);
13845+ if (do_version)
13846+ inode->i_version++;
dece6358 13847+}
1facf9fc 13848+
027c5e7a 13849+static int au_ii_refresh(struct inode *inode, int *update)
dece6358 13850+{
4a4d8108 13851+ int err, e;
027c5e7a 13852+ umode_t type;
4a4d8108 13853+ aufs_bindex_t bindex, new_bindex;
1308ab2a 13854+ struct super_block *sb;
4a4d8108 13855+ struct au_iinfo *iinfo;
027c5e7a 13856+ struct au_hinode *p, *q, tmp;
1facf9fc 13857+
4a4d8108 13858+ IiMustWriteLock(inode);
1facf9fc 13859+
027c5e7a 13860+ *update = 0;
4a4d8108 13861+ sb = inode->i_sb;
027c5e7a 13862+ type = inode->i_mode & S_IFMT;
4a4d8108
AM
13863+ iinfo = au_ii(inode);
13864+ err = au_ii_realloc(iinfo, au_sbend(sb) + 1);
13865+ if (unlikely(err))
1308ab2a 13866+ goto out;
1facf9fc 13867+
027c5e7a 13868+ AuDebugOn(iinfo->ii_bstart < 0);
4a4d8108 13869+ p = iinfo->ii_hinode + iinfo->ii_bstart;
4a4d8108
AM
13870+ for (bindex = iinfo->ii_bstart; bindex <= iinfo->ii_bend;
13871+ bindex++, p++) {
13872+ if (!p->hi_inode)
13873+ continue;
1facf9fc 13874+
027c5e7a 13875+ AuDebugOn(type != (p->hi_inode->i_mode & S_IFMT));
4a4d8108
AM
13876+ new_bindex = au_br_index(sb, p->hi_id);
13877+ if (new_bindex == bindex)
13878+ continue;
1facf9fc 13879+
4a4d8108 13880+ if (new_bindex < 0) {
027c5e7a 13881+ *update = 1;
4a4d8108
AM
13882+ au_hiput(p);
13883+ p->hi_inode = NULL;
13884+ continue;
1308ab2a 13885+ }
4a4d8108
AM
13886+
13887+ if (new_bindex < iinfo->ii_bstart)
13888+ iinfo->ii_bstart = new_bindex;
13889+ if (iinfo->ii_bend < new_bindex)
13890+ iinfo->ii_bend = new_bindex;
13891+ /* swap two lower inode, and loop again */
13892+ q = iinfo->ii_hinode + new_bindex;
13893+ tmp = *q;
13894+ *q = *p;
13895+ *p = tmp;
13896+ if (tmp.hi_inode) {
13897+ bindex--;
13898+ p--;
1308ab2a 13899+ }
13900+ }
4a4d8108
AM
13901+ au_update_ibrange(inode, /*do_put_zero*/0);
13902+ e = au_dy_irefresh(inode);
13903+ if (unlikely(e && !err))
13904+ err = e;
1facf9fc 13905+
4f0767ce 13906+out:
027c5e7a
AM
13907+ AuTraceErr(err);
13908+ return err;
13909+}
13910+
13911+int au_refresh_hinode_self(struct inode *inode)
13912+{
13913+ int err, update;
13914+
13915+ err = au_ii_refresh(inode, &update);
13916+ if (!err)
13917+ au_refresh_hinode_attr(inode, update && S_ISDIR(inode->i_mode));
13918+
13919+ AuTraceErr(err);
4a4d8108
AM
13920+ return err;
13921+}
1facf9fc 13922+
4a4d8108
AM
13923+int au_refresh_hinode(struct inode *inode, struct dentry *dentry)
13924+{
027c5e7a 13925+ int err, e, update;
4a4d8108 13926+ unsigned int flags;
027c5e7a 13927+ umode_t mode;
4a4d8108 13928+ aufs_bindex_t bindex, bend;
027c5e7a 13929+ unsigned char isdir;
4a4d8108
AM
13930+ struct au_hinode *p;
13931+ struct au_iinfo *iinfo;
1facf9fc 13932+
027c5e7a 13933+ err = au_ii_refresh(inode, &update);
4a4d8108
AM
13934+ if (unlikely(err))
13935+ goto out;
13936+
13937+ update = 0;
13938+ iinfo = au_ii(inode);
13939+ p = iinfo->ii_hinode + iinfo->ii_bstart;
027c5e7a
AM
13940+ mode = (inode->i_mode & S_IFMT);
13941+ isdir = S_ISDIR(mode);
4a4d8108
AM
13942+ flags = au_hi_flags(inode, isdir);
13943+ bend = au_dbend(dentry);
13944+ for (bindex = au_dbstart(dentry); bindex <= bend; bindex++) {
13945+ struct inode *h_i;
13946+ struct dentry *h_d;
13947+
13948+ h_d = au_h_dptr(dentry, bindex);
13949+ if (!h_d || !h_d->d_inode)
13950+ continue;
13951+
027c5e7a 13952+ AuDebugOn(mode != (h_d->d_inode->i_mode & S_IFMT));
4a4d8108
AM
13953+ if (iinfo->ii_bstart <= bindex && bindex <= iinfo->ii_bend) {
13954+ h_i = au_h_iptr(inode, bindex);
13955+ if (h_i) {
13956+ if (h_i == h_d->d_inode)
13957+ continue;
13958+ err = -EIO;
13959+ break;
13960+ }
13961+ }
13962+ if (bindex < iinfo->ii_bstart)
13963+ iinfo->ii_bstart = bindex;
13964+ if (iinfo->ii_bend < bindex)
13965+ iinfo->ii_bend = bindex;
13966+ au_set_h_iptr(inode, bindex, au_igrab(h_d->d_inode), flags);
13967+ update = 1;
1308ab2a 13968+ }
4a4d8108
AM
13969+ au_update_ibrange(inode, /*do_put_zero*/0);
13970+ e = au_dy_irefresh(inode);
13971+ if (unlikely(e && !err))
13972+ err = e;
027c5e7a
AM
13973+ if (!err)
13974+ au_refresh_hinode_attr(inode, update && isdir);
4a4d8108 13975+
4f0767ce 13976+out:
4a4d8108 13977+ AuTraceErr(err);
1308ab2a 13978+ return err;
dece6358
AM
13979+}
13980+
4a4d8108 13981+static int set_inode(struct inode *inode, struct dentry *dentry)
dece6358 13982+{
4a4d8108
AM
13983+ int err;
13984+ unsigned int flags;
13985+ umode_t mode;
13986+ aufs_bindex_t bindex, bstart, btail;
13987+ unsigned char isdir;
13988+ struct dentry *h_dentry;
13989+ struct inode *h_inode;
13990+ struct au_iinfo *iinfo;
dece6358 13991+
4a4d8108 13992+ IiMustWriteLock(inode);
dece6358 13993+
4a4d8108
AM
13994+ err = 0;
13995+ isdir = 0;
13996+ bstart = au_dbstart(dentry);
13997+ h_inode = au_h_dptr(dentry, bstart)->d_inode;
13998+ mode = h_inode->i_mode;
13999+ switch (mode & S_IFMT) {
14000+ case S_IFREG:
14001+ btail = au_dbtail(dentry);
14002+ inode->i_op = &aufs_iop;
14003+ inode->i_fop = &aufs_file_fop;
14004+ err = au_dy_iaop(inode, bstart, h_inode);
14005+ if (unlikely(err))
14006+ goto out;
14007+ break;
14008+ case S_IFDIR:
14009+ isdir = 1;
14010+ btail = au_dbtaildir(dentry);
14011+ inode->i_op = &aufs_dir_iop;
14012+ inode->i_fop = &aufs_dir_fop;
14013+ break;
14014+ case S_IFLNK:
14015+ btail = au_dbtail(dentry);
14016+ inode->i_op = &aufs_symlink_iop;
14017+ break;
14018+ case S_IFBLK:
14019+ case S_IFCHR:
14020+ case S_IFIFO:
14021+ case S_IFSOCK:
14022+ btail = au_dbtail(dentry);
14023+ inode->i_op = &aufs_iop;
14024+ au_init_special_fop(inode, mode, h_inode->i_rdev);
14025+ break;
14026+ default:
14027+ AuIOErr("Unknown file type 0%o\n", mode);
14028+ err = -EIO;
1308ab2a 14029+ goto out;
4a4d8108 14030+ }
dece6358 14031+
4a4d8108
AM
14032+ /* do not set hnotify for whiteouted dirs (SHWH mode) */
14033+ flags = au_hi_flags(inode, isdir);
14034+ if (au_opt_test(au_mntflags(dentry->d_sb), SHWH)
14035+ && au_ftest_hi(flags, HNOTIFY)
14036+ && dentry->d_name.len > AUFS_WH_PFX_LEN
14037+ && !memcmp(dentry->d_name.name, AUFS_WH_PFX, AUFS_WH_PFX_LEN))
14038+ au_fclr_hi(flags, HNOTIFY);
14039+ iinfo = au_ii(inode);
14040+ iinfo->ii_bstart = bstart;
14041+ iinfo->ii_bend = btail;
14042+ for (bindex = bstart; bindex <= btail; bindex++) {
14043+ h_dentry = au_h_dptr(dentry, bindex);
14044+ if (h_dentry)
14045+ au_set_h_iptr(inode, bindex,
14046+ au_igrab(h_dentry->d_inode), flags);
14047+ }
14048+ au_cpup_attr_all(inode, /*force*/1);
dece6358 14049+
4f0767ce 14050+out:
4a4d8108
AM
14051+ return err;
14052+}
dece6358 14053+
027c5e7a
AM
14054+/*
14055+ * successful returns with iinfo write_locked
14056+ * minus: errno
14057+ * zero: success, matched
14058+ * plus: no error, but unmatched
14059+ */
14060+static int reval_inode(struct inode *inode, struct dentry *dentry)
4a4d8108
AM
14061+{
14062+ int err;
14063+ aufs_bindex_t bindex, bend;
14064+ struct inode *h_inode, *h_dinode;
dece6358 14065+
4a4d8108
AM
14066+ /*
14067+ * before this function, if aufs got any iinfo lock, it must be only
14068+ * one, the parent dir.
14069+ * it can happen by UDBA and the obsoleted inode number.
14070+ */
14071+ err = -EIO;
14072+ if (unlikely(inode->i_ino == parent_ino(dentry)))
14073+ goto out;
14074+
027c5e7a 14075+ err = 1;
4a4d8108
AM
14076+ ii_write_lock_new_child(inode);
14077+ h_dinode = au_h_dptr(dentry, au_dbstart(dentry))->d_inode;
14078+ bend = au_ibend(inode);
14079+ for (bindex = au_ibstart(inode); bindex <= bend; bindex++) {
14080+ h_inode = au_h_iptr(inode, bindex);
14081+ if (h_inode && h_inode == h_dinode) {
4a4d8108 14082+ err = 0;
027c5e7a 14083+ if (au_iigen_test(inode, au_digen(dentry)))
4a4d8108
AM
14084+ err = au_refresh_hinode(inode, dentry);
14085+ break;
1308ab2a 14086+ }
1facf9fc 14087+ }
dece6358 14088+
4a4d8108
AM
14089+ if (unlikely(err))
14090+ ii_write_unlock(inode);
4f0767ce 14091+out:
1facf9fc 14092+ return err;
14093+}
1facf9fc 14094+
4a4d8108
AM
14095+int au_ino(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino,
14096+ unsigned int d_type, ino_t *ino)
1facf9fc 14097+{
4a4d8108
AM
14098+ int err;
14099+ struct mutex *mtx;
1facf9fc 14100+
b752ccd1 14101+ /* prevent hardlinked inode number from race condition */
4a4d8108 14102+ mtx = NULL;
b752ccd1 14103+ if (d_type != DT_DIR) {
4a4d8108
AM
14104+ mtx = &au_sbr(sb, bindex)->br_xino.xi_nondir_mtx;
14105+ mutex_lock(mtx);
14106+ }
14107+ err = au_xino_read(sb, bindex, h_ino, ino);
14108+ if (unlikely(err))
14109+ goto out;
1308ab2a 14110+
4a4d8108
AM
14111+ if (!*ino) {
14112+ err = -EIO;
14113+ *ino = au_xino_new_ino(sb);
14114+ if (unlikely(!*ino))
1facf9fc 14115+ goto out;
4a4d8108
AM
14116+ err = au_xino_write(sb, bindex, h_ino, *ino);
14117+ if (unlikely(err))
1308ab2a 14118+ goto out;
1308ab2a 14119+ }
1facf9fc 14120+
4f0767ce 14121+out:
b752ccd1 14122+ if (mtx)
4a4d8108 14123+ mutex_unlock(mtx);
1facf9fc 14124+ return err;
14125+}
14126+
4a4d8108
AM
14127+/* successful returns with iinfo write_locked */
14128+/* todo: return with unlocked? */
14129+struct inode *au_new_inode(struct dentry *dentry, int must_new)
1facf9fc 14130+{
b752ccd1 14131+ struct inode *inode, *h_inode;
4a4d8108
AM
14132+ struct dentry *h_dentry;
14133+ struct super_block *sb;
b752ccd1 14134+ struct mutex *mtx;
4a4d8108 14135+ ino_t h_ino, ino;
2dfbb274 14136+ int err, lc_idx;
4a4d8108 14137+ aufs_bindex_t bstart;
1facf9fc 14138+
4a4d8108
AM
14139+ sb = dentry->d_sb;
14140+ bstart = au_dbstart(dentry);
14141+ h_dentry = au_h_dptr(dentry, bstart);
b752ccd1
AM
14142+ h_inode = h_dentry->d_inode;
14143+ h_ino = h_inode->i_ino;
14144+
14145+ /*
14146+ * stop 'race'-ing between hardlinks under different
14147+ * parents.
14148+ */
14149+ mtx = NULL;
14150+ if (!S_ISDIR(h_inode->i_mode))
14151+ mtx = &au_sbr(sb, bstart)->br_xino.xi_nondir_mtx;
14152+
4f0767ce 14153+new_ino:
b752ccd1
AM
14154+ if (mtx)
14155+ mutex_lock(mtx);
4a4d8108
AM
14156+ err = au_xino_read(sb, bstart, h_ino, &ino);
14157+ inode = ERR_PTR(err);
14158+ if (unlikely(err))
14159+ goto out;
b752ccd1 14160+
4a4d8108
AM
14161+ if (!ino) {
14162+ ino = au_xino_new_ino(sb);
14163+ if (unlikely(!ino)) {
14164+ inode = ERR_PTR(-EIO);
dece6358
AM
14165+ goto out;
14166+ }
14167+ }
1facf9fc 14168+
4a4d8108
AM
14169+ AuDbg("i%lu\n", (unsigned long)ino);
14170+ inode = au_iget_locked(sb, ino);
14171+ err = PTR_ERR(inode);
14172+ if (IS_ERR(inode))
1facf9fc 14173+ goto out;
1facf9fc 14174+
4a4d8108
AM
14175+ AuDbg("%lx, new %d\n", inode->i_state, !!(inode->i_state & I_NEW));
14176+ if (inode->i_state & I_NEW) {
2dfbb274
AM
14177+ lc_idx = AuLcNonDir_IIINFO;
14178+ if (S_ISLNK(h_inode->i_mode))
14179+ lc_idx = AuLcSymlink_IIINFO;
14180+ else if (S_ISDIR(h_inode->i_mode))
14181+ lc_idx = AuLcDir_IIINFO;
14182+ au_rw_class(&au_ii(inode)->ii_rwsem, au_lc_key + lc_idx);
14183+
4a4d8108
AM
14184+ ii_write_lock_new_child(inode);
14185+ err = set_inode(inode, dentry);
14186+ if (!err) {
14187+ unlock_new_inode(inode);
14188+ goto out; /* success */
14189+ }
1308ab2a 14190+
027c5e7a
AM
14191+ /*
14192+ * iget_failed() calls iput(), but we need to call
14193+ * ii_write_unlock() after iget_failed(). so dirty hack for
14194+ * i_count.
14195+ */
14196+ atomic_inc(&inode->i_count);
4a4d8108 14197+ iget_failed(inode);
027c5e7a
AM
14198+ ii_write_unlock(inode);
14199+ au_xino_write(sb, bstart, h_ino, /*ino*/0);
14200+ /* ignore this error */
14201+ goto out_iput;
14202+ } else if (!must_new && !IS_DEADDIR(inode) && inode->i_nlink) {
b752ccd1
AM
14203+ /*
14204+ * horrible race condition between lookup, readdir and copyup
14205+ * (or something).
14206+ */
14207+ if (mtx)
14208+ mutex_unlock(mtx);
027c5e7a
AM
14209+ err = reval_inode(inode, dentry);
14210+ if (unlikely(err < 0)) {
14211+ mtx = NULL;
14212+ goto out_iput;
14213+ }
14214+
b752ccd1
AM
14215+ if (!err) {
14216+ mtx = NULL;
4a4d8108 14217+ goto out; /* success */
b752ccd1
AM
14218+ } else if (mtx)
14219+ mutex_lock(mtx);
4a4d8108
AM
14220+ }
14221+
14222+ if (unlikely(au_test_fs_unique_ino(h_dentry->d_inode)))
14223+ AuWarn1("Warning: Un-notified UDBA or repeatedly renamed dir,"
14224+ " b%d, %s, %.*s, hi%lu, i%lu.\n",
14225+ bstart, au_sbtype(h_dentry->d_sb), AuDLNPair(dentry),
14226+ (unsigned long)h_ino, (unsigned long)ino);
14227+ ino = 0;
14228+ err = au_xino_write(sb, bstart, h_ino, /*ino*/0);
14229+ if (!err) {
14230+ iput(inode);
b752ccd1
AM
14231+ if (mtx)
14232+ mutex_unlock(mtx);
4a4d8108
AM
14233+ goto new_ino;
14234+ }
1308ab2a 14235+
4f0767ce 14236+out_iput:
4a4d8108 14237+ iput(inode);
4a4d8108 14238+ inode = ERR_PTR(err);
4f0767ce 14239+out:
b752ccd1
AM
14240+ if (mtx)
14241+ mutex_unlock(mtx);
4a4d8108 14242+ return inode;
1facf9fc 14243+}
14244+
4a4d8108 14245+/* ---------------------------------------------------------------------- */
1facf9fc 14246+
4a4d8108
AM
14247+int au_test_ro(struct super_block *sb, aufs_bindex_t bindex,
14248+ struct inode *inode)
14249+{
14250+ int err;
1facf9fc 14251+
4a4d8108 14252+ err = au_br_rdonly(au_sbr(sb, bindex));
1facf9fc 14253+
4a4d8108
AM
14254+ /* pseudo-link after flushed may happen out of bounds */
14255+ if (!err
14256+ && inode
14257+ && au_ibstart(inode) <= bindex
14258+ && bindex <= au_ibend(inode)) {
14259+ /*
14260+ * permission check is unnecessary since vfsub routine
14261+ * will be called later
14262+ */
14263+ struct inode *hi = au_h_iptr(inode, bindex);
14264+ if (hi)
14265+ err = IS_IMMUTABLE(hi) ? -EROFS : 0;
1facf9fc 14266+ }
14267+
4a4d8108
AM
14268+ return err;
14269+}
dece6358 14270+
4a4d8108
AM
14271+int au_test_h_perm(struct inode *h_inode, int mask)
14272+{
2dfbb274 14273+ if (uid_eq(current_fsuid(), GLOBAL_ROOT_UID))
4a4d8108
AM
14274+ return 0;
14275+ return inode_permission(h_inode, mask);
14276+}
1facf9fc 14277+
4a4d8108
AM
14278+int au_test_h_perm_sio(struct inode *h_inode, int mask)
14279+{
14280+ if (au_test_nfs(h_inode->i_sb)
14281+ && (mask & MAY_WRITE)
14282+ && S_ISDIR(h_inode->i_mode))
14283+ mask |= MAY_READ; /* force permission check */
14284+ return au_test_h_perm(h_inode, mask);
1facf9fc 14285+}
7f207e10
AM
14286diff -urN /usr/share/empty/fs/aufs/inode.h linux/fs/aufs/inode.h
14287--- /usr/share/empty/fs/aufs/inode.h 1970-01-01 01:00:00.000000000 +0100
b4510431 14288+++ linux/fs/aufs/inode.h 2012-10-17 10:31:01.772481151 +0200
7eafdf33 14289@@ -0,0 +1,560 @@
4a4d8108 14290+/*
f6c5ef8b 14291+ * Copyright (C) 2005-2012 Junjiro R. Okajima
4a4d8108
AM
14292+ *
14293+ * This program, aufs is free software; you can redistribute it and/or modify
14294+ * it under the terms of the GNU General Public License as published by
14295+ * the Free Software Foundation; either version 2 of the License, or
14296+ * (at your option) any later version.
14297+ *
14298+ * This program is distributed in the hope that it will be useful,
14299+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
14300+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14301+ * GNU General Public License for more details.
14302+ *
14303+ * You should have received a copy of the GNU General Public License
14304+ * along with this program; if not, write to the Free Software
14305+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
14306+ */
1facf9fc 14307+
1308ab2a 14308+/*
4a4d8108 14309+ * inode operations
1308ab2a 14310+ */
dece6358 14311+
4a4d8108
AM
14312+#ifndef __AUFS_INODE_H__
14313+#define __AUFS_INODE_H__
dece6358 14314+
4a4d8108 14315+#ifdef __KERNEL__
1308ab2a 14316+
4a4d8108 14317+#include <linux/fsnotify.h>
4a4d8108 14318+#include "rwsem.h"
1308ab2a 14319+
4a4d8108 14320+struct vfsmount;
1facf9fc 14321+
4a4d8108
AM
14322+struct au_hnotify {
14323+#ifdef CONFIG_AUFS_HNOTIFY
14324+#ifdef CONFIG_AUFS_HFSNOTIFY
7f207e10 14325+ /* never use fsnotify_add_vfsmount_mark() */
0c5527e5 14326+ struct fsnotify_mark hn_mark;
4a4d8108 14327+#endif
7f207e10 14328+ struct inode *hn_aufs_inode; /* no get/put */
4a4d8108
AM
14329+#endif
14330+} ____cacheline_aligned_in_smp;
1facf9fc 14331+
4a4d8108
AM
14332+struct au_hinode {
14333+ struct inode *hi_inode;
14334+ aufs_bindex_t hi_id;
14335+#ifdef CONFIG_AUFS_HNOTIFY
14336+ struct au_hnotify *hi_notify;
14337+#endif
dece6358 14338+
4a4d8108
AM
14339+ /* reference to the copied-up whiteout with get/put */
14340+ struct dentry *hi_whdentry;
14341+};
dece6358 14342+
4a4d8108
AM
14343+struct au_vdir;
14344+struct au_iinfo {
14345+ atomic_t ii_generation;
14346+ struct super_block *ii_hsb1; /* no get/put */
1facf9fc 14347+
4a4d8108
AM
14348+ struct au_rwsem ii_rwsem;
14349+ aufs_bindex_t ii_bstart, ii_bend;
14350+ __u32 ii_higen;
14351+ struct au_hinode *ii_hinode;
14352+ struct au_vdir *ii_vdir;
14353+};
1facf9fc 14354+
4a4d8108
AM
14355+struct au_icntnr {
14356+ struct au_iinfo iinfo;
14357+ struct inode vfs_inode;
14358+} ____cacheline_aligned_in_smp;
1308ab2a 14359+
4a4d8108
AM
14360+/* au_pin flags */
14361+#define AuPin_DI_LOCKED 1
14362+#define AuPin_MNT_WRITE (1 << 1)
14363+#define au_ftest_pin(flags, name) ((flags) & AuPin_##name)
7f207e10
AM
14364+#define au_fset_pin(flags, name) \
14365+ do { (flags) |= AuPin_##name; } while (0)
14366+#define au_fclr_pin(flags, name) \
14367+ do { (flags) &= ~AuPin_##name; } while (0)
4a4d8108
AM
14368+
14369+struct au_pin {
14370+ /* input */
14371+ struct dentry *dentry;
14372+ unsigned int udba;
14373+ unsigned char lsc_di, lsc_hi, flags;
14374+ aufs_bindex_t bindex;
14375+
14376+ /* output */
14377+ struct dentry *parent;
14378+ struct au_hinode *hdir;
14379+ struct vfsmount *h_mnt;
14380+};
1facf9fc 14381+
1308ab2a 14382+/* ---------------------------------------------------------------------- */
14383+
4a4d8108 14384+static inline struct au_iinfo *au_ii(struct inode *inode)
1facf9fc 14385+{
4a4d8108 14386+ struct au_iinfo *iinfo;
1facf9fc 14387+
4a4d8108
AM
14388+ iinfo = &(container_of(inode, struct au_icntnr, vfs_inode)->iinfo);
14389+ if (iinfo->ii_hinode)
14390+ return iinfo;
14391+ return NULL; /* debugging bad_inode case */
14392+}
1facf9fc 14393+
4a4d8108 14394+/* ---------------------------------------------------------------------- */
1facf9fc 14395+
4a4d8108
AM
14396+/* inode.c */
14397+struct inode *au_igrab(struct inode *inode);
027c5e7a 14398+int au_refresh_hinode_self(struct inode *inode);
4a4d8108
AM
14399+int au_refresh_hinode(struct inode *inode, struct dentry *dentry);
14400+int au_ino(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino,
14401+ unsigned int d_type, ino_t *ino);
14402+struct inode *au_new_inode(struct dentry *dentry, int must_new);
14403+int au_test_ro(struct super_block *sb, aufs_bindex_t bindex,
14404+ struct inode *inode);
14405+int au_test_h_perm(struct inode *h_inode, int mask);
14406+int au_test_h_perm_sio(struct inode *h_inode, int mask);
1facf9fc 14407+
4a4d8108
AM
14408+static inline int au_wh_ino(struct super_block *sb, aufs_bindex_t bindex,
14409+ ino_t h_ino, unsigned int d_type, ino_t *ino)
14410+{
14411+#ifdef CONFIG_AUFS_SHWH
14412+ return au_ino(sb, bindex, h_ino, d_type, ino);
14413+#else
14414+ return 0;
14415+#endif
14416+}
1facf9fc 14417+
4a4d8108
AM
14418+/* i_op.c */
14419+extern struct inode_operations aufs_iop, aufs_symlink_iop, aufs_dir_iop;
1308ab2a 14420+
4a4d8108
AM
14421+/* au_wr_dir flags */
14422+#define AuWrDir_ADD_ENTRY 1
14423+#define AuWrDir_ISDIR (1 << 1)
14424+#define au_ftest_wrdir(flags, name) ((flags) & AuWrDir_##name)
7f207e10
AM
14425+#define au_fset_wrdir(flags, name) \
14426+ do { (flags) |= AuWrDir_##name; } while (0)
14427+#define au_fclr_wrdir(flags, name) \
14428+ do { (flags) &= ~AuWrDir_##name; } while (0)
1facf9fc 14429+
4a4d8108
AM
14430+struct au_wr_dir_args {
14431+ aufs_bindex_t force_btgt;
14432+ unsigned char flags;
14433+};
14434+int au_wr_dir(struct dentry *dentry, struct dentry *src_dentry,
14435+ struct au_wr_dir_args *args);
dece6358 14436+
4a4d8108
AM
14437+struct dentry *au_pinned_h_parent(struct au_pin *pin);
14438+void au_pin_init(struct au_pin *pin, struct dentry *dentry,
14439+ aufs_bindex_t bindex, int lsc_di, int lsc_hi,
14440+ unsigned int udba, unsigned char flags);
14441+int au_pin(struct au_pin *pin, struct dentry *dentry, aufs_bindex_t bindex,
14442+ unsigned int udba, unsigned char flags) __must_check;
14443+int au_do_pin(struct au_pin *pin) __must_check;
14444+void au_unpin(struct au_pin *pin);
1facf9fc 14445+
4a4d8108
AM
14446+/* i_op_add.c */
14447+int au_may_add(struct dentry *dentry, aufs_bindex_t bindex,
14448+ struct dentry *h_parent, int isdir);
7eafdf33
AM
14449+int aufs_mknod(struct inode *dir, struct dentry *dentry, umode_t mode,
14450+ dev_t dev);
4a4d8108 14451+int aufs_symlink(struct inode *dir, struct dentry *dentry, const char *symname);
7eafdf33 14452+int aufs_create(struct inode *dir, struct dentry *dentry, umode_t mode,
b4510431 14453+ bool want_excl);
4a4d8108
AM
14454+int aufs_link(struct dentry *src_dentry, struct inode *dir,
14455+ struct dentry *dentry);
7eafdf33 14456+int aufs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode);
1facf9fc 14457+
4a4d8108
AM
14458+/* i_op_del.c */
14459+int au_wr_dir_need_wh(struct dentry *dentry, int isdir, aufs_bindex_t *bcpup);
14460+int au_may_del(struct dentry *dentry, aufs_bindex_t bindex,
14461+ struct dentry *h_parent, int isdir);
14462+int aufs_unlink(struct inode *dir, struct dentry *dentry);
14463+int aufs_rmdir(struct inode *dir, struct dentry *dentry);
1308ab2a 14464+
4a4d8108
AM
14465+/* i_op_ren.c */
14466+int au_wbr(struct dentry *dentry, aufs_bindex_t btgt);
14467+int aufs_rename(struct inode *src_dir, struct dentry *src_dentry,
14468+ struct inode *dir, struct dentry *dentry);
1facf9fc 14469+
4a4d8108
AM
14470+/* iinfo.c */
14471+struct inode *au_h_iptr(struct inode *inode, aufs_bindex_t bindex);
14472+void au_hiput(struct au_hinode *hinode);
14473+void au_set_hi_wh(struct inode *inode, aufs_bindex_t bindex,
14474+ struct dentry *h_wh);
14475+unsigned int au_hi_flags(struct inode *inode, int isdir);
1308ab2a 14476+
4a4d8108
AM
14477+/* hinode flags */
14478+#define AuHi_XINO 1
14479+#define AuHi_HNOTIFY (1 << 1)
14480+#define au_ftest_hi(flags, name) ((flags) & AuHi_##name)
7f207e10
AM
14481+#define au_fset_hi(flags, name) \
14482+ do { (flags) |= AuHi_##name; } while (0)
14483+#define au_fclr_hi(flags, name) \
14484+ do { (flags) &= ~AuHi_##name; } while (0)
1facf9fc 14485+
4a4d8108
AM
14486+#ifndef CONFIG_AUFS_HNOTIFY
14487+#undef AuHi_HNOTIFY
14488+#define AuHi_HNOTIFY 0
14489+#endif
1facf9fc 14490+
4a4d8108
AM
14491+void au_set_h_iptr(struct inode *inode, aufs_bindex_t bindex,
14492+ struct inode *h_inode, unsigned int flags);
1facf9fc 14493+
4a4d8108
AM
14494+void au_update_iigen(struct inode *inode);
14495+void au_update_ibrange(struct inode *inode, int do_put_zero);
1facf9fc 14496+
4a4d8108
AM
14497+void au_icntnr_init_once(void *_c);
14498+int au_iinfo_init(struct inode *inode);
14499+void au_iinfo_fin(struct inode *inode);
14500+int au_ii_realloc(struct au_iinfo *iinfo, int nbr);
1308ab2a 14501+
e49829fe 14502+#ifdef CONFIG_PROC_FS
4a4d8108 14503+/* plink.c */
e49829fe
JR
14504+int au_plink_maint(struct super_block *sb, int flags);
14505+void au_plink_maint_leave(struct au_sbinfo *sbinfo);
14506+int au_plink_maint_enter(struct super_block *sb);
4a4d8108
AM
14507+#ifdef CONFIG_AUFS_DEBUG
14508+void au_plink_list(struct super_block *sb);
14509+#else
14510+AuStubVoid(au_plink_list, struct super_block *sb)
14511+#endif
14512+int au_plink_test(struct inode *inode);
14513+struct dentry *au_plink_lkup(struct inode *inode, aufs_bindex_t bindex);
14514+void au_plink_append(struct inode *inode, aufs_bindex_t bindex,
14515+ struct dentry *h_dentry);
e49829fe
JR
14516+void au_plink_put(struct super_block *sb, int verbose);
14517+void au_plink_clean(struct super_block *sb, int verbose);
4a4d8108 14518+void au_plink_half_refresh(struct super_block *sb, aufs_bindex_t br_id);
e49829fe
JR
14519+#else
14520+AuStubInt0(au_plink_maint, struct super_block *sb, int flags);
14521+AuStubVoid(au_plink_maint_leave, struct au_sbinfo *sbinfo);
14522+AuStubInt0(au_plink_maint_enter, struct super_block *sb);
14523+AuStubVoid(au_plink_list, struct super_block *sb);
14524+AuStubInt0(au_plink_test, struct inode *inode);
14525+AuStub(struct dentry *, au_plink_lkup, return NULL,
14526+ struct inode *inode, aufs_bindex_t bindex);
14527+AuStubVoid(au_plink_append, struct inode *inode, aufs_bindex_t bindex,
14528+ struct dentry *h_dentry);
14529+AuStubVoid(au_plink_put, struct super_block *sb, int verbose);
14530+AuStubVoid(au_plink_clean, struct super_block *sb, int verbose);
14531+AuStubVoid(au_plink_half_refresh, struct super_block *sb, aufs_bindex_t br_id);
14532+#endif /* CONFIG_PROC_FS */
1facf9fc 14533+
4a4d8108 14534+/* ---------------------------------------------------------------------- */
1308ab2a 14535+
4a4d8108
AM
14536+/* lock subclass for iinfo */
14537+enum {
14538+ AuLsc_II_CHILD, /* child first */
14539+ AuLsc_II_CHILD2, /* rename(2), link(2), and cpup at hnotify */
14540+ AuLsc_II_CHILD3, /* copyup dirs */
14541+ AuLsc_II_PARENT, /* see AuLsc_I_PARENT in vfsub.h */
14542+ AuLsc_II_PARENT2,
14543+ AuLsc_II_PARENT3, /* copyup dirs */
14544+ AuLsc_II_NEW_CHILD
14545+};
1308ab2a 14546+
1facf9fc 14547+/*
4a4d8108
AM
14548+ * ii_read_lock_child, ii_write_lock_child,
14549+ * ii_read_lock_child2, ii_write_lock_child2,
14550+ * ii_read_lock_child3, ii_write_lock_child3,
14551+ * ii_read_lock_parent, ii_write_lock_parent,
14552+ * ii_read_lock_parent2, ii_write_lock_parent2,
14553+ * ii_read_lock_parent3, ii_write_lock_parent3,
14554+ * ii_read_lock_new_child, ii_write_lock_new_child,
1facf9fc 14555+ */
4a4d8108
AM
14556+#define AuReadLockFunc(name, lsc) \
14557+static inline void ii_read_lock_##name(struct inode *i) \
14558+{ \
14559+ au_rw_read_lock_nested(&au_ii(i)->ii_rwsem, AuLsc_II_##lsc); \
14560+}
14561+
14562+#define AuWriteLockFunc(name, lsc) \
14563+static inline void ii_write_lock_##name(struct inode *i) \
14564+{ \
14565+ au_rw_write_lock_nested(&au_ii(i)->ii_rwsem, AuLsc_II_##lsc); \
14566+}
14567+
14568+#define AuRWLockFuncs(name, lsc) \
14569+ AuReadLockFunc(name, lsc) \
14570+ AuWriteLockFunc(name, lsc)
14571+
14572+AuRWLockFuncs(child, CHILD);
14573+AuRWLockFuncs(child2, CHILD2);
14574+AuRWLockFuncs(child3, CHILD3);
14575+AuRWLockFuncs(parent, PARENT);
14576+AuRWLockFuncs(parent2, PARENT2);
14577+AuRWLockFuncs(parent3, PARENT3);
14578+AuRWLockFuncs(new_child, NEW_CHILD);
14579+
14580+#undef AuReadLockFunc
14581+#undef AuWriteLockFunc
14582+#undef AuRWLockFuncs
1facf9fc 14583+
14584+/*
4a4d8108 14585+ * ii_read_unlock, ii_write_unlock, ii_downgrade_lock
1facf9fc 14586+ */
4a4d8108 14587+AuSimpleUnlockRwsemFuncs(ii, struct inode *i, &au_ii(i)->ii_rwsem);
1facf9fc 14588+
4a4d8108
AM
14589+#define IiMustNoWaiters(i) AuRwMustNoWaiters(&au_ii(i)->ii_rwsem)
14590+#define IiMustAnyLock(i) AuRwMustAnyLock(&au_ii(i)->ii_rwsem)
14591+#define IiMustWriteLock(i) AuRwMustWriteLock(&au_ii(i)->ii_rwsem)
1facf9fc 14592+
4a4d8108 14593+/* ---------------------------------------------------------------------- */
1308ab2a 14594+
027c5e7a
AM
14595+static inline void au_icntnr_init(struct au_icntnr *c)
14596+{
14597+#ifdef CONFIG_AUFS_DEBUG
14598+ c->vfs_inode.i_mode = 0;
14599+#endif
14600+}
14601+
4a4d8108
AM
14602+static inline unsigned int au_iigen(struct inode *inode)
14603+{
14604+ return atomic_read(&au_ii(inode)->ii_generation);
14605+}
1308ab2a 14606+
4a4d8108
AM
14607+/* tiny test for inode number */
14608+/* tmpfs generation is too rough */
14609+static inline int au_test_higen(struct inode *inode, struct inode *h_inode)
14610+{
14611+ struct au_iinfo *iinfo;
1308ab2a 14612+
4a4d8108
AM
14613+ iinfo = au_ii(inode);
14614+ AuRwMustAnyLock(&iinfo->ii_rwsem);
14615+ return !(iinfo->ii_hsb1 == h_inode->i_sb
14616+ && iinfo->ii_higen == h_inode->i_generation);
14617+}
1308ab2a 14618+
4a4d8108
AM
14619+static inline void au_iigen_dec(struct inode *inode)
14620+{
e49829fe 14621+ atomic_dec(&au_ii(inode)->ii_generation);
027c5e7a
AM
14622+}
14623+
14624+static inline int au_iigen_test(struct inode *inode, unsigned int sigen)
14625+{
14626+ int err;
14627+
14628+ err = 0;
14629+ if (unlikely(inode && au_iigen(inode) != sigen))
14630+ err = -EIO;
14631+
14632+ return err;
4a4d8108 14633+}
1308ab2a 14634+
4a4d8108 14635+/* ---------------------------------------------------------------------- */
1308ab2a 14636+
4a4d8108
AM
14637+static inline aufs_bindex_t au_ii_br_id(struct inode *inode,
14638+ aufs_bindex_t bindex)
14639+{
14640+ IiMustAnyLock(inode);
14641+ return au_ii(inode)->ii_hinode[0 + bindex].hi_id;
14642+}
1308ab2a 14643+
4a4d8108
AM
14644+static inline aufs_bindex_t au_ibstart(struct inode *inode)
14645+{
14646+ IiMustAnyLock(inode);
14647+ return au_ii(inode)->ii_bstart;
14648+}
1308ab2a 14649+
4a4d8108
AM
14650+static inline aufs_bindex_t au_ibend(struct inode *inode)
14651+{
14652+ IiMustAnyLock(inode);
14653+ return au_ii(inode)->ii_bend;
14654+}
1308ab2a 14655+
4a4d8108
AM
14656+static inline struct au_vdir *au_ivdir(struct inode *inode)
14657+{
14658+ IiMustAnyLock(inode);
14659+ return au_ii(inode)->ii_vdir;
14660+}
1308ab2a 14661+
4a4d8108
AM
14662+static inline struct dentry *au_hi_wh(struct inode *inode, aufs_bindex_t bindex)
14663+{
14664+ IiMustAnyLock(inode);
14665+ return au_ii(inode)->ii_hinode[0 + bindex].hi_whdentry;
14666+}
1308ab2a 14667+
4a4d8108 14668+static inline void au_set_ibstart(struct inode *inode, aufs_bindex_t bindex)
1308ab2a 14669+{
4a4d8108
AM
14670+ IiMustWriteLock(inode);
14671+ au_ii(inode)->ii_bstart = bindex;
14672+}
1308ab2a 14673+
4a4d8108
AM
14674+static inline void au_set_ibend(struct inode *inode, aufs_bindex_t bindex)
14675+{
14676+ IiMustWriteLock(inode);
14677+ au_ii(inode)->ii_bend = bindex;
1308ab2a 14678+}
14679+
4a4d8108
AM
14680+static inline void au_set_ivdir(struct inode *inode, struct au_vdir *vdir)
14681+{
14682+ IiMustWriteLock(inode);
14683+ au_ii(inode)->ii_vdir = vdir;
14684+}
1facf9fc 14685+
4a4d8108 14686+static inline struct au_hinode *au_hi(struct inode *inode, aufs_bindex_t bindex)
1308ab2a 14687+{
4a4d8108
AM
14688+ IiMustAnyLock(inode);
14689+ return au_ii(inode)->ii_hinode + bindex;
14690+}
dece6358 14691+
4a4d8108 14692+/* ---------------------------------------------------------------------- */
1facf9fc 14693+
4a4d8108
AM
14694+static inline struct dentry *au_pinned_parent(struct au_pin *pin)
14695+{
14696+ if (pin)
14697+ return pin->parent;
14698+ return NULL;
1facf9fc 14699+}
14700+
4a4d8108 14701+static inline struct inode *au_pinned_h_dir(struct au_pin *pin)
1facf9fc 14702+{
4a4d8108
AM
14703+ if (pin && pin->hdir)
14704+ return pin->hdir->hi_inode;
14705+ return NULL;
1308ab2a 14706+}
1facf9fc 14707+
4a4d8108
AM
14708+static inline struct au_hinode *au_pinned_hdir(struct au_pin *pin)
14709+{
14710+ if (pin)
14711+ return pin->hdir;
14712+ return NULL;
14713+}
1facf9fc 14714+
4a4d8108 14715+static inline void au_pin_set_dentry(struct au_pin *pin, struct dentry *dentry)
1308ab2a 14716+{
4a4d8108
AM
14717+ if (pin)
14718+ pin->dentry = dentry;
14719+}
1308ab2a 14720+
4a4d8108
AM
14721+static inline void au_pin_set_parent_lflag(struct au_pin *pin,
14722+ unsigned char lflag)
14723+{
14724+ if (pin) {
7f207e10 14725+ if (lflag)
4a4d8108 14726+ au_fset_pin(pin->flags, DI_LOCKED);
7f207e10 14727+ else
4a4d8108 14728+ au_fclr_pin(pin->flags, DI_LOCKED);
1308ab2a 14729+ }
4a4d8108
AM
14730+}
14731+
14732+static inline void au_pin_set_parent(struct au_pin *pin, struct dentry *parent)
14733+{
14734+ if (pin) {
14735+ dput(pin->parent);
14736+ pin->parent = dget(parent);
1facf9fc 14737+ }
4a4d8108 14738+}
1facf9fc 14739+
4a4d8108
AM
14740+/* ---------------------------------------------------------------------- */
14741+
027c5e7a 14742+struct au_branch;
4a4d8108
AM
14743+#ifdef CONFIG_AUFS_HNOTIFY
14744+struct au_hnotify_op {
14745+ void (*ctl)(struct au_hinode *hinode, int do_set);
027c5e7a 14746+ int (*alloc)(struct au_hinode *hinode);
7eafdf33
AM
14747+
14748+ /*
14749+ * if it returns true, the the caller should free hinode->hi_notify,
14750+ * otherwise ->free() frees it.
14751+ */
14752+ int (*free)(struct au_hinode *hinode,
14753+ struct au_hnotify *hn) __must_check;
4a4d8108
AM
14754+
14755+ void (*fin)(void);
14756+ int (*init)(void);
027c5e7a
AM
14757+
14758+ int (*reset_br)(unsigned int udba, struct au_branch *br, int perm);
14759+ void (*fin_br)(struct au_branch *br);
14760+ int (*init_br)(struct au_branch *br, int perm);
4a4d8108
AM
14761+};
14762+
14763+/* hnotify.c */
027c5e7a 14764+int au_hn_alloc(struct au_hinode *hinode, struct inode *inode);
4a4d8108
AM
14765+void au_hn_free(struct au_hinode *hinode);
14766+void au_hn_ctl(struct au_hinode *hinode, int do_set);
14767+void au_hn_reset(struct inode *inode, unsigned int flags);
14768+int au_hnotify(struct inode *h_dir, struct au_hnotify *hnotify, u32 mask,
14769+ struct qstr *h_child_qstr, struct inode *h_child_inode);
027c5e7a
AM
14770+int au_hnotify_reset_br(unsigned int udba, struct au_branch *br, int perm);
14771+int au_hnotify_init_br(struct au_branch *br, int perm);
14772+void au_hnotify_fin_br(struct au_branch *br);
4a4d8108
AM
14773+int __init au_hnotify_init(void);
14774+void au_hnotify_fin(void);
14775+
7f207e10 14776+/* hfsnotify.c */
4a4d8108
AM
14777+extern const struct au_hnotify_op au_hnotify_op;
14778+
14779+static inline
14780+void au_hn_init(struct au_hinode *hinode)
14781+{
14782+ hinode->hi_notify = NULL;
1308ab2a 14783+}
14784+
53392da6
AM
14785+static inline struct au_hnotify *au_hn(struct au_hinode *hinode)
14786+{
14787+ return hinode->hi_notify;
14788+}
14789+
4a4d8108
AM
14790+#else
14791+static inline
14792+int au_hn_alloc(struct au_hinode *hinode __maybe_unused,
027c5e7a 14793+ struct inode *inode __maybe_unused)
1308ab2a 14794+{
4a4d8108
AM
14795+ return -EOPNOTSUPP;
14796+}
1308ab2a 14797+
53392da6
AM
14798+static inline struct au_hnotify *au_hn(struct au_hinode *hinode)
14799+{
14800+ return NULL;
14801+}
14802+
4a4d8108
AM
14803+AuStubVoid(au_hn_free, struct au_hinode *hinode __maybe_unused)
14804+AuStubVoid(au_hn_ctl, struct au_hinode *hinode __maybe_unused,
14805+ int do_set __maybe_unused)
14806+AuStubVoid(au_hn_reset, struct inode *inode __maybe_unused,
14807+ unsigned int flags __maybe_unused)
027c5e7a
AM
14808+AuStubInt0(au_hnotify_reset_br, unsigned int udba __maybe_unused,
14809+ struct au_branch *br __maybe_unused,
14810+ int perm __maybe_unused)
14811+AuStubInt0(au_hnotify_init_br, struct au_branch *br __maybe_unused,
14812+ int perm __maybe_unused)
14813+AuStubVoid(au_hnotify_fin_br, struct au_branch *br __maybe_unused)
4a4d8108
AM
14814+AuStubInt0(__init au_hnotify_init, void)
14815+AuStubVoid(au_hnotify_fin, void)
14816+AuStubVoid(au_hn_init, struct au_hinode *hinode __maybe_unused)
14817+#endif /* CONFIG_AUFS_HNOTIFY */
14818+
14819+static inline void au_hn_suspend(struct au_hinode *hdir)
14820+{
14821+ au_hn_ctl(hdir, /*do_set*/0);
1308ab2a 14822+}
14823+
4a4d8108 14824+static inline void au_hn_resume(struct au_hinode *hdir)
1308ab2a 14825+{
4a4d8108
AM
14826+ au_hn_ctl(hdir, /*do_set*/1);
14827+}
1308ab2a 14828+
4a4d8108
AM
14829+static inline void au_hn_imtx_lock(struct au_hinode *hdir)
14830+{
14831+ mutex_lock(&hdir->hi_inode->i_mutex);
14832+ au_hn_suspend(hdir);
14833+}
dece6358 14834+
4a4d8108
AM
14835+static inline void au_hn_imtx_lock_nested(struct au_hinode *hdir,
14836+ unsigned int sc __maybe_unused)
14837+{
14838+ mutex_lock_nested(&hdir->hi_inode->i_mutex, sc);
14839+ au_hn_suspend(hdir);
1facf9fc 14840+}
1facf9fc 14841+
4a4d8108
AM
14842+static inline void au_hn_imtx_unlock(struct au_hinode *hdir)
14843+{
14844+ au_hn_resume(hdir);
14845+ mutex_unlock(&hdir->hi_inode->i_mutex);
14846+}
14847+
14848+#endif /* __KERNEL__ */
14849+#endif /* __AUFS_INODE_H__ */
7f207e10
AM
14850diff -urN /usr/share/empty/fs/aufs/ioctl.c linux/fs/aufs/ioctl.c
14851--- /usr/share/empty/fs/aufs/ioctl.c 1970-01-01 01:00:00.000000000 +0100
2dfbb274 14852+++ linux/fs/aufs/ioctl.c 2012-08-26 08:39:00.760508065 +0200
f6c5ef8b 14853@@ -0,0 +1,196 @@
4a4d8108 14854+/*
f6c5ef8b 14855+ * Copyright (C) 2005-2012 Junjiro R. Okajima
4a4d8108
AM
14856+ *
14857+ * This program, aufs is free software; you can redistribute it and/or modify
14858+ * it under the terms of the GNU General Public License as published by
14859+ * the Free Software Foundation; either version 2 of the License, or
14860+ * (at your option) any later version.
14861+ *
14862+ * This program is distributed in the hope that it will be useful,
14863+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
14864+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14865+ * GNU General Public License for more details.
14866+ *
14867+ * You should have received a copy of the GNU General Public License
14868+ * along with this program; if not, write to the Free Software
14869+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
14870+ */
14871+
14872+/*
14873+ * ioctl
14874+ * plink-management and readdir in userspace.
14875+ * assist the pathconf(3) wrapper library.
14876+ */
14877+
4a4d8108
AM
14878+#include "aufs.h"
14879+
1e00d052 14880+static int au_wbr_fd(struct path *path, struct aufs_wbr_fd __user *arg)
4a4d8108
AM
14881+{
14882+ int err, fd;
14883+ aufs_bindex_t wbi, bindex, bend;
14884+ struct file *h_file;
14885+ struct super_block *sb;
14886+ struct dentry *root;
1e00d052
AM
14887+ struct au_branch *br;
14888+ struct aufs_wbr_fd wbrfd = {
14889+ .oflags = au_dir_roflags,
14890+ .brid = -1
14891+ };
14892+ const int valid = O_RDONLY | O_NONBLOCK | O_LARGEFILE | O_DIRECTORY
14893+ | O_NOATIME | O_CLOEXEC;
4a4d8108 14894+
1e00d052
AM
14895+ AuDebugOn(wbrfd.oflags & ~valid);
14896+
14897+ if (arg) {
14898+ err = copy_from_user(&wbrfd, arg, sizeof(wbrfd));
14899+ if (unlikely(err)) {
14900+ err = -EFAULT;
14901+ goto out;
14902+ }
14903+
14904+ err = -EINVAL;
14905+ AuDbg("wbrfd{0%o, %d}\n", wbrfd.oflags, wbrfd.brid);
14906+ wbrfd.oflags |= au_dir_roflags;
14907+ AuDbg("0%o\n", wbrfd.oflags);
14908+ if (unlikely(wbrfd.oflags & ~valid))
14909+ goto out;
14910+ }
14911+
14912+ fd = get_unused_fd();
14913+ err = fd;
14914+ if (unlikely(fd < 0))
4a4d8108 14915+ goto out;
4a4d8108 14916+
1e00d052 14917+ h_file = ERR_PTR(-EINVAL);
4a4d8108 14918+ wbi = 0;
1e00d052 14919+ br = NULL;
4a4d8108
AM
14920+ sb = path->dentry->d_sb;
14921+ root = sb->s_root;
14922+ aufs_read_lock(root, AuLock_IR);
1e00d052
AM
14923+ bend = au_sbend(sb);
14924+ if (wbrfd.brid >= 0) {
14925+ wbi = au_br_index(sb, wbrfd.brid);
14926+ if (unlikely(wbi < 0 || wbi > bend))
14927+ goto out_unlock;
14928+ }
14929+
14930+ h_file = ERR_PTR(-ENOENT);
14931+ br = au_sbr(sb, wbi);
14932+ if (!au_br_writable(br->br_perm)) {
14933+ if (arg)
14934+ goto out_unlock;
14935+
14936+ bindex = wbi + 1;
14937+ wbi = -1;
14938+ for (; bindex <= bend; bindex++) {
14939+ br = au_sbr(sb, bindex);
14940+ if (au_br_writable(br->br_perm)) {
4a4d8108 14941+ wbi = bindex;
1e00d052 14942+ br = au_sbr(sb, wbi);
4a4d8108
AM
14943+ break;
14944+ }
14945+ }
4a4d8108
AM
14946+ }
14947+ AuDbg("wbi %d\n", wbi);
1e00d052
AM
14948+ if (wbi >= 0)
14949+ h_file = au_h_open(root, wbi, wbrfd.oflags, NULL);
14950+
14951+out_unlock:
4a4d8108
AM
14952+ aufs_read_unlock(root, AuLock_IR);
14953+ err = PTR_ERR(h_file);
14954+ if (IS_ERR(h_file))
14955+ goto out_fd;
14956+
1e00d052 14957+ atomic_dec(&br->br_count); /* cf. au_h_open() */
4a4d8108
AM
14958+ fd_install(fd, h_file);
14959+ err = fd;
14960+ goto out; /* success */
14961+
4f0767ce 14962+out_fd:
4a4d8108 14963+ put_unused_fd(fd);
4f0767ce 14964+out:
1e00d052 14965+ AuTraceErr(err);
4a4d8108
AM
14966+ return err;
14967+}
14968+
14969+/* ---------------------------------------------------------------------- */
14970+
14971+long aufs_ioctl_dir(struct file *file, unsigned int cmd, unsigned long arg)
14972+{
14973+ long err;
14974+
14975+ switch (cmd) {
4a4d8108
AM
14976+ case AUFS_CTL_RDU:
14977+ case AUFS_CTL_RDU_INO:
14978+ err = au_rdu_ioctl(file, cmd, arg);
14979+ break;
14980+
14981+ case AUFS_CTL_WBR_FD:
1e00d052 14982+ err = au_wbr_fd(&file->f_path, (void __user *)arg);
4a4d8108
AM
14983+ break;
14984+
027c5e7a
AM
14985+ case AUFS_CTL_IBUSY:
14986+ err = au_ibusy_ioctl(file, arg);
14987+ break;
14988+
4a4d8108
AM
14989+ default:
14990+ /* do not call the lower */
14991+ AuDbg("0x%x\n", cmd);
14992+ err = -ENOTTY;
14993+ }
14994+
14995+ AuTraceErr(err);
14996+ return err;
14997+}
14998+
14999+long aufs_ioctl_nondir(struct file *file, unsigned int cmd, unsigned long arg)
15000+{
15001+ long err;
15002+
15003+ switch (cmd) {
15004+ case AUFS_CTL_WBR_FD:
1e00d052 15005+ err = au_wbr_fd(&file->f_path, (void __user *)arg);
4a4d8108
AM
15006+ break;
15007+
15008+ default:
15009+ /* do not call the lower */
15010+ AuDbg("0x%x\n", cmd);
15011+ err = -ENOTTY;
15012+ }
15013+
15014+ AuTraceErr(err);
15015+ return err;
15016+}
b752ccd1
AM
15017+
15018+#ifdef CONFIG_COMPAT
15019+long aufs_compat_ioctl_dir(struct file *file, unsigned int cmd,
15020+ unsigned long arg)
15021+{
15022+ long err;
15023+
15024+ switch (cmd) {
15025+ case AUFS_CTL_RDU:
15026+ case AUFS_CTL_RDU_INO:
15027+ err = au_rdu_compat_ioctl(file, cmd, arg);
15028+ break;
15029+
027c5e7a
AM
15030+ case AUFS_CTL_IBUSY:
15031+ err = au_ibusy_compat_ioctl(file, arg);
15032+ break;
15033+
b752ccd1
AM
15034+ default:
15035+ err = aufs_ioctl_dir(file, cmd, arg);
15036+ }
15037+
15038+ AuTraceErr(err);
15039+ return err;
15040+}
15041+
15042+#if 0 /* unused yet */
15043+long aufs_compat_ioctl_nondir(struct file *file, unsigned int cmd,
15044+ unsigned long arg)
15045+{
15046+ return aufs_ioctl_nondir(file, cmd, (unsigned long)compat_ptr(arg));
15047+}
15048+#endif
15049+#endif
7f207e10
AM
15050diff -urN /usr/share/empty/fs/aufs/i_op_add.c linux/fs/aufs/i_op_add.c
15051--- /usr/share/empty/fs/aufs/i_op_add.c 1970-01-01 01:00:00.000000000 +0100
b4510431 15052+++ linux/fs/aufs/i_op_add.c 2012-10-17 10:31:01.772481151 +0200
7eafdf33 15053@@ -0,0 +1,712 @@
4a4d8108 15054+/*
f6c5ef8b 15055+ * Copyright (C) 2005-2012 Junjiro R. Okajima
4a4d8108
AM
15056+ *
15057+ * This program, aufs is free software; you can redistribute it and/or modify
15058+ * it under the terms of the GNU General Public License as published by
15059+ * the Free Software Foundation; either version 2 of the License, or
15060+ * (at your option) any later version.
15061+ *
15062+ * This program is distributed in the hope that it will be useful,
15063+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
15064+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15065+ * GNU General Public License for more details.
15066+ *
15067+ * You should have received a copy of the GNU General Public License
15068+ * along with this program; if not, write to the Free Software
15069+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
15070+ */
15071+
15072+/*
15073+ * inode operations (add entry)
15074+ */
15075+
15076+#include "aufs.h"
15077+
15078+/*
15079+ * final procedure of adding a new entry, except link(2).
15080+ * remove whiteout, instantiate, copyup the parent dir's times and size
15081+ * and update version.
15082+ * if it failed, re-create the removed whiteout.
15083+ */
15084+static int epilog(struct inode *dir, aufs_bindex_t bindex,
15085+ struct dentry *wh_dentry, struct dentry *dentry)
15086+{
15087+ int err, rerr;
15088+ aufs_bindex_t bwh;
15089+ struct path h_path;
15090+ struct inode *inode, *h_dir;
15091+ struct dentry *wh;
15092+
15093+ bwh = -1;
15094+ if (wh_dentry) {
15095+ h_dir = wh_dentry->d_parent->d_inode; /* dir inode is locked */
15096+ IMustLock(h_dir);
15097+ AuDebugOn(au_h_iptr(dir, bindex) != h_dir);
15098+ bwh = au_dbwh(dentry);
15099+ h_path.dentry = wh_dentry;
15100+ h_path.mnt = au_sbr_mnt(dir->i_sb, bindex);
15101+ err = au_wh_unlink_dentry(au_h_iptr(dir, bindex), &h_path,
15102+ dentry);
15103+ if (unlikely(err))
15104+ goto out;
15105+ }
15106+
15107+ inode = au_new_inode(dentry, /*must_new*/1);
15108+ if (!IS_ERR(inode)) {
15109+ d_instantiate(dentry, inode);
15110+ dir = dentry->d_parent->d_inode; /* dir inode is locked */
15111+ IMustLock(dir);
15112+ if (au_ibstart(dir) == au_dbstart(dentry))
15113+ au_cpup_attr_timesizes(dir);
15114+ dir->i_version++;
15115+ return 0; /* success */
15116+ }
15117+
15118+ err = PTR_ERR(inode);
15119+ if (!wh_dentry)
15120+ goto out;
15121+
15122+ /* revert */
15123+ /* dir inode is locked */
15124+ wh = au_wh_create(dentry, bwh, wh_dentry->d_parent);
15125+ rerr = PTR_ERR(wh);
15126+ if (IS_ERR(wh)) {
15127+ AuIOErr("%.*s reverting whiteout failed(%d, %d)\n",
15128+ AuDLNPair(dentry), err, rerr);
15129+ err = -EIO;
15130+ } else
15131+ dput(wh);
15132+
4f0767ce 15133+out:
4a4d8108
AM
15134+ return err;
15135+}
15136+
027c5e7a
AM
15137+static int au_d_may_add(struct dentry *dentry)
15138+{
15139+ int err;
15140+
15141+ err = 0;
15142+ if (unlikely(d_unhashed(dentry)))
15143+ err = -ENOENT;
15144+ if (unlikely(dentry->d_inode))
15145+ err = -EEXIST;
15146+ return err;
15147+}
15148+
4a4d8108
AM
15149+/*
15150+ * simple tests for the adding inode operations.
15151+ * following the checks in vfs, plus the parent-child relationship.
15152+ */
15153+int au_may_add(struct dentry *dentry, aufs_bindex_t bindex,
15154+ struct dentry *h_parent, int isdir)
15155+{
15156+ int err;
15157+ umode_t h_mode;
15158+ struct dentry *h_dentry;
15159+ struct inode *h_inode;
15160+
15161+ err = -ENAMETOOLONG;
15162+ if (unlikely(dentry->d_name.len > AUFS_MAX_NAMELEN))
15163+ goto out;
15164+
15165+ h_dentry = au_h_dptr(dentry, bindex);
15166+ h_inode = h_dentry->d_inode;
15167+ if (!dentry->d_inode) {
15168+ err = -EEXIST;
15169+ if (unlikely(h_inode))
15170+ goto out;
15171+ } else {
15172+ /* rename(2) case */
15173+ err = -EIO;
15174+ if (unlikely(!h_inode || !h_inode->i_nlink))
15175+ goto out;
15176+
15177+ h_mode = h_inode->i_mode;
15178+ if (!isdir) {
15179+ err = -EISDIR;
15180+ if (unlikely(S_ISDIR(h_mode)))
15181+ goto out;
15182+ } else if (unlikely(!S_ISDIR(h_mode))) {
15183+ err = -ENOTDIR;
15184+ goto out;
15185+ }
15186+ }
15187+
15188+ err = 0;
15189+ /* expected parent dir is locked */
15190+ if (unlikely(h_parent != h_dentry->d_parent))
15191+ err = -EIO;
15192+
4f0767ce 15193+out:
4a4d8108
AM
15194+ AuTraceErr(err);
15195+ return err;
15196+}
15197+
15198+/*
15199+ * initial procedure of adding a new entry.
15200+ * prepare writable branch and the parent dir, lock it,
15201+ * and lookup whiteout for the new entry.
15202+ */
15203+static struct dentry*
15204+lock_hdir_lkup_wh(struct dentry *dentry, struct au_dtime *dt,
15205+ struct dentry *src_dentry, struct au_pin *pin,
15206+ struct au_wr_dir_args *wr_dir_args)
15207+{
15208+ struct dentry *wh_dentry, *h_parent;
15209+ struct super_block *sb;
15210+ struct au_branch *br;
15211+ int err;
15212+ unsigned int udba;
15213+ aufs_bindex_t bcpup;
15214+
15215+ AuDbg("%.*s\n", AuDLNPair(dentry));
15216+
15217+ err = au_wr_dir(dentry, src_dentry, wr_dir_args);
15218+ bcpup = err;
15219+ wh_dentry = ERR_PTR(err);
15220+ if (unlikely(err < 0))
15221+ goto out;
15222+
15223+ sb = dentry->d_sb;
15224+ udba = au_opt_udba(sb);
15225+ err = au_pin(pin, dentry, bcpup, udba,
15226+ AuPin_DI_LOCKED | AuPin_MNT_WRITE);
15227+ wh_dentry = ERR_PTR(err);
15228+ if (unlikely(err))
15229+ goto out;
15230+
15231+ h_parent = au_pinned_h_parent(pin);
15232+ if (udba != AuOpt_UDBA_NONE
15233+ && au_dbstart(dentry) == bcpup)
15234+ err = au_may_add(dentry, bcpup, h_parent,
15235+ au_ftest_wrdir(wr_dir_args->flags, ISDIR));
15236+ else if (unlikely(dentry->d_name.len > AUFS_MAX_NAMELEN))
15237+ err = -ENAMETOOLONG;
15238+ wh_dentry = ERR_PTR(err);
15239+ if (unlikely(err))
15240+ goto out_unpin;
15241+
15242+ br = au_sbr(sb, bcpup);
15243+ if (dt) {
15244+ struct path tmp = {
15245+ .dentry = h_parent,
15246+ .mnt = br->br_mnt
15247+ };
15248+ au_dtime_store(dt, au_pinned_parent(pin), &tmp);
15249+ }
15250+
15251+ wh_dentry = NULL;
15252+ if (bcpup != au_dbwh(dentry))
15253+ goto out; /* success */
15254+
15255+ wh_dentry = au_wh_lkup(h_parent, &dentry->d_name, br);
15256+
4f0767ce 15257+out_unpin:
4a4d8108
AM
15258+ if (IS_ERR(wh_dentry))
15259+ au_unpin(pin);
4f0767ce 15260+out:
4a4d8108
AM
15261+ return wh_dentry;
15262+}
15263+
15264+/* ---------------------------------------------------------------------- */
15265+
15266+enum { Mknod, Symlink, Creat };
15267+struct simple_arg {
15268+ int type;
15269+ union {
15270+ struct {
7eafdf33 15271+ umode_t mode;
b4510431 15272+ bool want_excl;
4a4d8108
AM
15273+ } c;
15274+ struct {
15275+ const char *symname;
15276+ } s;
15277+ struct {
7eafdf33 15278+ umode_t mode;
4a4d8108
AM
15279+ dev_t dev;
15280+ } m;
15281+ } u;
15282+};
15283+
15284+static int add_simple(struct inode *dir, struct dentry *dentry,
15285+ struct simple_arg *arg)
15286+{
15287+ int err;
15288+ aufs_bindex_t bstart;
15289+ unsigned char created;
15290+ struct au_dtime dt;
15291+ struct au_pin pin;
15292+ struct path h_path;
15293+ struct dentry *wh_dentry, *parent;
15294+ struct inode *h_dir;
15295+ struct au_wr_dir_args wr_dir_args = {
15296+ .force_btgt = -1,
15297+ .flags = AuWrDir_ADD_ENTRY
15298+ };
15299+
15300+ AuDbg("%.*s\n", AuDLNPair(dentry));
15301+ IMustLock(dir);
15302+
15303+ parent = dentry->d_parent; /* dir inode is locked */
027c5e7a
AM
15304+ err = aufs_read_lock(dentry, AuLock_DW | AuLock_GEN);
15305+ if (unlikely(err))
15306+ goto out;
15307+ err = au_d_may_add(dentry);
15308+ if (unlikely(err))
15309+ goto out_unlock;
4a4d8108
AM
15310+ di_write_lock_parent(parent);
15311+ wh_dentry = lock_hdir_lkup_wh(dentry, &dt, /*src_dentry*/NULL, &pin,
15312+ &wr_dir_args);
15313+ err = PTR_ERR(wh_dentry);
15314+ if (IS_ERR(wh_dentry))
027c5e7a 15315+ goto out_parent;
4a4d8108
AM
15316+
15317+ bstart = au_dbstart(dentry);
15318+ h_path.dentry = au_h_dptr(dentry, bstart);
15319+ h_path.mnt = au_sbr_mnt(dentry->d_sb, bstart);
15320+ h_dir = au_pinned_h_dir(&pin);
15321+ switch (arg->type) {
15322+ case Creat:
b4510431 15323+ err = vfsub_create(h_dir, &h_path, arg->u.c.mode, arg->u.c.want_excl);
4a4d8108
AM
15324+ break;
15325+ case Symlink:
15326+ err = vfsub_symlink(h_dir, &h_path, arg->u.s.symname);
15327+ break;
15328+ case Mknod:
15329+ err = vfsub_mknod(h_dir, &h_path, arg->u.m.mode, arg->u.m.dev);
15330+ break;
15331+ default:
15332+ BUG();
15333+ }
15334+ created = !err;
15335+ if (!err)
15336+ err = epilog(dir, bstart, wh_dentry, dentry);
15337+
15338+ /* revert */
15339+ if (unlikely(created && err && h_path.dentry->d_inode)) {
15340+ int rerr;
15341+ rerr = vfsub_unlink(h_dir, &h_path, /*force*/0);
15342+ if (rerr) {
15343+ AuIOErr("%.*s revert failure(%d, %d)\n",
15344+ AuDLNPair(dentry), err, rerr);
15345+ err = -EIO;
15346+ }
15347+ au_dtime_revert(&dt);
4a4d8108
AM
15348+ }
15349+
15350+ au_unpin(&pin);
15351+ dput(wh_dentry);
15352+
027c5e7a
AM
15353+out_parent:
15354+ di_write_unlock(parent);
15355+out_unlock:
4a4d8108
AM
15356+ if (unlikely(err)) {
15357+ au_update_dbstart(dentry);
15358+ d_drop(dentry);
15359+ }
4a4d8108 15360+ aufs_read_unlock(dentry, AuLock_DW);
027c5e7a 15361+out:
4a4d8108
AM
15362+ return err;
15363+}
15364+
7eafdf33
AM
15365+int aufs_mknod(struct inode *dir, struct dentry *dentry, umode_t mode,
15366+ dev_t dev)
4a4d8108
AM
15367+{
15368+ struct simple_arg arg = {
15369+ .type = Mknod,
15370+ .u.m = {
15371+ .mode = mode,
15372+ .dev = dev
15373+ }
15374+ };
15375+ return add_simple(dir, dentry, &arg);
15376+}
15377+
15378+int aufs_symlink(struct inode *dir, struct dentry *dentry, const char *symname)
15379+{
15380+ struct simple_arg arg = {
15381+ .type = Symlink,
15382+ .u.s.symname = symname
15383+ };
15384+ return add_simple(dir, dentry, &arg);
15385+}
15386+
7eafdf33 15387+int aufs_create(struct inode *dir, struct dentry *dentry, umode_t mode,
b4510431 15388+ bool want_excl)
4a4d8108
AM
15389+{
15390+ struct simple_arg arg = {
15391+ .type = Creat,
15392+ .u.c = {
b4510431
AM
15393+ .mode = mode,
15394+ .want_excl = want_excl
4a4d8108
AM
15395+ }
15396+ };
15397+ return add_simple(dir, dentry, &arg);
15398+}
15399+
15400+/* ---------------------------------------------------------------------- */
15401+
15402+struct au_link_args {
15403+ aufs_bindex_t bdst, bsrc;
15404+ struct au_pin pin;
15405+ struct path h_path;
15406+ struct dentry *src_parent, *parent;
15407+};
15408+
15409+static int au_cpup_before_link(struct dentry *src_dentry,
15410+ struct au_link_args *a)
15411+{
15412+ int err;
15413+ struct dentry *h_src_dentry;
15414+ struct mutex *h_mtx;
15415+ struct file *h_file;
15416+
15417+ di_read_lock_parent(a->src_parent, AuLock_IR);
15418+ err = au_test_and_cpup_dirs(src_dentry, a->bdst);
15419+ if (unlikely(err))
15420+ goto out;
15421+
15422+ h_src_dentry = au_h_dptr(src_dentry, a->bsrc);
15423+ h_mtx = &h_src_dentry->d_inode->i_mutex;
15424+ err = au_pin(&a->pin, src_dentry, a->bdst,
15425+ au_opt_udba(src_dentry->d_sb),
15426+ AuPin_DI_LOCKED | AuPin_MNT_WRITE);
15427+ if (unlikely(err))
15428+ goto out;
15429+ mutex_lock_nested(h_mtx, AuLsc_I_CHILD);
15430+ h_file = au_h_open_pre(src_dentry, a->bsrc);
15431+ if (IS_ERR(h_file)) {
15432+ err = PTR_ERR(h_file);
15433+ h_file = NULL;
15434+ } else
1e00d052 15435+ err = au_sio_cpup_simple(src_dentry, a->bdst, -1,
4a4d8108
AM
15436+ AuCpup_DTIME /* | AuCpup_KEEPLINO */);
15437+ mutex_unlock(h_mtx);
15438+ au_h_open_post(src_dentry, a->bsrc, h_file);
15439+ au_unpin(&a->pin);
15440+
4f0767ce 15441+out:
4a4d8108
AM
15442+ di_read_unlock(a->src_parent, AuLock_IR);
15443+ return err;
15444+}
15445+
15446+static int au_cpup_or_link(struct dentry *src_dentry, struct au_link_args *a)
15447+{
15448+ int err;
15449+ unsigned char plink;
15450+ struct inode *h_inode, *inode;
15451+ struct dentry *h_src_dentry;
15452+ struct super_block *sb;
15453+ struct file *h_file;
15454+
15455+ plink = 0;
15456+ h_inode = NULL;
15457+ sb = src_dentry->d_sb;
15458+ inode = src_dentry->d_inode;
15459+ if (au_ibstart(inode) <= a->bdst)
15460+ h_inode = au_h_iptr(inode, a->bdst);
15461+ if (!h_inode || !h_inode->i_nlink) {
15462+ /* copyup src_dentry as the name of dentry. */
15463+ au_set_dbstart(src_dentry, a->bdst);
15464+ au_set_h_dptr(src_dentry, a->bdst, dget(a->h_path.dentry));
15465+ h_inode = au_h_dptr(src_dentry, a->bsrc)->d_inode;
15466+ mutex_lock_nested(&h_inode->i_mutex, AuLsc_I_CHILD);
15467+ h_file = au_h_open_pre(src_dentry, a->bsrc);
15468+ if (IS_ERR(h_file)) {
15469+ err = PTR_ERR(h_file);
15470+ h_file = NULL;
15471+ } else
15472+ err = au_sio_cpup_single(src_dentry, a->bdst, a->bsrc,
15473+ -1, AuCpup_KEEPLINO,
15474+ a->parent);
15475+ mutex_unlock(&h_inode->i_mutex);
15476+ au_h_open_post(src_dentry, a->bsrc, h_file);
15477+ au_set_h_dptr(src_dentry, a->bdst, NULL);
15478+ au_set_dbstart(src_dentry, a->bsrc);
15479+ } else {
15480+ /* the inode of src_dentry already exists on a.bdst branch */
15481+ h_src_dentry = d_find_alias(h_inode);
15482+ if (!h_src_dentry && au_plink_test(inode)) {
15483+ plink = 1;
15484+ h_src_dentry = au_plink_lkup(inode, a->bdst);
15485+ err = PTR_ERR(h_src_dentry);
15486+ if (IS_ERR(h_src_dentry))
15487+ goto out;
15488+
15489+ if (unlikely(!h_src_dentry->d_inode)) {
15490+ dput(h_src_dentry);
15491+ h_src_dentry = NULL;
15492+ }
15493+
15494+ }
15495+ if (h_src_dentry) {
15496+ err = vfsub_link(h_src_dentry, au_pinned_h_dir(&a->pin),
15497+ &a->h_path);
15498+ dput(h_src_dentry);
15499+ } else {
15500+ AuIOErr("no dentry found for hi%lu on b%d\n",
15501+ h_inode->i_ino, a->bdst);
15502+ err = -EIO;
15503+ }
15504+ }
15505+
15506+ if (!err && !plink)
15507+ au_plink_append(inode, a->bdst, a->h_path.dentry);
15508+
15509+out:
2cbb1c4b 15510+ AuTraceErr(err);
4a4d8108
AM
15511+ return err;
15512+}
15513+
15514+int aufs_link(struct dentry *src_dentry, struct inode *dir,
15515+ struct dentry *dentry)
15516+{
15517+ int err, rerr;
15518+ struct au_dtime dt;
15519+ struct au_link_args *a;
15520+ struct dentry *wh_dentry, *h_src_dentry;
15521+ struct inode *inode;
15522+ struct super_block *sb;
15523+ struct au_wr_dir_args wr_dir_args = {
15524+ /* .force_btgt = -1, */
15525+ .flags = AuWrDir_ADD_ENTRY
15526+ };
15527+
15528+ IMustLock(dir);
15529+ inode = src_dentry->d_inode;
15530+ IMustLock(inode);
15531+
4a4d8108
AM
15532+ err = -ENOMEM;
15533+ a = kzalloc(sizeof(*a), GFP_NOFS);
15534+ if (unlikely(!a))
15535+ goto out;
15536+
15537+ a->parent = dentry->d_parent; /* dir inode is locked */
027c5e7a
AM
15538+ err = aufs_read_and_write_lock2(dentry, src_dentry,
15539+ AuLock_NOPLM | AuLock_GEN);
e49829fe
JR
15540+ if (unlikely(err))
15541+ goto out_kfree;
027c5e7a
AM
15542+ err = au_d_hashed_positive(src_dentry);
15543+ if (unlikely(err))
15544+ goto out_unlock;
15545+ err = au_d_may_add(dentry);
15546+ if (unlikely(err))
15547+ goto out_unlock;
e49829fe 15548+
4a4d8108 15549+ a->src_parent = dget_parent(src_dentry);
2cbb1c4b 15550+ wr_dir_args.force_btgt = au_ibstart(inode);
4a4d8108
AM
15551+
15552+ di_write_lock_parent(a->parent);
15553+ wr_dir_args.force_btgt = au_wbr(dentry, wr_dir_args.force_btgt);
15554+ wh_dentry = lock_hdir_lkup_wh(dentry, &dt, src_dentry, &a->pin,
15555+ &wr_dir_args);
15556+ err = PTR_ERR(wh_dentry);
15557+ if (IS_ERR(wh_dentry))
027c5e7a 15558+ goto out_parent;
4a4d8108
AM
15559+
15560+ err = 0;
15561+ sb = dentry->d_sb;
15562+ a->bdst = au_dbstart(dentry);
15563+ a->h_path.dentry = au_h_dptr(dentry, a->bdst);
15564+ a->h_path.mnt = au_sbr_mnt(sb, a->bdst);
2cbb1c4b
JR
15565+ a->bsrc = au_ibstart(inode);
15566+ h_src_dentry = au_h_d_alias(src_dentry, a->bsrc);
15567+ if (!h_src_dentry) {
15568+ a->bsrc = au_dbstart(src_dentry);
15569+ h_src_dentry = au_h_d_alias(src_dentry, a->bsrc);
15570+ AuDebugOn(!h_src_dentry);
15571+ } else if (IS_ERR(h_src_dentry))
15572+ goto out_parent;
15573+
4a4d8108
AM
15574+ if (au_opt_test(au_mntflags(sb), PLINK)) {
15575+ if (a->bdst < a->bsrc
15576+ /* && h_src_dentry->d_sb != a->h_path.dentry->d_sb */)
15577+ err = au_cpup_or_link(src_dentry, a);
2cbb1c4b 15578+ else
4a4d8108
AM
15579+ err = vfsub_link(h_src_dentry, au_pinned_h_dir(&a->pin),
15580+ &a->h_path);
2cbb1c4b 15581+ dput(h_src_dentry);
4a4d8108
AM
15582+ } else {
15583+ /*
15584+ * copyup src_dentry to the branch we process,
15585+ * and then link(2) to it.
15586+ */
2cbb1c4b 15587+ dput(h_src_dentry);
4a4d8108
AM
15588+ if (a->bdst < a->bsrc
15589+ /* && h_src_dentry->d_sb != a->h_path.dentry->d_sb */) {
15590+ au_unpin(&a->pin);
15591+ di_write_unlock(a->parent);
15592+ err = au_cpup_before_link(src_dentry, a);
15593+ di_write_lock_parent(a->parent);
15594+ if (!err)
15595+ err = au_pin(&a->pin, dentry, a->bdst,
15596+ au_opt_udba(sb),
15597+ AuPin_DI_LOCKED | AuPin_MNT_WRITE);
15598+ if (unlikely(err))
15599+ goto out_wh;
15600+ }
15601+ if (!err) {
15602+ h_src_dentry = au_h_dptr(src_dentry, a->bdst);
15603+ err = -ENOENT;
15604+ if (h_src_dentry && h_src_dentry->d_inode)
15605+ err = vfsub_link(h_src_dentry,
15606+ au_pinned_h_dir(&a->pin),
15607+ &a->h_path);
15608+ }
15609+ }
15610+ if (unlikely(err))
15611+ goto out_unpin;
15612+
15613+ if (wh_dentry) {
15614+ a->h_path.dentry = wh_dentry;
15615+ err = au_wh_unlink_dentry(au_pinned_h_dir(&a->pin), &a->h_path,
15616+ dentry);
15617+ if (unlikely(err))
15618+ goto out_revert;
15619+ }
15620+
15621+ dir->i_version++;
15622+ if (au_ibstart(dir) == au_dbstart(dentry))
15623+ au_cpup_attr_timesizes(dir);
15624+ inc_nlink(inode);
15625+ inode->i_ctime = dir->i_ctime;
027c5e7a
AM
15626+ d_instantiate(dentry, au_igrab(inode));
15627+ if (d_unhashed(a->h_path.dentry))
4a4d8108
AM
15628+ /* some filesystem calls d_drop() */
15629+ d_drop(dentry);
15630+ goto out_unpin; /* success */
15631+
4f0767ce 15632+out_revert:
4a4d8108 15633+ rerr = vfsub_unlink(au_pinned_h_dir(&a->pin), &a->h_path, /*force*/0);
027c5e7a
AM
15634+ if (unlikely(rerr)) {
15635+ AuIOErr("%.*s reverting failed(%d, %d)\n",
15636+ AuDLNPair(dentry), err, rerr);
15637+ err = -EIO;
15638+ }
4a4d8108 15639+ au_dtime_revert(&dt);
4f0767ce 15640+out_unpin:
4a4d8108 15641+ au_unpin(&a->pin);
4f0767ce 15642+out_wh:
4a4d8108 15643+ dput(wh_dentry);
027c5e7a
AM
15644+out_parent:
15645+ di_write_unlock(a->parent);
15646+ dput(a->src_parent);
4f0767ce 15647+out_unlock:
4a4d8108
AM
15648+ if (unlikely(err)) {
15649+ au_update_dbstart(dentry);
15650+ d_drop(dentry);
15651+ }
4a4d8108 15652+ aufs_read_and_write_unlock2(dentry, src_dentry);
e49829fe 15653+out_kfree:
4a4d8108 15654+ kfree(a);
4f0767ce 15655+out:
4a4d8108
AM
15656+ return err;
15657+}
15658+
7eafdf33 15659+int aufs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
4a4d8108
AM
15660+{
15661+ int err, rerr;
15662+ aufs_bindex_t bindex;
15663+ unsigned char diropq;
15664+ struct path h_path;
15665+ struct dentry *wh_dentry, *parent, *opq_dentry;
15666+ struct mutex *h_mtx;
15667+ struct super_block *sb;
15668+ struct {
15669+ struct au_pin pin;
15670+ struct au_dtime dt;
15671+ } *a; /* reduce the stack usage */
15672+ struct au_wr_dir_args wr_dir_args = {
15673+ .force_btgt = -1,
15674+ .flags = AuWrDir_ADD_ENTRY | AuWrDir_ISDIR
15675+ };
15676+
15677+ IMustLock(dir);
15678+
15679+ err = -ENOMEM;
15680+ a = kmalloc(sizeof(*a), GFP_NOFS);
15681+ if (unlikely(!a))
15682+ goto out;
15683+
027c5e7a
AM
15684+ err = aufs_read_lock(dentry, AuLock_DW | AuLock_GEN);
15685+ if (unlikely(err))
15686+ goto out_free;
15687+ err = au_d_may_add(dentry);
15688+ if (unlikely(err))
15689+ goto out_unlock;
15690+
4a4d8108
AM
15691+ parent = dentry->d_parent; /* dir inode is locked */
15692+ di_write_lock_parent(parent);
15693+ wh_dentry = lock_hdir_lkup_wh(dentry, &a->dt, /*src_dentry*/NULL,
15694+ &a->pin, &wr_dir_args);
15695+ err = PTR_ERR(wh_dentry);
15696+ if (IS_ERR(wh_dentry))
027c5e7a 15697+ goto out_parent;
4a4d8108
AM
15698+
15699+ sb = dentry->d_sb;
15700+ bindex = au_dbstart(dentry);
15701+ h_path.dentry = au_h_dptr(dentry, bindex);
15702+ h_path.mnt = au_sbr_mnt(sb, bindex);
15703+ err = vfsub_mkdir(au_pinned_h_dir(&a->pin), &h_path, mode);
15704+ if (unlikely(err))
027c5e7a 15705+ goto out_unpin;
4a4d8108
AM
15706+
15707+ /* make the dir opaque */
15708+ diropq = 0;
15709+ h_mtx = &h_path.dentry->d_inode->i_mutex;
15710+ if (wh_dentry
15711+ || au_opt_test(au_mntflags(sb), ALWAYS_DIROPQ)) {
15712+ mutex_lock_nested(h_mtx, AuLsc_I_CHILD);
15713+ opq_dentry = au_diropq_create(dentry, bindex);
15714+ mutex_unlock(h_mtx);
15715+ err = PTR_ERR(opq_dentry);
15716+ if (IS_ERR(opq_dentry))
15717+ goto out_dir;
15718+ dput(opq_dentry);
15719+ diropq = 1;
15720+ }
15721+
15722+ err = epilog(dir, bindex, wh_dentry, dentry);
15723+ if (!err) {
15724+ inc_nlink(dir);
027c5e7a 15725+ goto out_unpin; /* success */
4a4d8108
AM
15726+ }
15727+
15728+ /* revert */
15729+ if (diropq) {
15730+ AuLabel(revert opq);
15731+ mutex_lock_nested(h_mtx, AuLsc_I_CHILD);
15732+ rerr = au_diropq_remove(dentry, bindex);
15733+ mutex_unlock(h_mtx);
15734+ if (rerr) {
15735+ AuIOErr("%.*s reverting diropq failed(%d, %d)\n",
15736+ AuDLNPair(dentry), err, rerr);
15737+ err = -EIO;
15738+ }
15739+ }
15740+
4f0767ce 15741+out_dir:
4a4d8108
AM
15742+ AuLabel(revert dir);
15743+ rerr = vfsub_rmdir(au_pinned_h_dir(&a->pin), &h_path);
15744+ if (rerr) {
15745+ AuIOErr("%.*s reverting dir failed(%d, %d)\n",
15746+ AuDLNPair(dentry), err, rerr);
15747+ err = -EIO;
15748+ }
4a4d8108 15749+ au_dtime_revert(&a->dt);
027c5e7a 15750+out_unpin:
4a4d8108
AM
15751+ au_unpin(&a->pin);
15752+ dput(wh_dentry);
027c5e7a
AM
15753+out_parent:
15754+ di_write_unlock(parent);
15755+out_unlock:
4a4d8108
AM
15756+ if (unlikely(err)) {
15757+ au_update_dbstart(dentry);
15758+ d_drop(dentry);
15759+ }
4a4d8108 15760+ aufs_read_unlock(dentry, AuLock_DW);
027c5e7a 15761+out_free:
4a4d8108 15762+ kfree(a);
4f0767ce 15763+out:
4a4d8108
AM
15764+ return err;
15765+}
7f207e10
AM
15766diff -urN /usr/share/empty/fs/aufs/i_op.c linux/fs/aufs/i_op.c
15767--- /usr/share/empty/fs/aufs/i_op.c 1970-01-01 01:00:00.000000000 +0100
b4510431 15768+++ linux/fs/aufs/i_op.c 2012-10-17 10:31:01.772481151 +0200
2dfbb274 15769@@ -0,0 +1,1009 @@
4a4d8108 15770+/*
f6c5ef8b 15771+ * Copyright (C) 2005-2012 Junjiro R. Okajima
4a4d8108
AM
15772+ *
15773+ * This program, aufs is free software; you can redistribute it and/or modify
15774+ * it under the terms of the GNU General Public License as published by
15775+ * the Free Software Foundation; either version 2 of the License, or
15776+ * (at your option) any later version.
15777+ *
15778+ * This program is distributed in the hope that it will be useful,
15779+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
15780+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15781+ * GNU General Public License for more details.
15782+ *
15783+ * You should have received a copy of the GNU General Public License
15784+ * along with this program; if not, write to the Free Software
15785+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
15786+ */
1facf9fc 15787+
1308ab2a 15788+/*
4a4d8108 15789+ * inode operations (except add/del/rename)
1308ab2a 15790+ */
4a4d8108
AM
15791+
15792+#include <linux/device_cgroup.h>
15793+#include <linux/fs_stack.h>
92d182d2 15794+#include <linux/mm.h>
4a4d8108
AM
15795+#include <linux/namei.h>
15796+#include <linux/security.h>
4a4d8108
AM
15797+#include "aufs.h"
15798+
1e00d052 15799+static int h_permission(struct inode *h_inode, int mask,
4a4d8108 15800+ struct vfsmount *h_mnt, int brperm)
1facf9fc 15801+{
1308ab2a 15802+ int err;
4a4d8108 15803+ const unsigned char write_mask = !!(mask & (MAY_WRITE | MAY_APPEND));
1facf9fc 15804+
4a4d8108
AM
15805+ err = -EACCES;
15806+ if ((write_mask && IS_IMMUTABLE(h_inode))
15807+ || ((mask & MAY_EXEC)
15808+ && S_ISREG(h_inode->i_mode)
15809+ && ((h_mnt->mnt_flags & MNT_NOEXEC)
15810+ || !(h_inode->i_mode & S_IXUGO))))
15811+ goto out;
15812+
15813+ /*
15814+ * - skip the lower fs test in the case of write to ro branch.
15815+ * - nfs dir permission write check is optimized, but a policy for
15816+ * link/rename requires a real check.
15817+ */
15818+ if ((write_mask && !au_br_writable(brperm))
15819+ || (au_test_nfs(h_inode->i_sb) && S_ISDIR(h_inode->i_mode)
15820+ && write_mask && !(mask & MAY_READ))
15821+ || !h_inode->i_op->permission) {
15822+ /* AuLabel(generic_permission); */
1e00d052 15823+ err = generic_permission(h_inode, mask);
1308ab2a 15824+ } else {
4a4d8108 15825+ /* AuLabel(h_inode->permission); */
1e00d052 15826+ err = h_inode->i_op->permission(h_inode, mask);
4a4d8108
AM
15827+ AuTraceErr(err);
15828+ }
1facf9fc 15829+
4a4d8108
AM
15830+ if (!err)
15831+ err = devcgroup_inode_permission(h_inode, mask);
7f207e10 15832+ if (!err)
4a4d8108 15833+ err = security_inode_permission(h_inode, mask);
4a4d8108
AM
15834+
15835+#if 0
15836+ if (!err) {
15837+ /* todo: do we need to call ima_path_check()? */
15838+ struct path h_path = {
15839+ .dentry =
15840+ .mnt = h_mnt
15841+ };
15842+ err = ima_path_check(&h_path,
15843+ mask & (MAY_READ | MAY_WRITE | MAY_EXEC),
15844+ IMA_COUNT_LEAVE);
1308ab2a 15845+ }
4a4d8108 15846+#endif
dece6358 15847+
4f0767ce 15848+out:
1308ab2a 15849+ return err;
15850+}
dece6358 15851+
1e00d052 15852+static int aufs_permission(struct inode *inode, int mask)
1308ab2a 15853+{
15854+ int err;
4a4d8108
AM
15855+ aufs_bindex_t bindex, bend;
15856+ const unsigned char isdir = !!S_ISDIR(inode->i_mode),
15857+ write_mask = !!(mask & (MAY_WRITE | MAY_APPEND));
15858+ struct inode *h_inode;
15859+ struct super_block *sb;
15860+ struct au_branch *br;
1facf9fc 15861+
027c5e7a 15862+ /* todo: support rcu-walk? */
1e00d052 15863+ if (mask & MAY_NOT_BLOCK)
027c5e7a
AM
15864+ return -ECHILD;
15865+
4a4d8108
AM
15866+ sb = inode->i_sb;
15867+ si_read_lock(sb, AuLock_FLUSH);
15868+ ii_read_lock_child(inode);
027c5e7a
AM
15869+#if 0
15870+ err = au_iigen_test(inode, au_sigen(sb));
15871+ if (unlikely(err))
15872+ goto out;
15873+#endif
dece6358 15874+
4a4d8108
AM
15875+ if (!isdir || write_mask) {
15876+ err = au_busy_or_stale();
15877+ h_inode = au_h_iptr(inode, au_ibstart(inode));
15878+ if (unlikely(!h_inode
15879+ || (h_inode->i_mode & S_IFMT)
15880+ != (inode->i_mode & S_IFMT)))
15881+ goto out;
1facf9fc 15882+
4a4d8108
AM
15883+ err = 0;
15884+ bindex = au_ibstart(inode);
15885+ br = au_sbr(sb, bindex);
1e00d052 15886+ err = h_permission(h_inode, mask, br->br_mnt, br->br_perm);
4a4d8108
AM
15887+ if (write_mask
15888+ && !err
15889+ && !special_file(h_inode->i_mode)) {
15890+ /* test whether the upper writable branch exists */
15891+ err = -EROFS;
15892+ for (; bindex >= 0; bindex--)
15893+ if (!au_br_rdonly(au_sbr(sb, bindex))) {
15894+ err = 0;
15895+ break;
15896+ }
15897+ }
15898+ goto out;
15899+ }
dece6358 15900+
4a4d8108 15901+ /* non-write to dir */
1308ab2a 15902+ err = 0;
4a4d8108
AM
15903+ bend = au_ibend(inode);
15904+ for (bindex = au_ibstart(inode); !err && bindex <= bend; bindex++) {
15905+ h_inode = au_h_iptr(inode, bindex);
15906+ if (h_inode) {
15907+ err = au_busy_or_stale();
15908+ if (unlikely(!S_ISDIR(h_inode->i_mode)))
15909+ break;
15910+
15911+ br = au_sbr(sb, bindex);
1e00d052 15912+ err = h_permission(h_inode, mask, br->br_mnt,
4a4d8108
AM
15913+ br->br_perm);
15914+ }
15915+ }
1308ab2a 15916+
4f0767ce 15917+out:
4a4d8108
AM
15918+ ii_read_unlock(inode);
15919+ si_read_unlock(sb);
1308ab2a 15920+ return err;
15921+}
15922+
4a4d8108 15923+/* ---------------------------------------------------------------------- */
1facf9fc 15924+
4a4d8108 15925+static struct dentry *aufs_lookup(struct inode *dir, struct dentry *dentry,
b4510431 15926+ unsigned int flags)
4a4d8108
AM
15927+{
15928+ struct dentry *ret, *parent;
b752ccd1 15929+ struct inode *inode;
4a4d8108 15930+ struct super_block *sb;
9dbd164d 15931+ int err, npositive, lc_idx;
dece6358 15932+
4a4d8108 15933+ IMustLock(dir);
1308ab2a 15934+
4a4d8108 15935+ sb = dir->i_sb;
7f207e10
AM
15936+ err = si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLM);
15937+ ret = ERR_PTR(err);
15938+ if (unlikely(err))
15939+ goto out;
15940+
4a4d8108
AM
15941+ ret = ERR_PTR(-ENAMETOOLONG);
15942+ if (unlikely(dentry->d_name.len > AUFS_MAX_NAMELEN))
7f207e10 15943+ goto out_si;
4a4d8108
AM
15944+ err = au_di_init(dentry);
15945+ ret = ERR_PTR(err);
15946+ if (unlikely(err))
7f207e10 15947+ goto out_si;
1308ab2a 15948+
9dbd164d 15949+ inode = NULL;
027c5e7a 15950+ npositive = 0; /* suppress a warning */
4a4d8108
AM
15951+ parent = dentry->d_parent; /* dir inode is locked */
15952+ di_read_lock_parent(parent, AuLock_IR);
027c5e7a
AM
15953+ err = au_alive_dir(parent);
15954+ if (!err)
15955+ err = au_digen_test(parent, au_sigen(sb));
15956+ if (!err) {
15957+ npositive = au_lkup_dentry(dentry, au_dbstart(parent),
b4510431 15958+ /*type*/0, flags);
027c5e7a
AM
15959+ err = npositive;
15960+ }
4a4d8108 15961+ di_read_unlock(parent, AuLock_IR);
4a4d8108
AM
15962+ ret = ERR_PTR(err);
15963+ if (unlikely(err < 0))
15964+ goto out_unlock;
1308ab2a 15965+
4a4d8108 15966+ if (npositive) {
b752ccd1 15967+ inode = au_new_inode(dentry, /*must_new*/0);
4a4d8108 15968+ ret = (void *)inode;
1facf9fc 15969+ }
9dbd164d
AM
15970+ if (IS_ERR(inode)) {
15971+ inode = NULL;
4a4d8108 15972+ goto out_unlock;
9dbd164d 15973+ }
4a4d8108
AM
15974+
15975+ ret = d_splice_alias(inode, dentry);
7f207e10 15976+ if (unlikely(IS_ERR(ret) && inode)) {
4a4d8108 15977+ ii_write_unlock(inode);
7f207e10 15978+ iput(inode);
2dfbb274 15979+ inode = NULL;
7f207e10 15980+ }
1facf9fc 15981+
4f0767ce 15982+out_unlock:
4a4d8108 15983+ di_write_unlock(dentry);
2dfbb274 15984+ if (inode) {
9dbd164d
AM
15985+ lc_idx = AuLcNonDir_DIINFO;
15986+ if (S_ISLNK(inode->i_mode))
15987+ lc_idx = AuLcSymlink_DIINFO;
15988+ else if (S_ISDIR(inode->i_mode))
15989+ lc_idx = AuLcDir_DIINFO;
15990+ au_rw_class(&au_di(dentry)->di_rwsem, au_lc_key + lc_idx);
15991+ }
7f207e10 15992+out_si:
4a4d8108 15993+ si_read_unlock(sb);
7f207e10 15994+out:
4a4d8108
AM
15995+ return ret;
15996+}
1facf9fc 15997+
4a4d8108 15998+/* ---------------------------------------------------------------------- */
1facf9fc 15999+
4a4d8108
AM
16000+static int au_wr_dir_cpup(struct dentry *dentry, struct dentry *parent,
16001+ const unsigned char add_entry, aufs_bindex_t bcpup,
16002+ aufs_bindex_t bstart)
16003+{
16004+ int err;
16005+ struct dentry *h_parent;
16006+ struct inode *h_dir;
1facf9fc 16007+
027c5e7a 16008+ if (add_entry)
4a4d8108 16009+ IMustLock(parent->d_inode);
027c5e7a 16010+ else
4a4d8108
AM
16011+ di_write_lock_parent(parent);
16012+
16013+ err = 0;
16014+ if (!au_h_dptr(parent, bcpup)) {
16015+ if (bstart < bcpup)
16016+ err = au_cpdown_dirs(dentry, bcpup);
16017+ else
16018+ err = au_cpup_dirs(dentry, bcpup);
16019+ }
16020+ if (!err && add_entry) {
16021+ h_parent = au_h_dptr(parent, bcpup);
16022+ h_dir = h_parent->d_inode;
16023+ mutex_lock_nested(&h_dir->i_mutex, AuLsc_I_PARENT);
16024+ err = au_lkup_neg(dentry, bcpup);
16025+ /* todo: no unlock here */
16026+ mutex_unlock(&h_dir->i_mutex);
027c5e7a
AM
16027+
16028+ AuDbg("bcpup %d\n", bcpup);
16029+ if (!err) {
16030+ if (!dentry->d_inode)
16031+ au_set_h_dptr(dentry, bstart, NULL);
4a4d8108
AM
16032+ au_update_dbrange(dentry, /*do_put_zero*/0);
16033+ }
1308ab2a 16034+ }
1facf9fc 16035+
4a4d8108
AM
16036+ if (!add_entry)
16037+ di_write_unlock(parent);
16038+ if (!err)
16039+ err = bcpup; /* success */
1308ab2a 16040+
027c5e7a 16041+ AuTraceErr(err);
4a4d8108
AM
16042+ return err;
16043+}
1facf9fc 16044+
4a4d8108
AM
16045+/*
16046+ * decide the branch and the parent dir where we will create a new entry.
16047+ * returns new bindex or an error.
16048+ * copyup the parent dir if needed.
16049+ */
16050+int au_wr_dir(struct dentry *dentry, struct dentry *src_dentry,
16051+ struct au_wr_dir_args *args)
16052+{
16053+ int err;
16054+ aufs_bindex_t bcpup, bstart, src_bstart;
16055+ const unsigned char add_entry = !!au_ftest_wrdir(args->flags,
16056+ ADD_ENTRY);
16057+ struct super_block *sb;
16058+ struct dentry *parent;
16059+ struct au_sbinfo *sbinfo;
1facf9fc 16060+
4a4d8108
AM
16061+ sb = dentry->d_sb;
16062+ sbinfo = au_sbi(sb);
16063+ parent = dget_parent(dentry);
16064+ bstart = au_dbstart(dentry);
16065+ bcpup = bstart;
16066+ if (args->force_btgt < 0) {
16067+ if (src_dentry) {
16068+ src_bstart = au_dbstart(src_dentry);
16069+ if (src_bstart < bstart)
16070+ bcpup = src_bstart;
16071+ } else if (add_entry) {
16072+ err = AuWbrCreate(sbinfo, dentry,
16073+ au_ftest_wrdir(args->flags, ISDIR));
16074+ bcpup = err;
16075+ }
1facf9fc 16076+
4a4d8108
AM
16077+ if (bcpup < 0 || au_test_ro(sb, bcpup, dentry->d_inode)) {
16078+ if (add_entry)
16079+ err = AuWbrCopyup(sbinfo, dentry);
16080+ else {
16081+ if (!IS_ROOT(dentry)) {
16082+ di_read_lock_parent(parent, !AuLock_IR);
16083+ err = AuWbrCopyup(sbinfo, dentry);
16084+ di_read_unlock(parent, !AuLock_IR);
16085+ } else
16086+ err = AuWbrCopyup(sbinfo, dentry);
16087+ }
16088+ bcpup = err;
16089+ if (unlikely(err < 0))
16090+ goto out;
16091+ }
16092+ } else {
16093+ bcpup = args->force_btgt;
16094+ AuDebugOn(au_test_ro(sb, bcpup, dentry->d_inode));
1308ab2a 16095+ }
027c5e7a 16096+
4a4d8108
AM
16097+ AuDbg("bstart %d, bcpup %d\n", bstart, bcpup);
16098+ err = bcpup;
16099+ if (bcpup == bstart)
16100+ goto out; /* success */
4a4d8108
AM
16101+
16102+ /* copyup the new parent into the branch we process */
16103+ err = au_wr_dir_cpup(dentry, parent, add_entry, bcpup, bstart);
027c5e7a
AM
16104+ if (err >= 0) {
16105+ if (!dentry->d_inode) {
16106+ au_set_h_dptr(dentry, bstart, NULL);
16107+ au_set_dbstart(dentry, bcpup);
16108+ au_set_dbend(dentry, bcpup);
16109+ }
16110+ AuDebugOn(add_entry && !au_h_dptr(dentry, bcpup));
16111+ }
4a4d8108 16112+
4f0767ce 16113+out:
4a4d8108 16114+ dput(parent);
dece6358
AM
16115+ return err;
16116+}
1facf9fc 16117+
1308ab2a 16118+/* ---------------------------------------------------------------------- */
16119+
4a4d8108 16120+struct dentry *au_pinned_h_parent(struct au_pin *pin)
1308ab2a 16121+{
4a4d8108
AM
16122+ if (pin && pin->parent)
16123+ return au_h_dptr(pin->parent, pin->bindex);
16124+ return NULL;
dece6358 16125+}
1facf9fc 16126+
4a4d8108 16127+void au_unpin(struct au_pin *p)
dece6358 16128+{
e49829fe 16129+ if (p->h_mnt && au_ftest_pin(p->flags, MNT_WRITE))
b4510431 16130+ vfsub_mnt_drop_write(p->h_mnt);
4a4d8108
AM
16131+ if (!p->hdir)
16132+ return;
1facf9fc 16133+
4a4d8108
AM
16134+ au_hn_imtx_unlock(p->hdir);
16135+ if (!au_ftest_pin(p->flags, DI_LOCKED))
16136+ di_read_unlock(p->parent, AuLock_IR);
16137+ iput(p->hdir->hi_inode);
16138+ dput(p->parent);
16139+ p->parent = NULL;
16140+ p->hdir = NULL;
16141+ p->h_mnt = NULL;
16142+}
1308ab2a 16143+
4a4d8108
AM
16144+int au_do_pin(struct au_pin *p)
16145+{
16146+ int err;
16147+ struct super_block *sb;
16148+ struct dentry *h_dentry, *h_parent;
16149+ struct au_branch *br;
16150+ struct inode *h_dir;
16151+
16152+ err = 0;
16153+ sb = p->dentry->d_sb;
16154+ br = au_sbr(sb, p->bindex);
16155+ if (IS_ROOT(p->dentry)) {
16156+ if (au_ftest_pin(p->flags, MNT_WRITE)) {
16157+ p->h_mnt = br->br_mnt;
b4510431 16158+ err = vfsub_mnt_want_write(p->h_mnt);
4a4d8108
AM
16159+ if (unlikely(err)) {
16160+ au_fclr_pin(p->flags, MNT_WRITE);
16161+ goto out_err;
16162+ }
16163+ }
dece6358 16164+ goto out;
1facf9fc 16165+ }
16166+
4a4d8108
AM
16167+ h_dentry = NULL;
16168+ if (p->bindex <= au_dbend(p->dentry))
16169+ h_dentry = au_h_dptr(p->dentry, p->bindex);
dece6358 16170+
4a4d8108
AM
16171+ p->parent = dget_parent(p->dentry);
16172+ if (!au_ftest_pin(p->flags, DI_LOCKED))
16173+ di_read_lock(p->parent, AuLock_IR, p->lsc_di);
dece6358 16174+
4a4d8108
AM
16175+ h_dir = NULL;
16176+ h_parent = au_h_dptr(p->parent, p->bindex);
16177+ p->hdir = au_hi(p->parent->d_inode, p->bindex);
16178+ if (p->hdir)
16179+ h_dir = p->hdir->hi_inode;
dece6358 16180+
b752ccd1
AM
16181+ /*
16182+ * udba case, or
16183+ * if DI_LOCKED is not set, then p->parent may be different
16184+ * and h_parent can be NULL.
16185+ */
16186+ if (unlikely(!p->hdir || !h_dir || !h_parent)) {
e49829fe 16187+ err = -EBUSY;
4a4d8108
AM
16188+ if (!au_ftest_pin(p->flags, DI_LOCKED))
16189+ di_read_unlock(p->parent, AuLock_IR);
16190+ dput(p->parent);
16191+ p->parent = NULL;
16192+ goto out_err;
16193+ }
1308ab2a 16194+
4a4d8108
AM
16195+ au_igrab(h_dir);
16196+ au_hn_imtx_lock_nested(p->hdir, p->lsc_hi);
1308ab2a 16197+
4a4d8108
AM
16198+ if (unlikely(p->hdir->hi_inode != h_parent->d_inode)) {
16199+ err = -EBUSY;
16200+ goto out_unpin;
16201+ }
16202+ if (h_dentry) {
16203+ err = au_h_verify(h_dentry, p->udba, h_dir, h_parent, br);
16204+ if (unlikely(err)) {
16205+ au_fclr_pin(p->flags, MNT_WRITE);
16206+ goto out_unpin;
16207+ }
1facf9fc 16208+ }
dece6358 16209+
4a4d8108
AM
16210+ if (au_ftest_pin(p->flags, MNT_WRITE)) {
16211+ p->h_mnt = br->br_mnt;
b4510431 16212+ err = vfsub_mnt_want_write(p->h_mnt);
dece6358 16213+ if (unlikely(err)) {
4a4d8108
AM
16214+ au_fclr_pin(p->flags, MNT_WRITE);
16215+ goto out_unpin;
dece6358
AM
16216+ }
16217+ }
4a4d8108
AM
16218+ goto out; /* success */
16219+
4f0767ce 16220+out_unpin:
4a4d8108 16221+ au_unpin(p);
4f0767ce 16222+out_err:
4a4d8108
AM
16223+ pr_err("err %d\n", err);
16224+ err = au_busy_or_stale();
4f0767ce 16225+out:
1facf9fc 16226+ return err;
16227+}
16228+
4a4d8108
AM
16229+void au_pin_init(struct au_pin *p, struct dentry *dentry,
16230+ aufs_bindex_t bindex, int lsc_di, int lsc_hi,
16231+ unsigned int udba, unsigned char flags)
16232+{
16233+ p->dentry = dentry;
16234+ p->udba = udba;
16235+ p->lsc_di = lsc_di;
16236+ p->lsc_hi = lsc_hi;
16237+ p->flags = flags;
16238+ p->bindex = bindex;
16239+
16240+ p->parent = NULL;
16241+ p->hdir = NULL;
16242+ p->h_mnt = NULL;
16243+}
16244+
16245+int au_pin(struct au_pin *pin, struct dentry *dentry, aufs_bindex_t bindex,
16246+ unsigned int udba, unsigned char flags)
16247+{
16248+ au_pin_init(pin, dentry, bindex, AuLsc_DI_PARENT, AuLsc_I_PARENT2,
16249+ udba, flags);
16250+ return au_do_pin(pin);
16251+}
16252+
dece6358
AM
16253+/* ---------------------------------------------------------------------- */
16254+
1308ab2a 16255+/*
4a4d8108
AM
16256+ * ->setattr() and ->getattr() are called in various cases.
16257+ * chmod, stat: dentry is revalidated.
16258+ * fchmod, fstat: file and dentry are not revalidated, additionally they may be
16259+ * unhashed.
16260+ * for ->setattr(), ia->ia_file is passed from ftruncate only.
1308ab2a 16261+ */
027c5e7a 16262+/* todo: consolidate with do_refresh() and simple_reval_dpath() */
4a4d8108 16263+static int au_reval_for_attr(struct dentry *dentry, unsigned int sigen)
1facf9fc 16264+{
4a4d8108
AM
16265+ int err;
16266+ struct inode *inode;
16267+ struct dentry *parent;
1facf9fc 16268+
1308ab2a 16269+ err = 0;
4a4d8108 16270+ inode = dentry->d_inode;
027c5e7a 16271+ if (au_digen_test(dentry, sigen)) {
4a4d8108
AM
16272+ parent = dget_parent(dentry);
16273+ di_read_lock_parent(parent, AuLock_IR);
027c5e7a 16274+ err = au_refresh_dentry(dentry, parent);
4a4d8108
AM
16275+ di_read_unlock(parent, AuLock_IR);
16276+ dput(parent);
dece6358 16277+ }
1facf9fc 16278+
4a4d8108 16279+ AuTraceErr(err);
1308ab2a 16280+ return err;
16281+}
dece6358 16282+
4a4d8108
AM
16283+#define AuIcpup_DID_CPUP 1
16284+#define au_ftest_icpup(flags, name) ((flags) & AuIcpup_##name)
7f207e10
AM
16285+#define au_fset_icpup(flags, name) \
16286+ do { (flags) |= AuIcpup_##name; } while (0)
16287+#define au_fclr_icpup(flags, name) \
16288+ do { (flags) &= ~AuIcpup_##name; } while (0)
1308ab2a 16289+
4a4d8108
AM
16290+struct au_icpup_args {
16291+ unsigned char flags;
16292+ unsigned char pin_flags;
16293+ aufs_bindex_t btgt;
16294+ unsigned int udba;
16295+ struct au_pin pin;
16296+ struct path h_path;
16297+ struct inode *h_inode;
16298+};
1308ab2a 16299+
4a4d8108
AM
16300+static int au_pin_and_icpup(struct dentry *dentry, struct iattr *ia,
16301+ struct au_icpup_args *a)
1308ab2a 16302+{
16303+ int err;
4a4d8108 16304+ loff_t sz;
e49829fe 16305+ aufs_bindex_t bstart, ibstart;
4a4d8108
AM
16306+ struct dentry *hi_wh, *parent;
16307+ struct inode *inode;
16308+ struct file *h_file;
16309+ struct au_wr_dir_args wr_dir_args = {
16310+ .force_btgt = -1,
16311+ .flags = 0
16312+ };
16313+
16314+ bstart = au_dbstart(dentry);
16315+ inode = dentry->d_inode;
16316+ if (S_ISDIR(inode->i_mode))
16317+ au_fset_wrdir(wr_dir_args.flags, ISDIR);
16318+ /* plink or hi_wh() case */
e49829fe 16319+ ibstart = au_ibstart(inode);
027c5e7a 16320+ if (bstart != ibstart && !au_test_ro(inode->i_sb, ibstart, inode))
e49829fe 16321+ wr_dir_args.force_btgt = ibstart;
4a4d8108
AM
16322+ err = au_wr_dir(dentry, /*src_dentry*/NULL, &wr_dir_args);
16323+ if (unlikely(err < 0))
16324+ goto out;
16325+ a->btgt = err;
16326+ if (err != bstart)
16327+ au_fset_icpup(a->flags, DID_CPUP);
16328+
16329+ err = 0;
16330+ a->pin_flags = AuPin_MNT_WRITE;
16331+ parent = NULL;
16332+ if (!IS_ROOT(dentry)) {
16333+ au_fset_pin(a->pin_flags, DI_LOCKED);
16334+ parent = dget_parent(dentry);
16335+ di_write_lock_parent(parent);
16336+ }
16337+
16338+ err = au_pin(&a->pin, dentry, a->btgt, a->udba, a->pin_flags);
16339+ if (unlikely(err))
16340+ goto out_parent;
16341+
16342+ a->h_path.dentry = au_h_dptr(dentry, bstart);
16343+ a->h_inode = a->h_path.dentry->d_inode;
16344+ mutex_lock_nested(&a->h_inode->i_mutex, AuLsc_I_CHILD);
16345+ sz = -1;
16346+ if ((ia->ia_valid & ATTR_SIZE) && ia->ia_size < i_size_read(a->h_inode))
16347+ sz = ia->ia_size;
16348+
16349+ h_file = NULL;
16350+ hi_wh = NULL;
027c5e7a 16351+ if (au_ftest_icpup(a->flags, DID_CPUP) && d_unlinked(dentry)) {
4a4d8108
AM
16352+ hi_wh = au_hi_wh(inode, a->btgt);
16353+ if (!hi_wh) {
16354+ err = au_sio_cpup_wh(dentry, a->btgt, sz, /*file*/NULL);
16355+ if (unlikely(err))
16356+ goto out_unlock;
16357+ hi_wh = au_hi_wh(inode, a->btgt);
16358+ /* todo: revalidate hi_wh? */
16359+ }
16360+ }
16361+
16362+ if (parent) {
16363+ au_pin_set_parent_lflag(&a->pin, /*lflag*/0);
16364+ di_downgrade_lock(parent, AuLock_IR);
16365+ dput(parent);
16366+ parent = NULL;
16367+ }
16368+ if (!au_ftest_icpup(a->flags, DID_CPUP))
16369+ goto out; /* success */
16370+
16371+ if (!d_unhashed(dentry)) {
16372+ h_file = au_h_open_pre(dentry, bstart);
16373+ if (IS_ERR(h_file)) {
16374+ err = PTR_ERR(h_file);
16375+ h_file = NULL;
16376+ } else
16377+ err = au_sio_cpup_simple(dentry, a->btgt, sz,
16378+ AuCpup_DTIME);
16379+ if (!err)
16380+ a->h_path.dentry = au_h_dptr(dentry, a->btgt);
16381+ } else if (!hi_wh)
16382+ a->h_path.dentry = au_h_dptr(dentry, a->btgt);
16383+ else
16384+ a->h_path.dentry = hi_wh; /* do not dget here */
1308ab2a 16385+
4f0767ce 16386+out_unlock:
4a4d8108
AM
16387+ mutex_unlock(&a->h_inode->i_mutex);
16388+ au_h_open_post(dentry, bstart, h_file);
16389+ a->h_inode = a->h_path.dentry->d_inode;
dece6358 16390+ if (!err) {
4a4d8108 16391+ mutex_lock_nested(&a->h_inode->i_mutex, AuLsc_I_CHILD);
dece6358 16392+ goto out; /* success */
1facf9fc 16393+ }
dece6358 16394+
4a4d8108 16395+ au_unpin(&a->pin);
4f0767ce 16396+out_parent:
4a4d8108
AM
16397+ if (parent) {
16398+ di_write_unlock(parent);
16399+ dput(parent);
16400+ }
4f0767ce 16401+out:
1facf9fc 16402+ return err;
16403+}
16404+
4a4d8108 16405+static int aufs_setattr(struct dentry *dentry, struct iattr *ia)
1facf9fc 16406+{
4a4d8108
AM
16407+ int err;
16408+ struct inode *inode;
16409+ struct super_block *sb;
16410+ struct file *file;
16411+ struct au_icpup_args *a;
1facf9fc 16412+
4a4d8108
AM
16413+ inode = dentry->d_inode;
16414+ IMustLock(inode);
dece6358 16415+
4a4d8108
AM
16416+ err = -ENOMEM;
16417+ a = kzalloc(sizeof(*a), GFP_NOFS);
16418+ if (unlikely(!a))
16419+ goto out;
1facf9fc 16420+
4a4d8108
AM
16421+ if (ia->ia_valid & (ATTR_KILL_SUID | ATTR_KILL_SGID))
16422+ ia->ia_valid &= ~ATTR_MODE;
dece6358 16423+
4a4d8108
AM
16424+ file = NULL;
16425+ sb = dentry->d_sb;
e49829fe
JR
16426+ err = si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLM);
16427+ if (unlikely(err))
16428+ goto out_kfree;
16429+
4a4d8108
AM
16430+ if (ia->ia_valid & ATTR_FILE) {
16431+ /* currently ftruncate(2) only */
16432+ AuDebugOn(!S_ISREG(inode->i_mode));
16433+ file = ia->ia_file;
16434+ err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/1);
16435+ if (unlikely(err))
16436+ goto out_si;
16437+ ia->ia_file = au_hf_top(file);
16438+ a->udba = AuOpt_UDBA_NONE;
16439+ } else {
16440+ /* fchmod() doesn't pass ia_file */
16441+ a->udba = au_opt_udba(sb);
027c5e7a
AM
16442+ di_write_lock_child(dentry);
16443+ /* no d_unlinked(), to set UDBA_NONE for root */
4a4d8108
AM
16444+ if (d_unhashed(dentry))
16445+ a->udba = AuOpt_UDBA_NONE;
4a4d8108
AM
16446+ if (a->udba != AuOpt_UDBA_NONE) {
16447+ AuDebugOn(IS_ROOT(dentry));
16448+ err = au_reval_for_attr(dentry, au_sigen(sb));
16449+ if (unlikely(err))
16450+ goto out_dentry;
16451+ }
dece6358 16452+ }
dece6358 16453+
4a4d8108
AM
16454+ err = au_pin_and_icpup(dentry, ia, a);
16455+ if (unlikely(err < 0))
16456+ goto out_dentry;
16457+ if (au_ftest_icpup(a->flags, DID_CPUP)) {
16458+ ia->ia_file = NULL;
16459+ ia->ia_valid &= ~ATTR_FILE;
1308ab2a 16460+ }
dece6358 16461+
4a4d8108
AM
16462+ a->h_path.mnt = au_sbr_mnt(sb, a->btgt);
16463+ if ((ia->ia_valid & (ATTR_MODE | ATTR_CTIME))
16464+ == (ATTR_MODE | ATTR_CTIME)) {
7eafdf33 16465+ err = security_path_chmod(&a->h_path, ia->ia_mode);
4a4d8108
AM
16466+ if (unlikely(err))
16467+ goto out_unlock;
16468+ } else if ((ia->ia_valid & (ATTR_UID | ATTR_GID))
16469+ && (ia->ia_valid & ATTR_CTIME)) {
0c3ec466
AM
16470+ err = security_path_chown(&a->h_path, vfsub_ia_uid(ia),
16471+ vfsub_ia_gid(ia));
4a4d8108
AM
16472+ if (unlikely(err))
16473+ goto out_unlock;
16474+ }
dece6358 16475+
4a4d8108
AM
16476+ if (ia->ia_valid & ATTR_SIZE) {
16477+ struct file *f;
1308ab2a 16478+
953406b4 16479+ if (ia->ia_size < i_size_read(inode))
4a4d8108 16480+ /* unmap only */
953406b4 16481+ truncate_setsize(inode, ia->ia_size);
1308ab2a 16482+
4a4d8108
AM
16483+ f = NULL;
16484+ if (ia->ia_valid & ATTR_FILE)
16485+ f = ia->ia_file;
16486+ mutex_unlock(&a->h_inode->i_mutex);
16487+ err = vfsub_trunc(&a->h_path, ia->ia_size, ia->ia_valid, f);
16488+ mutex_lock_nested(&a->h_inode->i_mutex, AuLsc_I_CHILD);
16489+ } else
16490+ err = vfsub_notify_change(&a->h_path, ia);
16491+ if (!err)
16492+ au_cpup_attr_changeable(inode);
1308ab2a 16493+
4f0767ce 16494+out_unlock:
4a4d8108
AM
16495+ mutex_unlock(&a->h_inode->i_mutex);
16496+ au_unpin(&a->pin);
027c5e7a
AM
16497+ if (unlikely(err))
16498+ au_update_dbstart(dentry);
4f0767ce 16499+out_dentry:
4a4d8108
AM
16500+ di_write_unlock(dentry);
16501+ if (file) {
16502+ fi_write_unlock(file);
16503+ ia->ia_file = file;
16504+ ia->ia_valid |= ATTR_FILE;
16505+ }
4f0767ce 16506+out_si:
4a4d8108 16507+ si_read_unlock(sb);
e49829fe 16508+out_kfree:
4a4d8108 16509+ kfree(a);
4f0767ce 16510+out:
4a4d8108
AM
16511+ AuTraceErr(err);
16512+ return err;
1facf9fc 16513+}
16514+
4a4d8108
AM
16515+static void au_refresh_iattr(struct inode *inode, struct kstat *st,
16516+ unsigned int nlink)
1facf9fc 16517+{
9dbd164d
AM
16518+ unsigned int n;
16519+
4a4d8108 16520+ inode->i_mode = st->mode;
0c3ec466
AM
16521+ i_uid_write(inode, st->uid);
16522+ i_gid_write(inode, st->gid);
4a4d8108
AM
16523+ inode->i_atime = st->atime;
16524+ inode->i_mtime = st->mtime;
16525+ inode->i_ctime = st->ctime;
1facf9fc 16526+
4a4d8108
AM
16527+ au_cpup_attr_nlink(inode, /*force*/0);
16528+ if (S_ISDIR(inode->i_mode)) {
9dbd164d
AM
16529+ n = inode->i_nlink;
16530+ n -= nlink;
16531+ n += st->nlink;
7eafdf33 16532+ /* 0 can happen */
92d182d2 16533+ set_nlink(inode, n);
4a4d8108 16534+ }
1facf9fc 16535+
4a4d8108
AM
16536+ spin_lock(&inode->i_lock);
16537+ inode->i_blocks = st->blocks;
16538+ i_size_write(inode, st->size);
16539+ spin_unlock(&inode->i_lock);
1facf9fc 16540+}
16541+
4a4d8108
AM
16542+static int aufs_getattr(struct vfsmount *mnt __maybe_unused,
16543+ struct dentry *dentry, struct kstat *st)
1facf9fc 16544+{
4a4d8108
AM
16545+ int err;
16546+ unsigned int mnt_flags;
16547+ aufs_bindex_t bindex;
16548+ unsigned char udba_none, positive;
16549+ struct super_block *sb, *h_sb;
16550+ struct inode *inode;
16551+ struct vfsmount *h_mnt;
16552+ struct dentry *h_dentry;
1facf9fc 16553+
4a4d8108
AM
16554+ sb = dentry->d_sb;
16555+ inode = dentry->d_inode;
7f207e10
AM
16556+ err = si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLM);
16557+ if (unlikely(err))
16558+ goto out;
4a4d8108
AM
16559+ mnt_flags = au_mntflags(sb);
16560+ udba_none = !!au_opt_test(mnt_flags, UDBA_NONE);
1facf9fc 16561+
4a4d8108 16562+ /* support fstat(2) */
027c5e7a 16563+ if (!d_unlinked(dentry) && !udba_none) {
4a4d8108 16564+ unsigned int sigen = au_sigen(sb);
027c5e7a
AM
16565+ err = au_digen_test(dentry, sigen);
16566+ if (!err) {
4a4d8108 16567+ di_read_lock_child(dentry, AuLock_IR);
027c5e7a
AM
16568+ err = au_dbrange_test(dentry);
16569+ if (unlikely(err))
16570+ goto out_unlock;
16571+ } else {
4a4d8108
AM
16572+ AuDebugOn(IS_ROOT(dentry));
16573+ di_write_lock_child(dentry);
027c5e7a
AM
16574+ err = au_dbrange_test(dentry);
16575+ if (!err)
16576+ err = au_reval_for_attr(dentry, sigen);
4a4d8108
AM
16577+ di_downgrade_lock(dentry, AuLock_IR);
16578+ if (unlikely(err))
7f207e10 16579+ goto out_unlock;
4a4d8108
AM
16580+ }
16581+ } else
16582+ di_read_lock_child(dentry, AuLock_IR);
1facf9fc 16583+
4a4d8108
AM
16584+ bindex = au_ibstart(inode);
16585+ h_mnt = au_sbr_mnt(sb, bindex);
16586+ h_sb = h_mnt->mnt_sb;
16587+ if (!au_test_fs_bad_iattr(h_sb) && udba_none)
16588+ goto out_fill; /* success */
1facf9fc 16589+
4a4d8108
AM
16590+ h_dentry = NULL;
16591+ if (au_dbstart(dentry) == bindex)
16592+ h_dentry = dget(au_h_dptr(dentry, bindex));
16593+ else if (au_opt_test(mnt_flags, PLINK) && au_plink_test(inode)) {
16594+ h_dentry = au_plink_lkup(inode, bindex);
16595+ if (IS_ERR(h_dentry))
16596+ goto out_fill; /* pretending success */
16597+ }
16598+ /* illegally overlapped or something */
16599+ if (unlikely(!h_dentry))
16600+ goto out_fill; /* pretending success */
16601+
16602+ positive = !!h_dentry->d_inode;
16603+ if (positive)
16604+ err = vfs_getattr(h_mnt, h_dentry, st);
16605+ dput(h_dentry);
16606+ if (!err) {
16607+ if (positive)
16608+ au_refresh_iattr(inode, st, h_dentry->d_inode->i_nlink);
16609+ goto out_fill; /* success */
1facf9fc 16610+ }
7f207e10
AM
16611+ AuTraceErr(err);
16612+ goto out_unlock;
4a4d8108 16613+
4f0767ce 16614+out_fill:
4a4d8108 16615+ generic_fillattr(inode, st);
7f207e10 16616+out_unlock:
4a4d8108
AM
16617+ di_read_unlock(dentry, AuLock_IR);
16618+ si_read_unlock(sb);
7f207e10
AM
16619+out:
16620+ AuTraceErr(err);
4a4d8108 16621+ return err;
1facf9fc 16622+}
16623+
16624+/* ---------------------------------------------------------------------- */
16625+
4a4d8108
AM
16626+static int h_readlink(struct dentry *dentry, int bindex, char __user *buf,
16627+ int bufsiz)
1facf9fc 16628+{
16629+ int err;
4a4d8108
AM
16630+ struct super_block *sb;
16631+ struct dentry *h_dentry;
1facf9fc 16632+
4a4d8108
AM
16633+ err = -EINVAL;
16634+ h_dentry = au_h_dptr(dentry, bindex);
16635+ if (unlikely(!h_dentry->d_inode->i_op->readlink))
16636+ goto out;
1facf9fc 16637+
4a4d8108
AM
16638+ err = security_inode_readlink(h_dentry);
16639+ if (unlikely(err))
dece6358 16640+ goto out;
1facf9fc 16641+
4a4d8108
AM
16642+ sb = dentry->d_sb;
16643+ if (!au_test_ro(sb, bindex, dentry->d_inode)) {
16644+ vfsub_touch_atime(au_sbr_mnt(sb, bindex), h_dentry);
16645+ fsstack_copy_attr_atime(dentry->d_inode, h_dentry->d_inode);
1facf9fc 16646+ }
4a4d8108 16647+ err = h_dentry->d_inode->i_op->readlink(h_dentry, buf, bufsiz);
1facf9fc 16648+
4f0767ce 16649+out:
4a4d8108
AM
16650+ return err;
16651+}
1facf9fc 16652+
4a4d8108
AM
16653+static int aufs_readlink(struct dentry *dentry, char __user *buf, int bufsiz)
16654+{
16655+ int err;
1facf9fc 16656+
027c5e7a
AM
16657+ err = aufs_read_lock(dentry, AuLock_IR | AuLock_GEN);
16658+ if (unlikely(err))
16659+ goto out;
16660+ err = au_d_hashed_positive(dentry);
16661+ if (!err)
16662+ err = h_readlink(dentry, au_dbstart(dentry), buf, bufsiz);
4a4d8108 16663+ aufs_read_unlock(dentry, AuLock_IR);
1facf9fc 16664+
027c5e7a 16665+out:
4a4d8108
AM
16666+ return err;
16667+}
1facf9fc 16668+
4a4d8108
AM
16669+static void *aufs_follow_link(struct dentry *dentry, struct nameidata *nd)
16670+{
16671+ int err;
4a4d8108 16672+ mm_segment_t old_fs;
b752ccd1
AM
16673+ union {
16674+ char *k;
16675+ char __user *u;
16676+ } buf;
1facf9fc 16677+
4a4d8108 16678+ err = -ENOMEM;
b752ccd1
AM
16679+ buf.k = __getname_gfp(GFP_NOFS);
16680+ if (unlikely(!buf.k))
4a4d8108 16681+ goto out;
1facf9fc 16682+
027c5e7a
AM
16683+ err = aufs_read_lock(dentry, AuLock_IR | AuLock_GEN);
16684+ if (unlikely(err))
16685+ goto out_name;
16686+
16687+ err = au_d_hashed_positive(dentry);
16688+ if (!err) {
16689+ old_fs = get_fs();
16690+ set_fs(KERNEL_DS);
16691+ err = h_readlink(dentry, au_dbstart(dentry), buf.u, PATH_MAX);
16692+ set_fs(old_fs);
16693+ }
4a4d8108 16694+ aufs_read_unlock(dentry, AuLock_IR);
1facf9fc 16695+
4a4d8108 16696+ if (err >= 0) {
b752ccd1 16697+ buf.k[err] = 0;
4a4d8108 16698+ /* will be freed by put_link */
b752ccd1 16699+ nd_set_link(nd, buf.k);
4a4d8108 16700+ return NULL; /* success */
1308ab2a 16701+ }
1facf9fc 16702+
027c5e7a
AM
16703+out_name:
16704+ __putname(buf.k);
4f0767ce 16705+out:
4a4d8108
AM
16706+ AuTraceErr(err);
16707+ return ERR_PTR(err);
16708+}
1facf9fc 16709+
4a4d8108
AM
16710+static void aufs_put_link(struct dentry *dentry __maybe_unused,
16711+ struct nameidata *nd, void *cookie __maybe_unused)
16712+{
16713+ __putname(nd_get_link(nd));
16714+}
1facf9fc 16715+
4a4d8108 16716+/* ---------------------------------------------------------------------- */
1facf9fc 16717+
0c3ec466 16718+static int aufs_update_time(struct inode *inode, struct timespec *ts, int flags)
4a4d8108 16719+{
0c3ec466
AM
16720+ int err;
16721+ struct super_block *sb;
16722+ struct inode *h_inode;
16723+
16724+ sb = inode->i_sb;
16725+ /* mmap_sem might be acquired already, cf. aufs_mmap() */
16726+ lockdep_off();
16727+ si_read_lock(sb, AuLock_FLUSH);
16728+ ii_write_lock_child(inode);
16729+ lockdep_on();
16730+ h_inode = au_h_iptr(inode, au_ibstart(inode));
16731+ err = vfsub_update_time(h_inode, ts, flags);
16732+ lockdep_off();
16733+ ii_write_unlock(inode);
16734+ si_read_unlock(sb);
16735+ lockdep_on();
16736+ return err;
4a4d8108 16737+}
1facf9fc 16738+
4a4d8108 16739+/* ---------------------------------------------------------------------- */
1308ab2a 16740+
4a4d8108
AM
16741+struct inode_operations aufs_symlink_iop = {
16742+ .permission = aufs_permission,
16743+ .setattr = aufs_setattr,
16744+ .getattr = aufs_getattr,
0c3ec466 16745+
4a4d8108
AM
16746+ .readlink = aufs_readlink,
16747+ .follow_link = aufs_follow_link,
0c3ec466
AM
16748+ .put_link = aufs_put_link,
16749+
16750+ /* .update_time = aufs_update_time */
4a4d8108
AM
16751+};
16752+
16753+struct inode_operations aufs_dir_iop = {
16754+ .create = aufs_create,
16755+ .lookup = aufs_lookup,
16756+ .link = aufs_link,
16757+ .unlink = aufs_unlink,
16758+ .symlink = aufs_symlink,
16759+ .mkdir = aufs_mkdir,
16760+ .rmdir = aufs_rmdir,
16761+ .mknod = aufs_mknod,
16762+ .rename = aufs_rename,
16763+
16764+ .permission = aufs_permission,
16765+ .setattr = aufs_setattr,
0c3ec466
AM
16766+ .getattr = aufs_getattr,
16767+
16768+ .update_time = aufs_update_time
b4510431 16769+ /* no support for atomic_open() */
4a4d8108
AM
16770+};
16771+
16772+struct inode_operations aufs_iop = {
16773+ .permission = aufs_permission,
16774+ .setattr = aufs_setattr,
16775+ .getattr = aufs_getattr,
0c3ec466
AM
16776+
16777+ .update_time = aufs_update_time
4a4d8108 16778+};
7f207e10
AM
16779diff -urN /usr/share/empty/fs/aufs/i_op_del.c linux/fs/aufs/i_op_del.c
16780--- /usr/share/empty/fs/aufs/i_op_del.c 1970-01-01 01:00:00.000000000 +0100
b4510431 16781+++ linux/fs/aufs/i_op_del.c 2012-10-17 10:31:01.772481151 +0200
53392da6 16782@@ -0,0 +1,478 @@
1facf9fc 16783+/*
f6c5ef8b 16784+ * Copyright (C) 2005-2012 Junjiro R. Okajima
1facf9fc 16785+ *
16786+ * This program, aufs is free software; you can redistribute it and/or modify
16787+ * it under the terms of the GNU General Public License as published by
16788+ * the Free Software Foundation; either version 2 of the License, or
16789+ * (at your option) any later version.
dece6358
AM
16790+ *
16791+ * This program is distributed in the hope that it will be useful,
16792+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
16793+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16794+ * GNU General Public License for more details.
16795+ *
16796+ * You should have received a copy of the GNU General Public License
16797+ * along with this program; if not, write to the Free Software
16798+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 16799+ */
16800+
16801+/*
4a4d8108 16802+ * inode operations (del entry)
1308ab2a 16803+ */
dece6358 16804+
1308ab2a 16805+#include "aufs.h"
dece6358 16806+
4a4d8108
AM
16807+/*
16808+ * decide if a new whiteout for @dentry is necessary or not.
16809+ * when it is necessary, prepare the parent dir for the upper branch whose
16810+ * branch index is @bcpup for creation. the actual creation of the whiteout will
16811+ * be done by caller.
16812+ * return value:
16813+ * 0: wh is unnecessary
16814+ * plus: wh is necessary
16815+ * minus: error
16816+ */
16817+int au_wr_dir_need_wh(struct dentry *dentry, int isdir, aufs_bindex_t *bcpup)
1308ab2a 16818+{
4a4d8108
AM
16819+ int need_wh, err;
16820+ aufs_bindex_t bstart;
16821+ struct super_block *sb;
dece6358 16822+
4a4d8108
AM
16823+ sb = dentry->d_sb;
16824+ bstart = au_dbstart(dentry);
16825+ if (*bcpup < 0) {
16826+ *bcpup = bstart;
16827+ if (au_test_ro(sb, bstart, dentry->d_inode)) {
16828+ err = AuWbrCopyup(au_sbi(sb), dentry);
16829+ *bcpup = err;
16830+ if (unlikely(err < 0))
16831+ goto out;
16832+ }
16833+ } else
16834+ AuDebugOn(bstart < *bcpup
16835+ || au_test_ro(sb, *bcpup, dentry->d_inode));
16836+ AuDbg("bcpup %d, bstart %d\n", *bcpup, bstart);
1308ab2a 16837+
4a4d8108
AM
16838+ if (*bcpup != bstart) {
16839+ err = au_cpup_dirs(dentry, *bcpup);
16840+ if (unlikely(err))
16841+ goto out;
16842+ need_wh = 1;
16843+ } else {
027c5e7a 16844+ struct au_dinfo *dinfo, *tmp;
4a4d8108 16845+
027c5e7a
AM
16846+ need_wh = -ENOMEM;
16847+ dinfo = au_di(dentry);
16848+ tmp = au_di_alloc(sb, AuLsc_DI_TMP);
16849+ if (tmp) {
16850+ au_di_cp(tmp, dinfo);
16851+ au_di_swap(tmp, dinfo);
16852+ /* returns the number of positive dentries */
16853+ need_wh = au_lkup_dentry(dentry, bstart + 1, /*type*/0,
b4510431 16854+ /*flags*/0);
027c5e7a
AM
16855+ au_di_swap(tmp, dinfo);
16856+ au_rw_write_unlock(&tmp->di_rwsem);
16857+ au_di_free(tmp);
4a4d8108
AM
16858+ }
16859+ }
16860+ AuDbg("need_wh %d\n", need_wh);
16861+ err = need_wh;
16862+
4f0767ce 16863+out:
4a4d8108 16864+ return err;
1facf9fc 16865+}
16866+
4a4d8108
AM
16867+/*
16868+ * simple tests for the del-entry operations.
16869+ * following the checks in vfs, plus the parent-child relationship.
16870+ */
16871+int au_may_del(struct dentry *dentry, aufs_bindex_t bindex,
16872+ struct dentry *h_parent, int isdir)
1facf9fc 16873+{
4a4d8108
AM
16874+ int err;
16875+ umode_t h_mode;
16876+ struct dentry *h_dentry, *h_latest;
1308ab2a 16877+ struct inode *h_inode;
1facf9fc 16878+
4a4d8108
AM
16879+ h_dentry = au_h_dptr(dentry, bindex);
16880+ h_inode = h_dentry->d_inode;
16881+ if (dentry->d_inode) {
16882+ err = -ENOENT;
16883+ if (unlikely(!h_inode || !h_inode->i_nlink))
16884+ goto out;
1facf9fc 16885+
4a4d8108
AM
16886+ h_mode = h_inode->i_mode;
16887+ if (!isdir) {
16888+ err = -EISDIR;
16889+ if (unlikely(S_ISDIR(h_mode)))
16890+ goto out;
16891+ } else if (unlikely(!S_ISDIR(h_mode))) {
16892+ err = -ENOTDIR;
16893+ goto out;
16894+ }
16895+ } else {
16896+ /* rename(2) case */
16897+ err = -EIO;
16898+ if (unlikely(h_inode))
16899+ goto out;
16900+ }
1facf9fc 16901+
4a4d8108
AM
16902+ err = -ENOENT;
16903+ /* expected parent dir is locked */
16904+ if (unlikely(h_parent != h_dentry->d_parent))
16905+ goto out;
16906+ err = 0;
16907+
16908+ /*
16909+ * rmdir a dir may break the consistency on some filesystem.
16910+ * let's try heavy test.
16911+ */
16912+ err = -EACCES;
16913+ if (unlikely(au_test_h_perm(h_parent->d_inode, MAY_EXEC | MAY_WRITE)))
16914+ goto out;
16915+
16916+ h_latest = au_sio_lkup_one(&dentry->d_name, h_parent,
16917+ au_sbr(dentry->d_sb, bindex));
16918+ err = -EIO;
16919+ if (IS_ERR(h_latest))
16920+ goto out;
16921+ if (h_latest == h_dentry)
16922+ err = 0;
16923+ dput(h_latest);
16924+
4f0767ce 16925+out:
4a4d8108 16926+ return err;
1308ab2a 16927+}
1facf9fc 16928+
4a4d8108
AM
16929+/*
16930+ * decide the branch where we operate for @dentry. the branch index will be set
16931+ * @rbcpup. after diciding it, 'pin' it and store the timestamps of the parent
16932+ * dir for reverting.
16933+ * when a new whiteout is necessary, create it.
16934+ */
16935+static struct dentry*
16936+lock_hdir_create_wh(struct dentry *dentry, int isdir, aufs_bindex_t *rbcpup,
16937+ struct au_dtime *dt, struct au_pin *pin)
1308ab2a 16938+{
4a4d8108
AM
16939+ struct dentry *wh_dentry;
16940+ struct super_block *sb;
16941+ struct path h_path;
16942+ int err, need_wh;
16943+ unsigned int udba;
16944+ aufs_bindex_t bcpup;
dece6358 16945+
4a4d8108
AM
16946+ need_wh = au_wr_dir_need_wh(dentry, isdir, rbcpup);
16947+ wh_dentry = ERR_PTR(need_wh);
16948+ if (unlikely(need_wh < 0))
16949+ goto out;
16950+
16951+ sb = dentry->d_sb;
16952+ udba = au_opt_udba(sb);
16953+ bcpup = *rbcpup;
16954+ err = au_pin(pin, dentry, bcpup, udba,
16955+ AuPin_DI_LOCKED | AuPin_MNT_WRITE);
16956+ wh_dentry = ERR_PTR(err);
16957+ if (unlikely(err))
16958+ goto out;
16959+
16960+ h_path.dentry = au_pinned_h_parent(pin);
16961+ if (udba != AuOpt_UDBA_NONE
16962+ && au_dbstart(dentry) == bcpup) {
16963+ err = au_may_del(dentry, bcpup, h_path.dentry, isdir);
16964+ wh_dentry = ERR_PTR(err);
16965+ if (unlikely(err))
16966+ goto out_unpin;
16967+ }
16968+
16969+ h_path.mnt = au_sbr_mnt(sb, bcpup);
16970+ au_dtime_store(dt, au_pinned_parent(pin), &h_path);
16971+ wh_dentry = NULL;
16972+ if (!need_wh)
16973+ goto out; /* success, no need to create whiteout */
16974+
16975+ wh_dentry = au_wh_create(dentry, bcpup, h_path.dentry);
16976+ if (IS_ERR(wh_dentry))
16977+ goto out_unpin;
16978+
16979+ /* returns with the parent is locked and wh_dentry is dget-ed */
16980+ goto out; /* success */
16981+
4f0767ce 16982+out_unpin:
4a4d8108 16983+ au_unpin(pin);
4f0767ce 16984+out:
4a4d8108 16985+ return wh_dentry;
1facf9fc 16986+}
16987+
4a4d8108
AM
16988+/*
16989+ * when removing a dir, rename it to a unique temporary whiteout-ed name first
16990+ * in order to be revertible and save time for removing many child whiteouts
16991+ * under the dir.
16992+ * returns 1 when there are too many child whiteout and caller should remove
16993+ * them asynchronously. returns 0 when the number of children is enough small to
16994+ * remove now or the branch fs is a remote fs.
16995+ * otherwise return an error.
16996+ */
16997+static int renwh_and_rmdir(struct dentry *dentry, aufs_bindex_t bindex,
16998+ struct au_nhash *whlist, struct inode *dir)
1facf9fc 16999+{
4a4d8108
AM
17000+ int rmdir_later, err, dirwh;
17001+ struct dentry *h_dentry;
17002+ struct super_block *sb;
17003+
17004+ sb = dentry->d_sb;
17005+ SiMustAnyLock(sb);
17006+ h_dentry = au_h_dptr(dentry, bindex);
17007+ err = au_whtmp_ren(h_dentry, au_sbr(sb, bindex));
17008+ if (unlikely(err))
17009+ goto out;
17010+
17011+ /* stop monitoring */
17012+ au_hn_free(au_hi(dentry->d_inode, bindex));
17013+
17014+ if (!au_test_fs_remote(h_dentry->d_sb)) {
17015+ dirwh = au_sbi(sb)->si_dirwh;
17016+ rmdir_later = (dirwh <= 1);
17017+ if (!rmdir_later)
17018+ rmdir_later = au_nhash_test_longer_wh(whlist, bindex,
17019+ dirwh);
17020+ if (rmdir_later)
17021+ return rmdir_later;
17022+ }
1facf9fc 17023+
4a4d8108
AM
17024+ err = au_whtmp_rmdir(dir, bindex, h_dentry, whlist);
17025+ if (unlikely(err)) {
17026+ AuIOErr("rmdir %.*s, b%d failed, %d. ignored\n",
17027+ AuDLNPair(h_dentry), bindex, err);
17028+ err = 0;
17029+ }
dece6358 17030+
4f0767ce 17031+out:
4a4d8108
AM
17032+ AuTraceErr(err);
17033+ return err;
17034+}
1308ab2a 17035+
4a4d8108
AM
17036+/*
17037+ * final procedure for deleting a entry.
17038+ * maintain dentry and iattr.
17039+ */
17040+static void epilog(struct inode *dir, struct dentry *dentry,
17041+ aufs_bindex_t bindex)
17042+{
17043+ struct inode *inode;
1308ab2a 17044+
4a4d8108
AM
17045+ inode = dentry->d_inode;
17046+ d_drop(dentry);
17047+ inode->i_ctime = dir->i_ctime;
1308ab2a 17048+
4a4d8108
AM
17049+ if (au_ibstart(dir) == bindex)
17050+ au_cpup_attr_timesizes(dir);
17051+ dir->i_version++;
1facf9fc 17052+}
17053+
4a4d8108
AM
17054+/*
17055+ * when an error happened, remove the created whiteout and revert everything.
17056+ */
7f207e10
AM
17057+static int do_revert(int err, struct inode *dir, aufs_bindex_t bindex,
17058+ aufs_bindex_t bwh, struct dentry *wh_dentry,
17059+ struct dentry *dentry, struct au_dtime *dt)
1facf9fc 17060+{
4a4d8108
AM
17061+ int rerr;
17062+ struct path h_path = {
17063+ .dentry = wh_dentry,
7f207e10 17064+ .mnt = au_sbr_mnt(dir->i_sb, bindex)
4a4d8108 17065+ };
dece6358 17066+
7f207e10 17067+ rerr = au_wh_unlink_dentry(au_h_iptr(dir, bindex), &h_path, dentry);
4a4d8108
AM
17068+ if (!rerr) {
17069+ au_set_dbwh(dentry, bwh);
17070+ au_dtime_revert(dt);
17071+ return 0;
17072+ }
dece6358 17073+
4a4d8108
AM
17074+ AuIOErr("%.*s reverting whiteout failed(%d, %d)\n",
17075+ AuDLNPair(dentry), err, rerr);
17076+ return -EIO;
1facf9fc 17077+}
17078+
4a4d8108 17079+/* ---------------------------------------------------------------------- */
1facf9fc 17080+
4a4d8108 17081+int aufs_unlink(struct inode *dir, struct dentry *dentry)
1308ab2a 17082+{
4a4d8108
AM
17083+ int err;
17084+ aufs_bindex_t bwh, bindex, bstart;
17085+ struct au_dtime dt;
17086+ struct au_pin pin;
17087+ struct path h_path;
17088+ struct inode *inode, *h_dir;
17089+ struct dentry *parent, *wh_dentry;
1facf9fc 17090+
4a4d8108 17091+ IMustLock(dir);
027c5e7a
AM
17092+
17093+ err = aufs_read_lock(dentry, AuLock_DW | AuLock_GEN);
17094+ if (unlikely(err))
17095+ goto out;
17096+ err = au_d_hashed_positive(dentry);
17097+ if (unlikely(err))
17098+ goto out_unlock;
4a4d8108 17099+ inode = dentry->d_inode;
4a4d8108 17100+ IMustLock(inode);
027c5e7a
AM
17101+ err = -EISDIR;
17102+ if (unlikely(S_ISDIR(inode->i_mode)))
17103+ goto out_unlock; /* possible? */
1facf9fc 17104+
4a4d8108
AM
17105+ bstart = au_dbstart(dentry);
17106+ bwh = au_dbwh(dentry);
17107+ bindex = -1;
027c5e7a
AM
17108+ parent = dentry->d_parent; /* dir inode is locked */
17109+ di_write_lock_parent(parent);
4a4d8108
AM
17110+ wh_dentry = lock_hdir_create_wh(dentry, /*isdir*/0, &bindex, &dt, &pin);
17111+ err = PTR_ERR(wh_dentry);
17112+ if (IS_ERR(wh_dentry))
027c5e7a 17113+ goto out_parent;
1facf9fc 17114+
4a4d8108
AM
17115+ h_path.mnt = au_sbr_mnt(dentry->d_sb, bstart);
17116+ h_path.dentry = au_h_dptr(dentry, bstart);
17117+ dget(h_path.dentry);
17118+ if (bindex == bstart) {
17119+ h_dir = au_pinned_h_dir(&pin);
17120+ err = vfsub_unlink(h_dir, &h_path, /*force*/0);
17121+ } else {
17122+ /* dir inode is locked */
17123+ h_dir = wh_dentry->d_parent->d_inode;
17124+ IMustLock(h_dir);
17125+ err = 0;
17126+ }
dece6358 17127+
4a4d8108 17128+ if (!err) {
7f207e10 17129+ vfsub_drop_nlink(inode);
4a4d8108
AM
17130+ epilog(dir, dentry, bindex);
17131+
17132+ /* update target timestamps */
17133+ if (bindex == bstart) {
17134+ vfsub_update_h_iattr(&h_path, /*did*/NULL); /*ignore*/
17135+ inode->i_ctime = h_path.dentry->d_inode->i_ctime;
17136+ } else
17137+ /* todo: this timestamp may be reverted later */
17138+ inode->i_ctime = h_dir->i_ctime;
027c5e7a 17139+ goto out_unpin; /* success */
1facf9fc 17140+ }
17141+
4a4d8108
AM
17142+ /* revert */
17143+ if (wh_dentry) {
17144+ int rerr;
17145+
7f207e10 17146+ rerr = do_revert(err, dir, bindex, bwh, wh_dentry, dentry, &dt);
4a4d8108
AM
17147+ if (rerr)
17148+ err = rerr;
dece6358 17149+ }
1facf9fc 17150+
027c5e7a 17151+out_unpin:
4a4d8108
AM
17152+ au_unpin(&pin);
17153+ dput(wh_dentry);
17154+ dput(h_path.dentry);
027c5e7a 17155+out_parent:
4a4d8108 17156+ di_write_unlock(parent);
027c5e7a 17157+out_unlock:
4a4d8108 17158+ aufs_read_unlock(dentry, AuLock_DW);
027c5e7a 17159+out:
4a4d8108 17160+ return err;
dece6358
AM
17161+}
17162+
4a4d8108 17163+int aufs_rmdir(struct inode *dir, struct dentry *dentry)
1308ab2a 17164+{
4a4d8108
AM
17165+ int err, rmdir_later;
17166+ aufs_bindex_t bwh, bindex, bstart;
17167+ struct au_dtime dt;
17168+ struct au_pin pin;
17169+ struct inode *inode;
17170+ struct dentry *parent, *wh_dentry, *h_dentry;
17171+ struct au_whtmp_rmdir *args;
1facf9fc 17172+
4a4d8108 17173+ IMustLock(dir);
027c5e7a
AM
17174+
17175+ err = aufs_read_lock(dentry, AuLock_DW | AuLock_FLUSH | AuLock_GEN);
17176+ if (unlikely(err))
4a4d8108 17177+ goto out;
53392da6
AM
17178+ err = au_alive_dir(dentry);
17179+ if (unlikely(err))
027c5e7a 17180+ goto out_unlock;
53392da6 17181+ inode = dentry->d_inode;
4a4d8108 17182+ IMustLock(inode);
027c5e7a
AM
17183+ err = -ENOTDIR;
17184+ if (unlikely(!S_ISDIR(inode->i_mode)))
17185+ goto out_unlock; /* possible? */
dece6358 17186+
4a4d8108
AM
17187+ err = -ENOMEM;
17188+ args = au_whtmp_rmdir_alloc(dir->i_sb, GFP_NOFS);
17189+ if (unlikely(!args))
17190+ goto out_unlock;
dece6358 17191+
4a4d8108
AM
17192+ parent = dentry->d_parent; /* dir inode is locked */
17193+ di_write_lock_parent(parent);
17194+ err = au_test_empty(dentry, &args->whlist);
17195+ if (unlikely(err))
027c5e7a 17196+ goto out_parent;
1facf9fc 17197+
4a4d8108
AM
17198+ bstart = au_dbstart(dentry);
17199+ bwh = au_dbwh(dentry);
17200+ bindex = -1;
17201+ wh_dentry = lock_hdir_create_wh(dentry, /*isdir*/1, &bindex, &dt, &pin);
17202+ err = PTR_ERR(wh_dentry);
17203+ if (IS_ERR(wh_dentry))
027c5e7a 17204+ goto out_parent;
1facf9fc 17205+
4a4d8108
AM
17206+ h_dentry = au_h_dptr(dentry, bstart);
17207+ dget(h_dentry);
17208+ rmdir_later = 0;
17209+ if (bindex == bstart) {
17210+ err = renwh_and_rmdir(dentry, bstart, &args->whlist, dir);
17211+ if (err > 0) {
17212+ rmdir_later = err;
17213+ err = 0;
17214+ }
17215+ } else {
17216+ /* stop monitoring */
17217+ au_hn_free(au_hi(inode, bstart));
17218+
17219+ /* dir inode is locked */
17220+ IMustLock(wh_dentry->d_parent->d_inode);
1facf9fc 17221+ err = 0;
17222+ }
17223+
4a4d8108 17224+ if (!err) {
027c5e7a 17225+ vfsub_dead_dir(inode);
4a4d8108
AM
17226+ au_set_dbdiropq(dentry, -1);
17227+ epilog(dir, dentry, bindex);
1308ab2a 17228+
4a4d8108
AM
17229+ if (rmdir_later) {
17230+ au_whtmp_kick_rmdir(dir, bstart, h_dentry, args);
17231+ args = NULL;
17232+ }
1308ab2a 17233+
4a4d8108 17234+ goto out_unpin; /* success */
1facf9fc 17235+ }
17236+
4a4d8108
AM
17237+ /* revert */
17238+ AuLabel(revert);
17239+ if (wh_dentry) {
17240+ int rerr;
1308ab2a 17241+
7f207e10 17242+ rerr = do_revert(err, dir, bindex, bwh, wh_dentry, dentry, &dt);
4a4d8108
AM
17243+ if (rerr)
17244+ err = rerr;
1facf9fc 17245+ }
17246+
4f0767ce 17247+out_unpin:
4a4d8108
AM
17248+ au_unpin(&pin);
17249+ dput(wh_dentry);
17250+ dput(h_dentry);
027c5e7a 17251+out_parent:
4a4d8108
AM
17252+ di_write_unlock(parent);
17253+ if (args)
17254+ au_whtmp_rmdir_free(args);
4f0767ce 17255+out_unlock:
4a4d8108 17256+ aufs_read_unlock(dentry, AuLock_DW);
4f0767ce 17257+out:
4a4d8108
AM
17258+ AuTraceErr(err);
17259+ return err;
dece6358 17260+}
7f207e10
AM
17261diff -urN /usr/share/empty/fs/aufs/i_op_ren.c linux/fs/aufs/i_op_ren.c
17262--- /usr/share/empty/fs/aufs/i_op_ren.c 1970-01-01 01:00:00.000000000 +0100
b4510431 17263+++ linux/fs/aufs/i_op_ren.c 2012-10-17 10:31:01.772481151 +0200
7eafdf33 17264@@ -0,0 +1,1026 @@
1facf9fc 17265+/*
f6c5ef8b 17266+ * Copyright (C) 2005-2012 Junjiro R. Okajima
1facf9fc 17267+ *
17268+ * This program, aufs is free software; you can redistribute it and/or modify
17269+ * it under the terms of the GNU General Public License as published by
17270+ * the Free Software Foundation; either version 2 of the License, or
17271+ * (at your option) any later version.
dece6358
AM
17272+ *
17273+ * This program is distributed in the hope that it will be useful,
17274+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
17275+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17276+ * GNU General Public License for more details.
17277+ *
17278+ * You should have received a copy of the GNU General Public License
17279+ * along with this program; if not, write to the Free Software
17280+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 17281+ */
17282+
17283+/*
4a4d8108
AM
17284+ * inode operation (rename entry)
17285+ * todo: this is crazy monster
1facf9fc 17286+ */
17287+
17288+#include "aufs.h"
17289+
4a4d8108
AM
17290+enum { AuSRC, AuDST, AuSrcDst };
17291+enum { AuPARENT, AuCHILD, AuParentChild };
1facf9fc 17292+
4a4d8108
AM
17293+#define AuRen_ISDIR 1
17294+#define AuRen_ISSAMEDIR (1 << 1)
17295+#define AuRen_WHSRC (1 << 2)
17296+#define AuRen_WHDST (1 << 3)
17297+#define AuRen_MNT_WRITE (1 << 4)
17298+#define AuRen_DT_DSTDIR (1 << 5)
17299+#define AuRen_DIROPQ (1 << 6)
17300+#define AuRen_CPUP (1 << 7)
17301+#define au_ftest_ren(flags, name) ((flags) & AuRen_##name)
7f207e10
AM
17302+#define au_fset_ren(flags, name) \
17303+ do { (flags) |= AuRen_##name; } while (0)
17304+#define au_fclr_ren(flags, name) \
17305+ do { (flags) &= ~AuRen_##name; } while (0)
1facf9fc 17306+
4a4d8108
AM
17307+struct au_ren_args {
17308+ struct {
17309+ struct dentry *dentry, *h_dentry, *parent, *h_parent,
17310+ *wh_dentry;
17311+ struct inode *dir, *inode;
17312+ struct au_hinode *hdir;
17313+ struct au_dtime dt[AuParentChild];
17314+ aufs_bindex_t bstart;
17315+ } sd[AuSrcDst];
1facf9fc 17316+
4a4d8108
AM
17317+#define src_dentry sd[AuSRC].dentry
17318+#define src_dir sd[AuSRC].dir
17319+#define src_inode sd[AuSRC].inode
17320+#define src_h_dentry sd[AuSRC].h_dentry
17321+#define src_parent sd[AuSRC].parent
17322+#define src_h_parent sd[AuSRC].h_parent
17323+#define src_wh_dentry sd[AuSRC].wh_dentry
17324+#define src_hdir sd[AuSRC].hdir
17325+#define src_h_dir sd[AuSRC].hdir->hi_inode
17326+#define src_dt sd[AuSRC].dt
17327+#define src_bstart sd[AuSRC].bstart
1facf9fc 17328+
4a4d8108
AM
17329+#define dst_dentry sd[AuDST].dentry
17330+#define dst_dir sd[AuDST].dir
17331+#define dst_inode sd[AuDST].inode
17332+#define dst_h_dentry sd[AuDST].h_dentry
17333+#define dst_parent sd[AuDST].parent
17334+#define dst_h_parent sd[AuDST].h_parent
17335+#define dst_wh_dentry sd[AuDST].wh_dentry
17336+#define dst_hdir sd[AuDST].hdir
17337+#define dst_h_dir sd[AuDST].hdir->hi_inode
17338+#define dst_dt sd[AuDST].dt
17339+#define dst_bstart sd[AuDST].bstart
17340+
17341+ struct dentry *h_trap;
17342+ struct au_branch *br;
17343+ struct au_hinode *src_hinode;
17344+ struct path h_path;
17345+ struct au_nhash whlist;
027c5e7a 17346+ aufs_bindex_t btgt, src_bwh, src_bdiropq;
1facf9fc 17347+
1308ab2a 17348+ unsigned int flags;
1facf9fc 17349+
4a4d8108
AM
17350+ struct au_whtmp_rmdir *thargs;
17351+ struct dentry *h_dst;
17352+};
1308ab2a 17353+
4a4d8108 17354+/* ---------------------------------------------------------------------- */
1308ab2a 17355+
4a4d8108
AM
17356+/*
17357+ * functions for reverting.
17358+ * when an error happened in a single rename systemcall, we should revert
17359+ * everything as if nothing happend.
17360+ * we don't need to revert the copied-up/down the parent dir since they are
17361+ * harmless.
17362+ */
1facf9fc 17363+
4a4d8108
AM
17364+#define RevertFailure(fmt, ...) do { \
17365+ AuIOErr("revert failure: " fmt " (%d, %d)\n", \
17366+ ##__VA_ARGS__, err, rerr); \
17367+ err = -EIO; \
17368+} while (0)
1facf9fc 17369+
4a4d8108 17370+static void au_ren_rev_diropq(int err, struct au_ren_args *a)
1facf9fc 17371+{
4a4d8108 17372+ int rerr;
1facf9fc 17373+
4a4d8108
AM
17374+ au_hn_imtx_lock_nested(a->src_hinode, AuLsc_I_CHILD);
17375+ rerr = au_diropq_remove(a->src_dentry, a->btgt);
17376+ au_hn_imtx_unlock(a->src_hinode);
027c5e7a 17377+ au_set_dbdiropq(a->src_dentry, a->src_bdiropq);
4a4d8108
AM
17378+ if (rerr)
17379+ RevertFailure("remove diropq %.*s", AuDLNPair(a->src_dentry));
17380+}
1facf9fc 17381+
4a4d8108
AM
17382+static void au_ren_rev_rename(int err, struct au_ren_args *a)
17383+{
17384+ int rerr;
1facf9fc 17385+
b4510431
AM
17386+ a->h_path.dentry = vfsub_lkup_one(&a->src_dentry->d_name,
17387+ a->src_h_parent);
4a4d8108
AM
17388+ rerr = PTR_ERR(a->h_path.dentry);
17389+ if (IS_ERR(a->h_path.dentry)) {
b4510431 17390+ RevertFailure("lkup one %.*s", AuDLNPair(a->src_dentry));
4a4d8108 17391+ return;
1facf9fc 17392+ }
17393+
4a4d8108
AM
17394+ rerr = vfsub_rename(a->dst_h_dir,
17395+ au_h_dptr(a->src_dentry, a->btgt),
17396+ a->src_h_dir, &a->h_path);
17397+ d_drop(a->h_path.dentry);
17398+ dput(a->h_path.dentry);
17399+ /* au_set_h_dptr(a->src_dentry, a->btgt, NULL); */
17400+ if (rerr)
17401+ RevertFailure("rename %.*s", AuDLNPair(a->src_dentry));
1facf9fc 17402+}
17403+
4a4d8108 17404+static void au_ren_rev_cpup(int err, struct au_ren_args *a)
1facf9fc 17405+{
4a4d8108 17406+ int rerr;
1facf9fc 17407+
4a4d8108
AM
17408+ a->h_path.dentry = a->dst_h_dentry;
17409+ rerr = vfsub_unlink(a->dst_h_dir, &a->h_path, /*force*/0);
17410+ au_set_h_dptr(a->src_dentry, a->btgt, NULL);
17411+ au_set_dbstart(a->src_dentry, a->src_bstart);
17412+ if (rerr)
17413+ RevertFailure("unlink %.*s", AuDLNPair(a->dst_h_dentry));
1facf9fc 17414+}
17415+
4a4d8108 17416+static void au_ren_rev_whtmp(int err, struct au_ren_args *a)
1facf9fc 17417+{
4a4d8108 17418+ int rerr;
dece6358 17419+
b4510431
AM
17420+ a->h_path.dentry = vfsub_lkup_one(&a->dst_dentry->d_name,
17421+ a->dst_h_parent);
4a4d8108
AM
17422+ rerr = PTR_ERR(a->h_path.dentry);
17423+ if (IS_ERR(a->h_path.dentry)) {
b4510431 17424+ RevertFailure("lkup one %.*s", AuDLNPair(a->dst_dentry));
4a4d8108
AM
17425+ return;
17426+ }
17427+ if (a->h_path.dentry->d_inode) {
17428+ d_drop(a->h_path.dentry);
17429+ dput(a->h_path.dentry);
17430+ return;
dece6358
AM
17431+ }
17432+
4a4d8108
AM
17433+ rerr = vfsub_rename(a->dst_h_dir, a->h_dst, a->dst_h_dir, &a->h_path);
17434+ d_drop(a->h_path.dentry);
17435+ dput(a->h_path.dentry);
17436+ if (!rerr)
17437+ au_set_h_dptr(a->dst_dentry, a->btgt, dget(a->h_dst));
17438+ else
17439+ RevertFailure("rename %.*s", AuDLNPair(a->h_dst));
17440+}
1308ab2a 17441+
4a4d8108
AM
17442+static void au_ren_rev_whsrc(int err, struct au_ren_args *a)
17443+{
17444+ int rerr;
1308ab2a 17445+
4a4d8108
AM
17446+ a->h_path.dentry = a->src_wh_dentry;
17447+ rerr = au_wh_unlink_dentry(a->src_h_dir, &a->h_path, a->src_dentry);
027c5e7a 17448+ au_set_dbwh(a->src_dentry, a->src_bwh);
4a4d8108
AM
17449+ if (rerr)
17450+ RevertFailure("unlink %.*s", AuDLNPair(a->src_wh_dentry));
17451+}
4a4d8108 17452+#undef RevertFailure
1facf9fc 17453+
1308ab2a 17454+/* ---------------------------------------------------------------------- */
17455+
4a4d8108
AM
17456+/*
17457+ * when we have to copyup the renaming entry, do it with the rename-target name
17458+ * in order to minimize the cost (the later actual rename is unnecessary).
17459+ * otherwise rename it on the target branch.
17460+ */
17461+static int au_ren_or_cpup(struct au_ren_args *a)
1facf9fc 17462+{
dece6358 17463+ int err;
4a4d8108 17464+ struct dentry *d;
1facf9fc 17465+
4a4d8108
AM
17466+ d = a->src_dentry;
17467+ if (au_dbstart(d) == a->btgt) {
17468+ a->h_path.dentry = a->dst_h_dentry;
17469+ if (au_ftest_ren(a->flags, DIROPQ)
17470+ && au_dbdiropq(d) == a->btgt)
17471+ au_fclr_ren(a->flags, DIROPQ);
17472+ AuDebugOn(au_dbstart(d) != a->btgt);
17473+ err = vfsub_rename(a->src_h_dir, au_h_dptr(d, a->btgt),
17474+ a->dst_h_dir, &a->h_path);
17475+ } else {
17476+ struct mutex *h_mtx = &a->src_h_dentry->d_inode->i_mutex;
17477+ struct file *h_file;
1308ab2a 17478+
4a4d8108
AM
17479+ au_fset_ren(a->flags, CPUP);
17480+ mutex_lock_nested(h_mtx, AuLsc_I_CHILD);
17481+ au_set_dbstart(d, a->btgt);
17482+ au_set_h_dptr(d, a->btgt, dget(a->dst_h_dentry));
17483+ h_file = au_h_open_pre(d, a->src_bstart);
17484+ if (IS_ERR(h_file)) {
17485+ err = PTR_ERR(h_file);
17486+ h_file = NULL;
17487+ } else
17488+ err = au_sio_cpup_single(d, a->btgt, a->src_bstart, -1,
17489+ !AuCpup_DTIME, a->dst_parent);
17490+ mutex_unlock(h_mtx);
17491+ au_h_open_post(d, a->src_bstart, h_file);
17492+ if (!err) {
17493+ d = a->dst_dentry;
17494+ au_set_h_dptr(d, a->btgt, NULL);
17495+ au_update_dbstart(d);
17496+ } else {
17497+ au_set_h_dptr(d, a->btgt, NULL);
17498+ au_set_dbstart(d, a->src_bstart);
17499+ }
1308ab2a 17500+ }
027c5e7a
AM
17501+ if (!err && a->h_dst)
17502+ /* it will be set to dinfo later */
17503+ dget(a->h_dst);
1facf9fc 17504+
dece6358
AM
17505+ return err;
17506+}
1facf9fc 17507+
4a4d8108
AM
17508+/* cf. aufs_rmdir() */
17509+static int au_ren_del_whtmp(struct au_ren_args *a)
dece6358 17510+{
4a4d8108
AM
17511+ int err;
17512+ struct inode *dir;
1facf9fc 17513+
4a4d8108
AM
17514+ dir = a->dst_dir;
17515+ SiMustAnyLock(dir->i_sb);
17516+ if (!au_nhash_test_longer_wh(&a->whlist, a->btgt,
17517+ au_sbi(dir->i_sb)->si_dirwh)
17518+ || au_test_fs_remote(a->h_dst->d_sb)) {
17519+ err = au_whtmp_rmdir(dir, a->btgt, a->h_dst, &a->whlist);
17520+ if (unlikely(err))
0c3ec466
AM
17521+ pr_warn("failed removing whtmp dir %.*s (%d), "
17522+ "ignored.\n", AuDLNPair(a->h_dst), err);
4a4d8108
AM
17523+ } else {
17524+ au_nhash_wh_free(&a->thargs->whlist);
17525+ a->thargs->whlist = a->whlist;
17526+ a->whlist.nh_num = 0;
17527+ au_whtmp_kick_rmdir(dir, a->btgt, a->h_dst, a->thargs);
17528+ dput(a->h_dst);
17529+ a->thargs = NULL;
17530+ }
17531+
17532+ return 0;
1308ab2a 17533+}
1facf9fc 17534+
4a4d8108
AM
17535+/* make it 'opaque' dir. */
17536+static int au_ren_diropq(struct au_ren_args *a)
17537+{
17538+ int err;
17539+ struct dentry *diropq;
1facf9fc 17540+
4a4d8108 17541+ err = 0;
027c5e7a 17542+ a->src_bdiropq = au_dbdiropq(a->src_dentry);
4a4d8108
AM
17543+ a->src_hinode = au_hi(a->src_inode, a->btgt);
17544+ au_hn_imtx_lock_nested(a->src_hinode, AuLsc_I_CHILD);
17545+ diropq = au_diropq_create(a->src_dentry, a->btgt);
17546+ au_hn_imtx_unlock(a->src_hinode);
17547+ if (IS_ERR(diropq))
17548+ err = PTR_ERR(diropq);
17549+ dput(diropq);
1facf9fc 17550+
4a4d8108
AM
17551+ return err;
17552+}
1facf9fc 17553+
4a4d8108
AM
17554+static int do_rename(struct au_ren_args *a)
17555+{
17556+ int err;
17557+ struct dentry *d, *h_d;
1facf9fc 17558+
4a4d8108
AM
17559+ /* prepare workqueue args for asynchronous rmdir */
17560+ h_d = a->dst_h_dentry;
17561+ if (au_ftest_ren(a->flags, ISDIR) && h_d->d_inode) {
17562+ err = -ENOMEM;
17563+ a->thargs = au_whtmp_rmdir_alloc(a->src_dentry->d_sb, GFP_NOFS);
17564+ if (unlikely(!a->thargs))
17565+ goto out;
17566+ a->h_dst = dget(h_d);
17567+ }
1facf9fc 17568+
4a4d8108
AM
17569+ /* create whiteout for src_dentry */
17570+ if (au_ftest_ren(a->flags, WHSRC)) {
027c5e7a
AM
17571+ a->src_bwh = au_dbwh(a->src_dentry);
17572+ AuDebugOn(a->src_bwh >= 0);
4a4d8108
AM
17573+ a->src_wh_dentry
17574+ = au_wh_create(a->src_dentry, a->btgt, a->src_h_parent);
17575+ err = PTR_ERR(a->src_wh_dentry);
17576+ if (IS_ERR(a->src_wh_dentry))
17577+ goto out_thargs;
17578+ }
1facf9fc 17579+
4a4d8108
AM
17580+ /* lookup whiteout for dentry */
17581+ if (au_ftest_ren(a->flags, WHDST)) {
17582+ h_d = au_wh_lkup(a->dst_h_parent, &a->dst_dentry->d_name,
17583+ a->br);
17584+ err = PTR_ERR(h_d);
17585+ if (IS_ERR(h_d))
17586+ goto out_whsrc;
17587+ if (!h_d->d_inode)
17588+ dput(h_d);
17589+ else
17590+ a->dst_wh_dentry = h_d;
17591+ }
1facf9fc 17592+
4a4d8108
AM
17593+ /* rename dentry to tmpwh */
17594+ if (a->thargs) {
17595+ err = au_whtmp_ren(a->dst_h_dentry, a->br);
17596+ if (unlikely(err))
17597+ goto out_whdst;
dece6358 17598+
4a4d8108
AM
17599+ d = a->dst_dentry;
17600+ au_set_h_dptr(d, a->btgt, NULL);
17601+ err = au_lkup_neg(d, a->btgt);
17602+ if (unlikely(err))
17603+ goto out_whtmp;
17604+ a->dst_h_dentry = au_h_dptr(d, a->btgt);
17605+ }
1facf9fc 17606+
4a4d8108
AM
17607+ /* cpup src */
17608+ if (a->dst_h_dentry->d_inode && a->src_bstart != a->btgt) {
17609+ struct mutex *h_mtx = &a->src_h_dentry->d_inode->i_mutex;
17610+ struct file *h_file;
1facf9fc 17611+
4a4d8108
AM
17612+ mutex_lock_nested(h_mtx, AuLsc_I_CHILD);
17613+ AuDebugOn(au_dbstart(a->src_dentry) != a->src_bstart);
17614+ h_file = au_h_open_pre(a->src_dentry, a->src_bstart);
17615+ if (IS_ERR(h_file)) {
17616+ err = PTR_ERR(h_file);
17617+ h_file = NULL;
17618+ } else
17619+ err = au_sio_cpup_simple(a->src_dentry, a->btgt, -1,
17620+ !AuCpup_DTIME);
17621+ mutex_unlock(h_mtx);
17622+ au_h_open_post(a->src_dentry, a->src_bstart, h_file);
17623+ if (unlikely(err))
17624+ goto out_whtmp;
17625+ }
1facf9fc 17626+
4a4d8108
AM
17627+ /* rename by vfs_rename or cpup */
17628+ d = a->dst_dentry;
17629+ if (au_ftest_ren(a->flags, ISDIR)
17630+ && (a->dst_wh_dentry
17631+ || au_dbdiropq(d) == a->btgt
17632+ /* hide the lower to keep xino */
17633+ || a->btgt < au_dbend(d)
17634+ || au_opt_test(au_mntflags(d->d_sb), ALWAYS_DIROPQ)))
17635+ au_fset_ren(a->flags, DIROPQ);
17636+ err = au_ren_or_cpup(a);
17637+ if (unlikely(err))
17638+ /* leave the copied-up one */
17639+ goto out_whtmp;
1308ab2a 17640+
4a4d8108
AM
17641+ /* make dir opaque */
17642+ if (au_ftest_ren(a->flags, DIROPQ)) {
17643+ err = au_ren_diropq(a);
17644+ if (unlikely(err))
17645+ goto out_rename;
17646+ }
1308ab2a 17647+
4a4d8108
AM
17648+ /* update target timestamps */
17649+ AuDebugOn(au_dbstart(a->src_dentry) != a->btgt);
17650+ a->h_path.dentry = au_h_dptr(a->src_dentry, a->btgt);
17651+ vfsub_update_h_iattr(&a->h_path, /*did*/NULL); /*ignore*/
17652+ a->src_inode->i_ctime = a->h_path.dentry->d_inode->i_ctime;
1facf9fc 17653+
4a4d8108
AM
17654+ /* remove whiteout for dentry */
17655+ if (a->dst_wh_dentry) {
17656+ a->h_path.dentry = a->dst_wh_dentry;
17657+ err = au_wh_unlink_dentry(a->dst_h_dir, &a->h_path,
17658+ a->dst_dentry);
17659+ if (unlikely(err))
17660+ goto out_diropq;
17661+ }
1facf9fc 17662+
4a4d8108
AM
17663+ /* remove whtmp */
17664+ if (a->thargs)
17665+ au_ren_del_whtmp(a); /* ignore this error */
1308ab2a 17666+
4a4d8108
AM
17667+ err = 0;
17668+ goto out_success;
17669+
4f0767ce 17670+out_diropq:
4a4d8108
AM
17671+ if (au_ftest_ren(a->flags, DIROPQ))
17672+ au_ren_rev_diropq(err, a);
4f0767ce 17673+out_rename:
4a4d8108
AM
17674+ if (!au_ftest_ren(a->flags, CPUP))
17675+ au_ren_rev_rename(err, a);
17676+ else
17677+ au_ren_rev_cpup(err, a);
027c5e7a 17678+ dput(a->h_dst);
4f0767ce 17679+out_whtmp:
4a4d8108
AM
17680+ if (a->thargs)
17681+ au_ren_rev_whtmp(err, a);
4f0767ce 17682+out_whdst:
4a4d8108
AM
17683+ dput(a->dst_wh_dentry);
17684+ a->dst_wh_dentry = NULL;
4f0767ce 17685+out_whsrc:
4a4d8108
AM
17686+ if (a->src_wh_dentry)
17687+ au_ren_rev_whsrc(err, a);
4f0767ce 17688+out_success:
4a4d8108
AM
17689+ dput(a->src_wh_dentry);
17690+ dput(a->dst_wh_dentry);
4f0767ce 17691+out_thargs:
4a4d8108
AM
17692+ if (a->thargs) {
17693+ dput(a->h_dst);
17694+ au_whtmp_rmdir_free(a->thargs);
17695+ a->thargs = NULL;
17696+ }
4f0767ce 17697+out:
4a4d8108 17698+ return err;
dece6358 17699+}
1facf9fc 17700+
1308ab2a 17701+/* ---------------------------------------------------------------------- */
1facf9fc 17702+
4a4d8108
AM
17703+/*
17704+ * test if @dentry dir can be rename destination or not.
17705+ * success means, it is a logically empty dir.
17706+ */
17707+static int may_rename_dstdir(struct dentry *dentry, struct au_nhash *whlist)
1308ab2a 17708+{
4a4d8108 17709+ return au_test_empty(dentry, whlist);
1308ab2a 17710+}
1facf9fc 17711+
4a4d8108
AM
17712+/*
17713+ * test if @dentry dir can be rename source or not.
17714+ * if it can, return 0 and @children is filled.
17715+ * success means,
17716+ * - it is a logically empty dir.
17717+ * - or, it exists on writable branch and has no children including whiteouts
17718+ * on the lower branch.
17719+ */
17720+static int may_rename_srcdir(struct dentry *dentry, aufs_bindex_t btgt)
17721+{
17722+ int err;
17723+ unsigned int rdhash;
17724+ aufs_bindex_t bstart;
1facf9fc 17725+
4a4d8108
AM
17726+ bstart = au_dbstart(dentry);
17727+ if (bstart != btgt) {
17728+ struct au_nhash whlist;
dece6358 17729+
4a4d8108
AM
17730+ SiMustAnyLock(dentry->d_sb);
17731+ rdhash = au_sbi(dentry->d_sb)->si_rdhash;
17732+ if (!rdhash)
17733+ rdhash = au_rdhash_est(au_dir_size(/*file*/NULL,
17734+ dentry));
17735+ err = au_nhash_alloc(&whlist, rdhash, GFP_NOFS);
17736+ if (unlikely(err))
17737+ goto out;
17738+ err = au_test_empty(dentry, &whlist);
17739+ au_nhash_wh_free(&whlist);
17740+ goto out;
17741+ }
dece6358 17742+
4a4d8108
AM
17743+ if (bstart == au_dbtaildir(dentry))
17744+ return 0; /* success */
dece6358 17745+
4a4d8108 17746+ err = au_test_empty_lower(dentry);
1facf9fc 17747+
4f0767ce 17748+out:
4a4d8108
AM
17749+ if (err == -ENOTEMPTY) {
17750+ AuWarn1("renaming dir who has child(ren) on multiple branches,"
17751+ " is not supported\n");
17752+ err = -EXDEV;
17753+ }
17754+ return err;
17755+}
1308ab2a 17756+
4a4d8108
AM
17757+/* side effect: sets whlist and h_dentry */
17758+static int au_ren_may_dir(struct au_ren_args *a)
1308ab2a 17759+{
4a4d8108
AM
17760+ int err;
17761+ unsigned int rdhash;
17762+ struct dentry *d;
1facf9fc 17763+
4a4d8108
AM
17764+ d = a->dst_dentry;
17765+ SiMustAnyLock(d->d_sb);
1facf9fc 17766+
4a4d8108
AM
17767+ err = 0;
17768+ if (au_ftest_ren(a->flags, ISDIR) && a->dst_inode) {
17769+ rdhash = au_sbi(d->d_sb)->si_rdhash;
17770+ if (!rdhash)
17771+ rdhash = au_rdhash_est(au_dir_size(/*file*/NULL, d));
17772+ err = au_nhash_alloc(&a->whlist, rdhash, GFP_NOFS);
17773+ if (unlikely(err))
17774+ goto out;
1308ab2a 17775+
4a4d8108
AM
17776+ au_set_dbstart(d, a->dst_bstart);
17777+ err = may_rename_dstdir(d, &a->whlist);
17778+ au_set_dbstart(d, a->btgt);
17779+ }
17780+ a->dst_h_dentry = au_h_dptr(d, au_dbstart(d));
17781+ if (unlikely(err))
17782+ goto out;
17783+
17784+ d = a->src_dentry;
17785+ a->src_h_dentry = au_h_dptr(d, au_dbstart(d));
17786+ if (au_ftest_ren(a->flags, ISDIR)) {
17787+ err = may_rename_srcdir(d, a->btgt);
17788+ if (unlikely(err)) {
17789+ au_nhash_wh_free(&a->whlist);
17790+ a->whlist.nh_num = 0;
17791+ }
17792+ }
4f0767ce 17793+out:
4a4d8108 17794+ return err;
1facf9fc 17795+}
17796+
4a4d8108 17797+/* ---------------------------------------------------------------------- */
1facf9fc 17798+
4a4d8108
AM
17799+/*
17800+ * simple tests for rename.
17801+ * following the checks in vfs, plus the parent-child relationship.
17802+ */
17803+static int au_may_ren(struct au_ren_args *a)
17804+{
17805+ int err, isdir;
17806+ struct inode *h_inode;
1facf9fc 17807+
4a4d8108
AM
17808+ if (a->src_bstart == a->btgt) {
17809+ err = au_may_del(a->src_dentry, a->btgt, a->src_h_parent,
17810+ au_ftest_ren(a->flags, ISDIR));
17811+ if (unlikely(err))
17812+ goto out;
17813+ err = -EINVAL;
17814+ if (unlikely(a->src_h_dentry == a->h_trap))
17815+ goto out;
17816+ }
1facf9fc 17817+
4a4d8108
AM
17818+ err = 0;
17819+ if (a->dst_bstart != a->btgt)
17820+ goto out;
1facf9fc 17821+
027c5e7a
AM
17822+ err = -ENOTEMPTY;
17823+ if (unlikely(a->dst_h_dentry == a->h_trap))
17824+ goto out;
17825+
4a4d8108
AM
17826+ err = -EIO;
17827+ h_inode = a->dst_h_dentry->d_inode;
17828+ isdir = !!au_ftest_ren(a->flags, ISDIR);
17829+ if (!a->dst_dentry->d_inode) {
17830+ if (unlikely(h_inode))
17831+ goto out;
17832+ err = au_may_add(a->dst_dentry, a->btgt, a->dst_h_parent,
17833+ isdir);
17834+ } else {
17835+ if (unlikely(!h_inode || !h_inode->i_nlink))
17836+ goto out;
17837+ err = au_may_del(a->dst_dentry, a->btgt, a->dst_h_parent,
17838+ isdir);
17839+ if (unlikely(err))
17840+ goto out;
4a4d8108 17841+ }
1facf9fc 17842+
4f0767ce 17843+out:
4a4d8108
AM
17844+ if (unlikely(err == -ENOENT || err == -EEXIST))
17845+ err = -EIO;
17846+ AuTraceErr(err);
17847+ return err;
17848+}
1facf9fc 17849+
1308ab2a 17850+/* ---------------------------------------------------------------------- */
1facf9fc 17851+
4a4d8108
AM
17852+/*
17853+ * locking order
17854+ * (VFS)
17855+ * - src_dir and dir by lock_rename()
17856+ * - inode if exitsts
17857+ * (aufs)
17858+ * - lock all
17859+ * + src_dentry and dentry by aufs_read_and_write_lock2() which calls,
17860+ * + si_read_lock
17861+ * + di_write_lock2_child()
17862+ * + di_write_lock_child()
17863+ * + ii_write_lock_child()
17864+ * + di_write_lock_child2()
17865+ * + ii_write_lock_child2()
17866+ * + src_parent and parent
17867+ * + di_write_lock_parent()
17868+ * + ii_write_lock_parent()
17869+ * + di_write_lock_parent2()
17870+ * + ii_write_lock_parent2()
17871+ * + lower src_dir and dir by vfsub_lock_rename()
17872+ * + verify the every relationships between child and parent. if any
17873+ * of them failed, unlock all and return -EBUSY.
17874+ */
17875+static void au_ren_unlock(struct au_ren_args *a)
1308ab2a 17876+{
4a4d8108
AM
17877+ struct super_block *sb;
17878+
17879+ sb = a->dst_dentry->d_sb;
17880+ if (au_ftest_ren(a->flags, MNT_WRITE))
b4510431 17881+ vfsub_mnt_drop_write(a->br->br_mnt);
4a4d8108
AM
17882+ vfsub_unlock_rename(a->src_h_parent, a->src_hdir,
17883+ a->dst_h_parent, a->dst_hdir);
1308ab2a 17884+}
17885+
4a4d8108 17886+static int au_ren_lock(struct au_ren_args *a)
1308ab2a 17887+{
4a4d8108
AM
17888+ int err;
17889+ unsigned int udba;
1308ab2a 17890+
4a4d8108
AM
17891+ err = 0;
17892+ a->src_h_parent = au_h_dptr(a->src_parent, a->btgt);
17893+ a->src_hdir = au_hi(a->src_dir, a->btgt);
17894+ a->dst_h_parent = au_h_dptr(a->dst_parent, a->btgt);
17895+ a->dst_hdir = au_hi(a->dst_dir, a->btgt);
17896+ a->h_trap = vfsub_lock_rename(a->src_h_parent, a->src_hdir,
17897+ a->dst_h_parent, a->dst_hdir);
17898+ udba = au_opt_udba(a->src_dentry->d_sb);
17899+ if (unlikely(a->src_hdir->hi_inode != a->src_h_parent->d_inode
17900+ || a->dst_hdir->hi_inode != a->dst_h_parent->d_inode))
17901+ err = au_busy_or_stale();
17902+ if (!err && au_dbstart(a->src_dentry) == a->btgt)
17903+ err = au_h_verify(a->src_h_dentry, udba,
17904+ a->src_h_parent->d_inode, a->src_h_parent,
17905+ a->br);
17906+ if (!err && au_dbstart(a->dst_dentry) == a->btgt)
17907+ err = au_h_verify(a->dst_h_dentry, udba,
17908+ a->dst_h_parent->d_inode, a->dst_h_parent,
17909+ a->br);
17910+ if (!err) {
b4510431 17911+ err = vfsub_mnt_want_write(a->br->br_mnt);
4a4d8108
AM
17912+ if (unlikely(err))
17913+ goto out_unlock;
17914+ au_fset_ren(a->flags, MNT_WRITE);
17915+ goto out; /* success */
17916+ }
17917+
17918+ err = au_busy_or_stale();
17919+
4f0767ce 17920+out_unlock:
4a4d8108 17921+ au_ren_unlock(a);
4f0767ce 17922+out:
4a4d8108 17923+ return err;
1facf9fc 17924+}
17925+
17926+/* ---------------------------------------------------------------------- */
17927+
4a4d8108 17928+static void au_ren_refresh_dir(struct au_ren_args *a)
1facf9fc 17929+{
4a4d8108 17930+ struct inode *dir;
dece6358 17931+
4a4d8108
AM
17932+ dir = a->dst_dir;
17933+ dir->i_version++;
17934+ if (au_ftest_ren(a->flags, ISDIR)) {
17935+ /* is this updating defined in POSIX? */
17936+ au_cpup_attr_timesizes(a->src_inode);
17937+ au_cpup_attr_nlink(dir, /*force*/1);
4a4d8108 17938+ }
027c5e7a 17939+
4a4d8108
AM
17940+ if (au_ibstart(dir) == a->btgt)
17941+ au_cpup_attr_timesizes(dir);
dece6358 17942+
4a4d8108
AM
17943+ if (au_ftest_ren(a->flags, ISSAMEDIR))
17944+ return;
dece6358 17945+
4a4d8108
AM
17946+ dir = a->src_dir;
17947+ dir->i_version++;
17948+ if (au_ftest_ren(a->flags, ISDIR))
17949+ au_cpup_attr_nlink(dir, /*force*/1);
17950+ if (au_ibstart(dir) == a->btgt)
17951+ au_cpup_attr_timesizes(dir);
1facf9fc 17952+}
17953+
4a4d8108 17954+static void au_ren_refresh(struct au_ren_args *a)
1facf9fc 17955+{
4a4d8108
AM
17956+ aufs_bindex_t bend, bindex;
17957+ struct dentry *d, *h_d;
17958+ struct inode *i, *h_i;
17959+ struct super_block *sb;
dece6358 17960+
027c5e7a
AM
17961+ d = a->dst_dentry;
17962+ d_drop(d);
17963+ if (a->h_dst)
17964+ /* already dget-ed by au_ren_or_cpup() */
17965+ au_set_h_dptr(d, a->btgt, a->h_dst);
17966+
17967+ i = a->dst_inode;
17968+ if (i) {
17969+ if (!au_ftest_ren(a->flags, ISDIR))
17970+ vfsub_drop_nlink(i);
17971+ else {
17972+ vfsub_dead_dir(i);
17973+ au_cpup_attr_timesizes(i);
17974+ }
17975+ au_update_dbrange(d, /*do_put_zero*/1);
17976+ } else {
17977+ bend = a->btgt;
17978+ for (bindex = au_dbstart(d); bindex < bend; bindex++)
17979+ au_set_h_dptr(d, bindex, NULL);
17980+ bend = au_dbend(d);
17981+ for (bindex = a->btgt + 1; bindex <= bend; bindex++)
17982+ au_set_h_dptr(d, bindex, NULL);
17983+ au_update_dbrange(d, /*do_put_zero*/0);
17984+ }
17985+
4a4d8108
AM
17986+ d = a->src_dentry;
17987+ au_set_dbwh(d, -1);
17988+ bend = au_dbend(d);
17989+ for (bindex = a->btgt + 1; bindex <= bend; bindex++) {
17990+ h_d = au_h_dptr(d, bindex);
17991+ if (h_d)
17992+ au_set_h_dptr(d, bindex, NULL);
17993+ }
17994+ au_set_dbend(d, a->btgt);
17995+
17996+ sb = d->d_sb;
17997+ i = a->src_inode;
17998+ if (au_opt_test(au_mntflags(sb), PLINK) && au_plink_test(i))
17999+ return; /* success */
18000+
18001+ bend = au_ibend(i);
18002+ for (bindex = a->btgt + 1; bindex <= bend; bindex++) {
18003+ h_i = au_h_iptr(i, bindex);
18004+ if (h_i) {
18005+ au_xino_write(sb, bindex, h_i->i_ino, /*ino*/0);
18006+ /* ignore this error */
18007+ au_set_h_iptr(i, bindex, NULL, 0);
18008+ }
18009+ }
18010+ au_set_ibend(i, a->btgt);
1308ab2a 18011+}
dece6358 18012+
4a4d8108
AM
18013+/* ---------------------------------------------------------------------- */
18014+
18015+/* mainly for link(2) and rename(2) */
18016+int au_wbr(struct dentry *dentry, aufs_bindex_t btgt)
1308ab2a 18017+{
4a4d8108
AM
18018+ aufs_bindex_t bdiropq, bwh;
18019+ struct dentry *parent;
18020+ struct au_branch *br;
18021+
18022+ parent = dentry->d_parent;
18023+ IMustLock(parent->d_inode); /* dir is locked */
18024+
18025+ bdiropq = au_dbdiropq(parent);
18026+ bwh = au_dbwh(dentry);
18027+ br = au_sbr(dentry->d_sb, btgt);
18028+ if (au_br_rdonly(br)
18029+ || (0 <= bdiropq && bdiropq < btgt)
18030+ || (0 <= bwh && bwh < btgt))
18031+ btgt = -1;
18032+
18033+ AuDbg("btgt %d\n", btgt);
18034+ return btgt;
1facf9fc 18035+}
18036+
4a4d8108
AM
18037+/* sets src_bstart, dst_bstart and btgt */
18038+static int au_ren_wbr(struct au_ren_args *a)
1facf9fc 18039+{
4a4d8108
AM
18040+ int err;
18041+ struct au_wr_dir_args wr_dir_args = {
18042+ /* .force_btgt = -1, */
18043+ .flags = AuWrDir_ADD_ENTRY
18044+ };
dece6358 18045+
4a4d8108
AM
18046+ a->src_bstart = au_dbstart(a->src_dentry);
18047+ a->dst_bstart = au_dbstart(a->dst_dentry);
18048+ if (au_ftest_ren(a->flags, ISDIR))
18049+ au_fset_wrdir(wr_dir_args.flags, ISDIR);
18050+ wr_dir_args.force_btgt = a->src_bstart;
18051+ if (a->dst_inode && a->dst_bstart < a->src_bstart)
18052+ wr_dir_args.force_btgt = a->dst_bstart;
18053+ wr_dir_args.force_btgt = au_wbr(a->dst_dentry, wr_dir_args.force_btgt);
18054+ err = au_wr_dir(a->dst_dentry, a->src_dentry, &wr_dir_args);
18055+ a->btgt = err;
dece6358 18056+
4a4d8108 18057+ return err;
1facf9fc 18058+}
18059+
4a4d8108 18060+static void au_ren_dt(struct au_ren_args *a)
1facf9fc 18061+{
4a4d8108
AM
18062+ a->h_path.dentry = a->src_h_parent;
18063+ au_dtime_store(a->src_dt + AuPARENT, a->src_parent, &a->h_path);
18064+ if (!au_ftest_ren(a->flags, ISSAMEDIR)) {
18065+ a->h_path.dentry = a->dst_h_parent;
18066+ au_dtime_store(a->dst_dt + AuPARENT, a->dst_parent, &a->h_path);
18067+ }
1facf9fc 18068+
4a4d8108
AM
18069+ au_fclr_ren(a->flags, DT_DSTDIR);
18070+ if (!au_ftest_ren(a->flags, ISDIR))
18071+ return;
dece6358 18072+
4a4d8108
AM
18073+ a->h_path.dentry = a->src_h_dentry;
18074+ au_dtime_store(a->src_dt + AuCHILD, a->src_dentry, &a->h_path);
18075+ if (a->dst_h_dentry->d_inode) {
18076+ au_fset_ren(a->flags, DT_DSTDIR);
18077+ a->h_path.dentry = a->dst_h_dentry;
18078+ au_dtime_store(a->dst_dt + AuCHILD, a->dst_dentry, &a->h_path);
18079+ }
1308ab2a 18080+}
dece6358 18081+
4a4d8108 18082+static void au_ren_rev_dt(int err, struct au_ren_args *a)
1308ab2a 18083+{
4a4d8108
AM
18084+ struct dentry *h_d;
18085+ struct mutex *h_mtx;
18086+
18087+ au_dtime_revert(a->src_dt + AuPARENT);
18088+ if (!au_ftest_ren(a->flags, ISSAMEDIR))
18089+ au_dtime_revert(a->dst_dt + AuPARENT);
18090+
18091+ if (au_ftest_ren(a->flags, ISDIR) && err != -EIO) {
18092+ h_d = a->src_dt[AuCHILD].dt_h_path.dentry;
18093+ h_mtx = &h_d->d_inode->i_mutex;
18094+ mutex_lock_nested(h_mtx, AuLsc_I_CHILD);
18095+ au_dtime_revert(a->src_dt + AuCHILD);
18096+ mutex_unlock(h_mtx);
18097+
18098+ if (au_ftest_ren(a->flags, DT_DSTDIR)) {
18099+ h_d = a->dst_dt[AuCHILD].dt_h_path.dentry;
18100+ h_mtx = &h_d->d_inode->i_mutex;
18101+ mutex_lock_nested(h_mtx, AuLsc_I_CHILD);
18102+ au_dtime_revert(a->dst_dt + AuCHILD);
18103+ mutex_unlock(h_mtx);
1facf9fc 18104+ }
18105+ }
18106+}
18107+
4a4d8108
AM
18108+/* ---------------------------------------------------------------------- */
18109+
18110+int aufs_rename(struct inode *_src_dir, struct dentry *_src_dentry,
18111+ struct inode *_dst_dir, struct dentry *_dst_dentry)
1facf9fc 18112+{
e49829fe 18113+ int err, flags;
4a4d8108
AM
18114+ /* reduce stack space */
18115+ struct au_ren_args *a;
18116+
18117+ AuDbg("%.*s, %.*s\n", AuDLNPair(_src_dentry), AuDLNPair(_dst_dentry));
18118+ IMustLock(_src_dir);
18119+ IMustLock(_dst_dir);
18120+
18121+ err = -ENOMEM;
18122+ BUILD_BUG_ON(sizeof(*a) > PAGE_SIZE);
18123+ a = kzalloc(sizeof(*a), GFP_NOFS);
18124+ if (unlikely(!a))
18125+ goto out;
18126+
18127+ a->src_dir = _src_dir;
18128+ a->src_dentry = _src_dentry;
18129+ a->src_inode = a->src_dentry->d_inode;
18130+ a->src_parent = a->src_dentry->d_parent; /* dir inode is locked */
18131+ a->dst_dir = _dst_dir;
18132+ a->dst_dentry = _dst_dentry;
18133+ a->dst_inode = a->dst_dentry->d_inode;
18134+ a->dst_parent = a->dst_dentry->d_parent; /* dir inode is locked */
18135+ if (a->dst_inode) {
18136+ IMustLock(a->dst_inode);
18137+ au_igrab(a->dst_inode);
1facf9fc 18138+ }
1facf9fc 18139+
4a4d8108 18140+ err = -ENOTDIR;
027c5e7a 18141+ flags = AuLock_FLUSH | AuLock_NOPLM | AuLock_GEN;
4a4d8108
AM
18142+ if (S_ISDIR(a->src_inode->i_mode)) {
18143+ au_fset_ren(a->flags, ISDIR);
18144+ if (unlikely(a->dst_inode && !S_ISDIR(a->dst_inode->i_mode)))
18145+ goto out_free;
e49829fe
JR
18146+ err = aufs_read_and_write_lock2(a->dst_dentry, a->src_dentry,
18147+ AuLock_DIR | flags);
4a4d8108 18148+ } else
e49829fe
JR
18149+ err = aufs_read_and_write_lock2(a->dst_dentry, a->src_dentry,
18150+ flags);
18151+ if (unlikely(err))
18152+ goto out_free;
1facf9fc 18153+
027c5e7a
AM
18154+ err = au_d_hashed_positive(a->src_dentry);
18155+ if (unlikely(err))
18156+ goto out_unlock;
18157+ err = -ENOENT;
18158+ if (a->dst_inode) {
18159+ /*
18160+ * If it is a dir, VFS unhash dst_dentry before this
18161+ * function. It means we cannot rely upon d_unhashed().
18162+ */
18163+ if (unlikely(!a->dst_inode->i_nlink))
18164+ goto out_unlock;
18165+ if (!S_ISDIR(a->dst_inode->i_mode)) {
18166+ err = au_d_hashed_positive(a->dst_dentry);
18167+ if (unlikely(err))
18168+ goto out_unlock;
18169+ } else if (unlikely(IS_DEADDIR(a->dst_inode)))
18170+ goto out_unlock;
18171+ } else if (unlikely(d_unhashed(a->dst_dentry)))
18172+ goto out_unlock;
18173+
7eafdf33
AM
18174+ /*
18175+ * is it possible?
18176+ * yes, it happend (in linux-3.3-rcN) but I don't know why.
18177+ * there may exist a problem somewhere else.
18178+ */
18179+ err = -EINVAL;
18180+ if (unlikely(a->dst_parent->d_inode == a->src_dentry->d_inode))
18181+ goto out_unlock;
18182+
4a4d8108
AM
18183+ au_fset_ren(a->flags, ISSAMEDIR); /* temporary */
18184+ di_write_lock_parent(a->dst_parent);
1facf9fc 18185+
4a4d8108
AM
18186+ /* which branch we process */
18187+ err = au_ren_wbr(a);
18188+ if (unlikely(err < 0))
027c5e7a 18189+ goto out_parent;
4a4d8108
AM
18190+ a->br = au_sbr(a->dst_dentry->d_sb, a->btgt);
18191+ a->h_path.mnt = a->br->br_mnt;
1facf9fc 18192+
4a4d8108
AM
18193+ /* are they available to be renamed */
18194+ err = au_ren_may_dir(a);
18195+ if (unlikely(err))
18196+ goto out_children;
1facf9fc 18197+
4a4d8108
AM
18198+ /* prepare the writable parent dir on the same branch */
18199+ if (a->dst_bstart == a->btgt) {
18200+ au_fset_ren(a->flags, WHDST);
18201+ } else {
18202+ err = au_cpup_dirs(a->dst_dentry, a->btgt);
18203+ if (unlikely(err))
18204+ goto out_children;
18205+ }
1facf9fc 18206+
4a4d8108
AM
18207+ if (a->src_dir != a->dst_dir) {
18208+ /*
18209+ * this temporary unlock is safe,
18210+ * because both dir->i_mutex are locked.
18211+ */
18212+ di_write_unlock(a->dst_parent);
18213+ di_write_lock_parent(a->src_parent);
18214+ err = au_wr_dir_need_wh(a->src_dentry,
18215+ au_ftest_ren(a->flags, ISDIR),
18216+ &a->btgt);
18217+ di_write_unlock(a->src_parent);
18218+ di_write_lock2_parent(a->src_parent, a->dst_parent, /*isdir*/1);
18219+ au_fclr_ren(a->flags, ISSAMEDIR);
18220+ } else
18221+ err = au_wr_dir_need_wh(a->src_dentry,
18222+ au_ftest_ren(a->flags, ISDIR),
18223+ &a->btgt);
18224+ if (unlikely(err < 0))
18225+ goto out_children;
18226+ if (err)
18227+ au_fset_ren(a->flags, WHSRC);
1facf9fc 18228+
4a4d8108
AM
18229+ /* lock them all */
18230+ err = au_ren_lock(a);
18231+ if (unlikely(err))
18232+ goto out_children;
1facf9fc 18233+
4a4d8108
AM
18234+ if (!au_opt_test(au_mntflags(a->dst_dir->i_sb), UDBA_NONE))
18235+ err = au_may_ren(a);
18236+ else if (unlikely(a->dst_dentry->d_name.len > AUFS_MAX_NAMELEN))
18237+ err = -ENAMETOOLONG;
18238+ if (unlikely(err))
18239+ goto out_hdir;
1facf9fc 18240+
4a4d8108
AM
18241+ /* store timestamps to be revertible */
18242+ au_ren_dt(a);
1facf9fc 18243+
4a4d8108
AM
18244+ /* here we go */
18245+ err = do_rename(a);
18246+ if (unlikely(err))
18247+ goto out_dt;
18248+
18249+ /* update dir attributes */
18250+ au_ren_refresh_dir(a);
18251+
18252+ /* dput/iput all lower dentries */
18253+ au_ren_refresh(a);
18254+
18255+ goto out_hdir; /* success */
18256+
4f0767ce 18257+out_dt:
4a4d8108 18258+ au_ren_rev_dt(err, a);
4f0767ce 18259+out_hdir:
4a4d8108 18260+ au_ren_unlock(a);
4f0767ce 18261+out_children:
4a4d8108 18262+ au_nhash_wh_free(&a->whlist);
027c5e7a
AM
18263+ if (err && a->dst_inode && a->dst_bstart != a->btgt) {
18264+ AuDbg("bstart %d, btgt %d\n", a->dst_bstart, a->btgt);
18265+ au_set_h_dptr(a->dst_dentry, a->btgt, NULL);
18266+ au_set_dbstart(a->dst_dentry, a->dst_bstart);
4a4d8108 18267+ }
027c5e7a 18268+out_parent:
4a4d8108
AM
18269+ if (!err)
18270+ d_move(a->src_dentry, a->dst_dentry);
027c5e7a
AM
18271+ else {
18272+ au_update_dbstart(a->dst_dentry);
18273+ if (!a->dst_inode)
18274+ d_drop(a->dst_dentry);
18275+ }
4a4d8108
AM
18276+ if (au_ftest_ren(a->flags, ISSAMEDIR))
18277+ di_write_unlock(a->dst_parent);
18278+ else
18279+ di_write_unlock2(a->src_parent, a->dst_parent);
027c5e7a 18280+out_unlock:
4a4d8108 18281+ aufs_read_and_write_unlock2(a->dst_dentry, a->src_dentry);
4f0767ce 18282+out_free:
4a4d8108
AM
18283+ iput(a->dst_inode);
18284+ if (a->thargs)
18285+ au_whtmp_rmdir_free(a->thargs);
18286+ kfree(a);
4f0767ce 18287+out:
4a4d8108
AM
18288+ AuTraceErr(err);
18289+ return err;
1308ab2a 18290+}
7f207e10
AM
18291diff -urN /usr/share/empty/fs/aufs/Kconfig linux/fs/aufs/Kconfig
18292--- /usr/share/empty/fs/aufs/Kconfig 1970-01-01 01:00:00.000000000 +0100
2dfbb274 18293+++ linux/fs/aufs/Kconfig 2012-08-26 08:39:00.757174634 +0200
2cbb1c4b 18294@@ -0,0 +1,203 @@
4a4d8108
AM
18295+config AUFS_FS
18296+ tristate "Aufs (Advanced multi layered unification filesystem) support"
18297+ depends on EXPERIMENTAL
18298+ help
18299+ Aufs is a stackable unification filesystem such as Unionfs,
18300+ which unifies several directories and provides a merged single
18301+ directory.
18302+ In the early days, aufs was entirely re-designed and
18303+ re-implemented Unionfs Version 1.x series. Introducing many
18304+ original ideas, approaches and improvements, it becomes totally
18305+ different from Unionfs while keeping the basic features.
1facf9fc 18306+
4a4d8108
AM
18307+if AUFS_FS
18308+choice
18309+ prompt "Maximum number of branches"
18310+ default AUFS_BRANCH_MAX_127
18311+ help
18312+ Specifies the maximum number of branches (or member directories)
18313+ in a single aufs. The larger value consumes more system
18314+ resources and has a minor impact to performance.
18315+config AUFS_BRANCH_MAX_127
18316+ bool "127"
18317+ help
18318+ Specifies the maximum number of branches (or member directories)
18319+ in a single aufs. The larger value consumes more system
18320+ resources and has a minor impact to performance.
18321+config AUFS_BRANCH_MAX_511
18322+ bool "511"
18323+ help
18324+ Specifies the maximum number of branches (or member directories)
18325+ in a single aufs. The larger value consumes more system
18326+ resources and has a minor impact to performance.
18327+config AUFS_BRANCH_MAX_1023
18328+ bool "1023"
18329+ help
18330+ Specifies the maximum number of branches (or member directories)
18331+ in a single aufs. The larger value consumes more system
18332+ resources and has a minor impact to performance.
18333+config AUFS_BRANCH_MAX_32767
18334+ bool "32767"
18335+ help
18336+ Specifies the maximum number of branches (or member directories)
18337+ in a single aufs. The larger value consumes more system
18338+ resources and has a minor impact to performance.
18339+endchoice
1facf9fc 18340+
e49829fe
JR
18341+config AUFS_SBILIST
18342+ bool
18343+ depends on AUFS_MAGIC_SYSRQ || PROC_FS
18344+ default y
18345+ help
18346+ Automatic configuration for internal use.
18347+ When aufs supports Magic SysRq or /proc, enabled automatically.
18348+
4a4d8108
AM
18349+config AUFS_HNOTIFY
18350+ bool "Detect direct branch access (bypassing aufs)"
18351+ help
18352+ If you want to modify files on branches directly, eg. bypassing aufs,
18353+ and want aufs to detect the changes of them fully, then enable this
18354+ option and use 'udba=notify' mount option.
7f207e10 18355+ Currently there is only one available configuration, "fsnotify".
4a4d8108
AM
18356+ It will have a negative impact to the performance.
18357+ See detail in aufs.5.
dece6358 18358+
4a4d8108
AM
18359+choice
18360+ prompt "method" if AUFS_HNOTIFY
18361+ default AUFS_HFSNOTIFY
18362+config AUFS_HFSNOTIFY
18363+ bool "fsnotify"
18364+ select FSNOTIFY
4a4d8108 18365+endchoice
1facf9fc 18366+
4a4d8108
AM
18367+config AUFS_EXPORT
18368+ bool "NFS-exportable aufs"
2cbb1c4b 18369+ depends on EXPORTFS
4a4d8108
AM
18370+ help
18371+ If you want to export your mounted aufs via NFS, then enable this
18372+ option. There are several requirements for this configuration.
18373+ See detail in aufs.5.
1facf9fc 18374+
4a4d8108
AM
18375+config AUFS_INO_T_64
18376+ bool
18377+ depends on AUFS_EXPORT
18378+ depends on 64BIT && !(ALPHA || S390)
18379+ default y
18380+ help
18381+ Automatic configuration for internal use.
18382+ /* typedef unsigned long/int __kernel_ino_t */
18383+ /* alpha and s390x are int */
1facf9fc 18384+
4a4d8108
AM
18385+config AUFS_RDU
18386+ bool "Readdir in userspace"
18387+ help
18388+ Aufs has two methods to provide a merged view for a directory,
18389+ by a user-space library and by kernel-space natively. The latter
18390+ is always enabled but sometimes large and slow.
18391+ If you enable this option, install the library in aufs2-util
18392+ package, and set some environment variables for your readdir(3),
18393+ then the work will be handled in user-space which generally
18394+ shows better performance in most cases.
18395+ See detail in aufs.5.
1facf9fc 18396+
2cbb1c4b
JR
18397+config AUFS_PROC_MAP
18398+ bool "support for /proc/maps and lsof(1)"
18399+ depends on PROC_FS
18400+ help
18401+ When you issue mmap(2) in aufs, it is actually a direct mmap(2)
18402+ call to the file on the branch fs since the file in aufs is
18403+ purely virtual. And the file path printed in /proc/maps (and
18404+ others) will be the path on the branch fs. In most cases, it
18405+ does no harm. But some utilities like lsof(1) may confuse since
18406+ the utility or user may expect the file path in aufs to be
18407+ printed.
18408+ To address this issue, aufs provides a patch which introduces a
18409+ new member called vm_prfile into struct vm_are_struct. The patch
18410+ is meaningless without enabling this configuration since nobody
18411+ sets the new vm_prfile member.
18412+ If you don't apply the patch, then enabling this configuration
18413+ will cause a compile error.
18414+ This approach is fragile since if someone else make some changes
18415+ around vm_file, then vm_prfile may not work anymore. As a
18416+ workaround such case, aufs provides this configuration. If you
18417+ disable it, then lsof(1) may produce incorrect result but the
18418+ problem will be gone even if the aufs patch is applied (I hope).
18419+
4a4d8108
AM
18420+config AUFS_SP_IATTR
18421+ bool "Respect the attributes (mtime/ctime mainly) of special files"
18422+ help
18423+ When you write something to a special file, some attributes of it
18424+ (mtime/ctime mainly) may be updated. Generally such updates are
18425+ less important (actually some device drivers and NFS ignore
18426+ it). But some applications (such like test program) requires
18427+ such updates. If you need these updates, then enable this
18428+ configuration which introduces some overhead.
18429+ Currently this configuration handles FIFO only.
1facf9fc 18430+
4a4d8108
AM
18431+config AUFS_SHWH
18432+ bool "Show whiteouts"
18433+ help
18434+ If you want to make the whiteouts in aufs visible, then enable
18435+ this option and specify 'shwh' mount option. Although it may
18436+ sounds like philosophy or something, but in technically it
18437+ simply shows the name of whiteout with keeping its behaviour.
1facf9fc 18438+
4a4d8108
AM
18439+config AUFS_BR_RAMFS
18440+ bool "Ramfs (initramfs/rootfs) as an aufs branch"
18441+ help
18442+ If you want to use ramfs as an aufs branch fs, then enable this
18443+ option. Generally tmpfs is recommended.
18444+ Aufs prohibited them to be a branch fs by default, because
18445+ initramfs becomes unusable after switch_root or something
18446+ generally. If you sets initramfs as an aufs branch and boot your
18447+ system by switch_root, you will meet a problem easily since the
18448+ files in initramfs may be inaccessible.
18449+ Unless you are going to use ramfs as an aufs branch fs without
18450+ switch_root or something, leave it N.
1facf9fc 18451+
4a4d8108
AM
18452+config AUFS_BR_FUSE
18453+ bool "Fuse fs as an aufs branch"
18454+ depends on FUSE_FS
18455+ select AUFS_POLL
18456+ help
18457+ If you want to use fuse-based userspace filesystem as an aufs
18458+ branch fs, then enable this option.
18459+ It implements the internal poll(2) operation which is
18460+ implemented by fuse only (curretnly).
1facf9fc 18461+
4a4d8108
AM
18462+config AUFS_POLL
18463+ bool
18464+ help
18465+ Automatic configuration for internal use.
1facf9fc 18466+
4a4d8108
AM
18467+config AUFS_BR_HFSPLUS
18468+ bool "Hfsplus as an aufs branch"
18469+ depends on HFSPLUS_FS
18470+ default y
18471+ help
18472+ If you want to use hfsplus fs as an aufs branch fs, then enable
18473+ this option. This option introduces a small overhead at
18474+ copying-up a file on hfsplus.
1facf9fc 18475+
4a4d8108
AM
18476+config AUFS_BDEV_LOOP
18477+ bool
18478+ depends on BLK_DEV_LOOP
18479+ default y
18480+ help
18481+ Automatic configuration for internal use.
18482+ Convert =[ym] into =y.
1308ab2a 18483+
4a4d8108
AM
18484+config AUFS_DEBUG
18485+ bool "Debug aufs"
18486+ help
18487+ Enable this to compile aufs internal debug code.
18488+ It will have a negative impact to the performance.
18489+
18490+config AUFS_MAGIC_SYSRQ
18491+ bool
18492+ depends on AUFS_DEBUG && MAGIC_SYSRQ
18493+ default y
18494+ help
18495+ Automatic configuration for internal use.
18496+ When aufs supports Magic SysRq, enabled automatically.
18497+endif
7f207e10
AM
18498diff -urN /usr/share/empty/fs/aufs/loop.c linux/fs/aufs/loop.c
18499--- /usr/share/empty/fs/aufs/loop.c 1970-01-01 01:00:00.000000000 +0100
2dfbb274 18500+++ linux/fs/aufs/loop.c 2012-08-26 08:39:00.760508065 +0200
87a755f4 18501@@ -0,0 +1,133 @@
1facf9fc 18502+/*
f6c5ef8b 18503+ * Copyright (C) 2005-2012 Junjiro R. Okajima
1facf9fc 18504+ *
18505+ * This program, aufs is free software; you can redistribute it and/or modify
18506+ * it under the terms of the GNU General Public License as published by
18507+ * the Free Software Foundation; either version 2 of the License, or
18508+ * (at your option) any later version.
dece6358
AM
18509+ *
18510+ * This program is distributed in the hope that it will be useful,
18511+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
18512+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18513+ * GNU General Public License for more details.
18514+ *
18515+ * You should have received a copy of the GNU General Public License
18516+ * along with this program; if not, write to the Free Software
18517+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 18518+ */
18519+
18520+/*
18521+ * support for loopback block device as a branch
18522+ */
18523+
18524+#include <linux/loop.h>
18525+#include "aufs.h"
18526+
18527+/*
18528+ * test if two lower dentries have overlapping branches.
18529+ */
b752ccd1 18530+int au_test_loopback_overlap(struct super_block *sb, struct dentry *h_adding)
1facf9fc 18531+{
b752ccd1 18532+ struct super_block *h_sb;
1facf9fc 18533+ struct loop_device *l;
18534+
b752ccd1
AM
18535+ h_sb = h_adding->d_sb;
18536+ if (MAJOR(h_sb->s_dev) != LOOP_MAJOR)
1facf9fc 18537+ return 0;
18538+
b752ccd1
AM
18539+ l = h_sb->s_bdev->bd_disk->private_data;
18540+ h_adding = l->lo_backing_file->f_dentry;
18541+ /*
18542+ * h_adding can be local NFS.
18543+ * in this case aufs cannot detect the loop.
18544+ */
18545+ if (unlikely(h_adding->d_sb == sb))
1facf9fc 18546+ return 1;
b752ccd1 18547+ return !!au_test_subdir(h_adding, sb->s_root);
1facf9fc 18548+}
18549+
18550+/* true if a kernel thread named 'loop[0-9].*' accesses a file */
18551+int au_test_loopback_kthread(void)
18552+{
b752ccd1
AM
18553+ int ret;
18554+ struct task_struct *tsk = current;
18555+
18556+ ret = 0;
18557+ if (tsk->flags & PF_KTHREAD) {
18558+ const char c = tsk->comm[4];
18559+ ret = ('0' <= c && c <= '9'
18560+ && !strncmp(tsk->comm, "loop", 4));
18561+ }
1facf9fc 18562+
b752ccd1 18563+ return ret;
1facf9fc 18564+}
87a755f4
AM
18565+
18566+/* ---------------------------------------------------------------------- */
18567+
18568+#define au_warn_loopback_step 16
18569+static int au_warn_loopback_nelem = au_warn_loopback_step;
18570+static unsigned long *au_warn_loopback_array;
18571+
18572+void au_warn_loopback(struct super_block *h_sb)
18573+{
18574+ int i, new_nelem;
18575+ unsigned long *a, magic;
18576+ static DEFINE_SPINLOCK(spin);
18577+
18578+ magic = h_sb->s_magic;
18579+ spin_lock(&spin);
18580+ a = au_warn_loopback_array;
18581+ for (i = 0; i < au_warn_loopback_nelem && *a; i++)
18582+ if (a[i] == magic) {
18583+ spin_unlock(&spin);
18584+ return;
18585+ }
18586+
18587+ /* h_sb is new to us, print it */
18588+ if (i < au_warn_loopback_nelem) {
18589+ a[i] = magic;
18590+ goto pr;
18591+ }
18592+
18593+ /* expand the array */
18594+ new_nelem = au_warn_loopback_nelem + au_warn_loopback_step;
18595+ a = au_kzrealloc(au_warn_loopback_array,
18596+ au_warn_loopback_nelem * sizeof(unsigned long),
18597+ new_nelem * sizeof(unsigned long), GFP_ATOMIC);
18598+ if (a) {
18599+ au_warn_loopback_nelem = new_nelem;
18600+ au_warn_loopback_array = a;
18601+ a[i] = magic;
18602+ goto pr;
18603+ }
18604+
18605+ spin_unlock(&spin);
18606+ AuWarn1("realloc failed, ignored\n");
18607+ return;
18608+
18609+pr:
18610+ spin_unlock(&spin);
0c3ec466
AM
18611+ pr_warn("you may want to try another patch for loopback file "
18612+ "on %s(0x%lx) branch\n", au_sbtype(h_sb), magic);
87a755f4
AM
18613+}
18614+
18615+int au_loopback_init(void)
18616+{
18617+ int err;
18618+ struct super_block *sb __maybe_unused;
18619+
18620+ AuDebugOn(sizeof(sb->s_magic) != sizeof(unsigned long));
18621+
18622+ err = 0;
18623+ au_warn_loopback_array = kcalloc(au_warn_loopback_step,
18624+ sizeof(unsigned long), GFP_NOFS);
18625+ if (unlikely(!au_warn_loopback_array))
18626+ err = -ENOMEM;
18627+
18628+ return err;
18629+}
18630+
18631+void au_loopback_fin(void)
18632+{
18633+ kfree(au_warn_loopback_array);
18634+}
7f207e10
AM
18635diff -urN /usr/share/empty/fs/aufs/loop.h linux/fs/aufs/loop.h
18636--- /usr/share/empty/fs/aufs/loop.h 1970-01-01 01:00:00.000000000 +0100
2dfbb274 18637+++ linux/fs/aufs/loop.h 2012-08-26 08:39:00.760508065 +0200
87a755f4 18638@@ -0,0 +1,50 @@
1facf9fc 18639+/*
f6c5ef8b 18640+ * Copyright (C) 2005-2012 Junjiro R. Okajima
1facf9fc 18641+ *
18642+ * This program, aufs is free software; you can redistribute it and/or modify
18643+ * it under the terms of the GNU General Public License as published by
18644+ * the Free Software Foundation; either version 2 of the License, or
18645+ * (at your option) any later version.
dece6358
AM
18646+ *
18647+ * This program is distributed in the hope that it will be useful,
18648+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
18649+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18650+ * GNU General Public License for more details.
18651+ *
18652+ * You should have received a copy of the GNU General Public License
18653+ * along with this program; if not, write to the Free Software
18654+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 18655+ */
18656+
18657+/*
18658+ * support for loopback mount as a branch
18659+ */
18660+
18661+#ifndef __AUFS_LOOP_H__
18662+#define __AUFS_LOOP_H__
18663+
18664+#ifdef __KERNEL__
18665+
dece6358
AM
18666+struct dentry;
18667+struct super_block;
1facf9fc 18668+
18669+#ifdef CONFIG_AUFS_BDEV_LOOP
18670+/* loop.c */
b752ccd1 18671+int au_test_loopback_overlap(struct super_block *sb, struct dentry *h_adding);
1facf9fc 18672+int au_test_loopback_kthread(void);
87a755f4
AM
18673+void au_warn_loopback(struct super_block *h_sb);
18674+
18675+int au_loopback_init(void);
18676+void au_loopback_fin(void);
1facf9fc 18677+#else
4a4d8108 18678+AuStubInt0(au_test_loopback_overlap, struct super_block *sb,
b752ccd1 18679+ struct dentry *h_adding)
4a4d8108 18680+AuStubInt0(au_test_loopback_kthread, void)
87a755f4
AM
18681+AuStubVoid(au_warn_loopback, struct super_block *h_sb)
18682+
18683+AuStubInt0(au_loopback_init, void)
18684+AuStubVoid(au_loopback_fin, void)
1facf9fc 18685+#endif /* BLK_DEV_LOOP */
18686+
18687+#endif /* __KERNEL__ */
18688+#endif /* __AUFS_LOOP_H__ */
7f207e10
AM
18689diff -urN /usr/share/empty/fs/aufs/magic.mk linux/fs/aufs/magic.mk
18690--- /usr/share/empty/fs/aufs/magic.mk 1970-01-01 01:00:00.000000000 +0100
2dfbb274 18691+++ linux/fs/aufs/magic.mk 2012-08-26 08:39:00.760508065 +0200
4a4d8108 18692@@ -0,0 +1,54 @@
1facf9fc 18693+
18694+# defined in ${srctree}/fs/fuse/inode.c
18695+# tristate
18696+ifdef CONFIG_FUSE_FS
18697+ccflags-y += -DFUSE_SUPER_MAGIC=0x65735546
18698+endif
18699+
18700+# defined in ${srctree}/fs/ocfs2/ocfs2_fs.h
18701+# tristate
18702+ifdef CONFIG_OCFS2_FS
18703+ccflags-y += -DOCFS2_SUPER_MAGIC=0x7461636f
18704+endif
18705+
18706+# defined in ${srctree}/fs/ocfs2/dlm/userdlm.h
18707+# tristate
18708+ifdef CONFIG_OCFS2_FS_O2CB
18709+ccflags-y += -DDLMFS_MAGIC=0x76a9f425
18710+endif
18711+
1facf9fc 18712+# defined in ${srctree}/fs/cifs/cifsfs.c
18713+# tristate
18714+ifdef CONFIG_CIFS_FS
18715+ccflags-y += -DCIFS_MAGIC_NUMBER=0xFF534D42
18716+endif
18717+
18718+# defined in ${srctree}/fs/xfs/xfs_sb.h
18719+# tristate
18720+ifdef CONFIG_XFS_FS
18721+ccflags-y += -DXFS_SB_MAGIC=0x58465342
18722+endif
18723+
18724+# defined in ${srctree}/fs/configfs/mount.c
18725+# tristate
18726+ifdef CONFIG_CONFIGFS_FS
18727+ccflags-y += -DCONFIGFS_MAGIC=0x62656570
18728+endif
18729+
18730+# defined in ${srctree}/fs/9p/v9fs.h
18731+# tristate
18732+ifdef CONFIG_9P_FS
18733+ccflags-y += -DV9FS_MAGIC=0x01021997
18734+endif
18735+
18736+# defined in ${srctree}/fs/ubifs/ubifs.h
18737+# tristate
18738+ifdef CONFIG_UBIFS_FS
18739+ccflags-y += -DUBIFS_SUPER_MAGIC=0x24051905
18740+endif
4a4d8108
AM
18741+
18742+# defined in ${srctree}/fs/hfsplus/hfsplus_raw.h
18743+# tristate
18744+ifdef CONFIG_HFSPLUS_FS
18745+ccflags-y += -DHFSPLUS_SUPER_MAGIC=0x482b
18746+endif
7f207e10
AM
18747diff -urN /usr/share/empty/fs/aufs/Makefile linux/fs/aufs/Makefile
18748--- /usr/share/empty/fs/aufs/Makefile 1970-01-01 01:00:00.000000000 +0100
2dfbb274
AM
18749+++ linux/fs/aufs/Makefile 2012-08-26 08:39:00.757174634 +0200
18750@@ -0,0 +1,42 @@
4a4d8108
AM
18751+
18752+include ${src}/magic.mk
18753+ifeq (${CONFIG_AUFS_FS},m)
18754+include ${src}/conf.mk
18755+endif
18756+-include ${src}/priv_def.mk
18757+
18758+# cf. include/linux/kernel.h
18759+# enable pr_debug
18760+ccflags-y += -DDEBUG
f6c5ef8b
AM
18761+# sparse requires the full pathname
18762+ifdef M
18763+ccflags-y += -include ${M}/../../include/linux/aufs_type.h
18764+else
18765+ccflags-y += -include ${srctree}/include/linux/aufs_type.h
18766+endif
4a4d8108
AM
18767+
18768+obj-$(CONFIG_AUFS_FS) += aufs.o
18769+aufs-y := module.o sbinfo.o super.o branch.o xino.o sysaufs.o opts.o \
18770+ wkq.o vfsub.o dcsub.o \
e49829fe 18771+ cpup.o whout.o wbr_policy.o \
4a4d8108
AM
18772+ dinfo.o dentry.o \
18773+ dynop.o \
18774+ finfo.o file.o f_op.o \
18775+ dir.o vdir.o \
18776+ iinfo.o inode.o i_op.o i_op_add.o i_op_del.o i_op_ren.o \
18777+ ioctl.o
18778+
18779+# all are boolean
e49829fe 18780+aufs-$(CONFIG_PROC_FS) += procfs.o plink.o
4a4d8108
AM
18781+aufs-$(CONFIG_SYSFS) += sysfs.o
18782+aufs-$(CONFIG_DEBUG_FS) += dbgaufs.o
18783+aufs-$(CONFIG_AUFS_BDEV_LOOP) += loop.o
18784+aufs-$(CONFIG_AUFS_HNOTIFY) += hnotify.o
18785+aufs-$(CONFIG_AUFS_HFSNOTIFY) += hfsnotify.o
4a4d8108
AM
18786+aufs-$(CONFIG_AUFS_EXPORT) += export.o
18787+aufs-$(CONFIG_AUFS_POLL) += poll.o
18788+aufs-$(CONFIG_AUFS_RDU) += rdu.o
18789+aufs-$(CONFIG_AUFS_SP_IATTR) += f_op_sp.o
18790+aufs-$(CONFIG_AUFS_BR_HFSPLUS) += hfsplus.o
18791+aufs-$(CONFIG_AUFS_DEBUG) += debug.o
18792+aufs-$(CONFIG_AUFS_MAGIC_SYSRQ) += sysrq.o
7f207e10
AM
18793diff -urN /usr/share/empty/fs/aufs/module.c linux/fs/aufs/module.c
18794--- /usr/share/empty/fs/aufs/module.c 1970-01-01 01:00:00.000000000 +0100
2dfbb274 18795+++ linux/fs/aufs/module.c 2012-08-26 08:39:00.760508065 +0200
7eafdf33 18796@@ -0,0 +1,196 @@
1facf9fc 18797+/*
f6c5ef8b 18798+ * Copyright (C) 2005-2012 Junjiro R. Okajima
1facf9fc 18799+ *
18800+ * This program, aufs is free software; you can redistribute it and/or modify
18801+ * it under the terms of the GNU General Public License as published by
18802+ * the Free Software Foundation; either version 2 of the License, or
18803+ * (at your option) any later version.
dece6358
AM
18804+ *
18805+ * This program is distributed in the hope that it will be useful,
18806+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
18807+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18808+ * GNU General Public License for more details.
18809+ *
18810+ * You should have received a copy of the GNU General Public License
18811+ * along with this program; if not, write to the Free Software
18812+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 18813+ */
18814+
18815+/*
18816+ * module global variables and operations
18817+ */
18818+
18819+#include <linux/module.h>
18820+#include <linux/seq_file.h>
18821+#include "aufs.h"
18822+
18823+void *au_kzrealloc(void *p, unsigned int nused, unsigned int new_sz, gfp_t gfp)
18824+{
18825+ if (new_sz <= nused)
18826+ return p;
18827+
18828+ p = krealloc(p, new_sz, gfp);
18829+ if (p)
18830+ memset(p + nused, 0, new_sz - nused);
18831+ return p;
18832+}
18833+
18834+/* ---------------------------------------------------------------------- */
18835+
18836+/*
18837+ * aufs caches
18838+ */
18839+struct kmem_cache *au_cachep[AuCache_Last];
18840+static int __init au_cache_init(void)
18841+{
4a4d8108 18842+ au_cachep[AuCache_DINFO] = AuCacheCtor(au_dinfo, au_di_init_once);
1facf9fc 18843+ if (au_cachep[AuCache_DINFO])
027c5e7a 18844+ /* SLAB_DESTROY_BY_RCU */
4a4d8108
AM
18845+ au_cachep[AuCache_ICNTNR] = AuCacheCtor(au_icntnr,
18846+ au_icntnr_init_once);
1facf9fc 18847+ if (au_cachep[AuCache_ICNTNR])
4a4d8108
AM
18848+ au_cachep[AuCache_FINFO] = AuCacheCtor(au_finfo,
18849+ au_fi_init_once);
1facf9fc 18850+ if (au_cachep[AuCache_FINFO])
18851+ au_cachep[AuCache_VDIR] = AuCache(au_vdir);
18852+ if (au_cachep[AuCache_VDIR])
18853+ au_cachep[AuCache_DEHSTR] = AuCache(au_vdir_dehstr);
18854+ if (au_cachep[AuCache_DEHSTR])
18855+ return 0;
18856+
18857+ return -ENOMEM;
18858+}
18859+
18860+static void au_cache_fin(void)
18861+{
18862+ int i;
4a4d8108 18863+
7eafdf33
AM
18864+ /* excluding AuCache_HNOTIFY */
18865+ BUILD_BUG_ON(AuCache_HNOTIFY + 1 != AuCache_Last);
18866+ for (i = 0; i < AuCache_HNOTIFY; i++)
1facf9fc 18867+ if (au_cachep[i]) {
18868+ kmem_cache_destroy(au_cachep[i]);
18869+ au_cachep[i] = NULL;
18870+ }
18871+}
18872+
18873+/* ---------------------------------------------------------------------- */
18874+
18875+int au_dir_roflags;
18876+
e49829fe 18877+#ifdef CONFIG_AUFS_SBILIST
1e00d052
AM
18878+/*
18879+ * iterate_supers_type() doesn't protect us from
18880+ * remounting (branch management)
18881+ */
e49829fe
JR
18882+struct au_splhead au_sbilist;
18883+#endif
18884+
9dbd164d
AM
18885+struct lock_class_key au_lc_key[AuLcKey_Last];
18886+
1facf9fc 18887+/*
18888+ * functions for module interface.
18889+ */
18890+MODULE_LICENSE("GPL");
18891+/* MODULE_LICENSE("GPL v2"); */
dece6358 18892+MODULE_AUTHOR("Junjiro R. Okajima <aufs-users@lists.sourceforge.net>");
1facf9fc 18893+MODULE_DESCRIPTION(AUFS_NAME
18894+ " -- Advanced multi layered unification filesystem");
18895+MODULE_VERSION(AUFS_VERSION);
18896+
1facf9fc 18897+/* this module parameter has no meaning when SYSFS is disabled */
18898+int sysaufs_brs = 1;
18899+MODULE_PARM_DESC(brs, "use <sysfs>/fs/aufs/si_*/brN");
18900+module_param_named(brs, sysaufs_brs, int, S_IRUGO);
18901+
18902+/* ---------------------------------------------------------------------- */
18903+
18904+static char au_esc_chars[0x20 + 3]; /* 0x01-0x20, backslash, del, and NULL */
18905+
18906+int au_seq_path(struct seq_file *seq, struct path *path)
18907+{
18908+ return seq_path(seq, path, au_esc_chars);
18909+}
18910+
18911+/* ---------------------------------------------------------------------- */
18912+
18913+static int __init aufs_init(void)
18914+{
18915+ int err, i;
18916+ char *p;
18917+
18918+ p = au_esc_chars;
18919+ for (i = 1; i <= ' '; i++)
18920+ *p++ = i;
18921+ *p++ = '\\';
18922+ *p++ = '\x7f';
18923+ *p = 0;
18924+
18925+ au_dir_roflags = au_file_roflags(O_DIRECTORY | O_LARGEFILE);
18926+
e49829fe 18927+ au_sbilist_init();
1facf9fc 18928+ sysaufs_brs_init();
18929+ au_debug_init();
4a4d8108 18930+ au_dy_init();
1facf9fc 18931+ err = sysaufs_init();
18932+ if (unlikely(err))
18933+ goto out;
e49829fe 18934+ err = au_procfs_init();
4f0767ce 18935+ if (unlikely(err))
953406b4 18936+ goto out_sysaufs;
e49829fe
JR
18937+ err = au_wkq_init();
18938+ if (unlikely(err))
18939+ goto out_procfs;
87a755f4 18940+ err = au_loopback_init();
1facf9fc 18941+ if (unlikely(err))
18942+ goto out_wkq;
87a755f4
AM
18943+ err = au_hnotify_init();
18944+ if (unlikely(err))
18945+ goto out_loopback;
1facf9fc 18946+ err = au_sysrq_init();
18947+ if (unlikely(err))
18948+ goto out_hin;
18949+ err = au_cache_init();
18950+ if (unlikely(err))
18951+ goto out_sysrq;
18952+ err = register_filesystem(&aufs_fs_type);
18953+ if (unlikely(err))
18954+ goto out_cache;
4a4d8108
AM
18955+ /* since we define pr_fmt, call printk directly */
18956+ printk(KERN_INFO AUFS_NAME " " AUFS_VERSION "\n");
1facf9fc 18957+ goto out; /* success */
18958+
4f0767ce 18959+out_cache:
1facf9fc 18960+ au_cache_fin();
4f0767ce 18961+out_sysrq:
1facf9fc 18962+ au_sysrq_fin();
4f0767ce 18963+out_hin:
4a4d8108 18964+ au_hnotify_fin();
87a755f4
AM
18965+out_loopback:
18966+ au_loopback_fin();
4f0767ce 18967+out_wkq:
1facf9fc 18968+ au_wkq_fin();
e49829fe
JR
18969+out_procfs:
18970+ au_procfs_fin();
4f0767ce 18971+out_sysaufs:
1facf9fc 18972+ sysaufs_fin();
4a4d8108 18973+ au_dy_fin();
4f0767ce 18974+out:
1facf9fc 18975+ return err;
18976+}
18977+
18978+static void __exit aufs_exit(void)
18979+{
18980+ unregister_filesystem(&aufs_fs_type);
18981+ au_cache_fin();
18982+ au_sysrq_fin();
4a4d8108 18983+ au_hnotify_fin();
87a755f4 18984+ au_loopback_fin();
1facf9fc 18985+ au_wkq_fin();
e49829fe 18986+ au_procfs_fin();
1facf9fc 18987+ sysaufs_fin();
4a4d8108 18988+ au_dy_fin();
1facf9fc 18989+}
18990+
18991+module_init(aufs_init);
18992+module_exit(aufs_exit);
7f207e10
AM
18993diff -urN /usr/share/empty/fs/aufs/module.h linux/fs/aufs/module.h
18994--- /usr/share/empty/fs/aufs/module.h 1970-01-01 01:00:00.000000000 +0100
2dfbb274 18995+++ linux/fs/aufs/module.h 2012-08-26 08:39:00.760508065 +0200
7eafdf33 18996@@ -0,0 +1,105 @@
1facf9fc 18997+/*
f6c5ef8b 18998+ * Copyright (C) 2005-2012 Junjiro R. Okajima
1facf9fc 18999+ *
19000+ * This program, aufs is free software; you can redistribute it and/or modify
19001+ * it under the terms of the GNU General Public License as published by
19002+ * the Free Software Foundation; either version 2 of the License, or
19003+ * (at your option) any later version.
dece6358
AM
19004+ *
19005+ * This program is distributed in the hope that it will be useful,
19006+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
19007+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19008+ * GNU General Public License for more details.
19009+ *
19010+ * You should have received a copy of the GNU General Public License
19011+ * along with this program; if not, write to the Free Software
19012+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 19013+ */
19014+
19015+/*
19016+ * module initialization and module-global
19017+ */
19018+
19019+#ifndef __AUFS_MODULE_H__
19020+#define __AUFS_MODULE_H__
19021+
19022+#ifdef __KERNEL__
19023+
19024+#include <linux/slab.h>
19025+
dece6358
AM
19026+struct path;
19027+struct seq_file;
19028+
1facf9fc 19029+/* module parameters */
1facf9fc 19030+extern int sysaufs_brs;
19031+
19032+/* ---------------------------------------------------------------------- */
19033+
19034+extern int au_dir_roflags;
19035+
9dbd164d
AM
19036+enum {
19037+ AuLcNonDir_FIINFO,
19038+ AuLcNonDir_DIINFO,
19039+ AuLcNonDir_IIINFO,
19040+
19041+ AuLcDir_FIINFO,
19042+ AuLcDir_DIINFO,
19043+ AuLcDir_IIINFO,
19044+
19045+ AuLcSymlink_DIINFO,
19046+ AuLcSymlink_IIINFO,
19047+
19048+ AuLcKey_Last
19049+};
19050+extern struct lock_class_key au_lc_key[AuLcKey_Last];
19051+
1facf9fc 19052+void *au_kzrealloc(void *p, unsigned int nused, unsigned int new_sz, gfp_t gfp);
19053+int au_seq_path(struct seq_file *seq, struct path *path);
19054+
e49829fe
JR
19055+#ifdef CONFIG_PROC_FS
19056+/* procfs.c */
19057+int __init au_procfs_init(void);
19058+void au_procfs_fin(void);
19059+#else
19060+AuStubInt0(au_procfs_init, void);
19061+AuStubVoid(au_procfs_fin, void);
19062+#endif
19063+
4f0767ce
JR
19064+/* ---------------------------------------------------------------------- */
19065+
19066+/* kmem cache */
1facf9fc 19067+enum {
19068+ AuCache_DINFO,
19069+ AuCache_ICNTNR,
19070+ AuCache_FINFO,
19071+ AuCache_VDIR,
19072+ AuCache_DEHSTR,
7eafdf33 19073+ AuCache_HNOTIFY, /* must be last */
1facf9fc 19074+ AuCache_Last
19075+};
19076+
4a4d8108
AM
19077+#define AuCacheFlags (SLAB_RECLAIM_ACCOUNT | SLAB_MEM_SPREAD)
19078+#define AuCache(type) KMEM_CACHE(type, AuCacheFlags)
19079+#define AuCacheCtor(type, ctor) \
19080+ kmem_cache_create(#type, sizeof(struct type), \
19081+ __alignof__(struct type), AuCacheFlags, ctor)
1facf9fc 19082+
19083+extern struct kmem_cache *au_cachep[];
19084+
19085+#define AuCacheFuncs(name, index) \
4a4d8108 19086+static inline struct au_##name *au_cache_alloc_##name(void) \
1facf9fc 19087+{ return kmem_cache_alloc(au_cachep[AuCache_##index], GFP_NOFS); } \
4a4d8108 19088+static inline void au_cache_free_##name(struct au_##name *p) \
1facf9fc 19089+{ kmem_cache_free(au_cachep[AuCache_##index], p); }
19090+
19091+AuCacheFuncs(dinfo, DINFO);
19092+AuCacheFuncs(icntnr, ICNTNR);
19093+AuCacheFuncs(finfo, FINFO);
19094+AuCacheFuncs(vdir, VDIR);
4a4d8108
AM
19095+AuCacheFuncs(vdir_dehstr, DEHSTR);
19096+#ifdef CONFIG_AUFS_HNOTIFY
19097+AuCacheFuncs(hnotify, HNOTIFY);
19098+#endif
1facf9fc 19099+
4a4d8108
AM
19100+#endif /* __KERNEL__ */
19101+#endif /* __AUFS_MODULE_H__ */
7f207e10
AM
19102diff -urN /usr/share/empty/fs/aufs/opts.c linux/fs/aufs/opts.c
19103--- /usr/share/empty/fs/aufs/opts.c 1970-01-01 01:00:00.000000000 +0100
2dfbb274 19104+++ linux/fs/aufs/opts.c 2012-08-26 08:39:00.760508065 +0200
f6c5ef8b 19105@@ -0,0 +1,1677 @@
1facf9fc 19106+/*
f6c5ef8b 19107+ * Copyright (C) 2005-2012 Junjiro R. Okajima
1facf9fc 19108+ *
19109+ * This program, aufs is free software; you can redistribute it and/or modify
19110+ * it under the terms of the GNU General Public License as published by
19111+ * the Free Software Foundation; either version 2 of the License, or
19112+ * (at your option) any later version.
dece6358
AM
19113+ *
19114+ * This program is distributed in the hope that it will be useful,
19115+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
19116+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19117+ * GNU General Public License for more details.
19118+ *
19119+ * You should have received a copy of the GNU General Public License
19120+ * along with this program; if not, write to the Free Software
19121+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 19122+ */
19123+
19124+/*
19125+ * mount options/flags
19126+ */
19127+
dece6358 19128+#include <linux/namei.h>
1facf9fc 19129+#include <linux/types.h> /* a distribution requires */
19130+#include <linux/parser.h>
19131+#include "aufs.h"
19132+
19133+/* ---------------------------------------------------------------------- */
19134+
19135+enum {
19136+ Opt_br,
19137+ Opt_add, Opt_del, Opt_mod, Opt_reorder, Opt_append, Opt_prepend,
19138+ Opt_idel, Opt_imod, Opt_ireorder,
19139+ Opt_dirwh, Opt_rdcache, Opt_rdblk, Opt_rdhash, Opt_rendir,
dece6358 19140+ Opt_rdblk_def, Opt_rdhash_def,
1facf9fc 19141+ Opt_xino, Opt_zxino, Opt_noxino,
19142+ Opt_trunc_xino, Opt_trunc_xino_v, Opt_notrunc_xino,
19143+ Opt_trunc_xino_path, Opt_itrunc_xino,
19144+ Opt_trunc_xib, Opt_notrunc_xib,
dece6358 19145+ Opt_shwh, Opt_noshwh,
1facf9fc 19146+ Opt_plink, Opt_noplink, Opt_list_plink,
19147+ Opt_udba,
4a4d8108 19148+ Opt_dio, Opt_nodio,
1facf9fc 19149+ /* Opt_lock, Opt_unlock, */
19150+ Opt_cmd, Opt_cmd_args,
19151+ Opt_diropq_a, Opt_diropq_w,
19152+ Opt_warn_perm, Opt_nowarn_perm,
19153+ Opt_wbr_copyup, Opt_wbr_create,
19154+ Opt_refrof, Opt_norefrof,
19155+ Opt_verbose, Opt_noverbose,
19156+ Opt_sum, Opt_nosum, Opt_wsum,
19157+ Opt_tail, Opt_ignore, Opt_ignore_silent, Opt_err
19158+};
19159+
19160+static match_table_t options = {
19161+ {Opt_br, "br=%s"},
19162+ {Opt_br, "br:%s"},
19163+
19164+ {Opt_add, "add=%d:%s"},
19165+ {Opt_add, "add:%d:%s"},
19166+ {Opt_add, "ins=%d:%s"},
19167+ {Opt_add, "ins:%d:%s"},
19168+ {Opt_append, "append=%s"},
19169+ {Opt_append, "append:%s"},
19170+ {Opt_prepend, "prepend=%s"},
19171+ {Opt_prepend, "prepend:%s"},
19172+
19173+ {Opt_del, "del=%s"},
19174+ {Opt_del, "del:%s"},
19175+ /* {Opt_idel, "idel:%d"}, */
19176+ {Opt_mod, "mod=%s"},
19177+ {Opt_mod, "mod:%s"},
19178+ /* {Opt_imod, "imod:%d:%s"}, */
19179+
19180+ {Opt_dirwh, "dirwh=%d"},
19181+
19182+ {Opt_xino, "xino=%s"},
19183+ {Opt_noxino, "noxino"},
19184+ {Opt_trunc_xino, "trunc_xino"},
19185+ {Opt_trunc_xino_v, "trunc_xino_v=%d:%d"},
19186+ {Opt_notrunc_xino, "notrunc_xino"},
19187+ {Opt_trunc_xino_path, "trunc_xino=%s"},
19188+ {Opt_itrunc_xino, "itrunc_xino=%d"},
19189+ /* {Opt_zxino, "zxino=%s"}, */
19190+ {Opt_trunc_xib, "trunc_xib"},
19191+ {Opt_notrunc_xib, "notrunc_xib"},
19192+
e49829fe 19193+#ifdef CONFIG_PROC_FS
1facf9fc 19194+ {Opt_plink, "plink"},
e49829fe
JR
19195+#else
19196+ {Opt_ignore_silent, "plink"},
19197+#endif
19198+
1facf9fc 19199+ {Opt_noplink, "noplink"},
e49829fe 19200+
1facf9fc 19201+#ifdef CONFIG_AUFS_DEBUG
19202+ {Opt_list_plink, "list_plink"},
19203+#endif
19204+
19205+ {Opt_udba, "udba=%s"},
19206+
4a4d8108
AM
19207+ {Opt_dio, "dio"},
19208+ {Opt_nodio, "nodio"},
19209+
1facf9fc 19210+ {Opt_diropq_a, "diropq=always"},
19211+ {Opt_diropq_a, "diropq=a"},
19212+ {Opt_diropq_w, "diropq=whiteouted"},
19213+ {Opt_diropq_w, "diropq=w"},
19214+
19215+ {Opt_warn_perm, "warn_perm"},
19216+ {Opt_nowarn_perm, "nowarn_perm"},
19217+
19218+ /* keep them temporary */
19219+ {Opt_ignore_silent, "coo=%s"},
19220+ {Opt_ignore_silent, "nodlgt"},
19221+ {Opt_ignore_silent, "nodirperm1"},
1facf9fc 19222+ {Opt_ignore_silent, "clean_plink"},
19223+
dece6358
AM
19224+#ifdef CONFIG_AUFS_SHWH
19225+ {Opt_shwh, "shwh"},
19226+#endif
19227+ {Opt_noshwh, "noshwh"},
19228+
1facf9fc 19229+ {Opt_rendir, "rendir=%d"},
19230+
19231+ {Opt_refrof, "refrof"},
19232+ {Opt_norefrof, "norefrof"},
19233+
19234+ {Opt_verbose, "verbose"},
19235+ {Opt_verbose, "v"},
19236+ {Opt_noverbose, "noverbose"},
19237+ {Opt_noverbose, "quiet"},
19238+ {Opt_noverbose, "q"},
19239+ {Opt_noverbose, "silent"},
19240+
19241+ {Opt_sum, "sum"},
19242+ {Opt_nosum, "nosum"},
19243+ {Opt_wsum, "wsum"},
19244+
19245+ {Opt_rdcache, "rdcache=%d"},
19246+ {Opt_rdblk, "rdblk=%d"},
dece6358 19247+ {Opt_rdblk_def, "rdblk=def"},
1facf9fc 19248+ {Opt_rdhash, "rdhash=%d"},
dece6358 19249+ {Opt_rdhash_def, "rdhash=def"},
1facf9fc 19250+
19251+ {Opt_wbr_create, "create=%s"},
19252+ {Opt_wbr_create, "create_policy=%s"},
19253+ {Opt_wbr_copyup, "cpup=%s"},
19254+ {Opt_wbr_copyup, "copyup=%s"},
19255+ {Opt_wbr_copyup, "copyup_policy=%s"},
19256+
19257+ /* internal use for the scripts */
19258+ {Opt_ignore_silent, "si=%s"},
19259+
19260+ {Opt_br, "dirs=%s"},
19261+ {Opt_ignore, "debug=%d"},
19262+ {Opt_ignore, "delete=whiteout"},
19263+ {Opt_ignore, "delete=all"},
19264+ {Opt_ignore, "imap=%s"},
19265+
1308ab2a 19266+ /* temporary workaround, due to old mount(8)? */
19267+ {Opt_ignore_silent, "relatime"},
19268+
1facf9fc 19269+ {Opt_err, NULL}
19270+};
19271+
19272+/* ---------------------------------------------------------------------- */
19273+
19274+static const char *au_parser_pattern(int val, struct match_token *token)
19275+{
19276+ while (token->pattern) {
19277+ if (token->token == val)
19278+ return token->pattern;
19279+ token++;
19280+ }
19281+ BUG();
19282+ return "??";
19283+}
19284+
19285+/* ---------------------------------------------------------------------- */
19286+
1e00d052 19287+static match_table_t brperm = {
1facf9fc 19288+ {AuBrPerm_RO, AUFS_BRPERM_RO},
19289+ {AuBrPerm_RR, AUFS_BRPERM_RR},
19290+ {AuBrPerm_RW, AUFS_BRPERM_RW},
1e00d052
AM
19291+ {0, NULL}
19292+};
1facf9fc 19293+
1e00d052
AM
19294+static match_table_t brrattr = {
19295+ {AuBrRAttr_WH, AUFS_BRRATTR_WH},
19296+ {0, NULL}
19297+};
1facf9fc 19298+
1e00d052
AM
19299+static match_table_t brwattr = {
19300+ {AuBrWAttr_NoLinkWH, AUFS_BRWATTR_NLWH},
19301+ {0, NULL}
1facf9fc 19302+};
19303+
1e00d052
AM
19304+#define AuBrStr_LONGEST AUFS_BRPERM_RW "+" AUFS_BRWATTR_NLWH
19305+
19306+static int br_attr_val(char *str, match_table_t table, substring_t args[])
19307+{
19308+ int attr, v;
19309+ char *p;
19310+
19311+ attr = 0;
19312+ do {
19313+ p = strchr(str, '+');
19314+ if (p)
19315+ *p = 0;
19316+ v = match_token(str, table, args);
19317+ if (v)
19318+ attr |= v;
19319+ else {
19320+ if (p)
19321+ *p = '+';
0c3ec466 19322+ pr_warn("ignored branch attribute %s\n", str);
1e00d052
AM
19323+ break;
19324+ }
19325+ if (p)
19326+ str = p + 1;
19327+ } while (p);
19328+
19329+ return attr;
19330+}
19331+
4a4d8108 19332+static int noinline_for_stack br_perm_val(char *perm)
1facf9fc 19333+{
19334+ int val;
1e00d052 19335+ char *p;
1facf9fc 19336+ substring_t args[MAX_OPT_ARGS];
19337+
1e00d052
AM
19338+ p = strchr(perm, '+');
19339+ if (p)
19340+ *p = 0;
19341+ val = match_token(perm, brperm, args);
19342+ if (!val) {
19343+ if (p)
19344+ *p = '+';
0c3ec466 19345+ pr_warn("ignored branch permission %s\n", perm);
1e00d052
AM
19346+ val = AuBrPerm_RO;
19347+ goto out;
19348+ }
19349+ if (!p)
19350+ goto out;
19351+
19352+ switch (val) {
19353+ case AuBrPerm_RO:
19354+ case AuBrPerm_RR:
19355+ val |= br_attr_val(p + 1, brrattr, args);
19356+ break;
19357+ case AuBrPerm_RW:
19358+ val |= br_attr_val(p + 1, brwattr, args);
19359+ break;
19360+ }
19361+
19362+out:
1facf9fc 19363+ return val;
19364+}
19365+
1e00d052
AM
19366+/* Caller should free the return value */
19367+char *au_optstr_br_perm(int brperm)
1facf9fc 19368+{
1e00d052
AM
19369+ char *p, a[sizeof(AuBrStr_LONGEST)];
19370+ int sz;
19371+
19372+#define SetPerm(str) do { \
19373+ sz = sizeof(str); \
19374+ memcpy(a, str, sz); \
19375+ p = a + sz - 1; \
19376+ } while (0)
19377+
19378+#define AppendAttr(flag, str) do { \
19379+ if (brperm & flag) { \
19380+ sz = sizeof(str); \
19381+ *p++ = '+'; \
19382+ memcpy(p, str, sz); \
19383+ p += sz - 1; \
19384+ } \
19385+ } while (0)
19386+
19387+ switch (brperm & AuBrPerm_Mask) {
19388+ case AuBrPerm_RO:
19389+ SetPerm(AUFS_BRPERM_RO);
19390+ break;
19391+ case AuBrPerm_RR:
19392+ SetPerm(AUFS_BRPERM_RR);
19393+ break;
19394+ case AuBrPerm_RW:
19395+ SetPerm(AUFS_BRPERM_RW);
19396+ break;
19397+ default:
19398+ AuDebugOn(1);
19399+ }
19400+
19401+ AppendAttr(AuBrRAttr_WH, AUFS_BRRATTR_WH);
19402+ AppendAttr(AuBrWAttr_NoLinkWH, AUFS_BRWATTR_NLWH);
19403+
19404+ AuDebugOn(strlen(a) >= sizeof(a));
19405+ return kstrdup(a, GFP_NOFS);
19406+#undef SetPerm
19407+#undef AppendAttr
1facf9fc 19408+}
19409+
19410+/* ---------------------------------------------------------------------- */
19411+
19412+static match_table_t udbalevel = {
19413+ {AuOpt_UDBA_REVAL, "reval"},
19414+ {AuOpt_UDBA_NONE, "none"},
4a4d8108
AM
19415+#ifdef CONFIG_AUFS_HNOTIFY
19416+ {AuOpt_UDBA_HNOTIFY, "notify"}, /* abstraction */
19417+#ifdef CONFIG_AUFS_HFSNOTIFY
19418+ {AuOpt_UDBA_HNOTIFY, "fsnotify"},
4a4d8108 19419+#endif
1facf9fc 19420+#endif
19421+ {-1, NULL}
19422+};
19423+
4a4d8108 19424+static int noinline_for_stack udba_val(char *str)
1facf9fc 19425+{
19426+ substring_t args[MAX_OPT_ARGS];
19427+
7f207e10 19428+ return match_token(str, udbalevel, args);
1facf9fc 19429+}
19430+
19431+const char *au_optstr_udba(int udba)
19432+{
19433+ return au_parser_pattern(udba, (void *)udbalevel);
19434+}
19435+
19436+/* ---------------------------------------------------------------------- */
19437+
19438+static match_table_t au_wbr_create_policy = {
19439+ {AuWbrCreate_TDP, "tdp"},
19440+ {AuWbrCreate_TDP, "top-down-parent"},
19441+ {AuWbrCreate_RR, "rr"},
19442+ {AuWbrCreate_RR, "round-robin"},
19443+ {AuWbrCreate_MFS, "mfs"},
19444+ {AuWbrCreate_MFS, "most-free-space"},
19445+ {AuWbrCreate_MFSV, "mfs:%d"},
19446+ {AuWbrCreate_MFSV, "most-free-space:%d"},
19447+
19448+ {AuWbrCreate_MFSRR, "mfsrr:%d"},
19449+ {AuWbrCreate_MFSRRV, "mfsrr:%d:%d"},
19450+ {AuWbrCreate_PMFS, "pmfs"},
19451+ {AuWbrCreate_PMFSV, "pmfs:%d"},
19452+
19453+ {-1, NULL}
19454+};
19455+
dece6358
AM
19456+/*
19457+ * cf. linux/lib/parser.c and cmdline.c
19458+ * gave up calling memparse() since it uses simple_strtoull() instead of
9dbd164d 19459+ * kstrto...().
dece6358 19460+ */
4a4d8108
AM
19461+static int noinline_for_stack
19462+au_match_ull(substring_t *s, unsigned long long *result)
1facf9fc 19463+{
19464+ int err;
19465+ unsigned int len;
19466+ char a[32];
19467+
19468+ err = -ERANGE;
19469+ len = s->to - s->from;
19470+ if (len + 1 <= sizeof(a)) {
19471+ memcpy(a, s->from, len);
19472+ a[len] = '\0';
9dbd164d 19473+ err = kstrtoull(a, 0, result);
1facf9fc 19474+ }
19475+ return err;
19476+}
19477+
19478+static int au_wbr_mfs_wmark(substring_t *arg, char *str,
19479+ struct au_opt_wbr_create *create)
19480+{
19481+ int err;
19482+ unsigned long long ull;
19483+
19484+ err = 0;
19485+ if (!au_match_ull(arg, &ull))
19486+ create->mfsrr_watermark = ull;
19487+ else {
4a4d8108 19488+ pr_err("bad integer in %s\n", str);
1facf9fc 19489+ err = -EINVAL;
19490+ }
19491+
19492+ return err;
19493+}
19494+
19495+static int au_wbr_mfs_sec(substring_t *arg, char *str,
19496+ struct au_opt_wbr_create *create)
19497+{
19498+ int n, err;
19499+
19500+ err = 0;
027c5e7a 19501+ if (!match_int(arg, &n) && 0 <= n && n <= AUFS_MFS_MAX_SEC)
1facf9fc 19502+ create->mfs_second = n;
19503+ else {
4a4d8108 19504+ pr_err("bad integer in %s\n", str);
1facf9fc 19505+ err = -EINVAL;
19506+ }
19507+
19508+ return err;
19509+}
19510+
4a4d8108
AM
19511+static int noinline_for_stack
19512+au_wbr_create_val(char *str, struct au_opt_wbr_create *create)
1facf9fc 19513+{
19514+ int err, e;
19515+ substring_t args[MAX_OPT_ARGS];
19516+
19517+ err = match_token(str, au_wbr_create_policy, args);
19518+ create->wbr_create = err;
19519+ switch (err) {
19520+ case AuWbrCreate_MFSRRV:
19521+ e = au_wbr_mfs_wmark(&args[0], str, create);
19522+ if (!e)
19523+ e = au_wbr_mfs_sec(&args[1], str, create);
19524+ if (unlikely(e))
19525+ err = e;
19526+ break;
19527+ case AuWbrCreate_MFSRR:
19528+ e = au_wbr_mfs_wmark(&args[0], str, create);
19529+ if (unlikely(e)) {
19530+ err = e;
19531+ break;
19532+ }
19533+ /*FALLTHROUGH*/
19534+ case AuWbrCreate_MFS:
19535+ case AuWbrCreate_PMFS:
027c5e7a 19536+ create->mfs_second = AUFS_MFS_DEF_SEC;
1facf9fc 19537+ break;
19538+ case AuWbrCreate_MFSV:
19539+ case AuWbrCreate_PMFSV:
19540+ e = au_wbr_mfs_sec(&args[0], str, create);
19541+ if (unlikely(e))
19542+ err = e;
19543+ break;
19544+ }
19545+
19546+ return err;
19547+}
19548+
19549+const char *au_optstr_wbr_create(int wbr_create)
19550+{
19551+ return au_parser_pattern(wbr_create, (void *)au_wbr_create_policy);
19552+}
19553+
19554+static match_table_t au_wbr_copyup_policy = {
19555+ {AuWbrCopyup_TDP, "tdp"},
19556+ {AuWbrCopyup_TDP, "top-down-parent"},
19557+ {AuWbrCopyup_BUP, "bup"},
19558+ {AuWbrCopyup_BUP, "bottom-up-parent"},
19559+ {AuWbrCopyup_BU, "bu"},
19560+ {AuWbrCopyup_BU, "bottom-up"},
19561+ {-1, NULL}
19562+};
19563+
4a4d8108 19564+static int noinline_for_stack au_wbr_copyup_val(char *str)
1facf9fc 19565+{
19566+ substring_t args[MAX_OPT_ARGS];
19567+
19568+ return match_token(str, au_wbr_copyup_policy, args);
19569+}
19570+
19571+const char *au_optstr_wbr_copyup(int wbr_copyup)
19572+{
19573+ return au_parser_pattern(wbr_copyup, (void *)au_wbr_copyup_policy);
19574+}
19575+
19576+/* ---------------------------------------------------------------------- */
19577+
19578+static const int lkup_dirflags = LOOKUP_FOLLOW | LOOKUP_DIRECTORY;
19579+
19580+static void dump_opts(struct au_opts *opts)
19581+{
19582+#ifdef CONFIG_AUFS_DEBUG
19583+ /* reduce stack space */
19584+ union {
19585+ struct au_opt_add *add;
19586+ struct au_opt_del *del;
19587+ struct au_opt_mod *mod;
19588+ struct au_opt_xino *xino;
19589+ struct au_opt_xino_itrunc *xino_itrunc;
19590+ struct au_opt_wbr_create *create;
19591+ } u;
19592+ struct au_opt *opt;
19593+
19594+ opt = opts->opt;
19595+ while (opt->type != Opt_tail) {
19596+ switch (opt->type) {
19597+ case Opt_add:
19598+ u.add = &opt->add;
19599+ AuDbg("add {b%d, %s, 0x%x, %p}\n",
19600+ u.add->bindex, u.add->pathname, u.add->perm,
19601+ u.add->path.dentry);
19602+ break;
19603+ case Opt_del:
19604+ case Opt_idel:
19605+ u.del = &opt->del;
19606+ AuDbg("del {%s, %p}\n",
19607+ u.del->pathname, u.del->h_path.dentry);
19608+ break;
19609+ case Opt_mod:
19610+ case Opt_imod:
19611+ u.mod = &opt->mod;
19612+ AuDbg("mod {%s, 0x%x, %p}\n",
19613+ u.mod->path, u.mod->perm, u.mod->h_root);
19614+ break;
19615+ case Opt_append:
19616+ u.add = &opt->add;
19617+ AuDbg("append {b%d, %s, 0x%x, %p}\n",
19618+ u.add->bindex, u.add->pathname, u.add->perm,
19619+ u.add->path.dentry);
19620+ break;
19621+ case Opt_prepend:
19622+ u.add = &opt->add;
19623+ AuDbg("prepend {b%d, %s, 0x%x, %p}\n",
19624+ u.add->bindex, u.add->pathname, u.add->perm,
19625+ u.add->path.dentry);
19626+ break;
19627+ case Opt_dirwh:
19628+ AuDbg("dirwh %d\n", opt->dirwh);
19629+ break;
19630+ case Opt_rdcache:
19631+ AuDbg("rdcache %d\n", opt->rdcache);
19632+ break;
19633+ case Opt_rdblk:
19634+ AuDbg("rdblk %u\n", opt->rdblk);
19635+ break;
dece6358
AM
19636+ case Opt_rdblk_def:
19637+ AuDbg("rdblk_def\n");
19638+ break;
1facf9fc 19639+ case Opt_rdhash:
19640+ AuDbg("rdhash %u\n", opt->rdhash);
19641+ break;
dece6358
AM
19642+ case Opt_rdhash_def:
19643+ AuDbg("rdhash_def\n");
19644+ break;
1facf9fc 19645+ case Opt_xino:
19646+ u.xino = &opt->xino;
19647+ AuDbg("xino {%s %.*s}\n",
19648+ u.xino->path,
19649+ AuDLNPair(u.xino->file->f_dentry));
19650+ break;
19651+ case Opt_trunc_xino:
19652+ AuLabel(trunc_xino);
19653+ break;
19654+ case Opt_notrunc_xino:
19655+ AuLabel(notrunc_xino);
19656+ break;
19657+ case Opt_trunc_xino_path:
19658+ case Opt_itrunc_xino:
19659+ u.xino_itrunc = &opt->xino_itrunc;
19660+ AuDbg("trunc_xino %d\n", u.xino_itrunc->bindex);
19661+ break;
19662+
19663+ case Opt_noxino:
19664+ AuLabel(noxino);
19665+ break;
19666+ case Opt_trunc_xib:
19667+ AuLabel(trunc_xib);
19668+ break;
19669+ case Opt_notrunc_xib:
19670+ AuLabel(notrunc_xib);
19671+ break;
dece6358
AM
19672+ case Opt_shwh:
19673+ AuLabel(shwh);
19674+ break;
19675+ case Opt_noshwh:
19676+ AuLabel(noshwh);
19677+ break;
1facf9fc 19678+ case Opt_plink:
19679+ AuLabel(plink);
19680+ break;
19681+ case Opt_noplink:
19682+ AuLabel(noplink);
19683+ break;
19684+ case Opt_list_plink:
19685+ AuLabel(list_plink);
19686+ break;
19687+ case Opt_udba:
19688+ AuDbg("udba %d, %s\n",
19689+ opt->udba, au_optstr_udba(opt->udba));
19690+ break;
4a4d8108
AM
19691+ case Opt_dio:
19692+ AuLabel(dio);
19693+ break;
19694+ case Opt_nodio:
19695+ AuLabel(nodio);
19696+ break;
1facf9fc 19697+ case Opt_diropq_a:
19698+ AuLabel(diropq_a);
19699+ break;
19700+ case Opt_diropq_w:
19701+ AuLabel(diropq_w);
19702+ break;
19703+ case Opt_warn_perm:
19704+ AuLabel(warn_perm);
19705+ break;
19706+ case Opt_nowarn_perm:
19707+ AuLabel(nowarn_perm);
19708+ break;
19709+ case Opt_refrof:
19710+ AuLabel(refrof);
19711+ break;
19712+ case Opt_norefrof:
19713+ AuLabel(norefrof);
19714+ break;
19715+ case Opt_verbose:
19716+ AuLabel(verbose);
19717+ break;
19718+ case Opt_noverbose:
19719+ AuLabel(noverbose);
19720+ break;
19721+ case Opt_sum:
19722+ AuLabel(sum);
19723+ break;
19724+ case Opt_nosum:
19725+ AuLabel(nosum);
19726+ break;
19727+ case Opt_wsum:
19728+ AuLabel(wsum);
19729+ break;
19730+ case Opt_wbr_create:
19731+ u.create = &opt->wbr_create;
19732+ AuDbg("create %d, %s\n", u.create->wbr_create,
19733+ au_optstr_wbr_create(u.create->wbr_create));
19734+ switch (u.create->wbr_create) {
19735+ case AuWbrCreate_MFSV:
19736+ case AuWbrCreate_PMFSV:
19737+ AuDbg("%d sec\n", u.create->mfs_second);
19738+ break;
19739+ case AuWbrCreate_MFSRR:
19740+ AuDbg("%llu watermark\n",
19741+ u.create->mfsrr_watermark);
19742+ break;
19743+ case AuWbrCreate_MFSRRV:
19744+ AuDbg("%llu watermark, %d sec\n",
19745+ u.create->mfsrr_watermark,
19746+ u.create->mfs_second);
19747+ break;
19748+ }
19749+ break;
19750+ case Opt_wbr_copyup:
19751+ AuDbg("copyup %d, %s\n", opt->wbr_copyup,
19752+ au_optstr_wbr_copyup(opt->wbr_copyup));
19753+ break;
19754+ default:
19755+ BUG();
19756+ }
19757+ opt++;
19758+ }
19759+#endif
19760+}
19761+
19762+void au_opts_free(struct au_opts *opts)
19763+{
19764+ struct au_opt *opt;
19765+
19766+ opt = opts->opt;
19767+ while (opt->type != Opt_tail) {
19768+ switch (opt->type) {
19769+ case Opt_add:
19770+ case Opt_append:
19771+ case Opt_prepend:
19772+ path_put(&opt->add.path);
19773+ break;
19774+ case Opt_del:
19775+ case Opt_idel:
19776+ path_put(&opt->del.h_path);
19777+ break;
19778+ case Opt_mod:
19779+ case Opt_imod:
19780+ dput(opt->mod.h_root);
19781+ break;
19782+ case Opt_xino:
19783+ fput(opt->xino.file);
19784+ break;
19785+ }
19786+ opt++;
19787+ }
19788+}
19789+
19790+static int opt_add(struct au_opt *opt, char *opt_str, unsigned long sb_flags,
19791+ aufs_bindex_t bindex)
19792+{
19793+ int err;
19794+ struct au_opt_add *add = &opt->add;
19795+ char *p;
19796+
19797+ add->bindex = bindex;
1e00d052 19798+ add->perm = AuBrPerm_RO;
1facf9fc 19799+ add->pathname = opt_str;
19800+ p = strchr(opt_str, '=');
19801+ if (p) {
19802+ *p++ = 0;
19803+ if (*p)
19804+ add->perm = br_perm_val(p);
19805+ }
19806+
19807+ err = vfsub_kern_path(add->pathname, lkup_dirflags, &add->path);
19808+ if (!err) {
19809+ if (!p) {
19810+ add->perm = AuBrPerm_RO;
19811+ if (au_test_fs_rr(add->path.dentry->d_sb))
19812+ add->perm = AuBrPerm_RR;
19813+ else if (!bindex && !(sb_flags & MS_RDONLY))
19814+ add->perm = AuBrPerm_RW;
19815+ }
19816+ opt->type = Opt_add;
19817+ goto out;
19818+ }
4a4d8108 19819+ pr_err("lookup failed %s (%d)\n", add->pathname, err);
1facf9fc 19820+ err = -EINVAL;
19821+
4f0767ce 19822+out:
1facf9fc 19823+ return err;
19824+}
19825+
19826+static int au_opts_parse_del(struct au_opt_del *del, substring_t args[])
19827+{
19828+ int err;
19829+
19830+ del->pathname = args[0].from;
19831+ AuDbg("del path %s\n", del->pathname);
19832+
19833+ err = vfsub_kern_path(del->pathname, lkup_dirflags, &del->h_path);
19834+ if (unlikely(err))
4a4d8108 19835+ pr_err("lookup failed %s (%d)\n", del->pathname, err);
1facf9fc 19836+
19837+ return err;
19838+}
19839+
19840+#if 0 /* reserved for future use */
19841+static int au_opts_parse_idel(struct super_block *sb, aufs_bindex_t bindex,
19842+ struct au_opt_del *del, substring_t args[])
19843+{
19844+ int err;
19845+ struct dentry *root;
19846+
19847+ err = -EINVAL;
19848+ root = sb->s_root;
19849+ aufs_read_lock(root, AuLock_FLUSH);
19850+ if (bindex < 0 || au_sbend(sb) < bindex) {
4a4d8108 19851+ pr_err("out of bounds, %d\n", bindex);
1facf9fc 19852+ goto out;
19853+ }
19854+
19855+ err = 0;
19856+ del->h_path.dentry = dget(au_h_dptr(root, bindex));
19857+ del->h_path.mnt = mntget(au_sbr_mnt(sb, bindex));
19858+
4f0767ce 19859+out:
1facf9fc 19860+ aufs_read_unlock(root, !AuLock_IR);
19861+ return err;
19862+}
19863+#endif
19864+
4a4d8108
AM
19865+static int noinline_for_stack
19866+au_opts_parse_mod(struct au_opt_mod *mod, substring_t args[])
1facf9fc 19867+{
19868+ int err;
19869+ struct path path;
19870+ char *p;
19871+
19872+ err = -EINVAL;
19873+ mod->path = args[0].from;
19874+ p = strchr(mod->path, '=');
19875+ if (unlikely(!p)) {
4a4d8108 19876+ pr_err("no permssion %s\n", args[0].from);
1facf9fc 19877+ goto out;
19878+ }
19879+
19880+ *p++ = 0;
19881+ err = vfsub_kern_path(mod->path, lkup_dirflags, &path);
19882+ if (unlikely(err)) {
4a4d8108 19883+ pr_err("lookup failed %s (%d)\n", mod->path, err);
1facf9fc 19884+ goto out;
19885+ }
19886+
19887+ mod->perm = br_perm_val(p);
19888+ AuDbg("mod path %s, perm 0x%x, %s\n", mod->path, mod->perm, p);
19889+ mod->h_root = dget(path.dentry);
19890+ path_put(&path);
19891+
4f0767ce 19892+out:
1facf9fc 19893+ return err;
19894+}
19895+
19896+#if 0 /* reserved for future use */
19897+static int au_opts_parse_imod(struct super_block *sb, aufs_bindex_t bindex,
19898+ struct au_opt_mod *mod, substring_t args[])
19899+{
19900+ int err;
19901+ struct dentry *root;
19902+
19903+ err = -EINVAL;
19904+ root = sb->s_root;
19905+ aufs_read_lock(root, AuLock_FLUSH);
19906+ if (bindex < 0 || au_sbend(sb) < bindex) {
4a4d8108 19907+ pr_err("out of bounds, %d\n", bindex);
1facf9fc 19908+ goto out;
19909+ }
19910+
19911+ err = 0;
19912+ mod->perm = br_perm_val(args[1].from);
19913+ AuDbg("mod path %s, perm 0x%x, %s\n",
19914+ mod->path, mod->perm, args[1].from);
19915+ mod->h_root = dget(au_h_dptr(root, bindex));
19916+
4f0767ce 19917+out:
1facf9fc 19918+ aufs_read_unlock(root, !AuLock_IR);
19919+ return err;
19920+}
19921+#endif
19922+
19923+static int au_opts_parse_xino(struct super_block *sb, struct au_opt_xino *xino,
19924+ substring_t args[])
19925+{
19926+ int err;
19927+ struct file *file;
19928+
19929+ file = au_xino_create(sb, args[0].from, /*silent*/0);
19930+ err = PTR_ERR(file);
19931+ if (IS_ERR(file))
19932+ goto out;
19933+
19934+ err = -EINVAL;
19935+ if (unlikely(file->f_dentry->d_sb == sb)) {
19936+ fput(file);
4a4d8108 19937+ pr_err("%s must be outside\n", args[0].from);
1facf9fc 19938+ goto out;
19939+ }
19940+
19941+ err = 0;
19942+ xino->file = file;
19943+ xino->path = args[0].from;
19944+
4f0767ce 19945+out:
1facf9fc 19946+ return err;
19947+}
19948+
4a4d8108
AM
19949+static int noinline_for_stack
19950+au_opts_parse_xino_itrunc_path(struct super_block *sb,
19951+ struct au_opt_xino_itrunc *xino_itrunc,
19952+ substring_t args[])
1facf9fc 19953+{
19954+ int err;
19955+ aufs_bindex_t bend, bindex;
19956+ struct path path;
19957+ struct dentry *root;
19958+
19959+ err = vfsub_kern_path(args[0].from, lkup_dirflags, &path);
19960+ if (unlikely(err)) {
4a4d8108 19961+ pr_err("lookup failed %s (%d)\n", args[0].from, err);
1facf9fc 19962+ goto out;
19963+ }
19964+
19965+ xino_itrunc->bindex = -1;
19966+ root = sb->s_root;
19967+ aufs_read_lock(root, AuLock_FLUSH);
19968+ bend = au_sbend(sb);
19969+ for (bindex = 0; bindex <= bend; bindex++) {
19970+ if (au_h_dptr(root, bindex) == path.dentry) {
19971+ xino_itrunc->bindex = bindex;
19972+ break;
19973+ }
19974+ }
19975+ aufs_read_unlock(root, !AuLock_IR);
19976+ path_put(&path);
19977+
19978+ if (unlikely(xino_itrunc->bindex < 0)) {
4a4d8108 19979+ pr_err("no such branch %s\n", args[0].from);
1facf9fc 19980+ err = -EINVAL;
19981+ }
19982+
4f0767ce 19983+out:
1facf9fc 19984+ return err;
19985+}
19986+
19987+/* called without aufs lock */
19988+int au_opts_parse(struct super_block *sb, char *str, struct au_opts *opts)
19989+{
19990+ int err, n, token;
19991+ aufs_bindex_t bindex;
19992+ unsigned char skipped;
19993+ struct dentry *root;
19994+ struct au_opt *opt, *opt_tail;
19995+ char *opt_str;
19996+ /* reduce the stack space */
19997+ union {
19998+ struct au_opt_xino_itrunc *xino_itrunc;
19999+ struct au_opt_wbr_create *create;
20000+ } u;
20001+ struct {
20002+ substring_t args[MAX_OPT_ARGS];
20003+ } *a;
20004+
20005+ err = -ENOMEM;
20006+ a = kmalloc(sizeof(*a), GFP_NOFS);
20007+ if (unlikely(!a))
20008+ goto out;
20009+
20010+ root = sb->s_root;
20011+ err = 0;
20012+ bindex = 0;
20013+ opt = opts->opt;
20014+ opt_tail = opt + opts->max_opt - 1;
20015+ opt->type = Opt_tail;
20016+ while (!err && (opt_str = strsep(&str, ",")) && *opt_str) {
20017+ err = -EINVAL;
20018+ skipped = 0;
20019+ token = match_token(opt_str, options, a->args);
20020+ switch (token) {
20021+ case Opt_br:
20022+ err = 0;
20023+ while (!err && (opt_str = strsep(&a->args[0].from, ":"))
20024+ && *opt_str) {
20025+ err = opt_add(opt, opt_str, opts->sb_flags,
20026+ bindex++);
20027+ if (unlikely(!err && ++opt > opt_tail)) {
20028+ err = -E2BIG;
20029+ break;
20030+ }
20031+ opt->type = Opt_tail;
20032+ skipped = 1;
20033+ }
20034+ break;
20035+ case Opt_add:
20036+ if (unlikely(match_int(&a->args[0], &n))) {
4a4d8108 20037+ pr_err("bad integer in %s\n", opt_str);
1facf9fc 20038+ break;
20039+ }
20040+ bindex = n;
20041+ err = opt_add(opt, a->args[1].from, opts->sb_flags,
20042+ bindex);
20043+ if (!err)
20044+ opt->type = token;
20045+ break;
20046+ case Opt_append:
20047+ err = opt_add(opt, a->args[0].from, opts->sb_flags,
20048+ /*dummy bindex*/1);
20049+ if (!err)
20050+ opt->type = token;
20051+ break;
20052+ case Opt_prepend:
20053+ err = opt_add(opt, a->args[0].from, opts->sb_flags,
20054+ /*bindex*/0);
20055+ if (!err)
20056+ opt->type = token;
20057+ break;
20058+ case Opt_del:
20059+ err = au_opts_parse_del(&opt->del, a->args);
20060+ if (!err)
20061+ opt->type = token;
20062+ break;
20063+#if 0 /* reserved for future use */
20064+ case Opt_idel:
20065+ del->pathname = "(indexed)";
20066+ if (unlikely(match_int(&args[0], &n))) {
4a4d8108 20067+ pr_err("bad integer in %s\n", opt_str);
1facf9fc 20068+ break;
20069+ }
20070+ err = au_opts_parse_idel(sb, n, &opt->del, a->args);
20071+ if (!err)
20072+ opt->type = token;
20073+ break;
20074+#endif
20075+ case Opt_mod:
20076+ err = au_opts_parse_mod(&opt->mod, a->args);
20077+ if (!err)
20078+ opt->type = token;
20079+ break;
20080+#ifdef IMOD /* reserved for future use */
20081+ case Opt_imod:
20082+ u.mod->path = "(indexed)";
20083+ if (unlikely(match_int(&a->args[0], &n))) {
4a4d8108 20084+ pr_err("bad integer in %s\n", opt_str);
1facf9fc 20085+ break;
20086+ }
20087+ err = au_opts_parse_imod(sb, n, &opt->mod, a->args);
20088+ if (!err)
20089+ opt->type = token;
20090+ break;
20091+#endif
20092+ case Opt_xino:
20093+ err = au_opts_parse_xino(sb, &opt->xino, a->args);
20094+ if (!err)
20095+ opt->type = token;
20096+ break;
20097+
20098+ case Opt_trunc_xino_path:
20099+ err = au_opts_parse_xino_itrunc_path
20100+ (sb, &opt->xino_itrunc, a->args);
20101+ if (!err)
20102+ opt->type = token;
20103+ break;
20104+
20105+ case Opt_itrunc_xino:
20106+ u.xino_itrunc = &opt->xino_itrunc;
20107+ if (unlikely(match_int(&a->args[0], &n))) {
4a4d8108 20108+ pr_err("bad integer in %s\n", opt_str);
1facf9fc 20109+ break;
20110+ }
20111+ u.xino_itrunc->bindex = n;
20112+ aufs_read_lock(root, AuLock_FLUSH);
20113+ if (n < 0 || au_sbend(sb) < n) {
4a4d8108 20114+ pr_err("out of bounds, %d\n", n);
1facf9fc 20115+ aufs_read_unlock(root, !AuLock_IR);
20116+ break;
20117+ }
20118+ aufs_read_unlock(root, !AuLock_IR);
20119+ err = 0;
20120+ opt->type = token;
20121+ break;
20122+
20123+ case Opt_dirwh:
20124+ if (unlikely(match_int(&a->args[0], &opt->dirwh)))
20125+ break;
20126+ err = 0;
20127+ opt->type = token;
20128+ break;
20129+
20130+ case Opt_rdcache:
027c5e7a
AM
20131+ if (unlikely(match_int(&a->args[0], &n))) {
20132+ pr_err("bad integer in %s\n", opt_str);
1facf9fc 20133+ break;
027c5e7a
AM
20134+ }
20135+ if (unlikely(n > AUFS_RDCACHE_MAX)) {
20136+ pr_err("rdcache must be smaller than %d\n",
20137+ AUFS_RDCACHE_MAX);
20138+ break;
20139+ }
20140+ opt->rdcache = n;
1facf9fc 20141+ err = 0;
20142+ opt->type = token;
20143+ break;
20144+ case Opt_rdblk:
20145+ if (unlikely(match_int(&a->args[0], &n)
1308ab2a 20146+ || n < 0
1facf9fc 20147+ || n > KMALLOC_MAX_SIZE)) {
4a4d8108 20148+ pr_err("bad integer in %s\n", opt_str);
1facf9fc 20149+ break;
20150+ }
1308ab2a 20151+ if (unlikely(n && n < NAME_MAX)) {
4a4d8108
AM
20152+ pr_err("rdblk must be larger than %d\n",
20153+ NAME_MAX);
1facf9fc 20154+ break;
20155+ }
20156+ opt->rdblk = n;
20157+ err = 0;
20158+ opt->type = token;
20159+ break;
20160+ case Opt_rdhash:
20161+ if (unlikely(match_int(&a->args[0], &n)
1308ab2a 20162+ || n < 0
1facf9fc 20163+ || n * sizeof(struct hlist_head)
20164+ > KMALLOC_MAX_SIZE)) {
4a4d8108 20165+ pr_err("bad integer in %s\n", opt_str);
1facf9fc 20166+ break;
20167+ }
20168+ opt->rdhash = n;
20169+ err = 0;
20170+ opt->type = token;
20171+ break;
20172+
20173+ case Opt_trunc_xino:
20174+ case Opt_notrunc_xino:
20175+ case Opt_noxino:
20176+ case Opt_trunc_xib:
20177+ case Opt_notrunc_xib:
dece6358
AM
20178+ case Opt_shwh:
20179+ case Opt_noshwh:
1facf9fc 20180+ case Opt_plink:
20181+ case Opt_noplink:
20182+ case Opt_list_plink:
4a4d8108
AM
20183+ case Opt_dio:
20184+ case Opt_nodio:
1facf9fc 20185+ case Opt_diropq_a:
20186+ case Opt_diropq_w:
20187+ case Opt_warn_perm:
20188+ case Opt_nowarn_perm:
20189+ case Opt_refrof:
20190+ case Opt_norefrof:
20191+ case Opt_verbose:
20192+ case Opt_noverbose:
20193+ case Opt_sum:
20194+ case Opt_nosum:
20195+ case Opt_wsum:
dece6358
AM
20196+ case Opt_rdblk_def:
20197+ case Opt_rdhash_def:
1facf9fc 20198+ err = 0;
20199+ opt->type = token;
20200+ break;
20201+
20202+ case Opt_udba:
20203+ opt->udba = udba_val(a->args[0].from);
20204+ if (opt->udba >= 0) {
20205+ err = 0;
20206+ opt->type = token;
20207+ } else
4a4d8108 20208+ pr_err("wrong value, %s\n", opt_str);
1facf9fc 20209+ break;
20210+
20211+ case Opt_wbr_create:
20212+ u.create = &opt->wbr_create;
20213+ u.create->wbr_create
20214+ = au_wbr_create_val(a->args[0].from, u.create);
20215+ if (u.create->wbr_create >= 0) {
20216+ err = 0;
20217+ opt->type = token;
20218+ } else
4a4d8108 20219+ pr_err("wrong value, %s\n", opt_str);
1facf9fc 20220+ break;
20221+ case Opt_wbr_copyup:
20222+ opt->wbr_copyup = au_wbr_copyup_val(a->args[0].from);
20223+ if (opt->wbr_copyup >= 0) {
20224+ err = 0;
20225+ opt->type = token;
20226+ } else
4a4d8108 20227+ pr_err("wrong value, %s\n", opt_str);
1facf9fc 20228+ break;
20229+
20230+ case Opt_ignore:
0c3ec466 20231+ pr_warn("ignored %s\n", opt_str);
1facf9fc 20232+ /*FALLTHROUGH*/
20233+ case Opt_ignore_silent:
20234+ skipped = 1;
20235+ err = 0;
20236+ break;
20237+ case Opt_err:
4a4d8108 20238+ pr_err("unknown option %s\n", opt_str);
1facf9fc 20239+ break;
20240+ }
20241+
20242+ if (!err && !skipped) {
20243+ if (unlikely(++opt > opt_tail)) {
20244+ err = -E2BIG;
20245+ opt--;
20246+ opt->type = Opt_tail;
20247+ break;
20248+ }
20249+ opt->type = Opt_tail;
20250+ }
20251+ }
20252+
20253+ kfree(a);
20254+ dump_opts(opts);
20255+ if (unlikely(err))
20256+ au_opts_free(opts);
20257+
4f0767ce 20258+out:
1facf9fc 20259+ return err;
20260+}
20261+
20262+static int au_opt_wbr_create(struct super_block *sb,
20263+ struct au_opt_wbr_create *create)
20264+{
20265+ int err;
20266+ struct au_sbinfo *sbinfo;
20267+
dece6358
AM
20268+ SiMustWriteLock(sb);
20269+
1facf9fc 20270+ err = 1; /* handled */
20271+ sbinfo = au_sbi(sb);
20272+ if (sbinfo->si_wbr_create_ops->fin) {
20273+ err = sbinfo->si_wbr_create_ops->fin(sb);
20274+ if (!err)
20275+ err = 1;
20276+ }
20277+
20278+ sbinfo->si_wbr_create = create->wbr_create;
20279+ sbinfo->si_wbr_create_ops = au_wbr_create_ops + create->wbr_create;
20280+ switch (create->wbr_create) {
20281+ case AuWbrCreate_MFSRRV:
20282+ case AuWbrCreate_MFSRR:
20283+ sbinfo->si_wbr_mfs.mfsrr_watermark = create->mfsrr_watermark;
20284+ /*FALLTHROUGH*/
20285+ case AuWbrCreate_MFS:
20286+ case AuWbrCreate_MFSV:
20287+ case AuWbrCreate_PMFS:
20288+ case AuWbrCreate_PMFSV:
e49829fe
JR
20289+ sbinfo->si_wbr_mfs.mfs_expire
20290+ = msecs_to_jiffies(create->mfs_second * MSEC_PER_SEC);
1facf9fc 20291+ break;
20292+ }
20293+
20294+ if (sbinfo->si_wbr_create_ops->init)
20295+ sbinfo->si_wbr_create_ops->init(sb); /* ignore */
20296+
20297+ return err;
20298+}
20299+
20300+/*
20301+ * returns,
20302+ * plus: processed without an error
20303+ * zero: unprocessed
20304+ */
20305+static int au_opt_simple(struct super_block *sb, struct au_opt *opt,
20306+ struct au_opts *opts)
20307+{
20308+ int err;
20309+ struct au_sbinfo *sbinfo;
20310+
dece6358
AM
20311+ SiMustWriteLock(sb);
20312+
1facf9fc 20313+ err = 1; /* handled */
20314+ sbinfo = au_sbi(sb);
20315+ switch (opt->type) {
20316+ case Opt_udba:
20317+ sbinfo->si_mntflags &= ~AuOptMask_UDBA;
20318+ sbinfo->si_mntflags |= opt->udba;
20319+ opts->given_udba |= opt->udba;
20320+ break;
20321+
20322+ case Opt_plink:
20323+ au_opt_set(sbinfo->si_mntflags, PLINK);
20324+ break;
20325+ case Opt_noplink:
20326+ if (au_opt_test(sbinfo->si_mntflags, PLINK))
e49829fe 20327+ au_plink_put(sb, /*verbose*/1);
1facf9fc 20328+ au_opt_clr(sbinfo->si_mntflags, PLINK);
20329+ break;
20330+ case Opt_list_plink:
20331+ if (au_opt_test(sbinfo->si_mntflags, PLINK))
20332+ au_plink_list(sb);
20333+ break;
20334+
4a4d8108
AM
20335+ case Opt_dio:
20336+ au_opt_set(sbinfo->si_mntflags, DIO);
20337+ au_fset_opts(opts->flags, REFRESH_DYAOP);
20338+ break;
20339+ case Opt_nodio:
20340+ au_opt_clr(sbinfo->si_mntflags, DIO);
20341+ au_fset_opts(opts->flags, REFRESH_DYAOP);
20342+ break;
20343+
1facf9fc 20344+ case Opt_diropq_a:
20345+ au_opt_set(sbinfo->si_mntflags, ALWAYS_DIROPQ);
20346+ break;
20347+ case Opt_diropq_w:
20348+ au_opt_clr(sbinfo->si_mntflags, ALWAYS_DIROPQ);
20349+ break;
20350+
20351+ case Opt_warn_perm:
20352+ au_opt_set(sbinfo->si_mntflags, WARN_PERM);
20353+ break;
20354+ case Opt_nowarn_perm:
20355+ au_opt_clr(sbinfo->si_mntflags, WARN_PERM);
20356+ break;
20357+
20358+ case Opt_refrof:
20359+ au_opt_set(sbinfo->si_mntflags, REFROF);
20360+ break;
20361+ case Opt_norefrof:
20362+ au_opt_clr(sbinfo->si_mntflags, REFROF);
20363+ break;
20364+
20365+ case Opt_verbose:
20366+ au_opt_set(sbinfo->si_mntflags, VERBOSE);
20367+ break;
20368+ case Opt_noverbose:
20369+ au_opt_clr(sbinfo->si_mntflags, VERBOSE);
20370+ break;
20371+
20372+ case Opt_sum:
20373+ au_opt_set(sbinfo->si_mntflags, SUM);
20374+ break;
20375+ case Opt_wsum:
20376+ au_opt_clr(sbinfo->si_mntflags, SUM);
20377+ au_opt_set(sbinfo->si_mntflags, SUM_W);
20378+ case Opt_nosum:
20379+ au_opt_clr(sbinfo->si_mntflags, SUM);
20380+ au_opt_clr(sbinfo->si_mntflags, SUM_W);
20381+ break;
20382+
20383+ case Opt_wbr_create:
20384+ err = au_opt_wbr_create(sb, &opt->wbr_create);
20385+ break;
20386+ case Opt_wbr_copyup:
20387+ sbinfo->si_wbr_copyup = opt->wbr_copyup;
20388+ sbinfo->si_wbr_copyup_ops = au_wbr_copyup_ops + opt->wbr_copyup;
20389+ break;
20390+
20391+ case Opt_dirwh:
20392+ sbinfo->si_dirwh = opt->dirwh;
20393+ break;
20394+
20395+ case Opt_rdcache:
e49829fe
JR
20396+ sbinfo->si_rdcache
20397+ = msecs_to_jiffies(opt->rdcache * MSEC_PER_SEC);
1facf9fc 20398+ break;
20399+ case Opt_rdblk:
20400+ sbinfo->si_rdblk = opt->rdblk;
20401+ break;
dece6358
AM
20402+ case Opt_rdblk_def:
20403+ sbinfo->si_rdblk = AUFS_RDBLK_DEF;
20404+ break;
1facf9fc 20405+ case Opt_rdhash:
20406+ sbinfo->si_rdhash = opt->rdhash;
20407+ break;
dece6358
AM
20408+ case Opt_rdhash_def:
20409+ sbinfo->si_rdhash = AUFS_RDHASH_DEF;
20410+ break;
20411+
20412+ case Opt_shwh:
20413+ au_opt_set(sbinfo->si_mntflags, SHWH);
20414+ break;
20415+ case Opt_noshwh:
20416+ au_opt_clr(sbinfo->si_mntflags, SHWH);
20417+ break;
1facf9fc 20418+
20419+ case Opt_trunc_xino:
20420+ au_opt_set(sbinfo->si_mntflags, TRUNC_XINO);
20421+ break;
20422+ case Opt_notrunc_xino:
20423+ au_opt_clr(sbinfo->si_mntflags, TRUNC_XINO);
20424+ break;
20425+
20426+ case Opt_trunc_xino_path:
20427+ case Opt_itrunc_xino:
20428+ err = au_xino_trunc(sb, opt->xino_itrunc.bindex);
20429+ if (!err)
20430+ err = 1;
20431+ break;
20432+
20433+ case Opt_trunc_xib:
20434+ au_fset_opts(opts->flags, TRUNC_XIB);
20435+ break;
20436+ case Opt_notrunc_xib:
20437+ au_fclr_opts(opts->flags, TRUNC_XIB);
20438+ break;
20439+
20440+ default:
20441+ err = 0;
20442+ break;
20443+ }
20444+
20445+ return err;
20446+}
20447+
20448+/*
20449+ * returns tri-state.
20450+ * plus: processed without an error
20451+ * zero: unprocessed
20452+ * minus: error
20453+ */
20454+static int au_opt_br(struct super_block *sb, struct au_opt *opt,
20455+ struct au_opts *opts)
20456+{
20457+ int err, do_refresh;
20458+
20459+ err = 0;
20460+ switch (opt->type) {
20461+ case Opt_append:
20462+ opt->add.bindex = au_sbend(sb) + 1;
20463+ if (opt->add.bindex < 0)
20464+ opt->add.bindex = 0;
20465+ goto add;
20466+ case Opt_prepend:
20467+ opt->add.bindex = 0;
20468+ add:
20469+ case Opt_add:
20470+ err = au_br_add(sb, &opt->add,
20471+ au_ftest_opts(opts->flags, REMOUNT));
20472+ if (!err) {
20473+ err = 1;
027c5e7a 20474+ au_fset_opts(opts->flags, REFRESH);
1facf9fc 20475+ }
20476+ break;
20477+
20478+ case Opt_del:
20479+ case Opt_idel:
20480+ err = au_br_del(sb, &opt->del,
20481+ au_ftest_opts(opts->flags, REMOUNT));
20482+ if (!err) {
20483+ err = 1;
20484+ au_fset_opts(opts->flags, TRUNC_XIB);
027c5e7a 20485+ au_fset_opts(opts->flags, REFRESH);
1facf9fc 20486+ }
20487+ break;
20488+
20489+ case Opt_mod:
20490+ case Opt_imod:
20491+ err = au_br_mod(sb, &opt->mod,
20492+ au_ftest_opts(opts->flags, REMOUNT),
20493+ &do_refresh);
20494+ if (!err) {
20495+ err = 1;
027c5e7a
AM
20496+ if (do_refresh)
20497+ au_fset_opts(opts->flags, REFRESH);
1facf9fc 20498+ }
20499+ break;
20500+ }
20501+
20502+ return err;
20503+}
20504+
20505+static int au_opt_xino(struct super_block *sb, struct au_opt *opt,
20506+ struct au_opt_xino **opt_xino,
20507+ struct au_opts *opts)
20508+{
20509+ int err;
20510+ aufs_bindex_t bend, bindex;
20511+ struct dentry *root, *parent, *h_root;
20512+
20513+ err = 0;
20514+ switch (opt->type) {
20515+ case Opt_xino:
20516+ err = au_xino_set(sb, &opt->xino,
20517+ !!au_ftest_opts(opts->flags, REMOUNT));
20518+ if (unlikely(err))
20519+ break;
20520+
20521+ *opt_xino = &opt->xino;
20522+ au_xino_brid_set(sb, -1);
20523+
20524+ /* safe d_parent access */
20525+ parent = opt->xino.file->f_dentry->d_parent;
20526+ root = sb->s_root;
20527+ bend = au_sbend(sb);
20528+ for (bindex = 0; bindex <= bend; bindex++) {
20529+ h_root = au_h_dptr(root, bindex);
20530+ if (h_root == parent) {
20531+ au_xino_brid_set(sb, au_sbr_id(sb, bindex));
20532+ break;
20533+ }
20534+ }
20535+ break;
20536+
20537+ case Opt_noxino:
20538+ au_xino_clr(sb);
20539+ au_xino_brid_set(sb, -1);
20540+ *opt_xino = (void *)-1;
20541+ break;
20542+ }
20543+
20544+ return err;
20545+}
20546+
20547+int au_opts_verify(struct super_block *sb, unsigned long sb_flags,
20548+ unsigned int pending)
20549+{
20550+ int err;
20551+ aufs_bindex_t bindex, bend;
20552+ unsigned char do_plink, skip, do_free;
20553+ struct au_branch *br;
20554+ struct au_wbr *wbr;
20555+ struct dentry *root;
20556+ struct inode *dir, *h_dir;
20557+ struct au_sbinfo *sbinfo;
20558+ struct au_hinode *hdir;
20559+
dece6358
AM
20560+ SiMustAnyLock(sb);
20561+
1facf9fc 20562+ sbinfo = au_sbi(sb);
20563+ AuDebugOn(!(sbinfo->si_mntflags & AuOptMask_UDBA));
20564+
dece6358
AM
20565+ if (!(sb_flags & MS_RDONLY)) {
20566+ if (unlikely(!au_br_writable(au_sbr_perm(sb, 0))))
0c3ec466 20567+ pr_warn("first branch should be rw\n");
dece6358 20568+ if (unlikely(au_opt_test(sbinfo->si_mntflags, SHWH)))
0c3ec466 20569+ pr_warn("shwh should be used with ro\n");
dece6358 20570+ }
1facf9fc 20571+
4a4d8108 20572+ if (au_opt_test((sbinfo->si_mntflags | pending), UDBA_HNOTIFY)
1facf9fc 20573+ && !au_opt_test(sbinfo->si_mntflags, XINO))
0c3ec466 20574+ pr_warn("udba=*notify requires xino\n");
1facf9fc 20575+
20576+ err = 0;
20577+ root = sb->s_root;
4a4d8108 20578+ dir = root->d_inode;
1facf9fc 20579+ do_plink = !!au_opt_test(sbinfo->si_mntflags, PLINK);
20580+ bend = au_sbend(sb);
20581+ for (bindex = 0; !err && bindex <= bend; bindex++) {
20582+ skip = 0;
20583+ h_dir = au_h_iptr(dir, bindex);
20584+ br = au_sbr(sb, bindex);
20585+ do_free = 0;
20586+
20587+ wbr = br->br_wbr;
20588+ if (wbr)
20589+ wbr_wh_read_lock(wbr);
20590+
1e00d052 20591+ if (!au_br_writable(br->br_perm)) {
1facf9fc 20592+ do_free = !!wbr;
20593+ skip = (!wbr
20594+ || (!wbr->wbr_whbase
20595+ && !wbr->wbr_plink
20596+ && !wbr->wbr_orph));
1e00d052 20597+ } else if (!au_br_wh_linkable(br->br_perm)) {
1facf9fc 20598+ /* skip = (!br->br_whbase && !br->br_orph); */
20599+ skip = (!wbr || !wbr->wbr_whbase);
20600+ if (skip && wbr) {
20601+ if (do_plink)
20602+ skip = !!wbr->wbr_plink;
20603+ else
20604+ skip = !wbr->wbr_plink;
20605+ }
1e00d052 20606+ } else {
1facf9fc 20607+ /* skip = (br->br_whbase && br->br_ohph); */
20608+ skip = (wbr && wbr->wbr_whbase);
20609+ if (skip) {
20610+ if (do_plink)
20611+ skip = !!wbr->wbr_plink;
20612+ else
20613+ skip = !wbr->wbr_plink;
20614+ }
1facf9fc 20615+ }
20616+ if (wbr)
20617+ wbr_wh_read_unlock(wbr);
20618+
20619+ if (skip)
20620+ continue;
20621+
20622+ hdir = au_hi(dir, bindex);
4a4d8108 20623+ au_hn_imtx_lock_nested(hdir, AuLsc_I_PARENT);
1facf9fc 20624+ if (wbr)
20625+ wbr_wh_write_lock(wbr);
20626+ err = au_wh_init(au_h_dptr(root, bindex), br, sb);
20627+ if (wbr)
20628+ wbr_wh_write_unlock(wbr);
4a4d8108 20629+ au_hn_imtx_unlock(hdir);
1facf9fc 20630+
20631+ if (!err && do_free) {
20632+ kfree(wbr);
20633+ br->br_wbr = NULL;
20634+ }
20635+ }
20636+
20637+ return err;
20638+}
20639+
20640+int au_opts_mount(struct super_block *sb, struct au_opts *opts)
20641+{
20642+ int err;
20643+ unsigned int tmp;
027c5e7a 20644+ aufs_bindex_t bindex, bend;
1facf9fc 20645+ struct au_opt *opt;
20646+ struct au_opt_xino *opt_xino, xino;
20647+ struct au_sbinfo *sbinfo;
027c5e7a 20648+ struct au_branch *br;
1facf9fc 20649+
dece6358
AM
20650+ SiMustWriteLock(sb);
20651+
1facf9fc 20652+ err = 0;
20653+ opt_xino = NULL;
20654+ opt = opts->opt;
20655+ while (err >= 0 && opt->type != Opt_tail)
20656+ err = au_opt_simple(sb, opt++, opts);
20657+ if (err > 0)
20658+ err = 0;
20659+ else if (unlikely(err < 0))
20660+ goto out;
20661+
20662+ /* disable xino and udba temporary */
20663+ sbinfo = au_sbi(sb);
20664+ tmp = sbinfo->si_mntflags;
20665+ au_opt_clr(sbinfo->si_mntflags, XINO);
20666+ au_opt_set_udba(sbinfo->si_mntflags, UDBA_REVAL);
20667+
20668+ opt = opts->opt;
20669+ while (err >= 0 && opt->type != Opt_tail)
20670+ err = au_opt_br(sb, opt++, opts);
20671+ if (err > 0)
20672+ err = 0;
20673+ else if (unlikely(err < 0))
20674+ goto out;
20675+
20676+ bend = au_sbend(sb);
20677+ if (unlikely(bend < 0)) {
20678+ err = -EINVAL;
4a4d8108 20679+ pr_err("no branches\n");
1facf9fc 20680+ goto out;
20681+ }
20682+
20683+ if (au_opt_test(tmp, XINO))
20684+ au_opt_set(sbinfo->si_mntflags, XINO);
20685+ opt = opts->opt;
20686+ while (!err && opt->type != Opt_tail)
20687+ err = au_opt_xino(sb, opt++, &opt_xino, opts);
20688+ if (unlikely(err))
20689+ goto out;
20690+
20691+ err = au_opts_verify(sb, sb->s_flags, tmp);
20692+ if (unlikely(err))
20693+ goto out;
20694+
20695+ /* restore xino */
20696+ if (au_opt_test(tmp, XINO) && !opt_xino) {
20697+ xino.file = au_xino_def(sb);
20698+ err = PTR_ERR(xino.file);
20699+ if (IS_ERR(xino.file))
20700+ goto out;
20701+
20702+ err = au_xino_set(sb, &xino, /*remount*/0);
20703+ fput(xino.file);
20704+ if (unlikely(err))
20705+ goto out;
20706+ }
20707+
20708+ /* restore udba */
027c5e7a 20709+ tmp &= AuOptMask_UDBA;
1facf9fc 20710+ sbinfo->si_mntflags &= ~AuOptMask_UDBA;
027c5e7a
AM
20711+ sbinfo->si_mntflags |= tmp;
20712+ bend = au_sbend(sb);
20713+ for (bindex = 0; bindex <= bend; bindex++) {
20714+ br = au_sbr(sb, bindex);
20715+ err = au_hnotify_reset_br(tmp, br, br->br_perm);
20716+ if (unlikely(err))
20717+ AuIOErr("hnotify failed on br %d, %d, ignored\n",
20718+ bindex, err);
20719+ /* go on even if err */
20720+ }
4a4d8108 20721+ if (au_opt_test(tmp, UDBA_HNOTIFY)) {
1facf9fc 20722+ struct inode *dir = sb->s_root->d_inode;
4a4d8108 20723+ au_hn_reset(dir, au_hi_flags(dir, /*isdir*/1) & ~AuHi_XINO);
1facf9fc 20724+ }
20725+
4f0767ce 20726+out:
1facf9fc 20727+ return err;
20728+}
20729+
20730+int au_opts_remount(struct super_block *sb, struct au_opts *opts)
20731+{
20732+ int err, rerr;
20733+ struct inode *dir;
20734+ struct au_opt_xino *opt_xino;
20735+ struct au_opt *opt;
20736+ struct au_sbinfo *sbinfo;
20737+
dece6358
AM
20738+ SiMustWriteLock(sb);
20739+
1facf9fc 20740+ dir = sb->s_root->d_inode;
20741+ sbinfo = au_sbi(sb);
20742+ err = 0;
20743+ opt_xino = NULL;
20744+ opt = opts->opt;
20745+ while (err >= 0 && opt->type != Opt_tail) {
20746+ err = au_opt_simple(sb, opt, opts);
20747+ if (!err)
20748+ err = au_opt_br(sb, opt, opts);
20749+ if (!err)
20750+ err = au_opt_xino(sb, opt, &opt_xino, opts);
20751+ opt++;
20752+ }
20753+ if (err > 0)
20754+ err = 0;
20755+ AuTraceErr(err);
20756+ /* go on even err */
20757+
20758+ rerr = au_opts_verify(sb, opts->sb_flags, /*pending*/0);
20759+ if (unlikely(rerr && !err))
20760+ err = rerr;
20761+
20762+ if (au_ftest_opts(opts->flags, TRUNC_XIB)) {
20763+ rerr = au_xib_trunc(sb);
20764+ if (unlikely(rerr && !err))
20765+ err = rerr;
20766+ }
20767+
20768+ /* will be handled by the caller */
027c5e7a 20769+ if (!au_ftest_opts(opts->flags, REFRESH)
1facf9fc 20770+ && (opts->given_udba || au_opt_test(sbinfo->si_mntflags, XINO)))
027c5e7a 20771+ au_fset_opts(opts->flags, REFRESH);
1facf9fc 20772+
20773+ AuDbg("status 0x%x\n", opts->flags);
20774+ return err;
20775+}
20776+
20777+/* ---------------------------------------------------------------------- */
20778+
20779+unsigned int au_opt_udba(struct super_block *sb)
20780+{
20781+ return au_mntflags(sb) & AuOptMask_UDBA;
20782+}
7f207e10
AM
20783diff -urN /usr/share/empty/fs/aufs/opts.h linux/fs/aufs/opts.h
20784--- /usr/share/empty/fs/aufs/opts.h 1970-01-01 01:00:00.000000000 +0100
2dfbb274 20785+++ linux/fs/aufs/opts.h 2012-08-26 08:39:00.760508065 +0200
f6c5ef8b 20786@@ -0,0 +1,209 @@
1facf9fc 20787+/*
f6c5ef8b 20788+ * Copyright (C) 2005-2012 Junjiro R. Okajima
1facf9fc 20789+ *
20790+ * This program, aufs is free software; you can redistribute it and/or modify
20791+ * it under the terms of the GNU General Public License as published by
20792+ * the Free Software Foundation; either version 2 of the License, or
20793+ * (at your option) any later version.
dece6358
AM
20794+ *
20795+ * This program is distributed in the hope that it will be useful,
20796+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
20797+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20798+ * GNU General Public License for more details.
20799+ *
20800+ * You should have received a copy of the GNU General Public License
20801+ * along with this program; if not, write to the Free Software
20802+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 20803+ */
20804+
20805+/*
20806+ * mount options/flags
20807+ */
20808+
20809+#ifndef __AUFS_OPTS_H__
20810+#define __AUFS_OPTS_H__
20811+
20812+#ifdef __KERNEL__
20813+
dece6358 20814+#include <linux/path.h>
1facf9fc 20815+
dece6358
AM
20816+struct file;
20817+struct super_block;
20818+
1facf9fc 20819+/* ---------------------------------------------------------------------- */
20820+
20821+/* mount flags */
20822+#define AuOpt_XINO 1 /* external inode number bitmap
20823+ and translation table */
20824+#define AuOpt_TRUNC_XINO (1 << 1) /* truncate xino files */
20825+#define AuOpt_UDBA_NONE (1 << 2) /* users direct branch access */
20826+#define AuOpt_UDBA_REVAL (1 << 3)
4a4d8108 20827+#define AuOpt_UDBA_HNOTIFY (1 << 4)
dece6358
AM
20828+#define AuOpt_SHWH (1 << 5) /* show whiteout */
20829+#define AuOpt_PLINK (1 << 6) /* pseudo-link */
20830+#define AuOpt_DIRPERM1 (1 << 7) /* unimplemented */
20831+#define AuOpt_REFROF (1 << 8) /* unimplemented */
20832+#define AuOpt_ALWAYS_DIROPQ (1 << 9) /* policy to creating diropq */
20833+#define AuOpt_SUM (1 << 10) /* summation for statfs(2) */
20834+#define AuOpt_SUM_W (1 << 11) /* unimplemented */
20835+#define AuOpt_WARN_PERM (1 << 12) /* warn when add-branch */
20836+#define AuOpt_VERBOSE (1 << 13) /* busy inode when del-branch */
4a4d8108 20837+#define AuOpt_DIO (1 << 14) /* direct io */
1facf9fc 20838+
4a4d8108
AM
20839+#ifndef CONFIG_AUFS_HNOTIFY
20840+#undef AuOpt_UDBA_HNOTIFY
20841+#define AuOpt_UDBA_HNOTIFY 0
1facf9fc 20842+#endif
dece6358
AM
20843+#ifndef CONFIG_AUFS_SHWH
20844+#undef AuOpt_SHWH
20845+#define AuOpt_SHWH 0
20846+#endif
1facf9fc 20847+
20848+#define AuOpt_Def (AuOpt_XINO \
20849+ | AuOpt_UDBA_REVAL \
20850+ | AuOpt_PLINK \
20851+ /* | AuOpt_DIRPERM1 */ \
20852+ | AuOpt_WARN_PERM)
20853+#define AuOptMask_UDBA (AuOpt_UDBA_NONE \
20854+ | AuOpt_UDBA_REVAL \
4a4d8108 20855+ | AuOpt_UDBA_HNOTIFY)
1facf9fc 20856+
20857+#define au_opt_test(flags, name) (flags & AuOpt_##name)
20858+#define au_opt_set(flags, name) do { \
20859+ BUILD_BUG_ON(AuOpt_##name & AuOptMask_UDBA); \
20860+ ((flags) |= AuOpt_##name); \
20861+} while (0)
20862+#define au_opt_set_udba(flags, name) do { \
20863+ (flags) &= ~AuOptMask_UDBA; \
20864+ ((flags) |= AuOpt_##name); \
20865+} while (0)
7f207e10
AM
20866+#define au_opt_clr(flags, name) do { \
20867+ ((flags) &= ~AuOpt_##name); \
20868+} while (0)
1facf9fc 20869+
e49829fe
JR
20870+static inline unsigned int au_opts_plink(unsigned int mntflags)
20871+{
20872+#ifdef CONFIG_PROC_FS
20873+ return mntflags;
20874+#else
20875+ return mntflags & ~AuOpt_PLINK;
20876+#endif
20877+}
20878+
1facf9fc 20879+/* ---------------------------------------------------------------------- */
20880+
20881+/* policies to select one among multiple writable branches */
20882+enum {
20883+ AuWbrCreate_TDP, /* top down parent */
20884+ AuWbrCreate_RR, /* round robin */
20885+ AuWbrCreate_MFS, /* most free space */
20886+ AuWbrCreate_MFSV, /* mfs with seconds */
20887+ AuWbrCreate_MFSRR, /* mfs then rr */
20888+ AuWbrCreate_MFSRRV, /* mfs then rr with seconds */
20889+ AuWbrCreate_PMFS, /* parent and mfs */
20890+ AuWbrCreate_PMFSV, /* parent and mfs with seconds */
20891+
20892+ AuWbrCreate_Def = AuWbrCreate_TDP
20893+};
20894+
20895+enum {
20896+ AuWbrCopyup_TDP, /* top down parent */
20897+ AuWbrCopyup_BUP, /* bottom up parent */
20898+ AuWbrCopyup_BU, /* bottom up */
20899+
20900+ AuWbrCopyup_Def = AuWbrCopyup_TDP
20901+};
20902+
20903+/* ---------------------------------------------------------------------- */
20904+
20905+struct au_opt_add {
20906+ aufs_bindex_t bindex;
20907+ char *pathname;
20908+ int perm;
20909+ struct path path;
20910+};
20911+
20912+struct au_opt_del {
20913+ char *pathname;
20914+ struct path h_path;
20915+};
20916+
20917+struct au_opt_mod {
20918+ char *path;
20919+ int perm;
20920+ struct dentry *h_root;
20921+};
20922+
20923+struct au_opt_xino {
20924+ char *path;
20925+ struct file *file;
20926+};
20927+
20928+struct au_opt_xino_itrunc {
20929+ aufs_bindex_t bindex;
20930+};
20931+
20932+struct au_opt_wbr_create {
20933+ int wbr_create;
20934+ int mfs_second;
20935+ unsigned long long mfsrr_watermark;
20936+};
20937+
20938+struct au_opt {
20939+ int type;
20940+ union {
20941+ struct au_opt_xino xino;
20942+ struct au_opt_xino_itrunc xino_itrunc;
20943+ struct au_opt_add add;
20944+ struct au_opt_del del;
20945+ struct au_opt_mod mod;
20946+ int dirwh;
20947+ int rdcache;
20948+ unsigned int rdblk;
20949+ unsigned int rdhash;
20950+ int udba;
20951+ struct au_opt_wbr_create wbr_create;
20952+ int wbr_copyup;
20953+ };
20954+};
20955+
20956+/* opts flags */
20957+#define AuOpts_REMOUNT 1
027c5e7a
AM
20958+#define AuOpts_REFRESH (1 << 1)
20959+#define AuOpts_TRUNC_XIB (1 << 2)
20960+#define AuOpts_REFRESH_DYAOP (1 << 3)
1facf9fc 20961+#define au_ftest_opts(flags, name) ((flags) & AuOpts_##name)
7f207e10
AM
20962+#define au_fset_opts(flags, name) \
20963+ do { (flags) |= AuOpts_##name; } while (0)
20964+#define au_fclr_opts(flags, name) \
20965+ do { (flags) &= ~AuOpts_##name; } while (0)
1facf9fc 20966+
20967+struct au_opts {
20968+ struct au_opt *opt;
20969+ int max_opt;
20970+
20971+ unsigned int given_udba;
20972+ unsigned int flags;
20973+ unsigned long sb_flags;
20974+};
20975+
20976+/* ---------------------------------------------------------------------- */
20977+
1e00d052 20978+char *au_optstr_br_perm(int brperm);
1facf9fc 20979+const char *au_optstr_udba(int udba);
20980+const char *au_optstr_wbr_copyup(int wbr_copyup);
20981+const char *au_optstr_wbr_create(int wbr_create);
20982+
20983+void au_opts_free(struct au_opts *opts);
20984+int au_opts_parse(struct super_block *sb, char *str, struct au_opts *opts);
20985+int au_opts_verify(struct super_block *sb, unsigned long sb_flags,
20986+ unsigned int pending);
20987+int au_opts_mount(struct super_block *sb, struct au_opts *opts);
20988+int au_opts_remount(struct super_block *sb, struct au_opts *opts);
20989+
20990+unsigned int au_opt_udba(struct super_block *sb);
20991+
20992+/* ---------------------------------------------------------------------- */
20993+
20994+#endif /* __KERNEL__ */
20995+#endif /* __AUFS_OPTS_H__ */
7f207e10
AM
20996diff -urN /usr/share/empty/fs/aufs/plink.c linux/fs/aufs/plink.c
20997--- /usr/share/empty/fs/aufs/plink.c 1970-01-01 01:00:00.000000000 +0100
b4510431 20998+++ linux/fs/aufs/plink.c 2012-10-17 10:31:01.775814563 +0200
0c3ec466 20999@@ -0,0 +1,511 @@
1facf9fc 21000+/*
f6c5ef8b 21001+ * Copyright (C) 2005-2012 Junjiro R. Okajima
1facf9fc 21002+ *
21003+ * This program, aufs is free software; you can redistribute it and/or modify
21004+ * it under the terms of the GNU General Public License as published by
21005+ * the Free Software Foundation; either version 2 of the License, or
21006+ * (at your option) any later version.
dece6358
AM
21007+ *
21008+ * This program is distributed in the hope that it will be useful,
21009+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
21010+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21011+ * GNU General Public License for more details.
21012+ *
21013+ * You should have received a copy of the GNU General Public License
21014+ * along with this program; if not, write to the Free Software
21015+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 21016+ */
21017+
21018+/*
21019+ * pseudo-link
21020+ */
21021+
21022+#include "aufs.h"
21023+
21024+/*
e49829fe 21025+ * the pseudo-link maintenance mode.
1facf9fc 21026+ * during a user process maintains the pseudo-links,
21027+ * prohibit adding a new plink and branch manipulation.
e49829fe
JR
21028+ *
21029+ * Flags
21030+ * NOPLM:
21031+ * For entry functions which will handle plink, and i_mutex is already held
21032+ * in VFS.
21033+ * They cannot wait and should return an error at once.
21034+ * Callers has to check the error.
21035+ * NOPLMW:
21036+ * For entry functions which will handle plink, but i_mutex is not held
21037+ * in VFS.
21038+ * They can wait the plink maintenance mode to finish.
21039+ *
21040+ * They behave like F_SETLK and F_SETLKW.
21041+ * If the caller never handle plink, then both flags are unnecessary.
1facf9fc 21042+ */
e49829fe
JR
21043+
21044+int au_plink_maint(struct super_block *sb, int flags)
1facf9fc 21045+{
e49829fe
JR
21046+ int err;
21047+ pid_t pid, ppid;
21048+ struct au_sbinfo *sbi;
dece6358
AM
21049+
21050+ SiMustAnyLock(sb);
21051+
e49829fe
JR
21052+ err = 0;
21053+ if (!au_opt_test(au_mntflags(sb), PLINK))
21054+ goto out;
21055+
21056+ sbi = au_sbi(sb);
21057+ pid = sbi->si_plink_maint_pid;
21058+ if (!pid || pid == current->pid)
21059+ goto out;
21060+
21061+ /* todo: it highly depends upon /sbin/mount.aufs */
21062+ rcu_read_lock();
21063+ ppid = task_pid_vnr(rcu_dereference(current->real_parent));
21064+ rcu_read_unlock();
21065+ if (pid == ppid)
21066+ goto out;
21067+
21068+ if (au_ftest_lock(flags, NOPLMW)) {
027c5e7a
AM
21069+ /* if there is no i_mutex lock in VFS, we don't need to wait */
21070+ /* AuDebugOn(!lockdep_depth(current)); */
e49829fe
JR
21071+ while (sbi->si_plink_maint_pid) {
21072+ si_read_unlock(sb);
21073+ /* gave up wake_up_bit() */
21074+ wait_event(sbi->si_plink_wq, !sbi->si_plink_maint_pid);
21075+
21076+ if (au_ftest_lock(flags, FLUSH))
21077+ au_nwt_flush(&sbi->si_nowait);
21078+ si_noflush_read_lock(sb);
21079+ }
21080+ } else if (au_ftest_lock(flags, NOPLM)) {
21081+ AuDbg("ppid %d, pid %d\n", ppid, pid);
21082+ err = -EAGAIN;
21083+ }
21084+
21085+out:
21086+ return err;
4a4d8108
AM
21087+}
21088+
e49829fe 21089+void au_plink_maint_leave(struct au_sbinfo *sbinfo)
4a4d8108 21090+{
4a4d8108 21091+ spin_lock(&sbinfo->si_plink_maint_lock);
027c5e7a 21092+ sbinfo->si_plink_maint_pid = 0;
4a4d8108 21093+ spin_unlock(&sbinfo->si_plink_maint_lock);
027c5e7a 21094+ wake_up_all(&sbinfo->si_plink_wq);
4a4d8108
AM
21095+}
21096+
e49829fe 21097+int au_plink_maint_enter(struct super_block *sb)
4a4d8108
AM
21098+{
21099+ int err;
4a4d8108
AM
21100+ struct au_sbinfo *sbinfo;
21101+
21102+ err = 0;
4a4d8108
AM
21103+ sbinfo = au_sbi(sb);
21104+ /* make sure i am the only one in this fs */
e49829fe
JR
21105+ si_write_lock(sb, AuLock_FLUSH);
21106+ if (au_opt_test(au_mntflags(sb), PLINK)) {
21107+ spin_lock(&sbinfo->si_plink_maint_lock);
21108+ if (!sbinfo->si_plink_maint_pid)
21109+ sbinfo->si_plink_maint_pid = current->pid;
21110+ else
21111+ err = -EBUSY;
21112+ spin_unlock(&sbinfo->si_plink_maint_lock);
21113+ }
4a4d8108
AM
21114+ si_write_unlock(sb);
21115+
21116+ return err;
1facf9fc 21117+}
21118+
21119+/* ---------------------------------------------------------------------- */
21120+
21121+struct pseudo_link {
4a4d8108
AM
21122+ union {
21123+ struct list_head list;
21124+ struct rcu_head rcu;
21125+ };
1facf9fc 21126+ struct inode *inode;
21127+};
21128+
21129+#ifdef CONFIG_AUFS_DEBUG
21130+void au_plink_list(struct super_block *sb)
21131+{
21132+ struct au_sbinfo *sbinfo;
21133+ struct list_head *plink_list;
21134+ struct pseudo_link *plink;
21135+
dece6358
AM
21136+ SiMustAnyLock(sb);
21137+
1facf9fc 21138+ sbinfo = au_sbi(sb);
21139+ AuDebugOn(!au_opt_test(au_mntflags(sb), PLINK));
e49829fe 21140+ AuDebugOn(au_plink_maint(sb, AuLock_NOPLM));
1facf9fc 21141+
21142+ plink_list = &sbinfo->si_plink.head;
4a4d8108
AM
21143+ rcu_read_lock();
21144+ list_for_each_entry_rcu(plink, plink_list, list)
1facf9fc 21145+ AuDbg("%lu\n", plink->inode->i_ino);
4a4d8108 21146+ rcu_read_unlock();
1facf9fc 21147+}
21148+#endif
21149+
21150+/* is the inode pseudo-linked? */
21151+int au_plink_test(struct inode *inode)
21152+{
21153+ int found;
21154+ struct au_sbinfo *sbinfo;
21155+ struct list_head *plink_list;
21156+ struct pseudo_link *plink;
21157+
21158+ sbinfo = au_sbi(inode->i_sb);
dece6358 21159+ AuRwMustAnyLock(&sbinfo->si_rwsem);
1facf9fc 21160+ AuDebugOn(!au_opt_test(au_mntflags(inode->i_sb), PLINK));
e49829fe 21161+ AuDebugOn(au_plink_maint(inode->i_sb, AuLock_NOPLM));
1facf9fc 21162+
21163+ found = 0;
21164+ plink_list = &sbinfo->si_plink.head;
4a4d8108
AM
21165+ rcu_read_lock();
21166+ list_for_each_entry_rcu(plink, plink_list, list)
1facf9fc 21167+ if (plink->inode == inode) {
21168+ found = 1;
21169+ break;
21170+ }
4a4d8108 21171+ rcu_read_unlock();
1facf9fc 21172+ return found;
21173+}
21174+
21175+/* ---------------------------------------------------------------------- */
21176+
21177+/*
21178+ * generate a name for plink.
21179+ * the file will be stored under AUFS_WH_PLINKDIR.
21180+ */
21181+/* 20 is max digits length of ulong 64 */
21182+#define PLINK_NAME_LEN ((20 + 1) * 2)
21183+
21184+static int plink_name(char *name, int len, struct inode *inode,
21185+ aufs_bindex_t bindex)
21186+{
21187+ int rlen;
21188+ struct inode *h_inode;
21189+
21190+ h_inode = au_h_iptr(inode, bindex);
21191+ rlen = snprintf(name, len, "%lu.%lu", inode->i_ino, h_inode->i_ino);
21192+ return rlen;
21193+}
21194+
7f207e10
AM
21195+struct au_do_plink_lkup_args {
21196+ struct dentry **errp;
21197+ struct qstr *tgtname;
21198+ struct dentry *h_parent;
21199+ struct au_branch *br;
21200+};
21201+
21202+static struct dentry *au_do_plink_lkup(struct qstr *tgtname,
21203+ struct dentry *h_parent,
21204+ struct au_branch *br)
21205+{
21206+ struct dentry *h_dentry;
21207+ struct mutex *h_mtx;
21208+
21209+ h_mtx = &h_parent->d_inode->i_mutex;
21210+ mutex_lock_nested(h_mtx, AuLsc_I_CHILD2);
b4510431 21211+ h_dentry = vfsub_lkup_one(tgtname, h_parent);
7f207e10
AM
21212+ mutex_unlock(h_mtx);
21213+ return h_dentry;
21214+}
21215+
21216+static void au_call_do_plink_lkup(void *args)
21217+{
21218+ struct au_do_plink_lkup_args *a = args;
21219+ *a->errp = au_do_plink_lkup(a->tgtname, a->h_parent, a->br);
21220+}
21221+
1facf9fc 21222+/* lookup the plink-ed @inode under the branch at @bindex */
21223+struct dentry *au_plink_lkup(struct inode *inode, aufs_bindex_t bindex)
21224+{
21225+ struct dentry *h_dentry, *h_parent;
21226+ struct au_branch *br;
21227+ struct inode *h_dir;
7f207e10 21228+ int wkq_err;
1facf9fc 21229+ char a[PLINK_NAME_LEN];
0c3ec466 21230+ struct qstr tgtname = QSTR_INIT(a, 0);
1facf9fc 21231+
e49829fe
JR
21232+ AuDebugOn(au_plink_maint(inode->i_sb, AuLock_NOPLM));
21233+
1facf9fc 21234+ br = au_sbr(inode->i_sb, bindex);
21235+ h_parent = br->br_wbr->wbr_plink;
21236+ h_dir = h_parent->d_inode;
21237+ tgtname.len = plink_name(a, sizeof(a), inode, bindex);
21238+
2dfbb274 21239+ if (!uid_eq(current_fsuid(), GLOBAL_ROOT_UID)) {
7f207e10
AM
21240+ struct au_do_plink_lkup_args args = {
21241+ .errp = &h_dentry,
21242+ .tgtname = &tgtname,
21243+ .h_parent = h_parent,
21244+ .br = br
21245+ };
21246+
21247+ wkq_err = au_wkq_wait(au_call_do_plink_lkup, &args);
21248+ if (unlikely(wkq_err))
21249+ h_dentry = ERR_PTR(wkq_err);
21250+ } else
21251+ h_dentry = au_do_plink_lkup(&tgtname, h_parent, br);
21252+
1facf9fc 21253+ return h_dentry;
21254+}
21255+
21256+/* create a pseudo-link */
21257+static int do_whplink(struct qstr *tgt, struct dentry *h_parent,
21258+ struct dentry *h_dentry, struct au_branch *br)
21259+{
21260+ int err;
21261+ struct path h_path = {
21262+ .mnt = br->br_mnt
21263+ };
21264+ struct inode *h_dir;
21265+
21266+ h_dir = h_parent->d_inode;
7f207e10 21267+ mutex_lock_nested(&h_dir->i_mutex, AuLsc_I_CHILD2);
4f0767ce 21268+again:
b4510431 21269+ h_path.dentry = vfsub_lkup_one(tgt, h_parent);
1facf9fc 21270+ err = PTR_ERR(h_path.dentry);
21271+ if (IS_ERR(h_path.dentry))
21272+ goto out;
21273+
21274+ err = 0;
21275+ /* wh.plink dir is not monitored */
7f207e10 21276+ /* todo: is it really safe? */
1facf9fc 21277+ if (h_path.dentry->d_inode
21278+ && h_path.dentry->d_inode != h_dentry->d_inode) {
21279+ err = vfsub_unlink(h_dir, &h_path, /*force*/0);
21280+ dput(h_path.dentry);
21281+ h_path.dentry = NULL;
21282+ if (!err)
21283+ goto again;
21284+ }
21285+ if (!err && !h_path.dentry->d_inode)
21286+ err = vfsub_link(h_dentry, h_dir, &h_path);
21287+ dput(h_path.dentry);
21288+
4f0767ce 21289+out:
7f207e10 21290+ mutex_unlock(&h_dir->i_mutex);
1facf9fc 21291+ return err;
21292+}
21293+
21294+struct do_whplink_args {
21295+ int *errp;
21296+ struct qstr *tgt;
21297+ struct dentry *h_parent;
21298+ struct dentry *h_dentry;
21299+ struct au_branch *br;
21300+};
21301+
21302+static void call_do_whplink(void *args)
21303+{
21304+ struct do_whplink_args *a = args;
21305+ *a->errp = do_whplink(a->tgt, a->h_parent, a->h_dentry, a->br);
21306+}
21307+
21308+static int whplink(struct dentry *h_dentry, struct inode *inode,
21309+ aufs_bindex_t bindex, struct au_branch *br)
21310+{
21311+ int err, wkq_err;
21312+ struct au_wbr *wbr;
21313+ struct dentry *h_parent;
21314+ struct inode *h_dir;
21315+ char a[PLINK_NAME_LEN];
0c3ec466 21316+ struct qstr tgtname = QSTR_INIT(a, 0);
1facf9fc 21317+
21318+ wbr = au_sbr(inode->i_sb, bindex)->br_wbr;
21319+ h_parent = wbr->wbr_plink;
21320+ h_dir = h_parent->d_inode;
21321+ tgtname.len = plink_name(a, sizeof(a), inode, bindex);
21322+
21323+ /* always superio. */
2dfbb274 21324+ if (!uid_eq(current_fsuid(), GLOBAL_ROOT_UID)) {
1facf9fc 21325+ struct do_whplink_args args = {
21326+ .errp = &err,
21327+ .tgt = &tgtname,
21328+ .h_parent = h_parent,
21329+ .h_dentry = h_dentry,
21330+ .br = br
21331+ };
21332+ wkq_err = au_wkq_wait(call_do_whplink, &args);
21333+ if (unlikely(wkq_err))
21334+ err = wkq_err;
21335+ } else
21336+ err = do_whplink(&tgtname, h_parent, h_dentry, br);
1facf9fc 21337+
21338+ return err;
21339+}
21340+
21341+/* free a single plink */
21342+static void do_put_plink(struct pseudo_link *plink, int do_del)
21343+{
1facf9fc 21344+ if (do_del)
21345+ list_del(&plink->list);
4a4d8108
AM
21346+ iput(plink->inode);
21347+ kfree(plink);
21348+}
21349+
21350+static void do_put_plink_rcu(struct rcu_head *rcu)
21351+{
21352+ struct pseudo_link *plink;
21353+
21354+ plink = container_of(rcu, struct pseudo_link, rcu);
21355+ iput(plink->inode);
1facf9fc 21356+ kfree(plink);
21357+}
21358+
21359+/*
21360+ * create a new pseudo-link for @h_dentry on @bindex.
21361+ * the linked inode is held in aufs @inode.
21362+ */
21363+void au_plink_append(struct inode *inode, aufs_bindex_t bindex,
21364+ struct dentry *h_dentry)
21365+{
21366+ struct super_block *sb;
21367+ struct au_sbinfo *sbinfo;
21368+ struct list_head *plink_list;
4a4d8108 21369+ struct pseudo_link *plink, *tmp;
1facf9fc 21370+ int found, err, cnt;
21371+
21372+ sb = inode->i_sb;
21373+ sbinfo = au_sbi(sb);
21374+ AuDebugOn(!au_opt_test(au_mntflags(sb), PLINK));
e49829fe 21375+ AuDebugOn(au_plink_maint(sb, AuLock_NOPLM));
1facf9fc 21376+
1facf9fc 21377+ cnt = 0;
21378+ found = 0;
21379+ plink_list = &sbinfo->si_plink.head;
4a4d8108
AM
21380+ rcu_read_lock();
21381+ list_for_each_entry_rcu(plink, plink_list, list) {
1facf9fc 21382+ cnt++;
21383+ if (plink->inode == inode) {
21384+ found = 1;
21385+ break;
21386+ }
21387+ }
4a4d8108
AM
21388+ rcu_read_unlock();
21389+ if (found)
1facf9fc 21390+ return;
4a4d8108
AM
21391+
21392+ tmp = kmalloc(sizeof(*plink), GFP_NOFS);
21393+ if (tmp)
21394+ tmp->inode = au_igrab(inode);
21395+ else {
21396+ err = -ENOMEM;
21397+ goto out;
1facf9fc 21398+ }
21399+
4a4d8108
AM
21400+ spin_lock(&sbinfo->si_plink.spin);
21401+ list_for_each_entry(plink, plink_list, list) {
21402+ if (plink->inode == inode) {
21403+ found = 1;
21404+ break;
21405+ }
1facf9fc 21406+ }
4a4d8108
AM
21407+ if (!found)
21408+ list_add_rcu(&tmp->list, plink_list);
1facf9fc 21409+ spin_unlock(&sbinfo->si_plink.spin);
4a4d8108
AM
21410+ if (!found) {
21411+ cnt++;
21412+ WARN_ONCE(cnt > AUFS_PLINK_WARN,
21413+ "unexpectedly many pseudo links, %d\n", cnt);
1facf9fc 21414+ err = whplink(h_dentry, inode, bindex, au_sbr(sb, bindex));
4a4d8108
AM
21415+ } else {
21416+ do_put_plink(tmp, 0);
21417+ return;
1facf9fc 21418+ }
21419+
4a4d8108 21420+out:
1facf9fc 21421+ if (unlikely(err)) {
0c3ec466 21422+ pr_warn("err %d, damaged pseudo link.\n", err);
4a4d8108
AM
21423+ if (tmp) {
21424+ au_spl_del_rcu(&tmp->list, &sbinfo->si_plink);
21425+ call_rcu(&tmp->rcu, do_put_plink_rcu);
21426+ }
1facf9fc 21427+ }
21428+}
21429+
21430+/* free all plinks */
e49829fe 21431+void au_plink_put(struct super_block *sb, int verbose)
1facf9fc 21432+{
21433+ struct au_sbinfo *sbinfo;
21434+ struct list_head *plink_list;
21435+ struct pseudo_link *plink, *tmp;
21436+
dece6358
AM
21437+ SiMustWriteLock(sb);
21438+
1facf9fc 21439+ sbinfo = au_sbi(sb);
21440+ AuDebugOn(!au_opt_test(au_mntflags(sb), PLINK));
e49829fe 21441+ AuDebugOn(au_plink_maint(sb, AuLock_NOPLM));
1facf9fc 21442+
21443+ plink_list = &sbinfo->si_plink.head;
21444+ /* no spin_lock since sbinfo is write-locked */
e49829fe 21445+ WARN(verbose && !list_empty(plink_list), "pseudo-link is not flushed");
1facf9fc 21446+ list_for_each_entry_safe(plink, tmp, plink_list, list)
21447+ do_put_plink(plink, 0);
21448+ INIT_LIST_HEAD(plink_list);
21449+}
21450+
e49829fe
JR
21451+void au_plink_clean(struct super_block *sb, int verbose)
21452+{
21453+ struct dentry *root;
21454+
21455+ root = sb->s_root;
21456+ aufs_write_lock(root);
21457+ if (au_opt_test(au_mntflags(sb), PLINK))
21458+ au_plink_put(sb, verbose);
21459+ aufs_write_unlock(root);
21460+}
21461+
1facf9fc 21462+/* free the plinks on a branch specified by @br_id */
21463+void au_plink_half_refresh(struct super_block *sb, aufs_bindex_t br_id)
21464+{
21465+ struct au_sbinfo *sbinfo;
21466+ struct list_head *plink_list;
21467+ struct pseudo_link *plink, *tmp;
21468+ struct inode *inode;
21469+ aufs_bindex_t bstart, bend, bindex;
21470+ unsigned char do_put;
21471+
dece6358
AM
21472+ SiMustWriteLock(sb);
21473+
1facf9fc 21474+ sbinfo = au_sbi(sb);
21475+ AuDebugOn(!au_opt_test(au_mntflags(sb), PLINK));
e49829fe 21476+ AuDebugOn(au_plink_maint(sb, AuLock_NOPLM));
1facf9fc 21477+
21478+ plink_list = &sbinfo->si_plink.head;
21479+ /* no spin_lock since sbinfo is write-locked */
21480+ list_for_each_entry_safe(plink, tmp, plink_list, list) {
21481+ do_put = 0;
21482+ inode = au_igrab(plink->inode);
21483+ ii_write_lock_child(inode);
21484+ bstart = au_ibstart(inode);
21485+ bend = au_ibend(inode);
21486+ if (bstart >= 0) {
21487+ for (bindex = bstart; bindex <= bend; bindex++) {
21488+ if (!au_h_iptr(inode, bindex)
21489+ || au_ii_br_id(inode, bindex) != br_id)
21490+ continue;
21491+ au_set_h_iptr(inode, bindex, NULL, 0);
21492+ do_put = 1;
21493+ break;
21494+ }
21495+ } else
21496+ do_put_plink(plink, 1);
21497+
dece6358
AM
21498+ if (do_put) {
21499+ for (bindex = bstart; bindex <= bend; bindex++)
21500+ if (au_h_iptr(inode, bindex)) {
21501+ do_put = 0;
21502+ break;
21503+ }
21504+ if (do_put)
21505+ do_put_plink(plink, 1);
21506+ }
21507+ ii_write_unlock(inode);
21508+ iput(inode);
21509+ }
21510+}
7f207e10
AM
21511diff -urN /usr/share/empty/fs/aufs/poll.c linux/fs/aufs/poll.c
21512--- /usr/share/empty/fs/aufs/poll.c 1970-01-01 01:00:00.000000000 +0100
2dfbb274 21513+++ linux/fs/aufs/poll.c 2012-08-26 08:39:00.763841498 +0200
dece6358
AM
21514@@ -0,0 +1,56 @@
21515+/*
f6c5ef8b 21516+ * Copyright (C) 2005-2012 Junjiro R. Okajima
dece6358
AM
21517+ *
21518+ * This program, aufs is free software; you can redistribute it and/or modify
21519+ * it under the terms of the GNU General Public License as published by
21520+ * the Free Software Foundation; either version 2 of the License, or
21521+ * (at your option) any later version.
21522+ *
21523+ * This program is distributed in the hope that it will be useful,
21524+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
21525+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21526+ * GNU General Public License for more details.
21527+ *
21528+ * You should have received a copy of the GNU General Public License
21529+ * along with this program; if not, write to the Free Software
21530+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
21531+ */
21532+
1308ab2a 21533+/*
21534+ * poll operation
21535+ * There is only one filesystem which implements ->poll operation, currently.
21536+ */
21537+
21538+#include "aufs.h"
21539+
21540+unsigned int aufs_poll(struct file *file, poll_table *wait)
21541+{
21542+ unsigned int mask;
21543+ int err;
21544+ struct file *h_file;
21545+ struct dentry *dentry;
21546+ struct super_block *sb;
21547+
21548+ /* We should pretend an error happened. */
21549+ mask = POLLERR /* | POLLIN | POLLOUT */;
21550+ dentry = file->f_dentry;
21551+ sb = dentry->d_sb;
e49829fe 21552+ si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLMW);
1308ab2a 21553+ err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/0);
21554+ if (unlikely(err))
21555+ goto out;
21556+
21557+ /* it is not an error if h_file has no operation */
21558+ mask = DEFAULT_POLLMASK;
4a4d8108 21559+ h_file = au_hf_top(file);
1308ab2a 21560+ if (h_file->f_op && h_file->f_op->poll)
21561+ mask = h_file->f_op->poll(h_file, wait);
21562+
21563+ di_read_unlock(dentry, AuLock_IR);
21564+ fi_read_unlock(file);
21565+
4f0767ce 21566+out:
1308ab2a 21567+ si_read_unlock(sb);
21568+ AuTraceErr((int)mask);
21569+ return mask;
21570+}
7f207e10
AM
21571diff -urN /usr/share/empty/fs/aufs/procfs.c linux/fs/aufs/procfs.c
21572--- /usr/share/empty/fs/aufs/procfs.c 1970-01-01 01:00:00.000000000 +0100
2dfbb274 21573+++ linux/fs/aufs/procfs.c 2012-08-26 08:39:00.763841498 +0200
53392da6 21574@@ -0,0 +1,170 @@
e49829fe 21575+/*
f6c5ef8b 21576+ * Copyright (C) 2010-2012 Junjiro R. Okajima
e49829fe
JR
21577+ *
21578+ * This program, aufs is free software; you can redistribute it and/or modify
21579+ * it under the terms of the GNU General Public License as published by
21580+ * the Free Software Foundation; either version 2 of the License, or
21581+ * (at your option) any later version.
21582+ *
21583+ * This program is distributed in the hope that it will be useful,
21584+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
21585+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21586+ * GNU General Public License for more details.
21587+ *
21588+ * You should have received a copy of the GNU General Public License
21589+ * along with this program; if not, write to the Free Software
21590+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
21591+ */
21592+
21593+/*
21594+ * procfs interfaces
21595+ */
21596+
21597+#include <linux/proc_fs.h>
21598+#include "aufs.h"
21599+
21600+static int au_procfs_plm_release(struct inode *inode, struct file *file)
21601+{
21602+ struct au_sbinfo *sbinfo;
21603+
21604+ sbinfo = file->private_data;
21605+ if (sbinfo) {
21606+ au_plink_maint_leave(sbinfo);
21607+ kobject_put(&sbinfo->si_kobj);
21608+ }
21609+
21610+ return 0;
21611+}
21612+
21613+static void au_procfs_plm_write_clean(struct file *file)
21614+{
21615+ struct au_sbinfo *sbinfo;
21616+
21617+ sbinfo = file->private_data;
21618+ if (sbinfo)
21619+ au_plink_clean(sbinfo->si_sb, /*verbose*/0);
21620+}
21621+
21622+static int au_procfs_plm_write_si(struct file *file, unsigned long id)
21623+{
21624+ int err;
21625+ struct super_block *sb;
21626+ struct au_sbinfo *sbinfo;
21627+
21628+ err = -EBUSY;
21629+ if (unlikely(file->private_data))
21630+ goto out;
21631+
21632+ sb = NULL;
53392da6 21633+ /* don't use au_sbilist_lock() here */
e49829fe
JR
21634+ spin_lock(&au_sbilist.spin);
21635+ list_for_each_entry(sbinfo, &au_sbilist.head, si_list)
21636+ if (id == sysaufs_si_id(sbinfo)) {
21637+ kobject_get(&sbinfo->si_kobj);
21638+ sb = sbinfo->si_sb;
21639+ break;
21640+ }
21641+ spin_unlock(&au_sbilist.spin);
21642+
21643+ err = -EINVAL;
21644+ if (unlikely(!sb))
21645+ goto out;
21646+
21647+ err = au_plink_maint_enter(sb);
21648+ if (!err)
21649+ /* keep kobject_get() */
21650+ file->private_data = sbinfo;
21651+ else
21652+ kobject_put(&sbinfo->si_kobj);
21653+out:
21654+ return err;
21655+}
21656+
21657+/*
21658+ * Accept a valid "si=xxxx" only.
21659+ * Once it is accepted successfully, accept "clean" too.
21660+ */
21661+static ssize_t au_procfs_plm_write(struct file *file, const char __user *ubuf,
21662+ size_t count, loff_t *ppos)
21663+{
21664+ ssize_t err;
21665+ unsigned long id;
21666+ /* last newline is allowed */
21667+ char buf[3 + sizeof(unsigned long) * 2 + 1];
21668+
21669+ err = -EACCES;
21670+ if (unlikely(!capable(CAP_SYS_ADMIN)))
21671+ goto out;
21672+
21673+ err = -EINVAL;
21674+ if (unlikely(count > sizeof(buf)))
21675+ goto out;
21676+
21677+ err = copy_from_user(buf, ubuf, count);
21678+ if (unlikely(err)) {
21679+ err = -EFAULT;
21680+ goto out;
21681+ }
21682+ buf[count] = 0;
21683+
21684+ err = -EINVAL;
21685+ if (!strcmp("clean", buf)) {
21686+ au_procfs_plm_write_clean(file);
21687+ goto out_success;
21688+ } else if (unlikely(strncmp("si=", buf, 3)))
21689+ goto out;
21690+
9dbd164d 21691+ err = kstrtoul(buf + 3, 16, &id);
e49829fe
JR
21692+ if (unlikely(err))
21693+ goto out;
21694+
21695+ err = au_procfs_plm_write_si(file, id);
21696+ if (unlikely(err))
21697+ goto out;
21698+
21699+out_success:
21700+ err = count; /* success */
21701+out:
21702+ return err;
21703+}
21704+
21705+static const struct file_operations au_procfs_plm_fop = {
21706+ .write = au_procfs_plm_write,
21707+ .release = au_procfs_plm_release,
21708+ .owner = THIS_MODULE
21709+};
21710+
21711+/* ---------------------------------------------------------------------- */
21712+
21713+static struct proc_dir_entry *au_procfs_dir;
21714+
21715+void au_procfs_fin(void)
21716+{
21717+ remove_proc_entry(AUFS_PLINK_MAINT_NAME, au_procfs_dir);
21718+ remove_proc_entry(AUFS_PLINK_MAINT_DIR, NULL);
21719+}
21720+
21721+int __init au_procfs_init(void)
21722+{
21723+ int err;
21724+ struct proc_dir_entry *entry;
21725+
21726+ err = -ENOMEM;
21727+ au_procfs_dir = proc_mkdir(AUFS_PLINK_MAINT_DIR, NULL);
21728+ if (unlikely(!au_procfs_dir))
21729+ goto out;
21730+
21731+ entry = proc_create(AUFS_PLINK_MAINT_NAME, S_IFREG | S_IWUSR,
21732+ au_procfs_dir, &au_procfs_plm_fop);
21733+ if (unlikely(!entry))
21734+ goto out_dir;
21735+
21736+ err = 0;
21737+ goto out; /* success */
21738+
21739+
21740+out_dir:
21741+ remove_proc_entry(AUFS_PLINK_MAINT_DIR, NULL);
21742+out:
21743+ return err;
21744+}
7f207e10
AM
21745diff -urN /usr/share/empty/fs/aufs/rdu.c linux/fs/aufs/rdu.c
21746--- /usr/share/empty/fs/aufs/rdu.c 1970-01-01 01:00:00.000000000 +0100
2dfbb274 21747+++ linux/fs/aufs/rdu.c 2012-08-26 08:39:00.763841498 +0200
92d182d2 21748@@ -0,0 +1,384 @@
1308ab2a 21749+/*
f6c5ef8b 21750+ * Copyright (C) 2005-2012 Junjiro R. Okajima
1308ab2a 21751+ *
21752+ * This program, aufs is free software; you can redistribute it and/or modify
21753+ * it under the terms of the GNU General Public License as published by
21754+ * the Free Software Foundation; either version 2 of the License, or
21755+ * (at your option) any later version.
21756+ *
21757+ * This program is distributed in the hope that it will be useful,
21758+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
21759+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21760+ * GNU General Public License for more details.
21761+ *
21762+ * You should have received a copy of the GNU General Public License
21763+ * along with this program; if not, write to the Free Software
21764+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
21765+ */
21766+
21767+/*
21768+ * readdir in userspace.
21769+ */
21770+
b752ccd1 21771+#include <linux/compat.h>
4a4d8108 21772+#include <linux/fs_stack.h>
1308ab2a 21773+#include <linux/security.h>
1308ab2a 21774+#include "aufs.h"
21775+
21776+/* bits for struct aufs_rdu.flags */
21777+#define AuRdu_CALLED 1
21778+#define AuRdu_CONT (1 << 1)
21779+#define AuRdu_FULL (1 << 2)
21780+#define au_ftest_rdu(flags, name) ((flags) & AuRdu_##name)
7f207e10
AM
21781+#define au_fset_rdu(flags, name) \
21782+ do { (flags) |= AuRdu_##name; } while (0)
21783+#define au_fclr_rdu(flags, name) \
21784+ do { (flags) &= ~AuRdu_##name; } while (0)
1308ab2a 21785+
21786+struct au_rdu_arg {
21787+ struct aufs_rdu *rdu;
21788+ union au_rdu_ent_ul ent;
21789+ unsigned long end;
21790+
21791+ struct super_block *sb;
21792+ int err;
21793+};
21794+
21795+static int au_rdu_fill(void *__arg, const char *name, int nlen,
21796+ loff_t offset, u64 h_ino, unsigned int d_type)
21797+{
21798+ int err, len;
21799+ struct au_rdu_arg *arg = __arg;
21800+ struct aufs_rdu *rdu = arg->rdu;
21801+ struct au_rdu_ent ent;
21802+
21803+ err = 0;
21804+ arg->err = 0;
21805+ au_fset_rdu(rdu->cookie.flags, CALLED);
21806+ len = au_rdu_len(nlen);
21807+ if (arg->ent.ul + len < arg->end) {
21808+ ent.ino = h_ino;
21809+ ent.bindex = rdu->cookie.bindex;
21810+ ent.type = d_type;
21811+ ent.nlen = nlen;
4a4d8108
AM
21812+ if (unlikely(nlen > AUFS_MAX_NAMELEN))
21813+ ent.type = DT_UNKNOWN;
1308ab2a 21814+
9dbd164d 21815+ /* unnecessary to support mmap_sem since this is a dir */
1308ab2a 21816+ err = -EFAULT;
21817+ if (copy_to_user(arg->ent.e, &ent, sizeof(ent)))
21818+ goto out;
21819+ if (copy_to_user(arg->ent.e->name, name, nlen))
21820+ goto out;
21821+ /* the terminating NULL */
21822+ if (__put_user(0, arg->ent.e->name + nlen))
21823+ goto out;
21824+ err = 0;
21825+ /* AuDbg("%p, %.*s\n", arg->ent.p, nlen, name); */
21826+ arg->ent.ul += len;
21827+ rdu->rent++;
21828+ } else {
21829+ err = -EFAULT;
21830+ au_fset_rdu(rdu->cookie.flags, FULL);
21831+ rdu->full = 1;
21832+ rdu->tail = arg->ent;
21833+ }
21834+
4f0767ce 21835+out:
1308ab2a 21836+ /* AuTraceErr(err); */
21837+ return err;
21838+}
21839+
21840+static int au_rdu_do(struct file *h_file, struct au_rdu_arg *arg)
21841+{
21842+ int err;
21843+ loff_t offset;
21844+ struct au_rdu_cookie *cookie = &arg->rdu->cookie;
21845+
92d182d2 21846+ /* we don't have to care (FMODE_32BITHASH | FMODE_64BITHASH) for ext4 */
1308ab2a 21847+ offset = vfsub_llseek(h_file, cookie->h_pos, SEEK_SET);
21848+ err = offset;
21849+ if (unlikely(offset != cookie->h_pos))
21850+ goto out;
21851+
21852+ err = 0;
21853+ do {
21854+ arg->err = 0;
21855+ au_fclr_rdu(cookie->flags, CALLED);
21856+ /* smp_mb(); */
21857+ err = vfsub_readdir(h_file, au_rdu_fill, arg);
21858+ if (err >= 0)
21859+ err = arg->err;
21860+ } while (!err
21861+ && au_ftest_rdu(cookie->flags, CALLED)
21862+ && !au_ftest_rdu(cookie->flags, FULL));
21863+ cookie->h_pos = h_file->f_pos;
21864+
4f0767ce 21865+out:
1308ab2a 21866+ AuTraceErr(err);
21867+ return err;
21868+}
21869+
21870+static int au_rdu(struct file *file, struct aufs_rdu *rdu)
21871+{
21872+ int err;
21873+ aufs_bindex_t bend;
21874+ struct au_rdu_arg arg;
21875+ struct dentry *dentry;
21876+ struct inode *inode;
21877+ struct file *h_file;
21878+ struct au_rdu_cookie *cookie = &rdu->cookie;
21879+
21880+ err = !access_ok(VERIFY_WRITE, rdu->ent.e, rdu->sz);
21881+ if (unlikely(err)) {
21882+ err = -EFAULT;
21883+ AuTraceErr(err);
21884+ goto out;
21885+ }
21886+ rdu->rent = 0;
21887+ rdu->tail = rdu->ent;
21888+ rdu->full = 0;
21889+ arg.rdu = rdu;
21890+ arg.ent = rdu->ent;
21891+ arg.end = arg.ent.ul;
21892+ arg.end += rdu->sz;
21893+
21894+ err = -ENOTDIR;
21895+ if (unlikely(!file->f_op || !file->f_op->readdir))
21896+ goto out;
21897+
21898+ err = security_file_permission(file, MAY_READ);
21899+ AuTraceErr(err);
21900+ if (unlikely(err))
21901+ goto out;
21902+
21903+ dentry = file->f_dentry;
21904+ inode = dentry->d_inode;
21905+#if 1
21906+ mutex_lock(&inode->i_mutex);
21907+#else
21908+ err = mutex_lock_killable(&inode->i_mutex);
21909+ AuTraceErr(err);
21910+ if (unlikely(err))
21911+ goto out;
21912+#endif
1308ab2a 21913+
21914+ arg.sb = inode->i_sb;
e49829fe
JR
21915+ err = si_read_lock(arg.sb, AuLock_FLUSH | AuLock_NOPLM);
21916+ if (unlikely(err))
21917+ goto out_mtx;
027c5e7a
AM
21918+ err = au_alive_dir(dentry);
21919+ if (unlikely(err))
21920+ goto out_si;
e49829fe 21921+ /* todo: reval? */
1308ab2a 21922+ fi_read_lock(file);
21923+
21924+ err = -EAGAIN;
21925+ if (unlikely(au_ftest_rdu(cookie->flags, CONT)
21926+ && cookie->generation != au_figen(file)))
21927+ goto out_unlock;
21928+
21929+ err = 0;
21930+ if (!rdu->blk) {
21931+ rdu->blk = au_sbi(arg.sb)->si_rdblk;
21932+ if (!rdu->blk)
21933+ rdu->blk = au_dir_size(file, /*dentry*/NULL);
21934+ }
21935+ bend = au_fbstart(file);
21936+ if (cookie->bindex < bend)
21937+ cookie->bindex = bend;
4a4d8108 21938+ bend = au_fbend_dir(file);
1308ab2a 21939+ /* AuDbg("b%d, b%d\n", cookie->bindex, bend); */
21940+ for (; !err && cookie->bindex <= bend;
21941+ cookie->bindex++, cookie->h_pos = 0) {
4a4d8108 21942+ h_file = au_hf_dir(file, cookie->bindex);
1308ab2a 21943+ if (!h_file)
21944+ continue;
21945+
21946+ au_fclr_rdu(cookie->flags, FULL);
21947+ err = au_rdu_do(h_file, &arg);
21948+ AuTraceErr(err);
21949+ if (unlikely(au_ftest_rdu(cookie->flags, FULL) || err))
21950+ break;
21951+ }
21952+ AuDbg("rent %llu\n", rdu->rent);
21953+
21954+ if (!err && !au_ftest_rdu(cookie->flags, CONT)) {
21955+ rdu->shwh = !!au_opt_test(au_sbi(arg.sb)->si_mntflags, SHWH);
21956+ au_fset_rdu(cookie->flags, CONT);
21957+ cookie->generation = au_figen(file);
21958+ }
21959+
21960+ ii_read_lock_child(inode);
21961+ fsstack_copy_attr_atime(inode, au_h_iptr(inode, au_ibstart(inode)));
21962+ ii_read_unlock(inode);
21963+
4f0767ce 21964+out_unlock:
1308ab2a 21965+ fi_read_unlock(file);
027c5e7a 21966+out_si:
1308ab2a 21967+ si_read_unlock(arg.sb);
4f0767ce 21968+out_mtx:
1308ab2a 21969+ mutex_unlock(&inode->i_mutex);
4f0767ce 21970+out:
1308ab2a 21971+ AuTraceErr(err);
21972+ return err;
21973+}
21974+
21975+static int au_rdu_ino(struct file *file, struct aufs_rdu *rdu)
21976+{
21977+ int err;
21978+ ino_t ino;
21979+ unsigned long long nent;
21980+ union au_rdu_ent_ul *u;
21981+ struct au_rdu_ent ent;
21982+ struct super_block *sb;
21983+
21984+ err = 0;
21985+ nent = rdu->nent;
21986+ u = &rdu->ent;
21987+ sb = file->f_dentry->d_sb;
21988+ si_read_lock(sb, AuLock_FLUSH);
21989+ while (nent-- > 0) {
9dbd164d 21990+ /* unnecessary to support mmap_sem since this is a dir */
1308ab2a 21991+ err = copy_from_user(&ent, u->e, sizeof(ent));
4a4d8108
AM
21992+ if (!err)
21993+ err = !access_ok(VERIFY_WRITE, &u->e->ino, sizeof(ino));
1308ab2a 21994+ if (unlikely(err)) {
21995+ err = -EFAULT;
21996+ AuTraceErr(err);
21997+ break;
21998+ }
21999+
22000+ /* AuDbg("b%d, i%llu\n", ent.bindex, ent.ino); */
22001+ if (!ent.wh)
22002+ err = au_ino(sb, ent.bindex, ent.ino, ent.type, &ino);
22003+ else
22004+ err = au_wh_ino(sb, ent.bindex, ent.ino, ent.type,
22005+ &ino);
22006+ if (unlikely(err)) {
22007+ AuTraceErr(err);
22008+ break;
22009+ }
22010+
22011+ err = __put_user(ino, &u->e->ino);
22012+ if (unlikely(err)) {
22013+ err = -EFAULT;
22014+ AuTraceErr(err);
22015+ break;
22016+ }
22017+ u->ul += au_rdu_len(ent.nlen);
22018+ }
22019+ si_read_unlock(sb);
22020+
22021+ return err;
22022+}
22023+
22024+/* ---------------------------------------------------------------------- */
22025+
22026+static int au_rdu_verify(struct aufs_rdu *rdu)
22027+{
b752ccd1 22028+ AuDbg("rdu{%llu, %p, %u | %u | %llu, %u, %u | "
1308ab2a 22029+ "%llu, b%d, 0x%x, g%u}\n",
b752ccd1 22030+ rdu->sz, rdu->ent.e, rdu->verify[AufsCtlRduV_SZ],
1308ab2a 22031+ rdu->blk,
22032+ rdu->rent, rdu->shwh, rdu->full,
22033+ rdu->cookie.h_pos, rdu->cookie.bindex, rdu->cookie.flags,
22034+ rdu->cookie.generation);
dece6358 22035+
b752ccd1 22036+ if (rdu->verify[AufsCtlRduV_SZ] == sizeof(*rdu))
1308ab2a 22037+ return 0;
dece6358 22038+
b752ccd1
AM
22039+ AuDbg("%u:%u\n",
22040+ rdu->verify[AufsCtlRduV_SZ], (unsigned int)sizeof(*rdu));
1308ab2a 22041+ return -EINVAL;
22042+}
22043+
22044+long au_rdu_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
dece6358 22045+{
1308ab2a 22046+ long err, e;
22047+ struct aufs_rdu rdu;
22048+ void __user *p = (void __user *)arg;
dece6358 22049+
1308ab2a 22050+ err = copy_from_user(&rdu, p, sizeof(rdu));
22051+ if (unlikely(err)) {
22052+ err = -EFAULT;
22053+ AuTraceErr(err);
22054+ goto out;
22055+ }
22056+ err = au_rdu_verify(&rdu);
dece6358
AM
22057+ if (unlikely(err))
22058+ goto out;
22059+
1308ab2a 22060+ switch (cmd) {
22061+ case AUFS_CTL_RDU:
22062+ err = au_rdu(file, &rdu);
22063+ if (unlikely(err))
22064+ break;
dece6358 22065+
1308ab2a 22066+ e = copy_to_user(p, &rdu, sizeof(rdu));
22067+ if (unlikely(e)) {
22068+ err = -EFAULT;
22069+ AuTraceErr(err);
22070+ }
22071+ break;
22072+ case AUFS_CTL_RDU_INO:
22073+ err = au_rdu_ino(file, &rdu);
22074+ break;
22075+
22076+ default:
4a4d8108 22077+ /* err = -ENOTTY; */
1308ab2a 22078+ err = -EINVAL;
22079+ }
dece6358 22080+
4f0767ce 22081+out:
1308ab2a 22082+ AuTraceErr(err);
22083+ return err;
1facf9fc 22084+}
b752ccd1
AM
22085+
22086+#ifdef CONFIG_COMPAT
22087+long au_rdu_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
22088+{
22089+ long err, e;
22090+ struct aufs_rdu rdu;
22091+ void __user *p = compat_ptr(arg);
22092+
22093+ /* todo: get_user()? */
22094+ err = copy_from_user(&rdu, p, sizeof(rdu));
22095+ if (unlikely(err)) {
22096+ err = -EFAULT;
22097+ AuTraceErr(err);
22098+ goto out;
22099+ }
22100+ rdu.ent.e = compat_ptr(rdu.ent.ul);
22101+ err = au_rdu_verify(&rdu);
22102+ if (unlikely(err))
22103+ goto out;
22104+
22105+ switch (cmd) {
22106+ case AUFS_CTL_RDU:
22107+ err = au_rdu(file, &rdu);
22108+ if (unlikely(err))
22109+ break;
22110+
22111+ rdu.ent.ul = ptr_to_compat(rdu.ent.e);
22112+ rdu.tail.ul = ptr_to_compat(rdu.tail.e);
22113+ e = copy_to_user(p, &rdu, sizeof(rdu));
22114+ if (unlikely(e)) {
22115+ err = -EFAULT;
22116+ AuTraceErr(err);
22117+ }
22118+ break;
22119+ case AUFS_CTL_RDU_INO:
22120+ err = au_rdu_ino(file, &rdu);
22121+ break;
22122+
22123+ default:
22124+ /* err = -ENOTTY; */
22125+ err = -EINVAL;
22126+ }
22127+
4f0767ce 22128+out:
b752ccd1
AM
22129+ AuTraceErr(err);
22130+ return err;
22131+}
22132+#endif
7f207e10
AM
22133diff -urN /usr/share/empty/fs/aufs/rwsem.h linux/fs/aufs/rwsem.h
22134--- /usr/share/empty/fs/aufs/rwsem.h 1970-01-01 01:00:00.000000000 +0100
2dfbb274 22135+++ linux/fs/aufs/rwsem.h 2012-08-26 08:39:00.763841498 +0200
f6c5ef8b 22136@@ -0,0 +1,188 @@
1facf9fc 22137+/*
f6c5ef8b 22138+ * Copyright (C) 2005-2012 Junjiro R. Okajima
1facf9fc 22139+ *
22140+ * This program, aufs is free software; you can redistribute it and/or modify
22141+ * it under the terms of the GNU General Public License as published by
22142+ * the Free Software Foundation; either version 2 of the License, or
22143+ * (at your option) any later version.
dece6358
AM
22144+ *
22145+ * This program is distributed in the hope that it will be useful,
22146+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
22147+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22148+ * GNU General Public License for more details.
22149+ *
22150+ * You should have received a copy of the GNU General Public License
22151+ * along with this program; if not, write to the Free Software
22152+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 22153+ */
22154+
22155+/*
22156+ * simple read-write semaphore wrappers
22157+ */
22158+
22159+#ifndef __AUFS_RWSEM_H__
22160+#define __AUFS_RWSEM_H__
22161+
22162+#ifdef __KERNEL__
22163+
4a4d8108 22164+#include "debug.h"
dece6358
AM
22165+
22166+struct au_rwsem {
22167+ struct rw_semaphore rwsem;
22168+#ifdef CONFIG_AUFS_DEBUG
22169+ /* just for debugging, not almighty counter */
22170+ atomic_t rcnt, wcnt;
22171+#endif
22172+};
22173+
22174+#ifdef CONFIG_AUFS_DEBUG
22175+#define AuDbgCntInit(rw) do { \
22176+ atomic_set(&(rw)->rcnt, 0); \
22177+ atomic_set(&(rw)->wcnt, 0); \
22178+ smp_mb(); /* atomic set */ \
22179+} while (0)
22180+
e49829fe 22181+#define AuDbgRcntInc(rw) atomic_inc(&(rw)->rcnt)
dece6358 22182+#define AuDbgRcntDec(rw) WARN_ON(atomic_dec_return(&(rw)->rcnt) < 0)
e49829fe 22183+#define AuDbgWcntInc(rw) atomic_inc(&(rw)->wcnt)
dece6358
AM
22184+#define AuDbgWcntDec(rw) WARN_ON(atomic_dec_return(&(rw)->wcnt) < 0)
22185+#else
22186+#define AuDbgCntInit(rw) do {} while (0)
22187+#define AuDbgRcntInc(rw) do {} while (0)
22188+#define AuDbgRcntDec(rw) do {} while (0)
22189+#define AuDbgWcntInc(rw) do {} while (0)
22190+#define AuDbgWcntDec(rw) do {} while (0)
22191+#endif /* CONFIG_AUFS_DEBUG */
22192+
22193+/* to debug easier, do not make them inlined functions */
22194+#define AuRwMustNoWaiters(rw) AuDebugOn(!list_empty(&(rw)->rwsem.wait_list))
22195+/* rwsem_is_locked() is unusable */
22196+#define AuRwMustReadLock(rw) AuDebugOn(atomic_read(&(rw)->rcnt) <= 0)
22197+#define AuRwMustWriteLock(rw) AuDebugOn(atomic_read(&(rw)->wcnt) <= 0)
22198+#define AuRwMustAnyLock(rw) AuDebugOn(atomic_read(&(rw)->rcnt) <= 0 \
22199+ && atomic_read(&(rw)->wcnt) <= 0)
22200+#define AuRwDestroy(rw) AuDebugOn(atomic_read(&(rw)->rcnt) \
22201+ || atomic_read(&(rw)->wcnt))
22202+
e49829fe
JR
22203+#define au_rw_class(rw, key) lockdep_set_class(&(rw)->rwsem, key)
22204+
dece6358
AM
22205+static inline void au_rw_init(struct au_rwsem *rw)
22206+{
22207+ AuDbgCntInit(rw);
22208+ init_rwsem(&rw->rwsem);
22209+}
22210+
22211+static inline void au_rw_init_wlock(struct au_rwsem *rw)
22212+{
22213+ au_rw_init(rw);
22214+ down_write(&rw->rwsem);
22215+ AuDbgWcntInc(rw);
22216+}
22217+
22218+static inline void au_rw_init_wlock_nested(struct au_rwsem *rw,
22219+ unsigned int lsc)
22220+{
22221+ au_rw_init(rw);
22222+ down_write_nested(&rw->rwsem, lsc);
22223+ AuDbgWcntInc(rw);
22224+}
22225+
22226+static inline void au_rw_read_lock(struct au_rwsem *rw)
22227+{
22228+ down_read(&rw->rwsem);
22229+ AuDbgRcntInc(rw);
22230+}
22231+
22232+static inline void au_rw_read_lock_nested(struct au_rwsem *rw, unsigned int lsc)
22233+{
22234+ down_read_nested(&rw->rwsem, lsc);
22235+ AuDbgRcntInc(rw);
22236+}
22237+
22238+static inline void au_rw_read_unlock(struct au_rwsem *rw)
22239+{
22240+ AuRwMustReadLock(rw);
22241+ AuDbgRcntDec(rw);
22242+ up_read(&rw->rwsem);
22243+}
22244+
22245+static inline void au_rw_dgrade_lock(struct au_rwsem *rw)
22246+{
22247+ AuRwMustWriteLock(rw);
22248+ AuDbgRcntInc(rw);
22249+ AuDbgWcntDec(rw);
22250+ downgrade_write(&rw->rwsem);
22251+}
22252+
22253+static inline void au_rw_write_lock(struct au_rwsem *rw)
22254+{
22255+ down_write(&rw->rwsem);
22256+ AuDbgWcntInc(rw);
22257+}
22258+
22259+static inline void au_rw_write_lock_nested(struct au_rwsem *rw,
22260+ unsigned int lsc)
22261+{
22262+ down_write_nested(&rw->rwsem, lsc);
22263+ AuDbgWcntInc(rw);
22264+}
1facf9fc 22265+
dece6358
AM
22266+static inline void au_rw_write_unlock(struct au_rwsem *rw)
22267+{
22268+ AuRwMustWriteLock(rw);
22269+ AuDbgWcntDec(rw);
22270+ up_write(&rw->rwsem);
22271+}
22272+
22273+/* why is not _nested version defined */
22274+static inline int au_rw_read_trylock(struct au_rwsem *rw)
22275+{
22276+ int ret = down_read_trylock(&rw->rwsem);
22277+ if (ret)
22278+ AuDbgRcntInc(rw);
22279+ return ret;
22280+}
22281+
22282+static inline int au_rw_write_trylock(struct au_rwsem *rw)
22283+{
22284+ int ret = down_write_trylock(&rw->rwsem);
22285+ if (ret)
22286+ AuDbgWcntInc(rw);
22287+ return ret;
22288+}
22289+
22290+#undef AuDbgCntInit
22291+#undef AuDbgRcntInc
22292+#undef AuDbgRcntDec
22293+#undef AuDbgWcntInc
22294+#undef AuDbgWcntDec
1facf9fc 22295+
22296+#define AuSimpleLockRwsemFuncs(prefix, param, rwsem) \
22297+static inline void prefix##_read_lock(param) \
dece6358 22298+{ au_rw_read_lock(rwsem); } \
1facf9fc 22299+static inline void prefix##_write_lock(param) \
dece6358 22300+{ au_rw_write_lock(rwsem); } \
1facf9fc 22301+static inline int prefix##_read_trylock(param) \
dece6358 22302+{ return au_rw_read_trylock(rwsem); } \
1facf9fc 22303+static inline int prefix##_write_trylock(param) \
dece6358 22304+{ return au_rw_write_trylock(rwsem); }
1facf9fc 22305+/* why is not _nested version defined */
22306+/* static inline void prefix##_read_trylock_nested(param, lsc)
dece6358 22307+{ au_rw_read_trylock_nested(rwsem, lsc)); }
1facf9fc 22308+static inline void prefix##_write_trylock_nestd(param, lsc)
dece6358 22309+{ au_rw_write_trylock_nested(rwsem, lsc); } */
1facf9fc 22310+
22311+#define AuSimpleUnlockRwsemFuncs(prefix, param, rwsem) \
22312+static inline void prefix##_read_unlock(param) \
dece6358 22313+{ au_rw_read_unlock(rwsem); } \
1facf9fc 22314+static inline void prefix##_write_unlock(param) \
dece6358 22315+{ au_rw_write_unlock(rwsem); } \
1facf9fc 22316+static inline void prefix##_downgrade_lock(param) \
dece6358 22317+{ au_rw_dgrade_lock(rwsem); }
1facf9fc 22318+
22319+#define AuSimpleRwsemFuncs(prefix, param, rwsem) \
22320+ AuSimpleLockRwsemFuncs(prefix, param, rwsem) \
22321+ AuSimpleUnlockRwsemFuncs(prefix, param, rwsem)
22322+
22323+#endif /* __KERNEL__ */
22324+#endif /* __AUFS_RWSEM_H__ */
7f207e10
AM
22325diff -urN /usr/share/empty/fs/aufs/sbinfo.c linux/fs/aufs/sbinfo.c
22326--- /usr/share/empty/fs/aufs/sbinfo.c 1970-01-01 01:00:00.000000000 +0100
2dfbb274 22327+++ linux/fs/aufs/sbinfo.c 2012-08-26 08:39:00.763841498 +0200
f6c5ef8b 22328@@ -0,0 +1,343 @@
1facf9fc 22329+/*
f6c5ef8b 22330+ * Copyright (C) 2005-2012 Junjiro R. Okajima
1facf9fc 22331+ *
22332+ * This program, aufs is free software; you can redistribute it and/or modify
22333+ * it under the terms of the GNU General Public License as published by
22334+ * the Free Software Foundation; either version 2 of the License, or
22335+ * (at your option) any later version.
dece6358
AM
22336+ *
22337+ * This program is distributed in the hope that it will be useful,
22338+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
22339+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22340+ * GNU General Public License for more details.
22341+ *
22342+ * You should have received a copy of the GNU General Public License
22343+ * along with this program; if not, write to the Free Software
22344+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 22345+ */
22346+
22347+/*
22348+ * superblock private data
22349+ */
22350+
22351+#include "aufs.h"
22352+
22353+/*
22354+ * they are necessary regardless sysfs is disabled.
22355+ */
22356+void au_si_free(struct kobject *kobj)
22357+{
22358+ struct au_sbinfo *sbinfo;
b752ccd1 22359+ char *locked __maybe_unused; /* debug only */
1facf9fc 22360+
22361+ sbinfo = container_of(kobj, struct au_sbinfo, si_kobj);
22362+ AuDebugOn(!list_empty(&sbinfo->si_plink.head));
e49829fe 22363+ AuDebugOn(atomic_read(&sbinfo->si_nowait.nw_len));
1facf9fc 22364+
e49829fe 22365+ au_rw_write_lock(&sbinfo->si_rwsem);
1facf9fc 22366+ au_br_free(sbinfo);
e49829fe 22367+ au_rw_write_unlock(&sbinfo->si_rwsem);
b752ccd1
AM
22368+
22369+ AuDebugOn(radix_tree_gang_lookup
22370+ (&sbinfo->au_si_pid.tree, (void **)&locked,
22371+ /*first_index*/PID_MAX_DEFAULT - 1,
22372+ /*max_items*/sizeof(locked)/sizeof(*locked)));
22373+
1facf9fc 22374+ kfree(sbinfo->si_branch);
b752ccd1 22375+ kfree(sbinfo->au_si_pid.bitmap);
1facf9fc 22376+ mutex_destroy(&sbinfo->si_xib_mtx);
dece6358 22377+ AuRwDestroy(&sbinfo->si_rwsem);
1facf9fc 22378+
22379+ kfree(sbinfo);
22380+}
22381+
22382+int au_si_alloc(struct super_block *sb)
22383+{
22384+ int err;
22385+ struct au_sbinfo *sbinfo;
e49829fe 22386+ static struct lock_class_key aufs_si;
1facf9fc 22387+
22388+ err = -ENOMEM;
4a4d8108 22389+ sbinfo = kzalloc(sizeof(*sbinfo), GFP_NOFS);
1facf9fc 22390+ if (unlikely(!sbinfo))
22391+ goto out;
22392+
b752ccd1
AM
22393+ BUILD_BUG_ON(sizeof(unsigned long) !=
22394+ sizeof(*sbinfo->au_si_pid.bitmap));
22395+ sbinfo->au_si_pid.bitmap = kcalloc(BITS_TO_LONGS(PID_MAX_DEFAULT),
22396+ sizeof(*sbinfo->au_si_pid.bitmap),
22397+ GFP_NOFS);
22398+ if (unlikely(!sbinfo->au_si_pid.bitmap))
22399+ goto out_sbinfo;
22400+
1facf9fc 22401+ /* will be reallocated separately */
22402+ sbinfo->si_branch = kzalloc(sizeof(*sbinfo->si_branch), GFP_NOFS);
22403+ if (unlikely(!sbinfo->si_branch))
b752ccd1 22404+ goto out_pidmap;
1facf9fc 22405+
1facf9fc 22406+ err = sysaufs_si_init(sbinfo);
22407+ if (unlikely(err))
22408+ goto out_br;
22409+
22410+ au_nwt_init(&sbinfo->si_nowait);
dece6358 22411+ au_rw_init_wlock(&sbinfo->si_rwsem);
e49829fe 22412+ au_rw_class(&sbinfo->si_rwsem, &aufs_si);
b752ccd1
AM
22413+ spin_lock_init(&sbinfo->au_si_pid.tree_lock);
22414+ INIT_RADIX_TREE(&sbinfo->au_si_pid.tree, GFP_ATOMIC | __GFP_NOFAIL);
22415+
7f207e10 22416+ atomic_long_set(&sbinfo->si_ninodes, 0);
7f207e10
AM
22417+ atomic_long_set(&sbinfo->si_nfiles, 0);
22418+
1facf9fc 22419+ sbinfo->si_bend = -1;
1facf9fc 22420+
22421+ sbinfo->si_wbr_copyup = AuWbrCopyup_Def;
22422+ sbinfo->si_wbr_create = AuWbrCreate_Def;
4a4d8108
AM
22423+ sbinfo->si_wbr_copyup_ops = au_wbr_copyup_ops + sbinfo->si_wbr_copyup;
22424+ sbinfo->si_wbr_create_ops = au_wbr_create_ops + sbinfo->si_wbr_create;
1facf9fc 22425+
e49829fe 22426+ sbinfo->si_mntflags = au_opts_plink(AuOpt_Def);
1facf9fc 22427+
1facf9fc 22428+ mutex_init(&sbinfo->si_xib_mtx);
1facf9fc 22429+ sbinfo->si_xino_brid = -1;
22430+ /* leave si_xib_last_pindex and si_xib_next_bit */
22431+
e49829fe 22432+ sbinfo->si_rdcache = msecs_to_jiffies(AUFS_RDCACHE_DEF * MSEC_PER_SEC);
1facf9fc 22433+ sbinfo->si_rdblk = AUFS_RDBLK_DEF;
22434+ sbinfo->si_rdhash = AUFS_RDHASH_DEF;
22435+ sbinfo->si_dirwh = AUFS_DIRWH_DEF;
22436+
22437+ au_spl_init(&sbinfo->si_plink);
22438+ init_waitqueue_head(&sbinfo->si_plink_wq);
4a4d8108 22439+ spin_lock_init(&sbinfo->si_plink_maint_lock);
1facf9fc 22440+
22441+ /* leave other members for sysaufs and si_mnt. */
22442+ sbinfo->si_sb = sb;
22443+ sb->s_fs_info = sbinfo;
b752ccd1 22444+ si_pid_set(sb);
1facf9fc 22445+ au_debug_sbinfo_init(sbinfo);
22446+ return 0; /* success */
22447+
4f0767ce 22448+out_br:
1facf9fc 22449+ kfree(sbinfo->si_branch);
4f0767ce 22450+out_pidmap:
b752ccd1 22451+ kfree(sbinfo->au_si_pid.bitmap);
4f0767ce 22452+out_sbinfo:
1facf9fc 22453+ kfree(sbinfo);
4f0767ce 22454+out:
1facf9fc 22455+ return err;
22456+}
22457+
22458+int au_sbr_realloc(struct au_sbinfo *sbinfo, int nbr)
22459+{
22460+ int err, sz;
22461+ struct au_branch **brp;
22462+
dece6358
AM
22463+ AuRwMustWriteLock(&sbinfo->si_rwsem);
22464+
1facf9fc 22465+ err = -ENOMEM;
22466+ sz = sizeof(*brp) * (sbinfo->si_bend + 1);
22467+ if (unlikely(!sz))
22468+ sz = sizeof(*brp);
22469+ brp = au_kzrealloc(sbinfo->si_branch, sz, sizeof(*brp) * nbr, GFP_NOFS);
22470+ if (brp) {
22471+ sbinfo->si_branch = brp;
22472+ err = 0;
22473+ }
22474+
22475+ return err;
22476+}
22477+
22478+/* ---------------------------------------------------------------------- */
22479+
22480+unsigned int au_sigen_inc(struct super_block *sb)
22481+{
22482+ unsigned int gen;
22483+
dece6358
AM
22484+ SiMustWriteLock(sb);
22485+
1facf9fc 22486+ gen = ++au_sbi(sb)->si_generation;
22487+ au_update_digen(sb->s_root);
22488+ au_update_iigen(sb->s_root->d_inode);
22489+ sb->s_root->d_inode->i_version++;
22490+ return gen;
22491+}
22492+
22493+aufs_bindex_t au_new_br_id(struct super_block *sb)
22494+{
22495+ aufs_bindex_t br_id;
22496+ int i;
22497+ struct au_sbinfo *sbinfo;
22498+
dece6358
AM
22499+ SiMustWriteLock(sb);
22500+
1facf9fc 22501+ sbinfo = au_sbi(sb);
22502+ for (i = 0; i <= AUFS_BRANCH_MAX; i++) {
22503+ br_id = ++sbinfo->si_last_br_id;
7f207e10 22504+ AuDebugOn(br_id < 0);
1facf9fc 22505+ if (br_id && au_br_index(sb, br_id) < 0)
22506+ return br_id;
22507+ }
22508+
22509+ return -1;
22510+}
22511+
22512+/* ---------------------------------------------------------------------- */
22513+
e49829fe
JR
22514+/* it is ok that new 'nwt' tasks are appended while we are sleeping */
22515+int si_read_lock(struct super_block *sb, int flags)
22516+{
22517+ int err;
22518+
22519+ err = 0;
22520+ if (au_ftest_lock(flags, FLUSH))
22521+ au_nwt_flush(&au_sbi(sb)->si_nowait);
22522+
22523+ si_noflush_read_lock(sb);
22524+ err = au_plink_maint(sb, flags);
22525+ if (unlikely(err))
22526+ si_read_unlock(sb);
22527+
22528+ return err;
22529+}
22530+
22531+int si_write_lock(struct super_block *sb, int flags)
22532+{
22533+ int err;
22534+
22535+ if (au_ftest_lock(flags, FLUSH))
22536+ au_nwt_flush(&au_sbi(sb)->si_nowait);
22537+
22538+ si_noflush_write_lock(sb);
22539+ err = au_plink_maint(sb, flags);
22540+ if (unlikely(err))
22541+ si_write_unlock(sb);
22542+
22543+ return err;
22544+}
22545+
1facf9fc 22546+/* dentry and super_block lock. call at entry point */
e49829fe 22547+int aufs_read_lock(struct dentry *dentry, int flags)
1facf9fc 22548+{
e49829fe 22549+ int err;
027c5e7a 22550+ struct super_block *sb;
e49829fe 22551+
027c5e7a
AM
22552+ sb = dentry->d_sb;
22553+ err = si_read_lock(sb, flags);
22554+ if (unlikely(err))
22555+ goto out;
22556+
22557+ if (au_ftest_lock(flags, DW))
22558+ di_write_lock_child(dentry);
22559+ else
22560+ di_read_lock_child(dentry, flags);
22561+
22562+ if (au_ftest_lock(flags, GEN)) {
22563+ err = au_digen_test(dentry, au_sigen(sb));
22564+ AuDebugOn(!err && au_dbrange_test(dentry));
22565+ if (unlikely(err))
22566+ aufs_read_unlock(dentry, flags);
e49829fe
JR
22567+ }
22568+
027c5e7a 22569+out:
e49829fe 22570+ return err;
1facf9fc 22571+}
22572+
22573+void aufs_read_unlock(struct dentry *dentry, int flags)
22574+{
22575+ if (au_ftest_lock(flags, DW))
22576+ di_write_unlock(dentry);
22577+ else
22578+ di_read_unlock(dentry, flags);
22579+ si_read_unlock(dentry->d_sb);
22580+}
22581+
22582+void aufs_write_lock(struct dentry *dentry)
22583+{
e49829fe 22584+ si_write_lock(dentry->d_sb, AuLock_FLUSH | AuLock_NOPLMW);
1facf9fc 22585+ di_write_lock_child(dentry);
22586+}
22587+
22588+void aufs_write_unlock(struct dentry *dentry)
22589+{
22590+ di_write_unlock(dentry);
22591+ si_write_unlock(dentry->d_sb);
22592+}
22593+
e49829fe 22594+int aufs_read_and_write_lock2(struct dentry *d1, struct dentry *d2, int flags)
1facf9fc 22595+{
e49829fe 22596+ int err;
027c5e7a
AM
22597+ unsigned int sigen;
22598+ struct super_block *sb;
e49829fe 22599+
027c5e7a
AM
22600+ sb = d1->d_sb;
22601+ err = si_read_lock(sb, flags);
22602+ if (unlikely(err))
22603+ goto out;
22604+
22605+ di_write_lock2_child(d1, d2, au_ftest_lock(flags, DIR));
22606+
22607+ if (au_ftest_lock(flags, GEN)) {
22608+ sigen = au_sigen(sb);
22609+ err = au_digen_test(d1, sigen);
22610+ AuDebugOn(!err && au_dbrange_test(d1));
22611+ if (!err) {
22612+ err = au_digen_test(d2, sigen);
22613+ AuDebugOn(!err && au_dbrange_test(d2));
22614+ }
22615+ if (unlikely(err))
22616+ aufs_read_and_write_unlock2(d1, d2);
22617+ }
22618+
22619+out:
e49829fe 22620+ return err;
1facf9fc 22621+}
22622+
22623+void aufs_read_and_write_unlock2(struct dentry *d1, struct dentry *d2)
22624+{
22625+ di_write_unlock2(d1, d2);
22626+ si_read_unlock(d1->d_sb);
22627+}
b752ccd1
AM
22628+
22629+/* ---------------------------------------------------------------------- */
22630+
22631+int si_pid_test_slow(struct super_block *sb)
22632+{
22633+ void *p;
22634+
22635+ rcu_read_lock();
22636+ p = radix_tree_lookup(&au_sbi(sb)->au_si_pid.tree, current->pid);
22637+ rcu_read_unlock();
22638+
027c5e7a 22639+ return (long)!!p;
b752ccd1
AM
22640+}
22641+
22642+void si_pid_set_slow(struct super_block *sb)
22643+{
22644+ int err;
22645+ struct au_sbinfo *sbinfo;
22646+
22647+ AuDebugOn(si_pid_test_slow(sb));
22648+
22649+ sbinfo = au_sbi(sb);
22650+ err = radix_tree_preload(GFP_NOFS | __GFP_NOFAIL);
22651+ AuDebugOn(err);
22652+ spin_lock(&sbinfo->au_si_pid.tree_lock);
22653+ err = radix_tree_insert(&sbinfo->au_si_pid.tree, current->pid,
027c5e7a 22654+ /*any valid ptr*/sb);
b752ccd1
AM
22655+ spin_unlock(&sbinfo->au_si_pid.tree_lock);
22656+ AuDebugOn(err);
22657+ radix_tree_preload_end();
22658+}
22659+
22660+void si_pid_clr_slow(struct super_block *sb)
22661+{
22662+ void *p;
22663+ struct au_sbinfo *sbinfo;
22664+
22665+ AuDebugOn(!si_pid_test_slow(sb));
22666+
22667+ sbinfo = au_sbi(sb);
22668+ spin_lock(&sbinfo->au_si_pid.tree_lock);
22669+ p = radix_tree_delete(&sbinfo->au_si_pid.tree, current->pid);
22670+ spin_unlock(&sbinfo->au_si_pid.tree_lock);
b752ccd1 22671+}
7f207e10
AM
22672diff -urN /usr/share/empty/fs/aufs/spl.h linux/fs/aufs/spl.h
22673--- /usr/share/empty/fs/aufs/spl.h 1970-01-01 01:00:00.000000000 +0100
2dfbb274 22674+++ linux/fs/aufs/spl.h 2012-08-26 08:39:00.763841498 +0200
f6c5ef8b 22675@@ -0,0 +1,62 @@
1facf9fc 22676+/*
f6c5ef8b 22677+ * Copyright (C) 2005-2012 Junjiro R. Okajima
1facf9fc 22678+ *
22679+ * This program, aufs is free software; you can redistribute it and/or modify
22680+ * it under the terms of the GNU General Public License as published by
22681+ * the Free Software Foundation; either version 2 of the License, or
22682+ * (at your option) any later version.
dece6358
AM
22683+ *
22684+ * This program is distributed in the hope that it will be useful,
22685+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
22686+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22687+ * GNU General Public License for more details.
22688+ *
22689+ * You should have received a copy of the GNU General Public License
22690+ * along with this program; if not, write to the Free Software
22691+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 22692+ */
22693+
22694+/*
22695+ * simple list protected by a spinlock
22696+ */
22697+
22698+#ifndef __AUFS_SPL_H__
22699+#define __AUFS_SPL_H__
22700+
22701+#ifdef __KERNEL__
22702+
1facf9fc 22703+struct au_splhead {
22704+ spinlock_t spin;
22705+ struct list_head head;
22706+};
22707+
22708+static inline void au_spl_init(struct au_splhead *spl)
22709+{
22710+ spin_lock_init(&spl->spin);
22711+ INIT_LIST_HEAD(&spl->head);
22712+}
22713+
22714+static inline void au_spl_add(struct list_head *list, struct au_splhead *spl)
22715+{
22716+ spin_lock(&spl->spin);
22717+ list_add(list, &spl->head);
22718+ spin_unlock(&spl->spin);
22719+}
22720+
22721+static inline void au_spl_del(struct list_head *list, struct au_splhead *spl)
22722+{
22723+ spin_lock(&spl->spin);
22724+ list_del(list);
22725+ spin_unlock(&spl->spin);
22726+}
22727+
4a4d8108
AM
22728+static inline void au_spl_del_rcu(struct list_head *list,
22729+ struct au_splhead *spl)
22730+{
22731+ spin_lock(&spl->spin);
22732+ list_del_rcu(list);
22733+ spin_unlock(&spl->spin);
22734+}
22735+
1facf9fc 22736+#endif /* __KERNEL__ */
22737+#endif /* __AUFS_SPL_H__ */
7f207e10
AM
22738diff -urN /usr/share/empty/fs/aufs/super.c linux/fs/aufs/super.c
22739--- /usr/share/empty/fs/aufs/super.c 1970-01-01 01:00:00.000000000 +0100
b4510431 22740+++ linux/fs/aufs/super.c 2012-10-17 10:31:01.775814563 +0200
92d182d2 22741@@ -0,0 +1,962 @@
1facf9fc 22742+/*
f6c5ef8b 22743+ * Copyright (C) 2005-2012 Junjiro R. Okajima
1facf9fc 22744+ *
22745+ * This program, aufs is free software; you can redistribute it and/or modify
22746+ * it under the terms of the GNU General Public License as published by
22747+ * the Free Software Foundation; either version 2 of the License, or
22748+ * (at your option) any later version.
dece6358
AM
22749+ *
22750+ * This program is distributed in the hope that it will be useful,
22751+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
22752+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22753+ * GNU General Public License for more details.
22754+ *
22755+ * You should have received a copy of the GNU General Public License
22756+ * along with this program; if not, write to the Free Software
22757+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 22758+ */
22759+
22760+/*
22761+ * mount and super_block operations
22762+ */
22763+
f6c5ef8b 22764+#include <linux/mm.h>
dece6358 22765+#include <linux/module.h>
1facf9fc 22766+#include <linux/seq_file.h>
22767+#include <linux/statfs.h>
7f207e10
AM
22768+#include <linux/vmalloc.h>
22769+#include <linux/writeback.h>
1facf9fc 22770+#include "aufs.h"
22771+
22772+/*
22773+ * super_operations
22774+ */
22775+static struct inode *aufs_alloc_inode(struct super_block *sb __maybe_unused)
22776+{
22777+ struct au_icntnr *c;
22778+
22779+ c = au_cache_alloc_icntnr();
22780+ if (c) {
027c5e7a 22781+ au_icntnr_init(c);
1facf9fc 22782+ c->vfs_inode.i_version = 1; /* sigen(sb); */
22783+ c->iinfo.ii_hinode = NULL;
22784+ return &c->vfs_inode;
22785+ }
22786+ return NULL;
22787+}
22788+
027c5e7a
AM
22789+static void aufs_destroy_inode_cb(struct rcu_head *head)
22790+{
22791+ struct inode *inode = container_of(head, struct inode, i_rcu);
22792+
b4510431 22793+ INIT_HLIST_HEAD(&inode->i_dentry);
027c5e7a
AM
22794+ au_cache_free_icntnr(container_of(inode, struct au_icntnr, vfs_inode));
22795+}
22796+
1facf9fc 22797+static void aufs_destroy_inode(struct inode *inode)
22798+{
22799+ au_iinfo_fin(inode);
027c5e7a 22800+ call_rcu(&inode->i_rcu, aufs_destroy_inode_cb);
1facf9fc 22801+}
22802+
22803+struct inode *au_iget_locked(struct super_block *sb, ino_t ino)
22804+{
22805+ struct inode *inode;
22806+ int err;
22807+
22808+ inode = iget_locked(sb, ino);
22809+ if (unlikely(!inode)) {
22810+ inode = ERR_PTR(-ENOMEM);
22811+ goto out;
22812+ }
22813+ if (!(inode->i_state & I_NEW))
22814+ goto out;
22815+
22816+ err = au_xigen_new(inode);
22817+ if (!err)
22818+ err = au_iinfo_init(inode);
22819+ if (!err)
22820+ inode->i_version++;
22821+ else {
22822+ iget_failed(inode);
22823+ inode = ERR_PTR(err);
22824+ }
22825+
4f0767ce 22826+out:
1facf9fc 22827+ /* never return NULL */
22828+ AuDebugOn(!inode);
22829+ AuTraceErrPtr(inode);
22830+ return inode;
22831+}
22832+
22833+/* lock free root dinfo */
22834+static int au_show_brs(struct seq_file *seq, struct super_block *sb)
22835+{
22836+ int err;
22837+ aufs_bindex_t bindex, bend;
22838+ struct path path;
4a4d8108 22839+ struct au_hdentry *hdp;
1facf9fc 22840+ struct au_branch *br;
1e00d052 22841+ char *perm;
1facf9fc 22842+
22843+ err = 0;
22844+ bend = au_sbend(sb);
4a4d8108 22845+ hdp = au_di(sb->s_root)->di_hdentry;
1facf9fc 22846+ for (bindex = 0; !err && bindex <= bend; bindex++) {
22847+ br = au_sbr(sb, bindex);
22848+ path.mnt = br->br_mnt;
4a4d8108 22849+ path.dentry = hdp[bindex].hd_dentry;
1facf9fc 22850+ err = au_seq_path(seq, &path);
1e00d052
AM
22851+ if (err > 0) {
22852+ perm = au_optstr_br_perm(br->br_perm);
22853+ if (perm) {
22854+ err = seq_printf(seq, "=%s", perm);
22855+ kfree(perm);
22856+ if (err == -1)
22857+ err = -E2BIG;
22858+ } else
22859+ err = -ENOMEM;
22860+ }
1facf9fc 22861+ if (!err && bindex != bend)
22862+ err = seq_putc(seq, ':');
22863+ }
22864+
22865+ return err;
22866+}
22867+
22868+static void au_show_wbr_create(struct seq_file *m, int v,
22869+ struct au_sbinfo *sbinfo)
22870+{
22871+ const char *pat;
22872+
dece6358
AM
22873+ AuRwMustAnyLock(&sbinfo->si_rwsem);
22874+
1facf9fc 22875+ seq_printf(m, ",create=");
22876+ pat = au_optstr_wbr_create(v);
22877+ switch (v) {
22878+ case AuWbrCreate_TDP:
22879+ case AuWbrCreate_RR:
22880+ case AuWbrCreate_MFS:
22881+ case AuWbrCreate_PMFS:
22882+ seq_printf(m, pat);
22883+ break;
22884+ case AuWbrCreate_MFSV:
22885+ seq_printf(m, /*pat*/"mfs:%lu",
e49829fe
JR
22886+ jiffies_to_msecs(sbinfo->si_wbr_mfs.mfs_expire)
22887+ / MSEC_PER_SEC);
1facf9fc 22888+ break;
22889+ case AuWbrCreate_PMFSV:
22890+ seq_printf(m, /*pat*/"pmfs:%lu",
e49829fe
JR
22891+ jiffies_to_msecs(sbinfo->si_wbr_mfs.mfs_expire)
22892+ / MSEC_PER_SEC);
1facf9fc 22893+ break;
22894+ case AuWbrCreate_MFSRR:
22895+ seq_printf(m, /*pat*/"mfsrr:%llu",
22896+ sbinfo->si_wbr_mfs.mfsrr_watermark);
22897+ break;
22898+ case AuWbrCreate_MFSRRV:
22899+ seq_printf(m, /*pat*/"mfsrr:%llu:%lu",
22900+ sbinfo->si_wbr_mfs.mfsrr_watermark,
e49829fe
JR
22901+ jiffies_to_msecs(sbinfo->si_wbr_mfs.mfs_expire)
22902+ / MSEC_PER_SEC);
1facf9fc 22903+ break;
22904+ }
22905+}
22906+
7eafdf33 22907+static int au_show_xino(struct seq_file *seq, struct super_block *sb)
1facf9fc 22908+{
22909+#ifdef CONFIG_SYSFS
22910+ return 0;
22911+#else
22912+ int err;
22913+ const int len = sizeof(AUFS_XINO_FNAME) - 1;
22914+ aufs_bindex_t bindex, brid;
1facf9fc 22915+ struct qstr *name;
22916+ struct file *f;
22917+ struct dentry *d, *h_root;
4a4d8108 22918+ struct au_hdentry *hdp;
1facf9fc 22919+
dece6358
AM
22920+ AuRwMustAnyLock(&sbinfo->si_rwsem);
22921+
1facf9fc 22922+ err = 0;
1facf9fc 22923+ f = au_sbi(sb)->si_xib;
22924+ if (!f)
22925+ goto out;
22926+
22927+ /* stop printing the default xino path on the first writable branch */
22928+ h_root = NULL;
22929+ brid = au_xino_brid(sb);
22930+ if (brid >= 0) {
22931+ bindex = au_br_index(sb, brid);
4a4d8108
AM
22932+ hdp = au_di(sb->s_root)->di_hdentry;
22933+ h_root = hdp[0 + bindex].hd_dentry;
1facf9fc 22934+ }
22935+ d = f->f_dentry;
22936+ name = &d->d_name;
22937+ /* safe ->d_parent because the file is unlinked */
22938+ if (d->d_parent == h_root
22939+ && name->len == len
22940+ && !memcmp(name->name, AUFS_XINO_FNAME, len))
22941+ goto out;
22942+
22943+ seq_puts(seq, ",xino=");
22944+ err = au_xino_path(seq, f);
22945+
4f0767ce 22946+out:
1facf9fc 22947+ return err;
22948+#endif
22949+}
22950+
22951+/* seq_file will re-call me in case of too long string */
7eafdf33 22952+static int aufs_show_options(struct seq_file *m, struct dentry *dentry)
1facf9fc 22953+{
027c5e7a 22954+ int err;
1facf9fc 22955+ unsigned int mnt_flags, v;
22956+ struct super_block *sb;
22957+ struct au_sbinfo *sbinfo;
22958+
22959+#define AuBool(name, str) do { \
22960+ v = au_opt_test(mnt_flags, name); \
22961+ if (v != au_opt_test(AuOpt_Def, name)) \
22962+ seq_printf(m, ",%s" #str, v ? "" : "no"); \
22963+} while (0)
22964+
22965+#define AuStr(name, str) do { \
22966+ v = mnt_flags & AuOptMask_##name; \
22967+ if (v != (AuOpt_Def & AuOptMask_##name)) \
22968+ seq_printf(m, "," #str "=%s", au_optstr_##str(v)); \
22969+} while (0)
22970+
22971+#define AuUInt(name, str, val) do { \
22972+ if (val != AUFS_##name##_DEF) \
22973+ seq_printf(m, "," #str "=%u", val); \
22974+} while (0)
22975+
22976+ /* lock free root dinfo */
7eafdf33 22977+ sb = dentry->d_sb;
1facf9fc 22978+ si_noflush_read_lock(sb);
22979+ sbinfo = au_sbi(sb);
22980+ seq_printf(m, ",si=%lx", sysaufs_si_id(sbinfo));
22981+
22982+ mnt_flags = au_mntflags(sb);
22983+ if (au_opt_test(mnt_flags, XINO)) {
7eafdf33 22984+ err = au_show_xino(m, sb);
1facf9fc 22985+ if (unlikely(err))
22986+ goto out;
22987+ } else
22988+ seq_puts(m, ",noxino");
22989+
22990+ AuBool(TRUNC_XINO, trunc_xino);
22991+ AuStr(UDBA, udba);
dece6358 22992+ AuBool(SHWH, shwh);
1facf9fc 22993+ AuBool(PLINK, plink);
4a4d8108 22994+ AuBool(DIO, dio);
1facf9fc 22995+ /* AuBool(DIRPERM1, dirperm1); */
22996+ /* AuBool(REFROF, refrof); */
22997+
22998+ v = sbinfo->si_wbr_create;
22999+ if (v != AuWbrCreate_Def)
23000+ au_show_wbr_create(m, v, sbinfo);
23001+
23002+ v = sbinfo->si_wbr_copyup;
23003+ if (v != AuWbrCopyup_Def)
23004+ seq_printf(m, ",cpup=%s", au_optstr_wbr_copyup(v));
23005+
23006+ v = au_opt_test(mnt_flags, ALWAYS_DIROPQ);
23007+ if (v != au_opt_test(AuOpt_Def, ALWAYS_DIROPQ))
23008+ seq_printf(m, ",diropq=%c", v ? 'a' : 'w');
23009+
23010+ AuUInt(DIRWH, dirwh, sbinfo->si_dirwh);
23011+
027c5e7a
AM
23012+ v = jiffies_to_msecs(sbinfo->si_rdcache) / MSEC_PER_SEC;
23013+ AuUInt(RDCACHE, rdcache, v);
1facf9fc 23014+
23015+ AuUInt(RDBLK, rdblk, sbinfo->si_rdblk);
23016+ AuUInt(RDHASH, rdhash, sbinfo->si_rdhash);
23017+
23018+ AuBool(SUM, sum);
23019+ /* AuBool(SUM_W, wsum); */
23020+ AuBool(WARN_PERM, warn_perm);
23021+ AuBool(VERBOSE, verbose);
23022+
4f0767ce 23023+out:
1facf9fc 23024+ /* be sure to print "br:" last */
23025+ if (!sysaufs_brs) {
23026+ seq_puts(m, ",br:");
23027+ au_show_brs(m, sb);
23028+ }
23029+ si_read_unlock(sb);
23030+ return 0;
23031+
1facf9fc 23032+#undef AuBool
23033+#undef AuStr
4a4d8108 23034+#undef AuUInt
1facf9fc 23035+}
23036+
23037+/* ---------------------------------------------------------------------- */
23038+
23039+/* sum mode which returns the summation for statfs(2) */
23040+
23041+static u64 au_add_till_max(u64 a, u64 b)
23042+{
23043+ u64 old;
23044+
23045+ old = a;
23046+ a += b;
92d182d2
AM
23047+ if (old <= a)
23048+ return a;
23049+ return ULLONG_MAX;
23050+}
23051+
23052+static u64 au_mul_till_max(u64 a, long mul)
23053+{
23054+ u64 old;
23055+
23056+ old = a;
23057+ a *= mul;
23058+ if (old <= a)
1facf9fc 23059+ return a;
23060+ return ULLONG_MAX;
23061+}
23062+
23063+static int au_statfs_sum(struct super_block *sb, struct kstatfs *buf)
23064+{
23065+ int err;
92d182d2 23066+ long bsize, factor;
1facf9fc 23067+ u64 blocks, bfree, bavail, files, ffree;
23068+ aufs_bindex_t bend, bindex, i;
23069+ unsigned char shared;
7f207e10 23070+ struct path h_path;
1facf9fc 23071+ struct super_block *h_sb;
23072+
92d182d2
AM
23073+ err = 0;
23074+ bsize = LONG_MAX;
23075+ files = 0;
23076+ ffree = 0;
1facf9fc 23077+ blocks = 0;
23078+ bfree = 0;
23079+ bavail = 0;
1facf9fc 23080+ bend = au_sbend(sb);
92d182d2 23081+ for (bindex = 0; bindex <= bend; bindex++) {
7f207e10
AM
23082+ h_path.mnt = au_sbr_mnt(sb, bindex);
23083+ h_sb = h_path.mnt->mnt_sb;
1facf9fc 23084+ shared = 0;
92d182d2 23085+ for (i = 0; !shared && i < bindex; i++)
1facf9fc 23086+ shared = (au_sbr_sb(sb, i) == h_sb);
23087+ if (shared)
23088+ continue;
23089+
23090+ /* sb->s_root for NFS is unreliable */
7f207e10
AM
23091+ h_path.dentry = h_path.mnt->mnt_root;
23092+ err = vfs_statfs(&h_path, buf);
1facf9fc 23093+ if (unlikely(err))
23094+ goto out;
23095+
92d182d2
AM
23096+ if (bsize > buf->f_bsize) {
23097+ /*
23098+ * we will reduce bsize, so we have to expand blocks
23099+ * etc. to match them again
23100+ */
23101+ factor = (bsize / buf->f_bsize);
23102+ blocks = au_mul_till_max(blocks, factor);
23103+ bfree = au_mul_till_max(bfree, factor);
23104+ bavail = au_mul_till_max(bavail, factor);
23105+ bsize = buf->f_bsize;
23106+ }
23107+
23108+ factor = (buf->f_bsize / bsize);
23109+ blocks = au_add_till_max(blocks,
23110+ au_mul_till_max(buf->f_blocks, factor));
23111+ bfree = au_add_till_max(bfree,
23112+ au_mul_till_max(buf->f_bfree, factor));
23113+ bavail = au_add_till_max(bavail,
23114+ au_mul_till_max(buf->f_bavail, factor));
1facf9fc 23115+ files = au_add_till_max(files, buf->f_files);
23116+ ffree = au_add_till_max(ffree, buf->f_ffree);
23117+ }
23118+
92d182d2 23119+ buf->f_bsize = bsize;
1facf9fc 23120+ buf->f_blocks = blocks;
23121+ buf->f_bfree = bfree;
23122+ buf->f_bavail = bavail;
23123+ buf->f_files = files;
23124+ buf->f_ffree = ffree;
92d182d2 23125+ buf->f_frsize = 0;
1facf9fc 23126+
4f0767ce 23127+out:
1facf9fc 23128+ return err;
23129+}
23130+
23131+static int aufs_statfs(struct dentry *dentry, struct kstatfs *buf)
23132+{
23133+ int err;
7f207e10 23134+ struct path h_path;
1facf9fc 23135+ struct super_block *sb;
23136+
23137+ /* lock free root dinfo */
23138+ sb = dentry->d_sb;
23139+ si_noflush_read_lock(sb);
7f207e10 23140+ if (!au_opt_test(au_mntflags(sb), SUM)) {
1facf9fc 23141+ /* sb->s_root for NFS is unreliable */
7f207e10
AM
23142+ h_path.mnt = au_sbr_mnt(sb, 0);
23143+ h_path.dentry = h_path.mnt->mnt_root;
23144+ err = vfs_statfs(&h_path, buf);
23145+ } else
1facf9fc 23146+ err = au_statfs_sum(sb, buf);
23147+ si_read_unlock(sb);
23148+
23149+ if (!err) {
23150+ buf->f_type = AUFS_SUPER_MAGIC;
4a4d8108 23151+ buf->f_namelen = AUFS_MAX_NAMELEN;
1facf9fc 23152+ memset(&buf->f_fsid, 0, sizeof(buf->f_fsid));
23153+ }
23154+ /* buf->f_bsize = buf->f_blocks = buf->f_bfree = buf->f_bavail = -1; */
23155+
23156+ return err;
23157+}
23158+
23159+/* ---------------------------------------------------------------------- */
23160+
1facf9fc 23161+/* final actions when unmounting a file system */
23162+static void aufs_put_super(struct super_block *sb)
23163+{
23164+ struct au_sbinfo *sbinfo;
23165+
23166+ sbinfo = au_sbi(sb);
23167+ if (!sbinfo)
23168+ return;
23169+
1facf9fc 23170+ dbgaufs_si_fin(sbinfo);
23171+ kobject_put(&sbinfo->si_kobj);
23172+}
23173+
23174+/* ---------------------------------------------------------------------- */
23175+
7f207e10
AM
23176+void au_array_free(void *array)
23177+{
23178+ if (array) {
23179+ if (!is_vmalloc_addr(array))
23180+ kfree(array);
23181+ else
23182+ vfree(array);
23183+ }
23184+}
23185+
23186+void *au_array_alloc(unsigned long long *hint, au_arraycb_t cb, void *arg)
23187+{
23188+ void *array;
23189+ unsigned long long n;
23190+
23191+ array = NULL;
23192+ n = 0;
23193+ if (!*hint)
23194+ goto out;
23195+
23196+ if (*hint > ULLONG_MAX / sizeof(array)) {
23197+ array = ERR_PTR(-EMFILE);
23198+ pr_err("hint %llu\n", *hint);
23199+ goto out;
23200+ }
23201+
23202+ array = kmalloc(sizeof(array) * *hint, GFP_NOFS);
23203+ if (unlikely(!array))
23204+ array = vmalloc(sizeof(array) * *hint);
23205+ if (unlikely(!array)) {
23206+ array = ERR_PTR(-ENOMEM);
23207+ goto out;
23208+ }
23209+
23210+ n = cb(array, *hint, arg);
23211+ AuDebugOn(n > *hint);
23212+
23213+out:
23214+ *hint = n;
23215+ return array;
23216+}
23217+
23218+static unsigned long long au_iarray_cb(void *a,
23219+ unsigned long long max __maybe_unused,
23220+ void *arg)
23221+{
23222+ unsigned long long n;
23223+ struct inode **p, *inode;
23224+ struct list_head *head;
23225+
23226+ n = 0;
23227+ p = a;
23228+ head = arg;
2cbb1c4b 23229+ spin_lock(&inode_sb_list_lock);
7f207e10
AM
23230+ list_for_each_entry(inode, head, i_sb_list) {
23231+ if (!is_bad_inode(inode)
23232+ && au_ii(inode)->ii_bstart >= 0) {
2cbb1c4b
JR
23233+ spin_lock(&inode->i_lock);
23234+ if (atomic_read(&inode->i_count)) {
23235+ au_igrab(inode);
23236+ *p++ = inode;
23237+ n++;
23238+ AuDebugOn(n > max);
23239+ }
23240+ spin_unlock(&inode->i_lock);
7f207e10
AM
23241+ }
23242+ }
2cbb1c4b 23243+ spin_unlock(&inode_sb_list_lock);
7f207e10
AM
23244+
23245+ return n;
23246+}
23247+
23248+struct inode **au_iarray_alloc(struct super_block *sb, unsigned long long *max)
23249+{
23250+ *max = atomic_long_read(&au_sbi(sb)->si_ninodes);
23251+ return au_array_alloc(max, au_iarray_cb, &sb->s_inodes);
23252+}
23253+
23254+void au_iarray_free(struct inode **a, unsigned long long max)
23255+{
23256+ unsigned long long ull;
23257+
23258+ for (ull = 0; ull < max; ull++)
23259+ iput(a[ull]);
23260+ au_array_free(a);
23261+}
23262+
23263+/* ---------------------------------------------------------------------- */
23264+
1facf9fc 23265+/*
23266+ * refresh dentry and inode at remount time.
23267+ */
027c5e7a
AM
23268+/* todo: consolidate with simple_reval_dpath() and au_reval_for_attr() */
23269+static int au_do_refresh(struct dentry *dentry, unsigned int dir_flags,
23270+ struct dentry *parent)
1facf9fc 23271+{
23272+ int err;
1facf9fc 23273+
23274+ di_write_lock_child(dentry);
1facf9fc 23275+ di_read_lock_parent(parent, AuLock_IR);
027c5e7a
AM
23276+ err = au_refresh_dentry(dentry, parent);
23277+ if (!err && dir_flags)
23278+ au_hn_reset(dentry->d_inode, dir_flags);
1facf9fc 23279+ di_read_unlock(parent, AuLock_IR);
1facf9fc 23280+ di_write_unlock(dentry);
23281+
23282+ return err;
23283+}
23284+
027c5e7a
AM
23285+static int au_do_refresh_d(struct dentry *dentry, unsigned int sigen,
23286+ struct au_sbinfo *sbinfo,
23287+ const unsigned int dir_flags)
1facf9fc 23288+{
027c5e7a
AM
23289+ int err;
23290+ struct dentry *parent;
23291+ struct inode *inode;
23292+
23293+ err = 0;
23294+ parent = dget_parent(dentry);
23295+ if (!au_digen_test(parent, sigen) && au_digen_test(dentry, sigen)) {
23296+ inode = dentry->d_inode;
23297+ if (inode) {
23298+ if (!S_ISDIR(inode->i_mode))
23299+ err = au_do_refresh(dentry, /*dir_flags*/0,
23300+ parent);
23301+ else {
23302+ err = au_do_refresh(dentry, dir_flags, parent);
23303+ if (unlikely(err))
23304+ au_fset_si(sbinfo, FAILED_REFRESH_DIR);
23305+ }
23306+ } else
23307+ err = au_do_refresh(dentry, /*dir_flags*/0, parent);
23308+ AuDbgDentry(dentry);
23309+ }
23310+ dput(parent);
23311+
23312+ AuTraceErr(err);
23313+ return err;
1facf9fc 23314+}
23315+
027c5e7a 23316+static int au_refresh_d(struct super_block *sb)
1facf9fc 23317+{
23318+ int err, i, j, ndentry, e;
027c5e7a 23319+ unsigned int sigen;
1facf9fc 23320+ struct au_dcsub_pages dpages;
23321+ struct au_dpage *dpage;
027c5e7a
AM
23322+ struct dentry **dentries, *d;
23323+ struct au_sbinfo *sbinfo;
23324+ struct dentry *root = sb->s_root;
23325+ const unsigned int dir_flags = au_hi_flags(root->d_inode, /*isdir*/1);
1facf9fc 23326+
027c5e7a
AM
23327+ err = au_dpages_init(&dpages, GFP_NOFS);
23328+ if (unlikely(err))
1facf9fc 23329+ goto out;
027c5e7a
AM
23330+ err = au_dcsub_pages(&dpages, root, NULL, NULL);
23331+ if (unlikely(err))
1facf9fc 23332+ goto out_dpages;
1facf9fc 23333+
027c5e7a
AM
23334+ sigen = au_sigen(sb);
23335+ sbinfo = au_sbi(sb);
23336+ for (i = 0; i < dpages.ndpage; i++) {
1facf9fc 23337+ dpage = dpages.dpages + i;
23338+ dentries = dpage->dentries;
23339+ ndentry = dpage->ndentry;
027c5e7a 23340+ for (j = 0; j < ndentry; j++) {
1facf9fc 23341+ d = dentries[j];
027c5e7a
AM
23342+ e = au_do_refresh_d(d, sigen, sbinfo, dir_flags);
23343+ if (unlikely(e && !err))
23344+ err = e;
23345+ /* go on even err */
1facf9fc 23346+ }
23347+ }
23348+
4f0767ce 23349+out_dpages:
1facf9fc 23350+ au_dpages_free(&dpages);
4f0767ce 23351+out:
1facf9fc 23352+ return err;
23353+}
23354+
027c5e7a 23355+static int au_refresh_i(struct super_block *sb)
1facf9fc 23356+{
027c5e7a
AM
23357+ int err, e;
23358+ unsigned int sigen;
23359+ unsigned long long max, ull;
23360+ struct inode *inode, **array;
1facf9fc 23361+
027c5e7a
AM
23362+ array = au_iarray_alloc(sb, &max);
23363+ err = PTR_ERR(array);
23364+ if (IS_ERR(array))
23365+ goto out;
1facf9fc 23366+
23367+ err = 0;
027c5e7a
AM
23368+ sigen = au_sigen(sb);
23369+ for (ull = 0; ull < max; ull++) {
23370+ inode = array[ull];
23371+ if (au_iigen(inode) != sigen) {
1facf9fc 23372+ ii_write_lock_child(inode);
027c5e7a 23373+ e = au_refresh_hinode_self(inode);
1facf9fc 23374+ ii_write_unlock(inode);
23375+ if (unlikely(e)) {
027c5e7a 23376+ pr_err("error %d, i%lu\n", e, inode->i_ino);
1facf9fc 23377+ if (!err)
23378+ err = e;
23379+ /* go on even if err */
23380+ }
23381+ }
1facf9fc 23382+ }
23383+
027c5e7a 23384+ au_iarray_free(array, max);
1facf9fc 23385+
4f0767ce 23386+out:
1facf9fc 23387+ return err;
23388+}
23389+
027c5e7a 23390+static void au_remount_refresh(struct super_block *sb)
1facf9fc 23391+{
027c5e7a
AM
23392+ int err, e;
23393+ unsigned int udba;
23394+ aufs_bindex_t bindex, bend;
1facf9fc 23395+ struct dentry *root;
23396+ struct inode *inode;
027c5e7a 23397+ struct au_branch *br;
1facf9fc 23398+
23399+ au_sigen_inc(sb);
027c5e7a 23400+ au_fclr_si(au_sbi(sb), FAILED_REFRESH_DIR);
1facf9fc 23401+
23402+ root = sb->s_root;
23403+ DiMustNoWaiters(root);
23404+ inode = root->d_inode;
23405+ IiMustNoWaiters(inode);
1facf9fc 23406+
027c5e7a
AM
23407+ udba = au_opt_udba(sb);
23408+ bend = au_sbend(sb);
23409+ for (bindex = 0; bindex <= bend; bindex++) {
23410+ br = au_sbr(sb, bindex);
23411+ err = au_hnotify_reset_br(udba, br, br->br_perm);
1facf9fc 23412+ if (unlikely(err))
027c5e7a
AM
23413+ AuIOErr("hnotify failed on br %d, %d, ignored\n",
23414+ bindex, err);
23415+ /* go on even if err */
1facf9fc 23416+ }
027c5e7a 23417+ au_hn_reset(inode, au_hi_flags(inode, /*isdir*/1));
1facf9fc 23418+
027c5e7a
AM
23419+ di_write_unlock(root);
23420+ err = au_refresh_d(sb);
23421+ e = au_refresh_i(sb);
23422+ if (unlikely(e && !err))
23423+ err = e;
1facf9fc 23424+ /* aufs_write_lock() calls ..._child() */
23425+ di_write_lock_child(root);
027c5e7a
AM
23426+
23427+ au_cpup_attr_all(inode, /*force*/1);
23428+
23429+ if (unlikely(err))
23430+ AuIOErr("refresh failed, ignored, %d\n", err);
1facf9fc 23431+}
23432+
23433+/* stop extra interpretation of errno in mount(8), and strange error messages */
23434+static int cvt_err(int err)
23435+{
23436+ AuTraceErr(err);
23437+
23438+ switch (err) {
23439+ case -ENOENT:
23440+ case -ENOTDIR:
23441+ case -EEXIST:
23442+ case -EIO:
23443+ err = -EINVAL;
23444+ }
23445+ return err;
23446+}
23447+
23448+static int aufs_remount_fs(struct super_block *sb, int *flags, char *data)
23449+{
4a4d8108
AM
23450+ int err, do_dx;
23451+ unsigned int mntflags;
1facf9fc 23452+ struct au_opts opts;
23453+ struct dentry *root;
23454+ struct inode *inode;
23455+ struct au_sbinfo *sbinfo;
23456+
23457+ err = 0;
23458+ root = sb->s_root;
23459+ if (!data || !*data) {
e49829fe
JR
23460+ err = si_write_lock(sb, AuLock_FLUSH | AuLock_NOPLM);
23461+ if (!err) {
23462+ di_write_lock_child(root);
23463+ err = au_opts_verify(sb, *flags, /*pending*/0);
23464+ aufs_write_unlock(root);
23465+ }
1facf9fc 23466+ goto out;
23467+ }
23468+
23469+ err = -ENOMEM;
23470+ memset(&opts, 0, sizeof(opts));
23471+ opts.opt = (void *)__get_free_page(GFP_NOFS);
23472+ if (unlikely(!opts.opt))
23473+ goto out;
23474+ opts.max_opt = PAGE_SIZE / sizeof(*opts.opt);
23475+ opts.flags = AuOpts_REMOUNT;
23476+ opts.sb_flags = *flags;
23477+
23478+ /* parse it before aufs lock */
23479+ err = au_opts_parse(sb, data, &opts);
23480+ if (unlikely(err))
23481+ goto out_opts;
23482+
23483+ sbinfo = au_sbi(sb);
23484+ inode = root->d_inode;
23485+ mutex_lock(&inode->i_mutex);
e49829fe
JR
23486+ err = si_write_lock(sb, AuLock_FLUSH | AuLock_NOPLM);
23487+ if (unlikely(err))
23488+ goto out_mtx;
23489+ di_write_lock_child(root);
1facf9fc 23490+
23491+ /* au_opts_remount() may return an error */
23492+ err = au_opts_remount(sb, &opts);
23493+ au_opts_free(&opts);
23494+
027c5e7a
AM
23495+ if (au_ftest_opts(opts.flags, REFRESH))
23496+ au_remount_refresh(sb);
1facf9fc 23497+
4a4d8108
AM
23498+ if (au_ftest_opts(opts.flags, REFRESH_DYAOP)) {
23499+ mntflags = au_mntflags(sb);
23500+ do_dx = !!au_opt_test(mntflags, DIO);
23501+ au_dy_arefresh(do_dx);
23502+ }
23503+
1facf9fc 23504+ aufs_write_unlock(root);
953406b4 23505+
e49829fe
JR
23506+out_mtx:
23507+ mutex_unlock(&inode->i_mutex);
4f0767ce 23508+out_opts:
1facf9fc 23509+ free_page((unsigned long)opts.opt);
4f0767ce 23510+out:
1facf9fc 23511+ err = cvt_err(err);
23512+ AuTraceErr(err);
23513+ return err;
23514+}
23515+
4a4d8108 23516+static const struct super_operations aufs_sop = {
1facf9fc 23517+ .alloc_inode = aufs_alloc_inode,
23518+ .destroy_inode = aufs_destroy_inode,
b752ccd1 23519+ /* always deleting, no clearing */
1facf9fc 23520+ .drop_inode = generic_delete_inode,
23521+ .show_options = aufs_show_options,
23522+ .statfs = aufs_statfs,
23523+ .put_super = aufs_put_super,
23524+ .remount_fs = aufs_remount_fs
23525+};
23526+
23527+/* ---------------------------------------------------------------------- */
23528+
23529+static int alloc_root(struct super_block *sb)
23530+{
23531+ int err;
23532+ struct inode *inode;
23533+ struct dentry *root;
23534+
23535+ err = -ENOMEM;
23536+ inode = au_iget_locked(sb, AUFS_ROOT_INO);
23537+ err = PTR_ERR(inode);
23538+ if (IS_ERR(inode))
23539+ goto out;
23540+
23541+ inode->i_op = &aufs_dir_iop;
23542+ inode->i_fop = &aufs_dir_fop;
23543+ inode->i_mode = S_IFDIR;
9dbd164d 23544+ set_nlink(inode, 2);
1facf9fc 23545+ unlock_new_inode(inode);
23546+
92d182d2 23547+ root = d_make_root(inode);
1facf9fc 23548+ if (unlikely(!root))
92d182d2 23549+ goto out;
1facf9fc 23550+ err = PTR_ERR(root);
23551+ if (IS_ERR(root))
92d182d2 23552+ goto out;
1facf9fc 23553+
4a4d8108 23554+ err = au_di_init(root);
1facf9fc 23555+ if (!err) {
23556+ sb->s_root = root;
23557+ return 0; /* success */
23558+ }
23559+ dput(root);
1facf9fc 23560+
4f0767ce 23561+out:
1facf9fc 23562+ return err;
1facf9fc 23563+}
23564+
23565+static int aufs_fill_super(struct super_block *sb, void *raw_data,
23566+ int silent __maybe_unused)
23567+{
23568+ int err;
23569+ struct au_opts opts;
23570+ struct dentry *root;
23571+ struct inode *inode;
23572+ char *arg = raw_data;
23573+
23574+ if (unlikely(!arg || !*arg)) {
23575+ err = -EINVAL;
4a4d8108 23576+ pr_err("no arg\n");
1facf9fc 23577+ goto out;
23578+ }
23579+
23580+ err = -ENOMEM;
23581+ memset(&opts, 0, sizeof(opts));
23582+ opts.opt = (void *)__get_free_page(GFP_NOFS);
23583+ if (unlikely(!opts.opt))
23584+ goto out;
23585+ opts.max_opt = PAGE_SIZE / sizeof(*opts.opt);
23586+ opts.sb_flags = sb->s_flags;
23587+
23588+ err = au_si_alloc(sb);
23589+ if (unlikely(err))
23590+ goto out_opts;
23591+
23592+ /* all timestamps always follow the ones on the branch */
23593+ sb->s_flags |= MS_NOATIME | MS_NODIRATIME;
23594+ sb->s_op = &aufs_sop;
027c5e7a 23595+ sb->s_d_op = &aufs_dop;
1facf9fc 23596+ sb->s_magic = AUFS_SUPER_MAGIC;
23597+ sb->s_maxbytes = 0;
23598+ au_export_init(sb);
23599+
23600+ err = alloc_root(sb);
23601+ if (unlikely(err)) {
23602+ si_write_unlock(sb);
23603+ goto out_info;
23604+ }
23605+ root = sb->s_root;
23606+ inode = root->d_inode;
23607+
23608+ /*
23609+ * actually we can parse options regardless aufs lock here.
23610+ * but at remount time, parsing must be done before aufs lock.
23611+ * so we follow the same rule.
23612+ */
23613+ ii_write_lock_parent(inode);
23614+ aufs_write_unlock(root);
23615+ err = au_opts_parse(sb, arg, &opts);
23616+ if (unlikely(err))
23617+ goto out_root;
23618+
23619+ /* lock vfs_inode first, then aufs. */
23620+ mutex_lock(&inode->i_mutex);
1facf9fc 23621+ aufs_write_lock(root);
23622+ err = au_opts_mount(sb, &opts);
23623+ au_opts_free(&opts);
1facf9fc 23624+ aufs_write_unlock(root);
23625+ mutex_unlock(&inode->i_mutex);
4a4d8108
AM
23626+ if (!err)
23627+ goto out_opts; /* success */
1facf9fc 23628+
4f0767ce 23629+out_root:
1facf9fc 23630+ dput(root);
23631+ sb->s_root = NULL;
4f0767ce 23632+out_info:
2cbb1c4b 23633+ dbgaufs_si_fin(au_sbi(sb));
1facf9fc 23634+ kobject_put(&au_sbi(sb)->si_kobj);
23635+ sb->s_fs_info = NULL;
4f0767ce 23636+out_opts:
1facf9fc 23637+ free_page((unsigned long)opts.opt);
4f0767ce 23638+out:
1facf9fc 23639+ AuTraceErr(err);
23640+ err = cvt_err(err);
23641+ AuTraceErr(err);
23642+ return err;
23643+}
23644+
23645+/* ---------------------------------------------------------------------- */
23646+
027c5e7a
AM
23647+static struct dentry *aufs_mount(struct file_system_type *fs_type, int flags,
23648+ const char *dev_name __maybe_unused,
23649+ void *raw_data)
1facf9fc 23650+{
027c5e7a 23651+ struct dentry *root;
1facf9fc 23652+ struct super_block *sb;
23653+
23654+ /* all timestamps always follow the ones on the branch */
23655+ /* mnt->mnt_flags |= MNT_NOATIME | MNT_NODIRATIME; */
027c5e7a
AM
23656+ root = mount_nodev(fs_type, flags, raw_data, aufs_fill_super);
23657+ if (IS_ERR(root))
23658+ goto out;
23659+
23660+ sb = root->d_sb;
23661+ si_write_lock(sb, !AuLock_FLUSH);
23662+ sysaufs_brs_add(sb, 0);
23663+ si_write_unlock(sb);
23664+ au_sbilist_add(sb);
23665+
23666+out:
23667+ return root;
1facf9fc 23668+}
23669+
e49829fe
JR
23670+static void aufs_kill_sb(struct super_block *sb)
23671+{
23672+ struct au_sbinfo *sbinfo;
23673+
23674+ sbinfo = au_sbi(sb);
23675+ if (sbinfo) {
23676+ au_sbilist_del(sb);
23677+ aufs_write_lock(sb->s_root);
23678+ if (sbinfo->si_wbr_create_ops->fin)
23679+ sbinfo->si_wbr_create_ops->fin(sb);
23680+ if (au_opt_test(sbinfo->si_mntflags, UDBA_HNOTIFY)) {
23681+ au_opt_set_udba(sbinfo->si_mntflags, UDBA_NONE);
027c5e7a 23682+ au_remount_refresh(sb);
e49829fe
JR
23683+ }
23684+ if (au_opt_test(sbinfo->si_mntflags, PLINK))
23685+ au_plink_put(sb, /*verbose*/1);
23686+ au_xino_clr(sb);
1e00d052 23687+ sbinfo->si_sb = NULL;
e49829fe 23688+ aufs_write_unlock(sb->s_root);
e49829fe
JR
23689+ au_nwt_flush(&sbinfo->si_nowait);
23690+ }
23691+ generic_shutdown_super(sb);
23692+}
23693+
1facf9fc 23694+struct file_system_type aufs_fs_type = {
23695+ .name = AUFS_FSTYPE,
23696+ .fs_flags =
23697+ FS_RENAME_DOES_D_MOVE /* a race between rename and others */
23698+ | FS_REVAL_DOT, /* for NFS branch and udba */
027c5e7a 23699+ .mount = aufs_mount,
e49829fe 23700+ .kill_sb = aufs_kill_sb,
1facf9fc 23701+ /* no need to __module_get() and module_put(). */
23702+ .owner = THIS_MODULE,
23703+};
7f207e10
AM
23704diff -urN /usr/share/empty/fs/aufs/super.h linux/fs/aufs/super.h
23705--- /usr/share/empty/fs/aufs/super.h 1970-01-01 01:00:00.000000000 +0100
2dfbb274 23706+++ linux/fs/aufs/super.h 2012-08-26 08:39:00.763841498 +0200
f6c5ef8b 23707@@ -0,0 +1,546 @@
1facf9fc 23708+/*
f6c5ef8b 23709+ * Copyright (C) 2005-2012 Junjiro R. Okajima
1facf9fc 23710+ *
23711+ * This program, aufs is free software; you can redistribute it and/or modify
23712+ * it under the terms of the GNU General Public License as published by
23713+ * the Free Software Foundation; either version 2 of the License, or
23714+ * (at your option) any later version.
dece6358
AM
23715+ *
23716+ * This program is distributed in the hope that it will be useful,
23717+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
23718+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23719+ * GNU General Public License for more details.
23720+ *
23721+ * You should have received a copy of the GNU General Public License
23722+ * along with this program; if not, write to the Free Software
23723+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 23724+ */
23725+
23726+/*
23727+ * super_block operations
23728+ */
23729+
23730+#ifndef __AUFS_SUPER_H__
23731+#define __AUFS_SUPER_H__
23732+
23733+#ifdef __KERNEL__
23734+
23735+#include <linux/fs.h>
1facf9fc 23736+#include "rwsem.h"
23737+#include "spl.h"
23738+#include "wkq.h"
23739+
23740+typedef ssize_t (*au_readf_t)(struct file *, char __user *, size_t, loff_t *);
23741+typedef ssize_t (*au_writef_t)(struct file *, const char __user *, size_t,
23742+ loff_t *);
23743+
23744+/* policies to select one among multiple writable branches */
23745+struct au_wbr_copyup_operations {
23746+ int (*copyup)(struct dentry *dentry);
23747+};
23748+
23749+struct au_wbr_create_operations {
23750+ int (*create)(struct dentry *dentry, int isdir);
23751+ int (*init)(struct super_block *sb);
23752+ int (*fin)(struct super_block *sb);
23753+};
23754+
23755+struct au_wbr_mfs {
23756+ struct mutex mfs_lock; /* protect this structure */
23757+ unsigned long mfs_jiffy;
23758+ unsigned long mfs_expire;
23759+ aufs_bindex_t mfs_bindex;
23760+
23761+ unsigned long long mfsrr_bytes;
23762+ unsigned long long mfsrr_watermark;
23763+};
23764+
1facf9fc 23765+struct au_branch;
23766+struct au_sbinfo {
23767+ /* nowait tasks in the system-wide workqueue */
23768+ struct au_nowait_tasks si_nowait;
23769+
b752ccd1
AM
23770+ /*
23771+ * tried sb->s_umount, but failed due to the dependecy between i_mutex.
23772+ * rwsem for au_sbinfo is necessary.
23773+ */
dece6358 23774+ struct au_rwsem si_rwsem;
1facf9fc 23775+
b752ccd1
AM
23776+ /* prevent recursive locking in deleting inode */
23777+ struct {
23778+ unsigned long *bitmap;
23779+ spinlock_t tree_lock;
23780+ struct radix_tree_root tree;
23781+ } au_si_pid;
23782+
7f207e10
AM
23783+ /*
23784+ * dirty approach to protect sb->sb_inodes and ->s_files from remount.
23785+ */
23786+ atomic_long_t si_ninodes, si_nfiles;
23787+
1facf9fc 23788+ /* branch management */
23789+ unsigned int si_generation;
23790+
23791+ /* see above flags */
23792+ unsigned char au_si_status;
23793+
23794+ aufs_bindex_t si_bend;
7f207e10
AM
23795+
23796+ /* dirty trick to keep br_id plus */
23797+ unsigned int si_last_br_id :
23798+ sizeof(aufs_bindex_t) * BITS_PER_BYTE - 1;
1facf9fc 23799+ struct au_branch **si_branch;
23800+
23801+ /* policy to select a writable branch */
23802+ unsigned char si_wbr_copyup;
23803+ unsigned char si_wbr_create;
23804+ struct au_wbr_copyup_operations *si_wbr_copyup_ops;
23805+ struct au_wbr_create_operations *si_wbr_create_ops;
23806+
23807+ /* round robin */
23808+ atomic_t si_wbr_rr_next;
23809+
23810+ /* most free space */
23811+ struct au_wbr_mfs si_wbr_mfs;
23812+
23813+ /* mount flags */
23814+ /* include/asm-ia64/siginfo.h defines a macro named si_flags */
23815+ unsigned int si_mntflags;
23816+
23817+ /* external inode number (bitmap and translation table) */
23818+ au_readf_t si_xread;
23819+ au_writef_t si_xwrite;
23820+ struct file *si_xib;
23821+ struct mutex si_xib_mtx; /* protect xib members */
23822+ unsigned long *si_xib_buf;
23823+ unsigned long si_xib_last_pindex;
23824+ int si_xib_next_bit;
23825+ aufs_bindex_t si_xino_brid;
23826+ /* reserved for future use */
23827+ /* unsigned long long si_xib_limit; */ /* Max xib file size */
23828+
23829+#ifdef CONFIG_AUFS_EXPORT
23830+ /* i_generation */
23831+ struct file *si_xigen;
23832+ atomic_t si_xigen_next;
23833+#endif
23834+
23835+ /* vdir parameters */
e49829fe 23836+ unsigned long si_rdcache; /* max cache time in jiffies */
1facf9fc 23837+ unsigned int si_rdblk; /* deblk size */
23838+ unsigned int si_rdhash; /* hash size */
23839+
23840+ /*
23841+ * If the number of whiteouts are larger than si_dirwh, leave all of
23842+ * them after au_whtmp_ren to reduce the cost of rmdir(2).
23843+ * future fsck.aufs or kernel thread will remove them later.
23844+ * Otherwise, remove all whiteouts and the dir in rmdir(2).
23845+ */
23846+ unsigned int si_dirwh;
23847+
23848+ /*
23849+ * rename(2) a directory with all children.
23850+ */
23851+ /* reserved for future use */
23852+ /* int si_rendir; */
23853+
23854+ /* pseudo_link list */
23855+ struct au_splhead si_plink;
23856+ wait_queue_head_t si_plink_wq;
4a4d8108 23857+ spinlock_t si_plink_maint_lock;
e49829fe 23858+ pid_t si_plink_maint_pid;
1facf9fc 23859+
23860+ /*
23861+ * sysfs and lifetime management.
23862+ * this is not a small structure and it may be a waste of memory in case
23863+ * of sysfs is disabled, particulary when many aufs-es are mounted.
23864+ * but using sysfs is majority.
23865+ */
23866+ struct kobject si_kobj;
23867+#ifdef CONFIG_DEBUG_FS
23868+ struct dentry *si_dbgaufs, *si_dbgaufs_xib;
23869+#ifdef CONFIG_AUFS_EXPORT
23870+ struct dentry *si_dbgaufs_xigen;
23871+#endif
23872+#endif
23873+
e49829fe
JR
23874+#ifdef CONFIG_AUFS_SBILIST
23875+ struct list_head si_list;
23876+#endif
23877+
1facf9fc 23878+ /* dirty, necessary for unmounting, sysfs and sysrq */
23879+ struct super_block *si_sb;
23880+};
23881+
dece6358
AM
23882+/* sbinfo status flags */
23883+/*
23884+ * set true when refresh_dirs() failed at remount time.
23885+ * then try refreshing dirs at access time again.
23886+ * if it is false, refreshing dirs at access time is unnecesary
23887+ */
027c5e7a 23888+#define AuSi_FAILED_REFRESH_DIR 1
dece6358
AM
23889+static inline unsigned char au_do_ftest_si(struct au_sbinfo *sbi,
23890+ unsigned int flag)
23891+{
23892+ AuRwMustAnyLock(&sbi->si_rwsem);
23893+ return sbi->au_si_status & flag;
23894+}
23895+#define au_ftest_si(sbinfo, name) au_do_ftest_si(sbinfo, AuSi_##name)
23896+#define au_fset_si(sbinfo, name) do { \
23897+ AuRwMustWriteLock(&(sbinfo)->si_rwsem); \
23898+ (sbinfo)->au_si_status |= AuSi_##name; \
23899+} while (0)
23900+#define au_fclr_si(sbinfo, name) do { \
23901+ AuRwMustWriteLock(&(sbinfo)->si_rwsem); \
23902+ (sbinfo)->au_si_status &= ~AuSi_##name; \
23903+} while (0)
23904+
1facf9fc 23905+/* ---------------------------------------------------------------------- */
23906+
23907+/* policy to select one among writable branches */
4a4d8108
AM
23908+#define AuWbrCopyup(sbinfo, ...) \
23909+ ((sbinfo)->si_wbr_copyup_ops->copyup(__VA_ARGS__))
23910+#define AuWbrCreate(sbinfo, ...) \
23911+ ((sbinfo)->si_wbr_create_ops->create(__VA_ARGS__))
1facf9fc 23912+
23913+/* flags for si_read_lock()/aufs_read_lock()/di_read_lock() */
23914+#define AuLock_DW 1 /* write-lock dentry */
23915+#define AuLock_IR (1 << 1) /* read-lock inode */
23916+#define AuLock_IW (1 << 2) /* write-lock inode */
23917+#define AuLock_FLUSH (1 << 3) /* wait for 'nowait' tasks */
23918+#define AuLock_DIR (1 << 4) /* target is a dir */
e49829fe
JR
23919+#define AuLock_NOPLM (1 << 5) /* return err in plm mode */
23920+#define AuLock_NOPLMW (1 << 6) /* wait for plm mode ends */
027c5e7a 23921+#define AuLock_GEN (1 << 7) /* test digen/iigen */
1facf9fc 23922+#define au_ftest_lock(flags, name) ((flags) & AuLock_##name)
7f207e10
AM
23923+#define au_fset_lock(flags, name) \
23924+ do { (flags) |= AuLock_##name; } while (0)
23925+#define au_fclr_lock(flags, name) \
23926+ do { (flags) &= ~AuLock_##name; } while (0)
1facf9fc 23927+
23928+/* ---------------------------------------------------------------------- */
23929+
23930+/* super.c */
23931+extern struct file_system_type aufs_fs_type;
23932+struct inode *au_iget_locked(struct super_block *sb, ino_t ino);
7f207e10
AM
23933+typedef unsigned long long (*au_arraycb_t)(void *array, unsigned long long max,
23934+ void *arg);
23935+void au_array_free(void *array);
23936+void *au_array_alloc(unsigned long long *hint, au_arraycb_t cb, void *arg);
23937+struct inode **au_iarray_alloc(struct super_block *sb, unsigned long long *max);
23938+void au_iarray_free(struct inode **a, unsigned long long max);
1facf9fc 23939+
23940+/* sbinfo.c */
23941+void au_si_free(struct kobject *kobj);
23942+int au_si_alloc(struct super_block *sb);
23943+int au_sbr_realloc(struct au_sbinfo *sbinfo, int nbr);
23944+
23945+unsigned int au_sigen_inc(struct super_block *sb);
23946+aufs_bindex_t au_new_br_id(struct super_block *sb);
23947+
e49829fe
JR
23948+int si_read_lock(struct super_block *sb, int flags);
23949+int si_write_lock(struct super_block *sb, int flags);
23950+int aufs_read_lock(struct dentry *dentry, int flags);
1facf9fc 23951+void aufs_read_unlock(struct dentry *dentry, int flags);
23952+void aufs_write_lock(struct dentry *dentry);
23953+void aufs_write_unlock(struct dentry *dentry);
e49829fe 23954+int aufs_read_and_write_lock2(struct dentry *d1, struct dentry *d2, int flags);
1facf9fc 23955+void aufs_read_and_write_unlock2(struct dentry *d1, struct dentry *d2);
23956+
b752ccd1
AM
23957+int si_pid_test_slow(struct super_block *sb);
23958+void si_pid_set_slow(struct super_block *sb);
23959+void si_pid_clr_slow(struct super_block *sb);
23960+
1facf9fc 23961+/* wbr_policy.c */
23962+extern struct au_wbr_copyup_operations au_wbr_copyup_ops[];
23963+extern struct au_wbr_create_operations au_wbr_create_ops[];
23964+int au_cpdown_dirs(struct dentry *dentry, aufs_bindex_t bdst);
23965+
23966+/* ---------------------------------------------------------------------- */
23967+
23968+static inline struct au_sbinfo *au_sbi(struct super_block *sb)
23969+{
23970+ return sb->s_fs_info;
23971+}
23972+
23973+/* ---------------------------------------------------------------------- */
23974+
23975+#ifdef CONFIG_AUFS_EXPORT
23976+void au_export_init(struct super_block *sb);
23977+
b752ccd1 23978+static inline int au_test_nfsd(void)
1facf9fc 23979+{
b752ccd1
AM
23980+ struct task_struct *tsk = current;
23981+
23982+ return (tsk->flags & PF_KTHREAD)
23983+ && !strcmp(tsk->comm, "nfsd");
1facf9fc 23984+}
23985+
b752ccd1 23986+void au_xigen_inc(struct inode *inode);
1facf9fc 23987+int au_xigen_new(struct inode *inode);
23988+int au_xigen_set(struct super_block *sb, struct file *base);
23989+void au_xigen_clr(struct super_block *sb);
23990+
23991+static inline int au_busy_or_stale(void)
23992+{
b752ccd1 23993+ if (!au_test_nfsd())
1facf9fc 23994+ return -EBUSY;
23995+ return -ESTALE;
23996+}
23997+#else
4a4d8108 23998+AuStubVoid(au_export_init, struct super_block *sb)
b752ccd1
AM
23999+AuStubInt0(au_test_nfsd, void)
24000+AuStubVoid(au_xigen_inc, struct inode *inode)
4a4d8108
AM
24001+AuStubInt0(au_xigen_new, struct inode *inode)
24002+AuStubInt0(au_xigen_set, struct super_block *sb, struct file *base)
24003+AuStubVoid(au_xigen_clr, struct super_block *sb)
1facf9fc 24004+static inline int au_busy_or_stale(void)
24005+{
24006+ return -EBUSY;
24007+}
24008+#endif /* CONFIG_AUFS_EXPORT */
24009+
24010+/* ---------------------------------------------------------------------- */
24011+
e49829fe
JR
24012+#ifdef CONFIG_AUFS_SBILIST
24013+/* module.c */
24014+extern struct au_splhead au_sbilist;
24015+
24016+static inline void au_sbilist_init(void)
24017+{
24018+ au_spl_init(&au_sbilist);
24019+}
24020+
24021+static inline void au_sbilist_add(struct super_block *sb)
24022+{
24023+ au_spl_add(&au_sbi(sb)->si_list, &au_sbilist);
24024+}
24025+
24026+static inline void au_sbilist_del(struct super_block *sb)
24027+{
24028+ au_spl_del(&au_sbi(sb)->si_list, &au_sbilist);
24029+}
53392da6
AM
24030+
24031+#ifdef CONFIG_AUFS_MAGIC_SYSRQ
24032+static inline void au_sbilist_lock(void)
24033+{
24034+ spin_lock(&au_sbilist.spin);
24035+}
24036+
24037+static inline void au_sbilist_unlock(void)
24038+{
24039+ spin_unlock(&au_sbilist.spin);
24040+}
24041+#define AuGFP_SBILIST GFP_ATOMIC
24042+#else
24043+AuStubVoid(au_sbilist_lock, void)
24044+AuStubVoid(au_sbilist_unlock, void)
24045+#define AuGFP_SBILIST GFP_NOFS
24046+#endif /* CONFIG_AUFS_MAGIC_SYSRQ */
e49829fe
JR
24047+#else
24048+AuStubVoid(au_sbilist_init, void)
24049+AuStubVoid(au_sbilist_add, struct super_block*)
24050+AuStubVoid(au_sbilist_del, struct super_block*)
53392da6
AM
24051+AuStubVoid(au_sbilist_lock, void)
24052+AuStubVoid(au_sbilist_unlock, void)
24053+#define AuGFP_SBILIST GFP_NOFS
e49829fe
JR
24054+#endif
24055+
24056+/* ---------------------------------------------------------------------- */
24057+
1facf9fc 24058+static inline void dbgaufs_si_null(struct au_sbinfo *sbinfo)
24059+{
dece6358
AM
24060+ /*
24061+ * This function is a dynamic '__init' fucntion actually,
24062+ * so the tiny check for si_rwsem is unnecessary.
24063+ */
24064+ /* AuRwMustWriteLock(&sbinfo->si_rwsem); */
1facf9fc 24065+#ifdef CONFIG_DEBUG_FS
24066+ sbinfo->si_dbgaufs = NULL;
24067+ sbinfo->si_dbgaufs_xib = NULL;
24068+#ifdef CONFIG_AUFS_EXPORT
24069+ sbinfo->si_dbgaufs_xigen = NULL;
24070+#endif
24071+#endif
24072+}
24073+
24074+/* ---------------------------------------------------------------------- */
24075+
b752ccd1
AM
24076+static inline pid_t si_pid_bit(void)
24077+{
24078+ /* the origin of pid is 1, but the bitmap's is 0 */
24079+ return current->pid - 1;
24080+}
24081+
24082+static inline int si_pid_test(struct super_block *sb)
24083+{
24084+ pid_t bit = si_pid_bit();
24085+ if (bit < PID_MAX_DEFAULT)
24086+ return test_bit(bit, au_sbi(sb)->au_si_pid.bitmap);
24087+ else
24088+ return si_pid_test_slow(sb);
24089+}
24090+
24091+static inline void si_pid_set(struct super_block *sb)
24092+{
24093+ pid_t bit = si_pid_bit();
24094+ if (bit < PID_MAX_DEFAULT) {
24095+ AuDebugOn(test_bit(bit, au_sbi(sb)->au_si_pid.bitmap));
24096+ set_bit(bit, au_sbi(sb)->au_si_pid.bitmap);
24097+ /* smp_mb(); */
24098+ } else
24099+ si_pid_set_slow(sb);
24100+}
24101+
24102+static inline void si_pid_clr(struct super_block *sb)
24103+{
24104+ pid_t bit = si_pid_bit();
24105+ if (bit < PID_MAX_DEFAULT) {
24106+ AuDebugOn(!test_bit(bit, au_sbi(sb)->au_si_pid.bitmap));
24107+ clear_bit(bit, au_sbi(sb)->au_si_pid.bitmap);
24108+ /* smp_mb(); */
24109+ } else
24110+ si_pid_clr_slow(sb);
24111+}
24112+
24113+/* ---------------------------------------------------------------------- */
24114+
1facf9fc 24115+/* lock superblock. mainly for entry point functions */
24116+/*
b752ccd1
AM
24117+ * __si_read_lock, __si_write_lock,
24118+ * __si_read_unlock, __si_write_unlock, __si_downgrade_lock
1facf9fc 24119+ */
b752ccd1 24120+AuSimpleRwsemFuncs(__si, struct super_block *sb, &au_sbi(sb)->si_rwsem);
1facf9fc 24121+
dece6358
AM
24122+#define SiMustNoWaiters(sb) AuRwMustNoWaiters(&au_sbi(sb)->si_rwsem)
24123+#define SiMustAnyLock(sb) AuRwMustAnyLock(&au_sbi(sb)->si_rwsem)
24124+#define SiMustWriteLock(sb) AuRwMustWriteLock(&au_sbi(sb)->si_rwsem)
24125+
b752ccd1
AM
24126+static inline void si_noflush_read_lock(struct super_block *sb)
24127+{
24128+ __si_read_lock(sb);
24129+ si_pid_set(sb);
24130+}
24131+
24132+static inline int si_noflush_read_trylock(struct super_block *sb)
24133+{
24134+ int locked = __si_read_trylock(sb);
24135+ if (locked)
24136+ si_pid_set(sb);
24137+ return locked;
24138+}
24139+
24140+static inline void si_noflush_write_lock(struct super_block *sb)
24141+{
24142+ __si_write_lock(sb);
24143+ si_pid_set(sb);
24144+}
24145+
24146+static inline int si_noflush_write_trylock(struct super_block *sb)
24147+{
24148+ int locked = __si_write_trylock(sb);
24149+ if (locked)
24150+ si_pid_set(sb);
24151+ return locked;
24152+}
24153+
e49829fe 24154+#if 0 /* unused */
1facf9fc 24155+static inline int si_read_trylock(struct super_block *sb, int flags)
24156+{
24157+ if (au_ftest_lock(flags, FLUSH))
24158+ au_nwt_flush(&au_sbi(sb)->si_nowait);
24159+ return si_noflush_read_trylock(sb);
24160+}
e49829fe 24161+#endif
1facf9fc 24162+
b752ccd1
AM
24163+static inline void si_read_unlock(struct super_block *sb)
24164+{
24165+ si_pid_clr(sb);
24166+ __si_read_unlock(sb);
24167+}
24168+
b752ccd1 24169+#if 0 /* unused */
1facf9fc 24170+static inline int si_write_trylock(struct super_block *sb, int flags)
24171+{
24172+ if (au_ftest_lock(flags, FLUSH))
24173+ au_nwt_flush(&au_sbi(sb)->si_nowait);
24174+ return si_noflush_write_trylock(sb);
24175+}
b752ccd1
AM
24176+#endif
24177+
24178+static inline void si_write_unlock(struct super_block *sb)
24179+{
24180+ si_pid_clr(sb);
24181+ __si_write_unlock(sb);
24182+}
24183+
24184+#if 0 /* unused */
24185+static inline void si_downgrade_lock(struct super_block *sb)
24186+{
24187+ __si_downgrade_lock(sb);
24188+}
24189+#endif
1facf9fc 24190+
24191+/* ---------------------------------------------------------------------- */
24192+
24193+static inline aufs_bindex_t au_sbend(struct super_block *sb)
24194+{
dece6358 24195+ SiMustAnyLock(sb);
1facf9fc 24196+ return au_sbi(sb)->si_bend;
24197+}
24198+
24199+static inline unsigned int au_mntflags(struct super_block *sb)
24200+{
dece6358 24201+ SiMustAnyLock(sb);
1facf9fc 24202+ return au_sbi(sb)->si_mntflags;
24203+}
24204+
24205+static inline unsigned int au_sigen(struct super_block *sb)
24206+{
dece6358 24207+ SiMustAnyLock(sb);
1facf9fc 24208+ return au_sbi(sb)->si_generation;
24209+}
24210+
7f207e10
AM
24211+static inline void au_ninodes_inc(struct super_block *sb)
24212+{
24213+ atomic_long_inc(&au_sbi(sb)->si_ninodes);
24214+}
24215+
24216+static inline void au_ninodes_dec(struct super_block *sb)
24217+{
24218+ AuDebugOn(!atomic_long_read(&au_sbi(sb)->si_ninodes));
24219+ atomic_long_dec(&au_sbi(sb)->si_ninodes);
24220+}
24221+
24222+static inline void au_nfiles_inc(struct super_block *sb)
24223+{
24224+ atomic_long_inc(&au_sbi(sb)->si_nfiles);
24225+}
24226+
24227+static inline void au_nfiles_dec(struct super_block *sb)
24228+{
24229+ AuDebugOn(!atomic_long_read(&au_sbi(sb)->si_nfiles));
24230+ atomic_long_dec(&au_sbi(sb)->si_nfiles);
24231+}
24232+
1facf9fc 24233+static inline struct au_branch *au_sbr(struct super_block *sb,
24234+ aufs_bindex_t bindex)
24235+{
dece6358 24236+ SiMustAnyLock(sb);
1facf9fc 24237+ return au_sbi(sb)->si_branch[0 + bindex];
24238+}
24239+
24240+static inline void au_xino_brid_set(struct super_block *sb, aufs_bindex_t brid)
24241+{
dece6358 24242+ SiMustWriteLock(sb);
1facf9fc 24243+ au_sbi(sb)->si_xino_brid = brid;
24244+}
24245+
24246+static inline aufs_bindex_t au_xino_brid(struct super_block *sb)
24247+{
dece6358 24248+ SiMustAnyLock(sb);
1facf9fc 24249+ return au_sbi(sb)->si_xino_brid;
24250+}
24251+
24252+#endif /* __KERNEL__ */
24253+#endif /* __AUFS_SUPER_H__ */
7f207e10
AM
24254diff -urN /usr/share/empty/fs/aufs/sysaufs.c linux/fs/aufs/sysaufs.c
24255--- /usr/share/empty/fs/aufs/sysaufs.c 1970-01-01 01:00:00.000000000 +0100
2dfbb274 24256+++ linux/fs/aufs/sysaufs.c 2012-08-26 08:39:00.763841498 +0200
f6c5ef8b 24257@@ -0,0 +1,105 @@
1facf9fc 24258+/*
f6c5ef8b 24259+ * Copyright (C) 2005-2012 Junjiro R. Okajima
1facf9fc 24260+ *
24261+ * This program, aufs is free software; you can redistribute it and/or modify
24262+ * it under the terms of the GNU General Public License as published by
24263+ * the Free Software Foundation; either version 2 of the License, or
24264+ * (at your option) any later version.
dece6358
AM
24265+ *
24266+ * This program is distributed in the hope that it will be useful,
24267+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
24268+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24269+ * GNU General Public License for more details.
24270+ *
24271+ * You should have received a copy of the GNU General Public License
24272+ * along with this program; if not, write to the Free Software
24273+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 24274+ */
24275+
24276+/*
24277+ * sysfs interface and lifetime management
24278+ * they are necessary regardless sysfs is disabled.
24279+ */
24280+
1facf9fc 24281+#include <linux/random.h>
1facf9fc 24282+#include "aufs.h"
24283+
24284+unsigned long sysaufs_si_mask;
e49829fe 24285+struct kset *sysaufs_kset;
1facf9fc 24286+
24287+#define AuSiAttr(_name) { \
24288+ .attr = { .name = __stringify(_name), .mode = 0444 }, \
24289+ .show = sysaufs_si_##_name, \
24290+}
24291+
24292+static struct sysaufs_si_attr sysaufs_si_attr_xi_path = AuSiAttr(xi_path);
24293+struct attribute *sysaufs_si_attrs[] = {
24294+ &sysaufs_si_attr_xi_path.attr,
24295+ NULL,
24296+};
24297+
4a4d8108 24298+static const struct sysfs_ops au_sbi_ops = {
1facf9fc 24299+ .show = sysaufs_si_show
24300+};
24301+
24302+static struct kobj_type au_sbi_ktype = {
24303+ .release = au_si_free,
24304+ .sysfs_ops = &au_sbi_ops,
24305+ .default_attrs = sysaufs_si_attrs
24306+};
24307+
24308+/* ---------------------------------------------------------------------- */
24309+
24310+int sysaufs_si_init(struct au_sbinfo *sbinfo)
24311+{
24312+ int err;
24313+
e49829fe 24314+ sbinfo->si_kobj.kset = sysaufs_kset;
1facf9fc 24315+ /* cf. sysaufs_name() */
24316+ err = kobject_init_and_add
e49829fe 24317+ (&sbinfo->si_kobj, &au_sbi_ktype, /*&sysaufs_kset->kobj*/NULL,
1facf9fc 24318+ SysaufsSiNamePrefix "%lx", sysaufs_si_id(sbinfo));
24319+
24320+ dbgaufs_si_null(sbinfo);
24321+ if (!err) {
24322+ err = dbgaufs_si_init(sbinfo);
24323+ if (unlikely(err))
24324+ kobject_put(&sbinfo->si_kobj);
24325+ }
24326+ return err;
24327+}
24328+
24329+void sysaufs_fin(void)
24330+{
24331+ dbgaufs_fin();
e49829fe
JR
24332+ sysfs_remove_group(&sysaufs_kset->kobj, sysaufs_attr_group);
24333+ kset_unregister(sysaufs_kset);
1facf9fc 24334+}
24335+
24336+int __init sysaufs_init(void)
24337+{
24338+ int err;
24339+
24340+ do {
24341+ get_random_bytes(&sysaufs_si_mask, sizeof(sysaufs_si_mask));
24342+ } while (!sysaufs_si_mask);
24343+
4a4d8108 24344+ err = -EINVAL;
e49829fe
JR
24345+ sysaufs_kset = kset_create_and_add(AUFS_NAME, NULL, fs_kobj);
24346+ if (unlikely(!sysaufs_kset))
4a4d8108 24347+ goto out;
e49829fe
JR
24348+ err = PTR_ERR(sysaufs_kset);
24349+ if (IS_ERR(sysaufs_kset))
1facf9fc 24350+ goto out;
e49829fe 24351+ err = sysfs_create_group(&sysaufs_kset->kobj, sysaufs_attr_group);
1facf9fc 24352+ if (unlikely(err)) {
e49829fe 24353+ kset_unregister(sysaufs_kset);
1facf9fc 24354+ goto out;
24355+ }
24356+
24357+ err = dbgaufs_init();
24358+ if (unlikely(err))
24359+ sysaufs_fin();
4f0767ce 24360+out:
1facf9fc 24361+ return err;
24362+}
7f207e10
AM
24363diff -urN /usr/share/empty/fs/aufs/sysaufs.h linux/fs/aufs/sysaufs.h
24364--- /usr/share/empty/fs/aufs/sysaufs.h 1970-01-01 01:00:00.000000000 +0100
2dfbb274 24365+++ linux/fs/aufs/sysaufs.h 2012-08-26 08:39:00.763841498 +0200
f6c5ef8b 24366@@ -0,0 +1,104 @@
1facf9fc 24367+/*
f6c5ef8b 24368+ * Copyright (C) 2005-2012 Junjiro R. Okajima
1facf9fc 24369+ *
24370+ * This program, aufs is free software; you can redistribute it and/or modify
24371+ * it under the terms of the GNU General Public License as published by
24372+ * the Free Software Foundation; either version 2 of the License, or
24373+ * (at your option) any later version.
dece6358
AM
24374+ *
24375+ * This program is distributed in the hope that it will be useful,
24376+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
24377+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24378+ * GNU General Public License for more details.
24379+ *
24380+ * You should have received a copy of the GNU General Public License
24381+ * along with this program; if not, write to the Free Software
24382+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 24383+ */
24384+
24385+/*
24386+ * sysfs interface and mount lifetime management
24387+ */
24388+
24389+#ifndef __SYSAUFS_H__
24390+#define __SYSAUFS_H__
24391+
24392+#ifdef __KERNEL__
24393+
1facf9fc 24394+#include <linux/sysfs.h>
1facf9fc 24395+#include "module.h"
24396+
dece6358
AM
24397+struct super_block;
24398+struct au_sbinfo;
24399+
1facf9fc 24400+struct sysaufs_si_attr {
24401+ struct attribute attr;
24402+ int (*show)(struct seq_file *seq, struct super_block *sb);
24403+};
24404+
24405+/* ---------------------------------------------------------------------- */
24406+
24407+/* sysaufs.c */
24408+extern unsigned long sysaufs_si_mask;
e49829fe 24409+extern struct kset *sysaufs_kset;
1facf9fc 24410+extern struct attribute *sysaufs_si_attrs[];
24411+int sysaufs_si_init(struct au_sbinfo *sbinfo);
24412+int __init sysaufs_init(void);
24413+void sysaufs_fin(void);
24414+
24415+/* ---------------------------------------------------------------------- */
24416+
24417+/* some people doesn't like to show a pointer in kernel */
24418+static inline unsigned long sysaufs_si_id(struct au_sbinfo *sbinfo)
24419+{
24420+ return sysaufs_si_mask ^ (unsigned long)sbinfo;
24421+}
24422+
24423+#define SysaufsSiNamePrefix "si_"
24424+#define SysaufsSiNameLen (sizeof(SysaufsSiNamePrefix) + 16)
24425+static inline void sysaufs_name(struct au_sbinfo *sbinfo, char *name)
24426+{
24427+ snprintf(name, SysaufsSiNameLen, SysaufsSiNamePrefix "%lx",
24428+ sysaufs_si_id(sbinfo));
24429+}
24430+
24431+struct au_branch;
24432+#ifdef CONFIG_SYSFS
24433+/* sysfs.c */
24434+extern struct attribute_group *sysaufs_attr_group;
24435+
24436+int sysaufs_si_xi_path(struct seq_file *seq, struct super_block *sb);
24437+ssize_t sysaufs_si_show(struct kobject *kobj, struct attribute *attr,
24438+ char *buf);
24439+
24440+void sysaufs_br_init(struct au_branch *br);
24441+void sysaufs_brs_add(struct super_block *sb, aufs_bindex_t bindex);
24442+void sysaufs_brs_del(struct super_block *sb, aufs_bindex_t bindex);
24443+
24444+#define sysaufs_brs_init() do {} while (0)
24445+
24446+#else
24447+#define sysaufs_attr_group NULL
24448+
4a4d8108 24449+AuStubInt0(sysaufs_si_xi_path, struct seq_file *seq, struct super_block *sb)
1facf9fc 24450+
24451+static inline
24452+ssize_t sysaufs_si_show(struct kobject *kobj, struct attribute *attr,
24453+ char *buf)
24454+{
24455+ return 0;
24456+}
24457+
4a4d8108
AM
24458+AuStubVoid(sysaufs_br_init, struct au_branch *br)
24459+AuStubVoid(sysaufs_brs_add, struct super_block *sb, aufs_bindex_t bindex)
24460+AuStubVoid(sysaufs_brs_del, struct super_block *sb, aufs_bindex_t bindex)
1facf9fc 24461+
24462+static inline void sysaufs_brs_init(void)
24463+{
24464+ sysaufs_brs = 0;
24465+}
24466+
24467+#endif /* CONFIG_SYSFS */
24468+
24469+#endif /* __KERNEL__ */
24470+#endif /* __SYSAUFS_H__ */
7f207e10
AM
24471diff -urN /usr/share/empty/fs/aufs/sysfs.c linux/fs/aufs/sysfs.c
24472--- /usr/share/empty/fs/aufs/sysfs.c 1970-01-01 01:00:00.000000000 +0100
2dfbb274 24473+++ linux/fs/aufs/sysfs.c 2012-08-26 08:39:00.763841498 +0200
f6c5ef8b 24474@@ -0,0 +1,257 @@
1facf9fc 24475+/*
f6c5ef8b 24476+ * Copyright (C) 2005-2012 Junjiro R. Okajima
1facf9fc 24477+ *
24478+ * This program, aufs is free software; you can redistribute it and/or modify
24479+ * it under the terms of the GNU General Public License as published by
24480+ * the Free Software Foundation; either version 2 of the License, or
24481+ * (at your option) any later version.
dece6358
AM
24482+ *
24483+ * This program is distributed in the hope that it will be useful,
24484+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
24485+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24486+ * GNU General Public License for more details.
24487+ *
24488+ * You should have received a copy of the GNU General Public License
24489+ * along with this program; if not, write to the Free Software
24490+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 24491+ */
24492+
24493+/*
24494+ * sysfs interface
24495+ */
24496+
1facf9fc 24497+#include <linux/seq_file.h>
1facf9fc 24498+#include "aufs.h"
24499+
4a4d8108
AM
24500+#ifdef CONFIG_AUFS_FS_MODULE
24501+/* this entry violates the "one line per file" policy of sysfs */
24502+static ssize_t config_show(struct kobject *kobj, struct kobj_attribute *attr,
24503+ char *buf)
24504+{
24505+ ssize_t err;
24506+ static char *conf =
24507+/* this file is generated at compiling */
24508+#include "conf.str"
24509+ ;
24510+
24511+ err = snprintf(buf, PAGE_SIZE, conf);
24512+ if (unlikely(err >= PAGE_SIZE))
24513+ err = -EFBIG;
24514+ return err;
24515+}
24516+
24517+static struct kobj_attribute au_config_attr = __ATTR_RO(config);
24518+#endif
24519+
1facf9fc 24520+static struct attribute *au_attr[] = {
4a4d8108
AM
24521+#ifdef CONFIG_AUFS_FS_MODULE
24522+ &au_config_attr.attr,
24523+#endif
1facf9fc 24524+ NULL, /* need to NULL terminate the list of attributes */
24525+};
24526+
24527+static struct attribute_group sysaufs_attr_group_body = {
24528+ .attrs = au_attr
24529+};
24530+
24531+struct attribute_group *sysaufs_attr_group = &sysaufs_attr_group_body;
24532+
24533+/* ---------------------------------------------------------------------- */
24534+
24535+int sysaufs_si_xi_path(struct seq_file *seq, struct super_block *sb)
24536+{
24537+ int err;
24538+
dece6358
AM
24539+ SiMustAnyLock(sb);
24540+
1facf9fc 24541+ err = 0;
24542+ if (au_opt_test(au_mntflags(sb), XINO)) {
24543+ err = au_xino_path(seq, au_sbi(sb)->si_xib);
24544+ seq_putc(seq, '\n');
24545+ }
24546+ return err;
24547+}
24548+
24549+/*
24550+ * the lifetime of branch is independent from the entry under sysfs.
24551+ * sysfs handles the lifetime of the entry, and never call ->show() after it is
24552+ * unlinked.
24553+ */
24554+static int sysaufs_si_br(struct seq_file *seq, struct super_block *sb,
24555+ aufs_bindex_t bindex)
24556+{
1e00d052 24557+ int err;
1facf9fc 24558+ struct path path;
24559+ struct dentry *root;
24560+ struct au_branch *br;
1e00d052 24561+ char *perm;
1facf9fc 24562+
24563+ AuDbg("b%d\n", bindex);
24564+
1e00d052 24565+ err = 0;
1facf9fc 24566+ root = sb->s_root;
24567+ di_read_lock_parent(root, !AuLock_IR);
24568+ br = au_sbr(sb, bindex);
24569+ path.mnt = br->br_mnt;
24570+ path.dentry = au_h_dptr(root, bindex);
24571+ au_seq_path(seq, &path);
24572+ di_read_unlock(root, !AuLock_IR);
1e00d052
AM
24573+ perm = au_optstr_br_perm(br->br_perm);
24574+ if (perm) {
24575+ err = seq_printf(seq, "=%s\n", perm);
24576+ kfree(perm);
24577+ if (err == -1)
24578+ err = -E2BIG;
24579+ } else
24580+ err = -ENOMEM;
24581+ return err;
1facf9fc 24582+}
24583+
24584+/* ---------------------------------------------------------------------- */
24585+
24586+static struct seq_file *au_seq(char *p, ssize_t len)
24587+{
24588+ struct seq_file *seq;
24589+
24590+ seq = kzalloc(sizeof(*seq), GFP_NOFS);
24591+ if (seq) {
24592+ /* mutex_init(&seq.lock); */
24593+ seq->buf = p;
24594+ seq->size = len;
24595+ return seq; /* success */
24596+ }
24597+
24598+ seq = ERR_PTR(-ENOMEM);
24599+ return seq;
24600+}
24601+
24602+#define SysaufsBr_PREFIX "br"
24603+
24604+/* todo: file size may exceed PAGE_SIZE */
24605+ssize_t sysaufs_si_show(struct kobject *kobj, struct attribute *attr,
1308ab2a 24606+ char *buf)
1facf9fc 24607+{
24608+ ssize_t err;
24609+ long l;
24610+ aufs_bindex_t bend;
24611+ struct au_sbinfo *sbinfo;
24612+ struct super_block *sb;
24613+ struct seq_file *seq;
24614+ char *name;
24615+ struct attribute **cattr;
24616+
24617+ sbinfo = container_of(kobj, struct au_sbinfo, si_kobj);
24618+ sb = sbinfo->si_sb;
1308ab2a 24619+
24620+ /*
24621+ * prevent a race condition between sysfs and aufs.
24622+ * for instance, sysfs_file_read() calls sysfs_get_active_two() which
24623+ * prohibits maintaining the sysfs entries.
24624+ * hew we acquire read lock after sysfs_get_active_two().
24625+ * on the other hand, the remount process may maintain the sysfs/aufs
24626+ * entries after acquiring write lock.
24627+ * it can cause a deadlock.
24628+ * simply we gave up processing read here.
24629+ */
24630+ err = -EBUSY;
24631+ if (unlikely(!si_noflush_read_trylock(sb)))
24632+ goto out;
1facf9fc 24633+
24634+ seq = au_seq(buf, PAGE_SIZE);
24635+ err = PTR_ERR(seq);
24636+ if (IS_ERR(seq))
1308ab2a 24637+ goto out_unlock;
1facf9fc 24638+
24639+ name = (void *)attr->name;
24640+ cattr = sysaufs_si_attrs;
24641+ while (*cattr) {
24642+ if (!strcmp(name, (*cattr)->name)) {
24643+ err = container_of(*cattr, struct sysaufs_si_attr, attr)
24644+ ->show(seq, sb);
24645+ goto out_seq;
24646+ }
24647+ cattr++;
24648+ }
24649+
24650+ bend = au_sbend(sb);
24651+ if (!strncmp(name, SysaufsBr_PREFIX, sizeof(SysaufsBr_PREFIX) - 1)) {
24652+ name += sizeof(SysaufsBr_PREFIX) - 1;
9dbd164d 24653+ err = kstrtol(name, 10, &l);
1facf9fc 24654+ if (!err) {
24655+ if (l <= bend)
24656+ err = sysaufs_si_br(seq, sb, (aufs_bindex_t)l);
24657+ else
24658+ err = -ENOENT;
24659+ }
24660+ goto out_seq;
24661+ }
24662+ BUG();
24663+
4f0767ce 24664+out_seq:
1facf9fc 24665+ if (!err) {
24666+ err = seq->count;
24667+ /* sysfs limit */
24668+ if (unlikely(err == PAGE_SIZE))
24669+ err = -EFBIG;
24670+ }
24671+ kfree(seq);
4f0767ce 24672+out_unlock:
1facf9fc 24673+ si_read_unlock(sb);
4f0767ce 24674+out:
1facf9fc 24675+ return err;
24676+}
24677+
24678+/* ---------------------------------------------------------------------- */
24679+
24680+void sysaufs_br_init(struct au_branch *br)
24681+{
4a4d8108
AM
24682+ struct attribute *attr = &br->br_attr;
24683+
24684+ sysfs_attr_init(attr);
24685+ attr->name = br->br_name;
24686+ attr->mode = S_IRUGO;
1facf9fc 24687+}
24688+
24689+void sysaufs_brs_del(struct super_block *sb, aufs_bindex_t bindex)
24690+{
24691+ struct au_branch *br;
24692+ struct kobject *kobj;
24693+ aufs_bindex_t bend;
24694+
24695+ dbgaufs_brs_del(sb, bindex);
24696+
24697+ if (!sysaufs_brs)
24698+ return;
24699+
24700+ kobj = &au_sbi(sb)->si_kobj;
24701+ bend = au_sbend(sb);
24702+ for (; bindex <= bend; bindex++) {
24703+ br = au_sbr(sb, bindex);
24704+ sysfs_remove_file(kobj, &br->br_attr);
24705+ }
24706+}
24707+
24708+void sysaufs_brs_add(struct super_block *sb, aufs_bindex_t bindex)
24709+{
24710+ int err;
24711+ aufs_bindex_t bend;
24712+ struct kobject *kobj;
24713+ struct au_branch *br;
24714+
24715+ dbgaufs_brs_add(sb, bindex);
24716+
24717+ if (!sysaufs_brs)
24718+ return;
24719+
24720+ kobj = &au_sbi(sb)->si_kobj;
24721+ bend = au_sbend(sb);
24722+ for (; bindex <= bend; bindex++) {
24723+ br = au_sbr(sb, bindex);
24724+ snprintf(br->br_name, sizeof(br->br_name), SysaufsBr_PREFIX
24725+ "%d", bindex);
24726+ err = sysfs_create_file(kobj, &br->br_attr);
24727+ if (unlikely(err))
0c3ec466
AM
24728+ pr_warn("failed %s under sysfs(%d)\n",
24729+ br->br_name, err);
1facf9fc 24730+ }
24731+}
7f207e10
AM
24732diff -urN /usr/share/empty/fs/aufs/sysrq.c linux/fs/aufs/sysrq.c
24733--- /usr/share/empty/fs/aufs/sysrq.c 1970-01-01 01:00:00.000000000 +0100
b4510431 24734+++ linux/fs/aufs/sysrq.c 2012-10-17 10:31:01.775814563 +0200
f6c5ef8b 24735@@ -0,0 +1,148 @@
1facf9fc 24736+/*
f6c5ef8b 24737+ * Copyright (C) 2005-2012 Junjiro R. Okajima
1facf9fc 24738+ *
24739+ * This program, aufs is free software; you can redistribute it and/or modify
24740+ * it under the terms of the GNU General Public License as published by
24741+ * the Free Software Foundation; either version 2 of the License, or
24742+ * (at your option) any later version.
dece6358
AM
24743+ *
24744+ * This program is distributed in the hope that it will be useful,
24745+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
24746+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24747+ * GNU General Public License for more details.
24748+ *
24749+ * You should have received a copy of the GNU General Public License
24750+ * along with this program; if not, write to the Free Software
24751+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 24752+ */
24753+
24754+/*
24755+ * magic sysrq hanlder
24756+ */
24757+
1facf9fc 24758+/* #include <linux/sysrq.h> */
027c5e7a 24759+#include <linux/writeback.h>
1facf9fc 24760+#include "aufs.h"
24761+
24762+/* ---------------------------------------------------------------------- */
24763+
24764+static void sysrq_sb(struct super_block *sb)
24765+{
24766+ char *plevel;
24767+ struct au_sbinfo *sbinfo;
24768+ struct file *file;
24769+
24770+ plevel = au_plevel;
24771+ au_plevel = KERN_WARNING;
1facf9fc 24772+
24773+ sbinfo = au_sbi(sb);
4a4d8108
AM
24774+ /* since we define pr_fmt, call printk directly */
24775+ printk(KERN_WARNING "si=%lx\n", sysaufs_si_id(sbinfo));
24776+ printk(KERN_WARNING AUFS_NAME ": superblock\n");
1facf9fc 24777+ au_dpri_sb(sb);
027c5e7a
AM
24778+
24779+#if 0
4a4d8108 24780+ printk(KERN_WARNING AUFS_NAME ": root dentry\n");
1facf9fc 24781+ au_dpri_dentry(sb->s_root);
4a4d8108 24782+ printk(KERN_WARNING AUFS_NAME ": root inode\n");
1facf9fc 24783+ au_dpri_inode(sb->s_root->d_inode);
027c5e7a
AM
24784+#endif
24785+
1facf9fc 24786+#if 0
027c5e7a
AM
24787+ do {
24788+ int err, i, j, ndentry;
24789+ struct au_dcsub_pages dpages;
24790+ struct au_dpage *dpage;
24791+
24792+ err = au_dpages_init(&dpages, GFP_ATOMIC);
24793+ if (unlikely(err))
24794+ break;
24795+ err = au_dcsub_pages(&dpages, sb->s_root, NULL, NULL);
24796+ if (!err)
24797+ for (i = 0; i < dpages.ndpage; i++) {
24798+ dpage = dpages.dpages + i;
24799+ ndentry = dpage->ndentry;
24800+ for (j = 0; j < ndentry; j++)
24801+ au_dpri_dentry(dpage->dentries[j]);
24802+ }
24803+ au_dpages_free(&dpages);
24804+ } while (0);
24805+#endif
24806+
24807+#if 1
24808+ {
24809+ struct inode *i;
24810+ printk(KERN_WARNING AUFS_NAME ": isolated inode\n");
2cbb1c4b
JR
24811+ spin_lock(&inode_sb_list_lock);
24812+ list_for_each_entry(i, &sb->s_inodes, i_sb_list) {
24813+ spin_lock(&i->i_lock);
b4510431 24814+ if (1 || hlist_empty(&i->i_dentry))
027c5e7a 24815+ au_dpri_inode(i);
2cbb1c4b
JR
24816+ spin_unlock(&i->i_lock);
24817+ }
24818+ spin_unlock(&inode_sb_list_lock);
027c5e7a 24819+ }
1facf9fc 24820+#endif
4a4d8108 24821+ printk(KERN_WARNING AUFS_NAME ": files\n");
0c3ec466 24822+ lg_global_lock(&files_lglock);
0c5527e5 24823+ do_file_list_for_each_entry(sb, file) {
4a4d8108
AM
24824+ umode_t mode;
24825+ mode = file->f_dentry->d_inode->i_mode;
24826+ if (!special_file(mode) || au_special_file(mode))
1facf9fc 24827+ au_dpri_file(file);
0c5527e5 24828+ } while_file_list_for_each_entry;
0c3ec466 24829+ lg_global_unlock(&files_lglock);
e49829fe 24830+ printk(KERN_WARNING AUFS_NAME ": done\n");
1facf9fc 24831+
24832+ au_plevel = plevel;
1facf9fc 24833+}
24834+
24835+/* ---------------------------------------------------------------------- */
24836+
24837+/* module parameter */
24838+static char *aufs_sysrq_key = "a";
24839+module_param_named(sysrq, aufs_sysrq_key, charp, S_IRUGO);
24840+MODULE_PARM_DESC(sysrq, "MagicSysRq key for " AUFS_NAME);
24841+
0c5527e5 24842+static void au_sysrq(int key __maybe_unused)
1facf9fc 24843+{
1facf9fc 24844+ struct au_sbinfo *sbinfo;
24845+
027c5e7a 24846+ lockdep_off();
53392da6 24847+ au_sbilist_lock();
e49829fe 24848+ list_for_each_entry(sbinfo, &au_sbilist.head, si_list)
1facf9fc 24849+ sysrq_sb(sbinfo->si_sb);
53392da6 24850+ au_sbilist_unlock();
027c5e7a 24851+ lockdep_on();
1facf9fc 24852+}
24853+
24854+static struct sysrq_key_op au_sysrq_op = {
24855+ .handler = au_sysrq,
24856+ .help_msg = "Aufs",
24857+ .action_msg = "Aufs",
24858+ .enable_mask = SYSRQ_ENABLE_DUMP
24859+};
24860+
24861+/* ---------------------------------------------------------------------- */
24862+
24863+int __init au_sysrq_init(void)
24864+{
24865+ int err;
24866+ char key;
24867+
24868+ err = -1;
24869+ key = *aufs_sysrq_key;
24870+ if ('a' <= key && key <= 'z')
24871+ err = register_sysrq_key(key, &au_sysrq_op);
24872+ if (unlikely(err))
4a4d8108 24873+ pr_err("err %d, sysrq=%c\n", err, key);
1facf9fc 24874+ return err;
24875+}
24876+
24877+void au_sysrq_fin(void)
24878+{
24879+ int err;
24880+ err = unregister_sysrq_key(*aufs_sysrq_key, &au_sysrq_op);
24881+ if (unlikely(err))
4a4d8108 24882+ pr_err("err %d (ignored)\n", err);
1facf9fc 24883+}
7f207e10
AM
24884diff -urN /usr/share/empty/fs/aufs/vdir.c linux/fs/aufs/vdir.c
24885--- /usr/share/empty/fs/aufs/vdir.c 1970-01-01 01:00:00.000000000 +0100
2dfbb274 24886+++ linux/fs/aufs/vdir.c 2012-08-26 08:39:00.763841498 +0200
f6c5ef8b 24887@@ -0,0 +1,885 @@
1facf9fc 24888+/*
f6c5ef8b 24889+ * Copyright (C) 2005-2012 Junjiro R. Okajima
1facf9fc 24890+ *
24891+ * This program, aufs is free software; you can redistribute it and/or modify
24892+ * it under the terms of the GNU General Public License as published by
24893+ * the Free Software Foundation; either version 2 of the License, or
24894+ * (at your option) any later version.
dece6358
AM
24895+ *
24896+ * This program is distributed in the hope that it will be useful,
24897+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
24898+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24899+ * GNU General Public License for more details.
24900+ *
24901+ * You should have received a copy of the GNU General Public License
24902+ * along with this program; if not, write to the Free Software
24903+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 24904+ */
24905+
24906+/*
24907+ * virtual or vertical directory
24908+ */
24909+
24910+#include "aufs.h"
24911+
dece6358 24912+static unsigned int calc_size(int nlen)
1facf9fc 24913+{
dece6358 24914+ return ALIGN(sizeof(struct au_vdir_de) + nlen, sizeof(ino_t));
1facf9fc 24915+}
24916+
24917+static int set_deblk_end(union au_vdir_deblk_p *p,
24918+ union au_vdir_deblk_p *deblk_end)
24919+{
24920+ if (calc_size(0) <= deblk_end->deblk - p->deblk) {
24921+ p->de->de_str.len = 0;
24922+ /* smp_mb(); */
24923+ return 0;
24924+ }
24925+ return -1; /* error */
24926+}
24927+
24928+/* returns true or false */
24929+static int is_deblk_end(union au_vdir_deblk_p *p,
24930+ union au_vdir_deblk_p *deblk_end)
24931+{
24932+ if (calc_size(0) <= deblk_end->deblk - p->deblk)
24933+ return !p->de->de_str.len;
24934+ return 1;
24935+}
24936+
24937+static unsigned char *last_deblk(struct au_vdir *vdir)
24938+{
24939+ return vdir->vd_deblk[vdir->vd_nblk - 1];
24940+}
24941+
24942+/* ---------------------------------------------------------------------- */
24943+
1308ab2a 24944+/* estimate the apropriate size for name hash table */
24945+unsigned int au_rdhash_est(loff_t sz)
24946+{
24947+ unsigned int n;
24948+
24949+ n = UINT_MAX;
24950+ sz >>= 10;
24951+ if (sz < n)
24952+ n = sz;
24953+ if (sz < AUFS_RDHASH_DEF)
24954+ n = AUFS_RDHASH_DEF;
4a4d8108 24955+ /* pr_info("n %u\n", n); */
1308ab2a 24956+ return n;
24957+}
24958+
1facf9fc 24959+/*
24960+ * the allocated memory has to be freed by
dece6358 24961+ * au_nhash_wh_free() or au_nhash_de_free().
1facf9fc 24962+ */
dece6358 24963+int au_nhash_alloc(struct au_nhash *nhash, unsigned int num_hash, gfp_t gfp)
1facf9fc 24964+{
1facf9fc 24965+ struct hlist_head *head;
dece6358 24966+ unsigned int u;
1facf9fc 24967+
dece6358
AM
24968+ head = kmalloc(sizeof(*nhash->nh_head) * num_hash, gfp);
24969+ if (head) {
24970+ nhash->nh_num = num_hash;
24971+ nhash->nh_head = head;
24972+ for (u = 0; u < num_hash; u++)
1facf9fc 24973+ INIT_HLIST_HEAD(head++);
dece6358 24974+ return 0; /* success */
1facf9fc 24975+ }
1facf9fc 24976+
dece6358 24977+ return -ENOMEM;
1facf9fc 24978+}
24979+
dece6358
AM
24980+static void nhash_count(struct hlist_head *head)
24981+{
24982+#if 0
24983+ unsigned long n;
24984+ struct hlist_node *pos;
24985+
24986+ n = 0;
24987+ hlist_for_each(pos, head)
24988+ n++;
4a4d8108 24989+ pr_info("%lu\n", n);
dece6358
AM
24990+#endif
24991+}
24992+
24993+static void au_nhash_wh_do_free(struct hlist_head *head)
1facf9fc 24994+{
1facf9fc 24995+ struct au_vdir_wh *tpos;
24996+ struct hlist_node *pos, *node;
24997+
dece6358
AM
24998+ hlist_for_each_entry_safe(tpos, pos, node, head, wh_hash) {
24999+ /* hlist_del(pos); */
25000+ kfree(tpos);
1facf9fc 25001+ }
25002+}
25003+
dece6358 25004+static void au_nhash_de_do_free(struct hlist_head *head)
1facf9fc 25005+{
dece6358
AM
25006+ struct au_vdir_dehstr *tpos;
25007+ struct hlist_node *pos, *node;
1facf9fc 25008+
dece6358
AM
25009+ hlist_for_each_entry_safe(tpos, pos, node, head, hash) {
25010+ /* hlist_del(pos); */
4a4d8108 25011+ au_cache_free_vdir_dehstr(tpos);
1facf9fc 25012+ }
1facf9fc 25013+}
25014+
dece6358
AM
25015+static void au_nhash_do_free(struct au_nhash *nhash,
25016+ void (*free)(struct hlist_head *head))
1facf9fc 25017+{
1308ab2a 25018+ unsigned int n;
1facf9fc 25019+ struct hlist_head *head;
1facf9fc 25020+
dece6358 25021+ n = nhash->nh_num;
1308ab2a 25022+ if (!n)
25023+ return;
25024+
dece6358 25025+ head = nhash->nh_head;
1308ab2a 25026+ while (n-- > 0) {
dece6358
AM
25027+ nhash_count(head);
25028+ free(head++);
1facf9fc 25029+ }
dece6358 25030+ kfree(nhash->nh_head);
1facf9fc 25031+}
25032+
dece6358 25033+void au_nhash_wh_free(struct au_nhash *whlist)
1facf9fc 25034+{
dece6358
AM
25035+ au_nhash_do_free(whlist, au_nhash_wh_do_free);
25036+}
1facf9fc 25037+
dece6358
AM
25038+static void au_nhash_de_free(struct au_nhash *delist)
25039+{
25040+ au_nhash_do_free(delist, au_nhash_de_do_free);
1facf9fc 25041+}
25042+
25043+/* ---------------------------------------------------------------------- */
25044+
25045+int au_nhash_test_longer_wh(struct au_nhash *whlist, aufs_bindex_t btgt,
25046+ int limit)
25047+{
25048+ int num;
25049+ unsigned int u, n;
25050+ struct hlist_head *head;
25051+ struct au_vdir_wh *tpos;
25052+ struct hlist_node *pos;
25053+
25054+ num = 0;
25055+ n = whlist->nh_num;
25056+ head = whlist->nh_head;
1308ab2a 25057+ for (u = 0; u < n; u++, head++)
1facf9fc 25058+ hlist_for_each_entry(tpos, pos, head, wh_hash)
25059+ if (tpos->wh_bindex == btgt && ++num > limit)
25060+ return 1;
1facf9fc 25061+ return 0;
25062+}
25063+
25064+static struct hlist_head *au_name_hash(struct au_nhash *nhash,
dece6358 25065+ unsigned char *name,
1facf9fc 25066+ unsigned int len)
25067+{
dece6358
AM
25068+ unsigned int v;
25069+ /* const unsigned int magic_bit = 12; */
25070+
1308ab2a 25071+ AuDebugOn(!nhash->nh_num || !nhash->nh_head);
25072+
dece6358
AM
25073+ v = 0;
25074+ while (len--)
25075+ v += *name++;
25076+ /* v = hash_long(v, magic_bit); */
25077+ v %= nhash->nh_num;
25078+ return nhash->nh_head + v;
25079+}
25080+
25081+static int au_nhash_test_name(struct au_vdir_destr *str, const char *name,
25082+ int nlen)
25083+{
25084+ return str->len == nlen && !memcmp(str->name, name, nlen);
1facf9fc 25085+}
25086+
25087+/* returns found or not */
dece6358 25088+int au_nhash_test_known_wh(struct au_nhash *whlist, char *name, int nlen)
1facf9fc 25089+{
25090+ struct hlist_head *head;
25091+ struct au_vdir_wh *tpos;
25092+ struct hlist_node *pos;
25093+ struct au_vdir_destr *str;
25094+
dece6358 25095+ head = au_name_hash(whlist, name, nlen);
1facf9fc 25096+ hlist_for_each_entry(tpos, pos, head, wh_hash) {
25097+ str = &tpos->wh_str;
25098+ AuDbg("%.*s\n", str->len, str->name);
dece6358
AM
25099+ if (au_nhash_test_name(str, name, nlen))
25100+ return 1;
25101+ }
25102+ return 0;
25103+}
25104+
25105+/* returns found(true) or not */
25106+static int test_known(struct au_nhash *delist, char *name, int nlen)
25107+{
25108+ struct hlist_head *head;
25109+ struct au_vdir_dehstr *tpos;
25110+ struct hlist_node *pos;
25111+ struct au_vdir_destr *str;
25112+
25113+ head = au_name_hash(delist, name, nlen);
25114+ hlist_for_each_entry(tpos, pos, head, hash) {
25115+ str = tpos->str;
25116+ AuDbg("%.*s\n", str->len, str->name);
25117+ if (au_nhash_test_name(str, name, nlen))
1facf9fc 25118+ return 1;
25119+ }
25120+ return 0;
25121+}
25122+
dece6358
AM
25123+static void au_shwh_init_wh(struct au_vdir_wh *wh, ino_t ino,
25124+ unsigned char d_type)
25125+{
25126+#ifdef CONFIG_AUFS_SHWH
25127+ wh->wh_ino = ino;
25128+ wh->wh_type = d_type;
25129+#endif
25130+}
25131+
25132+/* ---------------------------------------------------------------------- */
25133+
25134+int au_nhash_append_wh(struct au_nhash *whlist, char *name, int nlen, ino_t ino,
25135+ unsigned int d_type, aufs_bindex_t bindex,
25136+ unsigned char shwh)
1facf9fc 25137+{
25138+ int err;
25139+ struct au_vdir_destr *str;
25140+ struct au_vdir_wh *wh;
25141+
dece6358 25142+ AuDbg("%.*s\n", nlen, name);
1308ab2a 25143+ AuDebugOn(!whlist->nh_num || !whlist->nh_head);
25144+
1facf9fc 25145+ err = -ENOMEM;
dece6358 25146+ wh = kmalloc(sizeof(*wh) + nlen, GFP_NOFS);
1facf9fc 25147+ if (unlikely(!wh))
25148+ goto out;
25149+
25150+ err = 0;
25151+ wh->wh_bindex = bindex;
dece6358
AM
25152+ if (shwh)
25153+ au_shwh_init_wh(wh, ino, d_type);
1facf9fc 25154+ str = &wh->wh_str;
dece6358
AM
25155+ str->len = nlen;
25156+ memcpy(str->name, name, nlen);
25157+ hlist_add_head(&wh->wh_hash, au_name_hash(whlist, name, nlen));
1facf9fc 25158+ /* smp_mb(); */
25159+
4f0767ce 25160+out:
1facf9fc 25161+ return err;
25162+}
25163+
1facf9fc 25164+static int append_deblk(struct au_vdir *vdir)
25165+{
25166+ int err;
dece6358 25167+ unsigned long ul;
1facf9fc 25168+ const unsigned int deblk_sz = vdir->vd_deblk_sz;
25169+ union au_vdir_deblk_p p, deblk_end;
25170+ unsigned char **o;
25171+
25172+ err = -ENOMEM;
dece6358
AM
25173+ o = krealloc(vdir->vd_deblk, sizeof(*o) * (vdir->vd_nblk + 1),
25174+ GFP_NOFS);
1facf9fc 25175+ if (unlikely(!o))
25176+ goto out;
25177+
25178+ vdir->vd_deblk = o;
25179+ p.deblk = kmalloc(deblk_sz, GFP_NOFS);
25180+ if (p.deblk) {
25181+ ul = vdir->vd_nblk++;
25182+ vdir->vd_deblk[ul] = p.deblk;
25183+ vdir->vd_last.ul = ul;
25184+ vdir->vd_last.p.deblk = p.deblk;
25185+ deblk_end.deblk = p.deblk + deblk_sz;
25186+ err = set_deblk_end(&p, &deblk_end);
25187+ }
25188+
4f0767ce 25189+out:
1facf9fc 25190+ return err;
25191+}
25192+
dece6358
AM
25193+static int append_de(struct au_vdir *vdir, char *name, int nlen, ino_t ino,
25194+ unsigned int d_type, struct au_nhash *delist)
25195+{
25196+ int err;
25197+ unsigned int sz;
25198+ const unsigned int deblk_sz = vdir->vd_deblk_sz;
25199+ union au_vdir_deblk_p p, *room, deblk_end;
25200+ struct au_vdir_dehstr *dehstr;
25201+
25202+ p.deblk = last_deblk(vdir);
25203+ deblk_end.deblk = p.deblk + deblk_sz;
25204+ room = &vdir->vd_last.p;
25205+ AuDebugOn(room->deblk < p.deblk || deblk_end.deblk <= room->deblk
25206+ || !is_deblk_end(room, &deblk_end));
25207+
25208+ sz = calc_size(nlen);
25209+ if (unlikely(sz > deblk_end.deblk - room->deblk)) {
25210+ err = append_deblk(vdir);
25211+ if (unlikely(err))
25212+ goto out;
25213+
25214+ p.deblk = last_deblk(vdir);
25215+ deblk_end.deblk = p.deblk + deblk_sz;
25216+ /* smp_mb(); */
25217+ AuDebugOn(room->deblk != p.deblk);
25218+ }
25219+
25220+ err = -ENOMEM;
4a4d8108 25221+ dehstr = au_cache_alloc_vdir_dehstr();
dece6358
AM
25222+ if (unlikely(!dehstr))
25223+ goto out;
25224+
25225+ dehstr->str = &room->de->de_str;
25226+ hlist_add_head(&dehstr->hash, au_name_hash(delist, name, nlen));
25227+ room->de->de_ino = ino;
25228+ room->de->de_type = d_type;
25229+ room->de->de_str.len = nlen;
25230+ memcpy(room->de->de_str.name, name, nlen);
25231+
25232+ err = 0;
25233+ room->deblk += sz;
25234+ if (unlikely(set_deblk_end(room, &deblk_end)))
25235+ err = append_deblk(vdir);
25236+ /* smp_mb(); */
25237+
4f0767ce 25238+out:
dece6358
AM
25239+ return err;
25240+}
25241+
25242+/* ---------------------------------------------------------------------- */
25243+
25244+void au_vdir_free(struct au_vdir *vdir)
25245+{
25246+ unsigned char **deblk;
25247+
25248+ deblk = vdir->vd_deblk;
25249+ while (vdir->vd_nblk--)
25250+ kfree(*deblk++);
25251+ kfree(vdir->vd_deblk);
25252+ au_cache_free_vdir(vdir);
25253+}
25254+
1308ab2a 25255+static struct au_vdir *alloc_vdir(struct file *file)
1facf9fc 25256+{
25257+ struct au_vdir *vdir;
1308ab2a 25258+ struct super_block *sb;
1facf9fc 25259+ int err;
25260+
1308ab2a 25261+ sb = file->f_dentry->d_sb;
dece6358
AM
25262+ SiMustAnyLock(sb);
25263+
1facf9fc 25264+ err = -ENOMEM;
25265+ vdir = au_cache_alloc_vdir();
25266+ if (unlikely(!vdir))
25267+ goto out;
25268+
25269+ vdir->vd_deblk = kzalloc(sizeof(*vdir->vd_deblk), GFP_NOFS);
25270+ if (unlikely(!vdir->vd_deblk))
25271+ goto out_free;
25272+
25273+ vdir->vd_deblk_sz = au_sbi(sb)->si_rdblk;
1308ab2a 25274+ if (!vdir->vd_deblk_sz) {
25275+ /* estimate the apropriate size for deblk */
25276+ vdir->vd_deblk_sz = au_dir_size(file, /*dentry*/NULL);
4a4d8108 25277+ /* pr_info("vd_deblk_sz %u\n", vdir->vd_deblk_sz); */
1308ab2a 25278+ }
1facf9fc 25279+ vdir->vd_nblk = 0;
25280+ vdir->vd_version = 0;
25281+ vdir->vd_jiffy = 0;
25282+ err = append_deblk(vdir);
25283+ if (!err)
25284+ return vdir; /* success */
25285+
25286+ kfree(vdir->vd_deblk);
25287+
4f0767ce 25288+out_free:
1facf9fc 25289+ au_cache_free_vdir(vdir);
4f0767ce 25290+out:
1facf9fc 25291+ vdir = ERR_PTR(err);
25292+ return vdir;
25293+}
25294+
25295+static int reinit_vdir(struct au_vdir *vdir)
25296+{
25297+ int err;
25298+ union au_vdir_deblk_p p, deblk_end;
25299+
25300+ while (vdir->vd_nblk > 1) {
25301+ kfree(vdir->vd_deblk[vdir->vd_nblk - 1]);
25302+ /* vdir->vd_deblk[vdir->vd_nblk - 1] = NULL; */
25303+ vdir->vd_nblk--;
25304+ }
25305+ p.deblk = vdir->vd_deblk[0];
25306+ deblk_end.deblk = p.deblk + vdir->vd_deblk_sz;
25307+ err = set_deblk_end(&p, &deblk_end);
25308+ /* keep vd_dblk_sz */
25309+ vdir->vd_last.ul = 0;
25310+ vdir->vd_last.p.deblk = vdir->vd_deblk[0];
25311+ vdir->vd_version = 0;
25312+ vdir->vd_jiffy = 0;
25313+ /* smp_mb(); */
25314+ return err;
25315+}
25316+
25317+/* ---------------------------------------------------------------------- */
25318+
1facf9fc 25319+#define AuFillVdir_CALLED 1
25320+#define AuFillVdir_WHABLE (1 << 1)
dece6358 25321+#define AuFillVdir_SHWH (1 << 2)
1facf9fc 25322+#define au_ftest_fillvdir(flags, name) ((flags) & AuFillVdir_##name)
7f207e10
AM
25323+#define au_fset_fillvdir(flags, name) \
25324+ do { (flags) |= AuFillVdir_##name; } while (0)
25325+#define au_fclr_fillvdir(flags, name) \
25326+ do { (flags) &= ~AuFillVdir_##name; } while (0)
1facf9fc 25327+
dece6358
AM
25328+#ifndef CONFIG_AUFS_SHWH
25329+#undef AuFillVdir_SHWH
25330+#define AuFillVdir_SHWH 0
25331+#endif
25332+
1facf9fc 25333+struct fillvdir_arg {
25334+ struct file *file;
25335+ struct au_vdir *vdir;
dece6358
AM
25336+ struct au_nhash delist;
25337+ struct au_nhash whlist;
1facf9fc 25338+ aufs_bindex_t bindex;
25339+ unsigned int flags;
25340+ int err;
25341+};
25342+
dece6358 25343+static int fillvdir(void *__arg, const char *__name, int nlen,
1facf9fc 25344+ loff_t offset __maybe_unused, u64 h_ino,
25345+ unsigned int d_type)
25346+{
25347+ struct fillvdir_arg *arg = __arg;
25348+ char *name = (void *)__name;
25349+ struct super_block *sb;
1facf9fc 25350+ ino_t ino;
dece6358 25351+ const unsigned char shwh = !!au_ftest_fillvdir(arg->flags, SHWH);
1facf9fc 25352+
1facf9fc 25353+ arg->err = 0;
dece6358 25354+ sb = arg->file->f_dentry->d_sb;
1facf9fc 25355+ au_fset_fillvdir(arg->flags, CALLED);
25356+ /* smp_mb(); */
dece6358 25357+ if (nlen <= AUFS_WH_PFX_LEN
1facf9fc 25358+ || memcmp(name, AUFS_WH_PFX, AUFS_WH_PFX_LEN)) {
dece6358
AM
25359+ if (test_known(&arg->delist, name, nlen)
25360+ || au_nhash_test_known_wh(&arg->whlist, name, nlen))
25361+ goto out; /* already exists or whiteouted */
1facf9fc 25362+
25363+ sb = arg->file->f_dentry->d_sb;
dece6358 25364+ arg->err = au_ino(sb, arg->bindex, h_ino, d_type, &ino);
4a4d8108
AM
25365+ if (!arg->err) {
25366+ if (unlikely(nlen > AUFS_MAX_NAMELEN))
25367+ d_type = DT_UNKNOWN;
dece6358
AM
25368+ arg->err = append_de(arg->vdir, name, nlen, ino,
25369+ d_type, &arg->delist);
4a4d8108 25370+ }
1facf9fc 25371+ } else if (au_ftest_fillvdir(arg->flags, WHABLE)) {
25372+ name += AUFS_WH_PFX_LEN;
dece6358
AM
25373+ nlen -= AUFS_WH_PFX_LEN;
25374+ if (au_nhash_test_known_wh(&arg->whlist, name, nlen))
25375+ goto out; /* already whiteouted */
1facf9fc 25376+
dece6358
AM
25377+ if (shwh)
25378+ arg->err = au_wh_ino(sb, arg->bindex, h_ino, d_type,
25379+ &ino);
4a4d8108
AM
25380+ if (!arg->err) {
25381+ if (nlen <= AUFS_MAX_NAMELEN + AUFS_WH_PFX_LEN)
25382+ d_type = DT_UNKNOWN;
1facf9fc 25383+ arg->err = au_nhash_append_wh
dece6358
AM
25384+ (&arg->whlist, name, nlen, ino, d_type,
25385+ arg->bindex, shwh);
4a4d8108 25386+ }
1facf9fc 25387+ }
25388+
4f0767ce 25389+out:
1facf9fc 25390+ if (!arg->err)
25391+ arg->vdir->vd_jiffy = jiffies;
25392+ /* smp_mb(); */
25393+ AuTraceErr(arg->err);
25394+ return arg->err;
25395+}
25396+
dece6358
AM
25397+static int au_handle_shwh(struct super_block *sb, struct au_vdir *vdir,
25398+ struct au_nhash *whlist, struct au_nhash *delist)
25399+{
25400+#ifdef CONFIG_AUFS_SHWH
25401+ int err;
25402+ unsigned int nh, u;
25403+ struct hlist_head *head;
25404+ struct au_vdir_wh *tpos;
25405+ struct hlist_node *pos, *n;
25406+ char *p, *o;
25407+ struct au_vdir_destr *destr;
25408+
25409+ AuDebugOn(!au_opt_test(au_mntflags(sb), SHWH));
25410+
25411+ err = -ENOMEM;
4a4d8108 25412+ o = p = __getname_gfp(GFP_NOFS);
dece6358
AM
25413+ if (unlikely(!p))
25414+ goto out;
25415+
25416+ err = 0;
25417+ nh = whlist->nh_num;
25418+ memcpy(p, AUFS_WH_PFX, AUFS_WH_PFX_LEN);
25419+ p += AUFS_WH_PFX_LEN;
25420+ for (u = 0; u < nh; u++) {
25421+ head = whlist->nh_head + u;
25422+ hlist_for_each_entry_safe(tpos, pos, n, head, wh_hash) {
25423+ destr = &tpos->wh_str;
25424+ memcpy(p, destr->name, destr->len);
25425+ err = append_de(vdir, o, destr->len + AUFS_WH_PFX_LEN,
25426+ tpos->wh_ino, tpos->wh_type, delist);
25427+ if (unlikely(err))
25428+ break;
25429+ }
25430+ }
25431+
25432+ __putname(o);
25433+
4f0767ce 25434+out:
dece6358
AM
25435+ AuTraceErr(err);
25436+ return err;
25437+#else
25438+ return 0;
25439+#endif
25440+}
25441+
1facf9fc 25442+static int au_do_read_vdir(struct fillvdir_arg *arg)
25443+{
25444+ int err;
dece6358 25445+ unsigned int rdhash;
1facf9fc 25446+ loff_t offset;
dece6358
AM
25447+ aufs_bindex_t bend, bindex, bstart;
25448+ unsigned char shwh;
1facf9fc 25449+ struct file *hf, *file;
25450+ struct super_block *sb;
25451+
1facf9fc 25452+ file = arg->file;
25453+ sb = file->f_dentry->d_sb;
dece6358
AM
25454+ SiMustAnyLock(sb);
25455+
25456+ rdhash = au_sbi(sb)->si_rdhash;
1308ab2a 25457+ if (!rdhash)
25458+ rdhash = au_rdhash_est(au_dir_size(file, /*dentry*/NULL));
dece6358
AM
25459+ err = au_nhash_alloc(&arg->delist, rdhash, GFP_NOFS);
25460+ if (unlikely(err))
1facf9fc 25461+ goto out;
dece6358
AM
25462+ err = au_nhash_alloc(&arg->whlist, rdhash, GFP_NOFS);
25463+ if (unlikely(err))
1facf9fc 25464+ goto out_delist;
25465+
25466+ err = 0;
25467+ arg->flags = 0;
dece6358
AM
25468+ shwh = 0;
25469+ if (au_opt_test(au_mntflags(sb), SHWH)) {
25470+ shwh = 1;
25471+ au_fset_fillvdir(arg->flags, SHWH);
25472+ }
25473+ bstart = au_fbstart(file);
4a4d8108 25474+ bend = au_fbend_dir(file);
dece6358 25475+ for (bindex = bstart; !err && bindex <= bend; bindex++) {
4a4d8108 25476+ hf = au_hf_dir(file, bindex);
1facf9fc 25477+ if (!hf)
25478+ continue;
25479+
25480+ offset = vfsub_llseek(hf, 0, SEEK_SET);
25481+ err = offset;
25482+ if (unlikely(offset))
25483+ break;
25484+
25485+ arg->bindex = bindex;
25486+ au_fclr_fillvdir(arg->flags, WHABLE);
dece6358
AM
25487+ if (shwh
25488+ || (bindex != bend
25489+ && au_br_whable(au_sbr_perm(sb, bindex))))
1facf9fc 25490+ au_fset_fillvdir(arg->flags, WHABLE);
25491+ do {
25492+ arg->err = 0;
25493+ au_fclr_fillvdir(arg->flags, CALLED);
25494+ /* smp_mb(); */
25495+ err = vfsub_readdir(hf, fillvdir, arg);
25496+ if (err >= 0)
25497+ err = arg->err;
25498+ } while (!err && au_ftest_fillvdir(arg->flags, CALLED));
25499+ }
dece6358
AM
25500+
25501+ if (!err && shwh)
25502+ err = au_handle_shwh(sb, arg->vdir, &arg->whlist, &arg->delist);
25503+
25504+ au_nhash_wh_free(&arg->whlist);
1facf9fc 25505+
4f0767ce 25506+out_delist:
dece6358 25507+ au_nhash_de_free(&arg->delist);
4f0767ce 25508+out:
1facf9fc 25509+ return err;
25510+}
25511+
25512+static int read_vdir(struct file *file, int may_read)
25513+{
25514+ int err;
25515+ unsigned long expire;
25516+ unsigned char do_read;
25517+ struct fillvdir_arg arg;
25518+ struct inode *inode;
25519+ struct au_vdir *vdir, *allocated;
25520+
25521+ err = 0;
25522+ inode = file->f_dentry->d_inode;
25523+ IMustLock(inode);
dece6358
AM
25524+ SiMustAnyLock(inode->i_sb);
25525+
1facf9fc 25526+ allocated = NULL;
25527+ do_read = 0;
25528+ expire = au_sbi(inode->i_sb)->si_rdcache;
25529+ vdir = au_ivdir(inode);
25530+ if (!vdir) {
25531+ do_read = 1;
1308ab2a 25532+ vdir = alloc_vdir(file);
1facf9fc 25533+ err = PTR_ERR(vdir);
25534+ if (IS_ERR(vdir))
25535+ goto out;
25536+ err = 0;
25537+ allocated = vdir;
25538+ } else if (may_read
25539+ && (inode->i_version != vdir->vd_version
25540+ || time_after(jiffies, vdir->vd_jiffy + expire))) {
25541+ do_read = 1;
25542+ err = reinit_vdir(vdir);
25543+ if (unlikely(err))
25544+ goto out;
25545+ }
25546+
25547+ if (!do_read)
25548+ return 0; /* success */
25549+
25550+ arg.file = file;
25551+ arg.vdir = vdir;
25552+ err = au_do_read_vdir(&arg);
25553+ if (!err) {
25554+ /* file->f_pos = 0; */
25555+ vdir->vd_version = inode->i_version;
25556+ vdir->vd_last.ul = 0;
25557+ vdir->vd_last.p.deblk = vdir->vd_deblk[0];
25558+ if (allocated)
25559+ au_set_ivdir(inode, allocated);
25560+ } else if (allocated)
25561+ au_vdir_free(allocated);
25562+
4f0767ce 25563+out:
1facf9fc 25564+ return err;
25565+}
25566+
25567+static int copy_vdir(struct au_vdir *tgt, struct au_vdir *src)
25568+{
25569+ int err, rerr;
25570+ unsigned long ul, n;
25571+ const unsigned int deblk_sz = src->vd_deblk_sz;
25572+
25573+ AuDebugOn(tgt->vd_nblk != 1);
25574+
25575+ err = -ENOMEM;
25576+ if (tgt->vd_nblk < src->vd_nblk) {
25577+ unsigned char **p;
25578+
dece6358
AM
25579+ p = krealloc(tgt->vd_deblk, sizeof(*p) * src->vd_nblk,
25580+ GFP_NOFS);
1facf9fc 25581+ if (unlikely(!p))
25582+ goto out;
25583+ tgt->vd_deblk = p;
25584+ }
25585+
1308ab2a 25586+ if (tgt->vd_deblk_sz != deblk_sz) {
25587+ unsigned char *p;
25588+
25589+ tgt->vd_deblk_sz = deblk_sz;
25590+ p = krealloc(tgt->vd_deblk[0], deblk_sz, GFP_NOFS);
25591+ if (unlikely(!p))
25592+ goto out;
25593+ tgt->vd_deblk[0] = p;
25594+ }
1facf9fc 25595+ memcpy(tgt->vd_deblk[0], src->vd_deblk[0], deblk_sz);
1facf9fc 25596+ tgt->vd_version = src->vd_version;
25597+ tgt->vd_jiffy = src->vd_jiffy;
25598+
25599+ n = src->vd_nblk;
25600+ for (ul = 1; ul < n; ul++) {
dece6358
AM
25601+ tgt->vd_deblk[ul] = kmemdup(src->vd_deblk[ul], deblk_sz,
25602+ GFP_NOFS);
25603+ if (unlikely(!tgt->vd_deblk[ul]))
1facf9fc 25604+ goto out;
1308ab2a 25605+ tgt->vd_nblk++;
1facf9fc 25606+ }
1308ab2a 25607+ tgt->vd_nblk = n;
25608+ tgt->vd_last.ul = tgt->vd_last.ul;
25609+ tgt->vd_last.p.deblk = tgt->vd_deblk[tgt->vd_last.ul];
25610+ tgt->vd_last.p.deblk += src->vd_last.p.deblk
25611+ - src->vd_deblk[src->vd_last.ul];
1facf9fc 25612+ /* smp_mb(); */
25613+ return 0; /* success */
25614+
4f0767ce 25615+out:
1facf9fc 25616+ rerr = reinit_vdir(tgt);
25617+ BUG_ON(rerr);
25618+ return err;
25619+}
25620+
25621+int au_vdir_init(struct file *file)
25622+{
25623+ int err;
25624+ struct inode *inode;
25625+ struct au_vdir *vdir_cache, *allocated;
25626+
25627+ err = read_vdir(file, !file->f_pos);
25628+ if (unlikely(err))
25629+ goto out;
25630+
25631+ allocated = NULL;
25632+ vdir_cache = au_fvdir_cache(file);
25633+ if (!vdir_cache) {
1308ab2a 25634+ vdir_cache = alloc_vdir(file);
1facf9fc 25635+ err = PTR_ERR(vdir_cache);
25636+ if (IS_ERR(vdir_cache))
25637+ goto out;
25638+ allocated = vdir_cache;
25639+ } else if (!file->f_pos && vdir_cache->vd_version != file->f_version) {
25640+ err = reinit_vdir(vdir_cache);
25641+ if (unlikely(err))
25642+ goto out;
25643+ } else
25644+ return 0; /* success */
25645+
25646+ inode = file->f_dentry->d_inode;
25647+ err = copy_vdir(vdir_cache, au_ivdir(inode));
25648+ if (!err) {
25649+ file->f_version = inode->i_version;
25650+ if (allocated)
25651+ au_set_fvdir_cache(file, allocated);
25652+ } else if (allocated)
25653+ au_vdir_free(allocated);
25654+
4f0767ce 25655+out:
1facf9fc 25656+ return err;
25657+}
25658+
25659+static loff_t calc_offset(struct au_vdir *vdir)
25660+{
25661+ loff_t offset;
25662+ union au_vdir_deblk_p p;
25663+
25664+ p.deblk = vdir->vd_deblk[vdir->vd_last.ul];
25665+ offset = vdir->vd_last.p.deblk - p.deblk;
25666+ offset += vdir->vd_deblk_sz * vdir->vd_last.ul;
25667+ return offset;
25668+}
25669+
25670+/* returns true or false */
25671+static int seek_vdir(struct file *file)
25672+{
25673+ int valid;
25674+ unsigned int deblk_sz;
25675+ unsigned long ul, n;
25676+ loff_t offset;
25677+ union au_vdir_deblk_p p, deblk_end;
25678+ struct au_vdir *vdir_cache;
25679+
25680+ valid = 1;
25681+ vdir_cache = au_fvdir_cache(file);
25682+ offset = calc_offset(vdir_cache);
25683+ AuDbg("offset %lld\n", offset);
25684+ if (file->f_pos == offset)
25685+ goto out;
25686+
25687+ vdir_cache->vd_last.ul = 0;
25688+ vdir_cache->vd_last.p.deblk = vdir_cache->vd_deblk[0];
25689+ if (!file->f_pos)
25690+ goto out;
25691+
25692+ valid = 0;
25693+ deblk_sz = vdir_cache->vd_deblk_sz;
25694+ ul = div64_u64(file->f_pos, deblk_sz);
25695+ AuDbg("ul %lu\n", ul);
25696+ if (ul >= vdir_cache->vd_nblk)
25697+ goto out;
25698+
25699+ n = vdir_cache->vd_nblk;
25700+ for (; ul < n; ul++) {
25701+ p.deblk = vdir_cache->vd_deblk[ul];
25702+ deblk_end.deblk = p.deblk + deblk_sz;
25703+ offset = ul;
25704+ offset *= deblk_sz;
25705+ while (!is_deblk_end(&p, &deblk_end) && offset < file->f_pos) {
25706+ unsigned int l;
25707+
25708+ l = calc_size(p.de->de_str.len);
25709+ offset += l;
25710+ p.deblk += l;
25711+ }
25712+ if (!is_deblk_end(&p, &deblk_end)) {
25713+ valid = 1;
25714+ vdir_cache->vd_last.ul = ul;
25715+ vdir_cache->vd_last.p = p;
25716+ break;
25717+ }
25718+ }
25719+
4f0767ce 25720+out:
1facf9fc 25721+ /* smp_mb(); */
25722+ AuTraceErr(!valid);
25723+ return valid;
25724+}
25725+
25726+int au_vdir_fill_de(struct file *file, void *dirent, filldir_t filldir)
25727+{
25728+ int err;
25729+ unsigned int l, deblk_sz;
25730+ union au_vdir_deblk_p deblk_end;
25731+ struct au_vdir *vdir_cache;
25732+ struct au_vdir_de *de;
25733+
25734+ vdir_cache = au_fvdir_cache(file);
25735+ if (!seek_vdir(file))
25736+ return 0;
25737+
25738+ deblk_sz = vdir_cache->vd_deblk_sz;
25739+ while (1) {
25740+ deblk_end.deblk = vdir_cache->vd_deblk[vdir_cache->vd_last.ul];
25741+ deblk_end.deblk += deblk_sz;
25742+ while (!is_deblk_end(&vdir_cache->vd_last.p, &deblk_end)) {
25743+ de = vdir_cache->vd_last.p.de;
25744+ AuDbg("%.*s, off%lld, i%lu, dt%d\n",
25745+ de->de_str.len, de->de_str.name, file->f_pos,
25746+ (unsigned long)de->de_ino, de->de_type);
25747+ err = filldir(dirent, de->de_str.name, de->de_str.len,
25748+ file->f_pos, de->de_ino, de->de_type);
25749+ if (unlikely(err)) {
25750+ AuTraceErr(err);
25751+ /* todo: ignore the error caused by udba? */
25752+ /* return err; */
25753+ return 0;
25754+ }
25755+
25756+ l = calc_size(de->de_str.len);
25757+ vdir_cache->vd_last.p.deblk += l;
25758+ file->f_pos += l;
25759+ }
25760+ if (vdir_cache->vd_last.ul < vdir_cache->vd_nblk - 1) {
25761+ vdir_cache->vd_last.ul++;
25762+ vdir_cache->vd_last.p.deblk
25763+ = vdir_cache->vd_deblk[vdir_cache->vd_last.ul];
25764+ file->f_pos = deblk_sz * vdir_cache->vd_last.ul;
25765+ continue;
25766+ }
25767+ break;
25768+ }
25769+
25770+ /* smp_mb(); */
25771+ return 0;
25772+}
7f207e10
AM
25773diff -urN /usr/share/empty/fs/aufs/vfsub.c linux/fs/aufs/vfsub.c
25774--- /usr/share/empty/fs/aufs/vfsub.c 1970-01-01 01:00:00.000000000 +0100
b4510431
AM
25775+++ linux/fs/aufs/vfsub.c 2012-10-17 10:31:01.775814563 +0200
25776@@ -0,0 +1,777 @@
1facf9fc 25777+/*
f6c5ef8b 25778+ * Copyright (C) 2005-2012 Junjiro R. Okajima
1facf9fc 25779+ *
25780+ * This program, aufs is free software; you can redistribute it and/or modify
25781+ * it under the terms of the GNU General Public License as published by
25782+ * the Free Software Foundation; either version 2 of the License, or
25783+ * (at your option) any later version.
dece6358
AM
25784+ *
25785+ * This program is distributed in the hope that it will be useful,
25786+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
25787+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
25788+ * GNU General Public License for more details.
25789+ *
25790+ * You should have received a copy of the GNU General Public License
25791+ * along with this program; if not, write to the Free Software
25792+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 25793+ */
25794+
25795+/*
25796+ * sub-routines for VFS
25797+ */
25798+
1308ab2a 25799+#include <linux/ima.h>
dece6358
AM
25800+#include <linux/namei.h>
25801+#include <linux/security.h>
25802+#include <linux/splice.h>
1facf9fc 25803+#include "aufs.h"
25804+
25805+int vfsub_update_h_iattr(struct path *h_path, int *did)
25806+{
25807+ int err;
25808+ struct kstat st;
25809+ struct super_block *h_sb;
25810+
25811+ /* for remote fs, leave work for its getattr or d_revalidate */
25812+ /* for bad i_attr fs, handle them in aufs_getattr() */
25813+ /* still some fs may acquire i_mutex. we need to skip them */
25814+ err = 0;
25815+ if (!did)
25816+ did = &err;
25817+ h_sb = h_path->dentry->d_sb;
25818+ *did = (!au_test_fs_remote(h_sb) && au_test_fs_refresh_iattr(h_sb));
25819+ if (*did)
25820+ err = vfs_getattr(h_path->mnt, h_path->dentry, &st);
25821+
25822+ return err;
25823+}
25824+
25825+/* ---------------------------------------------------------------------- */
25826+
4a4d8108 25827+struct file *vfsub_dentry_open(struct path *path, int flags)
1308ab2a 25828+{
25829+ struct file *file;
25830+
b4510431 25831+ file = dentry_open(path, flags /* | __FMODE_NONOTIFY */,
7f207e10 25832+ current_cred());
2cbb1c4b
JR
25833+ if (!IS_ERR_OR_NULL(file)
25834+ && (file->f_mode & (FMODE_READ | FMODE_WRITE)) == FMODE_READ)
25835+ i_readcount_inc(path->dentry->d_inode);
4a4d8108 25836+
1308ab2a 25837+ return file;
25838+}
25839+
1facf9fc 25840+struct file *vfsub_filp_open(const char *path, int oflags, int mode)
25841+{
25842+ struct file *file;
25843+
2cbb1c4b 25844+ lockdep_off();
7f207e10 25845+ file = filp_open(path,
2cbb1c4b 25846+ oflags /* | __FMODE_NONOTIFY */,
7f207e10 25847+ mode);
2cbb1c4b 25848+ lockdep_on();
1facf9fc 25849+ if (IS_ERR(file))
25850+ goto out;
25851+ vfsub_update_h_iattr(&file->f_path, /*did*/NULL); /*ignore*/
25852+
4f0767ce 25853+out:
1facf9fc 25854+ return file;
25855+}
25856+
25857+int vfsub_kern_path(const char *name, unsigned int flags, struct path *path)
25858+{
25859+ int err;
25860+
1facf9fc 25861+ err = kern_path(name, flags, path);
1facf9fc 25862+ if (!err && path->dentry->d_inode)
25863+ vfsub_update_h_iattr(path, /*did*/NULL); /*ignore*/
25864+ return err;
25865+}
25866+
25867+struct dentry *vfsub_lookup_one_len(const char *name, struct dentry *parent,
25868+ int len)
25869+{
25870+ struct path path = {
25871+ .mnt = NULL
25872+ };
25873+
1308ab2a 25874+ /* VFS checks it too, but by WARN_ON_ONCE() */
1facf9fc 25875+ IMustLock(parent->d_inode);
25876+
25877+ path.dentry = lookup_one_len(name, parent, len);
25878+ if (IS_ERR(path.dentry))
25879+ goto out;
25880+ if (path.dentry->d_inode)
25881+ vfsub_update_h_iattr(&path, /*did*/NULL); /*ignore*/
25882+
4f0767ce 25883+out:
4a4d8108 25884+ AuTraceErrPtr(path.dentry);
1facf9fc 25885+ return path.dentry;
25886+}
25887+
b4510431 25888+void vfsub_call_lkup_one(void *args)
2cbb1c4b 25889+{
b4510431
AM
25890+ struct vfsub_lkup_one_args *a = args;
25891+ *a->errp = vfsub_lkup_one(a->name, a->parent);
2cbb1c4b
JR
25892+}
25893+
1facf9fc 25894+/* ---------------------------------------------------------------------- */
25895+
25896+struct dentry *vfsub_lock_rename(struct dentry *d1, struct au_hinode *hdir1,
25897+ struct dentry *d2, struct au_hinode *hdir2)
25898+{
25899+ struct dentry *d;
25900+
2cbb1c4b 25901+ lockdep_off();
1facf9fc 25902+ d = lock_rename(d1, d2);
2cbb1c4b 25903+ lockdep_on();
4a4d8108 25904+ au_hn_suspend(hdir1);
1facf9fc 25905+ if (hdir1 != hdir2)
4a4d8108 25906+ au_hn_suspend(hdir2);
1facf9fc 25907+
25908+ return d;
25909+}
25910+
25911+void vfsub_unlock_rename(struct dentry *d1, struct au_hinode *hdir1,
25912+ struct dentry *d2, struct au_hinode *hdir2)
25913+{
4a4d8108 25914+ au_hn_resume(hdir1);
1facf9fc 25915+ if (hdir1 != hdir2)
4a4d8108 25916+ au_hn_resume(hdir2);
2cbb1c4b 25917+ lockdep_off();
1facf9fc 25918+ unlock_rename(d1, d2);
2cbb1c4b 25919+ lockdep_on();
1facf9fc 25920+}
25921+
25922+/* ---------------------------------------------------------------------- */
25923+
b4510431 25924+int vfsub_create(struct inode *dir, struct path *path, int mode, bool want_excl)
1facf9fc 25925+{
25926+ int err;
25927+ struct dentry *d;
25928+
25929+ IMustLock(dir);
25930+
25931+ d = path->dentry;
25932+ path->dentry = d->d_parent;
b752ccd1 25933+ err = security_path_mknod(path, d, mode, 0);
1facf9fc 25934+ path->dentry = d;
25935+ if (unlikely(err))
25936+ goto out;
25937+
b4510431 25938+ err = vfs_create(dir, path->dentry, mode, want_excl);
1facf9fc 25939+ if (!err) {
25940+ struct path tmp = *path;
25941+ int did;
25942+
25943+ vfsub_update_h_iattr(&tmp, &did);
25944+ if (did) {
25945+ tmp.dentry = path->dentry->d_parent;
25946+ vfsub_update_h_iattr(&tmp, /*did*/NULL);
25947+ }
25948+ /*ignore*/
25949+ }
25950+
4f0767ce 25951+out:
1facf9fc 25952+ return err;
25953+}
25954+
25955+int vfsub_symlink(struct inode *dir, struct path *path, const char *symname)
25956+{
25957+ int err;
25958+ struct dentry *d;
25959+
25960+ IMustLock(dir);
25961+
25962+ d = path->dentry;
25963+ path->dentry = d->d_parent;
b752ccd1 25964+ err = security_path_symlink(path, d, symname);
1facf9fc 25965+ path->dentry = d;
25966+ if (unlikely(err))
25967+ goto out;
25968+
25969+ err = vfs_symlink(dir, path->dentry, symname);
25970+ if (!err) {
25971+ struct path tmp = *path;
25972+ int did;
25973+
25974+ vfsub_update_h_iattr(&tmp, &did);
25975+ if (did) {
25976+ tmp.dentry = path->dentry->d_parent;
25977+ vfsub_update_h_iattr(&tmp, /*did*/NULL);
25978+ }
25979+ /*ignore*/
25980+ }
25981+
4f0767ce 25982+out:
1facf9fc 25983+ return err;
25984+}
25985+
25986+int vfsub_mknod(struct inode *dir, struct path *path, int mode, dev_t dev)
25987+{
25988+ int err;
25989+ struct dentry *d;
25990+
25991+ IMustLock(dir);
25992+
25993+ d = path->dentry;
25994+ path->dentry = d->d_parent;
027c5e7a 25995+ err = security_path_mknod(path, d, mode, new_encode_dev(dev));
1facf9fc 25996+ path->dentry = d;
25997+ if (unlikely(err))
25998+ goto out;
25999+
26000+ err = vfs_mknod(dir, path->dentry, mode, dev);
26001+ if (!err) {
26002+ struct path tmp = *path;
26003+ int did;
26004+
26005+ vfsub_update_h_iattr(&tmp, &did);
26006+ if (did) {
26007+ tmp.dentry = path->dentry->d_parent;
26008+ vfsub_update_h_iattr(&tmp, /*did*/NULL);
26009+ }
26010+ /*ignore*/
26011+ }
26012+
4f0767ce 26013+out:
1facf9fc 26014+ return err;
26015+}
26016+
26017+static int au_test_nlink(struct inode *inode)
26018+{
26019+ const unsigned int link_max = UINT_MAX >> 1; /* rough margin */
26020+
26021+ if (!au_test_fs_no_limit_nlink(inode->i_sb)
26022+ || inode->i_nlink < link_max)
26023+ return 0;
26024+ return -EMLINK;
26025+}
26026+
26027+int vfsub_link(struct dentry *src_dentry, struct inode *dir, struct path *path)
26028+{
26029+ int err;
26030+ struct dentry *d;
26031+
26032+ IMustLock(dir);
26033+
26034+ err = au_test_nlink(src_dentry->d_inode);
26035+ if (unlikely(err))
26036+ return err;
26037+
b4510431 26038+ /* we don't call may_linkat() */
1facf9fc 26039+ d = path->dentry;
26040+ path->dentry = d->d_parent;
b752ccd1 26041+ err = security_path_link(src_dentry, path, d);
1facf9fc 26042+ path->dentry = d;
26043+ if (unlikely(err))
26044+ goto out;
26045+
2cbb1c4b 26046+ lockdep_off();
1facf9fc 26047+ err = vfs_link(src_dentry, dir, path->dentry);
2cbb1c4b 26048+ lockdep_on();
1facf9fc 26049+ if (!err) {
26050+ struct path tmp = *path;
26051+ int did;
26052+
26053+ /* fuse has different memory inode for the same inumber */
26054+ vfsub_update_h_iattr(&tmp, &did);
26055+ if (did) {
26056+ tmp.dentry = path->dentry->d_parent;
26057+ vfsub_update_h_iattr(&tmp, /*did*/NULL);
26058+ tmp.dentry = src_dentry;
26059+ vfsub_update_h_iattr(&tmp, /*did*/NULL);
26060+ }
26061+ /*ignore*/
26062+ }
26063+
4f0767ce 26064+out:
1facf9fc 26065+ return err;
26066+}
26067+
26068+int vfsub_rename(struct inode *src_dir, struct dentry *src_dentry,
26069+ struct inode *dir, struct path *path)
26070+{
26071+ int err;
26072+ struct path tmp = {
26073+ .mnt = path->mnt
26074+ };
26075+ struct dentry *d;
26076+
26077+ IMustLock(dir);
26078+ IMustLock(src_dir);
26079+
26080+ d = path->dentry;
26081+ path->dentry = d->d_parent;
26082+ tmp.dentry = src_dentry->d_parent;
b752ccd1 26083+ err = security_path_rename(&tmp, src_dentry, path, d);
1facf9fc 26084+ path->dentry = d;
26085+ if (unlikely(err))
26086+ goto out;
26087+
2cbb1c4b 26088+ lockdep_off();
1facf9fc 26089+ err = vfs_rename(src_dir, src_dentry, dir, path->dentry);
2cbb1c4b 26090+ lockdep_on();
1facf9fc 26091+ if (!err) {
26092+ int did;
26093+
26094+ tmp.dentry = d->d_parent;
26095+ vfsub_update_h_iattr(&tmp, &did);
26096+ if (did) {
26097+ tmp.dentry = src_dentry;
26098+ vfsub_update_h_iattr(&tmp, /*did*/NULL);
26099+ tmp.dentry = src_dentry->d_parent;
26100+ vfsub_update_h_iattr(&tmp, /*did*/NULL);
26101+ }
26102+ /*ignore*/
26103+ }
26104+
4f0767ce 26105+out:
1facf9fc 26106+ return err;
26107+}
26108+
26109+int vfsub_mkdir(struct inode *dir, struct path *path, int mode)
26110+{
26111+ int err;
26112+ struct dentry *d;
26113+
26114+ IMustLock(dir);
26115+
26116+ d = path->dentry;
26117+ path->dentry = d->d_parent;
b752ccd1 26118+ err = security_path_mkdir(path, d, mode);
1facf9fc 26119+ path->dentry = d;
26120+ if (unlikely(err))
26121+ goto out;
26122+
26123+ err = vfs_mkdir(dir, path->dentry, mode);
26124+ if (!err) {
26125+ struct path tmp = *path;
26126+ int did;
26127+
26128+ vfsub_update_h_iattr(&tmp, &did);
26129+ if (did) {
26130+ tmp.dentry = path->dentry->d_parent;
26131+ vfsub_update_h_iattr(&tmp, /*did*/NULL);
26132+ }
26133+ /*ignore*/
26134+ }
26135+
4f0767ce 26136+out:
1facf9fc 26137+ return err;
26138+}
26139+
26140+int vfsub_rmdir(struct inode *dir, struct path *path)
26141+{
26142+ int err;
26143+ struct dentry *d;
26144+
26145+ IMustLock(dir);
26146+
26147+ d = path->dentry;
26148+ path->dentry = d->d_parent;
b752ccd1 26149+ err = security_path_rmdir(path, d);
1facf9fc 26150+ path->dentry = d;
26151+ if (unlikely(err))
26152+ goto out;
26153+
2cbb1c4b 26154+ lockdep_off();
1facf9fc 26155+ err = vfs_rmdir(dir, path->dentry);
2cbb1c4b 26156+ lockdep_on();
1facf9fc 26157+ if (!err) {
26158+ struct path tmp = {
26159+ .dentry = path->dentry->d_parent,
26160+ .mnt = path->mnt
26161+ };
26162+
26163+ vfsub_update_h_iattr(&tmp, /*did*/NULL); /*ignore*/
26164+ }
26165+
4f0767ce 26166+out:
1facf9fc 26167+ return err;
26168+}
26169+
26170+/* ---------------------------------------------------------------------- */
26171+
9dbd164d 26172+/* todo: support mmap_sem? */
1facf9fc 26173+ssize_t vfsub_read_u(struct file *file, char __user *ubuf, size_t count,
26174+ loff_t *ppos)
26175+{
26176+ ssize_t err;
26177+
2cbb1c4b 26178+ lockdep_off();
1facf9fc 26179+ err = vfs_read(file, ubuf, count, ppos);
2cbb1c4b 26180+ lockdep_on();
1facf9fc 26181+ if (err >= 0)
26182+ vfsub_update_h_iattr(&file->f_path, /*did*/NULL); /*ignore*/
26183+ return err;
26184+}
26185+
26186+/* todo: kernel_read()? */
26187+ssize_t vfsub_read_k(struct file *file, void *kbuf, size_t count,
26188+ loff_t *ppos)
26189+{
26190+ ssize_t err;
26191+ mm_segment_t oldfs;
b752ccd1
AM
26192+ union {
26193+ void *k;
26194+ char __user *u;
26195+ } buf;
1facf9fc 26196+
b752ccd1 26197+ buf.k = kbuf;
1facf9fc 26198+ oldfs = get_fs();
26199+ set_fs(KERNEL_DS);
b752ccd1 26200+ err = vfsub_read_u(file, buf.u, count, ppos);
1facf9fc 26201+ set_fs(oldfs);
26202+ return err;
26203+}
26204+
26205+ssize_t vfsub_write_u(struct file *file, const char __user *ubuf, size_t count,
26206+ loff_t *ppos)
26207+{
26208+ ssize_t err;
26209+
2cbb1c4b 26210+ lockdep_off();
1facf9fc 26211+ err = vfs_write(file, ubuf, count, ppos);
2cbb1c4b 26212+ lockdep_on();
1facf9fc 26213+ if (err >= 0)
26214+ vfsub_update_h_iattr(&file->f_path, /*did*/NULL); /*ignore*/
26215+ return err;
26216+}
26217+
26218+ssize_t vfsub_write_k(struct file *file, void *kbuf, size_t count, loff_t *ppos)
26219+{
26220+ ssize_t err;
26221+ mm_segment_t oldfs;
b752ccd1
AM
26222+ union {
26223+ void *k;
26224+ const char __user *u;
26225+ } buf;
1facf9fc 26226+
b752ccd1 26227+ buf.k = kbuf;
1facf9fc 26228+ oldfs = get_fs();
26229+ set_fs(KERNEL_DS);
b752ccd1 26230+ err = vfsub_write_u(file, buf.u, count, ppos);
1facf9fc 26231+ set_fs(oldfs);
26232+ return err;
26233+}
26234+
4a4d8108
AM
26235+int vfsub_flush(struct file *file, fl_owner_t id)
26236+{
26237+ int err;
26238+
26239+ err = 0;
26240+ if (file->f_op && file->f_op->flush) {
2cbb1c4b
JR
26241+ if (!au_test_nfs(file->f_dentry->d_sb))
26242+ err = file->f_op->flush(file, id);
26243+ else {
26244+ lockdep_off();
26245+ err = file->f_op->flush(file, id);
26246+ lockdep_on();
26247+ }
4a4d8108
AM
26248+ if (!err)
26249+ vfsub_update_h_iattr(&file->f_path, /*did*/NULL);
26250+ /*ignore*/
26251+ }
26252+ return err;
26253+}
26254+
1facf9fc 26255+int vfsub_readdir(struct file *file, filldir_t filldir, void *arg)
26256+{
26257+ int err;
26258+
2cbb1c4b 26259+ lockdep_off();
1facf9fc 26260+ err = vfs_readdir(file, filldir, arg);
2cbb1c4b 26261+ lockdep_on();
1facf9fc 26262+ if (err >= 0)
26263+ vfsub_update_h_iattr(&file->f_path, /*did*/NULL); /*ignore*/
26264+ return err;
26265+}
26266+
26267+long vfsub_splice_to(struct file *in, loff_t *ppos,
26268+ struct pipe_inode_info *pipe, size_t len,
26269+ unsigned int flags)
26270+{
26271+ long err;
26272+
2cbb1c4b 26273+ lockdep_off();
0fc653ad 26274+ err = do_splice_to(in, ppos, pipe, len, flags);
2cbb1c4b 26275+ lockdep_on();
4a4d8108 26276+ file_accessed(in);
1facf9fc 26277+ if (err >= 0)
26278+ vfsub_update_h_iattr(&in->f_path, /*did*/NULL); /*ignore*/
26279+ return err;
26280+}
26281+
26282+long vfsub_splice_from(struct pipe_inode_info *pipe, struct file *out,
26283+ loff_t *ppos, size_t len, unsigned int flags)
26284+{
26285+ long err;
26286+
2cbb1c4b 26287+ lockdep_off();
0fc653ad 26288+ err = do_splice_from(pipe, out, ppos, len, flags);
2cbb1c4b 26289+ lockdep_on();
1facf9fc 26290+ if (err >= 0)
26291+ vfsub_update_h_iattr(&out->f_path, /*did*/NULL); /*ignore*/
26292+ return err;
26293+}
26294+
53392da6
AM
26295+int vfsub_fsync(struct file *file, struct path *path, int datasync)
26296+{
26297+ int err;
26298+
26299+ /* file can be NULL */
26300+ lockdep_off();
26301+ err = vfs_fsync(file, datasync);
26302+ lockdep_on();
26303+ if (!err) {
26304+ if (!path) {
26305+ AuDebugOn(!file);
26306+ path = &file->f_path;
26307+ }
26308+ vfsub_update_h_iattr(path, /*did*/NULL); /*ignore*/
26309+ }
26310+ return err;
26311+}
26312+
1facf9fc 26313+/* cf. open.c:do_sys_truncate() and do_sys_ftruncate() */
26314+int vfsub_trunc(struct path *h_path, loff_t length, unsigned int attr,
26315+ struct file *h_file)
26316+{
26317+ int err;
26318+ struct inode *h_inode;
26319+
26320+ h_inode = h_path->dentry->d_inode;
26321+ if (!h_file) {
b4510431 26322+ err = vfsub_mnt_want_write(h_path->mnt);
1facf9fc 26323+ if (err)
26324+ goto out;
26325+ err = inode_permission(h_inode, MAY_WRITE);
26326+ if (err)
26327+ goto out_mnt;
26328+ err = get_write_access(h_inode);
26329+ if (err)
26330+ goto out_mnt;
4a4d8108 26331+ err = break_lease(h_inode, O_WRONLY);
1facf9fc 26332+ if (err)
26333+ goto out_inode;
26334+ }
26335+
26336+ err = locks_verify_truncate(h_inode, h_file, length);
26337+ if (!err)
953406b4 26338+ err = security_path_truncate(h_path);
2cbb1c4b
JR
26339+ if (!err) {
26340+ lockdep_off();
1facf9fc 26341+ err = do_truncate(h_path->dentry, length, attr, h_file);
2cbb1c4b
JR
26342+ lockdep_on();
26343+ }
1facf9fc 26344+
4f0767ce 26345+out_inode:
1facf9fc 26346+ if (!h_file)
26347+ put_write_access(h_inode);
4f0767ce 26348+out_mnt:
1facf9fc 26349+ if (!h_file)
b4510431 26350+ vfsub_mnt_drop_write(h_path->mnt);
4f0767ce 26351+out:
1facf9fc 26352+ return err;
26353+}
26354+
26355+/* ---------------------------------------------------------------------- */
26356+
26357+struct au_vfsub_mkdir_args {
26358+ int *errp;
26359+ struct inode *dir;
26360+ struct path *path;
26361+ int mode;
26362+};
26363+
26364+static void au_call_vfsub_mkdir(void *args)
26365+{
26366+ struct au_vfsub_mkdir_args *a = args;
26367+ *a->errp = vfsub_mkdir(a->dir, a->path, a->mode);
26368+}
26369+
26370+int vfsub_sio_mkdir(struct inode *dir, struct path *path, int mode)
26371+{
26372+ int err, do_sio, wkq_err;
26373+
26374+ do_sio = au_test_h_perm_sio(dir, MAY_EXEC | MAY_WRITE);
26375+ if (!do_sio)
26376+ err = vfsub_mkdir(dir, path, mode);
26377+ else {
26378+ struct au_vfsub_mkdir_args args = {
26379+ .errp = &err,
26380+ .dir = dir,
26381+ .path = path,
26382+ .mode = mode
26383+ };
26384+ wkq_err = au_wkq_wait(au_call_vfsub_mkdir, &args);
26385+ if (unlikely(wkq_err))
26386+ err = wkq_err;
26387+ }
26388+
26389+ return err;
26390+}
26391+
26392+struct au_vfsub_rmdir_args {
26393+ int *errp;
26394+ struct inode *dir;
26395+ struct path *path;
26396+};
26397+
26398+static void au_call_vfsub_rmdir(void *args)
26399+{
26400+ struct au_vfsub_rmdir_args *a = args;
26401+ *a->errp = vfsub_rmdir(a->dir, a->path);
26402+}
26403+
26404+int vfsub_sio_rmdir(struct inode *dir, struct path *path)
26405+{
26406+ int err, do_sio, wkq_err;
26407+
26408+ do_sio = au_test_h_perm_sio(dir, MAY_EXEC | MAY_WRITE);
26409+ if (!do_sio)
26410+ err = vfsub_rmdir(dir, path);
26411+ else {
26412+ struct au_vfsub_rmdir_args args = {
26413+ .errp = &err,
26414+ .dir = dir,
26415+ .path = path
26416+ };
26417+ wkq_err = au_wkq_wait(au_call_vfsub_rmdir, &args);
26418+ if (unlikely(wkq_err))
26419+ err = wkq_err;
26420+ }
26421+
26422+ return err;
26423+}
26424+
26425+/* ---------------------------------------------------------------------- */
26426+
26427+struct notify_change_args {
26428+ int *errp;
26429+ struct path *path;
26430+ struct iattr *ia;
26431+};
26432+
26433+static void call_notify_change(void *args)
26434+{
26435+ struct notify_change_args *a = args;
26436+ struct inode *h_inode;
26437+
26438+ h_inode = a->path->dentry->d_inode;
26439+ IMustLock(h_inode);
26440+
26441+ *a->errp = -EPERM;
26442+ if (!IS_IMMUTABLE(h_inode) && !IS_APPEND(h_inode)) {
1facf9fc 26443+ *a->errp = notify_change(a->path->dentry, a->ia);
1facf9fc 26444+ if (!*a->errp)
26445+ vfsub_update_h_iattr(a->path, /*did*/NULL); /*ignore*/
26446+ }
26447+ AuTraceErr(*a->errp);
26448+}
26449+
26450+int vfsub_notify_change(struct path *path, struct iattr *ia)
26451+{
26452+ int err;
26453+ struct notify_change_args args = {
26454+ .errp = &err,
26455+ .path = path,
26456+ .ia = ia
26457+ };
26458+
26459+ call_notify_change(&args);
26460+
26461+ return err;
26462+}
26463+
26464+int vfsub_sio_notify_change(struct path *path, struct iattr *ia)
26465+{
26466+ int err, wkq_err;
26467+ struct notify_change_args args = {
26468+ .errp = &err,
26469+ .path = path,
26470+ .ia = ia
26471+ };
26472+
26473+ wkq_err = au_wkq_wait(call_notify_change, &args);
26474+ if (unlikely(wkq_err))
26475+ err = wkq_err;
26476+
26477+ return err;
26478+}
26479+
26480+/* ---------------------------------------------------------------------- */
26481+
26482+struct unlink_args {
26483+ int *errp;
26484+ struct inode *dir;
26485+ struct path *path;
26486+};
26487+
26488+static void call_unlink(void *args)
26489+{
26490+ struct unlink_args *a = args;
26491+ struct dentry *d = a->path->dentry;
26492+ struct inode *h_inode;
26493+ const int stop_sillyrename = (au_test_nfs(d->d_sb)
027c5e7a 26494+ && d->d_count == 1);
1facf9fc 26495+
26496+ IMustLock(a->dir);
26497+
26498+ a->path->dentry = d->d_parent;
26499+ *a->errp = security_path_unlink(a->path, d);
26500+ a->path->dentry = d;
26501+ if (unlikely(*a->errp))
26502+ return;
26503+
26504+ if (!stop_sillyrename)
26505+ dget(d);
26506+ h_inode = d->d_inode;
26507+ if (h_inode)
027c5e7a 26508+ ihold(h_inode);
1facf9fc 26509+
2cbb1c4b 26510+ lockdep_off();
1facf9fc 26511+ *a->errp = vfs_unlink(a->dir, d);
2cbb1c4b 26512+ lockdep_on();
1facf9fc 26513+ if (!*a->errp) {
26514+ struct path tmp = {
26515+ .dentry = d->d_parent,
26516+ .mnt = a->path->mnt
26517+ };
26518+ vfsub_update_h_iattr(&tmp, /*did*/NULL); /*ignore*/
26519+ }
26520+
26521+ if (!stop_sillyrename)
26522+ dput(d);
26523+ if (h_inode)
26524+ iput(h_inode);
26525+
26526+ AuTraceErr(*a->errp);
26527+}
26528+
26529+/*
26530+ * @dir: must be locked.
26531+ * @dentry: target dentry.
26532+ */
26533+int vfsub_unlink(struct inode *dir, struct path *path, int force)
26534+{
26535+ int err;
26536+ struct unlink_args args = {
26537+ .errp = &err,
26538+ .dir = dir,
26539+ .path = path
26540+ };
26541+
26542+ if (!force)
26543+ call_unlink(&args);
26544+ else {
26545+ int wkq_err;
26546+
26547+ wkq_err = au_wkq_wait(call_unlink, &args);
26548+ if (unlikely(wkq_err))
26549+ err = wkq_err;
26550+ }
26551+
26552+ return err;
26553+}
7f207e10
AM
26554diff -urN /usr/share/empty/fs/aufs/vfsub.h linux/fs/aufs/vfsub.h
26555--- /usr/share/empty/fs/aufs/vfsub.h 1970-01-01 01:00:00.000000000 +0100
b4510431
AM
26556+++ linux/fs/aufs/vfsub.h 2012-10-17 10:31:01.775814563 +0200
26557@@ -0,0 +1,283 @@
1facf9fc 26558+/*
f6c5ef8b 26559+ * Copyright (C) 2005-2012 Junjiro R. Okajima
1facf9fc 26560+ *
26561+ * This program, aufs is free software; you can redistribute it and/or modify
26562+ * it under the terms of the GNU General Public License as published by
26563+ * the Free Software Foundation; either version 2 of the License, or
26564+ * (at your option) any later version.
dece6358
AM
26565+ *
26566+ * This program is distributed in the hope that it will be useful,
26567+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
26568+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
26569+ * GNU General Public License for more details.
26570+ *
26571+ * You should have received a copy of the GNU General Public License
26572+ * along with this program; if not, write to the Free Software
26573+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 26574+ */
26575+
26576+/*
26577+ * sub-routines for VFS
26578+ */
26579+
26580+#ifndef __AUFS_VFSUB_H__
26581+#define __AUFS_VFSUB_H__
26582+
26583+#ifdef __KERNEL__
26584+
26585+#include <linux/fs.h>
0c5527e5 26586+#include <linux/lglock.h>
b4510431 26587+#include <linux/mount.h>
7f207e10 26588+#include "debug.h"
1facf9fc 26589+
7f207e10 26590+/* copied from linux/fs/internal.h */
2cbb1c4b 26591+/* todo: BAD approach!! */
0c3ec466 26592+extern struct lglock vfsmount_lock;
2cbb1c4b 26593+extern spinlock_t inode_sb_list_lock;
0c5527e5 26594+
7f207e10 26595+/* copied from linux/fs/file_table.c */
0c3ec466 26596+extern struct lglock files_lglock;
0c5527e5
AM
26597+#ifdef CONFIG_SMP
26598+/*
26599+ * These macros iterate all files on all CPUs for a given superblock.
26600+ * files_lglock must be held globally.
26601+ */
26602+#define do_file_list_for_each_entry(__sb, __file) \
26603+{ \
26604+ int i; \
26605+ for_each_possible_cpu(i) { \
26606+ struct list_head *list; \
26607+ list = per_cpu_ptr((__sb)->s_files, i); \
26608+ list_for_each_entry((__file), list, f_u.fu_list)
26609+
26610+#define while_file_list_for_each_entry \
26611+ } \
26612+}
26613+
26614+#else
26615+
26616+#define do_file_list_for_each_entry(__sb, __file) \
26617+{ \
26618+ struct list_head *list; \
26619+ list = &(sb)->s_files; \
26620+ list_for_each_entry((__file), list, f_u.fu_list)
26621+
26622+#define while_file_list_for_each_entry \
26623+}
7f207e10
AM
26624+#endif
26625+
26626+/* ---------------------------------------------------------------------- */
1facf9fc 26627+
26628+/* lock subclass for lower inode */
26629+/* default MAX_LOCKDEP_SUBCLASSES(8) is not enough */
26630+/* reduce? gave up. */
26631+enum {
26632+ AuLsc_I_Begin = I_MUTEX_QUOTA, /* 4 */
26633+ AuLsc_I_PARENT, /* lower inode, parent first */
26634+ AuLsc_I_PARENT2, /* copyup dirs */
dece6358 26635+ AuLsc_I_PARENT3, /* copyup wh */
1facf9fc 26636+ AuLsc_I_CHILD,
26637+ AuLsc_I_CHILD2,
26638+ AuLsc_I_End
26639+};
26640+
26641+/* to debug easier, do not make them inlined functions */
26642+#define MtxMustLock(mtx) AuDebugOn(!mutex_is_locked(mtx))
26643+#define IMustLock(i) MtxMustLock(&(i)->i_mutex)
26644+
26645+/* ---------------------------------------------------------------------- */
26646+
7f207e10
AM
26647+static inline void vfsub_drop_nlink(struct inode *inode)
26648+{
26649+ AuDebugOn(!inode->i_nlink);
26650+ drop_nlink(inode);
26651+}
26652+
027c5e7a
AM
26653+static inline void vfsub_dead_dir(struct inode *inode)
26654+{
26655+ AuDebugOn(!S_ISDIR(inode->i_mode));
26656+ inode->i_flags |= S_DEAD;
26657+ clear_nlink(inode);
26658+}
26659+
7f207e10
AM
26660+/* ---------------------------------------------------------------------- */
26661+
0c3ec466
AM
26662+/* cf. i_[ug]id_read() in linux/include/fs.h */
26663+static inline uid_t vfsub_ia_uid(struct iattr *ia)
26664+{
26665+ return from_kuid(&init_user_ns, ia->ia_uid);
26666+}
26667+
26668+static inline gid_t vfsub_ia_gid(struct iattr *ia)
26669+{
26670+ return from_kgid(&init_user_ns, ia->ia_gid);
26671+}
26672+
26673+/* ---------------------------------------------------------------------- */
26674+
7f207e10
AM
26675+int vfsub_update_h_iattr(struct path *h_path, int *did);
26676+struct file *vfsub_dentry_open(struct path *path, int flags);
26677+struct file *vfsub_filp_open(const char *path, int oflags, int mode);
1facf9fc 26678+int vfsub_kern_path(const char *name, unsigned int flags, struct path *path);
b4510431 26679+
1facf9fc 26680+struct dentry *vfsub_lookup_one_len(const char *name, struct dentry *parent,
26681+ int len);
b4510431
AM
26682+
26683+struct vfsub_lkup_one_args {
26684+ struct dentry **errp;
26685+ struct qstr *name;
26686+ struct dentry *parent;
26687+};
26688+
26689+static inline struct dentry *vfsub_lkup_one(struct qstr *name,
26690+ struct dentry *parent)
26691+{
26692+ return vfsub_lookup_one_len(name->name, parent, name->len);
26693+}
26694+
26695+void vfsub_call_lkup_one(void *args);
26696+
26697+/* ---------------------------------------------------------------------- */
26698+
26699+static inline int vfsub_mnt_want_write(struct vfsmount *mnt)
26700+{
26701+ int err;
26702+ lockdep_off();
26703+ err = mnt_want_write(mnt);
26704+ lockdep_on();
26705+ return err;
26706+}
26707+
26708+static inline void vfsub_mnt_drop_write(struct vfsmount *mnt)
26709+{
26710+ lockdep_off();
26711+ mnt_drop_write(mnt);
26712+ lockdep_on();
26713+}
1facf9fc 26714+
26715+/* ---------------------------------------------------------------------- */
26716+
26717+struct au_hinode;
26718+struct dentry *vfsub_lock_rename(struct dentry *d1, struct au_hinode *hdir1,
26719+ struct dentry *d2, struct au_hinode *hdir2);
26720+void vfsub_unlock_rename(struct dentry *d1, struct au_hinode *hdir1,
26721+ struct dentry *d2, struct au_hinode *hdir2);
26722+
b4510431 26723+int vfsub_create(struct inode *dir, struct path *path, int mode, bool want_excl);
1facf9fc 26724+int vfsub_symlink(struct inode *dir, struct path *path,
26725+ const char *symname);
26726+int vfsub_mknod(struct inode *dir, struct path *path, int mode, dev_t dev);
26727+int vfsub_link(struct dentry *src_dentry, struct inode *dir,
26728+ struct path *path);
26729+int vfsub_rename(struct inode *src_hdir, struct dentry *src_dentry,
26730+ struct inode *hdir, struct path *path);
26731+int vfsub_mkdir(struct inode *dir, struct path *path, int mode);
26732+int vfsub_rmdir(struct inode *dir, struct path *path);
26733+
26734+/* ---------------------------------------------------------------------- */
26735+
26736+ssize_t vfsub_read_u(struct file *file, char __user *ubuf, size_t count,
26737+ loff_t *ppos);
26738+ssize_t vfsub_read_k(struct file *file, void *kbuf, size_t count,
26739+ loff_t *ppos);
26740+ssize_t vfsub_write_u(struct file *file, const char __user *ubuf, size_t count,
26741+ loff_t *ppos);
26742+ssize_t vfsub_write_k(struct file *file, void *kbuf, size_t count,
26743+ loff_t *ppos);
4a4d8108 26744+int vfsub_flush(struct file *file, fl_owner_t id);
1facf9fc 26745+int vfsub_readdir(struct file *file, filldir_t filldir, void *arg);
26746+
4a4d8108
AM
26747+static inline unsigned int vfsub_file_flags(struct file *file)
26748+{
26749+ unsigned int flags;
26750+
26751+ spin_lock(&file->f_lock);
26752+ flags = file->f_flags;
26753+ spin_unlock(&file->f_lock);
26754+
26755+ return flags;
26756+}
1308ab2a 26757+
1facf9fc 26758+static inline void vfsub_file_accessed(struct file *h_file)
26759+{
26760+ file_accessed(h_file);
26761+ vfsub_update_h_iattr(&h_file->f_path, /*did*/NULL); /*ignore*/
26762+}
26763+
26764+static inline void vfsub_touch_atime(struct vfsmount *h_mnt,
26765+ struct dentry *h_dentry)
26766+{
26767+ struct path h_path = {
26768+ .dentry = h_dentry,
26769+ .mnt = h_mnt
26770+ };
92d182d2 26771+ touch_atime(&h_path);
1facf9fc 26772+ vfsub_update_h_iattr(&h_path, /*did*/NULL); /*ignore*/
26773+}
26774+
0c3ec466
AM
26775+static inline int vfsub_update_time(struct inode *h_inode, struct timespec *ts,
26776+ int flags)
26777+{
26778+ return update_time(h_inode, ts, flags);
26779+ /* no vfsub_update_h_iattr() since we don't have struct path */
26780+}
26781+
4a4d8108
AM
26782+long vfsub_splice_to(struct file *in, loff_t *ppos,
26783+ struct pipe_inode_info *pipe, size_t len,
26784+ unsigned int flags);
26785+long vfsub_splice_from(struct pipe_inode_info *pipe, struct file *out,
26786+ loff_t *ppos, size_t len, unsigned int flags);
26787+int vfsub_trunc(struct path *h_path, loff_t length, unsigned int attr,
26788+ struct file *h_file);
53392da6 26789+int vfsub_fsync(struct file *file, struct path *path, int datasync);
4a4d8108 26790+
1facf9fc 26791+/* ---------------------------------------------------------------------- */
26792+
26793+static inline loff_t vfsub_llseek(struct file *file, loff_t offset, int origin)
26794+{
26795+ loff_t err;
26796+
2cbb1c4b 26797+ lockdep_off();
1facf9fc 26798+ err = vfs_llseek(file, offset, origin);
2cbb1c4b 26799+ lockdep_on();
1facf9fc 26800+ return err;
26801+}
26802+
26803+/* ---------------------------------------------------------------------- */
26804+
26805+/* dirty workaround for strict type of fmode_t */
26806+union vfsub_fmu {
26807+ fmode_t fm;
26808+ unsigned int ui;
26809+};
26810+
26811+static inline unsigned int vfsub_fmode_to_uint(fmode_t fm)
26812+{
26813+ union vfsub_fmu u = {
26814+ .fm = fm
26815+ };
26816+
26817+ BUILD_BUG_ON(sizeof(u.fm) != sizeof(u.ui));
26818+
26819+ return u.ui;
26820+}
26821+
26822+static inline fmode_t vfsub_uint_to_fmode(unsigned int ui)
26823+{
26824+ union vfsub_fmu u = {
26825+ .ui = ui
26826+ };
26827+
26828+ return u.fm;
26829+}
26830+
4a4d8108
AM
26831+/* ---------------------------------------------------------------------- */
26832+
26833+int vfsub_sio_mkdir(struct inode *dir, struct path *path, int mode);
26834+int vfsub_sio_rmdir(struct inode *dir, struct path *path);
26835+int vfsub_sio_notify_change(struct path *path, struct iattr *ia);
26836+int vfsub_notify_change(struct path *path, struct iattr *ia);
26837+int vfsub_unlink(struct inode *dir, struct path *path, int force);
26838+
1facf9fc 26839+#endif /* __KERNEL__ */
26840+#endif /* __AUFS_VFSUB_H__ */
7f207e10
AM
26841diff -urN /usr/share/empty/fs/aufs/wbr_policy.c linux/fs/aufs/wbr_policy.c
26842--- /usr/share/empty/fs/aufs/wbr_policy.c 1970-01-01 01:00:00.000000000 +0100
2dfbb274 26843+++ linux/fs/aufs/wbr_policy.c 2012-08-26 08:39:00.763841498 +0200
027c5e7a 26844@@ -0,0 +1,700 @@
1facf9fc 26845+/*
f6c5ef8b 26846+ * Copyright (C) 2005-2012 Junjiro R. Okajima
1facf9fc 26847+ *
26848+ * This program, aufs is free software; you can redistribute it and/or modify
26849+ * it under the terms of the GNU General Public License as published by
26850+ * the Free Software Foundation; either version 2 of the License, or
26851+ * (at your option) any later version.
dece6358
AM
26852+ *
26853+ * This program is distributed in the hope that it will be useful,
26854+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
26855+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
26856+ * GNU General Public License for more details.
26857+ *
26858+ * You should have received a copy of the GNU General Public License
26859+ * along with this program; if not, write to the Free Software
26860+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 26861+ */
26862+
26863+/*
26864+ * policies for selecting one among multiple writable branches
26865+ */
26866+
26867+#include <linux/statfs.h>
26868+#include "aufs.h"
26869+
26870+/* subset of cpup_attr() */
26871+static noinline_for_stack
26872+int au_cpdown_attr(struct path *h_path, struct dentry *h_src)
26873+{
26874+ int err, sbits;
26875+ struct iattr ia;
26876+ struct inode *h_isrc;
26877+
26878+ h_isrc = h_src->d_inode;
26879+ ia.ia_valid = ATTR_FORCE | ATTR_MODE | ATTR_UID | ATTR_GID;
26880+ ia.ia_mode = h_isrc->i_mode;
26881+ ia.ia_uid = h_isrc->i_uid;
26882+ ia.ia_gid = h_isrc->i_gid;
26883+ sbits = !!(ia.ia_mode & (S_ISUID | S_ISGID));
26884+ au_cpup_attr_flags(h_path->dentry->d_inode, h_isrc);
26885+ err = vfsub_sio_notify_change(h_path, &ia);
26886+
26887+ /* is this nfs only? */
26888+ if (!err && sbits && au_test_nfs(h_path->dentry->d_sb)) {
26889+ ia.ia_valid = ATTR_FORCE | ATTR_MODE;
26890+ ia.ia_mode = h_isrc->i_mode;
26891+ err = vfsub_sio_notify_change(h_path, &ia);
26892+ }
26893+
26894+ return err;
26895+}
26896+
26897+#define AuCpdown_PARENT_OPQ 1
26898+#define AuCpdown_WHED (1 << 1)
26899+#define AuCpdown_MADE_DIR (1 << 2)
26900+#define AuCpdown_DIROPQ (1 << 3)
26901+#define au_ftest_cpdown(flags, name) ((flags) & AuCpdown_##name)
7f207e10
AM
26902+#define au_fset_cpdown(flags, name) \
26903+ do { (flags) |= AuCpdown_##name; } while (0)
26904+#define au_fclr_cpdown(flags, name) \
26905+ do { (flags) &= ~AuCpdown_##name; } while (0)
1facf9fc 26906+
26907+struct au_cpdown_dir_args {
26908+ struct dentry *parent;
26909+ unsigned int flags;
26910+};
26911+
26912+static int au_cpdown_dir_opq(struct dentry *dentry, aufs_bindex_t bdst,
26913+ struct au_cpdown_dir_args *a)
26914+{
26915+ int err;
26916+ struct dentry *opq_dentry;
26917+
26918+ opq_dentry = au_diropq_create(dentry, bdst);
26919+ err = PTR_ERR(opq_dentry);
26920+ if (IS_ERR(opq_dentry))
26921+ goto out;
26922+ dput(opq_dentry);
26923+ au_fset_cpdown(a->flags, DIROPQ);
26924+
4f0767ce 26925+out:
1facf9fc 26926+ return err;
26927+}
26928+
26929+static int au_cpdown_dir_wh(struct dentry *dentry, struct dentry *h_parent,
26930+ struct inode *dir, aufs_bindex_t bdst)
26931+{
26932+ int err;
26933+ struct path h_path;
26934+ struct au_branch *br;
26935+
26936+ br = au_sbr(dentry->d_sb, bdst);
26937+ h_path.dentry = au_wh_lkup(h_parent, &dentry->d_name, br);
26938+ err = PTR_ERR(h_path.dentry);
26939+ if (IS_ERR(h_path.dentry))
26940+ goto out;
26941+
26942+ err = 0;
26943+ if (h_path.dentry->d_inode) {
26944+ h_path.mnt = br->br_mnt;
26945+ err = au_wh_unlink_dentry(au_h_iptr(dir, bdst), &h_path,
26946+ dentry);
26947+ }
26948+ dput(h_path.dentry);
26949+
4f0767ce 26950+out:
1facf9fc 26951+ return err;
26952+}
26953+
26954+static int au_cpdown_dir(struct dentry *dentry, aufs_bindex_t bdst,
26955+ struct dentry *h_parent, void *arg)
26956+{
26957+ int err, rerr;
4a4d8108 26958+ aufs_bindex_t bopq, bstart;
1facf9fc 26959+ struct path h_path;
26960+ struct dentry *parent;
26961+ struct inode *h_dir, *h_inode, *inode, *dir;
26962+ struct au_cpdown_dir_args *args = arg;
26963+
26964+ bstart = au_dbstart(dentry);
26965+ /* dentry is di-locked */
26966+ parent = dget_parent(dentry);
26967+ dir = parent->d_inode;
26968+ h_dir = h_parent->d_inode;
26969+ AuDebugOn(h_dir != au_h_iptr(dir, bdst));
26970+ IMustLock(h_dir);
26971+
26972+ err = au_lkup_neg(dentry, bdst);
26973+ if (unlikely(err < 0))
26974+ goto out;
26975+ h_path.dentry = au_h_dptr(dentry, bdst);
26976+ h_path.mnt = au_sbr_mnt(dentry->d_sb, bdst);
26977+ err = vfsub_sio_mkdir(au_h_iptr(dir, bdst), &h_path,
26978+ S_IRWXU | S_IRUGO | S_IXUGO);
26979+ if (unlikely(err))
26980+ goto out_put;
26981+ au_fset_cpdown(args->flags, MADE_DIR);
26982+
1facf9fc 26983+ bopq = au_dbdiropq(dentry);
26984+ au_fclr_cpdown(args->flags, WHED);
26985+ au_fclr_cpdown(args->flags, DIROPQ);
26986+ if (au_dbwh(dentry) == bdst)
26987+ au_fset_cpdown(args->flags, WHED);
26988+ if (!au_ftest_cpdown(args->flags, PARENT_OPQ) && bopq <= bdst)
26989+ au_fset_cpdown(args->flags, PARENT_OPQ);
1facf9fc 26990+ h_inode = h_path.dentry->d_inode;
26991+ mutex_lock_nested(&h_inode->i_mutex, AuLsc_I_CHILD);
26992+ if (au_ftest_cpdown(args->flags, WHED)) {
26993+ err = au_cpdown_dir_opq(dentry, bdst, args);
26994+ if (unlikely(err)) {
26995+ mutex_unlock(&h_inode->i_mutex);
26996+ goto out_dir;
26997+ }
26998+ }
26999+
27000+ err = au_cpdown_attr(&h_path, au_h_dptr(dentry, bstart));
27001+ mutex_unlock(&h_inode->i_mutex);
27002+ if (unlikely(err))
27003+ goto out_opq;
27004+
27005+ if (au_ftest_cpdown(args->flags, WHED)) {
27006+ err = au_cpdown_dir_wh(dentry, h_parent, dir, bdst);
27007+ if (unlikely(err))
27008+ goto out_opq;
27009+ }
27010+
27011+ inode = dentry->d_inode;
27012+ if (au_ibend(inode) < bdst)
27013+ au_set_ibend(inode, bdst);
27014+ au_set_h_iptr(inode, bdst, au_igrab(h_inode),
27015+ au_hi_flags(inode, /*isdir*/1));
27016+ goto out; /* success */
27017+
27018+ /* revert */
4f0767ce 27019+out_opq:
1facf9fc 27020+ if (au_ftest_cpdown(args->flags, DIROPQ)) {
27021+ mutex_lock_nested(&h_inode->i_mutex, AuLsc_I_CHILD);
27022+ rerr = au_diropq_remove(dentry, bdst);
27023+ mutex_unlock(&h_inode->i_mutex);
27024+ if (unlikely(rerr)) {
27025+ AuIOErr("failed removing diropq for %.*s b%d (%d)\n",
27026+ AuDLNPair(dentry), bdst, rerr);
27027+ err = -EIO;
27028+ goto out;
27029+ }
27030+ }
4f0767ce 27031+out_dir:
1facf9fc 27032+ if (au_ftest_cpdown(args->flags, MADE_DIR)) {
27033+ rerr = vfsub_sio_rmdir(au_h_iptr(dir, bdst), &h_path);
27034+ if (unlikely(rerr)) {
27035+ AuIOErr("failed removing %.*s b%d (%d)\n",
27036+ AuDLNPair(dentry), bdst, rerr);
27037+ err = -EIO;
27038+ }
27039+ }
4f0767ce 27040+out_put:
1facf9fc 27041+ au_set_h_dptr(dentry, bdst, NULL);
27042+ if (au_dbend(dentry) == bdst)
27043+ au_update_dbend(dentry);
4f0767ce 27044+out:
1facf9fc 27045+ dput(parent);
27046+ return err;
27047+}
27048+
27049+int au_cpdown_dirs(struct dentry *dentry, aufs_bindex_t bdst)
27050+{
27051+ int err;
27052+ struct au_cpdown_dir_args args = {
27053+ .parent = dget_parent(dentry),
27054+ .flags = 0
27055+ };
27056+
27057+ err = au_cp_dirs(dentry, bdst, au_cpdown_dir, &args);
27058+ dput(args.parent);
27059+
27060+ return err;
27061+}
27062+
27063+/* ---------------------------------------------------------------------- */
27064+
27065+/* policies for create */
27066+
4a4d8108
AM
27067+static int au_wbr_nonopq(struct dentry *dentry, aufs_bindex_t bindex)
27068+{
27069+ int err, i, j, ndentry;
27070+ aufs_bindex_t bopq;
27071+ struct au_dcsub_pages dpages;
27072+ struct au_dpage *dpage;
27073+ struct dentry **dentries, *parent, *d;
27074+
27075+ err = au_dpages_init(&dpages, GFP_NOFS);
27076+ if (unlikely(err))
27077+ goto out;
27078+ parent = dget_parent(dentry);
027c5e7a 27079+ err = au_dcsub_pages_rev_aufs(&dpages, parent, /*do_include*/0);
4a4d8108
AM
27080+ if (unlikely(err))
27081+ goto out_free;
27082+
27083+ err = bindex;
27084+ for (i = 0; i < dpages.ndpage; i++) {
27085+ dpage = dpages.dpages + i;
27086+ dentries = dpage->dentries;
27087+ ndentry = dpage->ndentry;
27088+ for (j = 0; j < ndentry; j++) {
27089+ d = dentries[j];
27090+ di_read_lock_parent2(d, !AuLock_IR);
27091+ bopq = au_dbdiropq(d);
27092+ di_read_unlock(d, !AuLock_IR);
27093+ if (bopq >= 0 && bopq < err)
27094+ err = bopq;
27095+ }
27096+ }
27097+
27098+out_free:
27099+ dput(parent);
27100+ au_dpages_free(&dpages);
27101+out:
27102+ return err;
27103+}
27104+
1facf9fc 27105+static int au_wbr_bu(struct super_block *sb, aufs_bindex_t bindex)
27106+{
27107+ for (; bindex >= 0; bindex--)
27108+ if (!au_br_rdonly(au_sbr(sb, bindex)))
27109+ return bindex;
27110+ return -EROFS;
27111+}
27112+
27113+/* top down parent */
27114+static int au_wbr_create_tdp(struct dentry *dentry, int isdir __maybe_unused)
27115+{
27116+ int err;
27117+ aufs_bindex_t bstart, bindex;
27118+ struct super_block *sb;
27119+ struct dentry *parent, *h_parent;
27120+
27121+ sb = dentry->d_sb;
27122+ bstart = au_dbstart(dentry);
27123+ err = bstart;
27124+ if (!au_br_rdonly(au_sbr(sb, bstart)))
27125+ goto out;
27126+
27127+ err = -EROFS;
27128+ parent = dget_parent(dentry);
27129+ for (bindex = au_dbstart(parent); bindex < bstart; bindex++) {
27130+ h_parent = au_h_dptr(parent, bindex);
27131+ if (!h_parent || !h_parent->d_inode)
27132+ continue;
27133+
27134+ if (!au_br_rdonly(au_sbr(sb, bindex))) {
27135+ err = bindex;
27136+ break;
27137+ }
27138+ }
27139+ dput(parent);
27140+
27141+ /* bottom up here */
4a4d8108 27142+ if (unlikely(err < 0)) {
1facf9fc 27143+ err = au_wbr_bu(sb, bstart - 1);
4a4d8108
AM
27144+ if (err >= 0)
27145+ err = au_wbr_nonopq(dentry, err);
27146+ }
1facf9fc 27147+
4f0767ce 27148+out:
1facf9fc 27149+ AuDbg("b%d\n", err);
27150+ return err;
27151+}
27152+
27153+/* ---------------------------------------------------------------------- */
27154+
27155+/* an exception for the policy other than tdp */
27156+static int au_wbr_create_exp(struct dentry *dentry)
27157+{
27158+ int err;
27159+ aufs_bindex_t bwh, bdiropq;
27160+ struct dentry *parent;
27161+
27162+ err = -1;
27163+ bwh = au_dbwh(dentry);
27164+ parent = dget_parent(dentry);
27165+ bdiropq = au_dbdiropq(parent);
27166+ if (bwh >= 0) {
27167+ if (bdiropq >= 0)
27168+ err = min(bdiropq, bwh);
27169+ else
27170+ err = bwh;
27171+ AuDbg("%d\n", err);
27172+ } else if (bdiropq >= 0) {
27173+ err = bdiropq;
27174+ AuDbg("%d\n", err);
27175+ }
27176+ dput(parent);
27177+
4a4d8108
AM
27178+ if (err >= 0)
27179+ err = au_wbr_nonopq(dentry, err);
27180+
1facf9fc 27181+ if (err >= 0 && au_br_rdonly(au_sbr(dentry->d_sb, err)))
27182+ err = -1;
27183+
27184+ AuDbg("%d\n", err);
27185+ return err;
27186+}
27187+
27188+/* ---------------------------------------------------------------------- */
27189+
27190+/* round robin */
27191+static int au_wbr_create_init_rr(struct super_block *sb)
27192+{
27193+ int err;
27194+
27195+ err = au_wbr_bu(sb, au_sbend(sb));
27196+ atomic_set(&au_sbi(sb)->si_wbr_rr_next, -err); /* less important */
dece6358 27197+ /* smp_mb(); */
1facf9fc 27198+
27199+ AuDbg("b%d\n", err);
27200+ return err;
27201+}
27202+
27203+static int au_wbr_create_rr(struct dentry *dentry, int isdir)
27204+{
27205+ int err, nbr;
27206+ unsigned int u;
27207+ aufs_bindex_t bindex, bend;
27208+ struct super_block *sb;
27209+ atomic_t *next;
27210+
27211+ err = au_wbr_create_exp(dentry);
27212+ if (err >= 0)
27213+ goto out;
27214+
27215+ sb = dentry->d_sb;
27216+ next = &au_sbi(sb)->si_wbr_rr_next;
27217+ bend = au_sbend(sb);
27218+ nbr = bend + 1;
27219+ for (bindex = 0; bindex <= bend; bindex++) {
27220+ if (!isdir) {
27221+ err = atomic_dec_return(next) + 1;
27222+ /* modulo for 0 is meaningless */
27223+ if (unlikely(!err))
27224+ err = atomic_dec_return(next) + 1;
27225+ } else
27226+ err = atomic_read(next);
27227+ AuDbg("%d\n", err);
27228+ u = err;
27229+ err = u % nbr;
27230+ AuDbg("%d\n", err);
27231+ if (!au_br_rdonly(au_sbr(sb, err)))
27232+ break;
27233+ err = -EROFS;
27234+ }
27235+
4a4d8108
AM
27236+ if (err >= 0)
27237+ err = au_wbr_nonopq(dentry, err);
27238+
4f0767ce 27239+out:
1facf9fc 27240+ AuDbg("%d\n", err);
27241+ return err;
27242+}
27243+
27244+/* ---------------------------------------------------------------------- */
27245+
27246+/* most free space */
27247+static void au_mfs(struct dentry *dentry)
27248+{
27249+ struct super_block *sb;
27250+ struct au_branch *br;
27251+ struct au_wbr_mfs *mfs;
27252+ aufs_bindex_t bindex, bend;
27253+ int err;
27254+ unsigned long long b, bavail;
7f207e10 27255+ struct path h_path;
1facf9fc 27256+ /* reduce the stack usage */
27257+ struct kstatfs *st;
27258+
27259+ st = kmalloc(sizeof(*st), GFP_NOFS);
27260+ if (unlikely(!st)) {
27261+ AuWarn1("failed updating mfs(%d), ignored\n", -ENOMEM);
27262+ return;
27263+ }
27264+
27265+ bavail = 0;
27266+ sb = dentry->d_sb;
27267+ mfs = &au_sbi(sb)->si_wbr_mfs;
dece6358 27268+ MtxMustLock(&mfs->mfs_lock);
1facf9fc 27269+ mfs->mfs_bindex = -EROFS;
27270+ mfs->mfsrr_bytes = 0;
27271+ bend = au_sbend(sb);
27272+ for (bindex = 0; bindex <= bend; bindex++) {
27273+ br = au_sbr(sb, bindex);
27274+ if (au_br_rdonly(br))
27275+ continue;
27276+
27277+ /* sb->s_root for NFS is unreliable */
7f207e10
AM
27278+ h_path.mnt = br->br_mnt;
27279+ h_path.dentry = h_path.mnt->mnt_root;
27280+ err = vfs_statfs(&h_path, st);
1facf9fc 27281+ if (unlikely(err)) {
27282+ AuWarn1("failed statfs, b%d, %d\n", bindex, err);
27283+ continue;
27284+ }
27285+
27286+ /* when the available size is equal, select the lower one */
27287+ BUILD_BUG_ON(sizeof(b) < sizeof(st->f_bavail)
27288+ || sizeof(b) < sizeof(st->f_bsize));
27289+ b = st->f_bavail * st->f_bsize;
27290+ br->br_wbr->wbr_bytes = b;
27291+ if (b >= bavail) {
27292+ bavail = b;
27293+ mfs->mfs_bindex = bindex;
27294+ mfs->mfs_jiffy = jiffies;
27295+ }
27296+ }
27297+
27298+ mfs->mfsrr_bytes = bavail;
27299+ AuDbg("b%d\n", mfs->mfs_bindex);
27300+ kfree(st);
27301+}
27302+
27303+static int au_wbr_create_mfs(struct dentry *dentry, int isdir __maybe_unused)
27304+{
27305+ int err;
27306+ struct super_block *sb;
27307+ struct au_wbr_mfs *mfs;
27308+
27309+ err = au_wbr_create_exp(dentry);
27310+ if (err >= 0)
27311+ goto out;
27312+
27313+ sb = dentry->d_sb;
27314+ mfs = &au_sbi(sb)->si_wbr_mfs;
27315+ mutex_lock(&mfs->mfs_lock);
27316+ if (time_after(jiffies, mfs->mfs_jiffy + mfs->mfs_expire)
27317+ || mfs->mfs_bindex < 0
27318+ || au_br_rdonly(au_sbr(sb, mfs->mfs_bindex)))
27319+ au_mfs(dentry);
27320+ mutex_unlock(&mfs->mfs_lock);
27321+ err = mfs->mfs_bindex;
27322+
4a4d8108
AM
27323+ if (err >= 0)
27324+ err = au_wbr_nonopq(dentry, err);
27325+
4f0767ce 27326+out:
1facf9fc 27327+ AuDbg("b%d\n", err);
27328+ return err;
27329+}
27330+
27331+static int au_wbr_create_init_mfs(struct super_block *sb)
27332+{
27333+ struct au_wbr_mfs *mfs;
27334+
27335+ mfs = &au_sbi(sb)->si_wbr_mfs;
27336+ mutex_init(&mfs->mfs_lock);
27337+ mfs->mfs_jiffy = 0;
27338+ mfs->mfs_bindex = -EROFS;
27339+
27340+ return 0;
27341+}
27342+
27343+static int au_wbr_create_fin_mfs(struct super_block *sb __maybe_unused)
27344+{
27345+ mutex_destroy(&au_sbi(sb)->si_wbr_mfs.mfs_lock);
27346+ return 0;
27347+}
27348+
27349+/* ---------------------------------------------------------------------- */
27350+
27351+/* most free space and then round robin */
27352+static int au_wbr_create_mfsrr(struct dentry *dentry, int isdir)
27353+{
27354+ int err;
27355+ struct au_wbr_mfs *mfs;
27356+
27357+ err = au_wbr_create_mfs(dentry, isdir);
27358+ if (err >= 0) {
27359+ mfs = &au_sbi(dentry->d_sb)->si_wbr_mfs;
dece6358 27360+ mutex_lock(&mfs->mfs_lock);
1facf9fc 27361+ if (mfs->mfsrr_bytes < mfs->mfsrr_watermark)
27362+ err = au_wbr_create_rr(dentry, isdir);
dece6358 27363+ mutex_unlock(&mfs->mfs_lock);
1facf9fc 27364+ }
27365+
27366+ AuDbg("b%d\n", err);
27367+ return err;
27368+}
27369+
27370+static int au_wbr_create_init_mfsrr(struct super_block *sb)
27371+{
27372+ int err;
27373+
27374+ au_wbr_create_init_mfs(sb); /* ignore */
27375+ err = au_wbr_create_init_rr(sb);
27376+
27377+ return err;
27378+}
27379+
27380+/* ---------------------------------------------------------------------- */
27381+
27382+/* top down parent and most free space */
27383+static int au_wbr_create_pmfs(struct dentry *dentry, int isdir)
27384+{
27385+ int err, e2;
27386+ unsigned long long b;
27387+ aufs_bindex_t bindex, bstart, bend;
27388+ struct super_block *sb;
27389+ struct dentry *parent, *h_parent;
27390+ struct au_branch *br;
27391+
27392+ err = au_wbr_create_tdp(dentry, isdir);
27393+ if (unlikely(err < 0))
27394+ goto out;
27395+ parent = dget_parent(dentry);
27396+ bstart = au_dbstart(parent);
27397+ bend = au_dbtaildir(parent);
27398+ if (bstart == bend)
27399+ goto out_parent; /* success */
27400+
27401+ e2 = au_wbr_create_mfs(dentry, isdir);
27402+ if (e2 < 0)
27403+ goto out_parent; /* success */
27404+
27405+ /* when the available size is equal, select upper one */
27406+ sb = dentry->d_sb;
27407+ br = au_sbr(sb, err);
27408+ b = br->br_wbr->wbr_bytes;
27409+ AuDbg("b%d, %llu\n", err, b);
27410+
27411+ for (bindex = bstart; bindex <= bend; bindex++) {
27412+ h_parent = au_h_dptr(parent, bindex);
27413+ if (!h_parent || !h_parent->d_inode)
27414+ continue;
27415+
27416+ br = au_sbr(sb, bindex);
27417+ if (!au_br_rdonly(br) && br->br_wbr->wbr_bytes > b) {
27418+ b = br->br_wbr->wbr_bytes;
27419+ err = bindex;
27420+ AuDbg("b%d, %llu\n", err, b);
27421+ }
27422+ }
27423+
4a4d8108
AM
27424+ if (err >= 0)
27425+ err = au_wbr_nonopq(dentry, err);
27426+
4f0767ce 27427+out_parent:
1facf9fc 27428+ dput(parent);
4f0767ce 27429+out:
1facf9fc 27430+ AuDbg("b%d\n", err);
27431+ return err;
27432+}
27433+
27434+/* ---------------------------------------------------------------------- */
27435+
27436+/* policies for copyup */
27437+
27438+/* top down parent */
27439+static int au_wbr_copyup_tdp(struct dentry *dentry)
27440+{
27441+ return au_wbr_create_tdp(dentry, /*isdir, anything is ok*/0);
27442+}
27443+
27444+/* bottom up parent */
27445+static int au_wbr_copyup_bup(struct dentry *dentry)
27446+{
27447+ int err;
27448+ aufs_bindex_t bindex, bstart;
27449+ struct dentry *parent, *h_parent;
27450+ struct super_block *sb;
27451+
27452+ err = -EROFS;
27453+ sb = dentry->d_sb;
27454+ parent = dget_parent(dentry);
27455+ bstart = au_dbstart(parent);
27456+ for (bindex = au_dbstart(dentry); bindex >= bstart; bindex--) {
27457+ h_parent = au_h_dptr(parent, bindex);
27458+ if (!h_parent || !h_parent->d_inode)
27459+ continue;
27460+
27461+ if (!au_br_rdonly(au_sbr(sb, bindex))) {
27462+ err = bindex;
27463+ break;
27464+ }
27465+ }
27466+ dput(parent);
27467+
27468+ /* bottom up here */
27469+ if (unlikely(err < 0))
27470+ err = au_wbr_bu(sb, bstart - 1);
27471+
27472+ AuDbg("b%d\n", err);
27473+ return err;
27474+}
27475+
27476+/* bottom up */
27477+static int au_wbr_copyup_bu(struct dentry *dentry)
27478+{
27479+ int err;
4a4d8108 27480+ aufs_bindex_t bstart;
1facf9fc 27481+
4a4d8108
AM
27482+ bstart = au_dbstart(dentry);
27483+ err = au_wbr_bu(dentry->d_sb, bstart);
27484+ AuDbg("b%d\n", err);
27485+ if (err > bstart)
27486+ err = au_wbr_nonopq(dentry, err);
1facf9fc 27487+
27488+ AuDbg("b%d\n", err);
27489+ return err;
27490+}
27491+
27492+/* ---------------------------------------------------------------------- */
27493+
27494+struct au_wbr_copyup_operations au_wbr_copyup_ops[] = {
27495+ [AuWbrCopyup_TDP] = {
27496+ .copyup = au_wbr_copyup_tdp
27497+ },
27498+ [AuWbrCopyup_BUP] = {
27499+ .copyup = au_wbr_copyup_bup
27500+ },
27501+ [AuWbrCopyup_BU] = {
27502+ .copyup = au_wbr_copyup_bu
27503+ }
27504+};
27505+
27506+struct au_wbr_create_operations au_wbr_create_ops[] = {
27507+ [AuWbrCreate_TDP] = {
27508+ .create = au_wbr_create_tdp
27509+ },
27510+ [AuWbrCreate_RR] = {
27511+ .create = au_wbr_create_rr,
27512+ .init = au_wbr_create_init_rr
27513+ },
27514+ [AuWbrCreate_MFS] = {
27515+ .create = au_wbr_create_mfs,
27516+ .init = au_wbr_create_init_mfs,
27517+ .fin = au_wbr_create_fin_mfs
27518+ },
27519+ [AuWbrCreate_MFSV] = {
27520+ .create = au_wbr_create_mfs,
27521+ .init = au_wbr_create_init_mfs,
27522+ .fin = au_wbr_create_fin_mfs
27523+ },
27524+ [AuWbrCreate_MFSRR] = {
27525+ .create = au_wbr_create_mfsrr,
27526+ .init = au_wbr_create_init_mfsrr,
27527+ .fin = au_wbr_create_fin_mfs
27528+ },
27529+ [AuWbrCreate_MFSRRV] = {
27530+ .create = au_wbr_create_mfsrr,
27531+ .init = au_wbr_create_init_mfsrr,
27532+ .fin = au_wbr_create_fin_mfs
27533+ },
27534+ [AuWbrCreate_PMFS] = {
27535+ .create = au_wbr_create_pmfs,
27536+ .init = au_wbr_create_init_mfs,
27537+ .fin = au_wbr_create_fin_mfs
27538+ },
27539+ [AuWbrCreate_PMFSV] = {
27540+ .create = au_wbr_create_pmfs,
27541+ .init = au_wbr_create_init_mfs,
27542+ .fin = au_wbr_create_fin_mfs
27543+ }
27544+};
7f207e10
AM
27545diff -urN /usr/share/empty/fs/aufs/whout.c linux/fs/aufs/whout.c
27546--- /usr/share/empty/fs/aufs/whout.c 1970-01-01 01:00:00.000000000 +0100
b4510431
AM
27547+++ linux/fs/aufs/whout.c 2012-10-17 10:31:01.775814563 +0200
27548@@ -0,0 +1,1042 @@
1facf9fc 27549+/*
f6c5ef8b 27550+ * Copyright (C) 2005-2012 Junjiro R. Okajima
1facf9fc 27551+ *
27552+ * This program, aufs is free software; you can redistribute it and/or modify
27553+ * it under the terms of the GNU General Public License as published by
27554+ * the Free Software Foundation; either version 2 of the License, or
27555+ * (at your option) any later version.
dece6358
AM
27556+ *
27557+ * This program is distributed in the hope that it will be useful,
27558+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
27559+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
27560+ * GNU General Public License for more details.
27561+ *
27562+ * You should have received a copy of the GNU General Public License
27563+ * along with this program; if not, write to the Free Software
27564+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 27565+ */
27566+
27567+/*
27568+ * whiteout for logical deletion and opaque directory
27569+ */
27570+
1facf9fc 27571+#include "aufs.h"
27572+
27573+#define WH_MASK S_IRUGO
27574+
27575+/*
27576+ * If a directory contains this file, then it is opaque. We start with the
27577+ * .wh. flag so that it is blocked by lookup.
27578+ */
0c3ec466
AM
27579+static struct qstr diropq_name = QSTR_INIT(AUFS_WH_DIROPQ,
27580+ sizeof(AUFS_WH_DIROPQ) - 1);
1facf9fc 27581+
27582+/*
27583+ * generate whiteout name, which is NOT terminated by NULL.
27584+ * @name: original d_name.name
27585+ * @len: original d_name.len
27586+ * @wh: whiteout qstr
27587+ * returns zero when succeeds, otherwise error.
27588+ * succeeded value as wh->name should be freed by kfree().
27589+ */
27590+int au_wh_name_alloc(struct qstr *wh, const struct qstr *name)
27591+{
27592+ char *p;
27593+
27594+ if (unlikely(name->len > PATH_MAX - AUFS_WH_PFX_LEN))
27595+ return -ENAMETOOLONG;
27596+
27597+ wh->len = name->len + AUFS_WH_PFX_LEN;
27598+ p = kmalloc(wh->len, GFP_NOFS);
27599+ wh->name = p;
27600+ if (p) {
27601+ memcpy(p, AUFS_WH_PFX, AUFS_WH_PFX_LEN);
27602+ memcpy(p + AUFS_WH_PFX_LEN, name->name, name->len);
27603+ /* smp_mb(); */
27604+ return 0;
27605+ }
27606+ return -ENOMEM;
27607+}
27608+
27609+/* ---------------------------------------------------------------------- */
27610+
27611+/*
27612+ * test if the @wh_name exists under @h_parent.
27613+ * @try_sio specifies the necessary of super-io.
27614+ */
27615+int au_wh_test(struct dentry *h_parent, struct qstr *wh_name,
27616+ struct au_branch *br, int try_sio)
27617+{
27618+ int err;
27619+ struct dentry *wh_dentry;
1facf9fc 27620+
1facf9fc 27621+ if (!try_sio)
b4510431 27622+ wh_dentry = vfsub_lkup_one(wh_name, h_parent);
1facf9fc 27623+ else
27624+ wh_dentry = au_sio_lkup_one(wh_name, h_parent, br);
27625+ err = PTR_ERR(wh_dentry);
27626+ if (IS_ERR(wh_dentry))
27627+ goto out;
27628+
27629+ err = 0;
27630+ if (!wh_dentry->d_inode)
27631+ goto out_wh; /* success */
27632+
27633+ err = 1;
27634+ if (S_ISREG(wh_dentry->d_inode->i_mode))
27635+ goto out_wh; /* success */
27636+
27637+ err = -EIO;
27638+ AuIOErr("%.*s Invalid whiteout entry type 0%o.\n",
27639+ AuDLNPair(wh_dentry), wh_dentry->d_inode->i_mode);
27640+
4f0767ce 27641+out_wh:
1facf9fc 27642+ dput(wh_dentry);
4f0767ce 27643+out:
1facf9fc 27644+ return err;
27645+}
27646+
27647+/*
27648+ * test if the @h_dentry sets opaque or not.
27649+ */
27650+int au_diropq_test(struct dentry *h_dentry, struct au_branch *br)
27651+{
27652+ int err;
27653+ struct inode *h_dir;
27654+
27655+ h_dir = h_dentry->d_inode;
27656+ err = au_wh_test(h_dentry, &diropq_name, br,
27657+ au_test_h_perm_sio(h_dir, MAY_EXEC));
27658+ return err;
27659+}
27660+
27661+/*
27662+ * returns a negative dentry whose name is unique and temporary.
27663+ */
27664+struct dentry *au_whtmp_lkup(struct dentry *h_parent, struct au_branch *br,
27665+ struct qstr *prefix)
27666+{
1facf9fc 27667+ struct dentry *dentry;
27668+ int i;
027c5e7a 27669+ char defname[NAME_MAX - AUFS_MAX_NAMELEN + DNAME_INLINE_LEN + 1],
4a4d8108 27670+ *name, *p;
027c5e7a 27671+ /* strict atomic_t is unnecessary here */
1facf9fc 27672+ static unsigned short cnt;
27673+ struct qstr qs;
27674+
4a4d8108
AM
27675+ BUILD_BUG_ON(sizeof(cnt) * 2 > AUFS_WH_TMP_LEN);
27676+
1facf9fc 27677+ name = defname;
027c5e7a
AM
27678+ qs.len = sizeof(defname) - DNAME_INLINE_LEN + prefix->len - 1;
27679+ if (unlikely(prefix->len > DNAME_INLINE_LEN)) {
1facf9fc 27680+ dentry = ERR_PTR(-ENAMETOOLONG);
4a4d8108 27681+ if (unlikely(qs.len > NAME_MAX))
1facf9fc 27682+ goto out;
27683+ dentry = ERR_PTR(-ENOMEM);
27684+ name = kmalloc(qs.len + 1, GFP_NOFS);
27685+ if (unlikely(!name))
27686+ goto out;
27687+ }
27688+
27689+ /* doubly whiteout-ed */
27690+ memcpy(name, AUFS_WH_PFX AUFS_WH_PFX, AUFS_WH_PFX_LEN * 2);
27691+ p = name + AUFS_WH_PFX_LEN * 2;
27692+ memcpy(p, prefix->name, prefix->len);
27693+ p += prefix->len;
27694+ *p++ = '.';
4a4d8108 27695+ AuDebugOn(name + qs.len + 1 - p <= AUFS_WH_TMP_LEN);
1facf9fc 27696+
27697+ qs.name = name;
27698+ for (i = 0; i < 3; i++) {
b752ccd1 27699+ sprintf(p, "%.*x", AUFS_WH_TMP_LEN, cnt++);
1facf9fc 27700+ dentry = au_sio_lkup_one(&qs, h_parent, br);
27701+ if (IS_ERR(dentry) || !dentry->d_inode)
27702+ goto out_name;
27703+ dput(dentry);
27704+ }
0c3ec466 27705+ /* pr_warn("could not get random name\n"); */
1facf9fc 27706+ dentry = ERR_PTR(-EEXIST);
27707+ AuDbg("%.*s\n", AuLNPair(&qs));
27708+ BUG();
27709+
4f0767ce 27710+out_name:
1facf9fc 27711+ if (name != defname)
27712+ kfree(name);
4f0767ce 27713+out:
4a4d8108 27714+ AuTraceErrPtr(dentry);
1facf9fc 27715+ return dentry;
1facf9fc 27716+}
27717+
27718+/*
27719+ * rename the @h_dentry on @br to the whiteouted temporary name.
27720+ */
27721+int au_whtmp_ren(struct dentry *h_dentry, struct au_branch *br)
27722+{
27723+ int err;
27724+ struct path h_path = {
27725+ .mnt = br->br_mnt
27726+ };
27727+ struct inode *h_dir;
27728+ struct dentry *h_parent;
27729+
27730+ h_parent = h_dentry->d_parent; /* dir inode is locked */
27731+ h_dir = h_parent->d_inode;
27732+ IMustLock(h_dir);
27733+
27734+ h_path.dentry = au_whtmp_lkup(h_parent, br, &h_dentry->d_name);
27735+ err = PTR_ERR(h_path.dentry);
27736+ if (IS_ERR(h_path.dentry))
27737+ goto out;
27738+
27739+ /* under the same dir, no need to lock_rename() */
27740+ err = vfsub_rename(h_dir, h_dentry, h_dir, &h_path);
27741+ AuTraceErr(err);
27742+ dput(h_path.dentry);
27743+
4f0767ce 27744+out:
4a4d8108 27745+ AuTraceErr(err);
1facf9fc 27746+ return err;
27747+}
27748+
27749+/* ---------------------------------------------------------------------- */
27750+/*
27751+ * functions for removing a whiteout
27752+ */
27753+
27754+static int do_unlink_wh(struct inode *h_dir, struct path *h_path)
27755+{
27756+ int force;
27757+
27758+ /*
27759+ * forces superio when the dir has a sticky bit.
27760+ * this may be a violation of unix fs semantics.
27761+ */
27762+ force = (h_dir->i_mode & S_ISVTX)
0c3ec466 27763+ && !uid_eq(current_fsuid(), h_path->dentry->d_inode->i_uid);
1facf9fc 27764+ return vfsub_unlink(h_dir, h_path, force);
27765+}
27766+
27767+int au_wh_unlink_dentry(struct inode *h_dir, struct path *h_path,
27768+ struct dentry *dentry)
27769+{
27770+ int err;
27771+
27772+ err = do_unlink_wh(h_dir, h_path);
27773+ if (!err && dentry)
27774+ au_set_dbwh(dentry, -1);
27775+
27776+ return err;
27777+}
27778+
27779+static int unlink_wh_name(struct dentry *h_parent, struct qstr *wh,
27780+ struct au_branch *br)
27781+{
27782+ int err;
27783+ struct path h_path = {
27784+ .mnt = br->br_mnt
27785+ };
27786+
27787+ err = 0;
b4510431 27788+ h_path.dentry = vfsub_lkup_one(wh, h_parent);
1facf9fc 27789+ if (IS_ERR(h_path.dentry))
27790+ err = PTR_ERR(h_path.dentry);
27791+ else {
27792+ if (h_path.dentry->d_inode
27793+ && S_ISREG(h_path.dentry->d_inode->i_mode))
27794+ err = do_unlink_wh(h_parent->d_inode, &h_path);
27795+ dput(h_path.dentry);
27796+ }
27797+
27798+ return err;
27799+}
27800+
27801+/* ---------------------------------------------------------------------- */
27802+/*
27803+ * initialize/clean whiteout for a branch
27804+ */
27805+
27806+static void au_wh_clean(struct inode *h_dir, struct path *whpath,
27807+ const int isdir)
27808+{
27809+ int err;
27810+
27811+ if (!whpath->dentry->d_inode)
27812+ return;
27813+
b4510431 27814+ err = vfsub_mnt_want_write(whpath->mnt);
1facf9fc 27815+ if (!err) {
27816+ if (isdir)
27817+ err = vfsub_rmdir(h_dir, whpath);
27818+ else
27819+ err = vfsub_unlink(h_dir, whpath, /*force*/0);
b4510431 27820+ vfsub_mnt_drop_write(whpath->mnt);
1facf9fc 27821+ }
27822+ if (unlikely(err))
0c3ec466
AM
27823+ pr_warn("failed removing %.*s (%d), ignored.\n",
27824+ AuDLNPair(whpath->dentry), err);
1facf9fc 27825+}
27826+
27827+static int test_linkable(struct dentry *h_root)
27828+{
27829+ struct inode *h_dir = h_root->d_inode;
27830+
27831+ if (h_dir->i_op->link)
27832+ return 0;
27833+
4a4d8108
AM
27834+ pr_err("%.*s (%s) doesn't support link(2), use noplink and rw+nolwh\n",
27835+ AuDLNPair(h_root), au_sbtype(h_root->d_sb));
1facf9fc 27836+ return -ENOSYS;
27837+}
27838+
27839+/* todo: should this mkdir be done in /sbin/mount.aufs helper? */
27840+static int au_whdir(struct inode *h_dir, struct path *path)
27841+{
27842+ int err;
27843+
27844+ err = -EEXIST;
27845+ if (!path->dentry->d_inode) {
27846+ int mode = S_IRWXU;
27847+
27848+ if (au_test_nfs(path->dentry->d_sb))
27849+ mode |= S_IXUGO;
b4510431 27850+ err = vfsub_mnt_want_write(path->mnt);
1facf9fc 27851+ if (!err) {
27852+ err = vfsub_mkdir(h_dir, path, mode);
b4510431 27853+ vfsub_mnt_drop_write(path->mnt);
1facf9fc 27854+ }
27855+ } else if (S_ISDIR(path->dentry->d_inode->i_mode))
27856+ err = 0;
27857+ else
4a4d8108 27858+ pr_err("unknown %.*s exists\n", AuDLNPair(path->dentry));
1facf9fc 27859+
27860+ return err;
27861+}
27862+
27863+struct au_wh_base {
27864+ const struct qstr *name;
27865+ struct dentry *dentry;
27866+};
27867+
27868+static void au_wh_init_ro(struct inode *h_dir, struct au_wh_base base[],
27869+ struct path *h_path)
27870+{
27871+ h_path->dentry = base[AuBrWh_BASE].dentry;
27872+ au_wh_clean(h_dir, h_path, /*isdir*/0);
27873+ h_path->dentry = base[AuBrWh_PLINK].dentry;
27874+ au_wh_clean(h_dir, h_path, /*isdir*/1);
27875+ h_path->dentry = base[AuBrWh_ORPH].dentry;
27876+ au_wh_clean(h_dir, h_path, /*isdir*/1);
27877+}
27878+
27879+/*
27880+ * returns tri-state,
27881+ * minus: error, caller should print the mesage
27882+ * zero: succuess
27883+ * plus: error, caller should NOT print the mesage
27884+ */
27885+static int au_wh_init_rw_nolink(struct dentry *h_root, struct au_wbr *wbr,
27886+ int do_plink, struct au_wh_base base[],
27887+ struct path *h_path)
27888+{
27889+ int err;
27890+ struct inode *h_dir;
27891+
27892+ h_dir = h_root->d_inode;
27893+ h_path->dentry = base[AuBrWh_BASE].dentry;
27894+ au_wh_clean(h_dir, h_path, /*isdir*/0);
27895+ h_path->dentry = base[AuBrWh_PLINK].dentry;
27896+ if (do_plink) {
27897+ err = test_linkable(h_root);
27898+ if (unlikely(err)) {
27899+ err = 1;
27900+ goto out;
27901+ }
27902+
27903+ err = au_whdir(h_dir, h_path);
27904+ if (unlikely(err))
27905+ goto out;
27906+ wbr->wbr_plink = dget(base[AuBrWh_PLINK].dentry);
27907+ } else
27908+ au_wh_clean(h_dir, h_path, /*isdir*/1);
27909+ h_path->dentry = base[AuBrWh_ORPH].dentry;
27910+ err = au_whdir(h_dir, h_path);
27911+ if (unlikely(err))
27912+ goto out;
27913+ wbr->wbr_orph = dget(base[AuBrWh_ORPH].dentry);
27914+
4f0767ce 27915+out:
1facf9fc 27916+ return err;
27917+}
27918+
27919+/*
27920+ * for the moment, aufs supports the branch filesystem which does not support
27921+ * link(2). testing on FAT which does not support i_op->setattr() fully either,
27922+ * copyup failed. finally, such filesystem will not be used as the writable
27923+ * branch.
27924+ *
27925+ * returns tri-state, see above.
27926+ */
27927+static int au_wh_init_rw(struct dentry *h_root, struct au_wbr *wbr,
27928+ int do_plink, struct au_wh_base base[],
27929+ struct path *h_path)
27930+{
27931+ int err;
27932+ struct inode *h_dir;
27933+
1308ab2a 27934+ WbrWhMustWriteLock(wbr);
27935+
1facf9fc 27936+ err = test_linkable(h_root);
27937+ if (unlikely(err)) {
27938+ err = 1;
27939+ goto out;
27940+ }
27941+
27942+ /*
27943+ * todo: should this create be done in /sbin/mount.aufs helper?
27944+ */
27945+ err = -EEXIST;
27946+ h_dir = h_root->d_inode;
27947+ if (!base[AuBrWh_BASE].dentry->d_inode) {
b4510431 27948+ err = vfsub_mnt_want_write(h_path->mnt);
1facf9fc 27949+ if (!err) {
27950+ h_path->dentry = base[AuBrWh_BASE].dentry;
b4510431
AM
27951+ err = vfsub_create(h_dir, h_path, WH_MASK,
27952+ /*want_excl*/true);
27953+ vfsub_mnt_drop_write(h_path->mnt);
1facf9fc 27954+ }
27955+ } else if (S_ISREG(base[AuBrWh_BASE].dentry->d_inode->i_mode))
27956+ err = 0;
27957+ else
4a4d8108
AM
27958+ pr_err("unknown %.*s/%.*s exists\n",
27959+ AuDLNPair(h_root), AuDLNPair(base[AuBrWh_BASE].dentry));
1facf9fc 27960+ if (unlikely(err))
27961+ goto out;
27962+
27963+ h_path->dentry = base[AuBrWh_PLINK].dentry;
27964+ if (do_plink) {
27965+ err = au_whdir(h_dir, h_path);
27966+ if (unlikely(err))
27967+ goto out;
27968+ wbr->wbr_plink = dget(base[AuBrWh_PLINK].dentry);
27969+ } else
27970+ au_wh_clean(h_dir, h_path, /*isdir*/1);
27971+ wbr->wbr_whbase = dget(base[AuBrWh_BASE].dentry);
27972+
27973+ h_path->dentry = base[AuBrWh_ORPH].dentry;
27974+ err = au_whdir(h_dir, h_path);
27975+ if (unlikely(err))
27976+ goto out;
27977+ wbr->wbr_orph = dget(base[AuBrWh_ORPH].dentry);
27978+
4f0767ce 27979+out:
1facf9fc 27980+ return err;
27981+}
27982+
27983+/*
27984+ * initialize the whiteout base file/dir for @br.
27985+ */
27986+int au_wh_init(struct dentry *h_root, struct au_branch *br,
27987+ struct super_block *sb)
27988+{
27989+ int err, i;
27990+ const unsigned char do_plink
27991+ = !!au_opt_test(au_mntflags(sb), PLINK);
27992+ struct path path = {
27993+ .mnt = br->br_mnt
27994+ };
27995+ struct inode *h_dir;
27996+ struct au_wbr *wbr = br->br_wbr;
27997+ static const struct qstr base_name[] = {
0c3ec466
AM
27998+ [AuBrWh_BASE] = QSTR_INIT(AUFS_BASE_NAME,
27999+ sizeof(AUFS_BASE_NAME) - 1),
28000+ [AuBrWh_PLINK] = QSTR_INIT(AUFS_PLINKDIR_NAME,
28001+ sizeof(AUFS_PLINKDIR_NAME) - 1),
28002+ [AuBrWh_ORPH] = QSTR_INIT(AUFS_ORPHDIR_NAME,
28003+ sizeof(AUFS_ORPHDIR_NAME) - 1)
1facf9fc 28004+ };
28005+ struct au_wh_base base[] = {
28006+ [AuBrWh_BASE] = {
28007+ .name = base_name + AuBrWh_BASE,
28008+ .dentry = NULL
28009+ },
28010+ [AuBrWh_PLINK] = {
28011+ .name = base_name + AuBrWh_PLINK,
28012+ .dentry = NULL
28013+ },
28014+ [AuBrWh_ORPH] = {
28015+ .name = base_name + AuBrWh_ORPH,
28016+ .dentry = NULL
28017+ }
28018+ };
28019+
1308ab2a 28020+ if (wbr)
28021+ WbrWhMustWriteLock(wbr);
1facf9fc 28022+
1facf9fc 28023+ for (i = 0; i < AuBrWh_Last; i++) {
28024+ /* doubly whiteouted */
28025+ struct dentry *d;
28026+
28027+ d = au_wh_lkup(h_root, (void *)base[i].name, br);
28028+ err = PTR_ERR(d);
28029+ if (IS_ERR(d))
28030+ goto out;
28031+
28032+ base[i].dentry = d;
28033+ AuDebugOn(wbr
28034+ && wbr->wbr_wh[i]
28035+ && wbr->wbr_wh[i] != base[i].dentry);
28036+ }
28037+
28038+ if (wbr)
28039+ for (i = 0; i < AuBrWh_Last; i++) {
28040+ dput(wbr->wbr_wh[i]);
28041+ wbr->wbr_wh[i] = NULL;
28042+ }
28043+
28044+ err = 0;
1e00d052 28045+ if (!au_br_writable(br->br_perm)) {
4a4d8108 28046+ h_dir = h_root->d_inode;
1facf9fc 28047+ au_wh_init_ro(h_dir, base, &path);
1e00d052 28048+ } else if (!au_br_wh_linkable(br->br_perm)) {
1facf9fc 28049+ err = au_wh_init_rw_nolink(h_root, wbr, do_plink, base, &path);
28050+ if (err > 0)
28051+ goto out;
28052+ else if (err)
28053+ goto out_err;
1e00d052 28054+ } else {
1facf9fc 28055+ err = au_wh_init_rw(h_root, wbr, do_plink, base, &path);
28056+ if (err > 0)
28057+ goto out;
28058+ else if (err)
28059+ goto out_err;
1facf9fc 28060+ }
28061+ goto out; /* success */
28062+
4f0767ce 28063+out_err:
4a4d8108
AM
28064+ pr_err("an error(%d) on the writable branch %.*s(%s)\n",
28065+ err, AuDLNPair(h_root), au_sbtype(h_root->d_sb));
4f0767ce 28066+out:
1facf9fc 28067+ for (i = 0; i < AuBrWh_Last; i++)
28068+ dput(base[i].dentry);
28069+ return err;
28070+}
28071+
28072+/* ---------------------------------------------------------------------- */
28073+/*
28074+ * whiteouts are all hard-linked usually.
28075+ * when its link count reaches a ceiling, we create a new whiteout base
28076+ * asynchronously.
28077+ */
28078+
28079+struct reinit_br_wh {
28080+ struct super_block *sb;
28081+ struct au_branch *br;
28082+};
28083+
28084+static void reinit_br_wh(void *arg)
28085+{
28086+ int err;
28087+ aufs_bindex_t bindex;
28088+ struct path h_path;
28089+ struct reinit_br_wh *a = arg;
28090+ struct au_wbr *wbr;
28091+ struct inode *dir;
28092+ struct dentry *h_root;
28093+ struct au_hinode *hdir;
28094+
28095+ err = 0;
28096+ wbr = a->br->br_wbr;
28097+ /* big aufs lock */
28098+ si_noflush_write_lock(a->sb);
28099+ if (!au_br_writable(a->br->br_perm))
28100+ goto out;
28101+ bindex = au_br_index(a->sb, a->br->br_id);
28102+ if (unlikely(bindex < 0))
28103+ goto out;
28104+
1308ab2a 28105+ di_read_lock_parent(a->sb->s_root, AuLock_IR);
1facf9fc 28106+ dir = a->sb->s_root->d_inode;
1facf9fc 28107+ hdir = au_hi(dir, bindex);
28108+ h_root = au_h_dptr(a->sb->s_root, bindex);
28109+
4a4d8108 28110+ au_hn_imtx_lock_nested(hdir, AuLsc_I_PARENT);
1facf9fc 28111+ wbr_wh_write_lock(wbr);
28112+ err = au_h_verify(wbr->wbr_whbase, au_opt_udba(a->sb), hdir->hi_inode,
28113+ h_root, a->br);
28114+ if (!err) {
b4510431 28115+ err = vfsub_mnt_want_write(a->br->br_mnt);
1facf9fc 28116+ if (!err) {
28117+ h_path.dentry = wbr->wbr_whbase;
28118+ h_path.mnt = a->br->br_mnt;
28119+ err = vfsub_unlink(hdir->hi_inode, &h_path, /*force*/0);
b4510431 28120+ vfsub_mnt_drop_write(a->br->br_mnt);
1facf9fc 28121+ }
28122+ } else {
0c3ec466
AM
28123+ pr_warn("%.*s is moved, ignored\n",
28124+ AuDLNPair(wbr->wbr_whbase));
1facf9fc 28125+ err = 0;
28126+ }
28127+ dput(wbr->wbr_whbase);
28128+ wbr->wbr_whbase = NULL;
28129+ if (!err)
28130+ err = au_wh_init(h_root, a->br, a->sb);
28131+ wbr_wh_write_unlock(wbr);
4a4d8108 28132+ au_hn_imtx_unlock(hdir);
1308ab2a 28133+ di_read_unlock(a->sb->s_root, AuLock_IR);
1facf9fc 28134+
4f0767ce 28135+out:
1facf9fc 28136+ if (wbr)
28137+ atomic_dec(&wbr->wbr_wh_running);
28138+ atomic_dec(&a->br->br_count);
1facf9fc 28139+ si_write_unlock(a->sb);
027c5e7a 28140+ au_nwt_done(&au_sbi(a->sb)->si_nowait);
1facf9fc 28141+ kfree(arg);
28142+ if (unlikely(err))
28143+ AuIOErr("err %d\n", err);
28144+}
28145+
28146+static void kick_reinit_br_wh(struct super_block *sb, struct au_branch *br)
28147+{
28148+ int do_dec, wkq_err;
28149+ struct reinit_br_wh *arg;
28150+
28151+ do_dec = 1;
28152+ if (atomic_inc_return(&br->br_wbr->wbr_wh_running) != 1)
28153+ goto out;
28154+
28155+ /* ignore ENOMEM */
28156+ arg = kmalloc(sizeof(*arg), GFP_NOFS);
28157+ if (arg) {
28158+ /*
28159+ * dec(wh_running), kfree(arg) and dec(br_count)
28160+ * in reinit function
28161+ */
28162+ arg->sb = sb;
28163+ arg->br = br;
28164+ atomic_inc(&br->br_count);
53392da6 28165+ wkq_err = au_wkq_nowait(reinit_br_wh, arg, sb, /*flags*/0);
1facf9fc 28166+ if (unlikely(wkq_err)) {
28167+ atomic_dec(&br->br_wbr->wbr_wh_running);
28168+ atomic_dec(&br->br_count);
28169+ kfree(arg);
28170+ }
28171+ do_dec = 0;
28172+ }
28173+
4f0767ce 28174+out:
1facf9fc 28175+ if (do_dec)
28176+ atomic_dec(&br->br_wbr->wbr_wh_running);
28177+}
28178+
28179+/* ---------------------------------------------------------------------- */
28180+
28181+/*
28182+ * create the whiteout @wh.
28183+ */
28184+static int link_or_create_wh(struct super_block *sb, aufs_bindex_t bindex,
28185+ struct dentry *wh)
28186+{
28187+ int err;
28188+ struct path h_path = {
28189+ .dentry = wh
28190+ };
28191+ struct au_branch *br;
28192+ struct au_wbr *wbr;
28193+ struct dentry *h_parent;
28194+ struct inode *h_dir;
28195+
28196+ h_parent = wh->d_parent; /* dir inode is locked */
28197+ h_dir = h_parent->d_inode;
28198+ IMustLock(h_dir);
28199+
28200+ br = au_sbr(sb, bindex);
28201+ h_path.mnt = br->br_mnt;
28202+ wbr = br->br_wbr;
28203+ wbr_wh_read_lock(wbr);
28204+ if (wbr->wbr_whbase) {
28205+ err = vfsub_link(wbr->wbr_whbase, h_dir, &h_path);
28206+ if (!err || err != -EMLINK)
28207+ goto out;
28208+
28209+ /* link count full. re-initialize br_whbase. */
28210+ kick_reinit_br_wh(sb, br);
28211+ }
28212+
28213+ /* return this error in this context */
b4510431 28214+ err = vfsub_create(h_dir, &h_path, WH_MASK, /*want_excl*/true);
1facf9fc 28215+
4f0767ce 28216+out:
1facf9fc 28217+ wbr_wh_read_unlock(wbr);
28218+ return err;
28219+}
28220+
28221+/* ---------------------------------------------------------------------- */
28222+
28223+/*
28224+ * create or remove the diropq.
28225+ */
28226+static struct dentry *do_diropq(struct dentry *dentry, aufs_bindex_t bindex,
28227+ unsigned int flags)
28228+{
28229+ struct dentry *opq_dentry, *h_dentry;
28230+ struct super_block *sb;
28231+ struct au_branch *br;
28232+ int err;
28233+
28234+ sb = dentry->d_sb;
28235+ br = au_sbr(sb, bindex);
28236+ h_dentry = au_h_dptr(dentry, bindex);
b4510431 28237+ opq_dentry = vfsub_lkup_one(&diropq_name, h_dentry);
1facf9fc 28238+ if (IS_ERR(opq_dentry))
28239+ goto out;
28240+
28241+ if (au_ftest_diropq(flags, CREATE)) {
28242+ err = link_or_create_wh(sb, bindex, opq_dentry);
28243+ if (!err) {
28244+ au_set_dbdiropq(dentry, bindex);
28245+ goto out; /* success */
28246+ }
28247+ } else {
28248+ struct path tmp = {
28249+ .dentry = opq_dentry,
28250+ .mnt = br->br_mnt
28251+ };
28252+ err = do_unlink_wh(au_h_iptr(dentry->d_inode, bindex), &tmp);
28253+ if (!err)
28254+ au_set_dbdiropq(dentry, -1);
28255+ }
28256+ dput(opq_dentry);
28257+ opq_dentry = ERR_PTR(err);
28258+
4f0767ce 28259+out:
1facf9fc 28260+ return opq_dentry;
28261+}
28262+
28263+struct do_diropq_args {
28264+ struct dentry **errp;
28265+ struct dentry *dentry;
28266+ aufs_bindex_t bindex;
28267+ unsigned int flags;
28268+};
28269+
28270+static void call_do_diropq(void *args)
28271+{
28272+ struct do_diropq_args *a = args;
28273+ *a->errp = do_diropq(a->dentry, a->bindex, a->flags);
28274+}
28275+
28276+struct dentry *au_diropq_sio(struct dentry *dentry, aufs_bindex_t bindex,
28277+ unsigned int flags)
28278+{
28279+ struct dentry *diropq, *h_dentry;
28280+
28281+ h_dentry = au_h_dptr(dentry, bindex);
28282+ if (!au_test_h_perm_sio(h_dentry->d_inode, MAY_EXEC | MAY_WRITE))
28283+ diropq = do_diropq(dentry, bindex, flags);
28284+ else {
28285+ int wkq_err;
28286+ struct do_diropq_args args = {
28287+ .errp = &diropq,
28288+ .dentry = dentry,
28289+ .bindex = bindex,
28290+ .flags = flags
28291+ };
28292+
28293+ wkq_err = au_wkq_wait(call_do_diropq, &args);
28294+ if (unlikely(wkq_err))
28295+ diropq = ERR_PTR(wkq_err);
28296+ }
28297+
28298+ return diropq;
28299+}
28300+
28301+/* ---------------------------------------------------------------------- */
28302+
28303+/*
28304+ * lookup whiteout dentry.
28305+ * @h_parent: lower parent dentry which must exist and be locked
28306+ * @base_name: name of dentry which will be whiteouted
28307+ * returns dentry for whiteout.
28308+ */
28309+struct dentry *au_wh_lkup(struct dentry *h_parent, struct qstr *base_name,
28310+ struct au_branch *br)
28311+{
28312+ int err;
28313+ struct qstr wh_name;
28314+ struct dentry *wh_dentry;
28315+
28316+ err = au_wh_name_alloc(&wh_name, base_name);
28317+ wh_dentry = ERR_PTR(err);
28318+ if (!err) {
b4510431 28319+ wh_dentry = vfsub_lkup_one(&wh_name, h_parent);
1facf9fc 28320+ kfree(wh_name.name);
28321+ }
28322+ return wh_dentry;
28323+}
28324+
28325+/*
28326+ * link/create a whiteout for @dentry on @bindex.
28327+ */
28328+struct dentry *au_wh_create(struct dentry *dentry, aufs_bindex_t bindex,
28329+ struct dentry *h_parent)
28330+{
28331+ struct dentry *wh_dentry;
28332+ struct super_block *sb;
28333+ int err;
28334+
28335+ sb = dentry->d_sb;
28336+ wh_dentry = au_wh_lkup(h_parent, &dentry->d_name, au_sbr(sb, bindex));
28337+ if (!IS_ERR(wh_dentry) && !wh_dentry->d_inode) {
28338+ err = link_or_create_wh(sb, bindex, wh_dentry);
28339+ if (!err)
28340+ au_set_dbwh(dentry, bindex);
28341+ else {
28342+ dput(wh_dentry);
28343+ wh_dentry = ERR_PTR(err);
28344+ }
28345+ }
28346+
28347+ return wh_dentry;
28348+}
28349+
28350+/* ---------------------------------------------------------------------- */
28351+
28352+/* Delete all whiteouts in this directory on branch bindex. */
28353+static int del_wh_children(struct dentry *h_dentry, struct au_nhash *whlist,
28354+ aufs_bindex_t bindex, struct au_branch *br)
28355+{
28356+ int err;
28357+ unsigned long ul, n;
28358+ struct qstr wh_name;
28359+ char *p;
28360+ struct hlist_head *head;
28361+ struct au_vdir_wh *tpos;
28362+ struct hlist_node *pos;
28363+ struct au_vdir_destr *str;
28364+
28365+ err = -ENOMEM;
4a4d8108 28366+ p = __getname_gfp(GFP_NOFS);
1facf9fc 28367+ wh_name.name = p;
28368+ if (unlikely(!wh_name.name))
28369+ goto out;
28370+
28371+ err = 0;
28372+ memcpy(p, AUFS_WH_PFX, AUFS_WH_PFX_LEN);
28373+ p += AUFS_WH_PFX_LEN;
28374+ n = whlist->nh_num;
28375+ head = whlist->nh_head;
28376+ for (ul = 0; !err && ul < n; ul++, head++) {
28377+ hlist_for_each_entry(tpos, pos, head, wh_hash) {
28378+ if (tpos->wh_bindex != bindex)
28379+ continue;
28380+
28381+ str = &tpos->wh_str;
28382+ if (str->len + AUFS_WH_PFX_LEN <= PATH_MAX) {
28383+ memcpy(p, str->name, str->len);
28384+ wh_name.len = AUFS_WH_PFX_LEN + str->len;
28385+ err = unlink_wh_name(h_dentry, &wh_name, br);
28386+ if (!err)
28387+ continue;
28388+ break;
28389+ }
28390+ AuIOErr("whiteout name too long %.*s\n",
28391+ str->len, str->name);
28392+ err = -EIO;
28393+ break;
28394+ }
28395+ }
28396+ __putname(wh_name.name);
28397+
4f0767ce 28398+out:
1facf9fc 28399+ return err;
28400+}
28401+
28402+struct del_wh_children_args {
28403+ int *errp;
28404+ struct dentry *h_dentry;
1308ab2a 28405+ struct au_nhash *whlist;
1facf9fc 28406+ aufs_bindex_t bindex;
28407+ struct au_branch *br;
28408+};
28409+
28410+static void call_del_wh_children(void *args)
28411+{
28412+ struct del_wh_children_args *a = args;
1308ab2a 28413+ *a->errp = del_wh_children(a->h_dentry, a->whlist, a->bindex, a->br);
1facf9fc 28414+}
28415+
28416+/* ---------------------------------------------------------------------- */
28417+
28418+struct au_whtmp_rmdir *au_whtmp_rmdir_alloc(struct super_block *sb, gfp_t gfp)
28419+{
28420+ struct au_whtmp_rmdir *whtmp;
dece6358 28421+ int err;
1308ab2a 28422+ unsigned int rdhash;
dece6358
AM
28423+
28424+ SiMustAnyLock(sb);
1facf9fc 28425+
28426+ whtmp = kmalloc(sizeof(*whtmp), gfp);
dece6358
AM
28427+ if (unlikely(!whtmp)) {
28428+ whtmp = ERR_PTR(-ENOMEM);
1facf9fc 28429+ goto out;
dece6358 28430+ }
1facf9fc 28431+
28432+ whtmp->dir = NULL;
027c5e7a 28433+ whtmp->br = NULL;
1facf9fc 28434+ whtmp->wh_dentry = NULL;
1308ab2a 28435+ /* no estimation for dir size */
28436+ rdhash = au_sbi(sb)->si_rdhash;
28437+ if (!rdhash)
28438+ rdhash = AUFS_RDHASH_DEF;
28439+ err = au_nhash_alloc(&whtmp->whlist, rdhash, gfp);
28440+ if (unlikely(err)) {
28441+ kfree(whtmp);
28442+ whtmp = ERR_PTR(err);
28443+ }
dece6358 28444+
4f0767ce 28445+out:
dece6358 28446+ return whtmp;
1facf9fc 28447+}
28448+
28449+void au_whtmp_rmdir_free(struct au_whtmp_rmdir *whtmp)
28450+{
027c5e7a
AM
28451+ if (whtmp->br)
28452+ atomic_dec(&whtmp->br->br_count);
1facf9fc 28453+ dput(whtmp->wh_dentry);
28454+ iput(whtmp->dir);
dece6358 28455+ au_nhash_wh_free(&whtmp->whlist);
1facf9fc 28456+ kfree(whtmp);
28457+}
28458+
28459+/*
28460+ * rmdir the whiteouted temporary named dir @h_dentry.
28461+ * @whlist: whiteouted children.
28462+ */
28463+int au_whtmp_rmdir(struct inode *dir, aufs_bindex_t bindex,
28464+ struct dentry *wh_dentry, struct au_nhash *whlist)
28465+{
28466+ int err;
28467+ struct path h_tmp;
28468+ struct inode *wh_inode, *h_dir;
28469+ struct au_branch *br;
28470+
28471+ h_dir = wh_dentry->d_parent->d_inode; /* dir inode is locked */
28472+ IMustLock(h_dir);
28473+
28474+ br = au_sbr(dir->i_sb, bindex);
28475+ wh_inode = wh_dentry->d_inode;
28476+ mutex_lock_nested(&wh_inode->i_mutex, AuLsc_I_CHILD);
28477+
28478+ /*
28479+ * someone else might change some whiteouts while we were sleeping.
28480+ * it means this whlist may have an obsoleted entry.
28481+ */
28482+ if (!au_test_h_perm_sio(wh_inode, MAY_EXEC | MAY_WRITE))
28483+ err = del_wh_children(wh_dentry, whlist, bindex, br);
28484+ else {
28485+ int wkq_err;
28486+ struct del_wh_children_args args = {
28487+ .errp = &err,
28488+ .h_dentry = wh_dentry,
1308ab2a 28489+ .whlist = whlist,
1facf9fc 28490+ .bindex = bindex,
28491+ .br = br
28492+ };
28493+
28494+ wkq_err = au_wkq_wait(call_del_wh_children, &args);
28495+ if (unlikely(wkq_err))
28496+ err = wkq_err;
28497+ }
28498+ mutex_unlock(&wh_inode->i_mutex);
28499+
28500+ if (!err) {
28501+ h_tmp.dentry = wh_dentry;
28502+ h_tmp.mnt = br->br_mnt;
28503+ err = vfsub_rmdir(h_dir, &h_tmp);
1facf9fc 28504+ }
28505+
28506+ if (!err) {
28507+ if (au_ibstart(dir) == bindex) {
7f207e10 28508+ /* todo: dir->i_mutex is necessary */
1facf9fc 28509+ au_cpup_attr_timesizes(dir);
7f207e10 28510+ vfsub_drop_nlink(dir);
1facf9fc 28511+ }
28512+ return 0; /* success */
28513+ }
28514+
0c3ec466
AM
28515+ pr_warn("failed removing %.*s(%d), ignored\n",
28516+ AuDLNPair(wh_dentry), err);
1facf9fc 28517+ return err;
28518+}
28519+
28520+static void call_rmdir_whtmp(void *args)
28521+{
28522+ int err;
e49829fe 28523+ aufs_bindex_t bindex;
1facf9fc 28524+ struct au_whtmp_rmdir *a = args;
28525+ struct super_block *sb;
28526+ struct dentry *h_parent;
28527+ struct inode *h_dir;
1facf9fc 28528+ struct au_hinode *hdir;
28529+
28530+ /* rmdir by nfsd may cause deadlock with this i_mutex */
28531+ /* mutex_lock(&a->dir->i_mutex); */
e49829fe 28532+ err = -EROFS;
1facf9fc 28533+ sb = a->dir->i_sb;
e49829fe
JR
28534+ si_read_lock(sb, !AuLock_FLUSH);
28535+ if (!au_br_writable(a->br->br_perm))
28536+ goto out;
28537+ bindex = au_br_index(sb, a->br->br_id);
28538+ if (unlikely(bindex < 0))
1facf9fc 28539+ goto out;
28540+
28541+ err = -EIO;
1facf9fc 28542+ ii_write_lock_parent(a->dir);
28543+ h_parent = dget_parent(a->wh_dentry);
28544+ h_dir = h_parent->d_inode;
e49829fe 28545+ hdir = au_hi(a->dir, bindex);
4a4d8108 28546+ au_hn_imtx_lock_nested(hdir, AuLsc_I_PARENT);
e49829fe
JR
28547+ err = au_h_verify(a->wh_dentry, au_opt_udba(sb), h_dir, h_parent,
28548+ a->br);
1facf9fc 28549+ if (!err) {
b4510431 28550+ err = vfsub_mnt_want_write(a->br->br_mnt);
1facf9fc 28551+ if (!err) {
e49829fe 28552+ err = au_whtmp_rmdir(a->dir, bindex, a->wh_dentry,
dece6358 28553+ &a->whlist);
b4510431 28554+ vfsub_mnt_drop_write(a->br->br_mnt);
1facf9fc 28555+ }
28556+ }
4a4d8108 28557+ au_hn_imtx_unlock(hdir);
1facf9fc 28558+ dput(h_parent);
28559+ ii_write_unlock(a->dir);
28560+
4f0767ce 28561+out:
1facf9fc 28562+ /* mutex_unlock(&a->dir->i_mutex); */
1facf9fc 28563+ au_whtmp_rmdir_free(a);
027c5e7a
AM
28564+ si_read_unlock(sb);
28565+ au_nwt_done(&au_sbi(sb)->si_nowait);
1facf9fc 28566+ if (unlikely(err))
28567+ AuIOErr("err %d\n", err);
28568+}
28569+
28570+void au_whtmp_kick_rmdir(struct inode *dir, aufs_bindex_t bindex,
28571+ struct dentry *wh_dentry, struct au_whtmp_rmdir *args)
28572+{
28573+ int wkq_err;
e49829fe 28574+ struct super_block *sb;
1facf9fc 28575+
28576+ IMustLock(dir);
28577+
28578+ /* all post-process will be done in do_rmdir_whtmp(). */
e49829fe 28579+ sb = dir->i_sb;
1facf9fc 28580+ args->dir = au_igrab(dir);
e49829fe
JR
28581+ args->br = au_sbr(sb, bindex);
28582+ atomic_inc(&args->br->br_count);
1facf9fc 28583+ args->wh_dentry = dget(wh_dentry);
53392da6 28584+ wkq_err = au_wkq_nowait(call_rmdir_whtmp, args, sb, /*flags*/0);
1facf9fc 28585+ if (unlikely(wkq_err)) {
0c3ec466
AM
28586+ pr_warn("rmdir error %.*s (%d), ignored\n",
28587+ AuDLNPair(wh_dentry), wkq_err);
1facf9fc 28588+ au_whtmp_rmdir_free(args);
28589+ }
28590+}
7f207e10
AM
28591diff -urN /usr/share/empty/fs/aufs/whout.h linux/fs/aufs/whout.h
28592--- /usr/share/empty/fs/aufs/whout.h 1970-01-01 01:00:00.000000000 +0100
2dfbb274 28593+++ linux/fs/aufs/whout.h 2012-08-26 08:39:00.763841498 +0200
f6c5ef8b 28594@@ -0,0 +1,88 @@
1facf9fc 28595+/*
f6c5ef8b 28596+ * Copyright (C) 2005-2012 Junjiro R. Okajima
1facf9fc 28597+ *
28598+ * This program, aufs is free software; you can redistribute it and/or modify
28599+ * it under the terms of the GNU General Public License as published by
28600+ * the Free Software Foundation; either version 2 of the License, or
28601+ * (at your option) any later version.
dece6358
AM
28602+ *
28603+ * This program is distributed in the hope that it will be useful,
28604+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
28605+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
28606+ * GNU General Public License for more details.
28607+ *
28608+ * You should have received a copy of the GNU General Public License
28609+ * along with this program; if not, write to the Free Software
28610+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 28611+ */
28612+
28613+/*
28614+ * whiteout for logical deletion and opaque directory
28615+ */
28616+
28617+#ifndef __AUFS_WHOUT_H__
28618+#define __AUFS_WHOUT_H__
28619+
28620+#ifdef __KERNEL__
28621+
1facf9fc 28622+#include "dir.h"
28623+
28624+/* whout.c */
28625+int au_wh_name_alloc(struct qstr *wh, const struct qstr *name);
28626+struct au_branch;
28627+int au_wh_test(struct dentry *h_parent, struct qstr *wh_name,
28628+ struct au_branch *br, int try_sio);
28629+int au_diropq_test(struct dentry *h_dentry, struct au_branch *br);
28630+struct dentry *au_whtmp_lkup(struct dentry *h_parent, struct au_branch *br,
28631+ struct qstr *prefix);
28632+int au_whtmp_ren(struct dentry *h_dentry, struct au_branch *br);
28633+int au_wh_unlink_dentry(struct inode *h_dir, struct path *h_path,
28634+ struct dentry *dentry);
28635+int au_wh_init(struct dentry *h_parent, struct au_branch *br,
28636+ struct super_block *sb);
28637+
28638+/* diropq flags */
28639+#define AuDiropq_CREATE 1
28640+#define au_ftest_diropq(flags, name) ((flags) & AuDiropq_##name)
7f207e10
AM
28641+#define au_fset_diropq(flags, name) \
28642+ do { (flags) |= AuDiropq_##name; } while (0)
28643+#define au_fclr_diropq(flags, name) \
28644+ do { (flags) &= ~AuDiropq_##name; } while (0)
1facf9fc 28645+
28646+struct dentry *au_diropq_sio(struct dentry *dentry, aufs_bindex_t bindex,
28647+ unsigned int flags);
28648+struct dentry *au_wh_lkup(struct dentry *h_parent, struct qstr *base_name,
28649+ struct au_branch *br);
28650+struct dentry *au_wh_create(struct dentry *dentry, aufs_bindex_t bindex,
28651+ struct dentry *h_parent);
28652+
28653+/* real rmdir for the whiteout-ed dir */
28654+struct au_whtmp_rmdir {
28655+ struct inode *dir;
e49829fe 28656+ struct au_branch *br;
1facf9fc 28657+ struct dentry *wh_dentry;
dece6358 28658+ struct au_nhash whlist;
1facf9fc 28659+};
28660+
28661+struct au_whtmp_rmdir *au_whtmp_rmdir_alloc(struct super_block *sb, gfp_t gfp);
28662+void au_whtmp_rmdir_free(struct au_whtmp_rmdir *whtmp);
28663+int au_whtmp_rmdir(struct inode *dir, aufs_bindex_t bindex,
28664+ struct dentry *wh_dentry, struct au_nhash *whlist);
28665+void au_whtmp_kick_rmdir(struct inode *dir, aufs_bindex_t bindex,
28666+ struct dentry *wh_dentry, struct au_whtmp_rmdir *args);
28667+
28668+/* ---------------------------------------------------------------------- */
28669+
28670+static inline struct dentry *au_diropq_create(struct dentry *dentry,
28671+ aufs_bindex_t bindex)
28672+{
28673+ return au_diropq_sio(dentry, bindex, AuDiropq_CREATE);
28674+}
28675+
28676+static inline int au_diropq_remove(struct dentry *dentry, aufs_bindex_t bindex)
28677+{
28678+ return PTR_ERR(au_diropq_sio(dentry, bindex, !AuDiropq_CREATE));
28679+}
28680+
28681+#endif /* __KERNEL__ */
28682+#endif /* __AUFS_WHOUT_H__ */
7f207e10
AM
28683diff -urN /usr/share/empty/fs/aufs/wkq.c linux/fs/aufs/wkq.c
28684--- /usr/share/empty/fs/aufs/wkq.c 1970-01-01 01:00:00.000000000 +0100
2dfbb274 28685+++ linux/fs/aufs/wkq.c 2012-08-26 08:39:00.763841498 +0200
9dbd164d 28686@@ -0,0 +1,214 @@
1facf9fc 28687+/*
f6c5ef8b 28688+ * Copyright (C) 2005-2012 Junjiro R. Okajima
1facf9fc 28689+ *
28690+ * This program, aufs is free software; you can redistribute it and/or modify
28691+ * it under the terms of the GNU General Public License as published by
28692+ * the Free Software Foundation; either version 2 of the License, or
28693+ * (at your option) any later version.
dece6358
AM
28694+ *
28695+ * This program is distributed in the hope that it will be useful,
28696+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
28697+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
28698+ * GNU General Public License for more details.
28699+ *
28700+ * You should have received a copy of the GNU General Public License
28701+ * along with this program; if not, write to the Free Software
28702+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 28703+ */
28704+
28705+/*
28706+ * workqueue for asynchronous/super-io operations
28707+ * todo: try new dredential scheme
28708+ */
28709+
dece6358 28710+#include <linux/module.h>
1facf9fc 28711+#include "aufs.h"
28712+
9dbd164d 28713+/* internal workqueue named AUFS_WKQ_NAME */
b752ccd1 28714+
9dbd164d 28715+static struct workqueue_struct *au_wkq;
1facf9fc 28716+
28717+struct au_wkinfo {
28718+ struct work_struct wk;
7f207e10 28719+ struct kobject *kobj;
1facf9fc 28720+
28721+ unsigned int flags; /* see wkq.h */
28722+
28723+ au_wkq_func_t func;
28724+ void *args;
28725+
1facf9fc 28726+ struct completion *comp;
28727+};
28728+
28729+/* ---------------------------------------------------------------------- */
28730+
1facf9fc 28731+static void wkq_func(struct work_struct *wk)
28732+{
28733+ struct au_wkinfo *wkinfo = container_of(wk, struct au_wkinfo, wk);
28734+
2dfbb274 28735+ AuDebugOn(!uid_eq(current_fsuid(), GLOBAL_ROOT_UID));
7f207e10
AM
28736+ AuDebugOn(rlimit(RLIMIT_FSIZE) != RLIM_INFINITY);
28737+
1facf9fc 28738+ wkinfo->func(wkinfo->args);
1facf9fc 28739+ if (au_ftest_wkq(wkinfo->flags, WAIT))
28740+ complete(wkinfo->comp);
28741+ else {
7f207e10 28742+ kobject_put(wkinfo->kobj);
9dbd164d 28743+ module_put(THIS_MODULE); /* todo: ?? */
1facf9fc 28744+ kfree(wkinfo);
28745+ }
28746+}
28747+
28748+/*
28749+ * Since struct completion is large, try allocating it dynamically.
28750+ */
28751+#if defined(CONFIG_4KSTACKS) || defined(AuTest4KSTACKS)
28752+#define AuWkqCompDeclare(name) struct completion *comp = NULL
28753+
28754+static int au_wkq_comp_alloc(struct au_wkinfo *wkinfo, struct completion **comp)
28755+{
28756+ *comp = kmalloc(sizeof(**comp), GFP_NOFS);
28757+ if (*comp) {
28758+ init_completion(*comp);
28759+ wkinfo->comp = *comp;
28760+ return 0;
28761+ }
28762+ return -ENOMEM;
28763+}
28764+
28765+static void au_wkq_comp_free(struct completion *comp)
28766+{
28767+ kfree(comp);
28768+}
28769+
28770+#else
28771+
28772+/* no braces */
28773+#define AuWkqCompDeclare(name) \
28774+ DECLARE_COMPLETION_ONSTACK(_ ## name); \
28775+ struct completion *comp = &_ ## name
28776+
28777+static int au_wkq_comp_alloc(struct au_wkinfo *wkinfo, struct completion **comp)
28778+{
28779+ wkinfo->comp = *comp;
28780+ return 0;
28781+}
28782+
28783+static void au_wkq_comp_free(struct completion *comp __maybe_unused)
28784+{
28785+ /* empty */
28786+}
28787+#endif /* 4KSTACKS */
28788+
53392da6 28789+static void au_wkq_run(struct au_wkinfo *wkinfo)
1facf9fc 28790+{
53392da6
AM
28791+ if (au_ftest_wkq(wkinfo->flags, NEST)) {
28792+ if (au_wkq_test()) {
28793+ AuWarn1("wkq from wkq, due to a dead dir by UDBA?\n");
28794+ AuDebugOn(au_ftest_wkq(wkinfo->flags, WAIT));
28795+ }
28796+ } else
28797+ au_dbg_verify_kthread();
28798+
28799+ if (au_ftest_wkq(wkinfo->flags, WAIT)) {
a1f66529 28800+ INIT_WORK_ONSTACK(&wkinfo->wk, wkq_func);
9dbd164d 28801+ queue_work(au_wkq, &wkinfo->wk);
4a4d8108
AM
28802+ } else {
28803+ INIT_WORK(&wkinfo->wk, wkq_func);
28804+ schedule_work(&wkinfo->wk);
28805+ }
1facf9fc 28806+}
28807+
7f207e10
AM
28808+/*
28809+ * Be careful. It is easy to make deadlock happen.
28810+ * processA: lock, wkq and wait
28811+ * processB: wkq and wait, lock in wkq
28812+ * --> deadlock
28813+ */
b752ccd1 28814+int au_wkq_do_wait(unsigned int flags, au_wkq_func_t func, void *args)
1facf9fc 28815+{
28816+ int err;
28817+ AuWkqCompDeclare(comp);
28818+ struct au_wkinfo wkinfo = {
b752ccd1 28819+ .flags = flags,
1facf9fc 28820+ .func = func,
28821+ .args = args
28822+ };
28823+
28824+ err = au_wkq_comp_alloc(&wkinfo, &comp);
28825+ if (!err) {
53392da6 28826+ au_wkq_run(&wkinfo);
1facf9fc 28827+ /* no timeout, no interrupt */
28828+ wait_for_completion(wkinfo.comp);
28829+ au_wkq_comp_free(comp);
4a4d8108 28830+ destroy_work_on_stack(&wkinfo.wk);
1facf9fc 28831+ }
28832+
28833+ return err;
28834+
28835+}
28836+
027c5e7a
AM
28837+/*
28838+ * Note: dget/dput() in func for aufs dentries are not supported. It will be a
28839+ * problem in a concurrent umounting.
28840+ */
53392da6
AM
28841+int au_wkq_nowait(au_wkq_func_t func, void *args, struct super_block *sb,
28842+ unsigned int flags)
1facf9fc 28843+{
28844+ int err;
28845+ struct au_wkinfo *wkinfo;
28846+
28847+ atomic_inc(&au_sbi(sb)->si_nowait.nw_len);
28848+
28849+ /*
28850+ * wkq_func() must free this wkinfo.
28851+ * it highly depends upon the implementation of workqueue.
28852+ */
28853+ err = 0;
28854+ wkinfo = kmalloc(sizeof(*wkinfo), GFP_NOFS);
28855+ if (wkinfo) {
7f207e10 28856+ wkinfo->kobj = &au_sbi(sb)->si_kobj;
53392da6 28857+ wkinfo->flags = flags & ~AuWkq_WAIT;
1facf9fc 28858+ wkinfo->func = func;
28859+ wkinfo->args = args;
28860+ wkinfo->comp = NULL;
7f207e10 28861+ kobject_get(wkinfo->kobj);
9dbd164d 28862+ __module_get(THIS_MODULE); /* todo: ?? */
1facf9fc 28863+
53392da6 28864+ au_wkq_run(wkinfo);
1facf9fc 28865+ } else {
28866+ err = -ENOMEM;
e49829fe 28867+ au_nwt_done(&au_sbi(sb)->si_nowait);
1facf9fc 28868+ }
28869+
28870+ return err;
28871+}
28872+
28873+/* ---------------------------------------------------------------------- */
28874+
28875+void au_nwt_init(struct au_nowait_tasks *nwt)
28876+{
28877+ atomic_set(&nwt->nw_len, 0);
4a4d8108 28878+ /* smp_mb(); */ /* atomic_set */
1facf9fc 28879+ init_waitqueue_head(&nwt->nw_wq);
28880+}
28881+
28882+void au_wkq_fin(void)
28883+{
9dbd164d 28884+ destroy_workqueue(au_wkq);
1facf9fc 28885+}
28886+
28887+int __init au_wkq_init(void)
28888+{
9dbd164d 28889+ int err;
b752ccd1
AM
28890+
28891+ err = 0;
9dbd164d
AM
28892+ BUILD_BUG_ON(!WQ_RESCUER);
28893+ au_wkq = alloc_workqueue(AUFS_WKQ_NAME, !WQ_RESCUER, WQ_DFL_ACTIVE);
28894+ if (IS_ERR(au_wkq))
28895+ err = PTR_ERR(au_wkq);
28896+ else if (!au_wkq)
28897+ err = -ENOMEM;
b752ccd1
AM
28898+
28899+ return err;
1facf9fc 28900+}
7f207e10
AM
28901diff -urN /usr/share/empty/fs/aufs/wkq.h linux/fs/aufs/wkq.h
28902--- /usr/share/empty/fs/aufs/wkq.h 1970-01-01 01:00:00.000000000 +0100
2dfbb274 28903+++ linux/fs/aufs/wkq.h 2012-08-26 08:39:00.763841498 +0200
f6c5ef8b 28904@@ -0,0 +1,92 @@
1facf9fc 28905+/*
f6c5ef8b 28906+ * Copyright (C) 2005-2012 Junjiro R. Okajima
1facf9fc 28907+ *
28908+ * This program, aufs is free software; you can redistribute it and/or modify
28909+ * it under the terms of the GNU General Public License as published by
28910+ * the Free Software Foundation; either version 2 of the License, or
28911+ * (at your option) any later version.
dece6358
AM
28912+ *
28913+ * This program is distributed in the hope that it will be useful,
28914+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
28915+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
28916+ * GNU General Public License for more details.
28917+ *
28918+ * You should have received a copy of the GNU General Public License
28919+ * along with this program; if not, write to the Free Software
28920+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 28921+ */
28922+
28923+/*
28924+ * workqueue for asynchronous/super-io operations
28925+ * todo: try new credentials management scheme
28926+ */
28927+
28928+#ifndef __AUFS_WKQ_H__
28929+#define __AUFS_WKQ_H__
28930+
28931+#ifdef __KERNEL__
28932+
dece6358
AM
28933+struct super_block;
28934+
1facf9fc 28935+/* ---------------------------------------------------------------------- */
28936+
28937+/*
28938+ * in the next operation, wait for the 'nowait' tasks in system-wide workqueue
28939+ */
28940+struct au_nowait_tasks {
28941+ atomic_t nw_len;
28942+ wait_queue_head_t nw_wq;
28943+};
28944+
28945+/* ---------------------------------------------------------------------- */
28946+
28947+typedef void (*au_wkq_func_t)(void *args);
28948+
28949+/* wkq flags */
28950+#define AuWkq_WAIT 1
9dbd164d 28951+#define AuWkq_NEST (1 << 1)
1facf9fc 28952+#define au_ftest_wkq(flags, name) ((flags) & AuWkq_##name)
7f207e10
AM
28953+#define au_fset_wkq(flags, name) \
28954+ do { (flags) |= AuWkq_##name; } while (0)
28955+#define au_fclr_wkq(flags, name) \
28956+ do { (flags) &= ~AuWkq_##name; } while (0)
1facf9fc 28957+
9dbd164d
AM
28958+#ifndef CONFIG_AUFS_HNOTIFY
28959+#undef AuWkq_NEST
28960+#define AuWkq_NEST 0
28961+#endif
28962+
1facf9fc 28963+/* wkq.c */
b752ccd1 28964+int au_wkq_do_wait(unsigned int flags, au_wkq_func_t func, void *args);
53392da6
AM
28965+int au_wkq_nowait(au_wkq_func_t func, void *args, struct super_block *sb,
28966+ unsigned int flags);
1facf9fc 28967+void au_nwt_init(struct au_nowait_tasks *nwt);
28968+int __init au_wkq_init(void);
28969+void au_wkq_fin(void);
28970+
28971+/* ---------------------------------------------------------------------- */
28972+
53392da6
AM
28973+static inline int au_wkq_test(void)
28974+{
28975+ return current->flags & PF_WQ_WORKER;
28976+}
28977+
b752ccd1 28978+static inline int au_wkq_wait(au_wkq_func_t func, void *args)
1facf9fc 28979+{
b752ccd1 28980+ return au_wkq_do_wait(AuWkq_WAIT, func, args);
1facf9fc 28981+}
28982+
28983+static inline void au_nwt_done(struct au_nowait_tasks *nwt)
28984+{
e49829fe 28985+ if (atomic_dec_and_test(&nwt->nw_len))
1facf9fc 28986+ wake_up_all(&nwt->nw_wq);
28987+}
28988+
28989+static inline int au_nwt_flush(struct au_nowait_tasks *nwt)
28990+{
28991+ wait_event(nwt->nw_wq, !atomic_read(&nwt->nw_len));
28992+ return 0;
28993+}
28994+
28995+#endif /* __KERNEL__ */
28996+#endif /* __AUFS_WKQ_H__ */
7f207e10
AM
28997diff -urN /usr/share/empty/fs/aufs/xino.c linux/fs/aufs/xino.c
28998--- /usr/share/empty/fs/aufs/xino.c 1970-01-01 01:00:00.000000000 +0100
2dfbb274 28999+++ linux/fs/aufs/xino.c 2012-08-26 08:39:00.763841498 +0200
f6c5ef8b 29000@@ -0,0 +1,1264 @@
1facf9fc 29001+/*
f6c5ef8b 29002+ * Copyright (C) 2005-2012 Junjiro R. Okajima
1facf9fc 29003+ *
29004+ * This program, aufs is free software; you can redistribute it and/or modify
29005+ * it under the terms of the GNU General Public License as published by
29006+ * the Free Software Foundation; either version 2 of the License, or
29007+ * (at your option) any later version.
dece6358
AM
29008+ *
29009+ * This program is distributed in the hope that it will be useful,
29010+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
29011+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
29012+ * GNU General Public License for more details.
29013+ *
29014+ * You should have received a copy of the GNU General Public License
29015+ * along with this program; if not, write to the Free Software
29016+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 29017+ */
29018+
29019+/*
29020+ * external inode number translation table and bitmap
29021+ */
29022+
29023+#include <linux/seq_file.h>
1facf9fc 29024+#include "aufs.h"
29025+
9dbd164d 29026+/* todo: unnecessary to support mmap_sem since kernel-space? */
b752ccd1 29027+ssize_t xino_fread(au_readf_t func, struct file *file, void *kbuf, size_t size,
1facf9fc 29028+ loff_t *pos)
29029+{
29030+ ssize_t err;
29031+ mm_segment_t oldfs;
b752ccd1
AM
29032+ union {
29033+ void *k;
29034+ char __user *u;
29035+ } buf;
1facf9fc 29036+
b752ccd1 29037+ buf.k = kbuf;
1facf9fc 29038+ oldfs = get_fs();
29039+ set_fs(KERNEL_DS);
29040+ do {
29041+ /* todo: signal_pending? */
b752ccd1 29042+ err = func(file, buf.u, size, pos);
1facf9fc 29043+ } while (err == -EAGAIN || err == -EINTR);
29044+ set_fs(oldfs);
29045+
29046+#if 0 /* reserved for future use */
29047+ if (err > 0)
29048+ fsnotify_access(file->f_dentry);
29049+#endif
29050+
29051+ return err;
29052+}
29053+
29054+/* ---------------------------------------------------------------------- */
29055+
b752ccd1 29056+static ssize_t do_xino_fwrite(au_writef_t func, struct file *file, void *kbuf,
1facf9fc 29057+ size_t size, loff_t *pos)
29058+{
29059+ ssize_t err;
29060+ mm_segment_t oldfs;
b752ccd1
AM
29061+ union {
29062+ void *k;
29063+ const char __user *u;
29064+ } buf;
1facf9fc 29065+
b752ccd1 29066+ buf.k = kbuf;
1facf9fc 29067+ oldfs = get_fs();
29068+ set_fs(KERNEL_DS);
1facf9fc 29069+ do {
29070+ /* todo: signal_pending? */
b752ccd1 29071+ err = func(file, buf.u, size, pos);
1facf9fc 29072+ } while (err == -EAGAIN || err == -EINTR);
1facf9fc 29073+ set_fs(oldfs);
29074+
29075+#if 0 /* reserved for future use */
29076+ if (err > 0)
29077+ fsnotify_modify(file->f_dentry);
29078+#endif
29079+
29080+ return err;
29081+}
29082+
29083+struct do_xino_fwrite_args {
29084+ ssize_t *errp;
29085+ au_writef_t func;
29086+ struct file *file;
29087+ void *buf;
29088+ size_t size;
29089+ loff_t *pos;
29090+};
29091+
29092+static void call_do_xino_fwrite(void *args)
29093+{
29094+ struct do_xino_fwrite_args *a = args;
29095+ *a->errp = do_xino_fwrite(a->func, a->file, a->buf, a->size, a->pos);
29096+}
29097+
29098+ssize_t xino_fwrite(au_writef_t func, struct file *file, void *buf, size_t size,
29099+ loff_t *pos)
29100+{
29101+ ssize_t err;
29102+
29103+ /* todo: signal block and no wkq? */
b752ccd1
AM
29104+ if (rlimit(RLIMIT_FSIZE) == RLIM_INFINITY) {
29105+ lockdep_off();
29106+ err = do_xino_fwrite(func, file, buf, size, pos);
29107+ lockdep_on();
29108+ } else {
29109+ /*
29110+ * it breaks RLIMIT_FSIZE and normal user's limit,
29111+ * users should care about quota and real 'filesystem full.'
29112+ */
1facf9fc 29113+ int wkq_err;
29114+ struct do_xino_fwrite_args args = {
29115+ .errp = &err,
29116+ .func = func,
29117+ .file = file,
29118+ .buf = buf,
29119+ .size = size,
29120+ .pos = pos
29121+ };
29122+
29123+ wkq_err = au_wkq_wait(call_do_xino_fwrite, &args);
29124+ if (unlikely(wkq_err))
29125+ err = wkq_err;
b752ccd1 29126+ }
1facf9fc 29127+
29128+ return err;
29129+}
29130+
29131+/* ---------------------------------------------------------------------- */
29132+
29133+/*
29134+ * create a new xinofile at the same place/path as @base_file.
29135+ */
29136+struct file *au_xino_create2(struct file *base_file, struct file *copy_src)
29137+{
29138+ struct file *file;
4a4d8108 29139+ struct dentry *base, *parent;
1facf9fc 29140+ struct inode *dir;
29141+ struct qstr *name;
1308ab2a 29142+ struct path path;
4a4d8108 29143+ int err;
1facf9fc 29144+
29145+ base = base_file->f_dentry;
29146+ parent = base->d_parent; /* dir inode is locked */
29147+ dir = parent->d_inode;
29148+ IMustLock(dir);
29149+
29150+ file = ERR_PTR(-EINVAL);
29151+ name = &base->d_name;
4a4d8108
AM
29152+ path.dentry = vfsub_lookup_one_len(name->name, parent, name->len);
29153+ if (IS_ERR(path.dentry)) {
29154+ file = (void *)path.dentry;
29155+ pr_err("%.*s lookup err %ld\n",
29156+ AuLNPair(name), PTR_ERR(path.dentry));
1facf9fc 29157+ goto out;
29158+ }
29159+
29160+ /* no need to mnt_want_write() since we call dentry_open() later */
4a4d8108 29161+ err = vfs_create(dir, path.dentry, S_IRUGO | S_IWUGO, NULL);
1facf9fc 29162+ if (unlikely(err)) {
29163+ file = ERR_PTR(err);
4a4d8108 29164+ pr_err("%.*s create err %d\n", AuLNPair(name), err);
1facf9fc 29165+ goto out_dput;
29166+ }
29167+
1308ab2a 29168+ path.mnt = base_file->f_vfsmnt;
4a4d8108 29169+ file = vfsub_dentry_open(&path,
7f207e10 29170+ O_RDWR | O_CREAT | O_EXCL | O_LARGEFILE
2cbb1c4b 29171+ /* | __FMODE_NONOTIFY */);
1facf9fc 29172+ if (IS_ERR(file)) {
4a4d8108 29173+ pr_err("%.*s open err %ld\n", AuLNPair(name), PTR_ERR(file));
1facf9fc 29174+ goto out_dput;
29175+ }
29176+
29177+ err = vfsub_unlink(dir, &file->f_path, /*force*/0);
29178+ if (unlikely(err)) {
4a4d8108 29179+ pr_err("%.*s unlink err %d\n", AuLNPair(name), err);
1facf9fc 29180+ goto out_fput;
29181+ }
29182+
29183+ if (copy_src) {
29184+ /* no one can touch copy_src xino */
29185+ err = au_copy_file(file, copy_src,
29186+ i_size_read(copy_src->f_dentry->d_inode));
29187+ if (unlikely(err)) {
4a4d8108 29188+ pr_err("%.*s copy err %d\n", AuLNPair(name), err);
1facf9fc 29189+ goto out_fput;
29190+ }
29191+ }
29192+ goto out_dput; /* success */
29193+
4f0767ce 29194+out_fput:
1facf9fc 29195+ fput(file);
29196+ file = ERR_PTR(err);
4f0767ce 29197+out_dput:
4a4d8108 29198+ dput(path.dentry);
4f0767ce 29199+out:
1facf9fc 29200+ return file;
29201+}
29202+
29203+struct au_xino_lock_dir {
29204+ struct au_hinode *hdir;
29205+ struct dentry *parent;
29206+ struct mutex *mtx;
29207+};
29208+
29209+static void au_xino_lock_dir(struct super_block *sb, struct file *xino,
29210+ struct au_xino_lock_dir *ldir)
29211+{
29212+ aufs_bindex_t brid, bindex;
29213+
29214+ ldir->hdir = NULL;
29215+ bindex = -1;
29216+ brid = au_xino_brid(sb);
29217+ if (brid >= 0)
29218+ bindex = au_br_index(sb, brid);
29219+ if (bindex >= 0) {
29220+ ldir->hdir = au_hi(sb->s_root->d_inode, bindex);
4a4d8108 29221+ au_hn_imtx_lock_nested(ldir->hdir, AuLsc_I_PARENT);
1facf9fc 29222+ } else {
29223+ ldir->parent = dget_parent(xino->f_dentry);
29224+ ldir->mtx = &ldir->parent->d_inode->i_mutex;
29225+ mutex_lock_nested(ldir->mtx, AuLsc_I_PARENT);
29226+ }
29227+}
29228+
29229+static void au_xino_unlock_dir(struct au_xino_lock_dir *ldir)
29230+{
29231+ if (ldir->hdir)
4a4d8108 29232+ au_hn_imtx_unlock(ldir->hdir);
1facf9fc 29233+ else {
29234+ mutex_unlock(ldir->mtx);
29235+ dput(ldir->parent);
29236+ }
29237+}
29238+
29239+/* ---------------------------------------------------------------------- */
29240+
29241+/* trucate xino files asynchronously */
29242+
29243+int au_xino_trunc(struct super_block *sb, aufs_bindex_t bindex)
29244+{
29245+ int err;
29246+ aufs_bindex_t bi, bend;
29247+ struct au_branch *br;
29248+ struct file *new_xino, *file;
29249+ struct super_block *h_sb;
29250+ struct au_xino_lock_dir ldir;
29251+
29252+ err = -EINVAL;
29253+ bend = au_sbend(sb);
29254+ if (unlikely(bindex < 0 || bend < bindex))
29255+ goto out;
29256+ br = au_sbr(sb, bindex);
29257+ file = br->br_xino.xi_file;
29258+ if (!file)
29259+ goto out;
29260+
29261+ au_xino_lock_dir(sb, file, &ldir);
29262+ /* mnt_want_write() is unnecessary here */
29263+ new_xino = au_xino_create2(file, file);
29264+ au_xino_unlock_dir(&ldir);
29265+ err = PTR_ERR(new_xino);
29266+ if (IS_ERR(new_xino))
29267+ goto out;
29268+ err = 0;
29269+ fput(file);
29270+ br->br_xino.xi_file = new_xino;
29271+
29272+ h_sb = br->br_mnt->mnt_sb;
29273+ for (bi = 0; bi <= bend; bi++) {
29274+ if (unlikely(bi == bindex))
29275+ continue;
29276+ br = au_sbr(sb, bi);
29277+ if (br->br_mnt->mnt_sb != h_sb)
29278+ continue;
29279+
29280+ fput(br->br_xino.xi_file);
29281+ br->br_xino.xi_file = new_xino;
29282+ get_file(new_xino);
29283+ }
29284+
4f0767ce 29285+out:
1facf9fc 29286+ return err;
29287+}
29288+
29289+struct xino_do_trunc_args {
29290+ struct super_block *sb;
29291+ struct au_branch *br;
29292+};
29293+
29294+static void xino_do_trunc(void *_args)
29295+{
29296+ struct xino_do_trunc_args *args = _args;
29297+ struct super_block *sb;
29298+ struct au_branch *br;
29299+ struct inode *dir;
29300+ int err;
29301+ aufs_bindex_t bindex;
29302+
29303+ err = 0;
29304+ sb = args->sb;
29305+ dir = sb->s_root->d_inode;
29306+ br = args->br;
29307+
29308+ si_noflush_write_lock(sb);
29309+ ii_read_lock_parent(dir);
29310+ bindex = au_br_index(sb, br->br_id);
29311+ err = au_xino_trunc(sb, bindex);
dece6358
AM
29312+ if (!err
29313+ && br->br_xino.xi_file->f_dentry->d_inode->i_blocks
1facf9fc 29314+ >= br->br_xino_upper)
29315+ br->br_xino_upper += AUFS_XINO_TRUNC_STEP;
29316+
1facf9fc 29317+ ii_read_unlock(dir);
29318+ if (unlikely(err))
0c3ec466 29319+ pr_warn("err b%d, (%d)\n", bindex, err);
1facf9fc 29320+ atomic_dec(&br->br_xino_running);
29321+ atomic_dec(&br->br_count);
1facf9fc 29322+ si_write_unlock(sb);
027c5e7a 29323+ au_nwt_done(&au_sbi(sb)->si_nowait);
1facf9fc 29324+ kfree(args);
29325+}
29326+
29327+static void xino_try_trunc(struct super_block *sb, struct au_branch *br)
29328+{
29329+ struct xino_do_trunc_args *args;
29330+ int wkq_err;
29331+
29332+ if (br->br_xino.xi_file->f_dentry->d_inode->i_blocks
29333+ < br->br_xino_upper)
29334+ return;
29335+
29336+ if (atomic_inc_return(&br->br_xino_running) > 1)
29337+ goto out;
29338+
29339+ /* lock and kfree() will be called in trunc_xino() */
29340+ args = kmalloc(sizeof(*args), GFP_NOFS);
29341+ if (unlikely(!args)) {
29342+ AuErr1("no memory\n");
29343+ goto out_args;
29344+ }
29345+
e49829fe 29346+ atomic_inc(&br->br_count);
1facf9fc 29347+ args->sb = sb;
29348+ args->br = br;
53392da6 29349+ wkq_err = au_wkq_nowait(xino_do_trunc, args, sb, /*flags*/0);
1facf9fc 29350+ if (!wkq_err)
29351+ return; /* success */
29352+
4a4d8108 29353+ pr_err("wkq %d\n", wkq_err);
e49829fe 29354+ atomic_dec(&br->br_count);
1facf9fc 29355+
4f0767ce 29356+out_args:
1facf9fc 29357+ kfree(args);
4f0767ce 29358+out:
e49829fe 29359+ atomic_dec(&br->br_xino_running);
1facf9fc 29360+}
29361+
29362+/* ---------------------------------------------------------------------- */
29363+
29364+static int au_xino_do_write(au_writef_t write, struct file *file,
29365+ ino_t h_ino, ino_t ino)
29366+{
29367+ loff_t pos;
29368+ ssize_t sz;
29369+
29370+ pos = h_ino;
29371+ if (unlikely(au_loff_max / sizeof(ino) - 1 < pos)) {
29372+ AuIOErr1("too large hi%lu\n", (unsigned long)h_ino);
29373+ return -EFBIG;
29374+ }
29375+ pos *= sizeof(ino);
29376+ sz = xino_fwrite(write, file, &ino, sizeof(ino), &pos);
29377+ if (sz == sizeof(ino))
29378+ return 0; /* success */
29379+
29380+ AuIOErr("write failed (%zd)\n", sz);
29381+ return -EIO;
29382+}
29383+
29384+/*
29385+ * write @ino to the xinofile for the specified branch{@sb, @bindex}
29386+ * at the position of @h_ino.
29387+ * even if @ino is zero, it is written to the xinofile and means no entry.
29388+ * if the size of the xino file on a specific filesystem exceeds the watermark,
29389+ * try truncating it.
29390+ */
29391+int au_xino_write(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino,
29392+ ino_t ino)
29393+{
29394+ int err;
29395+ unsigned int mnt_flags;
29396+ struct au_branch *br;
29397+
29398+ BUILD_BUG_ON(sizeof(long long) != sizeof(au_loff_max)
29399+ || ((loff_t)-1) > 0);
dece6358 29400+ SiMustAnyLock(sb);
1facf9fc 29401+
29402+ mnt_flags = au_mntflags(sb);
29403+ if (!au_opt_test(mnt_flags, XINO))
29404+ return 0;
29405+
29406+ br = au_sbr(sb, bindex);
29407+ err = au_xino_do_write(au_sbi(sb)->si_xwrite, br->br_xino.xi_file,
29408+ h_ino, ino);
29409+ if (!err) {
29410+ if (au_opt_test(mnt_flags, TRUNC_XINO)
29411+ && au_test_fs_trunc_xino(br->br_mnt->mnt_sb))
29412+ xino_try_trunc(sb, br);
29413+ return 0; /* success */
29414+ }
29415+
29416+ AuIOErr("write failed (%d)\n", err);
29417+ return -EIO;
29418+}
29419+
29420+/* ---------------------------------------------------------------------- */
29421+
29422+/* aufs inode number bitmap */
29423+
29424+static const int page_bits = (int)PAGE_SIZE * BITS_PER_BYTE;
29425+static ino_t xib_calc_ino(unsigned long pindex, int bit)
29426+{
29427+ ino_t ino;
29428+
29429+ AuDebugOn(bit < 0 || page_bits <= bit);
29430+ ino = AUFS_FIRST_INO + pindex * page_bits + bit;
29431+ return ino;
29432+}
29433+
29434+static void xib_calc_bit(ino_t ino, unsigned long *pindex, int *bit)
29435+{
29436+ AuDebugOn(ino < AUFS_FIRST_INO);
29437+ ino -= AUFS_FIRST_INO;
29438+ *pindex = ino / page_bits;
29439+ *bit = ino % page_bits;
29440+}
29441+
29442+static int xib_pindex(struct super_block *sb, unsigned long pindex)
29443+{
29444+ int err;
29445+ loff_t pos;
29446+ ssize_t sz;
29447+ struct au_sbinfo *sbinfo;
29448+ struct file *xib;
29449+ unsigned long *p;
29450+
29451+ sbinfo = au_sbi(sb);
29452+ MtxMustLock(&sbinfo->si_xib_mtx);
29453+ AuDebugOn(pindex > ULONG_MAX / PAGE_SIZE
29454+ || !au_opt_test(sbinfo->si_mntflags, XINO));
29455+
29456+ if (pindex == sbinfo->si_xib_last_pindex)
29457+ return 0;
29458+
29459+ xib = sbinfo->si_xib;
29460+ p = sbinfo->si_xib_buf;
29461+ pos = sbinfo->si_xib_last_pindex;
29462+ pos *= PAGE_SIZE;
29463+ sz = xino_fwrite(sbinfo->si_xwrite, xib, p, PAGE_SIZE, &pos);
29464+ if (unlikely(sz != PAGE_SIZE))
29465+ goto out;
29466+
29467+ pos = pindex;
29468+ pos *= PAGE_SIZE;
29469+ if (i_size_read(xib->f_dentry->d_inode) >= pos + PAGE_SIZE)
29470+ sz = xino_fread(sbinfo->si_xread, xib, p, PAGE_SIZE, &pos);
29471+ else {
29472+ memset(p, 0, PAGE_SIZE);
29473+ sz = xino_fwrite(sbinfo->si_xwrite, xib, p, PAGE_SIZE, &pos);
29474+ }
29475+ if (sz == PAGE_SIZE) {
29476+ sbinfo->si_xib_last_pindex = pindex;
29477+ return 0; /* success */
29478+ }
29479+
4f0767ce 29480+out:
b752ccd1
AM
29481+ AuIOErr1("write failed (%zd)\n", sz);
29482+ err = sz;
29483+ if (sz >= 0)
29484+ err = -EIO;
29485+ return err;
29486+}
29487+
29488+/* ---------------------------------------------------------------------- */
29489+
29490+static void au_xib_clear_bit(struct inode *inode)
29491+{
29492+ int err, bit;
29493+ unsigned long pindex;
29494+ struct super_block *sb;
29495+ struct au_sbinfo *sbinfo;
29496+
29497+ AuDebugOn(inode->i_nlink);
29498+
29499+ sb = inode->i_sb;
29500+ xib_calc_bit(inode->i_ino, &pindex, &bit);
29501+ AuDebugOn(page_bits <= bit);
29502+ sbinfo = au_sbi(sb);
29503+ mutex_lock(&sbinfo->si_xib_mtx);
29504+ err = xib_pindex(sb, pindex);
29505+ if (!err) {
29506+ clear_bit(bit, sbinfo->si_xib_buf);
29507+ sbinfo->si_xib_next_bit = bit;
29508+ }
29509+ mutex_unlock(&sbinfo->si_xib_mtx);
29510+}
29511+
29512+/* for s_op->delete_inode() */
29513+void au_xino_delete_inode(struct inode *inode, const int unlinked)
29514+{
29515+ int err;
29516+ unsigned int mnt_flags;
29517+ aufs_bindex_t bindex, bend, bi;
29518+ unsigned char try_trunc;
29519+ struct au_iinfo *iinfo;
29520+ struct super_block *sb;
29521+ struct au_hinode *hi;
29522+ struct inode *h_inode;
29523+ struct au_branch *br;
29524+ au_writef_t xwrite;
29525+
29526+ sb = inode->i_sb;
29527+ mnt_flags = au_mntflags(sb);
29528+ if (!au_opt_test(mnt_flags, XINO)
29529+ || inode->i_ino == AUFS_ROOT_INO)
29530+ return;
29531+
29532+ if (unlinked) {
29533+ au_xigen_inc(inode);
29534+ au_xib_clear_bit(inode);
29535+ }
29536+
29537+ iinfo = au_ii(inode);
29538+ if (!iinfo)
29539+ return;
1facf9fc 29540+
b752ccd1
AM
29541+ bindex = iinfo->ii_bstart;
29542+ if (bindex < 0)
29543+ return;
1facf9fc 29544+
b752ccd1
AM
29545+ xwrite = au_sbi(sb)->si_xwrite;
29546+ try_trunc = !!au_opt_test(mnt_flags, TRUNC_XINO);
29547+ hi = iinfo->ii_hinode + bindex;
29548+ bend = iinfo->ii_bend;
29549+ for (; bindex <= bend; bindex++, hi++) {
29550+ h_inode = hi->hi_inode;
29551+ if (!h_inode
29552+ || (!unlinked && h_inode->i_nlink))
29553+ continue;
1facf9fc 29554+
b752ccd1
AM
29555+ /* inode may not be revalidated */
29556+ bi = au_br_index(sb, hi->hi_id);
29557+ if (bi < 0)
29558+ continue;
1facf9fc 29559+
b752ccd1
AM
29560+ br = au_sbr(sb, bi);
29561+ err = au_xino_do_write(xwrite, br->br_xino.xi_file,
29562+ h_inode->i_ino, /*ino*/0);
29563+ if (!err && try_trunc
29564+ && au_test_fs_trunc_xino(br->br_mnt->mnt_sb))
29565+ xino_try_trunc(sb, br);
1facf9fc 29566+ }
1facf9fc 29567+}
29568+
29569+/* get an unused inode number from bitmap */
29570+ino_t au_xino_new_ino(struct super_block *sb)
29571+{
29572+ ino_t ino;
29573+ unsigned long *p, pindex, ul, pend;
29574+ struct au_sbinfo *sbinfo;
29575+ struct file *file;
29576+ int free_bit, err;
29577+
29578+ if (!au_opt_test(au_mntflags(sb), XINO))
29579+ return iunique(sb, AUFS_FIRST_INO);
29580+
29581+ sbinfo = au_sbi(sb);
29582+ mutex_lock(&sbinfo->si_xib_mtx);
29583+ p = sbinfo->si_xib_buf;
29584+ free_bit = sbinfo->si_xib_next_bit;
29585+ if (free_bit < page_bits && !test_bit(free_bit, p))
29586+ goto out; /* success */
29587+ free_bit = find_first_zero_bit(p, page_bits);
29588+ if (free_bit < page_bits)
29589+ goto out; /* success */
29590+
29591+ pindex = sbinfo->si_xib_last_pindex;
29592+ for (ul = pindex - 1; ul < ULONG_MAX; ul--) {
29593+ err = xib_pindex(sb, ul);
29594+ if (unlikely(err))
29595+ goto out_err;
29596+ free_bit = find_first_zero_bit(p, page_bits);
29597+ if (free_bit < page_bits)
29598+ goto out; /* success */
29599+ }
29600+
29601+ file = sbinfo->si_xib;
29602+ pend = i_size_read(file->f_dentry->d_inode) / PAGE_SIZE;
29603+ for (ul = pindex + 1; ul <= pend; ul++) {
29604+ err = xib_pindex(sb, ul);
29605+ if (unlikely(err))
29606+ goto out_err;
29607+ free_bit = find_first_zero_bit(p, page_bits);
29608+ if (free_bit < page_bits)
29609+ goto out; /* success */
29610+ }
29611+ BUG();
29612+
4f0767ce 29613+out:
1facf9fc 29614+ set_bit(free_bit, p);
7f207e10 29615+ sbinfo->si_xib_next_bit = free_bit + 1;
1facf9fc 29616+ pindex = sbinfo->si_xib_last_pindex;
29617+ mutex_unlock(&sbinfo->si_xib_mtx);
29618+ ino = xib_calc_ino(pindex, free_bit);
29619+ AuDbg("i%lu\n", (unsigned long)ino);
29620+ return ino;
4f0767ce 29621+out_err:
1facf9fc 29622+ mutex_unlock(&sbinfo->si_xib_mtx);
29623+ AuDbg("i0\n");
29624+ return 0;
29625+}
29626+
29627+/*
29628+ * read @ino from xinofile for the specified branch{@sb, @bindex}
29629+ * at the position of @h_ino.
29630+ * if @ino does not exist and @do_new is true, get new one.
29631+ */
29632+int au_xino_read(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino,
29633+ ino_t *ino)
29634+{
29635+ int err;
29636+ ssize_t sz;
29637+ loff_t pos;
29638+ struct file *file;
29639+ struct au_sbinfo *sbinfo;
29640+
29641+ *ino = 0;
29642+ if (!au_opt_test(au_mntflags(sb), XINO))
29643+ return 0; /* no xino */
29644+
29645+ err = 0;
29646+ sbinfo = au_sbi(sb);
29647+ pos = h_ino;
29648+ if (unlikely(au_loff_max / sizeof(*ino) - 1 < pos)) {
29649+ AuIOErr1("too large hi%lu\n", (unsigned long)h_ino);
29650+ return -EFBIG;
29651+ }
29652+ pos *= sizeof(*ino);
29653+
29654+ file = au_sbr(sb, bindex)->br_xino.xi_file;
29655+ if (i_size_read(file->f_dentry->d_inode) < pos + sizeof(*ino))
29656+ return 0; /* no ino */
29657+
29658+ sz = xino_fread(sbinfo->si_xread, file, ino, sizeof(*ino), &pos);
29659+ if (sz == sizeof(*ino))
29660+ return 0; /* success */
29661+
29662+ err = sz;
29663+ if (unlikely(sz >= 0)) {
29664+ err = -EIO;
29665+ AuIOErr("xino read error (%zd)\n", sz);
29666+ }
29667+
29668+ return err;
29669+}
29670+
29671+/* ---------------------------------------------------------------------- */
29672+
29673+/* create and set a new xino file */
29674+
29675+struct file *au_xino_create(struct super_block *sb, char *fname, int silent)
29676+{
29677+ struct file *file;
29678+ struct dentry *h_parent, *d;
29679+ struct inode *h_dir;
29680+ int err;
29681+
29682+ /*
29683+ * at mount-time, and the xino file is the default path,
4a4d8108 29684+ * hnotify is disabled so we have no notify events to ignore.
1facf9fc 29685+ * when a user specified the xino, we cannot get au_hdir to be ignored.
29686+ */
7f207e10 29687+ file = vfsub_filp_open(fname, O_RDWR | O_CREAT | O_EXCL | O_LARGEFILE
2cbb1c4b 29688+ /* | __FMODE_NONOTIFY */,
1facf9fc 29689+ S_IRUGO | S_IWUGO);
29690+ if (IS_ERR(file)) {
29691+ if (!silent)
4a4d8108 29692+ pr_err("open %s(%ld)\n", fname, PTR_ERR(file));
1facf9fc 29693+ return file;
29694+ }
29695+
29696+ /* keep file count */
29697+ h_parent = dget_parent(file->f_dentry);
29698+ h_dir = h_parent->d_inode;
29699+ mutex_lock_nested(&h_dir->i_mutex, AuLsc_I_PARENT);
29700+ /* mnt_want_write() is unnecessary here */
29701+ err = vfsub_unlink(h_dir, &file->f_path, /*force*/0);
29702+ mutex_unlock(&h_dir->i_mutex);
29703+ dput(h_parent);
29704+ if (unlikely(err)) {
29705+ if (!silent)
4a4d8108 29706+ pr_err("unlink %s(%d)\n", fname, err);
1facf9fc 29707+ goto out;
29708+ }
29709+
29710+ err = -EINVAL;
29711+ d = file->f_dentry;
29712+ if (unlikely(sb == d->d_sb)) {
29713+ if (!silent)
4a4d8108 29714+ pr_err("%s must be outside\n", fname);
1facf9fc 29715+ goto out;
29716+ }
29717+ if (unlikely(au_test_fs_bad_xino(d->d_sb))) {
29718+ if (!silent)
4a4d8108
AM
29719+ pr_err("xino doesn't support %s(%s)\n",
29720+ fname, au_sbtype(d->d_sb));
1facf9fc 29721+ goto out;
29722+ }
29723+ return file; /* success */
29724+
4f0767ce 29725+out:
1facf9fc 29726+ fput(file);
29727+ file = ERR_PTR(err);
29728+ return file;
29729+}
29730+
29731+/*
29732+ * find another branch who is on the same filesystem of the specified
29733+ * branch{@btgt}. search until @bend.
29734+ */
29735+static int is_sb_shared(struct super_block *sb, aufs_bindex_t btgt,
29736+ aufs_bindex_t bend)
29737+{
29738+ aufs_bindex_t bindex;
29739+ struct super_block *tgt_sb = au_sbr_sb(sb, btgt);
29740+
29741+ for (bindex = 0; bindex < btgt; bindex++)
29742+ if (unlikely(tgt_sb == au_sbr_sb(sb, bindex)))
29743+ return bindex;
29744+ for (bindex++; bindex <= bend; bindex++)
29745+ if (unlikely(tgt_sb == au_sbr_sb(sb, bindex)))
29746+ return bindex;
29747+ return -1;
29748+}
29749+
29750+/* ---------------------------------------------------------------------- */
29751+
29752+/*
29753+ * initialize the xinofile for the specified branch @br
29754+ * at the place/path where @base_file indicates.
29755+ * test whether another branch is on the same filesystem or not,
29756+ * if @do_test is true.
29757+ */
29758+int au_xino_br(struct super_block *sb, struct au_branch *br, ino_t h_ino,
29759+ struct file *base_file, int do_test)
29760+{
29761+ int err;
29762+ ino_t ino;
29763+ aufs_bindex_t bend, bindex;
29764+ struct au_branch *shared_br, *b;
29765+ struct file *file;
29766+ struct super_block *tgt_sb;
29767+
29768+ shared_br = NULL;
29769+ bend = au_sbend(sb);
29770+ if (do_test) {
29771+ tgt_sb = br->br_mnt->mnt_sb;
29772+ for (bindex = 0; bindex <= bend; bindex++) {
29773+ b = au_sbr(sb, bindex);
29774+ if (tgt_sb == b->br_mnt->mnt_sb) {
29775+ shared_br = b;
29776+ break;
29777+ }
29778+ }
29779+ }
29780+
29781+ if (!shared_br || !shared_br->br_xino.xi_file) {
29782+ struct au_xino_lock_dir ldir;
29783+
29784+ au_xino_lock_dir(sb, base_file, &ldir);
29785+ /* mnt_want_write() is unnecessary here */
29786+ file = au_xino_create2(base_file, NULL);
29787+ au_xino_unlock_dir(&ldir);
29788+ err = PTR_ERR(file);
29789+ if (IS_ERR(file))
29790+ goto out;
29791+ br->br_xino.xi_file = file;
29792+ } else {
29793+ br->br_xino.xi_file = shared_br->br_xino.xi_file;
29794+ get_file(br->br_xino.xi_file);
29795+ }
29796+
29797+ ino = AUFS_ROOT_INO;
29798+ err = au_xino_do_write(au_sbi(sb)->si_xwrite, br->br_xino.xi_file,
29799+ h_ino, ino);
b752ccd1
AM
29800+ if (unlikely(err)) {
29801+ fput(br->br_xino.xi_file);
29802+ br->br_xino.xi_file = NULL;
29803+ }
1facf9fc 29804+
4f0767ce 29805+out:
1facf9fc 29806+ return err;
29807+}
29808+
29809+/* ---------------------------------------------------------------------- */
29810+
29811+/* trucate a xino bitmap file */
29812+
29813+/* todo: slow */
29814+static int do_xib_restore(struct super_block *sb, struct file *file, void *page)
29815+{
29816+ int err, bit;
29817+ ssize_t sz;
29818+ unsigned long pindex;
29819+ loff_t pos, pend;
29820+ struct au_sbinfo *sbinfo;
29821+ au_readf_t func;
29822+ ino_t *ino;
29823+ unsigned long *p;
29824+
29825+ err = 0;
29826+ sbinfo = au_sbi(sb);
dece6358 29827+ MtxMustLock(&sbinfo->si_xib_mtx);
1facf9fc 29828+ p = sbinfo->si_xib_buf;
29829+ func = sbinfo->si_xread;
29830+ pend = i_size_read(file->f_dentry->d_inode);
29831+ pos = 0;
29832+ while (pos < pend) {
29833+ sz = xino_fread(func, file, page, PAGE_SIZE, &pos);
29834+ err = sz;
29835+ if (unlikely(sz <= 0))
29836+ goto out;
29837+
29838+ err = 0;
29839+ for (ino = page; sz > 0; ino++, sz -= sizeof(ino)) {
29840+ if (unlikely(*ino < AUFS_FIRST_INO))
29841+ continue;
29842+
29843+ xib_calc_bit(*ino, &pindex, &bit);
29844+ AuDebugOn(page_bits <= bit);
29845+ err = xib_pindex(sb, pindex);
29846+ if (!err)
29847+ set_bit(bit, p);
29848+ else
29849+ goto out;
29850+ }
29851+ }
29852+
4f0767ce 29853+out:
1facf9fc 29854+ return err;
29855+}
29856+
29857+static int xib_restore(struct super_block *sb)
29858+{
29859+ int err;
29860+ aufs_bindex_t bindex, bend;
29861+ void *page;
29862+
29863+ err = -ENOMEM;
29864+ page = (void *)__get_free_page(GFP_NOFS);
29865+ if (unlikely(!page))
29866+ goto out;
29867+
29868+ err = 0;
29869+ bend = au_sbend(sb);
29870+ for (bindex = 0; !err && bindex <= bend; bindex++)
29871+ if (!bindex || is_sb_shared(sb, bindex, bindex - 1) < 0)
29872+ err = do_xib_restore
29873+ (sb, au_sbr(sb, bindex)->br_xino.xi_file, page);
29874+ else
29875+ AuDbg("b%d\n", bindex);
29876+ free_page((unsigned long)page);
29877+
4f0767ce 29878+out:
1facf9fc 29879+ return err;
29880+}
29881+
29882+int au_xib_trunc(struct super_block *sb)
29883+{
29884+ int err;
29885+ ssize_t sz;
29886+ loff_t pos;
29887+ struct au_xino_lock_dir ldir;
29888+ struct au_sbinfo *sbinfo;
29889+ unsigned long *p;
29890+ struct file *file;
29891+
dece6358
AM
29892+ SiMustWriteLock(sb);
29893+
1facf9fc 29894+ err = 0;
29895+ sbinfo = au_sbi(sb);
29896+ if (!au_opt_test(sbinfo->si_mntflags, XINO))
29897+ goto out;
29898+
29899+ file = sbinfo->si_xib;
29900+ if (i_size_read(file->f_dentry->d_inode) <= PAGE_SIZE)
29901+ goto out;
29902+
29903+ au_xino_lock_dir(sb, file, &ldir);
29904+ /* mnt_want_write() is unnecessary here */
29905+ file = au_xino_create2(sbinfo->si_xib, NULL);
29906+ au_xino_unlock_dir(&ldir);
29907+ err = PTR_ERR(file);
29908+ if (IS_ERR(file))
29909+ goto out;
29910+ fput(sbinfo->si_xib);
29911+ sbinfo->si_xib = file;
29912+
29913+ p = sbinfo->si_xib_buf;
29914+ memset(p, 0, PAGE_SIZE);
29915+ pos = 0;
29916+ sz = xino_fwrite(sbinfo->si_xwrite, sbinfo->si_xib, p, PAGE_SIZE, &pos);
29917+ if (unlikely(sz != PAGE_SIZE)) {
29918+ err = sz;
29919+ AuIOErr("err %d\n", err);
29920+ if (sz >= 0)
29921+ err = -EIO;
29922+ goto out;
29923+ }
29924+
29925+ mutex_lock(&sbinfo->si_xib_mtx);
29926+ /* mnt_want_write() is unnecessary here */
29927+ err = xib_restore(sb);
29928+ mutex_unlock(&sbinfo->si_xib_mtx);
29929+
29930+out:
29931+ return err;
29932+}
29933+
29934+/* ---------------------------------------------------------------------- */
29935+
29936+/*
29937+ * xino mount option handlers
29938+ */
29939+static au_readf_t find_readf(struct file *h_file)
29940+{
29941+ const struct file_operations *fop = h_file->f_op;
29942+
29943+ if (fop) {
29944+ if (fop->read)
29945+ return fop->read;
29946+ if (fop->aio_read)
29947+ return do_sync_read;
29948+ }
29949+ return ERR_PTR(-ENOSYS);
29950+}
29951+
29952+static au_writef_t find_writef(struct file *h_file)
29953+{
29954+ const struct file_operations *fop = h_file->f_op;
29955+
29956+ if (fop) {
29957+ if (fop->write)
29958+ return fop->write;
29959+ if (fop->aio_write)
29960+ return do_sync_write;
29961+ }
29962+ return ERR_PTR(-ENOSYS);
29963+}
29964+
29965+/* xino bitmap */
29966+static void xino_clear_xib(struct super_block *sb)
29967+{
29968+ struct au_sbinfo *sbinfo;
29969+
dece6358
AM
29970+ SiMustWriteLock(sb);
29971+
1facf9fc 29972+ sbinfo = au_sbi(sb);
29973+ sbinfo->si_xread = NULL;
29974+ sbinfo->si_xwrite = NULL;
29975+ if (sbinfo->si_xib)
29976+ fput(sbinfo->si_xib);
29977+ sbinfo->si_xib = NULL;
29978+ free_page((unsigned long)sbinfo->si_xib_buf);
29979+ sbinfo->si_xib_buf = NULL;
29980+}
29981+
29982+static int au_xino_set_xib(struct super_block *sb, struct file *base)
29983+{
29984+ int err;
29985+ loff_t pos;
29986+ struct au_sbinfo *sbinfo;
29987+ struct file *file;
29988+
dece6358
AM
29989+ SiMustWriteLock(sb);
29990+
1facf9fc 29991+ sbinfo = au_sbi(sb);
29992+ file = au_xino_create2(base, sbinfo->si_xib);
29993+ err = PTR_ERR(file);
29994+ if (IS_ERR(file))
29995+ goto out;
29996+ if (sbinfo->si_xib)
29997+ fput(sbinfo->si_xib);
29998+ sbinfo->si_xib = file;
29999+ sbinfo->si_xread = find_readf(file);
30000+ sbinfo->si_xwrite = find_writef(file);
30001+
30002+ err = -ENOMEM;
30003+ if (!sbinfo->si_xib_buf)
30004+ sbinfo->si_xib_buf = (void *)get_zeroed_page(GFP_NOFS);
30005+ if (unlikely(!sbinfo->si_xib_buf))
30006+ goto out_unset;
30007+
30008+ sbinfo->si_xib_last_pindex = 0;
30009+ sbinfo->si_xib_next_bit = 0;
30010+ if (i_size_read(file->f_dentry->d_inode) < PAGE_SIZE) {
30011+ pos = 0;
30012+ err = xino_fwrite(sbinfo->si_xwrite, file, sbinfo->si_xib_buf,
30013+ PAGE_SIZE, &pos);
30014+ if (unlikely(err != PAGE_SIZE))
30015+ goto out_free;
30016+ }
30017+ err = 0;
30018+ goto out; /* success */
30019+
4f0767ce 30020+out_free:
1facf9fc 30021+ free_page((unsigned long)sbinfo->si_xib_buf);
b752ccd1
AM
30022+ sbinfo->si_xib_buf = NULL;
30023+ if (err >= 0)
30024+ err = -EIO;
4f0767ce 30025+out_unset:
b752ccd1
AM
30026+ fput(sbinfo->si_xib);
30027+ sbinfo->si_xib = NULL;
30028+ sbinfo->si_xread = NULL;
30029+ sbinfo->si_xwrite = NULL;
4f0767ce 30030+out:
b752ccd1 30031+ return err;
1facf9fc 30032+}
30033+
b752ccd1
AM
30034+/* xino for each branch */
30035+static void xino_clear_br(struct super_block *sb)
30036+{
30037+ aufs_bindex_t bindex, bend;
30038+ struct au_branch *br;
1facf9fc 30039+
b752ccd1
AM
30040+ bend = au_sbend(sb);
30041+ for (bindex = 0; bindex <= bend; bindex++) {
30042+ br = au_sbr(sb, bindex);
30043+ if (!br || !br->br_xino.xi_file)
30044+ continue;
30045+
30046+ fput(br->br_xino.xi_file);
30047+ br->br_xino.xi_file = NULL;
30048+ }
30049+}
30050+
30051+static int au_xino_set_br(struct super_block *sb, struct file *base)
1facf9fc 30052+{
30053+ int err;
b752ccd1
AM
30054+ ino_t ino;
30055+ aufs_bindex_t bindex, bend, bshared;
30056+ struct {
30057+ struct file *old, *new;
30058+ } *fpair, *p;
30059+ struct au_branch *br;
30060+ struct inode *inode;
30061+ au_writef_t writef;
1facf9fc 30062+
b752ccd1
AM
30063+ SiMustWriteLock(sb);
30064+
30065+ err = -ENOMEM;
30066+ bend = au_sbend(sb);
30067+ fpair = kcalloc(bend + 1, sizeof(*fpair), GFP_NOFS);
30068+ if (unlikely(!fpair))
1facf9fc 30069+ goto out;
30070+
b752ccd1
AM
30071+ inode = sb->s_root->d_inode;
30072+ ino = AUFS_ROOT_INO;
30073+ writef = au_sbi(sb)->si_xwrite;
30074+ for (bindex = 0, p = fpair; bindex <= bend; bindex++, p++) {
30075+ br = au_sbr(sb, bindex);
30076+ bshared = is_sb_shared(sb, bindex, bindex - 1);
30077+ if (bshared >= 0) {
30078+ /* shared xino */
30079+ *p = fpair[bshared];
30080+ get_file(p->new);
30081+ }
30082+
30083+ if (!p->new) {
30084+ /* new xino */
30085+ p->old = br->br_xino.xi_file;
30086+ p->new = au_xino_create2(base, br->br_xino.xi_file);
30087+ err = PTR_ERR(p->new);
30088+ if (IS_ERR(p->new)) {
30089+ p->new = NULL;
30090+ goto out_pair;
30091+ }
30092+ }
30093+
30094+ err = au_xino_do_write(writef, p->new,
30095+ au_h_iptr(inode, bindex)->i_ino, ino);
30096+ if (unlikely(err))
30097+ goto out_pair;
30098+ }
30099+
30100+ for (bindex = 0, p = fpair; bindex <= bend; bindex++, p++) {
30101+ br = au_sbr(sb, bindex);
30102+ if (br->br_xino.xi_file)
30103+ fput(br->br_xino.xi_file);
30104+ get_file(p->new);
30105+ br->br_xino.xi_file = p->new;
30106+ }
1facf9fc 30107+
4f0767ce 30108+out_pair:
b752ccd1
AM
30109+ for (bindex = 0, p = fpair; bindex <= bend; bindex++, p++)
30110+ if (p->new)
30111+ fput(p->new);
30112+ else
30113+ break;
30114+ kfree(fpair);
4f0767ce 30115+out:
1facf9fc 30116+ return err;
30117+}
b752ccd1
AM
30118+
30119+void au_xino_clr(struct super_block *sb)
30120+{
30121+ struct au_sbinfo *sbinfo;
30122+
30123+ au_xigen_clr(sb);
30124+ xino_clear_xib(sb);
30125+ xino_clear_br(sb);
30126+ sbinfo = au_sbi(sb);
30127+ /* lvalue, do not call au_mntflags() */
30128+ au_opt_clr(sbinfo->si_mntflags, XINO);
30129+}
30130+
30131+int au_xino_set(struct super_block *sb, struct au_opt_xino *xino, int remount)
30132+{
30133+ int err, skip;
30134+ struct dentry *parent, *cur_parent;
30135+ struct qstr *dname, *cur_name;
30136+ struct file *cur_xino;
30137+ struct inode *dir;
30138+ struct au_sbinfo *sbinfo;
30139+
30140+ SiMustWriteLock(sb);
30141+
30142+ err = 0;
30143+ sbinfo = au_sbi(sb);
30144+ parent = dget_parent(xino->file->f_dentry);
30145+ if (remount) {
30146+ skip = 0;
30147+ dname = &xino->file->f_dentry->d_name;
30148+ cur_xino = sbinfo->si_xib;
30149+ if (cur_xino) {
30150+ cur_parent = dget_parent(cur_xino->f_dentry);
30151+ cur_name = &cur_xino->f_dentry->d_name;
30152+ skip = (cur_parent == parent
30153+ && dname->len == cur_name->len
30154+ && !memcmp(dname->name, cur_name->name,
30155+ dname->len));
30156+ dput(cur_parent);
30157+ }
30158+ if (skip)
30159+ goto out;
30160+ }
30161+
30162+ au_opt_set(sbinfo->si_mntflags, XINO);
30163+ dir = parent->d_inode;
30164+ mutex_lock_nested(&dir->i_mutex, AuLsc_I_PARENT);
30165+ /* mnt_want_write() is unnecessary here */
30166+ err = au_xino_set_xib(sb, xino->file);
30167+ if (!err)
30168+ err = au_xigen_set(sb, xino->file);
30169+ if (!err)
30170+ err = au_xino_set_br(sb, xino->file);
30171+ mutex_unlock(&dir->i_mutex);
30172+ if (!err)
30173+ goto out; /* success */
30174+
30175+ /* reset all */
30176+ AuIOErr("failed creating xino(%d).\n", err);
30177+
4f0767ce 30178+out:
b752ccd1
AM
30179+ dput(parent);
30180+ return err;
30181+}
30182+
30183+/* ---------------------------------------------------------------------- */
30184+
30185+/*
30186+ * create a xinofile at the default place/path.
30187+ */
30188+struct file *au_xino_def(struct super_block *sb)
30189+{
30190+ struct file *file;
30191+ char *page, *p;
30192+ struct au_branch *br;
30193+ struct super_block *h_sb;
30194+ struct path path;
30195+ aufs_bindex_t bend, bindex, bwr;
30196+
30197+ br = NULL;
30198+ bend = au_sbend(sb);
30199+ bwr = -1;
30200+ for (bindex = 0; bindex <= bend; bindex++) {
30201+ br = au_sbr(sb, bindex);
30202+ if (au_br_writable(br->br_perm)
30203+ && !au_test_fs_bad_xino(br->br_mnt->mnt_sb)) {
30204+ bwr = bindex;
30205+ break;
30206+ }
30207+ }
30208+
7f207e10
AM
30209+ if (bwr >= 0) {
30210+ file = ERR_PTR(-ENOMEM);
30211+ page = __getname_gfp(GFP_NOFS);
30212+ if (unlikely(!page))
30213+ goto out;
30214+ path.mnt = br->br_mnt;
30215+ path.dentry = au_h_dptr(sb->s_root, bwr);
30216+ p = d_path(&path, page, PATH_MAX - sizeof(AUFS_XINO_FNAME));
30217+ file = (void *)p;
30218+ if (!IS_ERR(p)) {
30219+ strcat(p, "/" AUFS_XINO_FNAME);
30220+ AuDbg("%s\n", p);
30221+ file = au_xino_create(sb, p, /*silent*/0);
30222+ if (!IS_ERR(file))
30223+ au_xino_brid_set(sb, br->br_id);
30224+ }
30225+ __putname(page);
30226+ } else {
30227+ file = au_xino_create(sb, AUFS_XINO_DEFPATH, /*silent*/0);
30228+ if (IS_ERR(file))
30229+ goto out;
30230+ h_sb = file->f_dentry->d_sb;
30231+ if (unlikely(au_test_fs_bad_xino(h_sb))) {
30232+ pr_err("xino doesn't support %s(%s)\n",
30233+ AUFS_XINO_DEFPATH, au_sbtype(h_sb));
30234+ fput(file);
30235+ file = ERR_PTR(-EINVAL);
30236+ }
30237+ if (!IS_ERR(file))
30238+ au_xino_brid_set(sb, -1);
30239+ }
0c5527e5 30240+
7f207e10
AM
30241+out:
30242+ return file;
30243+}
30244+
30245+/* ---------------------------------------------------------------------- */
30246+
30247+int au_xino_path(struct seq_file *seq, struct file *file)
30248+{
30249+ int err;
30250+
30251+ err = au_seq_path(seq, &file->f_path);
30252+ if (unlikely(err < 0))
30253+ goto out;
30254+
30255+ err = 0;
30256+#define Deleted "\\040(deleted)"
30257+ seq->count -= sizeof(Deleted) - 1;
30258+ AuDebugOn(memcmp(seq->buf + seq->count, Deleted,
30259+ sizeof(Deleted) - 1));
30260+#undef Deleted
30261+
30262+out:
30263+ return err;
30264+}
30265diff -urN /usr/share/empty/include/linux/aufs_type.h linux/include/linux/aufs_type.h
30266--- /usr/share/empty/include/linux/aufs_type.h 1970-01-01 01:00:00.000000000 +0100
b4510431 30267+++ linux/include/linux/aufs_type.h 2012-10-17 10:31:01.775814563 +0200
f6c5ef8b 30268@@ -0,0 +1,233 @@
7f207e10 30269+/*
f6c5ef8b 30270+ * Copyright (C) 2005-2012 Junjiro R. Okajima
7f207e10
AM
30271+ *
30272+ * This program, aufs is free software; you can redistribute it and/or modify
30273+ * it under the terms of the GNU General Public License as published by
30274+ * the Free Software Foundation; either version 2 of the License, or
30275+ * (at your option) any later version.
30276+ *
30277+ * This program is distributed in the hope that it will be useful,
30278+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
30279+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
30280+ * GNU General Public License for more details.
30281+ *
30282+ * You should have received a copy of the GNU General Public License
30283+ * along with this program; if not, write to the Free Software
30284+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
30285+ */
30286+
30287+#ifndef __AUFS_TYPE_H__
30288+#define __AUFS_TYPE_H__
30289+
f6c5ef8b
AM
30290+#define AUFS_NAME "aufs"
30291+
9dbd164d 30292+#ifdef __KERNEL__
f6c5ef8b
AM
30293+/*
30294+ * define it before including all other headers.
30295+ * sched.h may use pr_* macros before defining "current", so define the
30296+ * no-current version first, and re-define later.
30297+ */
30298+#define pr_fmt(fmt) AUFS_NAME " %s:%d: " fmt, __func__, __LINE__
30299+#include <linux/sched.h>
30300+#undef pr_fmt
30301+#define pr_fmt(fmt) AUFS_NAME " %s:%d:%s[%d]: " fmt, \
30302+ __func__, __LINE__, current->comm, current->pid
9dbd164d
AM
30303+#else
30304+#include <stdint.h>
30305+#include <sys/types.h>
f6c5ef8b 30306+#endif /* __KERNEL__ */
7f207e10 30307+
f6c5ef8b
AM
30308+#include <linux/limits.h>
30309+
b4510431 30310+#define AUFS_VERSION "3.6-20121015"
7f207e10
AM
30311+
30312+/* todo? move this to linux-2.6.19/include/magic.h */
30313+#define AUFS_SUPER_MAGIC ('a' << 24 | 'u' << 16 | 'f' << 8 | 's')
30314+
30315+/* ---------------------------------------------------------------------- */
30316+
30317+#ifdef CONFIG_AUFS_BRANCH_MAX_127
9dbd164d 30318+typedef int8_t aufs_bindex_t;
7f207e10
AM
30319+#define AUFS_BRANCH_MAX 127
30320+#else
9dbd164d 30321+typedef int16_t aufs_bindex_t;
7f207e10
AM
30322+#ifdef CONFIG_AUFS_BRANCH_MAX_511
30323+#define AUFS_BRANCH_MAX 511
30324+#elif defined(CONFIG_AUFS_BRANCH_MAX_1023)
30325+#define AUFS_BRANCH_MAX 1023
30326+#elif defined(CONFIG_AUFS_BRANCH_MAX_32767)
30327+#define AUFS_BRANCH_MAX 32767
30328+#endif
30329+#endif
30330+
30331+#ifdef __KERNEL__
30332+#ifndef AUFS_BRANCH_MAX
30333+#error unknown CONFIG_AUFS_BRANCH_MAX value
30334+#endif
30335+#endif /* __KERNEL__ */
30336+
30337+/* ---------------------------------------------------------------------- */
30338+
7f207e10
AM
30339+#define AUFS_FSTYPE AUFS_NAME
30340+
30341+#define AUFS_ROOT_INO 2
30342+#define AUFS_FIRST_INO 11
30343+
30344+#define AUFS_WH_PFX ".wh."
30345+#define AUFS_WH_PFX_LEN ((int)sizeof(AUFS_WH_PFX) - 1)
30346+#define AUFS_WH_TMP_LEN 4
30347+/* a limit for rmdir/rename a dir */
30348+#define AUFS_MAX_NAMELEN (NAME_MAX \
30349+ - AUFS_WH_PFX_LEN * 2 /* doubly whiteouted */\
30350+ - 1 /* dot */\
30351+ - AUFS_WH_TMP_LEN) /* hex */
30352+#define AUFS_XINO_FNAME "." AUFS_NAME ".xino"
30353+#define AUFS_XINO_DEFPATH "/tmp/" AUFS_XINO_FNAME
30354+#define AUFS_XINO_TRUNC_INIT 64 /* blocks */
30355+#define AUFS_XINO_TRUNC_STEP 4 /* blocks */
30356+#define AUFS_DIRWH_DEF 3
30357+#define AUFS_RDCACHE_DEF 10 /* seconds */
027c5e7a 30358+#define AUFS_RDCACHE_MAX 3600 /* seconds */
7f207e10
AM
30359+#define AUFS_RDBLK_DEF 512 /* bytes */
30360+#define AUFS_RDHASH_DEF 32
30361+#define AUFS_WKQ_NAME AUFS_NAME "d"
027c5e7a
AM
30362+#define AUFS_MFS_DEF_SEC 30 /* seconds */
30363+#define AUFS_MFS_MAX_SEC 3600 /* seconds */
7f207e10
AM
30364+#define AUFS_PLINK_WARN 100 /* number of plinks */
30365+
30366+/* pseudo-link maintenace under /proc */
30367+#define AUFS_PLINK_MAINT_NAME "plink_maint"
30368+#define AUFS_PLINK_MAINT_DIR "fs/" AUFS_NAME
30369+#define AUFS_PLINK_MAINT_PATH AUFS_PLINK_MAINT_DIR "/" AUFS_PLINK_MAINT_NAME
30370+
30371+#define AUFS_DIROPQ_NAME AUFS_WH_PFX ".opq" /* whiteouted doubly */
30372+#define AUFS_WH_DIROPQ AUFS_WH_PFX AUFS_DIROPQ_NAME
30373+
30374+#define AUFS_BASE_NAME AUFS_WH_PFX AUFS_NAME
30375+#define AUFS_PLINKDIR_NAME AUFS_WH_PFX "plnk"
30376+#define AUFS_ORPHDIR_NAME AUFS_WH_PFX "orph"
30377+
30378+/* doubly whiteouted */
30379+#define AUFS_WH_BASE AUFS_WH_PFX AUFS_BASE_NAME
30380+#define AUFS_WH_PLINKDIR AUFS_WH_PFX AUFS_PLINKDIR_NAME
30381+#define AUFS_WH_ORPHDIR AUFS_WH_PFX AUFS_ORPHDIR_NAME
30382+
1e00d052 30383+/* branch permissions and attributes */
7f207e10
AM
30384+#define AUFS_BRPERM_RW "rw"
30385+#define AUFS_BRPERM_RO "ro"
30386+#define AUFS_BRPERM_RR "rr"
1e00d052
AM
30387+#define AUFS_BRRATTR_WH "wh"
30388+#define AUFS_BRWATTR_NLWH "nolwh"
7f207e10
AM
30389+
30390+/* ---------------------------------------------------------------------- */
30391+
30392+/* ioctl */
30393+enum {
30394+ /* readdir in userspace */
30395+ AuCtl_RDU,
30396+ AuCtl_RDU_INO,
30397+
30398+ /* pathconf wrapper */
027c5e7a
AM
30399+ AuCtl_WBR_FD,
30400+
30401+ /* busy inode */
30402+ AuCtl_IBUSY
7f207e10
AM
30403+};
30404+
30405+/* borrowed from linux/include/linux/kernel.h */
30406+#ifndef ALIGN
30407+#define ALIGN(x, a) __ALIGN_MASK(x, (typeof(x))(a)-1)
30408+#define __ALIGN_MASK(x, mask) (((x)+(mask))&~(mask))
30409+#endif
30410+
30411+/* borrowed from linux/include/linux/compiler-gcc3.h */
30412+#ifndef __aligned
30413+#define __aligned(x) __attribute__((aligned(x)))
53392da6
AM
30414+#endif
30415+
30416+#ifdef __KERNEL__
30417+#ifndef __packed
7f207e10
AM
30418+#define __packed __attribute__((packed))
30419+#endif
53392da6 30420+#endif
7f207e10
AM
30421+
30422+struct au_rdu_cookie {
9dbd164d
AM
30423+ uint64_t h_pos;
30424+ int16_t bindex;
30425+ uint8_t flags;
30426+ uint8_t pad;
30427+ uint32_t generation;
7f207e10
AM
30428+} __aligned(8);
30429+
30430+struct au_rdu_ent {
9dbd164d
AM
30431+ uint64_t ino;
30432+ int16_t bindex;
30433+ uint8_t type;
30434+ uint8_t nlen;
30435+ uint8_t wh;
7f207e10
AM
30436+ char name[0];
30437+} __aligned(8);
30438+
30439+static inline int au_rdu_len(int nlen)
30440+{
30441+ /* include the terminating NULL */
30442+ return ALIGN(sizeof(struct au_rdu_ent) + nlen + 1,
9dbd164d 30443+ sizeof(uint64_t));
7f207e10
AM
30444+}
30445+
30446+union au_rdu_ent_ul {
30447+ struct au_rdu_ent __user *e;
9dbd164d 30448+ uint64_t ul;
7f207e10
AM
30449+};
30450+
30451+enum {
30452+ AufsCtlRduV_SZ,
30453+ AufsCtlRduV_End
30454+};
30455+
30456+struct aufs_rdu {
30457+ /* input */
30458+ union {
9dbd164d
AM
30459+ uint64_t sz; /* AuCtl_RDU */
30460+ uint64_t nent; /* AuCtl_RDU_INO */
7f207e10
AM
30461+ };
30462+ union au_rdu_ent_ul ent;
9dbd164d 30463+ uint16_t verify[AufsCtlRduV_End];
7f207e10
AM
30464+
30465+ /* input/output */
9dbd164d 30466+ uint32_t blk;
7f207e10
AM
30467+
30468+ /* output */
30469+ union au_rdu_ent_ul tail;
30470+ /* number of entries which were added in a single call */
9dbd164d
AM
30471+ uint64_t rent;
30472+ uint8_t full;
30473+ uint8_t shwh;
7f207e10
AM
30474+
30475+ struct au_rdu_cookie cookie;
30476+} __aligned(8);
30477+
1e00d052
AM
30478+/* ---------------------------------------------------------------------- */
30479+
30480+struct aufs_wbr_fd {
9dbd164d
AM
30481+ uint32_t oflags;
30482+ int16_t brid;
1e00d052
AM
30483+} __aligned(8);
30484+
30485+/* ---------------------------------------------------------------------- */
30486+
027c5e7a 30487+struct aufs_ibusy {
9dbd164d
AM
30488+ uint64_t ino, h_ino;
30489+ int16_t bindex;
027c5e7a
AM
30490+} __aligned(8);
30491+
1e00d052
AM
30492+/* ---------------------------------------------------------------------- */
30493+
7f207e10
AM
30494+#define AuCtlType 'A'
30495+#define AUFS_CTL_RDU _IOWR(AuCtlType, AuCtl_RDU, struct aufs_rdu)
30496+#define AUFS_CTL_RDU_INO _IOWR(AuCtlType, AuCtl_RDU_INO, struct aufs_rdu)
1e00d052
AM
30497+#define AUFS_CTL_WBR_FD _IOW(AuCtlType, AuCtl_WBR_FD, \
30498+ struct aufs_wbr_fd)
027c5e7a 30499+#define AUFS_CTL_IBUSY _IOWR(AuCtlType, AuCtl_IBUSY, struct aufs_ibusy)
7f207e10
AM
30500+
30501+#endif /* __AUFS_TYPE_H__ */
This page took 4.336098 seconds and 4 git commands to generate.