]> git.pld-linux.org Git - packages/kernel.git/blame - kernel-aufs3.patch
- updated vserver patch to patch-3.7.1-vs2.3.5.4.diff
[packages/kernel.git] / kernel-aufs3.patch
CommitLineData
537831f9 1aufs3.x-rcN 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
537831f9 16index 1d7af79..06db6eb 100644
7f207e10
AM
17--- a/fs/Makefile
18+++ b/fs/Makefile
537831f9 19@@ -126,3 +126,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/
537831f9 24aufs3.x-rcN base patch
7f207e10 25
537831f9
AM
26diff --git a/fs/file_table.c b/fs/file_table.c
27index a72bf9d..dac6792 100644
28--- a/fs/file_table.c
29+++ b/fs/file_table.c
30@@ -36,7 +36,7 @@ struct files_stat_struct files_stat = {
31 .max_files = NR_FILE
32 };
33
34-DEFINE_STATIC_LGLOCK(files_lglock);
35+DEFINE_LGLOCK(files_lglock);
36
37 /* SLAB cache for file structures */
38 static struct kmem_cache *filp_cachep __read_mostly;
0c3ec466 39diff --git a/fs/inode.c b/fs/inode.c
537831f9 40index b03c719..ee497f9 100644
0c3ec466
AM
41--- a/fs/inode.c
42+++ b/fs/inode.c
43@@ -1491,7 +1491,7 @@ static int relatime_need_update(struct vfsmount *mnt, struct inode *inode,
44 * This does the actual work of updating an inodes time or version. Must have
45 * had called mnt_want_write() before calling this.
46 */
47-static int update_time(struct inode *inode, struct timespec *time, int flags)
48+int update_time(struct inode *inode, struct timespec *time, int flags)
49 {
50 if (inode->i_op->update_time)
51 return inode->i_op->update_time(inode, time, flags);
7f207e10 52diff --git a/fs/splice.c b/fs/splice.c
537831f9 53index 13e5b47..f185c6c 100644
7f207e10
AM
54--- a/fs/splice.c
55+++ b/fs/splice.c
b4510431 56@@ -1093,8 +1093,8 @@ EXPORT_SYMBOL(generic_splice_sendpage);
7f207e10
AM
57 /*
58 * Attempt to initiate a splice from pipe to file.
59 */
60-static long do_splice_from(struct pipe_inode_info *pipe, struct file *out,
61- loff_t *ppos, size_t len, unsigned int flags)
62+long do_splice_from(struct pipe_inode_info *pipe, struct file *out,
63+ loff_t *ppos, size_t len, unsigned int flags)
64 {
65 ssize_t (*splice_write)(struct pipe_inode_info *, struct file *,
66 loff_t *, size_t, unsigned int);
b4510431 67@@ -1121,9 +1121,9 @@ static long do_splice_from(struct pipe_inode_info *pipe, struct file *out,
7f207e10
AM
68 /*
69 * Attempt to initiate a splice from a file to a pipe.
70 */
71-static long do_splice_to(struct file *in, loff_t *ppos,
72- struct pipe_inode_info *pipe, size_t len,
73- unsigned int flags)
74+long do_splice_to(struct file *in, loff_t *ppos,
75+ struct pipe_inode_info *pipe, size_t len,
76+ unsigned int flags)
77 {
78 ssize_t (*splice_read)(struct file *, loff_t *,
79 struct pipe_inode_info *, size_t, unsigned int);
0c3ec466 80diff --git a/include/linux/fs.h b/include/linux/fs.h
537831f9 81index b33cfc9..963a61b 100644
0c3ec466
AM
82--- a/include/linux/fs.h
83+++ b/include/linux/fs.h
537831f9 84@@ -2558,6 +2558,7 @@ extern int inode_change_ok(const struct inode *, struct iattr *);
0c3ec466
AM
85 extern int inode_newsize_ok(const struct inode *, loff_t offset);
86 extern void setattr_copy(struct inode *inode, const struct iattr *attr);
87
88+extern int update_time(struct inode *, struct timespec *, int);
89 extern int file_update_time(struct file *file);
90
91 extern int generic_show_options(struct seq_file *m, struct dentry *root);
1e00d052 92diff --git a/include/linux/splice.h b/include/linux/splice.h
2dfbb274 93index 09a545a..1ac5727 100644
1e00d052
AM
94--- a/include/linux/splice.h
95+++ b/include/linux/splice.h
2dfbb274 96@@ -91,4 +91,10 @@ extern void splice_shrink_spd(struct splice_pipe_desc *);
4b3da204
AM
97 extern void spd_release_page(struct splice_pipe_desc *, unsigned int);
98
99 extern const struct pipe_buf_operations page_cache_pipe_buf_ops;
1e00d052
AM
100+
101+extern long do_splice_from(struct pipe_inode_info *pipe, struct file *out,
102+ loff_t *ppos, size_t len, unsigned int flags);
103+extern long do_splice_to(struct file *in, loff_t *ppos,
104+ struct pipe_inode_info *pipe, size_t len,
105+ unsigned int flags);
106 #endif
537831f9 107aufs3.x-rcN standalone patch
7f207e10
AM
108
109diff --git a/fs/file_table.c b/fs/file_table.c
537831f9 110index dac6792..e3f2c15 100644
7f207e10
AM
111--- a/fs/file_table.c
112+++ b/fs/file_table.c
b4510431 113@@ -37,6 +37,7 @@ struct files_stat_struct files_stat = {
0c3ec466
AM
114 };
115
116 DEFINE_LGLOCK(files_lglock);
117+EXPORT_SYMBOL(files_lglock);
118
119 /* SLAB cache for file structures */
120 static struct kmem_cache *filp_cachep __read_mostly;
537831f9 121@@ -403,6 +404,8 @@ void file_sb_list_del(struct file *file)
7f207e10
AM
122 }
123 }
124
125+EXPORT_SYMBOL(file_sb_list_del);
1facf9fc 126+
7f207e10
AM
127 #ifdef CONFIG_SMP
128
129 /*
1e00d052 130diff --git a/fs/inode.c b/fs/inode.c
537831f9 131index ee497f9..5e7eee7 100644
1e00d052
AM
132--- a/fs/inode.c
133+++ b/fs/inode.c
92d182d2 134@@ -56,6 +56,7 @@ static struct hlist_head *inode_hashtable __read_mostly;
4b3da204 135 static __cacheline_aligned_in_smp DEFINE_SPINLOCK(inode_hash_lock);
2cbb1c4b
JR
136
137 __cacheline_aligned_in_smp DEFINE_SPINLOCK(inode_sb_list_lock);
2cbb1c4b 138+EXPORT_SYMBOL(inode_sb_list_lock);
7f207e10
AM
139
140 /*
4b3da204 141 * Empty aops. Can be used for the cases where the user does not
0c3ec466
AM
142@@ -1507,6 +1508,7 @@ int update_time(struct inode *inode, struct timespec *time, int flags)
143 mark_inode_dirty_sync(inode);
144 return 0;
145 }
146+EXPORT_SYMBOL(update_time);
147
148 /**
149 * touch_atime - update the access time
7f207e10 150diff --git a/fs/namespace.c b/fs/namespace.c
537831f9 151index 2496062..3e66a90 100644
7f207e10
AM
152--- a/fs/namespace.c
153+++ b/fs/namespace.c
0c3ec466
AM
154@@ -50,6 +50,7 @@ EXPORT_SYMBOL_GPL(fs_kobj);
155 * tree or hash is modified or when a vfsmount structure is modified.
156 */
157 DEFINE_BRLOCK(vfsmount_lock);
158+EXPORT_SYMBOL(vfsmount_lock);
159
160 static inline unsigned long hash(struct vfsmount *mnt, struct dentry *dentry)
161 {
b4510431 162@@ -1401,6 +1402,7 @@ int iterate_mounts(int (*f)(struct vfsmount *, void *), void *arg,
7f207e10
AM
163 }
164 return 0;
165 }
166+EXPORT_SYMBOL(iterate_mounts);
167
7eafdf33 168 static void cleanup_group_ids(struct mount *mnt, struct mount *end)
7f207e10
AM
169 {
170diff --git a/fs/notify/group.c b/fs/notify/group.c
1e00d052 171index 63fc294..6f4adca 100644
7f207e10
AM
172--- a/fs/notify/group.c
173+++ b/fs/notify/group.c
174@@ -22,6 +22,7 @@
175 #include <linux/srcu.h>
176 #include <linux/rculist.h>
177 #include <linux/wait.h>
178+#include <linux/module.h>
179
180 #include <linux/fsnotify_backend.h>
181 #include "fsnotify.h"
182@@ -70,6 +71,7 @@ void fsnotify_put_group(struct fsnotify_group *group)
183 if (atomic_dec_and_test(&group->refcnt))
184 fsnotify_destroy_group(group);
185 }
186+EXPORT_SYMBOL(fsnotify_put_group);
187
188 /*
189 * Create a new fsnotify_group and hold a reference for the group returned.
190@@ -102,3 +104,4 @@ struct fsnotify_group *fsnotify_alloc_group(const struct fsnotify_ops *ops)
191
192 return group;
193 }
194+EXPORT_SYMBOL(fsnotify_alloc_group);
195diff --git a/fs/notify/mark.c b/fs/notify/mark.c
7eafdf33 196index f104d56..54f36db 100644
7f207e10
AM
197--- a/fs/notify/mark.c
198+++ b/fs/notify/mark.c
2cbb1c4b 199@@ -112,6 +112,7 @@ void fsnotify_put_mark(struct fsnotify_mark *mark)
7f207e10
AM
200 if (atomic_dec_and_test(&mark->refcnt))
201 mark->free_mark(mark);
202 }
203+EXPORT_SYMBOL(fsnotify_put_mark);
204
205 /*
206 * Any time a mark is getting freed we end up here.
7eafdf33 207@@ -191,6 +192,7 @@ void fsnotify_destroy_mark(struct fsnotify_mark *mark)
7f207e10
AM
208 if (unlikely(atomic_dec_and_test(&group->num_marks)))
209 fsnotify_final_destroy_group(group);
210 }
211+EXPORT_SYMBOL(fsnotify_destroy_mark);
212
213 void fsnotify_set_mark_mask_locked(struct fsnotify_mark *mark, __u32 mask)
214 {
7eafdf33 215@@ -278,6 +280,7 @@ err:
7f207e10
AM
216
217 return ret;
218 }
219+EXPORT_SYMBOL(fsnotify_add_mark);
220
221 /*
222 * clear any marks in a group in which mark->flags & flags is true
7eafdf33 223@@ -333,6 +336,7 @@ void fsnotify_init_mark(struct fsnotify_mark *mark,
7f207e10
AM
224 atomic_set(&mark->refcnt, 1);
225 mark->free_mark = free_mark;
226 }
227+EXPORT_SYMBOL(fsnotify_init_mark);
228
229 static int fsnotify_mark_destroy(void *ignored)
230 {
231diff --git a/fs/open.c b/fs/open.c
537831f9 232index 59071f5..7e4c856 100644
7f207e10
AM
233--- a/fs/open.c
234+++ b/fs/open.c
235@@ -60,6 +60,7 @@ int do_truncate(struct dentry *dentry, loff_t length, unsigned int time_attrs,
236 mutex_unlock(&dentry->d_inode->i_mutex);
237 return ret;
238 }
239+EXPORT_SYMBOL(do_truncate);
240
241 static long do_sys_truncate(const char __user *pathname, loff_t length)
242 {
243diff --git a/fs/splice.c b/fs/splice.c
537831f9 244index f185c6c..f3d89da 100644
7f207e10
AM
245--- a/fs/splice.c
246+++ b/fs/splice.c
b4510431 247@@ -1117,6 +1117,7 @@ long do_splice_from(struct pipe_inode_info *pipe, struct file *out,
7f207e10
AM
248
249 return splice_write(pipe, out, ppos, len, flags);
250 }
251+EXPORT_SYMBOL(do_splice_from);
252
253 /*
254 * Attempt to initiate a splice from a file to a pipe.
b4510431 255@@ -1143,6 +1144,7 @@ long do_splice_to(struct file *in, loff_t *ppos,
7f207e10
AM
256
257 return splice_read(in, ppos, pipe, len, flags);
258 }
259+EXPORT_SYMBOL(do_splice_to);
260
261 /**
262 * splice_direct_to_actor - splices data directly between two non-pipes
263diff --git a/security/commoncap.c b/security/commoncap.c
0c3ec466 264index 6dbae46..9f4f29a 100644
7f207e10
AM
265--- a/security/commoncap.c
266+++ b/security/commoncap.c
0c3ec466 267@@ -979,9 +979,11 @@ int cap_mmap_addr(unsigned long addr)
94337f0d 268 }
7f207e10
AM
269 return ret;
270 }
0c3ec466
AM
271+EXPORT_SYMBOL(cap_mmap_addr);
272
273 int cap_mmap_file(struct file *file, unsigned long reqprot,
274 unsigned long prot, unsigned long flags)
275 {
276 return 0;
277 }
278+EXPORT_SYMBOL(cap_mmap_file);
7f207e10 279diff --git a/security/device_cgroup.c b/security/device_cgroup.c
537831f9 280index b08d20c..a90420b 100644
7f207e10
AM
281--- a/security/device_cgroup.c
282+++ b/security/device_cgroup.c
f6c5ef8b
AM
283@@ -7,6 +7,7 @@
284 #include <linux/device_cgroup.h>
285 #include <linux/cgroup.h>
286 #include <linux/ctype.h>
287+#include <linux/export.h>
288 #include <linux/list.h>
289 #include <linux/uaccess.h>
290 #include <linux/seq_file.h>
537831f9
AM
291@@ -617,6 +618,7 @@ int __devcgroup_inode_permission(struct inode *inode, int mask)
292 return __devcgroup_check_permission(type, imajor(inode), iminor(inode),
293 access);
7f207e10 294 }
2cbb1c4b 295+EXPORT_SYMBOL(__devcgroup_inode_permission);
7f207e10
AM
296
297 int devcgroup_inode_mknod(int mode, dev_t dev)
298 {
299diff --git a/security/security.c b/security/security.c
537831f9 300index 8dcd4ae..6efe561 100644
7f207e10
AM
301--- a/security/security.c
302+++ b/security/security.c
537831f9 303@@ -396,6 +396,7 @@ int security_path_rmdir(struct path *dir, struct dentry *dentry)
7f207e10
AM
304 return 0;
305 return security_ops->path_rmdir(dir, dentry);
306 }
307+EXPORT_SYMBOL(security_path_rmdir);
308
309 int security_path_unlink(struct path *dir, struct dentry *dentry)
310 {
537831f9 311@@ -412,6 +413,7 @@ int security_path_symlink(struct path *dir, struct dentry *dentry,
7f207e10
AM
312 return 0;
313 return security_ops->path_symlink(dir, dentry, old_name);
314 }
315+EXPORT_SYMBOL(security_path_symlink);
316
317 int security_path_link(struct dentry *old_dentry, struct path *new_dir,
318 struct dentry *new_dentry)
537831f9 319@@ -420,6 +422,7 @@ int security_path_link(struct dentry *old_dentry, struct path *new_dir,
7f207e10
AM
320 return 0;
321 return security_ops->path_link(old_dentry, new_dir, new_dentry);
322 }
323+EXPORT_SYMBOL(security_path_link);
324
325 int security_path_rename(struct path *old_dir, struct dentry *old_dentry,
326 struct path *new_dir, struct dentry *new_dentry)
537831f9 327@@ -438,6 +441,7 @@ int security_path_truncate(struct path *path)
7f207e10
AM
328 return 0;
329 return security_ops->path_truncate(path);
330 }
331+EXPORT_SYMBOL(security_path_truncate);
332
7eafdf33
AM
333 int security_path_chmod(struct path *path, umode_t mode)
334 {
537831f9 335@@ -445,6 +449,7 @@ int security_path_chmod(struct path *path, umode_t mode)
7f207e10 336 return 0;
7eafdf33 337 return security_ops->path_chmod(path, mode);
7f207e10
AM
338 }
339+EXPORT_SYMBOL(security_path_chmod);
340
537831f9 341 int security_path_chown(struct path *path, kuid_t uid, kgid_t gid)
7f207e10 342 {
537831f9 343@@ -452,6 +457,7 @@ int security_path_chown(struct path *path, kuid_t uid, kgid_t gid)
7f207e10
AM
344 return 0;
345 return security_ops->path_chown(path, uid, gid);
346 }
347+EXPORT_SYMBOL(security_path_chown);
348
349 int security_path_chroot(struct path *path)
350 {
537831f9 351@@ -528,6 +534,7 @@ int security_inode_readlink(struct dentry *dentry)
7f207e10
AM
352 return 0;
353 return security_ops->inode_readlink(dentry);
354 }
355+EXPORT_SYMBOL(security_inode_readlink);
356
357 int security_inode_follow_link(struct dentry *dentry, struct nameidata *nd)
358 {
537831f9 359@@ -542,6 +549,7 @@ int security_inode_permission(struct inode *inode, int mask)
7f207e10 360 return 0;
1e00d052 361 return security_ops->inode_permission(inode, mask);
7f207e10
AM
362 }
363+EXPORT_SYMBOL(security_inode_permission);
364
1e00d052 365 int security_inode_setattr(struct dentry *dentry, struct iattr *attr)
7f207e10 366 {
537831f9 367@@ -663,6 +671,7 @@ int security_file_permission(struct file *file, int mask)
7f207e10
AM
368
369 return fsnotify_perm(file, mask);
370 }
371+EXPORT_SYMBOL(security_file_permission);
372
373 int security_file_alloc(struct file *file)
374 {
537831f9 375@@ -723,6 +732,7 @@ int security_mmap_file(struct file *file, unsigned long prot,
7f207e10
AM
376 return ret;
377 return ima_file_mmap(file, prot);
378 }
0c3ec466 379+EXPORT_SYMBOL(security_mmap_file);
7f207e10 380
0c3ec466
AM
381 int security_mmap_addr(unsigned long addr)
382 {
7f207e10
AM
383diff -urN /usr/share/empty/Documentation/ABI/testing/debugfs-aufs linux/Documentation/ABI/testing/debugfs-aufs
384--- /usr/share/empty/Documentation/ABI/testing/debugfs-aufs 1970-01-01 01:00:00.000000000 +0100
537831f9 385+++ linux/Documentation/ABI/testing/debugfs-aufs 2012-12-13 20:41:10.424793346 +0100
7f207e10
AM
386@@ -0,0 +1,37 @@
387+What: /debug/aufs/si_<id>/
388+Date: March 2009
389+Contact: J. R. Okajima <hooanon05@yahoo.co.jp>
390+Description:
391+ Under /debug/aufs, a directory named si_<id> is created
392+ per aufs mount, where <id> is a unique id generated
393+ internally.
1facf9fc 394+
7f207e10
AM
395+What: /debug/aufs/si_<id>/xib
396+Date: March 2009
397+Contact: J. R. Okajima <hooanon05@yahoo.co.jp>
398+Description:
399+ It shows the consumed blocks by xib (External Inode Number
400+ Bitmap), its block size and file size.
401+ When the aufs mount option 'noxino' is specified, it
402+ will be empty. About XINO files, see the aufs manual.
403+
404+What: /debug/aufs/si_<id>/xino0, xino1 ... xinoN
405+Date: March 2009
406+Contact: J. R. Okajima <hooanon05@yahoo.co.jp>
407+Description:
408+ It shows the consumed blocks by xino (External Inode Number
409+ Translation Table), its link count, block size and file
410+ size.
411+ When the aufs mount option 'noxino' is specified, it
412+ will be empty. About XINO files, see the aufs manual.
413+
414+What: /debug/aufs/si_<id>/xigen
415+Date: March 2009
416+Contact: J. R. Okajima <hooanon05@yahoo.co.jp>
417+Description:
418+ It shows the consumed blocks by xigen (External Inode
419+ Generation Table), its block size and file size.
420+ If CONFIG_AUFS_EXPORT is disabled, this entry will not
421+ be created.
422+ When the aufs mount option 'noxino' is specified, it
423+ will be empty. About XINO files, see the aufs manual.
424diff -urN /usr/share/empty/Documentation/ABI/testing/sysfs-aufs linux/Documentation/ABI/testing/sysfs-aufs
425--- /usr/share/empty/Documentation/ABI/testing/sysfs-aufs 1970-01-01 01:00:00.000000000 +0100
537831f9 426+++ linux/Documentation/ABI/testing/sysfs-aufs 2012-12-13 20:41:10.424793346 +0100
7f207e10
AM
427@@ -0,0 +1,24 @@
428+What: /sys/fs/aufs/si_<id>/
429+Date: March 2009
430+Contact: J. R. Okajima <hooanon05@yahoo.co.jp>
431+Description:
432+ Under /sys/fs/aufs, a directory named si_<id> is created
433+ per aufs mount, where <id> is a unique id generated
434+ internally.
435+
436+What: /sys/fs/aufs/si_<id>/br0, br1 ... brN
437+Date: March 2009
438+Contact: J. R. Okajima <hooanon05@yahoo.co.jp>
439+Description:
440+ It shows the abolute path of a member directory (which
441+ is called branch) in aufs, and its permission.
442+
443+What: /sys/fs/aufs/si_<id>/xi_path
444+Date: March 2009
445+Contact: J. R. Okajima <hooanon05@yahoo.co.jp>
446+Description:
447+ It shows the abolute path of XINO (External Inode Number
448+ Bitmap, Translation Table and Generation Table) file
449+ even if it is the default path.
450+ When the aufs mount option 'noxino' is specified, it
451+ will be empty. About XINO files, see the aufs manual.
53392da6
AM
452diff -urN /usr/share/empty/Documentation/filesystems/aufs/design/01intro.txt linux/Documentation/filesystems/aufs/design/01intro.txt
453--- /usr/share/empty/Documentation/filesystems/aufs/design/01intro.txt 1970-01-01 01:00:00.000000000 +0100
537831f9 454+++ linux/Documentation/filesystems/aufs/design/01intro.txt 2012-12-13 20:41:10.424793346 +0100
53392da6
AM
455@@ -0,0 +1,162 @@
456+
457+# Copyright (C) 2005-2011 Junjiro R. Okajima
458+#
459+# This program is free software; you can redistribute it and/or modify
460+# it under the terms of the GNU General Public License as published by
461+# the Free Software Foundation; either version 2 of the License, or
462+# (at your option) any later version.
463+#
464+# This program is distributed in the hope that it will be useful,
465+# but WITHOUT ANY WARRANTY; without even the implied warranty of
466+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
467+# GNU General Public License for more details.
468+#
469+# You should have received a copy of the GNU General Public License
470+# along with this program; if not, write to the Free Software
471+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
472+
473+Introduction
474+----------------------------------------
475+
476+aufs [ei ju: ef es] | [a u f s]
477+1. abbrev. for "advanced multi-layered unification filesystem".
478+2. abbrev. for "another unionfs".
479+3. abbrev. for "auf das" in German which means "on the" in English.
480+ Ex. "Butter aufs Brot"(G) means "butter onto bread"(E).
481+ But "Filesystem aufs Filesystem" is hard to understand.
482+
483+AUFS is a filesystem with features:
484+- multi layered stackable unification filesystem, the member directory
485+ is called as a branch.
486+- branch permission and attribute, 'readonly', 'real-readonly',
487+ 'readwrite', 'whiteout-able', 'link-able whiteout' and their
488+ combination.
489+- internal "file copy-on-write".
490+- logical deletion, whiteout.
491+- dynamic branch manipulation, adding, deleting and changing permission.
492+- allow bypassing aufs, user's direct branch access.
493+- external inode number translation table and bitmap which maintains the
494+ persistent aufs inode number.
495+- seekable directory, including NFS readdir.
496+- file mapping, mmap and sharing pages.
497+- pseudo-link, hardlink over branches.
498+- loopback mounted filesystem as a branch.
499+- several policies to select one among multiple writable branches.
500+- revert a single systemcall when an error occurs in aufs.
501+- and more...
502+
503+
504+Multi Layered Stackable Unification Filesystem
505+----------------------------------------------------------------------
506+Most people already knows what it is.
507+It is a filesystem which unifies several directories and provides a
508+merged single directory. When users access a file, the access will be
509+passed/re-directed/converted (sorry, I am not sure which English word is
510+correct) to the real file on the member filesystem. The member
511+filesystem is called 'lower filesystem' or 'branch' and has a mode
512+'readonly' and 'readwrite.' And the deletion for a file on the lower
513+readonly branch is handled by creating 'whiteout' on the upper writable
514+branch.
515+
516+On LKML, there have been discussions about UnionMount (Jan Blunck,
517+Bharata B Rao and Valerie Aurora) and Unionfs (Erez Zadok). They took
518+different approaches to implement the merged-view.
519+The former tries putting it into VFS, and the latter implements as a
520+separate filesystem.
521+(If I misunderstand about these implementations, please let me know and
522+I shall correct it. Because it is a long time ago when I read their
523+source files last time).
524+
525+UnionMount's approach will be able to small, but may be hard to share
526+branches between several UnionMount since the whiteout in it is
527+implemented in the inode on branch filesystem and always
528+shared. According to Bharata's post, readdir does not seems to be
529+finished yet.
530+There are several missing features known in this implementations such as
531+- for users, the inode number may change silently. eg. copy-up.
532+- link(2) may break by copy-up.
533+- read(2) may get an obsoleted filedata (fstat(2) too).
534+- fcntl(F_SETLK) may be broken by copy-up.
535+- unnecessary copy-up may happen, for example mmap(MAP_PRIVATE) after
536+ open(O_RDWR).
537+
538+Unionfs has a longer history. When I started implementing a stacking filesystem
539+(Aug 2005), it already existed. It has virtual super_block, inode,
540+dentry and file objects and they have an array pointing lower same kind
541+objects. After contributing many patches for Unionfs, I re-started my
542+project AUFS (Jun 2006).
543+
544+In AUFS, the structure of filesystem resembles to Unionfs, but I
545+implemented my own ideas, approaches and enhancements and it became
546+totally different one.
547+
548+Comparing DM snapshot and fs based implementation
549+- the number of bytes to be copied between devices is much smaller.
550+- the type of filesystem must be one and only.
551+- the fs must be writable, no readonly fs, even for the lower original
552+ device. so the compression fs will not be usable. but if we use
553+ loopback mount, we may address this issue.
554+ for instance,
555+ mount /cdrom/squashfs.img /sq
556+ losetup /sq/ext2.img
557+ losetup /somewhere/cow
558+ dmsetup "snapshot /dev/loop0 /dev/loop1 ..."
559+- it will be difficult (or needs more operations) to extract the
560+ difference between the original device and COW.
561+- DM snapshot-merge may help a lot when users try merging. in the
562+ fs-layer union, users will use rsync(1).
563+
564+
565+Several characters/aspects of aufs
566+----------------------------------------------------------------------
567+
568+Aufs has several characters or aspects.
569+1. a filesystem, callee of VFS helper
570+2. sub-VFS, caller of VFS helper for branches
571+3. a virtual filesystem which maintains persistent inode number
572+4. reader/writer of files on branches such like an application
573+
574+1. Callee of VFS Helper
575+As an ordinary linux filesystem, aufs is a callee of VFS. For instance,
576+unlink(2) from an application reaches sys_unlink() kernel function and
577+then vfs_unlink() is called. vfs_unlink() is one of VFS helper and it
578+calls filesystem specific unlink operation. Actually aufs implements the
579+unlink operation but it behaves like a redirector.
580+
581+2. Caller of VFS Helper for Branches
582+aufs_unlink() passes the unlink request to the branch filesystem as if
583+it were called from VFS. So the called unlink operation of the branch
584+filesystem acts as usual. As a caller of VFS helper, aufs should handle
585+every necessary pre/post operation for the branch filesystem.
586+- acquire the lock for the parent dir on a branch
587+- lookup in a branch
588+- revalidate dentry on a branch
589+- mnt_want_write() for a branch
590+- vfs_unlink() for a branch
591+- mnt_drop_write() for a branch
592+- release the lock on a branch
593+
594+3. Persistent Inode Number
595+One of the most important issue for a filesystem is to maintain inode
596+numbers. This is particularly important to support exporting a
597+filesystem via NFS. Aufs is a virtual filesystem which doesn't have a
598+backend block device for its own. But some storage is necessary to
599+maintain inode number. It may be a large space and may not suit to keep
600+in memory. Aufs rents some space from its first writable branch
601+filesystem (by default) and creates file(s) on it. These files are
602+created by aufs internally and removed soon (currently) keeping opened.
603+Note: Because these files are removed, they are totally gone after
604+ unmounting aufs. It means the inode numbers are not persistent
605+ across unmount or reboot. I have a plan to make them really
606+ persistent which will be important for aufs on NFS server.
607+
608+4. Read/Write Files Internally (copy-on-write)
609+Because a branch can be readonly, when you write a file on it, aufs will
610+"copy-up" it to the upper writable branch internally. And then write the
611+originally requested thing to the file. Generally kernel doesn't
612+open/read/write file actively. In aufs, even a single write may cause a
613+internal "file copy". This behaviour is very similar to cp(1) command.
614+
615+Some people may think it is better to pass such work to user space
616+helper, instead of doing in kernel space. Actually I am still thinking
617+about it. But currently I have implemented it in kernel space.
618diff -urN /usr/share/empty/Documentation/filesystems/aufs/design/02struct.txt linux/Documentation/filesystems/aufs/design/02struct.txt
619--- /usr/share/empty/Documentation/filesystems/aufs/design/02struct.txt 1970-01-01 01:00:00.000000000 +0100
537831f9 620+++ linux/Documentation/filesystems/aufs/design/02struct.txt 2012-12-13 20:41:10.424793346 +0100
53392da6
AM
621@@ -0,0 +1,226 @@
622+
623+# Copyright (C) 2005-2011 Junjiro R. Okajima
624+#
625+# This program is free software; you can redistribute it and/or modify
626+# it under the terms of the GNU General Public License as published by
627+# the Free Software Foundation; either version 2 of the License, or
628+# (at your option) any later version.
629+#
630+# This program is distributed in the hope that it will be useful,
631+# but WITHOUT ANY WARRANTY; without even the implied warranty of
632+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
633+# GNU General Public License for more details.
634+#
635+# You should have received a copy of the GNU General Public License
636+# along with this program; if not, write to the Free Software
637+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
638+
639+Basic Aufs Internal Structure
640+
641+Superblock/Inode/Dentry/File Objects
642+----------------------------------------------------------------------
643+As like an ordinary filesystem, aufs has its own
644+superblock/inode/dentry/file objects. All these objects have a
645+dynamically allocated array and store the same kind of pointers to the
646+lower filesystem, branch.
647+For example, when you build a union with one readwrite branch and one
648+readonly, mounted /au, /rw and /ro respectively.
649+- /au = /rw + /ro
650+- /ro/fileA exists but /rw/fileA
651+
652+Aufs lookup operation finds /ro/fileA and gets dentry for that. These
653+pointers are stored in a aufs dentry. The array in aufs dentry will be,
654+- [0] = NULL
655+- [1] = /ro/fileA
656+
657+This style of an array is essentially same to the aufs
658+superblock/inode/dentry/file objects.
659+
660+Because aufs supports manipulating branches, ie. add/delete/change
661+dynamically, these objects has its own generation. When branches are
662+changed, the generation in aufs superblock is incremented. And a
663+generation in other object are compared when it is accessed.
664+When a generation in other objects are obsoleted, aufs refreshes the
665+internal array.
666+
667+
668+Superblock
669+----------------------------------------------------------------------
670+Additionally aufs superblock has some data for policies to select one
671+among multiple writable branches, XIB files, pseudo-links and kobject.
672+See below in detail.
673+About the policies which supports copy-down a directory, see policy.txt
674+too.
675+
676+
677+Branch and XINO(External Inode Number Translation Table)
678+----------------------------------------------------------------------
679+Every branch has its own xino (external inode number translation table)
680+file. The xino file is created and unlinked by aufs internally. When two
681+members of a union exist on the same filesystem, they share the single
682+xino file.
683+The struct of a xino file is simple, just a sequence of aufs inode
684+numbers which is indexed by the lower inode number.
685+In the above sample, assume the inode number of /ro/fileA is i111 and
686+aufs assigns the inode number i999 for fileA. Then aufs writes 999 as
687+4(8) bytes at 111 * 4(8) bytes offset in the xino file.
688+
689+When the inode numbers are not contiguous, the xino file will be sparse
690+which has a hole in it and doesn't consume as much disk space as it
691+might appear. If your branch filesystem consumes disk space for such
692+holes, then you should specify 'xino=' option at mounting aufs.
693+
694+Also a writable branch has three kinds of "whiteout bases". All these
695+are existed when the branch is joined to aufs and the names are
696+whiteout-ed doubly, so that users will never see their names in aufs
697+hierarchy.
698+1. a regular file which will be linked to all whiteouts.
699+2. a directory to store a pseudo-link.
700+3. a directory to store an "orphan-ed" file temporary.
701+
702+1. Whiteout Base
703+ When you remove a file on a readonly branch, aufs handles it as a
704+ logical deletion and creates a whiteout on the upper writable branch
705+ as a hardlink of this file in order not to consume inode on the
706+ writable branch.
707+2. Pseudo-link Dir
708+ See below, Pseudo-link.
709+3. Step-Parent Dir
710+ When "fileC" exists on the lower readonly branch only and it is
711+ opened and removed with its parent dir, and then user writes
712+ something into it, then aufs copies-up fileC to this
713+ directory. Because there is no other dir to store fileC. After
714+ creating a file under this dir, the file is unlinked.
715+
716+Because aufs supports manipulating branches, ie. add/delete/change
717+dynamically, a branch has its own id. When the branch order changes, aufs
718+finds the new index by searching the branch id.
719+
720+
721+Pseudo-link
722+----------------------------------------------------------------------
723+Assume "fileA" exists on the lower readonly branch only and it is
724+hardlinked to "fileB" on the branch. When you write something to fileA,
725+aufs copies-up it to the upper writable branch. Additionally aufs
726+creates a hardlink under the Pseudo-link Directory of the writable
727+branch. The inode of a pseudo-link is kept in aufs super_block as a
728+simple list. If fileB is read after unlinking fileA, aufs returns
729+filedata from the pseudo-link instead of the lower readonly
730+branch. Because the pseudo-link is based upon the inode, to keep the
731+inode number by xino (see above) is important.
732+
733+All the hardlinks under the Pseudo-link Directory of the writable branch
734+should be restored in a proper location later. Aufs provides a utility
735+to do this. The userspace helpers executed at remounting and unmounting
736+aufs by default.
737+During this utility is running, it puts aufs into the pseudo-link
738+maintenance mode. In this mode, only the process which began the
739+maintenance mode (and its child processes) is allowed to operate in
740+aufs. Some other processes which are not related to the pseudo-link will
741+be allowed to run too, but the rest have to return an error or wait
742+until the maintenance mode ends. If a process already acquires an inode
743+mutex (in VFS), it has to return an error.
744+
745+
746+XIB(external inode number bitmap)
747+----------------------------------------------------------------------
748+Addition to the xino file per a branch, aufs has an external inode number
749+bitmap in a superblock object. It is also a file such like a xino file.
750+It is a simple bitmap to mark whether the aufs inode number is in-use or
751+not.
752+To reduce the file I/O, aufs prepares a single memory page to cache xib.
753+
754+Aufs implements a feature to truncate/refresh both of xino and xib to
755+reduce the number of consumed disk blocks for these files.
756+
757+
758+Virtual or Vertical Dir, and Readdir in Userspace
759+----------------------------------------------------------------------
760+In order to support multiple layers (branches), aufs readdir operation
761+constructs a virtual dir block on memory. For readdir, aufs calls
762+vfs_readdir() internally for each dir on branches, merges their entries
763+with eliminating the whiteout-ed ones, and sets it to file (dir)
764+object. So the file object has its entry list until it is closed. The
765+entry list will be updated when the file position is zero and becomes
766+old. This decision is made in aufs automatically.
767+
768+The dynamically allocated memory block for the name of entries has a
769+unit of 512 bytes (by default) and stores the names contiguously (no
770+padding). Another block for each entry is handled by kmem_cache too.
771+During building dir blocks, aufs creates hash list and judging whether
772+the entry is whiteouted by its upper branch or already listed.
773+The merged result is cached in the corresponding inode object and
774+maintained by a customizable life-time option.
775+
776+Some people may call it can be a security hole or invite DoS attack
777+since the opened and once readdir-ed dir (file object) holds its entry
778+list and becomes a pressure for system memory. But I'd say it is similar
779+to files under /proc or /sys. The virtual files in them also holds a
780+memory page (generally) while they are opened. When an idea to reduce
781+memory for them is introduced, it will be applied to aufs too.
782+For those who really hate this situation, I've developed readdir(3)
783+library which operates this merging in userspace. You just need to set
784+LD_PRELOAD environment variable, and aufs will not consume no memory in
785+kernel space for readdir(3).
786+
787+
788+Workqueue
789+----------------------------------------------------------------------
790+Aufs sometimes requires privilege access to a branch. For instance,
791+in copy-up/down operation. When a user process is going to make changes
792+to a file which exists in the lower readonly branch only, and the mode
793+of one of ancestor directories may not be writable by a user
794+process. Here aufs copy-up the file with its ancestors and they may
795+require privilege to set its owner/group/mode/etc.
796+This is a typical case of a application character of aufs (see
797+Introduction).
798+
799+Aufs uses workqueue synchronously for this case. It creates its own
800+workqueue. The workqueue is a kernel thread and has privilege. Aufs
801+passes the request to call mkdir or write (for example), and wait for
802+its completion. This approach solves a problem of a signal handler
803+simply.
804+If aufs didn't adopt the workqueue and changed the privilege of the
805+process, and if the mkdir/write call arises SIGXFSZ or other signal,
806+then the user process might gain a privilege or the generated core file
807+was owned by a superuser.
808+
809+Also aufs uses the system global workqueue ("events" kernel thread) too
810+for asynchronous tasks, such like handling inotify/fsnotify, re-creating a
811+whiteout base and etc. This is unrelated to a privilege.
812+Most of aufs operation tries acquiring a rw_semaphore for aufs
813+superblock at the beginning, at the same time waits for the completion
814+of all queued asynchronous tasks.
815+
816+
817+Whiteout
818+----------------------------------------------------------------------
819+The whiteout in aufs is very similar to Unionfs's. That is represented
820+by its filename. UnionMount takes an approach of a file mode, but I am
821+afraid several utilities (find(1) or something) will have to support it.
822+
823+Basically the whiteout represents "logical deletion" which stops aufs to
824+lookup further, but also it represents "dir is opaque" which also stop
825+lookup.
826+
827+In aufs, rmdir(2) and rename(2) for dir uses whiteout alternatively.
828+In order to make several functions in a single systemcall to be
829+revertible, aufs adopts an approach to rename a directory to a temporary
830+unique whiteouted name.
831+For example, in rename(2) dir where the target dir already existed, aufs
832+renames the target dir to a temporary unique whiteouted name before the
833+actual rename on a branch and then handles other actions (make it opaque,
834+update the attributes, etc). If an error happens in these actions, aufs
835+simply renames the whiteouted name back and returns an error. If all are
836+succeeded, aufs registers a function to remove the whiteouted unique
837+temporary name completely and asynchronously to the system global
838+workqueue.
839+
840+
841+Copy-up
842+----------------------------------------------------------------------
843+It is a well-known feature or concept.
844+When user modifies a file on a readonly branch, aufs operate "copy-up"
845+internally and makes change to the new file on the upper writable branch.
846+When the trigger systemcall does not update the timestamps of the parent
847+dir, aufs reverts it after copy-up.
848diff -urN /usr/share/empty/Documentation/filesystems/aufs/design/03lookup.txt linux/Documentation/filesystems/aufs/design/03lookup.txt
849--- /usr/share/empty/Documentation/filesystems/aufs/design/03lookup.txt 1970-01-01 01:00:00.000000000 +0100
537831f9 850+++ linux/Documentation/filesystems/aufs/design/03lookup.txt 2012-12-13 20:41:10.428126759 +0100
53392da6
AM
851@@ -0,0 +1,106 @@
852+
853+# Copyright (C) 2005-2011 Junjiro R. Okajima
854+#
855+# This program is free software; you can redistribute it and/or modify
856+# it under the terms of the GNU General Public License as published by
857+# the Free Software Foundation; either version 2 of the License, or
858+# (at your option) any later version.
859+#
860+# This program is distributed in the hope that it will be useful,
861+# but WITHOUT ANY WARRANTY; without even the implied warranty of
862+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
863+# GNU General Public License for more details.
864+#
865+# You should have received a copy of the GNU General Public License
866+# along with this program; if not, write to the Free Software
867+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
868+
869+Lookup in a Branch
870+----------------------------------------------------------------------
871+Since aufs has a character of sub-VFS (see Introduction), it operates
872+lookup for branches as VFS does. It may be a heavy work. Generally
873+speaking struct nameidata is a bigger structure and includes many
874+information. But almost all lookup operation in aufs is the simplest
875+case, ie. lookup only an entry directly connected to its parent. Digging
876+down the directory hierarchy is unnecessary.
877+
878+VFS has a function lookup_one_len() for that use, but it is not usable
879+for a branch filesystem which requires struct nameidata. So aufs
880+implements a simple lookup wrapper function. When a branch filesystem
881+allows NULL as nameidata, it calls lookup_one_len(). Otherwise it builds
882+a simplest nameidata and calls lookup_hash().
883+Here aufs applies "a principle in NFSD", ie. if the filesystem supports
884+NFS-export, then it has to support NULL as a nameidata parameter for
885+->create(), ->lookup() and ->d_revalidate(). So the lookup wrapper in
886+aufs tests if ->s_export_op in the branch is NULL or not.
887+
888+When a branch is a remote filesystem, aufs basically trusts its
889+->d_revalidate(), also aufs forces the hardest revalidate tests for
890+them.
891+For d_revalidate, aufs implements three levels of revalidate tests. See
892+"Revalidate Dentry and UDBA" in detail.
893+
894+
895+Loopback Mount
896+----------------------------------------------------------------------
897+Basically aufs supports any type of filesystem and block device for a
898+branch (actually there are some exceptions). But it is prohibited to add
899+a loopback mounted one whose backend file exists in a filesystem which is
900+already added to aufs. The reason is to protect aufs from a recursive
901+lookup. If it was allowed, the aufs lookup operation might re-enter a
902+lookup for the loopback mounted branch in the same context, and will
903+cause a deadlock.
904+
905+
906+Revalidate Dentry and UDBA (User's Direct Branch Access)
907+----------------------------------------------------------------------
908+Generally VFS helpers re-validate a dentry as a part of lookup.
909+0. digging down the directory hierarchy.
910+1. lock the parent dir by its i_mutex.
911+2. lookup the final (child) entry.
912+3. revalidate it.
913+4. call the actual operation (create, unlink, etc.)
914+5. unlock the parent dir
915+
916+If the filesystem implements its ->d_revalidate() (step 3), then it is
917+called. Actually aufs implements it and checks the dentry on a branch is
918+still valid.
919+But it is not enough. Because aufs has to release the lock for the
920+parent dir on a branch at the end of ->lookup() (step 2) and
921+->d_revalidate() (step 3) while the i_mutex of the aufs dir is still
922+held by VFS.
923+If the file on a branch is changed directly, eg. bypassing aufs, after
924+aufs released the lock, then the subsequent operation may cause
925+something unpleasant result.
926+
927+This situation is a result of VFS architecture, ->lookup() and
928+->d_revalidate() is separated. But I never say it is wrong. It is a good
929+design from VFS's point of view. It is just not suitable for sub-VFS
930+character in aufs.
931+
932+Aufs supports such case by three level of revalidation which is
933+selectable by user.
934+1. Simple Revalidate
935+ Addition to the native flow in VFS's, confirm the child-parent
936+ relationship on the branch just after locking the parent dir on the
937+ branch in the "actual operation" (step 4). When this validation
938+ fails, aufs returns EBUSY. ->d_revalidate() (step 3) in aufs still
939+ checks the validation of the dentry on branches.
940+2. Monitor Changes Internally by Inotify/Fsnotify
941+ Addition to above, in the "actual operation" (step 4) aufs re-lookup
942+ the dentry on the branch, and returns EBUSY if it finds different
943+ dentry.
944+ Additionally, aufs sets the inotify/fsnotify watch for every dir on branches
945+ during it is in cache. When the event is notified, aufs registers a
946+ function to kernel 'events' thread by schedule_work(). And the
947+ function sets some special status to the cached aufs dentry and inode
948+ private data. If they are not cached, then aufs has nothing to
949+ do. When the same file is accessed through aufs (step 0-3) later,
950+ aufs will detect the status and refresh all necessary data.
951+ In this mode, aufs has to ignore the event which is fired by aufs
952+ itself.
953+3. No Extra Validation
954+ This is the simplest test and doesn't add any additional revalidation
955+ test, and skip therevalidatin in step 4. It is useful and improves
956+ aufs performance when system surely hide the aufs branches from user,
957+ by over-mounting something (or another method).
958diff -urN /usr/share/empty/Documentation/filesystems/aufs/design/04branch.txt linux/Documentation/filesystems/aufs/design/04branch.txt
959--- /usr/share/empty/Documentation/filesystems/aufs/design/04branch.txt 1970-01-01 01:00:00.000000000 +0100
537831f9 960+++ linux/Documentation/filesystems/aufs/design/04branch.txt 2012-12-13 20:41:10.428126759 +0100
53392da6
AM
961@@ -0,0 +1,76 @@
962+
963+# Copyright (C) 2005-2011 Junjiro R. Okajima
964+#
965+# This program is free software; you can redistribute it and/or modify
966+# it under the terms of the GNU General Public License as published by
967+# the Free Software Foundation; either version 2 of the License, or
968+# (at your option) any later version.
969+#
970+# This program is distributed in the hope that it will be useful,
971+# but WITHOUT ANY WARRANTY; without even the implied warranty of
972+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
973+# GNU General Public License for more details.
974+#
975+# You should have received a copy of the GNU General Public License
976+# along with this program; if not, write to the Free Software
977+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
978+
979+Branch Manipulation
980+
981+Since aufs supports dynamic branch manipulation, ie. add/remove a branch
982+and changing its permission/attribute, there are a lot of works to do.
983+
984+
985+Add a Branch
986+----------------------------------------------------------------------
987+o Confirm the adding dir exists outside of aufs, including loopback
988+ mount.
989+- and other various attributes...
990+o Initialize the xino file and whiteout bases if necessary.
991+ See struct.txt.
992+
993+o Check the owner/group/mode of the directory
994+ When the owner/group/mode of the adding directory differs from the
995+ existing branch, aufs issues a warning because it may impose a
996+ security risk.
997+ For example, when a upper writable branch has a world writable empty
998+ top directory, a malicious user can create any files on the writable
999+ branch directly, like copy-up and modify manually. If something like
1000+ /etc/{passwd,shadow} exists on the lower readonly branch but the upper
1001+ writable branch, and the writable branch is world-writable, then a
1002+ malicious guy may create /etc/passwd on the writable branch directly
1003+ and the infected file will be valid in aufs.
1004+ I am afraid it can be a security issue, but nothing to do except
1005+ producing a warning.
1006+
1007+
1008+Delete a Branch
1009+----------------------------------------------------------------------
1010+o Confirm the deleting branch is not busy
1011+ To be general, there is one merit to adopt "remount" interface to
1012+ manipulate branches. It is to discard caches. At deleting a branch,
1013+ aufs checks the still cached (and connected) dentries and inodes. If
1014+ there are any, then they are all in-use. An inode without its
1015+ corresponding dentry can be alive alone (for example, inotify/fsnotify case).
1016+
1017+ For the cached one, aufs checks whether the same named entry exists on
1018+ other branches.
1019+ If the cached one is a directory, because aufs provides a merged view
1020+ to users, as long as one dir is left on any branch aufs can show the
1021+ dir to users. In this case, the branch can be removed from aufs.
1022+ Otherwise aufs rejects deleting the branch.
1023+
1024+ If any file on the deleting branch is opened by aufs, then aufs
1025+ rejects deleting.
1026+
1027+
1028+Modify the Permission of a Branch
1029+----------------------------------------------------------------------
1030+o Re-initialize or remove the xino file and whiteout bases if necessary.
1031+ See struct.txt.
1032+
1033+o rw --> ro: Confirm the modifying branch is not busy
1034+ Aufs rejects the request if any of these conditions are true.
1035+ - a file on the branch is mmap-ed.
1036+ - a regular file on the branch is opened for write and there is no
1037+ same named entry on the upper branch.
1038diff -urN /usr/share/empty/Documentation/filesystems/aufs/design/05wbr_policy.txt linux/Documentation/filesystems/aufs/design/05wbr_policy.txt
1039--- /usr/share/empty/Documentation/filesystems/aufs/design/05wbr_policy.txt 1970-01-01 01:00:00.000000000 +0100
537831f9 1040+++ linux/Documentation/filesystems/aufs/design/05wbr_policy.txt 2012-12-13 20:41:10.428126759 +0100
53392da6
AM
1041@@ -0,0 +1,65 @@
1042+
1043+# Copyright (C) 2005-2011 Junjiro R. Okajima
1044+#
1045+# This program is free software; you can redistribute it and/or modify
1046+# it under the terms of the GNU General Public License as published by
1047+# the Free Software Foundation; either version 2 of the License, or
1048+# (at your option) any later version.
1049+#
1050+# This program is distributed in the hope that it will be useful,
1051+# but WITHOUT ANY WARRANTY; without even the implied warranty of
1052+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1053+# GNU General Public License for more details.
1054+#
1055+# You should have received a copy of the GNU General Public License
1056+# along with this program; if not, write to the Free Software
1057+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1058+
1059+Policies to Select One among Multiple Writable Branches
1060+----------------------------------------------------------------------
1061+When the number of writable branch is more than one, aufs has to decide
1062+the target branch for file creation or copy-up. By default, the highest
1063+writable branch which has the parent (or ancestor) dir of the target
1064+file is chosen (top-down-parent policy).
1065+By user's request, aufs implements some other policies to select the
1066+writable branch, for file creation two policies, round-robin and
1067+most-free-space policies. For copy-up three policies, top-down-parent,
1068+bottom-up-parent and bottom-up policies.
1069+
1070+As expected, the round-robin policy selects the branch in circular. When
1071+you have two writable branches and creates 10 new files, 5 files will be
1072+created for each branch. mkdir(2) systemcall is an exception. When you
1073+create 10 new directories, all will be created on the same branch.
1074+And the most-free-space policy selects the one which has most free
1075+space among the writable branches. The amount of free space will be
1076+checked by aufs internally, and users can specify its time interval.
1077+
1078+The policies for copy-up is more simple,
1079+top-down-parent is equivalent to the same named on in create policy,
1080+bottom-up-parent selects the writable branch where the parent dir
1081+exists and the nearest upper one from the copyup-source,
1082+bottom-up selects the nearest upper writable branch from the
1083+copyup-source, regardless the existence of the parent dir.
1084+
1085+There are some rules or exceptions to apply these policies.
1086+- If there is a readonly branch above the policy-selected branch and
1087+ the parent dir is marked as opaque (a variation of whiteout), or the
1088+ target (creating) file is whiteout-ed on the upper readonly branch,
1089+ then the result of the policy is ignored and the target file will be
1090+ created on the nearest upper writable branch than the readonly branch.
1091+- If there is a writable branch above the policy-selected branch and
1092+ the parent dir is marked as opaque or the target file is whiteouted
1093+ on the branch, then the result of the policy is ignored and the target
1094+ file will be created on the highest one among the upper writable
1095+ branches who has diropq or whiteout. In case of whiteout, aufs removes
1096+ it as usual.
1097+- link(2) and rename(2) systemcalls are exceptions in every policy.
1098+ They try selecting the branch where the source exists as possible
1099+ since copyup a large file will take long time. If it can't be,
1100+ ie. the branch where the source exists is readonly, then they will
1101+ follow the copyup policy.
1102+- There is an exception for rename(2) when the target exists.
1103+ If the rename target exists, aufs compares the index of the branches
1104+ where the source and the target exists and selects the higher
1105+ one. If the selected branch is readonly, then aufs follows the
1106+ copyup policy.
1107diff -urN /usr/share/empty/Documentation/filesystems/aufs/design/06mmap.txt linux/Documentation/filesystems/aufs/design/06mmap.txt
1108--- /usr/share/empty/Documentation/filesystems/aufs/design/06mmap.txt 1970-01-01 01:00:00.000000000 +0100
537831f9 1109+++ linux/Documentation/filesystems/aufs/design/06mmap.txt 2012-12-13 20:41:10.428126759 +0100
53392da6
AM
1110@@ -0,0 +1,47 @@
1111+
1112+# Copyright (C) 2005-2011 Junjiro R. Okajima
1113+#
1114+# This program is free software; you can redistribute it and/or modify
1115+# it under the terms of the GNU General Public License as published by
1116+# the Free Software Foundation; either version 2 of the License, or
1117+# (at your option) any later version.
1118+#
1119+# This program is distributed in the hope that it will be useful,
1120+# but WITHOUT ANY WARRANTY; without even the implied warranty of
1121+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1122+# GNU General Public License for more details.
1123+#
1124+# You should have received a copy of the GNU General Public License
1125+# along with this program; if not, write to the Free Software
1126+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1127+
1128+mmap(2) -- File Memory Mapping
1129+----------------------------------------------------------------------
1130+In aufs, the file-mapped pages are handled by a branch fs directly, no
1131+interaction with aufs. It means aufs_mmap() calls the branch fs's
1132+->mmap().
1133+This approach is simple and good, but there is one problem.
1134+Under /proc, several entries show the mmap-ped files by its path (with
1135+device and inode number), and the printed path will be the path on the
1136+branch fs's instead of virtual aufs's.
1137+This is not a problem in most cases, but some utilities lsof(1) (and its
1138+user) may expect the path on aufs.
1139+
1140+To address this issue, aufs adds a new member called vm_prfile in struct
1141+vm_area_struct (and struct vm_region). The original vm_file points to
1142+the file on the branch fs in order to handle everything correctly as
1143+usual. The new vm_prfile points to a virtual file in aufs, and the
1144+show-functions in procfs refers to vm_prfile if it is set.
1145+Also we need to maintain several other places where touching vm_file
1146+such like
1147+- fork()/clone() copies vma and the reference count of vm_file is
1148+ incremented.
1149+- merging vma maintains the ref count too.
1150+
1151+This is not a good approach. It just faking the printed path. But it
1152+leaves all behaviour around f_mapping unchanged. This is surely an
1153+advantage.
1154+Actually aufs had adopted another complicated approach which calls
1155+generic_file_mmap() and handles struct vm_operations_struct. In this
1156+approach, aufs met a hard problem and I could not solve it without
1157+switching the approach.
1158diff -urN /usr/share/empty/Documentation/filesystems/aufs/design/07export.txt linux/Documentation/filesystems/aufs/design/07export.txt
1159--- /usr/share/empty/Documentation/filesystems/aufs/design/07export.txt 1970-01-01 01:00:00.000000000 +0100
537831f9 1160+++ linux/Documentation/filesystems/aufs/design/07export.txt 2012-12-13 20:41:10.428126759 +0100
53392da6
AM
1161@@ -0,0 +1,59 @@
1162+
1163+# Copyright (C) 2005-2011 Junjiro R. Okajima
1164+#
1165+# This program is free software; you can redistribute it and/or modify
1166+# it under the terms of the GNU General Public License as published by
1167+# the Free Software Foundation; either version 2 of the License, or
1168+# (at your option) any later version.
1169+#
1170+# This program is distributed in the hope that it will be useful,
1171+# but WITHOUT ANY WARRANTY; without even the implied warranty of
1172+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1173+# GNU General Public License for more details.
1174+#
1175+# You should have received a copy of the GNU General Public License
1176+# along with this program; if not, write to the Free Software
1177+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1178+
1179+Export Aufs via NFS
1180+----------------------------------------------------------------------
1181+Here is an approach.
1182+- like xino/xib, add a new file 'xigen' which stores aufs inode
1183+ generation.
1184+- iget_locked(): initialize aufs inode generation for a new inode, and
1185+ store it in xigen file.
1186+- destroy_inode(): increment aufs inode generation and store it in xigen
1187+ file. it is necessary even if it is not unlinked, because any data of
1188+ inode may be changed by UDBA.
1189+- encode_fh(): for a root dir, simply return FILEID_ROOT. otherwise
1190+ build file handle by
1191+ + branch id (4 bytes)
1192+ + superblock generation (4 bytes)
1193+ + inode number (4 or 8 bytes)
1194+ + parent dir inode number (4 or 8 bytes)
1195+ + inode generation (4 bytes))
1196+ + return value of exportfs_encode_fh() for the parent on a branch (4
1197+ bytes)
1198+ + file handle for a branch (by exportfs_encode_fh())
1199+- fh_to_dentry():
1200+ + find the index of a branch from its id in handle, and check it is
1201+ still exist in aufs.
1202+ + 1st level: get the inode number from handle and search it in cache.
1203+ + 2nd level: if not found, get the parent inode number from handle and
1204+ search it in cache. and then open the parent dir, find the matching
1205+ inode number by vfs_readdir() and get its name, and call
1206+ lookup_one_len() for the target dentry.
1207+ + 3rd level: if the parent dir is not cached, call
1208+ exportfs_decode_fh() for a branch and get the parent on a branch,
1209+ build a pathname of it, convert it a pathname in aufs, call
1210+ path_lookup(). now aufs gets a parent dir dentry, then handle it as
1211+ the 2nd level.
1212+ + to open the dir, aufs needs struct vfsmount. aufs keeps vfsmount
1213+ for every branch, but not itself. to get this, (currently) aufs
1214+ searches in current->nsproxy->mnt_ns list. it may not be a good
1215+ idea, but I didn't get other approach.
1216+ + test the generation of the gotten inode.
1217+- every inode operation: they may get EBUSY due to UDBA. in this case,
1218+ convert it into ESTALE for NFSD.
1219+- readdir(): call lockdep_on/off() because filldir in NFSD calls
1220+ lookup_one_len(), vfs_getattr(), encode_fh() and others.
1221diff -urN /usr/share/empty/Documentation/filesystems/aufs/design/08shwh.txt linux/Documentation/filesystems/aufs/design/08shwh.txt
1222--- /usr/share/empty/Documentation/filesystems/aufs/design/08shwh.txt 1970-01-01 01:00:00.000000000 +0100
537831f9 1223+++ linux/Documentation/filesystems/aufs/design/08shwh.txt 2012-12-13 20:41:10.428126759 +0100
53392da6
AM
1224@@ -0,0 +1,53 @@
1225+
1226+# Copyright (C) 2005-2011 Junjiro R. Okajima
1227+#
1228+# This program is free software; you can redistribute it and/or modify
1229+# it under the terms of the GNU General Public License as published by
1230+# the Free Software Foundation; either version 2 of the License, or
1231+# (at your option) any later version.
1232+#
1233+# This program is distributed in the hope that it will be useful,
1234+# but WITHOUT ANY WARRANTY; without even the implied warranty of
1235+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1236+# GNU General Public License for more details.
1237+#
1238+# You should have received a copy of the GNU General Public License
1239+# along with this program; if not, write to the Free Software
1240+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1241+
1242+Show Whiteout Mode (shwh)
1243+----------------------------------------------------------------------
1244+Generally aufs hides the name of whiteouts. But in some cases, to show
1245+them is very useful for users. For instance, creating a new middle layer
1246+(branch) by merging existing layers.
1247+
1248+(borrowing aufs1 HOW-TO from a user, Michael Towers)
1249+When you have three branches,
1250+- Bottom: 'system', squashfs (underlying base system), read-only
1251+- Middle: 'mods', squashfs, read-only
1252+- Top: 'overlay', ram (tmpfs), read-write
1253+
1254+The top layer is loaded at boot time and saved at shutdown, to preserve
1255+the changes made to the system during the session.
1256+When larger changes have been made, or smaller changes have accumulated,
1257+the size of the saved top layer data grows. At this point, it would be
1258+nice to be able to merge the two overlay branches ('mods' and 'overlay')
1259+and rewrite the 'mods' squashfs, clearing the top layer and thus
1260+restoring save and load speed.
1261+
1262+This merging is simplified by the use of another aufs mount, of just the
1263+two overlay branches using the 'shwh' option.
1264+# mount -t aufs -o ro,shwh,br:/livesys/overlay=ro+wh:/livesys/mods=rr+wh \
1265+ aufs /livesys/merge_union
1266+
1267+A merged view of these two branches is then available at
1268+/livesys/merge_union, and the new feature is that the whiteouts are
1269+visible!
1270+Note that in 'shwh' mode the aufs mount must be 'ro', which will disable
1271+writing to all branches. Also the default mode for all branches is 'ro'.
1272+It is now possible to save the combined contents of the two overlay
1273+branches to a new squashfs, e.g.:
1274+# mksquashfs /livesys/merge_union /path/to/newmods.squash
1275+
1276+This new squashfs archive can be stored on the boot device and the
1277+initramfs will use it to replace the old one at the next boot.
1278diff -urN /usr/share/empty/Documentation/filesystems/aufs/design/10dynop.txt linux/Documentation/filesystems/aufs/design/10dynop.txt
1279--- /usr/share/empty/Documentation/filesystems/aufs/design/10dynop.txt 1970-01-01 01:00:00.000000000 +0100
537831f9 1280+++ linux/Documentation/filesystems/aufs/design/10dynop.txt 2012-12-13 20:41:10.428126759 +0100
53392da6
AM
1281@@ -0,0 +1,47 @@
1282+
1283+# Copyright (C) 2010-2011 Junjiro R. Okajima
1284+#
1285+# This program is free software; you can redistribute it and/or modify
1286+# it under the terms of the GNU General Public License as published by
1287+# the Free Software Foundation; either version 2 of the License, or
1288+# (at your option) any later version.
1289+#
1290+# This program is distributed in the hope that it will be useful,
1291+# but WITHOUT ANY WARRANTY; without even the implied warranty of
1292+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1293+# GNU General Public License for more details.
1294+#
1295+# You should have received a copy of the GNU General Public License
1296+# along with this program; if not, write to the Free Software
1297+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1298+
1299+Dynamically customizable FS operations
1300+----------------------------------------------------------------------
1301+Generally FS operations (struct inode_operations, struct
1302+address_space_operations, struct file_operations, etc.) are defined as
1303+"static const", but it never means that FS have only one set of
1304+operation. Some FS have multiple sets of them. For instance, ext2 has
1305+three sets, one for XIP, for NOBH, and for normal.
1306+Since aufs overrides and redirects these operations, sometimes aufs has
1307+to change its behaviour according to the branch FS type. More imporantly
1308+VFS acts differently if a function (member in the struct) is set or
1309+not. It means aufs should have several sets of operations and select one
1310+among them according to the branch FS definition.
1311+
1312+In order to solve this problem and not to affect the behavour of VFS,
1313+aufs defines these operations dynamically. For instance, aufs defines
1314+aio_read function for struct file_operations, but it may not be set to
1315+the file_operations. When the branch FS doesn't have it, aufs doesn't
1316+set it to its file_operations while the function definition itself is
1317+still alive. So the behaviour of io_submit(2) will not change, and it
1318+will return an error when aio_read is not defined.
1319+
1320+The lifetime of these dynamically generated operation object is
1321+maintained by aufs branch object. When the branch is removed from aufs,
1322+the reference counter of the object is decremented. When it reaches
1323+zero, the dynamically generated operation object will be freed.
1324+
1325+This approach is designed to support AIO (io_submit), Direcit I/O and
1326+XIP mainly.
1327+Currently this approach is applied to file_operations and
1328+vm_operations_struct for regular files only.
1329diff -urN /usr/share/empty/Documentation/filesystems/aufs/design/99plan.txt linux/Documentation/filesystems/aufs/design/99plan.txt
1330--- /usr/share/empty/Documentation/filesystems/aufs/design/99plan.txt 1970-01-01 01:00:00.000000000 +0100
537831f9 1331+++ linux/Documentation/filesystems/aufs/design/99plan.txt 2012-12-13 20:41:10.428126759 +0100
53392da6
AM
1332@@ -0,0 +1,96 @@
1333+
1334+# Copyright (C) 2005-2011 Junjiro R. Okajima
1335+#
1336+# This program is free software; you can redistribute it and/or modify
1337+# it under the terms of the GNU General Public License as published by
1338+# the Free Software Foundation; either version 2 of the License, or
1339+# (at your option) any later version.
1340+#
1341+# This program is distributed in the hope that it will be useful,
1342+# but WITHOUT ANY WARRANTY; without even the implied warranty of
1343+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1344+# GNU General Public License for more details.
1345+#
1346+# You should have received a copy of the GNU General Public License
1347+# along with this program; if not, write to the Free Software
1348+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1349+
1350+Plan
1351+
1352+Restoring some features which was implemented in aufs1.
1353+They were dropped in aufs2 in order to make source files simpler and
1354+easier to be reviewed.
1355+
1356+
1357+Test Only the Highest One for the Directory Permission (dirperm1 option)
1358+----------------------------------------------------------------------
1359+Let's try case study.
1360+- aufs has two branches, upper readwrite and lower readonly.
1361+ /au = /rw + /ro
1362+- "dirA" exists under /ro, but /rw. and its mode is 0700.
1363+- user invoked "chmod a+rx /au/dirA"
1364+- then "dirA" becomes world readable?
1365+
1366+In this case, /ro/dirA is still 0700 since it exists in readonly branch,
1367+or it may be a natively readonly filesystem. If aufs respects the lower
1368+branch, it should not respond readdir request from other users. But user
1369+allowed it by chmod. Should really aufs rejects showing the entries
1370+under /ro/dirA?
1371+
1372+To be honest, I don't have a best solution for this case. So I
1373+implemented 'dirperm1' and 'nodirperm1' option in aufs1, and leave it to
1374+users.
1375+When dirperm1 is specified, aufs checks only the highest one for the
1376+directory permission, and shows the entries. Otherwise, as usual, checks
1377+every dir existing on all branches and rejects the request.
1378+
1379+As a side effect, dirperm1 option improves the performance of aufs
1380+because the number of permission check is reduced.
1381+
1382+
1383+Being Another Aufs's Readonly Branch (robr)
1384+----------------------------------------------------------------------
1385+Aufs1 allows aufs to be another aufs's readonly branch.
1386+This feature was developed by a user's request. But it may not be used
1387+currecnly.
1388+
1389+
1390+Copy-up on Open (coo=)
1391+----------------------------------------------------------------------
1392+By default the internal copy-up is executed when it is really necessary.
1393+It is not done when a file is opened for writing, but when write(2) is
1394+done. Users who have many (over 100) branches want to know and analyse
1395+when and what file is copied-up. To insert a new upper branch which
1396+contains such files only may improve the performance of aufs.
1397+
1398+Aufs1 implemented "coo=none | leaf | all" option.
1399+
1400+
1401+Refresh the Opened File (refrof)
1402+----------------------------------------------------------------------
1403+This option is implemented in aufs1 but incomplete.
1404+
1405+When user reads from a file, he expects to get its latest filedata
1406+generally. If the file is removed and a new same named file is created,
1407+the content he gets is unchanged, ie. the unlinked filedata.
1408+
1409+Let's try case study again.
1410+- aufs has two branches.
1411+ /au = /rw + /ro
1412+- "fileA" exists under /ro, but /rw.
1413+- user opened "/au/fileA".
1414+- he or someone else inserts a branch (/new) between /rw and /ro.
1415+ /au = /rw + /new + /ro
1416+- the new branch has "fileA".
1417+- user reads from the opened "fileA"
1418+- which filedata should aufs return, from /ro or /new?
1419+
1420+Some people says it has to be "from /ro" and it is a semantics of Unix.
1421+The others say it should be "from /new" because the file is not removed
1422+and it is equivalent to the case of someone else modifies the file.
1423+
1424+Here again I don't have a best and final answer. I got an idea to
1425+implement 'refrof' and 'norefrof' option. When 'refrof' (REFResh the
1426+Opened File) is specified (by default), aufs returns the filedata from
1427+/new.
1428+Otherwise from /new.
1429diff -urN /usr/share/empty/Documentation/filesystems/aufs/README linux/Documentation/filesystems/aufs/README
1430--- /usr/share/empty/Documentation/filesystems/aufs/README 1970-01-01 01:00:00.000000000 +0100
537831f9
AM
1431+++ linux/Documentation/filesystems/aufs/README 2012-12-13 20:41:10.424793346 +0100
1432@@ -0,0 +1,333 @@
53392da6
AM
1433+
1434+Aufs3 -- advanced multi layered unification filesystem version 3.x
1435+http://aufs.sf.net
1436+Junjiro R. Okajima
1437+
1438+
1439+0. Introduction
1440+----------------------------------------
1441+In the early days, aufs was entirely re-designed and re-implemented
1442+Unionfs Version 1.x series. After many original ideas, approaches,
1443+improvements and implementations, it becomes totally different from
1444+Unionfs while keeping the basic features.
1445+Recently, Unionfs Version 2.x series begin taking some of the same
1446+approaches to aufs1's.
1447+Unionfs is being developed by Professor Erez Zadok at Stony Brook
1448+University and his team.
1449+
1450+Aufs3 supports linux-3.0 and later.
1451+If you want older kernel version support, try aufs2-2.6.git or
1452+aufs2-standalone.git repository, aufs1 from CVS on SourceForge.
1453+
1454+Note: it becomes clear that "Aufs was rejected. Let's give it up."
1455+According to Christoph Hellwig, linux rejects all union-type filesystems
1456+but UnionMount.
1457+<http://marc.info/?l=linux-kernel&m=123938533724484&w=2>
1458+
1459+
1460+1. Features
1461+----------------------------------------
1462+- unite several directories into a single virtual filesystem. The member
1463+ directory is called as a branch.
1464+- you can specify the permission flags to the branch, which are 'readonly',
1465+ 'readwrite' and 'whiteout-able.'
1466+- by upper writable branch, internal copyup and whiteout, files/dirs on
1467+ readonly branch are modifiable logically.
1468+- dynamic branch manipulation, add, del.
1469+- etc...
1470+
1471+Also there are many enhancements in aufs1, such as:
1472+- readdir(3) in userspace.
1473+- keep inode number by external inode number table
1474+- keep the timestamps of file/dir in internal copyup operation
1475+- seekable directory, supporting NFS readdir.
1476+- whiteout is hardlinked in order to reduce the consumption of inodes
1477+ on branch
1478+- do not copyup, nor create a whiteout when it is unnecessary
1479+- revert a single systemcall when an error occurs in aufs
1480+- remount interface instead of ioctl
1481+- maintain /etc/mtab by an external command, /sbin/mount.aufs.
1482+- loopback mounted filesystem as a branch
1483+- kernel thread for removing the dir who has a plenty of whiteouts
1484+- support copyup sparse file (a file which has a 'hole' in it)
1485+- default permission flags for branches
1486+- selectable permission flags for ro branch, whether whiteout can
1487+ exist or not
1488+- export via NFS.
1489+- support <sysfs>/fs/aufs and <debugfs>/aufs.
1490+- support multiple writable branches, some policies to select one
1491+ among multiple writable branches.
1492+- a new semantics for link(2) and rename(2) to support multiple
1493+ writable branches.
1494+- no glibc changes are required.
1495+- pseudo hardlink (hardlink over branches)
1496+- allow a direct access manually to a file on branch, e.g. bypassing aufs.
1497+ including NFS or remote filesystem branch.
1498+- userspace wrapper for pathconf(3)/fpathconf(3) with _PC_LINK_MAX.
1499+- and more...
1500+
1501+Currently these features are dropped temporary from aufs3.
1502+See design/08plan.txt in detail.
1503+- test only the highest one for the directory permission (dirperm1)
1504+- copyup on open (coo=)
1505+- nested mount, i.e. aufs as readonly no-whiteout branch of another aufs
1506+ (robr)
1507+- statistics of aufs thread (/sys/fs/aufs/stat)
1508+- delegation mode (dlgt)
1509+ a delegation of the internal branch access to support task I/O
1510+ accounting, which also supports Linux Security Modules (LSM) mainly
1511+ for Suse AppArmor.
1512+- intent.open/create (file open in a single lookup)
1513+
1514+Features or just an idea in the future (see also design/*.txt),
1515+- reorder the branch index without del/re-add.
1516+- permanent xino files for NFSD
1517+- an option for refreshing the opened files after add/del branches
1518+- 'move' policy for copy-up between two writable branches, after
1519+ checking free space.
1520+- light version, without branch manipulation. (unnecessary?)
1521+- copyup in userspace
1522+- inotify in userspace
1523+- readv/writev
1524+- xattr, acl
1525+
1526+
1527+2. Download
1528+----------------------------------------
1e00d052
AM
1529+There were three GIT trees for aufs3, aufs3-linux.git,
1530+aufs3-standalone.git, and aufs-util.git. Note that there is no "3" in
1531+"aufs-util.git."
1532+While the aufs-util is always necessary, you need either of aufs3-linux
1533+or aufs3-standalone.
1534+
1535+The aufs3-linux tree includes the whole linux mainline GIT tree,
1536+git://git.kernel.org/.../torvalds/linux.git.
1537+And you cannot select CONFIG_AUFS_FS=m for this version, eg. you cannot
b4510431 1538+build aufs3 as an external kernel module.
1e00d052
AM
1539+
1540+On the other hand, the aufs3-standalone tree has only aufs source files
53392da6
AM
1541+and necessary patches, and you can select CONFIG_AUFS_FS=m.
1542+
1543+You will find GIT branches whose name is in form of "aufs3.x" where "x"
1544+represents the linux kernel version, "linux-3.x". For instance,
1e00d052
AM
1545+"aufs3.0" is for linux-3.0. For latest "linux-3.x-rcN", use
1546+"aufs3.x-rcN" branch.
1547+
1548+o aufs3-linux tree
1549+$ git clone --reference /your/linux/git/tree \
1550+ git://aufs.git.sourceforge.net/gitroot/aufs/aufs3-linux.git \
1551+ aufs3-linux.git
1552+- if you don't have linux GIT tree, then remove "--reference ..."
1553+$ cd aufs3-linux.git
1554+$ git checkout origin/aufs3.0
53392da6
AM
1555+
1556+o aufs3-standalone tree
1557+$ git clone git://aufs.git.sourceforge.net/gitroot/aufs/aufs3-standalone.git \
1558+ aufs3-standalone.git
1559+$ cd aufs3-standalone.git
1560+$ git checkout origin/aufs3.0
1561+
1562+o aufs-util tree
1563+$ git clone git://aufs.git.sourceforge.net/gitroot/aufs/aufs-util.git \
1564+ aufs-util.git
1565+$ cd aufs-util.git
1566+$ git checkout origin/aufs3.0
1567+
9dbd164d
AM
1568+Note: The 3.x-rcN branch is to be used with `rc' kernel versions ONLY.
1569+The minor version number, 'x' in '3.x', of aufs may not always
1570+follow the minor version number of the kernel.
1571+Because changes in the kernel that cause the use of a new
1572+minor version number do not always require changes to aufs-util.
1573+
1574+Since aufs-util has its own minor version number, you may not be
1575+able to find a GIT branch in aufs-util for your kernel's
1576+exact minor version number.
1577+In this case, you should git-checkout the branch for the
53392da6 1578+nearest lower number.
9dbd164d
AM
1579+
1580+For (an unreleased) example:
1581+If you are using "linux-3.10" and the "aufs3.10" branch
7eafdf33 1582+does not exist in aufs-util repository, then "aufs3.9", "aufs3.8"
9dbd164d
AM
1583+or something numerically smaller is the branch for your kernel.
1584+
53392da6
AM
1585+Also you can view all branches by
1586+ $ git branch -a
1587+
1588+
1589+3. Configuration and Compilation
1590+----------------------------------------
1591+Make sure you have git-checkout'ed the correct branch.
1592+
1e00d052
AM
1593+For aufs3-linux tree,
1594+- enable CONFIG_EXPERIMENTAL and CONFIG_AUFS_FS.
1595+- set other aufs configurations if necessary.
1596+
53392da6
AM
1597+For aufs3-standalone tree,
1598+There are several ways to build.
1599+
1600+1.
1601+- apply ./aufs3-kbuild.patch to your kernel source files.
1602+- apply ./aufs3-base.patch too.
1603+- apply ./aufs3-proc_map.patch too, if you want to make /proc/PID/maps (and
1604+ others including lsof(1)) show the file path on aufs instead of the
1605+ path on the branch fs.
1606+- apply ./aufs3-standalone.patch too, if you have a plan to set
1607+ CONFIG_AUFS_FS=m. otherwise you don't need ./aufs3-standalone.patch.
537831f9
AM
1608+- copy ./{Documentation,fs,include/uapi/linux/aufs_type.h} files to your
1609+ kernel source tree. Never copy $PWD/include/uapi/linux/Kbuild.
53392da6
AM
1610+- enable CONFIG_EXPERIMENTAL and CONFIG_AUFS_FS, you can select either
1611+ =m or =y.
1612+- and build your kernel as usual.
1613+- install the built kernel.
7eafdf33
AM
1614+- install the header files too by "make headers_install" to the
1615+ directory where you specify. By default, it is $PWD/usr.
b4510431 1616+ "make help" shows a brief note for headers_install.
53392da6
AM
1617+- and reboot your system.
1618+
1619+2.
1620+- module only (CONFIG_AUFS_FS=m).
1621+- apply ./aufs3-base.patch to your kernel source files.
1622+- apply ./aufs3-proc_map.patch too to your kernel source files,
1623+ if you want to make /proc/PID/maps (and others including lsof(1)) show
1624+ the file path on aufs instead of the path on the branch fs.
1625+- apply ./aufs3-standalone.patch too.
1626+- build your kernel, don't forget "make headers_install", and reboot.
1627+- edit ./config.mk and set other aufs configurations if necessary.
b4510431 1628+ Note: You should read $PWD/fs/aufs/Kconfig carefully which describes
53392da6
AM
1629+ every aufs configurations.
1630+- build the module by simple "make".
1631+- you can specify ${KDIR} make variable which points to your kernel
1632+ source tree.
1633+- install the files
1634+ + run "make install" to install the aufs module, or copy the built
b4510431
AM
1635+ $PWD/aufs.ko to /lib/modules/... and run depmod -a (or reboot simply).
1636+ + run "make install_headers" (instead of headers_install) to install
1637+ the modified aufs header file (you can specify DESTDIR which is
1638+ available in aufs standalone version's Makefile only), or copy
1639+ $PWD/usr/include/linux/aufs_type.h to /usr/include/linux or wherever
1640+ you like manually. By default, the target directory is $PWD/usr.
53392da6
AM
1641+- no need to apply aufs3-kbuild.patch, nor copying source files to your
1642+ kernel source tree.
1643+
b4510431 1644+Note: The header file aufs_type.h is necessary to build aufs-util
53392da6
AM
1645+ as well as "make headers_install" in the kernel source tree.
1646+ headers_install is subject to be forgotten, but it is essentially
1647+ necessary, not only for building aufs-util.
1648+ You may not meet problems without headers_install in some older
1649+ version though.
1650+
1651+And then,
1652+- read README in aufs-util, build and install it
9dbd164d
AM
1653+- note that your distribution may contain an obsoleted version of
1654+ aufs_type.h in /usr/include/linux or something. When you build aufs
1655+ utilities, make sure that your compiler refers the correct aufs header
1656+ file which is built by "make headers_install."
53392da6
AM
1657+- if you want to use readdir(3) in userspace or pathconf(3) wrapper,
1658+ then run "make install_ulib" too. And refer to the aufs manual in
1659+ detail.
1660+
1661+
1662+4. Usage
1663+----------------------------------------
1664+At first, make sure aufs-util are installed, and please read the aufs
1665+manual, aufs.5 in aufs-util.git tree.
1666+$ man -l aufs.5
1667+
1668+And then,
1669+$ mkdir /tmp/rw /tmp/aufs
1670+# mount -t aufs -o br=/tmp/rw:${HOME} none /tmp/aufs
1671+
1672+Here is another example. The result is equivalent.
1673+# mount -t aufs -o br=/tmp/rw=rw:${HOME}=ro none /tmp/aufs
1674+ Or
1675+# mount -t aufs -o br:/tmp/rw none /tmp/aufs
1676+# mount -o remount,append:${HOME} /tmp/aufs
1677+
1678+Then, you can see whole tree of your home dir through /tmp/aufs. If
1679+you modify a file under /tmp/aufs, the one on your home directory is
1680+not affected, instead the same named file will be newly created under
1681+/tmp/rw. And all of your modification to a file will be applied to
1682+the one under /tmp/rw. This is called the file based Copy on Write
1683+(COW) method.
1684+Aufs mount options are described in aufs.5.
1685+If you run chroot or something and make your aufs as a root directory,
1686+then you need to customize the shutdown script. See the aufs manual in
1687+detail.
1688+
1689+Additionally, there are some sample usages of aufs which are a
1690+diskless system with network booting, and LiveCD over NFS.
1691+See sample dir in CVS tree on SourceForge.
1692+
1693+
1694+5. Contact
1695+----------------------------------------
1696+When you have any problems or strange behaviour in aufs, please let me
1697+know with:
1698+- /proc/mounts (instead of the output of mount(8))
1699+- /sys/module/aufs/*
1700+- /sys/fs/aufs/* (if you have them)
1701+- /debug/aufs/* (if you have them)
1702+- linux kernel version
1703+ if your kernel is not plain, for example modified by distributor,
1704+ the url where i can download its source is necessary too.
1705+- aufs version which was printed at loading the module or booting the
1706+ system, instead of the date you downloaded.
1707+- configuration (define/undefine CONFIG_AUFS_xxx)
1708+- kernel configuration or /proc/config.gz (if you have it)
1709+- behaviour which you think to be incorrect
1710+- actual operation, reproducible one is better
1711+- mailto: aufs-users at lists.sourceforge.net
1712+
1713+Usually, I don't watch the Public Areas(Bugs, Support Requests, Patches,
1714+and Feature Requests) on SourceForge. Please join and write to
1715+aufs-users ML.
1716+
1717+
1718+6. Acknowledgements
1719+----------------------------------------
1720+Thanks to everyone who have tried and are using aufs, whoever
1721+have reported a bug or any feedback.
1722+
1723+Especially donators:
1724+Tomas Matejicek(slax.org) made a donation (much more than once).
1725+ Since Apr 2010, Tomas M (the author of Slax and Linux Live
1726+ scripts) is making "doubling" donations.
1727+ Unfortunately I cannot list all of the donators, but I really
b4510431 1728+ appreciate.
53392da6
AM
1729+ It ends Aug 2010, but the ordinary donation URL is still available.
1730+ <http://sourceforge.net/donate/index.php?group_id=167503>
1731+Dai Itasaka made a donation (2007/8).
1732+Chuck Smith made a donation (2008/4, 10 and 12).
1733+Henk Schoneveld made a donation (2008/9).
1734+Chih-Wei Huang, ASUS, CTC donated Eee PC 4G (2008/10).
1735+Francois Dupoux made a donation (2008/11).
1736+Bruno Cesar Ribas and Luis Carlos Erpen de Bona, C3SL serves public
1737+ aufs2 GIT tree (2009/2).
1738+William Grant made a donation (2009/3).
1739+Patrick Lane made a donation (2009/4).
1740+The Mail Archive (mail-archive.com) made donations (2009/5).
1741+Nippy Networks (Ed Wildgoose) made a donation (2009/7).
1742+New Dream Network, LLC (www.dreamhost.com) made a donation (2009/11).
1743+Pavel Pronskiy made a donation (2011/2).
1744+Iridium and Inmarsat satellite phone retailer (www.mailasail.com), Nippy
1745+ Networks (Ed Wildgoose) made a donation for hardware (2011/3).
537831f9
AM
1746+Max Lekomcev (DOM-TV project) made a donation (2011/7, 12, 2012/3, 6 and
1747+11).
1e00d052 1748+Sam Liddicott made a donation (2011/9).
53392da6
AM
1749+
1750+Thank you very much.
1751+Donations are always, including future donations, very important and
1752+helpful for me to keep on developing aufs.
1753+
1754+
1755+7.
1756+----------------------------------------
1757+If you are an experienced user, no explanation is needed. Aufs is
1758+just a linux filesystem.
1759+
1760+
1761+Enjoy!
1762+
1763+# Local variables: ;
1764+# mode: text;
1765+# End: ;
7f207e10
AM
1766diff -urN /usr/share/empty/fs/aufs/aufs.h linux/fs/aufs/aufs.h
1767--- /usr/share/empty/fs/aufs/aufs.h 1970-01-01 01:00:00.000000000 +0100
537831f9 1768+++ linux/fs/aufs/aufs.h 2012-12-13 20:41:10.428126759 +0100
2cbb1c4b 1769@@ -0,0 +1,60 @@
7f207e10 1770+/*
f6c5ef8b 1771+ * Copyright (C) 2005-2012 Junjiro R. Okajima
7f207e10
AM
1772+ *
1773+ * This program, aufs is free software; you can redistribute it and/or modify
1774+ * it under the terms of the GNU General Public License as published by
1775+ * the Free Software Foundation; either version 2 of the License, or
1776+ * (at your option) any later version.
1777+ *
1778+ * This program is distributed in the hope that it will be useful,
1779+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1780+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1781+ * GNU General Public License for more details.
1782+ *
1783+ * You should have received a copy of the GNU General Public License
1784+ * along with this program; if not, write to the Free Software
1785+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1786+ */
1787+
1788+/*
1789+ * all header files
1790+ */
1791+
1792+#ifndef __AUFS_H__
1793+#define __AUFS_H__
1794+
1795+#ifdef __KERNEL__
1796+
1797+#define AuStub(type, name, body, ...) \
1798+ static inline type name(__VA_ARGS__) { body; }
1799+
1800+#define AuStubVoid(name, ...) \
1801+ AuStub(void, name, , __VA_ARGS__)
1802+#define AuStubInt0(name, ...) \
1803+ AuStub(int, name, return 0, __VA_ARGS__)
1804+
1805+#include "debug.h"
1806+
1807+#include "branch.h"
1808+#include "cpup.h"
1809+#include "dcsub.h"
1810+#include "dbgaufs.h"
1811+#include "dentry.h"
1812+#include "dir.h"
1813+#include "dynop.h"
1814+#include "file.h"
1815+#include "fstype.h"
1816+#include "inode.h"
1817+#include "loop.h"
1818+#include "module.h"
7f207e10
AM
1819+#include "opts.h"
1820+#include "rwsem.h"
1821+#include "spl.h"
1822+#include "super.h"
1823+#include "sysaufs.h"
1824+#include "vfsub.h"
1825+#include "whout.h"
1826+#include "wkq.h"
1827+
1828+#endif /* __KERNEL__ */
1829+#endif /* __AUFS_H__ */
1830diff -urN /usr/share/empty/fs/aufs/branch.c linux/fs/aufs/branch.c
1831--- /usr/share/empty/fs/aufs/branch.c 1970-01-01 01:00:00.000000000 +0100
537831f9
AM
1832+++ linux/fs/aufs/branch.c 2012-12-13 20:41:10.428126759 +0100
1833@@ -0,0 +1,1172 @@
7f207e10 1834+/*
f6c5ef8b 1835+ * Copyright (C) 2005-2012 Junjiro R. Okajima
7f207e10
AM
1836+ *
1837+ * This program, aufs is free software; you can redistribute it and/or modify
1838+ * it under the terms of the GNU General Public License as published by
1839+ * the Free Software Foundation; either version 2 of the License, or
1840+ * (at your option) any later version.
1841+ *
1842+ * This program is distributed in the hope that it will be useful,
1843+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1844+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1845+ * GNU General Public License for more details.
1846+ *
1847+ * You should have received a copy of the GNU General Public License
1848+ * along with this program; if not, write to the Free Software
1849+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1850+ */
1851+
1852+/*
1853+ * branch management
1854+ */
1855+
027c5e7a 1856+#include <linux/compat.h>
7f207e10
AM
1857+#include <linux/statfs.h>
1858+#include "aufs.h"
1859+
1860+/*
1861+ * free a single branch
1facf9fc 1862+ */
1863+static void au_br_do_free(struct au_branch *br)
1864+{
1865+ int i;
1866+ struct au_wbr *wbr;
4a4d8108 1867+ struct au_dykey **key;
1facf9fc 1868+
027c5e7a
AM
1869+ au_hnotify_fin_br(br);
1870+
1facf9fc 1871+ if (br->br_xino.xi_file)
1872+ fput(br->br_xino.xi_file);
1873+ mutex_destroy(&br->br_xino.xi_nondir_mtx);
1874+
1875+ AuDebugOn(atomic_read(&br->br_count));
1876+
1877+ wbr = br->br_wbr;
1878+ if (wbr) {
1879+ for (i = 0; i < AuBrWh_Last; i++)
1880+ dput(wbr->wbr_wh[i]);
1881+ AuDebugOn(atomic_read(&wbr->wbr_wh_running));
dece6358 1882+ AuRwDestroy(&wbr->wbr_wh_rwsem);
1facf9fc 1883+ }
1884+
4a4d8108
AM
1885+ key = br->br_dykey;
1886+ for (i = 0; i < AuBrDynOp; i++, key++)
1887+ if (*key)
1888+ au_dy_put(*key);
1889+ else
1890+ break;
1891+
537831f9
AM
1892+ /* recursive lock, s_umount of branch's */
1893+ lockdep_off();
1facf9fc 1894+ mntput(br->br_mnt);
537831f9 1895+ lockdep_on();
1facf9fc 1896+ kfree(wbr);
1897+ kfree(br);
1898+}
1899+
1900+/*
1901+ * frees all branches
1902+ */
1903+void au_br_free(struct au_sbinfo *sbinfo)
1904+{
1905+ aufs_bindex_t bmax;
1906+ struct au_branch **br;
1907+
dece6358
AM
1908+ AuRwMustWriteLock(&sbinfo->si_rwsem);
1909+
1facf9fc 1910+ bmax = sbinfo->si_bend + 1;
1911+ br = sbinfo->si_branch;
1912+ while (bmax--)
1913+ au_br_do_free(*br++);
1914+}
1915+
1916+/*
1917+ * find the index of a branch which is specified by @br_id.
1918+ */
1919+int au_br_index(struct super_block *sb, aufs_bindex_t br_id)
1920+{
1921+ aufs_bindex_t bindex, bend;
1922+
1923+ bend = au_sbend(sb);
1924+ for (bindex = 0; bindex <= bend; bindex++)
1925+ if (au_sbr_id(sb, bindex) == br_id)
1926+ return bindex;
1927+ return -1;
1928+}
1929+
1930+/* ---------------------------------------------------------------------- */
1931+
1932+/*
1933+ * add a branch
1934+ */
1935+
b752ccd1
AM
1936+static int test_overlap(struct super_block *sb, struct dentry *h_adding,
1937+ struct dentry *h_root)
1facf9fc 1938+{
b752ccd1
AM
1939+ if (unlikely(h_adding == h_root
1940+ || au_test_loopback_overlap(sb, h_adding)))
1facf9fc 1941+ return 1;
b752ccd1
AM
1942+ if (h_adding->d_sb != h_root->d_sb)
1943+ return 0;
1944+ return au_test_subdir(h_adding, h_root)
1945+ || au_test_subdir(h_root, h_adding);
1facf9fc 1946+}
1947+
1948+/*
1949+ * returns a newly allocated branch. @new_nbranch is a number of branches
1950+ * after adding a branch.
1951+ */
1952+static struct au_branch *au_br_alloc(struct super_block *sb, int new_nbranch,
1953+ int perm)
1954+{
1955+ struct au_branch *add_branch;
1956+ struct dentry *root;
4a4d8108 1957+ int err;
1facf9fc 1958+
4a4d8108 1959+ err = -ENOMEM;
1facf9fc 1960+ root = sb->s_root;
1961+ add_branch = kmalloc(sizeof(*add_branch), GFP_NOFS);
1962+ if (unlikely(!add_branch))
1963+ goto out;
1964+
027c5e7a
AM
1965+ err = au_hnotify_init_br(add_branch, perm);
1966+ if (unlikely(err))
1967+ goto out_br;
1968+
1facf9fc 1969+ add_branch->br_wbr = NULL;
1970+ if (au_br_writable(perm)) {
1971+ /* may be freed separately at changing the branch permission */
1972+ add_branch->br_wbr = kmalloc(sizeof(*add_branch->br_wbr),
1973+ GFP_NOFS);
1974+ if (unlikely(!add_branch->br_wbr))
027c5e7a 1975+ goto out_hnotify;
1facf9fc 1976+ }
1977+
4a4d8108
AM
1978+ err = au_sbr_realloc(au_sbi(sb), new_nbranch);
1979+ if (!err)
1980+ err = au_di_realloc(au_di(root), new_nbranch);
1981+ if (!err)
1982+ err = au_ii_realloc(au_ii(root->d_inode), new_nbranch);
1983+ if (!err)
1984+ return add_branch; /* success */
1facf9fc 1985+
1facf9fc 1986+ kfree(add_branch->br_wbr);
4a4d8108 1987+
027c5e7a
AM
1988+out_hnotify:
1989+ au_hnotify_fin_br(add_branch);
4f0767ce 1990+out_br:
1facf9fc 1991+ kfree(add_branch);
4f0767ce 1992+out:
4a4d8108 1993+ return ERR_PTR(err);
1facf9fc 1994+}
1995+
1996+/*
1997+ * test if the branch permission is legal or not.
1998+ */
1999+static int test_br(struct inode *inode, int brperm, char *path)
2000+{
2001+ int err;
2002+
4a4d8108
AM
2003+ err = (au_br_writable(brperm) && IS_RDONLY(inode));
2004+ if (!err)
2005+ goto out;
1facf9fc 2006+
4a4d8108
AM
2007+ err = -EINVAL;
2008+ pr_err("write permission for readonly mount or inode, %s\n", path);
2009+
4f0767ce 2010+out:
1facf9fc 2011+ return err;
2012+}
2013+
2014+/*
2015+ * returns:
2016+ * 0: success, the caller will add it
2017+ * plus: success, it is already unified, the caller should ignore it
2018+ * minus: error
2019+ */
2020+static int test_add(struct super_block *sb, struct au_opt_add *add, int remount)
2021+{
2022+ int err;
2023+ aufs_bindex_t bend, bindex;
2024+ struct dentry *root;
2025+ struct inode *inode, *h_inode;
2026+
2027+ root = sb->s_root;
2028+ bend = au_sbend(sb);
2029+ if (unlikely(bend >= 0
2030+ && au_find_dbindex(root, add->path.dentry) >= 0)) {
2031+ err = 1;
2032+ if (!remount) {
2033+ err = -EINVAL;
4a4d8108 2034+ pr_err("%s duplicated\n", add->pathname);
1facf9fc 2035+ }
2036+ goto out;
2037+ }
2038+
2039+ err = -ENOSPC; /* -E2BIG; */
2040+ if (unlikely(AUFS_BRANCH_MAX <= add->bindex
2041+ || AUFS_BRANCH_MAX - 1 <= bend)) {
4a4d8108 2042+ pr_err("number of branches exceeded %s\n", add->pathname);
1facf9fc 2043+ goto out;
2044+ }
2045+
2046+ err = -EDOM;
2047+ if (unlikely(add->bindex < 0 || bend + 1 < add->bindex)) {
4a4d8108 2048+ pr_err("bad index %d\n", add->bindex);
1facf9fc 2049+ goto out;
2050+ }
2051+
2052+ inode = add->path.dentry->d_inode;
2053+ err = -ENOENT;
2054+ if (unlikely(!inode->i_nlink)) {
4a4d8108 2055+ pr_err("no existence %s\n", add->pathname);
1facf9fc 2056+ goto out;
2057+ }
2058+
2059+ err = -EINVAL;
2060+ if (unlikely(inode->i_sb == sb)) {
4a4d8108 2061+ pr_err("%s must be outside\n", add->pathname);
1facf9fc 2062+ goto out;
2063+ }
2064+
2065+ if (unlikely(au_test_fs_unsuppoted(inode->i_sb))) {
4a4d8108
AM
2066+ pr_err("unsupported filesystem, %s (%s)\n",
2067+ add->pathname, au_sbtype(inode->i_sb));
1facf9fc 2068+ goto out;
2069+ }
2070+
2071+ err = test_br(add->path.dentry->d_inode, add->perm, add->pathname);
2072+ if (unlikely(err))
2073+ goto out;
2074+
2075+ if (bend < 0)
2076+ return 0; /* success */
2077+
2078+ err = -EINVAL;
2079+ for (bindex = 0; bindex <= bend; bindex++)
2080+ if (unlikely(test_overlap(sb, add->path.dentry,
2081+ au_h_dptr(root, bindex)))) {
4a4d8108 2082+ pr_err("%s is overlapped\n", add->pathname);
1facf9fc 2083+ goto out;
2084+ }
2085+
2086+ err = 0;
2087+ if (au_opt_test(au_mntflags(sb), WARN_PERM)) {
2088+ h_inode = au_h_dptr(root, 0)->d_inode;
2089+ if ((h_inode->i_mode & S_IALLUGO) != (inode->i_mode & S_IALLUGO)
0c3ec466
AM
2090+ || !uid_eq(h_inode->i_uid, inode->i_uid)
2091+ || !gid_eq(h_inode->i_gid, inode->i_gid))
2092+ pr_warn("uid/gid/perm %s %u/%u/0%o, %u/%u/0%o\n",
2093+ add->pathname,
2094+ i_uid_read(inode), i_gid_read(inode),
2095+ (inode->i_mode & S_IALLUGO),
2096+ i_uid_read(h_inode), i_gid_read(h_inode),
2097+ (h_inode->i_mode & S_IALLUGO));
1facf9fc 2098+ }
2099+
4f0767ce 2100+out:
1facf9fc 2101+ return err;
2102+}
2103+
2104+/*
2105+ * initialize or clean the whiteouts for an adding branch
2106+ */
2107+static int au_br_init_wh(struct super_block *sb, struct au_branch *br,
2108+ int new_perm, struct dentry *h_root)
2109+{
2110+ int err, old_perm;
2111+ aufs_bindex_t bindex;
2112+ struct mutex *h_mtx;
2113+ struct au_wbr *wbr;
2114+ struct au_hinode *hdir;
2115+
2116+ wbr = br->br_wbr;
2117+ old_perm = br->br_perm;
2118+ br->br_perm = new_perm;
2119+ hdir = NULL;
2120+ h_mtx = NULL;
2121+ bindex = au_br_index(sb, br->br_id);
2122+ if (0 <= bindex) {
2123+ hdir = au_hi(sb->s_root->d_inode, bindex);
4a4d8108 2124+ au_hn_imtx_lock_nested(hdir, AuLsc_I_PARENT);
1facf9fc 2125+ } else {
2126+ h_mtx = &h_root->d_inode->i_mutex;
2127+ mutex_lock_nested(h_mtx, AuLsc_I_PARENT);
2128+ }
2129+ if (!wbr)
2130+ err = au_wh_init(h_root, br, sb);
2131+ else {
2132+ wbr_wh_write_lock(wbr);
2133+ err = au_wh_init(h_root, br, sb);
2134+ wbr_wh_write_unlock(wbr);
2135+ }
2136+ if (hdir)
4a4d8108 2137+ au_hn_imtx_unlock(hdir);
1facf9fc 2138+ else
2139+ mutex_unlock(h_mtx);
2140+ br->br_perm = old_perm;
2141+
2142+ if (!err && wbr && !au_br_writable(new_perm)) {
2143+ kfree(wbr);
2144+ br->br_wbr = NULL;
2145+ }
2146+
2147+ return err;
2148+}
2149+
2150+static int au_wbr_init(struct au_branch *br, struct super_block *sb,
2151+ int perm, struct path *path)
2152+{
2153+ int err;
4a4d8108 2154+ struct kstatfs kst;
1facf9fc 2155+ struct au_wbr *wbr;
4a4d8108 2156+ struct dentry *h_dentry;
1facf9fc 2157+
2158+ wbr = br->br_wbr;
dece6358 2159+ au_rw_init(&wbr->wbr_wh_rwsem);
1facf9fc 2160+ memset(wbr->wbr_wh, 0, sizeof(wbr->wbr_wh));
2161+ atomic_set(&wbr->wbr_wh_running, 0);
2162+ wbr->wbr_bytes = 0;
2163+
4a4d8108
AM
2164+ /*
2165+ * a limit for rmdir/rename a dir
2166+ * cf. AUFS_MAX_NAMELEN in include/linux/aufs_type.h
2167+ */
7f207e10 2168+ err = vfs_statfs(path, &kst);
4a4d8108
AM
2169+ if (unlikely(err))
2170+ goto out;
2171+ err = -EINVAL;
7f207e10 2172+ h_dentry = path->dentry;
4a4d8108
AM
2173+ if (kst.f_namelen >= NAME_MAX)
2174+ err = au_br_init_wh(sb, br, perm, h_dentry);
2175+ else
2176+ pr_err("%.*s(%s), unsupported namelen %ld\n",
2177+ AuDLNPair(h_dentry), au_sbtype(h_dentry->d_sb),
2178+ kst.f_namelen);
1facf9fc 2179+
4f0767ce 2180+out:
1facf9fc 2181+ return err;
2182+}
2183+
2184+/* intialize a new branch */
2185+static int au_br_init(struct au_branch *br, struct super_block *sb,
2186+ struct au_opt_add *add)
2187+{
2188+ int err;
2189+
2190+ err = 0;
2191+ memset(&br->br_xino, 0, sizeof(br->br_xino));
2192+ mutex_init(&br->br_xino.xi_nondir_mtx);
2193+ br->br_perm = add->perm;
2194+ br->br_mnt = add->path.mnt; /* set first, mntget() later */
4a4d8108
AM
2195+ spin_lock_init(&br->br_dykey_lock);
2196+ memset(br->br_dykey, 0, sizeof(br->br_dykey));
1facf9fc 2197+ atomic_set(&br->br_count, 0);
2198+ br->br_xino_upper = AUFS_XINO_TRUNC_INIT;
2199+ atomic_set(&br->br_xino_running, 0);
2200+ br->br_id = au_new_br_id(sb);
7f207e10 2201+ AuDebugOn(br->br_id < 0);
1facf9fc 2202+
2203+ if (au_br_writable(add->perm)) {
2204+ err = au_wbr_init(br, sb, add->perm, &add->path);
2205+ if (unlikely(err))
b752ccd1 2206+ goto out_err;
1facf9fc 2207+ }
2208+
2209+ if (au_opt_test(au_mntflags(sb), XINO)) {
2210+ err = au_xino_br(sb, br, add->path.dentry->d_inode->i_ino,
2211+ au_sbr(sb, 0)->br_xino.xi_file, /*do_test*/1);
2212+ if (unlikely(err)) {
2213+ AuDebugOn(br->br_xino.xi_file);
b752ccd1 2214+ goto out_err;
1facf9fc 2215+ }
2216+ }
2217+
2218+ sysaufs_br_init(br);
2219+ mntget(add->path.mnt);
b752ccd1 2220+ goto out; /* success */
1facf9fc 2221+
4f0767ce 2222+out_err:
b752ccd1 2223+ br->br_mnt = NULL;
4f0767ce 2224+out:
1facf9fc 2225+ return err;
2226+}
2227+
2228+static void au_br_do_add_brp(struct au_sbinfo *sbinfo, aufs_bindex_t bindex,
2229+ struct au_branch *br, aufs_bindex_t bend,
2230+ aufs_bindex_t amount)
2231+{
2232+ struct au_branch **brp;
2233+
dece6358
AM
2234+ AuRwMustWriteLock(&sbinfo->si_rwsem);
2235+
1facf9fc 2236+ brp = sbinfo->si_branch + bindex;
2237+ memmove(brp + 1, brp, sizeof(*brp) * amount);
2238+ *brp = br;
2239+ sbinfo->si_bend++;
2240+ if (unlikely(bend < 0))
2241+ sbinfo->si_bend = 0;
2242+}
2243+
2244+static void au_br_do_add_hdp(struct au_dinfo *dinfo, aufs_bindex_t bindex,
2245+ aufs_bindex_t bend, aufs_bindex_t amount)
2246+{
2247+ struct au_hdentry *hdp;
2248+
1308ab2a 2249+ AuRwMustWriteLock(&dinfo->di_rwsem);
2250+
1facf9fc 2251+ hdp = dinfo->di_hdentry + bindex;
2252+ memmove(hdp + 1, hdp, sizeof(*hdp) * amount);
2253+ au_h_dentry_init(hdp);
2254+ dinfo->di_bend++;
2255+ if (unlikely(bend < 0))
2256+ dinfo->di_bstart = 0;
2257+}
2258+
2259+static void au_br_do_add_hip(struct au_iinfo *iinfo, aufs_bindex_t bindex,
2260+ aufs_bindex_t bend, aufs_bindex_t amount)
2261+{
2262+ struct au_hinode *hip;
2263+
1308ab2a 2264+ AuRwMustWriteLock(&iinfo->ii_rwsem);
2265+
1facf9fc 2266+ hip = iinfo->ii_hinode + bindex;
2267+ memmove(hip + 1, hip, sizeof(*hip) * amount);
2268+ hip->hi_inode = NULL;
4a4d8108 2269+ au_hn_init(hip);
1facf9fc 2270+ iinfo->ii_bend++;
2271+ if (unlikely(bend < 0))
2272+ iinfo->ii_bstart = 0;
2273+}
2274+
2275+static void au_br_do_add(struct super_block *sb, struct dentry *h_dentry,
2276+ struct au_branch *br, aufs_bindex_t bindex)
2277+{
2278+ struct dentry *root;
2279+ struct inode *root_inode;
2280+ aufs_bindex_t bend, amount;
2281+
2282+ root = sb->s_root;
2283+ root_inode = root->d_inode;
1facf9fc 2284+ bend = au_sbend(sb);
2285+ amount = bend + 1 - bindex;
53392da6 2286+ au_sbilist_lock();
1facf9fc 2287+ au_br_do_add_brp(au_sbi(sb), bindex, br, bend, amount);
2288+ au_br_do_add_hdp(au_di(root), bindex, bend, amount);
2289+ au_br_do_add_hip(au_ii(root_inode), bindex, bend, amount);
2290+ au_set_h_dptr(root, bindex, dget(h_dentry));
2291+ au_set_h_iptr(root_inode, bindex, au_igrab(h_dentry->d_inode),
2292+ /*flags*/0);
53392da6 2293+ au_sbilist_unlock();
1facf9fc 2294+}
2295+
2296+int au_br_add(struct super_block *sb, struct au_opt_add *add, int remount)
2297+{
2298+ int err;
1facf9fc 2299+ aufs_bindex_t bend, add_bindex;
2300+ struct dentry *root, *h_dentry;
2301+ struct inode *root_inode;
2302+ struct au_branch *add_branch;
2303+
2304+ root = sb->s_root;
2305+ root_inode = root->d_inode;
2306+ IMustLock(root_inode);
2307+ err = test_add(sb, add, remount);
2308+ if (unlikely(err < 0))
2309+ goto out;
2310+ if (err) {
2311+ err = 0;
2312+ goto out; /* success */
2313+ }
2314+
2315+ bend = au_sbend(sb);
2316+ add_branch = au_br_alloc(sb, bend + 2, add->perm);
2317+ err = PTR_ERR(add_branch);
2318+ if (IS_ERR(add_branch))
2319+ goto out;
2320+
2321+ err = au_br_init(add_branch, sb, add);
2322+ if (unlikely(err)) {
2323+ au_br_do_free(add_branch);
2324+ goto out;
2325+ }
2326+
2327+ add_bindex = add->bindex;
2328+ h_dentry = add->path.dentry;
2329+ if (!remount)
2330+ au_br_do_add(sb, h_dentry, add_branch, add_bindex);
2331+ else {
2332+ sysaufs_brs_del(sb, add_bindex);
2333+ au_br_do_add(sb, h_dentry, add_branch, add_bindex);
2334+ sysaufs_brs_add(sb, add_bindex);
2335+ }
2336+
1308ab2a 2337+ if (!add_bindex) {
1facf9fc 2338+ au_cpup_attr_all(root_inode, /*force*/1);
1308ab2a 2339+ sb->s_maxbytes = h_dentry->d_sb->s_maxbytes;
2340+ } else
1facf9fc 2341+ au_add_nlink(root_inode, h_dentry->d_inode);
1facf9fc 2342+
2343+ /*
4a4d8108 2344+ * this test/set prevents aufs from handling unnecesary notify events
027c5e7a 2345+ * of xino files, in case of re-adding a writable branch which was
1facf9fc 2346+ * once detached from aufs.
2347+ */
2348+ if (au_xino_brid(sb) < 0
2349+ && au_br_writable(add_branch->br_perm)
2350+ && !au_test_fs_bad_xino(h_dentry->d_sb)
2351+ && add_branch->br_xino.xi_file
2352+ && add_branch->br_xino.xi_file->f_dentry->d_parent == h_dentry)
2353+ au_xino_brid_set(sb, add_branch->br_id);
2354+
4f0767ce 2355+out:
1facf9fc 2356+ return err;
2357+}
2358+
2359+/* ---------------------------------------------------------------------- */
2360+
2361+/*
2362+ * delete a branch
2363+ */
2364+
2365+/* to show the line number, do not make it inlined function */
4a4d8108 2366+#define AuVerbose(do_info, fmt, ...) do { \
1facf9fc 2367+ if (do_info) \
4a4d8108 2368+ pr_info(fmt, ##__VA_ARGS__); \
1facf9fc 2369+} while (0)
2370+
027c5e7a
AM
2371+static int au_test_ibusy(struct inode *inode, aufs_bindex_t bstart,
2372+ aufs_bindex_t bend)
2373+{
2374+ return (inode && !S_ISDIR(inode->i_mode)) || bstart == bend;
2375+}
2376+
2377+static int au_test_dbusy(struct dentry *dentry, aufs_bindex_t bstart,
2378+ aufs_bindex_t bend)
2379+{
2380+ return au_test_ibusy(dentry->d_inode, bstart, bend);
2381+}
2382+
1facf9fc 2383+/*
2384+ * test if the branch is deletable or not.
2385+ */
2386+static int test_dentry_busy(struct dentry *root, aufs_bindex_t bindex,
b752ccd1 2387+ unsigned int sigen, const unsigned int verbose)
1facf9fc 2388+{
2389+ int err, i, j, ndentry;
2390+ aufs_bindex_t bstart, bend;
1facf9fc 2391+ struct au_dcsub_pages dpages;
2392+ struct au_dpage *dpage;
2393+ struct dentry *d;
1facf9fc 2394+
2395+ err = au_dpages_init(&dpages, GFP_NOFS);
2396+ if (unlikely(err))
2397+ goto out;
2398+ err = au_dcsub_pages(&dpages, root, NULL, NULL);
2399+ if (unlikely(err))
2400+ goto out_dpages;
2401+
1facf9fc 2402+ for (i = 0; !err && i < dpages.ndpage; i++) {
2403+ dpage = dpages.dpages + i;
2404+ ndentry = dpage->ndentry;
2405+ for (j = 0; !err && j < ndentry; j++) {
2406+ d = dpage->dentries[j];
027c5e7a
AM
2407+ AuDebugOn(!d->d_count);
2408+ if (!au_digen_test(d, sigen)) {
1facf9fc 2409+ di_read_lock_child(d, AuLock_IR);
027c5e7a
AM
2410+ if (unlikely(au_dbrange_test(d))) {
2411+ di_read_unlock(d, AuLock_IR);
2412+ continue;
2413+ }
2414+ } else {
1facf9fc 2415+ di_write_lock_child(d);
027c5e7a
AM
2416+ if (unlikely(au_dbrange_test(d))) {
2417+ di_write_unlock(d);
2418+ continue;
2419+ }
1facf9fc 2420+ err = au_reval_dpath(d, sigen);
2421+ if (!err)
2422+ di_downgrade_lock(d, AuLock_IR);
2423+ else {
2424+ di_write_unlock(d);
2425+ break;
2426+ }
2427+ }
2428+
027c5e7a 2429+ /* AuDbgDentry(d); */
1facf9fc 2430+ bstart = au_dbstart(d);
2431+ bend = au_dbend(d);
2432+ if (bstart <= bindex
2433+ && bindex <= bend
2434+ && au_h_dptr(d, bindex)
027c5e7a 2435+ && au_test_dbusy(d, bstart, bend)) {
1facf9fc 2436+ err = -EBUSY;
2437+ AuVerbose(verbose, "busy %.*s\n", AuDLNPair(d));
027c5e7a 2438+ AuDbgDentry(d);
1facf9fc 2439+ }
2440+ di_read_unlock(d, AuLock_IR);
2441+ }
2442+ }
2443+
4f0767ce 2444+out_dpages:
1facf9fc 2445+ au_dpages_free(&dpages);
4f0767ce 2446+out:
1facf9fc 2447+ return err;
2448+}
2449+
2450+static int test_inode_busy(struct super_block *sb, aufs_bindex_t bindex,
b752ccd1 2451+ unsigned int sigen, const unsigned int verbose)
1facf9fc 2452+{
2453+ int err;
7f207e10
AM
2454+ unsigned long long max, ull;
2455+ struct inode *i, **array;
1facf9fc 2456+ aufs_bindex_t bstart, bend;
1facf9fc 2457+
7f207e10
AM
2458+ array = au_iarray_alloc(sb, &max);
2459+ err = PTR_ERR(array);
2460+ if (IS_ERR(array))
2461+ goto out;
2462+
1facf9fc 2463+ err = 0;
7f207e10
AM
2464+ AuDbg("b%d\n", bindex);
2465+ for (ull = 0; !err && ull < max; ull++) {
2466+ i = array[ull];
2467+ if (i->i_ino == AUFS_ROOT_INO)
1facf9fc 2468+ continue;
2469+
7f207e10 2470+ /* AuDbgInode(i); */
537831f9 2471+ if (au_iigen(i, NULL) == sigen)
1facf9fc 2472+ ii_read_lock_child(i);
2473+ else {
2474+ ii_write_lock_child(i);
027c5e7a
AM
2475+ err = au_refresh_hinode_self(i);
2476+ au_iigen_dec(i);
1facf9fc 2477+ if (!err)
2478+ ii_downgrade_lock(i);
2479+ else {
2480+ ii_write_unlock(i);
2481+ break;
2482+ }
2483+ }
2484+
2485+ bstart = au_ibstart(i);
2486+ bend = au_ibend(i);
2487+ if (bstart <= bindex
2488+ && bindex <= bend
2489+ && au_h_iptr(i, bindex)
027c5e7a 2490+ && au_test_ibusy(i, bstart, bend)) {
1facf9fc 2491+ err = -EBUSY;
2492+ AuVerbose(verbose, "busy i%lu\n", i->i_ino);
7f207e10 2493+ AuDbgInode(i);
1facf9fc 2494+ }
2495+ ii_read_unlock(i);
2496+ }
7f207e10 2497+ au_iarray_free(array, max);
1facf9fc 2498+
7f207e10 2499+out:
1facf9fc 2500+ return err;
2501+}
2502+
b752ccd1
AM
2503+static int test_children_busy(struct dentry *root, aufs_bindex_t bindex,
2504+ const unsigned int verbose)
1facf9fc 2505+{
2506+ int err;
2507+ unsigned int sigen;
2508+
2509+ sigen = au_sigen(root->d_sb);
2510+ DiMustNoWaiters(root);
2511+ IiMustNoWaiters(root->d_inode);
2512+ di_write_unlock(root);
b752ccd1 2513+ err = test_dentry_busy(root, bindex, sigen, verbose);
1facf9fc 2514+ if (!err)
b752ccd1 2515+ err = test_inode_busy(root->d_sb, bindex, sigen, verbose);
1facf9fc 2516+ di_write_lock_child(root); /* aufs_write_lock() calls ..._child() */
2517+
2518+ return err;
2519+}
2520+
2521+static void au_br_do_del_brp(struct au_sbinfo *sbinfo,
2522+ const aufs_bindex_t bindex,
2523+ const aufs_bindex_t bend)
2524+{
2525+ struct au_branch **brp, **p;
2526+
dece6358
AM
2527+ AuRwMustWriteLock(&sbinfo->si_rwsem);
2528+
1facf9fc 2529+ brp = sbinfo->si_branch + bindex;
2530+ if (bindex < bend)
2531+ memmove(brp, brp + 1, sizeof(*brp) * (bend - bindex));
2532+ sbinfo->si_branch[0 + bend] = NULL;
2533+ sbinfo->si_bend--;
2534+
53392da6 2535+ p = krealloc(sbinfo->si_branch, sizeof(*p) * bend, AuGFP_SBILIST);
1facf9fc 2536+ if (p)
2537+ sbinfo->si_branch = p;
4a4d8108 2538+ /* harmless error */
1facf9fc 2539+}
2540+
2541+static void au_br_do_del_hdp(struct au_dinfo *dinfo, const aufs_bindex_t bindex,
2542+ const aufs_bindex_t bend)
2543+{
2544+ struct au_hdentry *hdp, *p;
2545+
1308ab2a 2546+ AuRwMustWriteLock(&dinfo->di_rwsem);
2547+
4a4d8108 2548+ hdp = dinfo->di_hdentry;
1facf9fc 2549+ if (bindex < bend)
4a4d8108
AM
2550+ memmove(hdp + bindex, hdp + bindex + 1,
2551+ sizeof(*hdp) * (bend - bindex));
2552+ hdp[0 + bend].hd_dentry = NULL;
1facf9fc 2553+ dinfo->di_bend--;
2554+
53392da6 2555+ p = krealloc(hdp, sizeof(*p) * bend, AuGFP_SBILIST);
1facf9fc 2556+ if (p)
2557+ dinfo->di_hdentry = p;
4a4d8108 2558+ /* harmless error */
1facf9fc 2559+}
2560+
2561+static void au_br_do_del_hip(struct au_iinfo *iinfo, const aufs_bindex_t bindex,
2562+ const aufs_bindex_t bend)
2563+{
2564+ struct au_hinode *hip, *p;
2565+
1308ab2a 2566+ AuRwMustWriteLock(&iinfo->ii_rwsem);
2567+
1facf9fc 2568+ hip = iinfo->ii_hinode + bindex;
2569+ if (bindex < bend)
2570+ memmove(hip, hip + 1, sizeof(*hip) * (bend - bindex));
2571+ iinfo->ii_hinode[0 + bend].hi_inode = NULL;
4a4d8108 2572+ au_hn_init(iinfo->ii_hinode + bend);
1facf9fc 2573+ iinfo->ii_bend--;
2574+
53392da6 2575+ p = krealloc(iinfo->ii_hinode, sizeof(*p) * bend, AuGFP_SBILIST);
1facf9fc 2576+ if (p)
2577+ iinfo->ii_hinode = p;
4a4d8108 2578+ /* harmless error */
1facf9fc 2579+}
2580+
2581+static void au_br_do_del(struct super_block *sb, aufs_bindex_t bindex,
2582+ struct au_branch *br)
2583+{
2584+ aufs_bindex_t bend;
2585+ struct au_sbinfo *sbinfo;
53392da6
AM
2586+ struct dentry *root, *h_root;
2587+ struct inode *inode, *h_inode;
2588+ struct au_hinode *hinode;
1facf9fc 2589+
dece6358
AM
2590+ SiMustWriteLock(sb);
2591+
1facf9fc 2592+ root = sb->s_root;
2593+ inode = root->d_inode;
1facf9fc 2594+ sbinfo = au_sbi(sb);
2595+ bend = sbinfo->si_bend;
2596+
53392da6
AM
2597+ h_root = au_h_dptr(root, bindex);
2598+ hinode = au_hi(inode, bindex);
2599+ h_inode = au_igrab(hinode->hi_inode);
2600+ au_hiput(hinode);
1facf9fc 2601+
53392da6 2602+ au_sbilist_lock();
1facf9fc 2603+ au_br_do_del_brp(sbinfo, bindex, bend);
2604+ au_br_do_del_hdp(au_di(root), bindex, bend);
2605+ au_br_do_del_hip(au_ii(inode), bindex, bend);
53392da6
AM
2606+ au_sbilist_unlock();
2607+
2608+ dput(h_root);
2609+ iput(h_inode);
2610+ au_br_do_free(br);
1facf9fc 2611+}
2612+
2613+int au_br_del(struct super_block *sb, struct au_opt_del *del, int remount)
2614+{
2615+ int err, rerr, i;
2616+ unsigned int mnt_flags;
2617+ aufs_bindex_t bindex, bend, br_id;
2618+ unsigned char do_wh, verbose;
2619+ struct au_branch *br;
2620+ struct au_wbr *wbr;
2621+
2622+ err = 0;
2623+ bindex = au_find_dbindex(sb->s_root, del->h_path.dentry);
2624+ if (bindex < 0) {
2625+ if (remount)
2626+ goto out; /* success */
2627+ err = -ENOENT;
4a4d8108 2628+ pr_err("%s no such branch\n", del->pathname);
1facf9fc 2629+ goto out;
2630+ }
2631+ AuDbg("bindex b%d\n", bindex);
2632+
2633+ err = -EBUSY;
2634+ mnt_flags = au_mntflags(sb);
2635+ verbose = !!au_opt_test(mnt_flags, VERBOSE);
2636+ bend = au_sbend(sb);
2637+ if (unlikely(!bend)) {
2638+ AuVerbose(verbose, "no more branches left\n");
2639+ goto out;
2640+ }
2641+ br = au_sbr(sb, bindex);
2642+ i = atomic_read(&br->br_count);
2643+ if (unlikely(i)) {
2644+ AuVerbose(verbose, "%d file(s) opened\n", i);
e49829fe 2645+ goto out;
1facf9fc 2646+ }
2647+
2648+ wbr = br->br_wbr;
2649+ do_wh = wbr && (wbr->wbr_whbase || wbr->wbr_plink || wbr->wbr_orph);
2650+ if (do_wh) {
1308ab2a 2651+ /* instead of WbrWhMustWriteLock(wbr) */
2652+ SiMustWriteLock(sb);
1facf9fc 2653+ for (i = 0; i < AuBrWh_Last; i++) {
2654+ dput(wbr->wbr_wh[i]);
2655+ wbr->wbr_wh[i] = NULL;
2656+ }
2657+ }
2658+
b752ccd1 2659+ err = test_children_busy(sb->s_root, bindex, verbose);
1facf9fc 2660+ if (unlikely(err)) {
2661+ if (do_wh)
2662+ goto out_wh;
2663+ goto out;
2664+ }
2665+
2666+ err = 0;
2667+ br_id = br->br_id;
2668+ if (!remount)
2669+ au_br_do_del(sb, bindex, br);
2670+ else {
2671+ sysaufs_brs_del(sb, bindex);
2672+ au_br_do_del(sb, bindex, br);
2673+ sysaufs_brs_add(sb, bindex);
2674+ }
2675+
1308ab2a 2676+ if (!bindex) {
1facf9fc 2677+ au_cpup_attr_all(sb->s_root->d_inode, /*force*/1);
1308ab2a 2678+ sb->s_maxbytes = au_sbr_sb(sb, 0)->s_maxbytes;
2679+ } else
1facf9fc 2680+ au_sub_nlink(sb->s_root->d_inode, del->h_path.dentry->d_inode);
2681+ if (au_opt_test(mnt_flags, PLINK))
2682+ au_plink_half_refresh(sb, br_id);
2683+
b752ccd1 2684+ if (au_xino_brid(sb) == br_id)
1facf9fc 2685+ au_xino_brid_set(sb, -1);
2686+ goto out; /* success */
2687+
4f0767ce 2688+out_wh:
1facf9fc 2689+ /* revert */
2690+ rerr = au_br_init_wh(sb, br, br->br_perm, del->h_path.dentry);
2691+ if (rerr)
0c3ec466
AM
2692+ pr_warn("failed re-creating base whiteout, %s. (%d)\n",
2693+ del->pathname, rerr);
4f0767ce 2694+out:
1facf9fc 2695+ return err;
2696+}
2697+
2698+/* ---------------------------------------------------------------------- */
2699+
027c5e7a
AM
2700+static int au_ibusy(struct super_block *sb, struct aufs_ibusy __user *arg)
2701+{
2702+ int err;
2703+ aufs_bindex_t bstart, bend;
2704+ struct aufs_ibusy ibusy;
2705+ struct inode *inode, *h_inode;
2706+
2707+ err = -EPERM;
2708+ if (unlikely(!capable(CAP_SYS_ADMIN)))
2709+ goto out;
2710+
2711+ err = copy_from_user(&ibusy, arg, sizeof(ibusy));
2712+ if (!err)
2713+ err = !access_ok(VERIFY_WRITE, &arg->h_ino, sizeof(arg->h_ino));
2714+ if (unlikely(err)) {
2715+ err = -EFAULT;
2716+ AuTraceErr(err);
2717+ goto out;
2718+ }
2719+
2720+ err = -EINVAL;
2721+ si_read_lock(sb, AuLock_FLUSH);
2722+ if (unlikely(ibusy.bindex < 0 || ibusy.bindex > au_sbend(sb)))
2723+ goto out_unlock;
2724+
2725+ err = 0;
2726+ ibusy.h_ino = 0; /* invalid */
2727+ inode = ilookup(sb, ibusy.ino);
2728+ if (!inode
2729+ || inode->i_ino == AUFS_ROOT_INO
2730+ || is_bad_inode(inode))
2731+ goto out_unlock;
2732+
2733+ ii_read_lock_child(inode);
2734+ bstart = au_ibstart(inode);
2735+ bend = au_ibend(inode);
2736+ if (bstart <= ibusy.bindex && ibusy.bindex <= bend) {
2737+ h_inode = au_h_iptr(inode, ibusy.bindex);
2738+ if (h_inode && au_test_ibusy(inode, bstart, bend))
2739+ ibusy.h_ino = h_inode->i_ino;
2740+ }
2741+ ii_read_unlock(inode);
2742+ iput(inode);
2743+
2744+out_unlock:
2745+ si_read_unlock(sb);
2746+ if (!err) {
2747+ err = __put_user(ibusy.h_ino, &arg->h_ino);
2748+ if (unlikely(err)) {
2749+ err = -EFAULT;
2750+ AuTraceErr(err);
2751+ }
2752+ }
2753+out:
2754+ return err;
2755+}
2756+
2757+long au_ibusy_ioctl(struct file *file, unsigned long arg)
2758+{
2759+ return au_ibusy(file->f_dentry->d_sb, (void __user *)arg);
2760+}
2761+
2762+#ifdef CONFIG_COMPAT
2763+long au_ibusy_compat_ioctl(struct file *file, unsigned long arg)
2764+{
2765+ return au_ibusy(file->f_dentry->d_sb, compat_ptr(arg));
2766+}
2767+#endif
2768+
2769+/* ---------------------------------------------------------------------- */
2770+
1facf9fc 2771+/*
2772+ * change a branch permission
2773+ */
2774+
dece6358
AM
2775+static void au_warn_ima(void)
2776+{
2777+#ifdef CONFIG_IMA
1308ab2a 2778+ /* since it doesn't support mark_files_ro() */
027c5e7a 2779+ AuWarn1("RW -> RO makes IMA to produce wrong message\n");
dece6358
AM
2780+#endif
2781+}
2782+
1facf9fc 2783+static int do_need_sigen_inc(int a, int b)
2784+{
2785+ return au_br_whable(a) && !au_br_whable(b);
2786+}
2787+
2788+static int need_sigen_inc(int old, int new)
2789+{
2790+ return do_need_sigen_inc(old, new)
2791+ || do_need_sigen_inc(new, old);
2792+}
2793+
7f207e10
AM
2794+static unsigned long long au_farray_cb(void *a,
2795+ unsigned long long max __maybe_unused,
2796+ void *arg)
2797+{
2798+ unsigned long long n;
2799+ struct file **p, *f;
2800+ struct super_block *sb = arg;
2801+
2802+ n = 0;
2803+ p = a;
0c3ec466 2804+ lg_global_lock(&files_lglock);
7f207e10
AM
2805+ do_file_list_for_each_entry(sb, f) {
2806+ if (au_fi(f)
027c5e7a 2807+ && file_count(f)
7f207e10
AM
2808+ && !special_file(f->f_dentry->d_inode->i_mode)) {
2809+ get_file(f);
2810+ *p++ = f;
2811+ n++;
2812+ AuDebugOn(n > max);
2813+ }
2814+ } while_file_list_for_each_entry;
0c3ec466 2815+ lg_global_unlock(&files_lglock);
7f207e10
AM
2816+
2817+ return n;
2818+}
2819+
2820+static struct file **au_farray_alloc(struct super_block *sb,
2821+ unsigned long long *max)
2822+{
2823+ *max = atomic_long_read(&au_sbi(sb)->si_nfiles);
2824+ return au_array_alloc(max, au_farray_cb, sb);
2825+}
2826+
2827+static void au_farray_free(struct file **a, unsigned long long max)
2828+{
2829+ unsigned long long ull;
2830+
2831+ for (ull = 0; ull < max; ull++)
2832+ if (a[ull])
2833+ fput(a[ull]);
2834+ au_array_free(a);
2835+}
2836+
1facf9fc 2837+static int au_br_mod_files_ro(struct super_block *sb, aufs_bindex_t bindex)
2838+{
7f207e10 2839+ int err, do_warn;
027c5e7a 2840+ unsigned int mnt_flags;
7f207e10 2841+ unsigned long long ull, max;
e49829fe 2842+ aufs_bindex_t br_id;
027c5e7a 2843+ unsigned char verbose;
7f207e10 2844+ struct file *file, *hf, **array;
e49829fe
JR
2845+ struct inode *inode;
2846+ struct au_hfile *hfile;
1facf9fc 2847+
027c5e7a
AM
2848+ mnt_flags = au_mntflags(sb);
2849+ verbose = !!au_opt_test(mnt_flags, VERBOSE);
2850+
7f207e10
AM
2851+ array = au_farray_alloc(sb, &max);
2852+ err = PTR_ERR(array);
2853+ if (IS_ERR(array))
1facf9fc 2854+ goto out;
2855+
7f207e10 2856+ do_warn = 0;
e49829fe 2857+ br_id = au_sbr_id(sb, bindex);
7f207e10
AM
2858+ for (ull = 0; ull < max; ull++) {
2859+ file = array[ull];
1facf9fc 2860+
7f207e10 2861+ /* AuDbg("%.*s\n", AuDLNPair(file->f_dentry)); */
1facf9fc 2862+ fi_read_lock(file);
2863+ if (unlikely(au_test_mmapped(file))) {
2864+ err = -EBUSY;
027c5e7a
AM
2865+ AuVerbose(verbose, "mmapped %.*s\n",
2866+ AuDLNPair(file->f_dentry));
7f207e10 2867+ AuDbgFile(file);
1facf9fc 2868+ FiMustNoWaiters(file);
2869+ fi_read_unlock(file);
7f207e10 2870+ goto out_array;
1facf9fc 2871+ }
2872+
027c5e7a 2873+ inode = file->f_dentry->d_inode;
e49829fe
JR
2874+ hfile = &au_fi(file)->fi_htop;
2875+ hf = hfile->hf_file;
2876+ if (!S_ISREG(inode->i_mode)
1facf9fc 2877+ || !(file->f_mode & FMODE_WRITE)
e49829fe 2878+ || hfile->hf_br->br_id != br_id
7f207e10
AM
2879+ || !(hf->f_mode & FMODE_WRITE))
2880+ array[ull] = NULL;
2881+ else {
2882+ do_warn = 1;
2883+ get_file(file);
1facf9fc 2884+ }
2885+
1facf9fc 2886+ FiMustNoWaiters(file);
2887+ fi_read_unlock(file);
7f207e10
AM
2888+ fput(file);
2889+ }
1facf9fc 2890+
2891+ err = 0;
7f207e10 2892+ if (do_warn)
dece6358 2893+ au_warn_ima();
7f207e10
AM
2894+
2895+ for (ull = 0; ull < max; ull++) {
2896+ file = array[ull];
2897+ if (!file)
2898+ continue;
2899+
1facf9fc 2900+ /* todo: already flushed? */
2901+ /* cf. fs/super.c:mark_files_ro() */
7f207e10
AM
2902+ /* fi_read_lock(file); */
2903+ hfile = &au_fi(file)->fi_htop;
2904+ hf = hfile->hf_file;
2905+ /* fi_read_unlock(file); */
027c5e7a 2906+ spin_lock(&hf->f_lock);
1facf9fc 2907+ hf->f_mode &= ~FMODE_WRITE;
027c5e7a 2908+ spin_unlock(&hf->f_lock);
1facf9fc 2909+ if (!file_check_writeable(hf)) {
2910+ file_release_write(hf);
b4510431 2911+ vfsub_mnt_drop_write(hf->f_vfsmnt);
1facf9fc 2912+ }
2913+ }
2914+
7f207e10
AM
2915+out_array:
2916+ au_farray_free(array, max);
4f0767ce 2917+out:
7f207e10 2918+ AuTraceErr(err);
1facf9fc 2919+ return err;
2920+}
2921+
2922+int au_br_mod(struct super_block *sb, struct au_opt_mod *mod, int remount,
7f207e10 2923+ int *do_refresh)
1facf9fc 2924+{
2925+ int err, rerr;
2926+ aufs_bindex_t bindex;
1308ab2a 2927+ struct path path;
1facf9fc 2928+ struct dentry *root;
2929+ struct au_branch *br;
2930+
2931+ root = sb->s_root;
1facf9fc 2932+ bindex = au_find_dbindex(root, mod->h_root);
2933+ if (bindex < 0) {
2934+ if (remount)
2935+ return 0; /* success */
2936+ err = -ENOENT;
4a4d8108 2937+ pr_err("%s no such branch\n", mod->path);
1facf9fc 2938+ goto out;
2939+ }
2940+ AuDbg("bindex b%d\n", bindex);
2941+
2942+ err = test_br(mod->h_root->d_inode, mod->perm, mod->path);
2943+ if (unlikely(err))
2944+ goto out;
2945+
2946+ br = au_sbr(sb, bindex);
2947+ if (br->br_perm == mod->perm)
2948+ return 0; /* success */
2949+
2950+ if (au_br_writable(br->br_perm)) {
2951+ /* remove whiteout base */
2952+ err = au_br_init_wh(sb, br, mod->perm, mod->h_root);
2953+ if (unlikely(err))
2954+ goto out;
2955+
2956+ if (!au_br_writable(mod->perm)) {
2957+ /* rw --> ro, file might be mmapped */
2958+ DiMustNoWaiters(root);
2959+ IiMustNoWaiters(root->d_inode);
2960+ di_write_unlock(root);
2961+ err = au_br_mod_files_ro(sb, bindex);
2962+ /* aufs_write_lock() calls ..._child() */
2963+ di_write_lock_child(root);
2964+
2965+ if (unlikely(err)) {
2966+ rerr = -ENOMEM;
2967+ br->br_wbr = kmalloc(sizeof(*br->br_wbr),
2968+ GFP_NOFS);
1308ab2a 2969+ if (br->br_wbr) {
2970+ path.mnt = br->br_mnt;
2971+ path.dentry = mod->h_root;
2972+ rerr = au_wbr_init(br, sb, br->br_perm,
2973+ &path);
2974+ }
1facf9fc 2975+ if (unlikely(rerr)) {
2976+ AuIOErr("nested error %d (%d)\n",
2977+ rerr, err);
2978+ br->br_perm = mod->perm;
2979+ }
2980+ }
2981+ }
2982+ } else if (au_br_writable(mod->perm)) {
2983+ /* ro --> rw */
2984+ err = -ENOMEM;
2985+ br->br_wbr = kmalloc(sizeof(*br->br_wbr), GFP_NOFS);
2986+ if (br->br_wbr) {
1308ab2a 2987+ path.mnt = br->br_mnt;
2988+ path.dentry = mod->h_root;
1facf9fc 2989+ err = au_wbr_init(br, sb, mod->perm, &path);
2990+ if (unlikely(err)) {
2991+ kfree(br->br_wbr);
2992+ br->br_wbr = NULL;
2993+ }
2994+ }
2995+ }
2996+
2997+ if (!err) {
7f207e10 2998+ *do_refresh |= need_sigen_inc(br->br_perm, mod->perm);
1facf9fc 2999+ br->br_perm = mod->perm;
3000+ }
3001+
4f0767ce 3002+out:
7f207e10 3003+ AuTraceErr(err);
1facf9fc 3004+ return err;
3005+}
7f207e10
AM
3006diff -urN /usr/share/empty/fs/aufs/branch.h linux/fs/aufs/branch.h
3007--- /usr/share/empty/fs/aufs/branch.h 1970-01-01 01:00:00.000000000 +0100
537831f9 3008+++ linux/fs/aufs/branch.h 2012-12-13 20:41:10.428126759 +0100
f6c5ef8b 3009@@ -0,0 +1,230 @@
1facf9fc 3010+/*
f6c5ef8b 3011+ * Copyright (C) 2005-2012 Junjiro R. Okajima
1facf9fc 3012+ *
3013+ * This program, aufs is free software; you can redistribute it and/or modify
3014+ * it under the terms of the GNU General Public License as published by
3015+ * the Free Software Foundation; either version 2 of the License, or
3016+ * (at your option) any later version.
dece6358
AM
3017+ *
3018+ * This program is distributed in the hope that it will be useful,
3019+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
3020+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
3021+ * GNU General Public License for more details.
3022+ *
3023+ * You should have received a copy of the GNU General Public License
3024+ * along with this program; if not, write to the Free Software
3025+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 3026+ */
3027+
3028+/*
3029+ * branch filesystems and xino for them
3030+ */
3031+
3032+#ifndef __AUFS_BRANCH_H__
3033+#define __AUFS_BRANCH_H__
3034+
3035+#ifdef __KERNEL__
3036+
1facf9fc 3037+#include <linux/mount.h>
4a4d8108 3038+#include "dynop.h"
1facf9fc 3039+#include "rwsem.h"
3040+#include "super.h"
3041+
3042+/* ---------------------------------------------------------------------- */
3043+
3044+/* a xino file */
3045+struct au_xino_file {
3046+ struct file *xi_file;
3047+ struct mutex xi_nondir_mtx;
3048+
3049+ /* todo: make xino files an array to support huge inode number */
3050+
3051+#ifdef CONFIG_DEBUG_FS
3052+ struct dentry *xi_dbgaufs;
3053+#endif
3054+};
3055+
3056+/* members for writable branch only */
3057+enum {AuBrWh_BASE, AuBrWh_PLINK, AuBrWh_ORPH, AuBrWh_Last};
3058+struct au_wbr {
dece6358 3059+ struct au_rwsem wbr_wh_rwsem;
1facf9fc 3060+ struct dentry *wbr_wh[AuBrWh_Last];
4a4d8108 3061+ atomic_t wbr_wh_running;
1facf9fc 3062+#define wbr_whbase wbr_wh[AuBrWh_BASE] /* whiteout base */
3063+#define wbr_plink wbr_wh[AuBrWh_PLINK] /* pseudo-link dir */
3064+#define wbr_orph wbr_wh[AuBrWh_ORPH] /* dir for orphans */
3065+
3066+ /* mfs mode */
3067+ unsigned long long wbr_bytes;
3068+};
3069+
4a4d8108
AM
3070+/* ext2 has 3 types of operations at least, ext3 has 4 */
3071+#define AuBrDynOp (AuDyLast * 4)
3072+
1facf9fc 3073+/* protected by superblock rwsem */
3074+struct au_branch {
3075+ struct au_xino_file br_xino;
3076+
3077+ aufs_bindex_t br_id;
3078+
3079+ int br_perm;
3080+ struct vfsmount *br_mnt;
4a4d8108
AM
3081+ spinlock_t br_dykey_lock;
3082+ struct au_dykey *br_dykey[AuBrDynOp];
1facf9fc 3083+ atomic_t br_count;
3084+
3085+ struct au_wbr *br_wbr;
3086+
3087+ /* xino truncation */
3088+ blkcnt_t br_xino_upper; /* watermark in blocks */
3089+ atomic_t br_xino_running;
3090+
027c5e7a
AM
3091+#ifdef CONFIG_AUFS_HFSNOTIFY
3092+ struct fsnotify_group *br_hfsn_group;
3093+ struct fsnotify_ops br_hfsn_ops;
3094+#endif
3095+
1facf9fc 3096+#ifdef CONFIG_SYSFS
3097+ /* an entry under sysfs per mount-point */
3098+ char br_name[8];
3099+ struct attribute br_attr;
3100+#endif
3101+};
3102+
3103+/* ---------------------------------------------------------------------- */
3104+
1e00d052
AM
3105+/* branch permissions and attributes */
3106+#define AuBrPerm_RW 1 /* writable, hardlinkable wh */
3107+#define AuBrPerm_RO (1 << 1) /* readonly */
3108+#define AuBrPerm_RR (1 << 2) /* natively readonly */
3109+#define AuBrPerm_Mask (AuBrPerm_RW | AuBrPerm_RO | AuBrPerm_RR)
1facf9fc 3110+
1e00d052 3111+#define AuBrRAttr_WH (1 << 3) /* whiteout-able */
1facf9fc 3112+
1e00d052 3113+#define AuBrWAttr_NoLinkWH (1 << 4) /* un-hardlinkable whiteouts */
1facf9fc 3114+
3115+static inline int au_br_writable(int brperm)
3116+{
1e00d052 3117+ return brperm & AuBrPerm_RW;
1facf9fc 3118+}
3119+
3120+static inline int au_br_whable(int brperm)
3121+{
1e00d052
AM
3122+ return brperm & (AuBrPerm_RW | AuBrRAttr_WH);
3123+}
3124+
3125+static inline int au_br_wh_linkable(int brperm)
3126+{
3127+ return !(brperm & AuBrWAttr_NoLinkWH);
1facf9fc 3128+}
3129+
3130+static inline int au_br_rdonly(struct au_branch *br)
3131+{
3132+ return ((br->br_mnt->mnt_sb->s_flags & MS_RDONLY)
3133+ || !au_br_writable(br->br_perm))
3134+ ? -EROFS : 0;
3135+}
3136+
4a4d8108 3137+static inline int au_br_hnotifyable(int brperm __maybe_unused)
1facf9fc 3138+{
4a4d8108 3139+#ifdef CONFIG_AUFS_HNOTIFY
1e00d052 3140+ return !(brperm & AuBrPerm_RR);
1facf9fc 3141+#else
3142+ return 0;
3143+#endif
3144+}
3145+
3146+/* ---------------------------------------------------------------------- */
3147+
3148+/* branch.c */
3149+struct au_sbinfo;
3150+void au_br_free(struct au_sbinfo *sinfo);
3151+int au_br_index(struct super_block *sb, aufs_bindex_t br_id);
3152+struct au_opt_add;
3153+int au_br_add(struct super_block *sb, struct au_opt_add *add, int remount);
3154+struct au_opt_del;
3155+int au_br_del(struct super_block *sb, struct au_opt_del *del, int remount);
027c5e7a
AM
3156+long au_ibusy_ioctl(struct file *file, unsigned long arg);
3157+#ifdef CONFIG_COMPAT
3158+long au_ibusy_compat_ioctl(struct file *file, unsigned long arg);
3159+#endif
1facf9fc 3160+struct au_opt_mod;
3161+int au_br_mod(struct super_block *sb, struct au_opt_mod *mod, int remount,
7f207e10 3162+ int *do_refresh);
1facf9fc 3163+
3164+/* xino.c */
3165+static const loff_t au_loff_max = LLONG_MAX;
3166+
3167+int au_xib_trunc(struct super_block *sb);
3168+ssize_t xino_fread(au_readf_t func, struct file *file, void *buf, size_t size,
3169+ loff_t *pos);
3170+ssize_t xino_fwrite(au_writef_t func, struct file *file, void *buf, size_t size,
3171+ loff_t *pos);
3172+struct file *au_xino_create2(struct file *base_file, struct file *copy_src);
3173+struct file *au_xino_create(struct super_block *sb, char *fname, int silent);
3174+ino_t au_xino_new_ino(struct super_block *sb);
b752ccd1 3175+void au_xino_delete_inode(struct inode *inode, const int unlinked);
1facf9fc 3176+int au_xino_write(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino,
3177+ ino_t ino);
3178+int au_xino_read(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino,
3179+ ino_t *ino);
3180+int au_xino_br(struct super_block *sb, struct au_branch *br, ino_t hino,
3181+ struct file *base_file, int do_test);
3182+int au_xino_trunc(struct super_block *sb, aufs_bindex_t bindex);
3183+
3184+struct au_opt_xino;
3185+int au_xino_set(struct super_block *sb, struct au_opt_xino *xino, int remount);
3186+void au_xino_clr(struct super_block *sb);
3187+struct file *au_xino_def(struct super_block *sb);
3188+int au_xino_path(struct seq_file *seq, struct file *file);
3189+
3190+/* ---------------------------------------------------------------------- */
3191+
3192+/* Superblock to branch */
3193+static inline
3194+aufs_bindex_t au_sbr_id(struct super_block *sb, aufs_bindex_t bindex)
3195+{
3196+ return au_sbr(sb, bindex)->br_id;
3197+}
3198+
3199+static inline
3200+struct vfsmount *au_sbr_mnt(struct super_block *sb, aufs_bindex_t bindex)
3201+{
3202+ return au_sbr(sb, bindex)->br_mnt;
3203+}
3204+
3205+static inline
3206+struct super_block *au_sbr_sb(struct super_block *sb, aufs_bindex_t bindex)
3207+{
3208+ return au_sbr_mnt(sb, bindex)->mnt_sb;
3209+}
3210+
3211+static inline void au_sbr_put(struct super_block *sb, aufs_bindex_t bindex)
3212+{
e49829fe 3213+ atomic_dec(&au_sbr(sb, bindex)->br_count);
1facf9fc 3214+}
3215+
3216+static inline int au_sbr_perm(struct super_block *sb, aufs_bindex_t bindex)
3217+{
3218+ return au_sbr(sb, bindex)->br_perm;
3219+}
3220+
3221+static inline int au_sbr_whable(struct super_block *sb, aufs_bindex_t bindex)
3222+{
3223+ return au_br_whable(au_sbr_perm(sb, bindex));
3224+}
3225+
3226+/* ---------------------------------------------------------------------- */
3227+
3228+/*
3229+ * wbr_wh_read_lock, wbr_wh_write_lock
3230+ * wbr_wh_read_unlock, wbr_wh_write_unlock, wbr_wh_downgrade_lock
3231+ */
3232+AuSimpleRwsemFuncs(wbr_wh, struct au_wbr *wbr, &wbr->wbr_wh_rwsem);
3233+
dece6358
AM
3234+#define WbrWhMustNoWaiters(wbr) AuRwMustNoWaiters(&wbr->wbr_wh_rwsem)
3235+#define WbrWhMustAnyLock(wbr) AuRwMustAnyLock(&wbr->wbr_wh_rwsem)
3236+#define WbrWhMustWriteLock(wbr) AuRwMustWriteLock(&wbr->wbr_wh_rwsem)
3237+
1facf9fc 3238+#endif /* __KERNEL__ */
3239+#endif /* __AUFS_BRANCH_H__ */
7f207e10
AM
3240diff -urN /usr/share/empty/fs/aufs/conf.mk linux/fs/aufs/conf.mk
3241--- /usr/share/empty/fs/aufs/conf.mk 1970-01-01 01:00:00.000000000 +0100
537831f9 3242+++ linux/fs/aufs/conf.mk 2012-12-13 20:41:10.428126759 +0100
2cbb1c4b 3243@@ -0,0 +1,38 @@
4a4d8108
AM
3244+
3245+AuConfStr = CONFIG_AUFS_FS=${CONFIG_AUFS_FS}
3246+
3247+define AuConf
3248+ifdef ${1}
3249+AuConfStr += ${1}=${${1}}
3250+endif
3251+endef
3252+
b752ccd1 3253+AuConfAll = BRANCH_MAX_127 BRANCH_MAX_511 BRANCH_MAX_1023 BRANCH_MAX_32767 \
e49829fe 3254+ SBILIST \
7f207e10 3255+ HNOTIFY HFSNOTIFY \
4a4d8108
AM
3256+ EXPORT INO_T_64 \
3257+ RDU \
2cbb1c4b 3258+ PROC_MAP \
4a4d8108
AM
3259+ SP_IATTR \
3260+ SHWH \
3261+ BR_RAMFS \
3262+ BR_FUSE POLL \
3263+ BR_HFSPLUS \
3264+ BDEV_LOOP \
b752ccd1
AM
3265+ DEBUG MAGIC_SYSRQ
3266+$(foreach i, ${AuConfAll}, \
4a4d8108
AM
3267+ $(eval $(call AuConf,CONFIG_AUFS_${i})))
3268+
3269+AuConfName = ${obj}/conf.str
3270+${AuConfName}.tmp: FORCE
3271+ @echo ${AuConfStr} | tr ' ' '\n' | sed -e 's/^/"/' -e 's/$$/\\n"/' > $@
3272+${AuConfName}: ${AuConfName}.tmp
3273+ @diff -q $< $@ > /dev/null 2>&1 || { \
3274+ echo ' GEN ' $@; \
3275+ cp -p $< $@; \
3276+ }
3277+FORCE:
3278+clean-files += ${AuConfName} ${AuConfName}.tmp
3279+${obj}/sysfs.o: ${AuConfName}
b752ccd1
AM
3280+
3281+-include ${srctree}/${src}/conf_priv.mk
7f207e10
AM
3282diff -urN /usr/share/empty/fs/aufs/cpup.c linux/fs/aufs/cpup.c
3283--- /usr/share/empty/fs/aufs/cpup.c 1970-01-01 01:00:00.000000000 +0100
537831f9 3284+++ linux/fs/aufs/cpup.c 2012-12-13 20:41:10.428126759 +0100
b4510431 3285@@ -0,0 +1,1085 @@
1facf9fc 3286+/*
f6c5ef8b 3287+ * Copyright (C) 2005-2012 Junjiro R. Okajima
1facf9fc 3288+ *
3289+ * This program, aufs is free software; you can redistribute it and/or modify
3290+ * it under the terms of the GNU General Public License as published by
3291+ * the Free Software Foundation; either version 2 of the License, or
3292+ * (at your option) any later version.
dece6358
AM
3293+ *
3294+ * This program is distributed in the hope that it will be useful,
3295+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
3296+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
3297+ * GNU General Public License for more details.
3298+ *
3299+ * You should have received a copy of the GNU General Public License
3300+ * along with this program; if not, write to the Free Software
3301+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 3302+ */
3303+
3304+/*
3305+ * copy-up functions, see wbr_policy.c for copy-down
3306+ */
3307+
3308+#include <linux/fs_stack.h>
dece6358 3309+#include <linux/mm.h>
1facf9fc 3310+#include "aufs.h"
3311+
3312+void au_cpup_attr_flags(struct inode *dst, struct inode *src)
3313+{
3314+ const unsigned int mask = S_DEAD | S_SWAPFILE | S_PRIVATE
3315+ | S_NOATIME | S_NOCMTIME;
3316+
3317+ dst->i_flags |= src->i_flags & ~mask;
3318+ if (au_test_fs_notime(dst->i_sb))
3319+ dst->i_flags |= S_NOATIME | S_NOCMTIME;
3320+}
3321+
3322+void au_cpup_attr_timesizes(struct inode *inode)
3323+{
3324+ struct inode *h_inode;
3325+
3326+ h_inode = au_h_iptr(inode, au_ibstart(inode));
3327+ fsstack_copy_attr_times(inode, h_inode);
4a4d8108 3328+ fsstack_copy_inode_size(inode, h_inode);
1facf9fc 3329+}
3330+
3331+void au_cpup_attr_nlink(struct inode *inode, int force)
3332+{
3333+ struct inode *h_inode;
3334+ struct super_block *sb;
3335+ aufs_bindex_t bindex, bend;
3336+
3337+ sb = inode->i_sb;
3338+ bindex = au_ibstart(inode);
3339+ h_inode = au_h_iptr(inode, bindex);
3340+ if (!force
3341+ && !S_ISDIR(h_inode->i_mode)
3342+ && au_opt_test(au_mntflags(sb), PLINK)
3343+ && au_plink_test(inode))
3344+ return;
3345+
7eafdf33
AM
3346+ /*
3347+ * 0 can happen in revalidating.
3348+ * h_inode->i_mutex is not held, but it is harmless since once i_nlink
3349+ * reaches 0, it will never become positive.
3350+ */
92d182d2 3351+ set_nlink(inode, h_inode->i_nlink);
1facf9fc 3352+
3353+ /*
3354+ * fewer nlink makes find(1) noisy, but larger nlink doesn't.
3355+ * it may includes whplink directory.
3356+ */
3357+ if (S_ISDIR(h_inode->i_mode)) {
3358+ bend = au_ibend(inode);
3359+ for (bindex++; bindex <= bend; bindex++) {
3360+ h_inode = au_h_iptr(inode, bindex);
3361+ if (h_inode)
3362+ au_add_nlink(inode, h_inode);
3363+ }
3364+ }
3365+}
3366+
3367+void au_cpup_attr_changeable(struct inode *inode)
3368+{
3369+ struct inode *h_inode;
3370+
3371+ h_inode = au_h_iptr(inode, au_ibstart(inode));
3372+ inode->i_mode = h_inode->i_mode;
3373+ inode->i_uid = h_inode->i_uid;
3374+ inode->i_gid = h_inode->i_gid;
3375+ au_cpup_attr_timesizes(inode);
3376+ au_cpup_attr_flags(inode, h_inode);
3377+}
3378+
3379+void au_cpup_igen(struct inode *inode, struct inode *h_inode)
3380+{
3381+ struct au_iinfo *iinfo = au_ii(inode);
3382+
1308ab2a 3383+ IiMustWriteLock(inode);
3384+
1facf9fc 3385+ iinfo->ii_higen = h_inode->i_generation;
3386+ iinfo->ii_hsb1 = h_inode->i_sb;
3387+}
3388+
3389+void au_cpup_attr_all(struct inode *inode, int force)
3390+{
3391+ struct inode *h_inode;
3392+
3393+ h_inode = au_h_iptr(inode, au_ibstart(inode));
3394+ au_cpup_attr_changeable(inode);
3395+ if (inode->i_nlink > 0)
3396+ au_cpup_attr_nlink(inode, force);
3397+ inode->i_rdev = h_inode->i_rdev;
3398+ inode->i_blkbits = h_inode->i_blkbits;
3399+ au_cpup_igen(inode, h_inode);
3400+}
3401+
3402+/* ---------------------------------------------------------------------- */
3403+
3404+/* Note: dt_dentry and dt_h_dentry are not dget/dput-ed */
3405+
3406+/* keep the timestamps of the parent dir when cpup */
3407+void au_dtime_store(struct au_dtime *dt, struct dentry *dentry,
3408+ struct path *h_path)
3409+{
3410+ struct inode *h_inode;
3411+
3412+ dt->dt_dentry = dentry;
3413+ dt->dt_h_path = *h_path;
3414+ h_inode = h_path->dentry->d_inode;
3415+ dt->dt_atime = h_inode->i_atime;
3416+ dt->dt_mtime = h_inode->i_mtime;
3417+ /* smp_mb(); */
3418+}
3419+
3420+void au_dtime_revert(struct au_dtime *dt)
3421+{
3422+ struct iattr attr;
3423+ int err;
3424+
3425+ attr.ia_atime = dt->dt_atime;
3426+ attr.ia_mtime = dt->dt_mtime;
3427+ attr.ia_valid = ATTR_FORCE | ATTR_MTIME | ATTR_MTIME_SET
3428+ | ATTR_ATIME | ATTR_ATIME_SET;
3429+
3430+ err = vfsub_notify_change(&dt->dt_h_path, &attr);
3431+ if (unlikely(err))
0c3ec466 3432+ pr_warn("restoring timestamps failed(%d). ignored\n", err);
1facf9fc 3433+}
3434+
3435+/* ---------------------------------------------------------------------- */
3436+
3437+static noinline_for_stack
3438+int cpup_iattr(struct dentry *dst, aufs_bindex_t bindex, struct dentry *h_src)
3439+{
3440+ int err, sbits;
3441+ struct iattr ia;
3442+ struct path h_path;
1308ab2a 3443+ struct inode *h_isrc, *h_idst;
1facf9fc 3444+
3445+ h_path.dentry = au_h_dptr(dst, bindex);
1308ab2a 3446+ h_idst = h_path.dentry->d_inode;
1facf9fc 3447+ h_path.mnt = au_sbr_mnt(dst->d_sb, bindex);
3448+ h_isrc = h_src->d_inode;
1308ab2a 3449+ ia.ia_valid = ATTR_FORCE | ATTR_UID | ATTR_GID
1facf9fc 3450+ | ATTR_ATIME | ATTR_MTIME
3451+ | ATTR_ATIME_SET | ATTR_MTIME_SET;
1facf9fc 3452+ ia.ia_uid = h_isrc->i_uid;
3453+ ia.ia_gid = h_isrc->i_gid;
3454+ ia.ia_atime = h_isrc->i_atime;
3455+ ia.ia_mtime = h_isrc->i_mtime;
1308ab2a 3456+ if (h_idst->i_mode != h_isrc->i_mode
3457+ && !S_ISLNK(h_idst->i_mode)) {
3458+ ia.ia_valid |= ATTR_MODE;
3459+ ia.ia_mode = h_isrc->i_mode;
3460+ }
3461+ sbits = !!(h_isrc->i_mode & (S_ISUID | S_ISGID));
3462+ au_cpup_attr_flags(h_idst, h_isrc);
1facf9fc 3463+ err = vfsub_notify_change(&h_path, &ia);
3464+
3465+ /* is this nfs only? */
3466+ if (!err && sbits && au_test_nfs(h_path.dentry->d_sb)) {
3467+ ia.ia_valid = ATTR_FORCE | ATTR_MODE;
3468+ ia.ia_mode = h_isrc->i_mode;
3469+ err = vfsub_notify_change(&h_path, &ia);
3470+ }
3471+
3472+ return err;
3473+}
3474+
3475+/* ---------------------------------------------------------------------- */
3476+
3477+static int au_do_copy_file(struct file *dst, struct file *src, loff_t len,
3478+ char *buf, unsigned long blksize)
3479+{
3480+ int err;
3481+ size_t sz, rbytes, wbytes;
3482+ unsigned char all_zero;
3483+ char *p, *zp;
3484+ struct mutex *h_mtx;
3485+ /* reduce stack usage */
3486+ struct iattr *ia;
3487+
3488+ zp = page_address(ZERO_PAGE(0));
3489+ if (unlikely(!zp))
3490+ return -ENOMEM; /* possible? */
3491+
3492+ err = 0;
3493+ all_zero = 0;
3494+ while (len) {
3495+ AuDbg("len %lld\n", len);
3496+ sz = blksize;
3497+ if (len < blksize)
3498+ sz = len;
3499+
3500+ rbytes = 0;
3501+ /* todo: signal_pending? */
3502+ while (!rbytes || err == -EAGAIN || err == -EINTR) {
3503+ rbytes = vfsub_read_k(src, buf, sz, &src->f_pos);
3504+ err = rbytes;
3505+ }
3506+ if (unlikely(err < 0))
3507+ break;
3508+
3509+ all_zero = 0;
3510+ if (len >= rbytes && rbytes == blksize)
3511+ all_zero = !memcmp(buf, zp, rbytes);
3512+ if (!all_zero) {
3513+ wbytes = rbytes;
3514+ p = buf;
3515+ while (wbytes) {
3516+ size_t b;
3517+
3518+ b = vfsub_write_k(dst, p, wbytes, &dst->f_pos);
3519+ err = b;
3520+ /* todo: signal_pending? */
3521+ if (unlikely(err == -EAGAIN || err == -EINTR))
3522+ continue;
3523+ if (unlikely(err < 0))
3524+ break;
3525+ wbytes -= b;
3526+ p += b;
3527+ }
3528+ } else {
3529+ loff_t res;
3530+
3531+ AuLabel(hole);
3532+ res = vfsub_llseek(dst, rbytes, SEEK_CUR);
3533+ err = res;
3534+ if (unlikely(res < 0))
3535+ break;
3536+ }
3537+ len -= rbytes;
3538+ err = 0;
3539+ }
3540+
3541+ /* the last block may be a hole */
3542+ if (!err && all_zero) {
3543+ AuLabel(last hole);
3544+
3545+ err = 1;
3546+ if (au_test_nfs(dst->f_dentry->d_sb)) {
3547+ /* nfs requires this step to make last hole */
3548+ /* is this only nfs? */
3549+ do {
3550+ /* todo: signal_pending? */
3551+ err = vfsub_write_k(dst, "\0", 1, &dst->f_pos);
3552+ } while (err == -EAGAIN || err == -EINTR);
3553+ if (err == 1)
3554+ dst->f_pos--;
3555+ }
3556+
3557+ if (err == 1) {
3558+ ia = (void *)buf;
3559+ ia->ia_size = dst->f_pos;
3560+ ia->ia_valid = ATTR_SIZE | ATTR_FILE;
3561+ ia->ia_file = dst;
3562+ h_mtx = &dst->f_dentry->d_inode->i_mutex;
3563+ mutex_lock_nested(h_mtx, AuLsc_I_CHILD2);
3564+ err = vfsub_notify_change(&dst->f_path, ia);
3565+ mutex_unlock(h_mtx);
3566+ }
3567+ }
3568+
3569+ return err;
3570+}
3571+
3572+int au_copy_file(struct file *dst, struct file *src, loff_t len)
3573+{
3574+ int err;
3575+ unsigned long blksize;
3576+ unsigned char do_kfree;
3577+ char *buf;
3578+
3579+ err = -ENOMEM;
3580+ blksize = dst->f_dentry->d_sb->s_blocksize;
3581+ if (!blksize || PAGE_SIZE < blksize)
3582+ blksize = PAGE_SIZE;
3583+ AuDbg("blksize %lu\n", blksize);
3584+ do_kfree = (blksize != PAGE_SIZE && blksize >= sizeof(struct iattr *));
3585+ if (do_kfree)
3586+ buf = kmalloc(blksize, GFP_NOFS);
3587+ else
3588+ buf = (void *)__get_free_page(GFP_NOFS);
3589+ if (unlikely(!buf))
3590+ goto out;
3591+
3592+ if (len > (1 << 22))
3593+ AuDbg("copying a large file %lld\n", (long long)len);
3594+
3595+ src->f_pos = 0;
3596+ dst->f_pos = 0;
3597+ err = au_do_copy_file(dst, src, len, buf, blksize);
3598+ if (do_kfree)
3599+ kfree(buf);
3600+ else
3601+ free_page((unsigned long)buf);
3602+
4f0767ce 3603+out:
1facf9fc 3604+ return err;
3605+}
3606+
3607+/*
3608+ * to support a sparse file which is opened with O_APPEND,
3609+ * we need to close the file.
3610+ */
3611+static int au_cp_regular(struct dentry *dentry, aufs_bindex_t bdst,
4a4d8108 3612+ aufs_bindex_t bsrc, loff_t len)
1facf9fc 3613+{
3614+ int err, i;
3615+ enum { SRC, DST };
3616+ struct {
3617+ aufs_bindex_t bindex;
3618+ unsigned int flags;
3619+ struct dentry *dentry;
3620+ struct file *file;
3621+ void *label, *label_file;
3622+ } *f, file[] = {
3623+ {
3624+ .bindex = bsrc,
3625+ .flags = O_RDONLY | O_NOATIME | O_LARGEFILE,
3626+ .file = NULL,
3627+ .label = &&out,
3628+ .label_file = &&out_src
3629+ },
3630+ {
3631+ .bindex = bdst,
3632+ .flags = O_WRONLY | O_NOATIME | O_LARGEFILE,
3633+ .file = NULL,
3634+ .label = &&out_src,
3635+ .label_file = &&out_dst
3636+ }
3637+ };
3638+ struct super_block *sb;
3639+
3640+ /* bsrc branch can be ro/rw. */
3641+ sb = dentry->d_sb;
3642+ f = file;
3643+ for (i = 0; i < 2; i++, f++) {
3644+ f->dentry = au_h_dptr(dentry, f->bindex);
3645+ f->file = au_h_open(dentry, f->bindex, f->flags, /*file*/NULL);
3646+ err = PTR_ERR(f->file);
3647+ if (IS_ERR(f->file))
3648+ goto *f->label;
3649+ err = -EINVAL;
3650+ if (unlikely(!f->file->f_op))
3651+ goto *f->label_file;
3652+ }
3653+
3654+ /* try stopping to update while we copyup */
3655+ IMustLock(file[SRC].dentry->d_inode);
3656+ err = au_copy_file(file[DST].file, file[SRC].file, len);
3657+
4f0767ce 3658+out_dst:
1facf9fc 3659+ fput(file[DST].file);
3660+ au_sbr_put(sb, file[DST].bindex);
4f0767ce 3661+out_src:
1facf9fc 3662+ fput(file[SRC].file);
3663+ au_sbr_put(sb, file[SRC].bindex);
4f0767ce 3664+out:
1facf9fc 3665+ return err;
3666+}
3667+
3668+static int au_do_cpup_regular(struct dentry *dentry, aufs_bindex_t bdst,
3669+ aufs_bindex_t bsrc, loff_t len,
3670+ struct inode *h_dir, struct path *h_path)
3671+{
3672+ int err, rerr;
3673+ loff_t l;
3674+
3675+ err = 0;
3676+ l = i_size_read(au_h_iptr(dentry->d_inode, bsrc));
3677+ if (len == -1 || l < len)
3678+ len = l;
3679+ if (len)
3680+ err = au_cp_regular(dentry, bdst, bsrc, len);
3681+ if (!err)
3682+ goto out; /* success */
3683+
3684+ rerr = vfsub_unlink(h_dir, h_path, /*force*/0);
3685+ if (rerr) {
3686+ AuIOErr("failed unlinking cpup-ed %.*s(%d, %d)\n",
3687+ AuDLNPair(h_path->dentry), err, rerr);
3688+ err = -EIO;
3689+ }
3690+
4f0767ce 3691+out:
1facf9fc 3692+ return err;
3693+}
3694+
3695+static int au_do_cpup_symlink(struct path *h_path, struct dentry *h_src,
3696+ struct inode *h_dir)
3697+{
3698+ int err, symlen;
3699+ mm_segment_t old_fs;
b752ccd1
AM
3700+ union {
3701+ char *k;
3702+ char __user *u;
3703+ } sym;
1facf9fc 3704+
3705+ err = -ENOSYS;
3706+ if (unlikely(!h_src->d_inode->i_op->readlink))
3707+ goto out;
3708+
3709+ err = -ENOMEM;
537831f9 3710+ sym.k = (void *)__get_free_page(GFP_NOFS);
b752ccd1 3711+ if (unlikely(!sym.k))
1facf9fc 3712+ goto out;
3713+
9dbd164d 3714+ /* unnecessary to support mmap_sem since symlink is not mmap-able */
1facf9fc 3715+ old_fs = get_fs();
3716+ set_fs(KERNEL_DS);
b752ccd1 3717+ symlen = h_src->d_inode->i_op->readlink(h_src, sym.u, PATH_MAX);
1facf9fc 3718+ err = symlen;
3719+ set_fs(old_fs);
3720+
3721+ if (symlen > 0) {
b752ccd1
AM
3722+ sym.k[symlen] = 0;
3723+ err = vfsub_symlink(h_dir, h_path, sym.k);
1facf9fc 3724+ }
537831f9 3725+ free_page((unsigned long)sym.k);
1facf9fc 3726+
4f0767ce 3727+out:
1facf9fc 3728+ return err;
3729+}
3730+
3731+/* return with the lower dst inode is locked */
3732+static noinline_for_stack
3733+int cpup_entry(struct dentry *dentry, aufs_bindex_t bdst,
3734+ aufs_bindex_t bsrc, loff_t len, unsigned int flags,
3735+ struct dentry *dst_parent)
3736+{
3737+ int err;
3738+ umode_t mode;
3739+ unsigned int mnt_flags;
3740+ unsigned char isdir;
3741+ const unsigned char do_dt = !!au_ftest_cpup(flags, DTIME);
3742+ struct au_dtime dt;
3743+ struct path h_path;
3744+ struct dentry *h_src, *h_dst, *h_parent;
3745+ struct inode *h_inode, *h_dir;
3746+ struct super_block *sb;
3747+
3748+ /* bsrc branch can be ro/rw. */
3749+ h_src = au_h_dptr(dentry, bsrc);
3750+ h_inode = h_src->d_inode;
3751+ AuDebugOn(h_inode != au_h_iptr(dentry->d_inode, bsrc));
3752+
3753+ /* try stopping to be referenced while we are creating */
3754+ h_dst = au_h_dptr(dentry, bdst);
3755+ h_parent = h_dst->d_parent; /* dir inode is locked */
3756+ h_dir = h_parent->d_inode;
3757+ IMustLock(h_dir);
3758+ AuDebugOn(h_parent != h_dst->d_parent);
3759+
3760+ sb = dentry->d_sb;
3761+ h_path.mnt = au_sbr_mnt(sb, bdst);
3762+ if (do_dt) {
3763+ h_path.dentry = h_parent;
3764+ au_dtime_store(&dt, dst_parent, &h_path);
3765+ }
3766+ h_path.dentry = h_dst;
3767+
3768+ isdir = 0;
3769+ mode = h_inode->i_mode;
3770+ switch (mode & S_IFMT) {
3771+ case S_IFREG:
3772+ /* try stopping to update while we are referencing */
3773+ IMustLock(h_inode);
b4510431
AM
3774+ err = vfsub_create(h_dir, &h_path, mode | S_IWUSR,
3775+ /*want_excl*/true);
1facf9fc 3776+ if (!err)
3777+ err = au_do_cpup_regular
3778+ (dentry, bdst, bsrc, len,
3779+ au_h_iptr(dst_parent->d_inode, bdst), &h_path);
3780+ break;
3781+ case S_IFDIR:
3782+ isdir = 1;
3783+ err = vfsub_mkdir(h_dir, &h_path, mode);
3784+ if (!err) {
3785+ /*
3786+ * strange behaviour from the users view,
3787+ * particularry setattr case
3788+ */
3789+ if (au_ibstart(dst_parent->d_inode) == bdst)
3790+ au_cpup_attr_nlink(dst_parent->d_inode,
3791+ /*force*/1);
3792+ au_cpup_attr_nlink(dentry->d_inode, /*force*/1);
3793+ }
3794+ break;
3795+ case S_IFLNK:
3796+ err = au_do_cpup_symlink(&h_path, h_src, h_dir);
3797+ break;
3798+ case S_IFCHR:
3799+ case S_IFBLK:
3800+ AuDebugOn(!capable(CAP_MKNOD));
3801+ /*FALLTHROUGH*/
3802+ case S_IFIFO:
3803+ case S_IFSOCK:
3804+ err = vfsub_mknod(h_dir, &h_path, mode, h_inode->i_rdev);
3805+ break;
3806+ default:
3807+ AuIOErr("Unknown inode type 0%o\n", mode);
3808+ err = -EIO;
3809+ }
3810+
3811+ mnt_flags = au_mntflags(sb);
3812+ if (!au_opt_test(mnt_flags, UDBA_NONE)
3813+ && !isdir
3814+ && au_opt_test(mnt_flags, XINO)
3815+ && h_inode->i_nlink == 1
3816+ /* todo: unnecessary? */
3817+ /* && dentry->d_inode->i_nlink == 1 */
3818+ && bdst < bsrc
3819+ && !au_ftest_cpup(flags, KEEPLINO))
1308ab2a 3820+ au_xino_write(sb, bsrc, h_inode->i_ino, /*ino*/0);
1facf9fc 3821+ /* ignore this error */
3822+
3823+ if (do_dt)
3824+ au_dtime_revert(&dt);
3825+ return err;
3826+}
3827+
3828+/*
3829+ * copyup the @dentry from @bsrc to @bdst.
3830+ * the caller must set the both of lower dentries.
3831+ * @len is for truncating when it is -1 copyup the entire file.
3832+ * in link/rename cases, @dst_parent may be different from the real one.
3833+ */
3834+static int au_cpup_single(struct dentry *dentry, aufs_bindex_t bdst,
3835+ aufs_bindex_t bsrc, loff_t len, unsigned int flags,
3836+ struct dentry *dst_parent)
3837+{
3838+ int err, rerr;
3839+ aufs_bindex_t old_ibstart;
3840+ unsigned char isdir, plink;
3841+ struct au_dtime dt;
3842+ struct path h_path;
3843+ struct dentry *h_src, *h_dst, *h_parent;
3844+ struct inode *dst_inode, *h_dir, *inode;
3845+ struct super_block *sb;
3846+
3847+ AuDebugOn(bsrc <= bdst);
3848+
3849+ sb = dentry->d_sb;
3850+ h_path.mnt = au_sbr_mnt(sb, bdst);
3851+ h_dst = au_h_dptr(dentry, bdst);
3852+ h_parent = h_dst->d_parent; /* dir inode is locked */
3853+ h_dir = h_parent->d_inode;
3854+ IMustLock(h_dir);
3855+
3856+ h_src = au_h_dptr(dentry, bsrc);
3857+ inode = dentry->d_inode;
3858+
3859+ if (!dst_parent)
3860+ dst_parent = dget_parent(dentry);
3861+ else
3862+ dget(dst_parent);
3863+
3864+ plink = !!au_opt_test(au_mntflags(sb), PLINK);
3865+ dst_inode = au_h_iptr(inode, bdst);
3866+ if (dst_inode) {
3867+ if (unlikely(!plink)) {
3868+ err = -EIO;
027c5e7a
AM
3869+ AuIOErr("hi%lu(i%lu) exists on b%d "
3870+ "but plink is disabled\n",
3871+ dst_inode->i_ino, inode->i_ino, bdst);
1facf9fc 3872+ goto out;
3873+ }
3874+
3875+ if (dst_inode->i_nlink) {
3876+ const int do_dt = au_ftest_cpup(flags, DTIME);
3877+
3878+ h_src = au_plink_lkup(inode, bdst);
3879+ err = PTR_ERR(h_src);
3880+ if (IS_ERR(h_src))
3881+ goto out;
3882+ if (unlikely(!h_src->d_inode)) {
3883+ err = -EIO;
3884+ AuIOErr("i%lu exists on a upper branch "
027c5e7a
AM
3885+ "but not pseudo-linked\n",
3886+ inode->i_ino);
1facf9fc 3887+ dput(h_src);
3888+ goto out;
3889+ }
3890+
3891+ if (do_dt) {
3892+ h_path.dentry = h_parent;
3893+ au_dtime_store(&dt, dst_parent, &h_path);
3894+ }
3895+ h_path.dentry = h_dst;
3896+ err = vfsub_link(h_src, h_dir, &h_path);
3897+ if (do_dt)
3898+ au_dtime_revert(&dt);
3899+ dput(h_src);
3900+ goto out;
3901+ } else
3902+ /* todo: cpup_wh_file? */
3903+ /* udba work */
4a4d8108 3904+ au_update_ibrange(inode, /*do_put_zero*/1);
1facf9fc 3905+ }
3906+
3907+ old_ibstart = au_ibstart(inode);
3908+ err = cpup_entry(dentry, bdst, bsrc, len, flags, dst_parent);
3909+ if (unlikely(err))
3910+ goto out;
3911+ dst_inode = h_dst->d_inode;
3912+ mutex_lock_nested(&dst_inode->i_mutex, AuLsc_I_CHILD2);
3913+
3914+ err = cpup_iattr(dentry, bdst, h_src);
3915+ isdir = S_ISDIR(dst_inode->i_mode);
3916+ if (!err) {
4a4d8108
AM
3917+ if (bdst < old_ibstart) {
3918+ if (S_ISREG(inode->i_mode)) {
3919+ err = au_dy_iaop(inode, bdst, dst_inode);
3920+ if (unlikely(err))
3921+ goto out_rev;
3922+ }
1facf9fc 3923+ au_set_ibstart(inode, bdst);
4a4d8108 3924+ }
1facf9fc 3925+ au_set_h_iptr(inode, bdst, au_igrab(dst_inode),
3926+ au_hi_flags(inode, isdir));
3927+ mutex_unlock(&dst_inode->i_mutex);
3928+ if (!isdir
3929+ && h_src->d_inode->i_nlink > 1
3930+ && plink)
3931+ au_plink_append(inode, bdst, h_dst);
3932+ goto out; /* success */
3933+ }
3934+
3935+ /* revert */
4a4d8108 3936+out_rev:
1facf9fc 3937+ h_path.dentry = h_parent;
3938+ mutex_unlock(&dst_inode->i_mutex);
3939+ au_dtime_store(&dt, dst_parent, &h_path);
3940+ h_path.dentry = h_dst;
3941+ if (!isdir)
3942+ rerr = vfsub_unlink(h_dir, &h_path, /*force*/0);
3943+ else
3944+ rerr = vfsub_rmdir(h_dir, &h_path);
3945+ au_dtime_revert(&dt);
3946+ if (rerr) {
3947+ AuIOErr("failed removing broken entry(%d, %d)\n", err, rerr);
3948+ err = -EIO;
3949+ }
3950+
4f0767ce 3951+out:
1facf9fc 3952+ dput(dst_parent);
3953+ return err;
3954+}
3955+
3956+struct au_cpup_single_args {
3957+ int *errp;
3958+ struct dentry *dentry;
3959+ aufs_bindex_t bdst, bsrc;
3960+ loff_t len;
3961+ unsigned int flags;
3962+ struct dentry *dst_parent;
3963+};
3964+
3965+static void au_call_cpup_single(void *args)
3966+{
3967+ struct au_cpup_single_args *a = args;
3968+ *a->errp = au_cpup_single(a->dentry, a->bdst, a->bsrc, a->len,
3969+ a->flags, a->dst_parent);
3970+}
3971+
53392da6
AM
3972+/*
3973+ * prevent SIGXFSZ in copy-up.
3974+ * testing CAP_MKNOD is for generic fs,
3975+ * but CAP_FSETID is for xfs only, currently.
3976+ */
3977+static int au_cpup_sio_test(struct super_block *sb, umode_t mode)
3978+{
3979+ int do_sio;
3980+
3981+ do_sio = 0;
3982+ if (!au_wkq_test()
3983+ && (!au_sbi(sb)->si_plink_maint_pid
3984+ || au_plink_maint(sb, AuLock_NOPLM))) {
3985+ switch (mode & S_IFMT) {
3986+ case S_IFREG:
3987+ /* no condition about RLIMIT_FSIZE and the file size */
3988+ do_sio = 1;
3989+ break;
3990+ case S_IFCHR:
3991+ case S_IFBLK:
3992+ do_sio = !capable(CAP_MKNOD);
3993+ break;
3994+ }
3995+ if (!do_sio)
3996+ do_sio = ((mode & (S_ISUID | S_ISGID))
3997+ && !capable(CAP_FSETID));
3998+ }
3999+
4000+ return do_sio;
4001+}
4002+
1facf9fc 4003+int au_sio_cpup_single(struct dentry *dentry, aufs_bindex_t bdst,
4004+ aufs_bindex_t bsrc, loff_t len, unsigned int flags,
4005+ struct dentry *dst_parent)
4006+{
4007+ int err, wkq_err;
1facf9fc 4008+ struct dentry *h_dentry;
4009+
4010+ h_dentry = au_h_dptr(dentry, bsrc);
53392da6 4011+ if (!au_cpup_sio_test(dentry->d_sb, h_dentry->d_inode->i_mode))
1facf9fc 4012+ err = au_cpup_single(dentry, bdst, bsrc, len, flags,
4013+ dst_parent);
4014+ else {
4015+ struct au_cpup_single_args args = {
4016+ .errp = &err,
4017+ .dentry = dentry,
4018+ .bdst = bdst,
4019+ .bsrc = bsrc,
4020+ .len = len,
4021+ .flags = flags,
4022+ .dst_parent = dst_parent
4023+ };
4024+ wkq_err = au_wkq_wait(au_call_cpup_single, &args);
4025+ if (unlikely(wkq_err))
4026+ err = wkq_err;
4027+ }
4028+
4029+ return err;
4030+}
4031+
4032+/*
4033+ * copyup the @dentry from the first active lower branch to @bdst,
4034+ * using au_cpup_single().
4035+ */
4036+static int au_cpup_simple(struct dentry *dentry, aufs_bindex_t bdst, loff_t len,
4037+ unsigned int flags)
4038+{
4039+ int err;
4040+ aufs_bindex_t bsrc, bend;
4041+
4042+ bend = au_dbend(dentry);
4043+ for (bsrc = bdst + 1; bsrc <= bend; bsrc++)
4044+ if (au_h_dptr(dentry, bsrc))
4045+ break;
4046+
4047+ err = au_lkup_neg(dentry, bdst);
4048+ if (!err) {
4049+ err = au_cpup_single(dentry, bdst, bsrc, len, flags, NULL);
4050+ if (!err)
4051+ return 0; /* success */
4052+
4053+ /* revert */
4054+ au_set_h_dptr(dentry, bdst, NULL);
4055+ au_set_dbstart(dentry, bsrc);
4056+ }
4057+
4058+ return err;
4059+}
4060+
4061+struct au_cpup_simple_args {
4062+ int *errp;
4063+ struct dentry *dentry;
4064+ aufs_bindex_t bdst;
4065+ loff_t len;
4066+ unsigned int flags;
4067+};
4068+
4069+static void au_call_cpup_simple(void *args)
4070+{
4071+ struct au_cpup_simple_args *a = args;
4072+ *a->errp = au_cpup_simple(a->dentry, a->bdst, a->len, a->flags);
4073+}
4074+
4075+int au_sio_cpup_simple(struct dentry *dentry, aufs_bindex_t bdst, loff_t len,
4076+ unsigned int flags)
4077+{
4078+ int err, wkq_err;
1facf9fc 4079+ struct dentry *parent;
4080+ struct inode *h_dir;
4081+
4082+ parent = dget_parent(dentry);
4083+ h_dir = au_h_iptr(parent->d_inode, bdst);
53392da6
AM
4084+ if (!au_test_h_perm_sio(h_dir, MAY_EXEC | MAY_WRITE)
4085+ && !au_cpup_sio_test(dentry->d_sb, dentry->d_inode->i_mode))
1facf9fc 4086+ err = au_cpup_simple(dentry, bdst, len, flags);
4087+ else {
4088+ struct au_cpup_simple_args args = {
4089+ .errp = &err,
4090+ .dentry = dentry,
4091+ .bdst = bdst,
4092+ .len = len,
4093+ .flags = flags
4094+ };
4095+ wkq_err = au_wkq_wait(au_call_cpup_simple, &args);
4096+ if (unlikely(wkq_err))
4097+ err = wkq_err;
4098+ }
4099+
4100+ dput(parent);
4101+ return err;
4102+}
4103+
4104+/* ---------------------------------------------------------------------- */
4105+
4106+/*
4107+ * copyup the deleted file for writing.
4108+ */
4109+static int au_do_cpup_wh(struct dentry *dentry, aufs_bindex_t bdst,
4110+ struct dentry *wh_dentry, struct file *file,
4111+ loff_t len)
4112+{
4113+ int err;
4114+ aufs_bindex_t bstart;
4115+ struct au_dinfo *dinfo;
4116+ struct dentry *h_d_dst, *h_d_start;
4a4d8108 4117+ struct au_hdentry *hdp;
1facf9fc 4118+
4119+ dinfo = au_di(dentry);
1308ab2a 4120+ AuRwMustWriteLock(&dinfo->di_rwsem);
4121+
1facf9fc 4122+ bstart = dinfo->di_bstart;
4a4d8108
AM
4123+ hdp = dinfo->di_hdentry;
4124+ h_d_dst = hdp[0 + bdst].hd_dentry;
1facf9fc 4125+ dinfo->di_bstart = bdst;
4a4d8108 4126+ hdp[0 + bdst].hd_dentry = wh_dentry;
027c5e7a
AM
4127+ if (file) {
4128+ h_d_start = hdp[0 + bstart].hd_dentry;
4a4d8108 4129+ hdp[0 + bstart].hd_dentry = au_hf_top(file)->f_dentry;
027c5e7a 4130+ }
1facf9fc 4131+ err = au_cpup_single(dentry, bdst, bstart, len, !AuCpup_DTIME,
4132+ /*h_parent*/NULL);
027c5e7a
AM
4133+ if (file) {
4134+ if (!err)
4135+ err = au_reopen_nondir(file);
4a4d8108 4136+ hdp[0 + bstart].hd_dentry = h_d_start;
1facf9fc 4137+ }
4a4d8108 4138+ hdp[0 + bdst].hd_dentry = h_d_dst;
1facf9fc 4139+ dinfo->di_bstart = bstart;
4140+
4141+ return err;
4142+}
4143+
4144+static int au_cpup_wh(struct dentry *dentry, aufs_bindex_t bdst, loff_t len,
4145+ struct file *file)
4146+{
4147+ int err;
4148+ struct au_dtime dt;
4149+ struct dentry *parent, *h_parent, *wh_dentry;
4150+ struct au_branch *br;
4151+ struct path h_path;
4152+
4153+ br = au_sbr(dentry->d_sb, bdst);
4154+ parent = dget_parent(dentry);
4155+ h_parent = au_h_dptr(parent, bdst);
4156+ wh_dentry = au_whtmp_lkup(h_parent, br, &dentry->d_name);
4157+ err = PTR_ERR(wh_dentry);
4158+ if (IS_ERR(wh_dentry))
4159+ goto out;
4160+
4161+ h_path.dentry = h_parent;
4162+ h_path.mnt = br->br_mnt;
4163+ au_dtime_store(&dt, parent, &h_path);
4164+ err = au_do_cpup_wh(dentry, bdst, wh_dentry, file, len);
4165+ if (unlikely(err))
4166+ goto out_wh;
4167+
4168+ dget(wh_dentry);
4169+ h_path.dentry = wh_dentry;
4a4d8108
AM
4170+ if (!S_ISDIR(wh_dentry->d_inode->i_mode))
4171+ err = vfsub_unlink(h_parent->d_inode, &h_path, /*force*/0);
4172+ else
4173+ err = vfsub_rmdir(h_parent->d_inode, &h_path);
1facf9fc 4174+ if (unlikely(err)) {
4175+ AuIOErr("failed remove copied-up tmp file %.*s(%d)\n",
4176+ AuDLNPair(wh_dentry), err);
4177+ err = -EIO;
4178+ }
4179+ au_dtime_revert(&dt);
4180+ au_set_hi_wh(dentry->d_inode, bdst, wh_dentry);
4181+
4f0767ce 4182+out_wh:
1facf9fc 4183+ dput(wh_dentry);
4f0767ce 4184+out:
1facf9fc 4185+ dput(parent);
4186+ return err;
4187+}
4188+
4189+struct au_cpup_wh_args {
4190+ int *errp;
4191+ struct dentry *dentry;
4192+ aufs_bindex_t bdst;
4193+ loff_t len;
4194+ struct file *file;
4195+};
4196+
4197+static void au_call_cpup_wh(void *args)
4198+{
4199+ struct au_cpup_wh_args *a = args;
4200+ *a->errp = au_cpup_wh(a->dentry, a->bdst, a->len, a->file);
4201+}
4202+
4203+int au_sio_cpup_wh(struct dentry *dentry, aufs_bindex_t bdst, loff_t len,
4204+ struct file *file)
4205+{
4206+ int err, wkq_err;
4207+ struct dentry *parent, *h_orph, *h_parent, *h_dentry;
4208+ struct inode *dir, *h_dir, *h_tmpdir, *h_inode;
4209+ struct au_wbr *wbr;
4210+
4211+ parent = dget_parent(dentry);
4212+ dir = parent->d_inode;
4213+ h_orph = NULL;
4214+ h_parent = NULL;
4215+ h_dir = au_igrab(au_h_iptr(dir, bdst));
4216+ h_tmpdir = h_dir;
4217+ if (!h_dir->i_nlink) {
4218+ wbr = au_sbr(dentry->d_sb, bdst)->br_wbr;
4219+ h_orph = wbr->wbr_orph;
4220+
4221+ h_parent = dget(au_h_dptr(parent, bdst));
1facf9fc 4222+ au_set_h_dptr(parent, bdst, dget(h_orph));
4223+ h_tmpdir = h_orph->d_inode;
1facf9fc 4224+ au_set_h_iptr(dir, bdst, au_igrab(h_tmpdir), /*flags*/0);
4225+
4226+ /* this temporary unlock is safe */
4227+ if (file)
4a4d8108 4228+ h_dentry = au_hf_top(file)->f_dentry;
1facf9fc 4229+ else
4230+ h_dentry = au_h_dptr(dentry, au_dbstart(dentry));
4231+ h_inode = h_dentry->d_inode;
4232+ IMustLock(h_inode);
4233+ mutex_unlock(&h_inode->i_mutex);
dece6358 4234+ mutex_lock_nested(&h_tmpdir->i_mutex, AuLsc_I_PARENT3);
1facf9fc 4235+ mutex_lock_nested(&h_inode->i_mutex, AuLsc_I_CHILD);
4a4d8108 4236+ /* todo: au_h_open_pre()? */
1facf9fc 4237+ }
4238+
53392da6
AM
4239+ if (!au_test_h_perm_sio(h_tmpdir, MAY_EXEC | MAY_WRITE)
4240+ && !au_cpup_sio_test(dentry->d_sb, dentry->d_inode->i_mode))
1facf9fc 4241+ err = au_cpup_wh(dentry, bdst, len, file);
4242+ else {
4243+ struct au_cpup_wh_args args = {
4244+ .errp = &err,
4245+ .dentry = dentry,
4246+ .bdst = bdst,
4247+ .len = len,
4248+ .file = file
4249+ };
4250+ wkq_err = au_wkq_wait(au_call_cpup_wh, &args);
4251+ if (unlikely(wkq_err))
4252+ err = wkq_err;
4253+ }
4254+
4255+ if (h_orph) {
4256+ mutex_unlock(&h_tmpdir->i_mutex);
4a4d8108 4257+ /* todo: au_h_open_post()? */
1facf9fc 4258+ au_set_h_iptr(dir, bdst, au_igrab(h_dir), /*flags*/0);
1facf9fc 4259+ au_set_h_dptr(parent, bdst, h_parent);
4260+ }
4261+ iput(h_dir);
4262+ dput(parent);
4263+
4264+ return err;
4265+}
4266+
4267+/* ---------------------------------------------------------------------- */
4268+
4269+/*
4270+ * generic routine for both of copy-up and copy-down.
4271+ */
4272+/* cf. revalidate function in file.c */
4273+int au_cp_dirs(struct dentry *dentry, aufs_bindex_t bdst,
4274+ int (*cp)(struct dentry *dentry, aufs_bindex_t bdst,
4275+ struct dentry *h_parent, void *arg),
4276+ void *arg)
4277+{
4278+ int err;
4279+ struct au_pin pin;
4280+ struct dentry *d, *parent, *h_parent, *real_parent;
4281+
4282+ err = 0;
4283+ parent = dget_parent(dentry);
4284+ if (IS_ROOT(parent))
4285+ goto out;
4286+
4287+ au_pin_init(&pin, dentry, bdst, AuLsc_DI_PARENT2, AuLsc_I_PARENT2,
4288+ au_opt_udba(dentry->d_sb), AuPin_MNT_WRITE);
4289+
4290+ /* do not use au_dpage */
4291+ real_parent = parent;
4292+ while (1) {
4293+ dput(parent);
4294+ parent = dget_parent(dentry);
4295+ h_parent = au_h_dptr(parent, bdst);
4296+ if (h_parent)
4297+ goto out; /* success */
4298+
4299+ /* find top dir which is necessary to cpup */
4300+ do {
4301+ d = parent;
4302+ dput(parent);
4303+ parent = dget_parent(d);
4304+ di_read_lock_parent3(parent, !AuLock_IR);
4305+ h_parent = au_h_dptr(parent, bdst);
4306+ di_read_unlock(parent, !AuLock_IR);
4307+ } while (!h_parent);
4308+
4309+ if (d != real_parent)
4310+ di_write_lock_child3(d);
4311+
4312+ /* somebody else might create while we were sleeping */
4313+ if (!au_h_dptr(d, bdst) || !au_h_dptr(d, bdst)->d_inode) {
4314+ if (au_h_dptr(d, bdst))
4315+ au_update_dbstart(d);
4316+
4317+ au_pin_set_dentry(&pin, d);
4318+ err = au_do_pin(&pin);
4319+ if (!err) {
4320+ err = cp(d, bdst, h_parent, arg);
4321+ au_unpin(&pin);
4322+ }
4323+ }
4324+
4325+ if (d != real_parent)
4326+ di_write_unlock(d);
4327+ if (unlikely(err))
4328+ break;
4329+ }
4330+
4f0767ce 4331+out:
1facf9fc 4332+ dput(parent);
4333+ return err;
4334+}
4335+
4336+static int au_cpup_dir(struct dentry *dentry, aufs_bindex_t bdst,
4337+ struct dentry *h_parent __maybe_unused ,
4338+ void *arg __maybe_unused)
4339+{
4340+ return au_sio_cpup_simple(dentry, bdst, -1, AuCpup_DTIME);
4341+}
4342+
4343+int au_cpup_dirs(struct dentry *dentry, aufs_bindex_t bdst)
4344+{
4345+ return au_cp_dirs(dentry, bdst, au_cpup_dir, NULL);
4346+}
4347+
4348+int au_test_and_cpup_dirs(struct dentry *dentry, aufs_bindex_t bdst)
4349+{
4350+ int err;
4351+ struct dentry *parent;
4352+ struct inode *dir;
4353+
4354+ parent = dget_parent(dentry);
4355+ dir = parent->d_inode;
4356+ err = 0;
4357+ if (au_h_iptr(dir, bdst))
4358+ goto out;
4359+
4360+ di_read_unlock(parent, AuLock_IR);
4361+ di_write_lock_parent(parent);
4362+ /* someone else might change our inode while we were sleeping */
4363+ if (!au_h_iptr(dir, bdst))
4364+ err = au_cpup_dirs(dentry, bdst);
4365+ di_downgrade_lock(parent, AuLock_IR);
4366+
4f0767ce 4367+out:
1facf9fc 4368+ dput(parent);
4369+ return err;
4370+}
7f207e10
AM
4371diff -urN /usr/share/empty/fs/aufs/cpup.h linux/fs/aufs/cpup.h
4372--- /usr/share/empty/fs/aufs/cpup.h 1970-01-01 01:00:00.000000000 +0100
537831f9 4373+++ linux/fs/aufs/cpup.h 2012-12-13 20:41:10.428126759 +0100
f6c5ef8b 4374@@ -0,0 +1,81 @@
1facf9fc 4375+/*
f6c5ef8b 4376+ * Copyright (C) 2005-2012 Junjiro R. Okajima
1facf9fc 4377+ *
4378+ * This program, aufs is free software; you can redistribute it and/or modify
4379+ * it under the terms of the GNU General Public License as published by
4380+ * the Free Software Foundation; either version 2 of the License, or
4381+ * (at your option) any later version.
dece6358
AM
4382+ *
4383+ * This program is distributed in the hope that it will be useful,
4384+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
4385+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
4386+ * GNU General Public License for more details.
4387+ *
4388+ * You should have received a copy of the GNU General Public License
4389+ * along with this program; if not, write to the Free Software
4390+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 4391+ */
4392+
4393+/*
4394+ * copy-up/down functions
4395+ */
4396+
4397+#ifndef __AUFS_CPUP_H__
4398+#define __AUFS_CPUP_H__
4399+
4400+#ifdef __KERNEL__
4401+
dece6358 4402+#include <linux/path.h>
1facf9fc 4403+
dece6358
AM
4404+struct inode;
4405+struct file;
4406+
1facf9fc 4407+void au_cpup_attr_flags(struct inode *dst, struct inode *src);
4408+void au_cpup_attr_timesizes(struct inode *inode);
4409+void au_cpup_attr_nlink(struct inode *inode, int force);
4410+void au_cpup_attr_changeable(struct inode *inode);
4411+void au_cpup_igen(struct inode *inode, struct inode *h_inode);
4412+void au_cpup_attr_all(struct inode *inode, int force);
4413+
4414+/* ---------------------------------------------------------------------- */
4415+
4416+/* cpup flags */
4417+#define AuCpup_DTIME 1 /* do dtime_store/revert */
4418+#define AuCpup_KEEPLINO (1 << 1) /* do not clear the lower xino,
4419+ for link(2) */
4420+#define au_ftest_cpup(flags, name) ((flags) & AuCpup_##name)
7f207e10
AM
4421+#define au_fset_cpup(flags, name) \
4422+ do { (flags) |= AuCpup_##name; } while (0)
4423+#define au_fclr_cpup(flags, name) \
4424+ do { (flags) &= ~AuCpup_##name; } while (0)
1facf9fc 4425+
4426+int au_copy_file(struct file *dst, struct file *src, loff_t len);
4427+int au_sio_cpup_single(struct dentry *dentry, aufs_bindex_t bdst,
4428+ aufs_bindex_t bsrc, loff_t len, unsigned int flags,
4429+ struct dentry *dst_parent);
4430+int au_sio_cpup_simple(struct dentry *dentry, aufs_bindex_t bdst, loff_t len,
4431+ unsigned int flags);
4432+int au_sio_cpup_wh(struct dentry *dentry, aufs_bindex_t bdst, loff_t len,
4433+ struct file *file);
4434+
4435+int au_cp_dirs(struct dentry *dentry, aufs_bindex_t bdst,
4436+ int (*cp)(struct dentry *dentry, aufs_bindex_t bdst,
4437+ struct dentry *h_parent, void *arg),
4438+ void *arg);
4439+int au_cpup_dirs(struct dentry *dentry, aufs_bindex_t bdst);
4440+int au_test_and_cpup_dirs(struct dentry *dentry, aufs_bindex_t bdst);
4441+
4442+/* ---------------------------------------------------------------------- */
4443+
4444+/* keep timestamps when copyup */
4445+struct au_dtime {
4446+ struct dentry *dt_dentry;
4447+ struct path dt_h_path;
4448+ struct timespec dt_atime, dt_mtime;
4449+};
4450+void au_dtime_store(struct au_dtime *dt, struct dentry *dentry,
4451+ struct path *h_path);
4452+void au_dtime_revert(struct au_dtime *dt);
4453+
4454+#endif /* __KERNEL__ */
4455+#endif /* __AUFS_CPUP_H__ */
7f207e10
AM
4456diff -urN /usr/share/empty/fs/aufs/dbgaufs.c linux/fs/aufs/dbgaufs.c
4457--- /usr/share/empty/fs/aufs/dbgaufs.c 1970-01-01 01:00:00.000000000 +0100
537831f9 4458+++ linux/fs/aufs/dbgaufs.c 2012-12-13 20:41:10.428126759 +0100
4a4d8108 4459@@ -0,0 +1,334 @@
1facf9fc 4460+/*
f6c5ef8b 4461+ * Copyright (C) 2005-2012 Junjiro R. Okajima
1facf9fc 4462+ *
4463+ * This program, aufs is free software; you can redistribute it and/or modify
4464+ * it under the terms of the GNU General Public License as published by
4465+ * the Free Software Foundation; either version 2 of the License, or
4466+ * (at your option) any later version.
dece6358
AM
4467+ *
4468+ * This program is distributed in the hope that it will be useful,
4469+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
4470+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
4471+ * GNU General Public License for more details.
4472+ *
4473+ * You should have received a copy of the GNU General Public License
4474+ * along with this program; if not, write to the Free Software
4475+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 4476+ */
4477+
4478+/*
4479+ * debugfs interface
4480+ */
4481+
4482+#include <linux/debugfs.h>
4483+#include "aufs.h"
4484+
4485+#ifndef CONFIG_SYSFS
4486+#error DEBUG_FS depends upon SYSFS
4487+#endif
4488+
4489+static struct dentry *dbgaufs;
4490+static const mode_t dbgaufs_mode = S_IRUSR | S_IRGRP | S_IROTH;
4491+
4492+/* 20 is max digits length of ulong 64 */
4493+struct dbgaufs_arg {
4494+ int n;
4495+ char a[20 * 4];
4496+};
4497+
4498+/*
4499+ * common function for all XINO files
4500+ */
4501+static int dbgaufs_xi_release(struct inode *inode __maybe_unused,
4502+ struct file *file)
4503+{
4504+ kfree(file->private_data);
4505+ return 0;
4506+}
4507+
4508+static int dbgaufs_xi_open(struct file *xf, struct file *file, int do_fcnt)
4509+{
4510+ int err;
4511+ struct kstat st;
4512+ struct dbgaufs_arg *p;
4513+
4514+ err = -ENOMEM;
4515+ p = kmalloc(sizeof(*p), GFP_NOFS);
4516+ if (unlikely(!p))
4517+ goto out;
4518+
4519+ err = 0;
4520+ p->n = 0;
4521+ file->private_data = p;
4522+ if (!xf)
4523+ goto out;
4524+
4525+ err = vfs_getattr(xf->f_vfsmnt, xf->f_dentry, &st);
4526+ if (!err) {
4527+ if (do_fcnt)
4528+ p->n = snprintf
4529+ (p->a, sizeof(p->a), "%ld, %llux%lu %lld\n",
4530+ (long)file_count(xf), st.blocks, st.blksize,
4531+ (long long)st.size);
4532+ else
4533+ p->n = snprintf(p->a, sizeof(p->a), "%llux%lu %lld\n",
4534+ st.blocks, st.blksize,
4535+ (long long)st.size);
4536+ AuDebugOn(p->n >= sizeof(p->a));
4537+ } else {
4538+ p->n = snprintf(p->a, sizeof(p->a), "err %d\n", err);
4539+ err = 0;
4540+ }
4541+
4f0767ce 4542+out:
1facf9fc 4543+ return err;
4544+
4545+}
4546+
4547+static ssize_t dbgaufs_xi_read(struct file *file, char __user *buf,
4548+ size_t count, loff_t *ppos)
4549+{
4550+ struct dbgaufs_arg *p;
4551+
4552+ p = file->private_data;
4553+ return simple_read_from_buffer(buf, count, ppos, p->a, p->n);
4554+}
4555+
4556+/* ---------------------------------------------------------------------- */
4557+
4558+static int dbgaufs_xib_open(struct inode *inode, struct file *file)
4559+{
4560+ int err;
4561+ struct au_sbinfo *sbinfo;
4562+ struct super_block *sb;
4563+
4564+ sbinfo = inode->i_private;
4565+ sb = sbinfo->si_sb;
4566+ si_noflush_read_lock(sb);
4567+ err = dbgaufs_xi_open(sbinfo->si_xib, file, /*do_fcnt*/0);
4568+ si_read_unlock(sb);
4569+ return err;
4570+}
4571+
4572+static const struct file_operations dbgaufs_xib_fop = {
4a4d8108 4573+ .owner = THIS_MODULE,
1facf9fc 4574+ .open = dbgaufs_xib_open,
4575+ .release = dbgaufs_xi_release,
4576+ .read = dbgaufs_xi_read
4577+};
4578+
4579+/* ---------------------------------------------------------------------- */
4580+
4581+#define DbgaufsXi_PREFIX "xi"
4582+
4583+static int dbgaufs_xino_open(struct inode *inode, struct file *file)
4584+{
4585+ int err;
4586+ long l;
4587+ struct au_sbinfo *sbinfo;
4588+ struct super_block *sb;
4589+ struct file *xf;
4590+ struct qstr *name;
4591+
4592+ err = -ENOENT;
4593+ xf = NULL;
4594+ name = &file->f_dentry->d_name;
4595+ if (unlikely(name->len < sizeof(DbgaufsXi_PREFIX)
4596+ || memcmp(name->name, DbgaufsXi_PREFIX,
4597+ sizeof(DbgaufsXi_PREFIX) - 1)))
4598+ goto out;
9dbd164d 4599+ err = kstrtol(name->name + sizeof(DbgaufsXi_PREFIX) - 1, 10, &l);
1facf9fc 4600+ if (unlikely(err))
4601+ goto out;
4602+
4603+ sbinfo = inode->i_private;
4604+ sb = sbinfo->si_sb;
4605+ si_noflush_read_lock(sb);
4606+ if (l <= au_sbend(sb)) {
4607+ xf = au_sbr(sb, (aufs_bindex_t)l)->br_xino.xi_file;
4608+ err = dbgaufs_xi_open(xf, file, /*do_fcnt*/1);
4609+ } else
4610+ err = -ENOENT;
4611+ si_read_unlock(sb);
4612+
4f0767ce 4613+out:
1facf9fc 4614+ return err;
4615+}
4616+
4617+static const struct file_operations dbgaufs_xino_fop = {
4a4d8108 4618+ .owner = THIS_MODULE,
1facf9fc 4619+ .open = dbgaufs_xino_open,
4620+ .release = dbgaufs_xi_release,
4621+ .read = dbgaufs_xi_read
4622+};
4623+
4624+void dbgaufs_brs_del(struct super_block *sb, aufs_bindex_t bindex)
4625+{
4626+ aufs_bindex_t bend;
4627+ struct au_branch *br;
4628+ struct au_xino_file *xi;
4629+
4630+ if (!au_sbi(sb)->si_dbgaufs)
4631+ return;
4632+
4633+ bend = au_sbend(sb);
4634+ for (; bindex <= bend; bindex++) {
4635+ br = au_sbr(sb, bindex);
4636+ xi = &br->br_xino;
4637+ if (xi->xi_dbgaufs) {
4638+ debugfs_remove(xi->xi_dbgaufs);
4639+ xi->xi_dbgaufs = NULL;
4640+ }
4641+ }
4642+}
4643+
4644+void dbgaufs_brs_add(struct super_block *sb, aufs_bindex_t bindex)
4645+{
4646+ struct au_sbinfo *sbinfo;
4647+ struct dentry *parent;
4648+ struct au_branch *br;
4649+ struct au_xino_file *xi;
4650+ aufs_bindex_t bend;
4651+ char name[sizeof(DbgaufsXi_PREFIX) + 5]; /* "xi" bindex NULL */
4652+
4653+ sbinfo = au_sbi(sb);
4654+ parent = sbinfo->si_dbgaufs;
4655+ if (!parent)
4656+ return;
4657+
4658+ bend = au_sbend(sb);
4659+ for (; bindex <= bend; bindex++) {
4660+ snprintf(name, sizeof(name), DbgaufsXi_PREFIX "%d", bindex);
4661+ br = au_sbr(sb, bindex);
4662+ xi = &br->br_xino;
4663+ AuDebugOn(xi->xi_dbgaufs);
4664+ xi->xi_dbgaufs = debugfs_create_file(name, dbgaufs_mode, parent,
4665+ sbinfo, &dbgaufs_xino_fop);
4666+ /* ignore an error */
4667+ if (unlikely(!xi->xi_dbgaufs))
4668+ AuWarn1("failed %s under debugfs\n", name);
4669+ }
4670+}
4671+
4672+/* ---------------------------------------------------------------------- */
4673+
4674+#ifdef CONFIG_AUFS_EXPORT
4675+static int dbgaufs_xigen_open(struct inode *inode, struct file *file)
4676+{
4677+ int err;
4678+ struct au_sbinfo *sbinfo;
4679+ struct super_block *sb;
4680+
4681+ sbinfo = inode->i_private;
4682+ sb = sbinfo->si_sb;
4683+ si_noflush_read_lock(sb);
4684+ err = dbgaufs_xi_open(sbinfo->si_xigen, file, /*do_fcnt*/0);
4685+ si_read_unlock(sb);
4686+ return err;
4687+}
4688+
4689+static const struct file_operations dbgaufs_xigen_fop = {
4a4d8108 4690+ .owner = THIS_MODULE,
1facf9fc 4691+ .open = dbgaufs_xigen_open,
4692+ .release = dbgaufs_xi_release,
4693+ .read = dbgaufs_xi_read
4694+};
4695+
4696+static int dbgaufs_xigen_init(struct au_sbinfo *sbinfo)
4697+{
4698+ int err;
4699+
dece6358
AM
4700+ /*
4701+ * This function is a dynamic '__init' fucntion actually,
4702+ * so the tiny check for si_rwsem is unnecessary.
4703+ */
4704+ /* AuRwMustWriteLock(&sbinfo->si_rwsem); */
4705+
1facf9fc 4706+ err = -EIO;
4707+ sbinfo->si_dbgaufs_xigen = debugfs_create_file
4708+ ("xigen", dbgaufs_mode, sbinfo->si_dbgaufs, sbinfo,
4709+ &dbgaufs_xigen_fop);
4710+ if (sbinfo->si_dbgaufs_xigen)
4711+ err = 0;
4712+
4713+ return err;
4714+}
4715+#else
4716+static int dbgaufs_xigen_init(struct au_sbinfo *sbinfo)
4717+{
4718+ return 0;
4719+}
4720+#endif /* CONFIG_AUFS_EXPORT */
4721+
4722+/* ---------------------------------------------------------------------- */
4723+
4724+void dbgaufs_si_fin(struct au_sbinfo *sbinfo)
4725+{
dece6358
AM
4726+ /*
4727+ * This function is a dynamic '__init' fucntion actually,
4728+ * so the tiny check for si_rwsem is unnecessary.
4729+ */
4730+ /* AuRwMustWriteLock(&sbinfo->si_rwsem); */
4731+
1facf9fc 4732+ debugfs_remove_recursive(sbinfo->si_dbgaufs);
4733+ sbinfo->si_dbgaufs = NULL;
4734+ kobject_put(&sbinfo->si_kobj);
4735+}
4736+
4737+int dbgaufs_si_init(struct au_sbinfo *sbinfo)
4738+{
4739+ int err;
4740+ char name[SysaufsSiNameLen];
4741+
dece6358
AM
4742+ /*
4743+ * This function is a dynamic '__init' fucntion actually,
4744+ * so the tiny check for si_rwsem is unnecessary.
4745+ */
4746+ /* AuRwMustWriteLock(&sbinfo->si_rwsem); */
4747+
1facf9fc 4748+ err = -ENOENT;
4749+ if (!dbgaufs) {
4750+ AuErr1("/debug/aufs is uninitialized\n");
4751+ goto out;
4752+ }
4753+
4754+ err = -EIO;
4755+ sysaufs_name(sbinfo, name);
4756+ sbinfo->si_dbgaufs = debugfs_create_dir(name, dbgaufs);
4757+ if (unlikely(!sbinfo->si_dbgaufs))
4758+ goto out;
4759+ kobject_get(&sbinfo->si_kobj);
4760+
4761+ sbinfo->si_dbgaufs_xib = debugfs_create_file
4762+ ("xib", dbgaufs_mode, sbinfo->si_dbgaufs, sbinfo,
4763+ &dbgaufs_xib_fop);
4764+ if (unlikely(!sbinfo->si_dbgaufs_xib))
4765+ goto out_dir;
4766+
4767+ err = dbgaufs_xigen_init(sbinfo);
4768+ if (!err)
4769+ goto out; /* success */
4770+
4f0767ce 4771+out_dir:
1facf9fc 4772+ dbgaufs_si_fin(sbinfo);
4f0767ce 4773+out:
1facf9fc 4774+ return err;
4775+}
4776+
4777+/* ---------------------------------------------------------------------- */
4778+
4779+void dbgaufs_fin(void)
4780+{
4781+ debugfs_remove(dbgaufs);
4782+}
4783+
4784+int __init dbgaufs_init(void)
4785+{
4786+ int err;
4787+
4788+ err = -EIO;
4789+ dbgaufs = debugfs_create_dir(AUFS_NAME, NULL);
4790+ if (dbgaufs)
4791+ err = 0;
4792+ return err;
4793+}
7f207e10
AM
4794diff -urN /usr/share/empty/fs/aufs/dbgaufs.h linux/fs/aufs/dbgaufs.h
4795--- /usr/share/empty/fs/aufs/dbgaufs.h 1970-01-01 01:00:00.000000000 +0100
537831f9 4796+++ linux/fs/aufs/dbgaufs.h 2012-12-13 20:41:10.428126759 +0100
f6c5ef8b 4797@@ -0,0 +1,49 @@
1facf9fc 4798+/*
f6c5ef8b 4799+ * Copyright (C) 2005-2012 Junjiro R. Okajima
1facf9fc 4800+ *
4801+ * This program, aufs is free software; you can redistribute it and/or modify
4802+ * it under the terms of the GNU General Public License as published by
4803+ * the Free Software Foundation; either version 2 of the License, or
4804+ * (at your option) any later version.
dece6358
AM
4805+ *
4806+ * This program is distributed in the hope that it will be useful,
4807+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
4808+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
4809+ * GNU General Public License for more details.
4810+ *
4811+ * You should have received a copy of the GNU General Public License
4812+ * along with this program; if not, write to the Free Software
4813+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 4814+ */
4815+
4816+/*
4817+ * debugfs interface
4818+ */
4819+
4820+#ifndef __DBGAUFS_H__
4821+#define __DBGAUFS_H__
4822+
4823+#ifdef __KERNEL__
4824+
dece6358 4825+struct super_block;
1facf9fc 4826+struct au_sbinfo;
dece6358 4827+
1facf9fc 4828+#ifdef CONFIG_DEBUG_FS
4829+/* dbgaufs.c */
4830+void dbgaufs_brs_del(struct super_block *sb, aufs_bindex_t bindex);
4831+void dbgaufs_brs_add(struct super_block *sb, aufs_bindex_t bindex);
4832+void dbgaufs_si_fin(struct au_sbinfo *sbinfo);
4833+int dbgaufs_si_init(struct au_sbinfo *sbinfo);
4834+void dbgaufs_fin(void);
4835+int __init dbgaufs_init(void);
1facf9fc 4836+#else
4a4d8108
AM
4837+AuStubVoid(dbgaufs_brs_del, struct super_block *sb, aufs_bindex_t bindex)
4838+AuStubVoid(dbgaufs_brs_add, struct super_block *sb, aufs_bindex_t bindex)
4839+AuStubVoid(dbgaufs_si_fin, struct au_sbinfo *sbinfo)
4840+AuStubInt0(dbgaufs_si_init, struct au_sbinfo *sbinfo)
4841+AuStubVoid(dbgaufs_fin, void)
4842+AuStubInt0(__init dbgaufs_init, void)
1facf9fc 4843+#endif /* CONFIG_DEBUG_FS */
4844+
4845+#endif /* __KERNEL__ */
4846+#endif /* __DBGAUFS_H__ */
7f207e10
AM
4847diff -urN /usr/share/empty/fs/aufs/dcsub.c linux/fs/aufs/dcsub.c
4848--- /usr/share/empty/fs/aufs/dcsub.c 1970-01-01 01:00:00.000000000 +0100
537831f9 4849+++ linux/fs/aufs/dcsub.c 2012-12-13 20:41:10.428126759 +0100
027c5e7a 4850@@ -0,0 +1,243 @@
1facf9fc 4851+/*
f6c5ef8b 4852+ * Copyright (C) 2005-2012 Junjiro R. Okajima
1facf9fc 4853+ *
4854+ * This program, aufs is free software; you can redistribute it and/or modify
4855+ * it under the terms of the GNU General Public License as published by
4856+ * the Free Software Foundation; either version 2 of the License, or
4857+ * (at your option) any later version.
dece6358
AM
4858+ *
4859+ * This program is distributed in the hope that it will be useful,
4860+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
4861+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
4862+ * GNU General Public License for more details.
4863+ *
4864+ * You should have received a copy of the GNU General Public License
4865+ * along with this program; if not, write to the Free Software
4866+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 4867+ */
4868+
4869+/*
4870+ * sub-routines for dentry cache
4871+ */
4872+
4873+#include "aufs.h"
4874+
4875+static void au_dpage_free(struct au_dpage *dpage)
4876+{
4877+ int i;
4878+ struct dentry **p;
4879+
4880+ p = dpage->dentries;
4881+ for (i = 0; i < dpage->ndentry; i++)
4882+ dput(*p++);
4883+ free_page((unsigned long)dpage->dentries);
4884+}
4885+
4886+int au_dpages_init(struct au_dcsub_pages *dpages, gfp_t gfp)
4887+{
4888+ int err;
4889+ void *p;
4890+
4891+ err = -ENOMEM;
4892+ dpages->dpages = kmalloc(sizeof(*dpages->dpages), gfp);
4893+ if (unlikely(!dpages->dpages))
4894+ goto out;
4895+
4896+ p = (void *)__get_free_page(gfp);
4897+ if (unlikely(!p))
4898+ goto out_dpages;
4899+
4900+ dpages->dpages[0].ndentry = 0;
4901+ dpages->dpages[0].dentries = p;
4902+ dpages->ndpage = 1;
4903+ return 0; /* success */
4904+
4f0767ce 4905+out_dpages:
1facf9fc 4906+ kfree(dpages->dpages);
4f0767ce 4907+out:
1facf9fc 4908+ return err;
4909+}
4910+
4911+void au_dpages_free(struct au_dcsub_pages *dpages)
4912+{
4913+ int i;
4914+ struct au_dpage *p;
4915+
4916+ p = dpages->dpages;
4917+ for (i = 0; i < dpages->ndpage; i++)
4918+ au_dpage_free(p++);
4919+ kfree(dpages->dpages);
4920+}
4921+
4922+static int au_dpages_append(struct au_dcsub_pages *dpages,
4923+ struct dentry *dentry, gfp_t gfp)
4924+{
4925+ int err, sz;
4926+ struct au_dpage *dpage;
4927+ void *p;
4928+
4929+ dpage = dpages->dpages + dpages->ndpage - 1;
4930+ sz = PAGE_SIZE / sizeof(dentry);
4931+ if (unlikely(dpage->ndentry >= sz)) {
4932+ AuLabel(new dpage);
4933+ err = -ENOMEM;
4934+ sz = dpages->ndpage * sizeof(*dpages->dpages);
4935+ p = au_kzrealloc(dpages->dpages, sz,
4936+ sz + sizeof(*dpages->dpages), gfp);
4937+ if (unlikely(!p))
4938+ goto out;
4939+
4940+ dpages->dpages = p;
4941+ dpage = dpages->dpages + dpages->ndpage;
4942+ p = (void *)__get_free_page(gfp);
4943+ if (unlikely(!p))
4944+ goto out;
4945+
4946+ dpage->ndentry = 0;
4947+ dpage->dentries = p;
4948+ dpages->ndpage++;
4949+ }
4950+
027c5e7a
AM
4951+ AuDebugOn(!dentry->d_count);
4952+ dpage->dentries[dpage->ndentry++] = dget_dlock(dentry);
1facf9fc 4953+ return 0; /* success */
4954+
4f0767ce 4955+out:
1facf9fc 4956+ return err;
4957+}
4958+
4959+int au_dcsub_pages(struct au_dcsub_pages *dpages, struct dentry *root,
4960+ au_dpages_test test, void *arg)
4961+{
4962+ int err;
027c5e7a 4963+ struct dentry *this_parent;
1facf9fc 4964+ struct list_head *next;
4965+ struct super_block *sb = root->d_sb;
4966+
4967+ err = 0;
027c5e7a
AM
4968+ write_seqlock(&rename_lock);
4969+ this_parent = root;
4970+ spin_lock(&this_parent->d_lock);
4f0767ce 4971+repeat:
1facf9fc 4972+ next = this_parent->d_subdirs.next;
4f0767ce 4973+resume:
1facf9fc 4974+ if (this_parent->d_sb == sb
4975+ && !IS_ROOT(this_parent)
027c5e7a
AM
4976+ && au_di(this_parent)
4977+ && this_parent->d_count
1facf9fc 4978+ && (!test || test(this_parent, arg))) {
4979+ err = au_dpages_append(dpages, this_parent, GFP_ATOMIC);
4980+ if (unlikely(err))
4981+ goto out;
4982+ }
4983+
4984+ while (next != &this_parent->d_subdirs) {
4985+ struct list_head *tmp = next;
4986+ struct dentry *dentry = list_entry(tmp, struct dentry,
4987+ d_u.d_child);
027c5e7a 4988+
1facf9fc 4989+ next = tmp->next;
027c5e7a
AM
4990+ spin_lock_nested(&dentry->d_lock, DENTRY_D_LOCK_NESTED);
4991+ if (dentry->d_count) {
4992+ if (!list_empty(&dentry->d_subdirs)) {
4993+ spin_unlock(&this_parent->d_lock);
4994+ spin_release(&dentry->d_lock.dep_map, 1,
4995+ _RET_IP_);
4996+ this_parent = dentry;
4997+ spin_acquire(&this_parent->d_lock.dep_map, 0, 1,
4998+ _RET_IP_);
4999+ goto repeat;
5000+ }
5001+ if (dentry->d_sb == sb
5002+ && au_di(dentry)
5003+ && (!test || test(dentry, arg)))
5004+ err = au_dpages_append(dpages, dentry,
5005+ GFP_ATOMIC);
1facf9fc 5006+ }
027c5e7a
AM
5007+ spin_unlock(&dentry->d_lock);
5008+ if (unlikely(err))
5009+ goto out;
1facf9fc 5010+ }
5011+
5012+ if (this_parent != root) {
027c5e7a
AM
5013+ struct dentry *tmp;
5014+ struct dentry *child;
5015+
5016+ tmp = this_parent->d_parent;
5017+ rcu_read_lock();
5018+ spin_unlock(&this_parent->d_lock);
5019+ child = this_parent;
5020+ this_parent = tmp;
5021+ spin_lock(&this_parent->d_lock);
5022+ rcu_read_unlock();
5023+ next = child->d_u.d_child.next;
1facf9fc 5024+ goto resume;
5025+ }
027c5e7a 5026+
4f0767ce 5027+out:
027c5e7a
AM
5028+ spin_unlock(&this_parent->d_lock);
5029+ write_sequnlock(&rename_lock);
1facf9fc 5030+ return err;
5031+}
5032+
5033+int au_dcsub_pages_rev(struct au_dcsub_pages *dpages, struct dentry *dentry,
5034+ int do_include, au_dpages_test test, void *arg)
5035+{
5036+ int err;
5037+
5038+ err = 0;
027c5e7a
AM
5039+ write_seqlock(&rename_lock);
5040+ spin_lock(&dentry->d_lock);
5041+ if (do_include
5042+ && dentry->d_count
5043+ && (!test || test(dentry, arg)))
1facf9fc 5044+ err = au_dpages_append(dpages, dentry, GFP_ATOMIC);
027c5e7a
AM
5045+ spin_unlock(&dentry->d_lock);
5046+ if (unlikely(err))
5047+ goto out;
5048+
5049+ /*
5050+ * vfsmount_lock is unnecessary since this is a traverse in a single
5051+ * mount
5052+ */
1facf9fc 5053+ while (!IS_ROOT(dentry)) {
027c5e7a
AM
5054+ dentry = dentry->d_parent; /* rename_lock is locked */
5055+ spin_lock(&dentry->d_lock);
5056+ if (dentry->d_count
5057+ && (!test || test(dentry, arg)))
1facf9fc 5058+ err = au_dpages_append(dpages, dentry, GFP_ATOMIC);
027c5e7a
AM
5059+ spin_unlock(&dentry->d_lock);
5060+ if (unlikely(err))
5061+ break;
1facf9fc 5062+ }
5063+
4f0767ce 5064+out:
027c5e7a 5065+ write_sequnlock(&rename_lock);
1facf9fc 5066+ return err;
5067+}
5068+
027c5e7a
AM
5069+static inline int au_dcsub_dpages_aufs(struct dentry *dentry, void *arg)
5070+{
5071+ return au_di(dentry) && dentry->d_sb == arg;
5072+}
5073+
5074+int au_dcsub_pages_rev_aufs(struct au_dcsub_pages *dpages,
5075+ struct dentry *dentry, int do_include)
5076+{
5077+ return au_dcsub_pages_rev(dpages, dentry, do_include,
5078+ au_dcsub_dpages_aufs, dentry->d_sb);
5079+}
5080+
4a4d8108 5081+int au_test_subdir(struct dentry *d1, struct dentry *d2)
1facf9fc 5082+{
4a4d8108
AM
5083+ struct path path[2] = {
5084+ {
5085+ .dentry = d1
5086+ },
5087+ {
5088+ .dentry = d2
5089+ }
5090+ };
1facf9fc 5091+
4a4d8108 5092+ return path_is_under(path + 0, path + 1);
1facf9fc 5093+}
7f207e10
AM
5094diff -urN /usr/share/empty/fs/aufs/dcsub.h linux/fs/aufs/dcsub.h
5095--- /usr/share/empty/fs/aufs/dcsub.h 1970-01-01 01:00:00.000000000 +0100
537831f9 5096+++ linux/fs/aufs/dcsub.h 2012-12-13 20:41:10.428126759 +0100
f6c5ef8b 5097@@ -0,0 +1,94 @@
1facf9fc 5098+/*
f6c5ef8b 5099+ * Copyright (C) 2005-2012 Junjiro R. Okajima
1facf9fc 5100+ *
5101+ * This program, aufs is free software; you can redistribute it and/or modify
5102+ * it under the terms of the GNU General Public License as published by
5103+ * the Free Software Foundation; either version 2 of the License, or
5104+ * (at your option) any later version.
dece6358
AM
5105+ *
5106+ * This program is distributed in the hope that it will be useful,
5107+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
5108+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
5109+ * GNU General Public License for more details.
5110+ *
5111+ * You should have received a copy of the GNU General Public License
5112+ * along with this program; if not, write to the Free Software
5113+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 5114+ */
5115+
5116+/*
5117+ * sub-routines for dentry cache
5118+ */
5119+
5120+#ifndef __AUFS_DCSUB_H__
5121+#define __AUFS_DCSUB_H__
5122+
5123+#ifdef __KERNEL__
5124+
7f207e10 5125+#include <linux/dcache.h>
027c5e7a 5126+#include <linux/fs.h>
dece6358
AM
5127+
5128+struct dentry;
1facf9fc 5129+
5130+struct au_dpage {
5131+ int ndentry;
5132+ struct dentry **dentries;
5133+};
5134+
5135+struct au_dcsub_pages {
5136+ int ndpage;
5137+ struct au_dpage *dpages;
5138+};
5139+
5140+/* ---------------------------------------------------------------------- */
5141+
7f207e10 5142+/* dcsub.c */
1facf9fc 5143+int au_dpages_init(struct au_dcsub_pages *dpages, gfp_t gfp);
5144+void au_dpages_free(struct au_dcsub_pages *dpages);
5145+typedef int (*au_dpages_test)(struct dentry *dentry, void *arg);
5146+int au_dcsub_pages(struct au_dcsub_pages *dpages, struct dentry *root,
5147+ au_dpages_test test, void *arg);
5148+int au_dcsub_pages_rev(struct au_dcsub_pages *dpages, struct dentry *dentry,
5149+ int do_include, au_dpages_test test, void *arg);
027c5e7a
AM
5150+int au_dcsub_pages_rev_aufs(struct au_dcsub_pages *dpages,
5151+ struct dentry *dentry, int do_include);
4a4d8108 5152+int au_test_subdir(struct dentry *d1, struct dentry *d2);
1facf9fc 5153+
7f207e10
AM
5154+/* ---------------------------------------------------------------------- */
5155+
027c5e7a
AM
5156+static inline int au_d_hashed_positive(struct dentry *d)
5157+{
5158+ int err;
5159+ struct inode *inode = d->d_inode;
5160+ err = 0;
5161+ if (unlikely(d_unhashed(d) || !inode || !inode->i_nlink))
5162+ err = -ENOENT;
5163+ return err;
5164+}
5165+
5166+static inline int au_d_alive(struct dentry *d)
5167+{
5168+ int err;
5169+ struct inode *inode;
5170+ err = 0;
5171+ if (!IS_ROOT(d))
5172+ err = au_d_hashed_positive(d);
5173+ else {
5174+ inode = d->d_inode;
5175+ if (unlikely(d_unlinked(d) || !inode || !inode->i_nlink))
5176+ err = -ENOENT;
5177+ }
5178+ return err;
5179+}
5180+
5181+static inline int au_alive_dir(struct dentry *d)
7f207e10 5182+{
027c5e7a
AM
5183+ int err;
5184+ err = au_d_alive(d);
5185+ if (unlikely(err || IS_DEADDIR(d->d_inode)))
5186+ err = -ENOENT;
5187+ return err;
7f207e10
AM
5188+}
5189+
1facf9fc 5190+#endif /* __KERNEL__ */
5191+#endif /* __AUFS_DCSUB_H__ */
7f207e10
AM
5192diff -urN /usr/share/empty/fs/aufs/debug.c linux/fs/aufs/debug.c
5193--- /usr/share/empty/fs/aufs/debug.c 1970-01-01 01:00:00.000000000 +0100
537831f9 5194+++ linux/fs/aufs/debug.c 2012-12-13 20:41:10.428126759 +0100
b4510431 5195@@ -0,0 +1,490 @@
1facf9fc 5196+/*
f6c5ef8b 5197+ * Copyright (C) 2005-2012 Junjiro R. Okajima
1facf9fc 5198+ *
5199+ * This program, aufs is free software; you can redistribute it and/or modify
5200+ * it under the terms of the GNU General Public License as published by
5201+ * the Free Software Foundation; either version 2 of the License, or
5202+ * (at your option) any later version.
dece6358
AM
5203+ *
5204+ * This program is distributed in the hope that it will be useful,
5205+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
5206+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
5207+ * GNU General Public License for more details.
5208+ *
5209+ * You should have received a copy of the GNU General Public License
5210+ * along with this program; if not, write to the Free Software
5211+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 5212+ */
5213+
5214+/*
5215+ * debug print functions
5216+ */
5217+
7f207e10 5218+#include <linux/vt_kern.h>
1facf9fc 5219+#include "aufs.h"
5220+
5221+int aufs_debug;
5222+MODULE_PARM_DESC(debug, "debug print");
5223+module_param_named(debug, aufs_debug, int, S_IRUGO | S_IWUSR | S_IWGRP);
5224+
5225+char *au_plevel = KERN_DEBUG;
e49829fe
JR
5226+#define dpri(fmt, ...) do { \
5227+ if ((au_plevel \
5228+ && strcmp(au_plevel, KERN_DEBUG)) \
5229+ || au_debug_test()) \
5230+ printk("%s" fmt, au_plevel, ##__VA_ARGS__); \
1facf9fc 5231+} while (0)
5232+
5233+/* ---------------------------------------------------------------------- */
5234+
5235+void au_dpri_whlist(struct au_nhash *whlist)
5236+{
5237+ unsigned long ul, n;
5238+ struct hlist_head *head;
5239+ struct au_vdir_wh *tpos;
5240+ struct hlist_node *pos;
5241+
5242+ n = whlist->nh_num;
5243+ head = whlist->nh_head;
5244+ for (ul = 0; ul < n; ul++) {
5245+ hlist_for_each_entry(tpos, pos, head, wh_hash)
5246+ dpri("b%d, %.*s, %d\n",
5247+ tpos->wh_bindex,
5248+ tpos->wh_str.len, tpos->wh_str.name,
5249+ tpos->wh_str.len);
5250+ head++;
5251+ }
5252+}
5253+
5254+void au_dpri_vdir(struct au_vdir *vdir)
5255+{
5256+ unsigned long ul;
5257+ union au_vdir_deblk_p p;
5258+ unsigned char *o;
5259+
5260+ if (!vdir || IS_ERR(vdir)) {
5261+ dpri("err %ld\n", PTR_ERR(vdir));
5262+ return;
5263+ }
5264+
5265+ dpri("deblk %u, nblk %lu, deblk %p, last{%lu, %p}, ver %lu\n",
5266+ vdir->vd_deblk_sz, vdir->vd_nblk, vdir->vd_deblk,
5267+ vdir->vd_last.ul, vdir->vd_last.p.deblk, vdir->vd_version);
5268+ for (ul = 0; ul < vdir->vd_nblk; ul++) {
5269+ p.deblk = vdir->vd_deblk[ul];
5270+ o = p.deblk;
5271+ dpri("[%lu]: %p\n", ul, o);
5272+ }
5273+}
5274+
53392da6 5275+static int do_pri_inode(aufs_bindex_t bindex, struct inode *inode, int hn,
1facf9fc 5276+ struct dentry *wh)
5277+{
5278+ char *n = NULL;
5279+ int l = 0;
5280+
5281+ if (!inode || IS_ERR(inode)) {
5282+ dpri("i%d: err %ld\n", bindex, PTR_ERR(inode));
5283+ return -1;
5284+ }
5285+
5286+ /* the type of i_blocks depends upon CONFIG_LSF */
5287+ BUILD_BUG_ON(sizeof(inode->i_blocks) != sizeof(unsigned long)
5288+ && sizeof(inode->i_blocks) != sizeof(u64));
5289+ if (wh) {
5290+ n = (void *)wh->d_name.name;
5291+ l = wh->d_name.len;
5292+ }
5293+
53392da6
AM
5294+ dpri("i%d: %p, i%lu, %s, cnt %d, nl %u, 0%o, sz %llu, blk %llu,"
5295+ " hn %d, ct %lld, np %lu, st 0x%lx, f 0x%x, v %llu, g %x%s%.*s\n",
5296+ bindex, inode,
1facf9fc 5297+ inode->i_ino, inode->i_sb ? au_sbtype(inode->i_sb) : "??",
5298+ atomic_read(&inode->i_count), inode->i_nlink, inode->i_mode,
5299+ i_size_read(inode), (unsigned long long)inode->i_blocks,
53392da6 5300+ hn, (long long)timespec_to_ns(&inode->i_ctime) & 0x0ffff,
1facf9fc 5301+ inode->i_mapping ? inode->i_mapping->nrpages : 0,
b752ccd1
AM
5302+ inode->i_state, inode->i_flags, inode->i_version,
5303+ inode->i_generation,
1facf9fc 5304+ l ? ", wh " : "", l, n);
5305+ return 0;
5306+}
5307+
5308+void au_dpri_inode(struct inode *inode)
5309+{
5310+ struct au_iinfo *iinfo;
5311+ aufs_bindex_t bindex;
53392da6 5312+ int err, hn;
1facf9fc 5313+
53392da6 5314+ err = do_pri_inode(-1, inode, -1, NULL);
1facf9fc 5315+ if (err || !au_test_aufs(inode->i_sb))
5316+ return;
5317+
5318+ iinfo = au_ii(inode);
5319+ if (!iinfo)
5320+ return;
5321+ dpri("i-1: bstart %d, bend %d, gen %d\n",
537831f9 5322+ iinfo->ii_bstart, iinfo->ii_bend, au_iigen(inode, NULL));
1facf9fc 5323+ if (iinfo->ii_bstart < 0)
5324+ return;
53392da6
AM
5325+ hn = 0;
5326+ for (bindex = iinfo->ii_bstart; bindex <= iinfo->ii_bend; bindex++) {
5327+ hn = !!au_hn(iinfo->ii_hinode + bindex);
5328+ do_pri_inode(bindex, iinfo->ii_hinode[0 + bindex].hi_inode, hn,
1facf9fc 5329+ iinfo->ii_hinode[0 + bindex].hi_whdentry);
53392da6 5330+ }
1facf9fc 5331+}
5332+
2cbb1c4b
JR
5333+void au_dpri_dalias(struct inode *inode)
5334+{
5335+ struct dentry *d;
b4510431 5336+ struct hlist_node *p;
2cbb1c4b
JR
5337+
5338+ spin_lock(&inode->i_lock);
b4510431 5339+ hlist_for_each_entry(d, p, &inode->i_dentry, d_alias)
2cbb1c4b
JR
5340+ au_dpri_dentry(d);
5341+ spin_unlock(&inode->i_lock);
5342+}
5343+
1facf9fc 5344+static int do_pri_dentry(aufs_bindex_t bindex, struct dentry *dentry)
5345+{
5346+ struct dentry *wh = NULL;
53392da6 5347+ int hn;
1facf9fc 5348+
5349+ if (!dentry || IS_ERR(dentry)) {
5350+ dpri("d%d: err %ld\n", bindex, PTR_ERR(dentry));
5351+ return -1;
5352+ }
5353+ /* do not call dget_parent() here */
027c5e7a 5354+ /* note: access d_xxx without d_lock */
1facf9fc 5355+ dpri("d%d: %.*s?/%.*s, %s, cnt %d, flags 0x%x\n",
5356+ bindex,
5357+ AuDLNPair(dentry->d_parent), AuDLNPair(dentry),
5358+ dentry->d_sb ? au_sbtype(dentry->d_sb) : "??",
027c5e7a 5359+ dentry->d_count, dentry->d_flags);
53392da6 5360+ hn = -1;
1facf9fc 5361+ if (bindex >= 0 && dentry->d_inode && au_test_aufs(dentry->d_sb)) {
5362+ struct au_iinfo *iinfo = au_ii(dentry->d_inode);
53392da6
AM
5363+ if (iinfo) {
5364+ hn = !!au_hn(iinfo->ii_hinode + bindex);
1facf9fc 5365+ wh = iinfo->ii_hinode[0 + bindex].hi_whdentry;
53392da6 5366+ }
1facf9fc 5367+ }
53392da6 5368+ do_pri_inode(bindex, dentry->d_inode, hn, wh);
1facf9fc 5369+ return 0;
5370+}
5371+
5372+void au_dpri_dentry(struct dentry *dentry)
5373+{
5374+ struct au_dinfo *dinfo;
5375+ aufs_bindex_t bindex;
5376+ int err;
4a4d8108 5377+ struct au_hdentry *hdp;
1facf9fc 5378+
5379+ err = do_pri_dentry(-1, dentry);
5380+ if (err || !au_test_aufs(dentry->d_sb))
5381+ return;
5382+
5383+ dinfo = au_di(dentry);
5384+ if (!dinfo)
5385+ return;
5386+ dpri("d-1: bstart %d, bend %d, bwh %d, bdiropq %d, gen %d\n",
5387+ dinfo->di_bstart, dinfo->di_bend,
5388+ dinfo->di_bwh, dinfo->di_bdiropq, au_digen(dentry));
5389+ if (dinfo->di_bstart < 0)
5390+ return;
4a4d8108 5391+ hdp = dinfo->di_hdentry;
1facf9fc 5392+ for (bindex = dinfo->di_bstart; bindex <= dinfo->di_bend; bindex++)
4a4d8108 5393+ do_pri_dentry(bindex, hdp[0 + bindex].hd_dentry);
1facf9fc 5394+}
5395+
5396+static int do_pri_file(aufs_bindex_t bindex, struct file *file)
5397+{
5398+ char a[32];
5399+
5400+ if (!file || IS_ERR(file)) {
5401+ dpri("f%d: err %ld\n", bindex, PTR_ERR(file));
5402+ return -1;
5403+ }
5404+ a[0] = 0;
5405+ if (bindex < 0
5406+ && file->f_dentry
5407+ && au_test_aufs(file->f_dentry->d_sb)
5408+ && au_fi(file))
e49829fe 5409+ snprintf(a, sizeof(a), ", gen %d, mmapped %d",
2cbb1c4b 5410+ au_figen(file), atomic_read(&au_fi(file)->fi_mmapped));
b752ccd1 5411+ dpri("f%d: mode 0x%x, flags 0%o, cnt %ld, v %llu, pos %llu%s\n",
1facf9fc 5412+ bindex, file->f_mode, file->f_flags, (long)file_count(file),
b752ccd1 5413+ file->f_version, file->f_pos, a);
1facf9fc 5414+ if (file->f_dentry)
5415+ do_pri_dentry(bindex, file->f_dentry);
5416+ return 0;
5417+}
5418+
5419+void au_dpri_file(struct file *file)
5420+{
5421+ struct au_finfo *finfo;
4a4d8108
AM
5422+ struct au_fidir *fidir;
5423+ struct au_hfile *hfile;
1facf9fc 5424+ aufs_bindex_t bindex;
5425+ int err;
5426+
5427+ err = do_pri_file(-1, file);
5428+ if (err || !file->f_dentry || !au_test_aufs(file->f_dentry->d_sb))
5429+ return;
5430+
5431+ finfo = au_fi(file);
5432+ if (!finfo)
5433+ return;
4a4d8108 5434+ if (finfo->fi_btop < 0)
1facf9fc 5435+ return;
4a4d8108
AM
5436+ fidir = finfo->fi_hdir;
5437+ if (!fidir)
5438+ do_pri_file(finfo->fi_btop, finfo->fi_htop.hf_file);
5439+ else
e49829fe
JR
5440+ for (bindex = finfo->fi_btop;
5441+ bindex >= 0 && bindex <= fidir->fd_bbot;
4a4d8108
AM
5442+ bindex++) {
5443+ hfile = fidir->fd_hfile + bindex;
5444+ do_pri_file(bindex, hfile ? hfile->hf_file : NULL);
5445+ }
1facf9fc 5446+}
5447+
5448+static int do_pri_br(aufs_bindex_t bindex, struct au_branch *br)
5449+{
5450+ struct vfsmount *mnt;
5451+ struct super_block *sb;
5452+
5453+ if (!br || IS_ERR(br))
5454+ goto out;
5455+ mnt = br->br_mnt;
5456+ if (!mnt || IS_ERR(mnt))
5457+ goto out;
5458+ sb = mnt->mnt_sb;
5459+ if (!sb || IS_ERR(sb))
5460+ goto out;
5461+
1e00d052 5462+ dpri("s%d: {perm 0x%x, id %d, cnt %d, wbr %p}, "
b752ccd1 5463+ "%s, dev 0x%02x%02x, flags 0x%lx, cnt %d, active %d, "
1facf9fc 5464+ "xino %d\n",
1e00d052
AM
5465+ bindex, br->br_perm, br->br_id, atomic_read(&br->br_count),
5466+ br->br_wbr, au_sbtype(sb), MAJOR(sb->s_dev), MINOR(sb->s_dev),
b752ccd1 5467+ sb->s_flags, sb->s_count,
1facf9fc 5468+ atomic_read(&sb->s_active), !!br->br_xino.xi_file);
5469+ return 0;
5470+
4f0767ce 5471+out:
1facf9fc 5472+ dpri("s%d: err %ld\n", bindex, PTR_ERR(br));
5473+ return -1;
5474+}
5475+
5476+void au_dpri_sb(struct super_block *sb)
5477+{
5478+ struct au_sbinfo *sbinfo;
5479+ aufs_bindex_t bindex;
5480+ int err;
5481+ /* to reuduce stack size */
5482+ struct {
5483+ struct vfsmount mnt;
5484+ struct au_branch fake;
5485+ } *a;
5486+
5487+ /* this function can be called from magic sysrq */
5488+ a = kzalloc(sizeof(*a), GFP_ATOMIC);
5489+ if (unlikely(!a)) {
5490+ dpri("no memory\n");
5491+ return;
5492+ }
5493+
5494+ a->mnt.mnt_sb = sb;
5495+ a->fake.br_perm = 0;
5496+ a->fake.br_mnt = &a->mnt;
5497+ a->fake.br_xino.xi_file = NULL;
5498+ atomic_set(&a->fake.br_count, 0);
5499+ smp_mb(); /* atomic_set */
5500+ err = do_pri_br(-1, &a->fake);
5501+ kfree(a);
5502+ dpri("dev 0x%x\n", sb->s_dev);
5503+ if (err || !au_test_aufs(sb))
5504+ return;
5505+
5506+ sbinfo = au_sbi(sb);
5507+ if (!sbinfo)
5508+ return;
5509+ dpri("nw %d, gen %u, kobj %d\n",
5510+ atomic_read(&sbinfo->si_nowait.nw_len), sbinfo->si_generation,
5511+ atomic_read(&sbinfo->si_kobj.kref.refcount));
5512+ for (bindex = 0; bindex <= sbinfo->si_bend; bindex++)
5513+ do_pri_br(bindex, sbinfo->si_branch[0 + bindex]);
5514+}
5515+
5516+/* ---------------------------------------------------------------------- */
5517+
5518+void au_dbg_sleep_jiffy(int jiffy)
5519+{
5520+ while (jiffy)
5521+ jiffy = schedule_timeout_uninterruptible(jiffy);
5522+}
5523+
5524+void au_dbg_iattr(struct iattr *ia)
5525+{
5526+#define AuBit(name) if (ia->ia_valid & ATTR_ ## name) \
5527+ dpri(#name "\n")
5528+ AuBit(MODE);
5529+ AuBit(UID);
5530+ AuBit(GID);
5531+ AuBit(SIZE);
5532+ AuBit(ATIME);
5533+ AuBit(MTIME);
5534+ AuBit(CTIME);
5535+ AuBit(ATIME_SET);
5536+ AuBit(MTIME_SET);
5537+ AuBit(FORCE);
5538+ AuBit(ATTR_FLAG);
5539+ AuBit(KILL_SUID);
5540+ AuBit(KILL_SGID);
5541+ AuBit(FILE);
5542+ AuBit(KILL_PRIV);
5543+ AuBit(OPEN);
5544+ AuBit(TIMES_SET);
5545+#undef AuBit
5546+ dpri("ia_file %p\n", ia->ia_file);
5547+}
5548+
5549+/* ---------------------------------------------------------------------- */
5550+
027c5e7a
AM
5551+void __au_dbg_verify_dinode(struct dentry *dentry, const char *func, int line)
5552+{
5553+ struct inode *h_inode, *inode = dentry->d_inode;
5554+ struct dentry *h_dentry;
5555+ aufs_bindex_t bindex, bend, bi;
5556+
5557+ if (!inode /* || au_di(dentry)->di_lsc == AuLsc_DI_TMP */)
5558+ return;
5559+
5560+ bend = au_dbend(dentry);
5561+ bi = au_ibend(inode);
5562+ if (bi < bend)
5563+ bend = bi;
5564+ bindex = au_dbstart(dentry);
5565+ bi = au_ibstart(inode);
5566+ if (bi > bindex)
5567+ bindex = bi;
5568+
5569+ for (; bindex <= bend; bindex++) {
5570+ h_dentry = au_h_dptr(dentry, bindex);
5571+ if (!h_dentry)
5572+ continue;
5573+ h_inode = au_h_iptr(inode, bindex);
5574+ if (unlikely(h_inode != h_dentry->d_inode)) {
5575+ int old = au_debug_test();
5576+ if (!old)
5577+ au_debug(1);
5578+ AuDbg("b%d, %s:%d\n", bindex, func, line);
5579+ AuDbgDentry(dentry);
5580+ AuDbgInode(inode);
5581+ if (!old)
5582+ au_debug(0);
5583+ BUG();
5584+ }
5585+ }
5586+}
5587+
1facf9fc 5588+void au_dbg_verify_dir_parent(struct dentry *dentry, unsigned int sigen)
5589+{
5590+ struct dentry *parent;
5591+
5592+ parent = dget_parent(dentry);
027c5e7a
AM
5593+ AuDebugOn(!S_ISDIR(dentry->d_inode->i_mode));
5594+ AuDebugOn(IS_ROOT(dentry));
5595+ AuDebugOn(au_digen_test(parent, sigen));
1facf9fc 5596+ dput(parent);
5597+}
5598+
5599+void au_dbg_verify_nondir_parent(struct dentry *dentry, unsigned int sigen)
5600+{
5601+ struct dentry *parent;
027c5e7a 5602+ struct inode *inode;
1facf9fc 5603+
5604+ parent = dget_parent(dentry);
027c5e7a
AM
5605+ inode = dentry->d_inode;
5606+ AuDebugOn(inode && S_ISDIR(dentry->d_inode->i_mode));
5607+ AuDebugOn(au_digen_test(parent, sigen));
1facf9fc 5608+ dput(parent);
5609+}
5610+
5611+void au_dbg_verify_gen(struct dentry *parent, unsigned int sigen)
5612+{
5613+ int err, i, j;
5614+ struct au_dcsub_pages dpages;
5615+ struct au_dpage *dpage;
5616+ struct dentry **dentries;
5617+
5618+ err = au_dpages_init(&dpages, GFP_NOFS);
5619+ AuDebugOn(err);
027c5e7a 5620+ err = au_dcsub_pages_rev_aufs(&dpages, parent, /*do_include*/1);
1facf9fc 5621+ AuDebugOn(err);
5622+ for (i = dpages.ndpage - 1; !err && i >= 0; i--) {
5623+ dpage = dpages.dpages + i;
5624+ dentries = dpage->dentries;
5625+ for (j = dpage->ndentry - 1; !err && j >= 0; j--)
027c5e7a 5626+ AuDebugOn(au_digen_test(dentries[j], sigen));
1facf9fc 5627+ }
5628+ au_dpages_free(&dpages);
5629+}
5630+
1facf9fc 5631+void au_dbg_verify_kthread(void)
5632+{
53392da6 5633+ if (au_wkq_test()) {
1facf9fc 5634+ au_dbg_blocked();
1e00d052
AM
5635+ /*
5636+ * It may be recursive, but udba=notify between two aufs mounts,
5637+ * where a single ro branch is shared, is not a problem.
5638+ */
5639+ /* WARN_ON(1); */
1facf9fc 5640+ }
5641+}
5642+
5643+/* ---------------------------------------------------------------------- */
5644+
5645+void au_debug_sbinfo_init(struct au_sbinfo *sbinfo __maybe_unused)
5646+{
5647+#ifdef AuForceNoPlink
5648+ au_opt_clr(sbinfo->si_mntflags, PLINK);
5649+#endif
5650+#ifdef AuForceNoXino
5651+ au_opt_clr(sbinfo->si_mntflags, XINO);
5652+#endif
5653+#ifdef AuForceNoRefrof
5654+ au_opt_clr(sbinfo->si_mntflags, REFROF);
5655+#endif
4a4d8108
AM
5656+#ifdef AuForceHnotify
5657+ au_opt_set_udba(sbinfo->si_mntflags, UDBA_HNOTIFY);
1facf9fc 5658+#endif
1308ab2a 5659+#ifdef AuForceRd0
5660+ sbinfo->si_rdblk = 0;
5661+ sbinfo->si_rdhash = 0;
5662+#endif
1facf9fc 5663+}
5664+
5665+int __init au_debug_init(void)
5666+{
5667+ aufs_bindex_t bindex;
5668+ struct au_vdir_destr destr;
5669+
5670+ bindex = -1;
5671+ AuDebugOn(bindex >= 0);
5672+
5673+ destr.len = -1;
5674+ AuDebugOn(destr.len < NAME_MAX);
5675+
5676+#ifdef CONFIG_4KSTACKS
0c3ec466 5677+ pr_warn("CONFIG_4KSTACKS is defined.\n");
1facf9fc 5678+#endif
5679+
5680+#ifdef AuForceNoBrs
5681+ sysaufs_brs = 0;
5682+#endif
5683+
5684+ return 0;
5685+}
7f207e10
AM
5686diff -urN /usr/share/empty/fs/aufs/debug.h linux/fs/aufs/debug.h
5687--- /usr/share/empty/fs/aufs/debug.h 1970-01-01 01:00:00.000000000 +0100
537831f9 5688+++ linux/fs/aufs/debug.h 2012-12-13 20:41:10.428126759 +0100
92d182d2 5689@@ -0,0 +1,242 @@
1facf9fc 5690+/*
f6c5ef8b 5691+ * Copyright (C) 2005-2012 Junjiro R. Okajima
1facf9fc 5692+ *
5693+ * This program, aufs is free software; you can redistribute it and/or modify
5694+ * it under the terms of the GNU General Public License as published by
5695+ * the Free Software Foundation; either version 2 of the License, or
5696+ * (at your option) any later version.
dece6358
AM
5697+ *
5698+ * This program is distributed in the hope that it will be useful,
5699+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
5700+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
5701+ * GNU General Public License for more details.
5702+ *
5703+ * You should have received a copy of the GNU General Public License
5704+ * along with this program; if not, write to the Free Software
5705+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 5706+ */
5707+
5708+/*
5709+ * debug print functions
5710+ */
5711+
5712+#ifndef __AUFS_DEBUG_H__
5713+#define __AUFS_DEBUG_H__
5714+
5715+#ifdef __KERNEL__
5716+
4a4d8108
AM
5717+#include <linux/module.h>
5718+#include <linux/kallsyms.h>
1facf9fc 5719+#include <linux/sysrq.h>
4a4d8108 5720+
1facf9fc 5721+#ifdef CONFIG_AUFS_DEBUG
5722+#define AuDebugOn(a) BUG_ON(a)
5723+
5724+/* module parameter */
5725+extern int aufs_debug;
5726+static inline void au_debug(int n)
5727+{
5728+ aufs_debug = n;
5729+ smp_mb();
5730+}
5731+
5732+static inline int au_debug_test(void)
5733+{
5734+ return aufs_debug;
5735+}
5736+#else
5737+#define AuDebugOn(a) do {} while (0)
4a4d8108
AM
5738+AuStubVoid(au_debug, int n)
5739+AuStubInt0(au_debug_test, void)
1facf9fc 5740+#endif /* CONFIG_AUFS_DEBUG */
5741+
5742+/* ---------------------------------------------------------------------- */
5743+
5744+/* debug print */
5745+
4a4d8108 5746+#define AuDbg(fmt, ...) do { \
1facf9fc 5747+ if (au_debug_test()) \
4a4d8108 5748+ pr_debug("DEBUG: " fmt, ##__VA_ARGS__); \
1facf9fc 5749+} while (0)
4a4d8108
AM
5750+#define AuLabel(l) AuDbg(#l "\n")
5751+#define AuIOErr(fmt, ...) pr_err("I/O Error, " fmt, ##__VA_ARGS__)
5752+#define AuWarn1(fmt, ...) do { \
1facf9fc 5753+ static unsigned char _c; \
5754+ if (!_c++) \
0c3ec466 5755+ pr_warn(fmt, ##__VA_ARGS__); \
1facf9fc 5756+} while (0)
5757+
4a4d8108 5758+#define AuErr1(fmt, ...) do { \
1facf9fc 5759+ static unsigned char _c; \
5760+ if (!_c++) \
4a4d8108 5761+ pr_err(fmt, ##__VA_ARGS__); \
1facf9fc 5762+} while (0)
5763+
4a4d8108 5764+#define AuIOErr1(fmt, ...) do { \
1facf9fc 5765+ static unsigned char _c; \
5766+ if (!_c++) \
4a4d8108 5767+ AuIOErr(fmt, ##__VA_ARGS__); \
1facf9fc 5768+} while (0)
5769+
5770+#define AuUnsupportMsg "This operation is not supported." \
5771+ " Please report this application to aufs-users ML."
4a4d8108
AM
5772+#define AuUnsupport(fmt, ...) do { \
5773+ pr_err(AuUnsupportMsg "\n" fmt, ##__VA_ARGS__); \
1facf9fc 5774+ dump_stack(); \
5775+} while (0)
5776+
5777+#define AuTraceErr(e) do { \
5778+ if (unlikely((e) < 0)) \
5779+ AuDbg("err %d\n", (int)(e)); \
5780+} while (0)
5781+
5782+#define AuTraceErrPtr(p) do { \
5783+ if (IS_ERR(p)) \
5784+ AuDbg("err %ld\n", PTR_ERR(p)); \
5785+} while (0)
5786+
5787+/* dirty macros for debug print, use with "%.*s" and caution */
5788+#define AuLNPair(qstr) (qstr)->len, (qstr)->name
5789+#define AuDLNPair(d) AuLNPair(&(d)->d_name)
5790+
5791+/* ---------------------------------------------------------------------- */
5792+
5793+struct au_sbinfo;
5794+struct au_finfo;
dece6358 5795+struct dentry;
1facf9fc 5796+#ifdef CONFIG_AUFS_DEBUG
5797+extern char *au_plevel;
5798+struct au_nhash;
5799+void au_dpri_whlist(struct au_nhash *whlist);
5800+struct au_vdir;
5801+void au_dpri_vdir(struct au_vdir *vdir);
dece6358 5802+struct inode;
1facf9fc 5803+void au_dpri_inode(struct inode *inode);
2cbb1c4b 5804+void au_dpri_dalias(struct inode *inode);
1facf9fc 5805+void au_dpri_dentry(struct dentry *dentry);
dece6358 5806+struct file;
1facf9fc 5807+void au_dpri_file(struct file *filp);
dece6358 5808+struct super_block;
1facf9fc 5809+void au_dpri_sb(struct super_block *sb);
5810+
5811+void au_dbg_sleep_jiffy(int jiffy);
dece6358 5812+struct iattr;
1facf9fc 5813+void au_dbg_iattr(struct iattr *ia);
5814+
027c5e7a
AM
5815+#define au_dbg_verify_dinode(d) __au_dbg_verify_dinode(d, __func__, __LINE__)
5816+void __au_dbg_verify_dinode(struct dentry *dentry, const char *func, int line);
1facf9fc 5817+void au_dbg_verify_dir_parent(struct dentry *dentry, unsigned int sigen);
5818+void au_dbg_verify_nondir_parent(struct dentry *dentry, unsigned int sigen);
5819+void au_dbg_verify_gen(struct dentry *parent, unsigned int sigen);
1facf9fc 5820+void au_dbg_verify_kthread(void);
5821+
5822+int __init au_debug_init(void);
5823+void au_debug_sbinfo_init(struct au_sbinfo *sbinfo);
5824+#define AuDbgWhlist(w) do { \
5825+ AuDbg(#w "\n"); \
5826+ au_dpri_whlist(w); \
5827+} while (0)
5828+
5829+#define AuDbgVdir(v) do { \
5830+ AuDbg(#v "\n"); \
5831+ au_dpri_vdir(v); \
5832+} while (0)
5833+
5834+#define AuDbgInode(i) do { \
5835+ AuDbg(#i "\n"); \
5836+ au_dpri_inode(i); \
5837+} while (0)
5838+
2cbb1c4b
JR
5839+#define AuDbgDAlias(i) do { \
5840+ AuDbg(#i "\n"); \
5841+ au_dpri_dalias(i); \
5842+} while (0)
5843+
1facf9fc 5844+#define AuDbgDentry(d) do { \
5845+ AuDbg(#d "\n"); \
5846+ au_dpri_dentry(d); \
5847+} while (0)
5848+
5849+#define AuDbgFile(f) do { \
5850+ AuDbg(#f "\n"); \
5851+ au_dpri_file(f); \
5852+} while (0)
5853+
5854+#define AuDbgSb(sb) do { \
5855+ AuDbg(#sb "\n"); \
5856+ au_dpri_sb(sb); \
5857+} while (0)
5858+
5859+#define AuDbgSleep(sec) do { \
5860+ AuDbg("sleep %d sec\n", sec); \
5861+ ssleep(sec); \
5862+} while (0)
5863+
5864+#define AuDbgSleepJiffy(jiffy) do { \
5865+ AuDbg("sleep %d jiffies\n", jiffy); \
5866+ au_dbg_sleep_jiffy(jiffy); \
5867+} while (0)
5868+
5869+#define AuDbgIAttr(ia) do { \
5870+ AuDbg("ia_valid 0x%x\n", (ia)->ia_valid); \
5871+ au_dbg_iattr(ia); \
5872+} while (0)
4a4d8108
AM
5873+
5874+#define AuDbgSym(addr) do { \
5875+ char sym[KSYM_SYMBOL_LEN]; \
5876+ sprint_symbol(sym, (unsigned long)addr); \
5877+ AuDbg("%s\n", sym); \
5878+} while (0)
5879+
5880+#define AuInfoSym(addr) do { \
5881+ char sym[KSYM_SYMBOL_LEN]; \
5882+ sprint_symbol(sym, (unsigned long)addr); \
5883+ AuInfo("%s\n", sym); \
5884+} while (0)
1facf9fc 5885+#else
027c5e7a 5886+AuStubVoid(au_dbg_verify_dinode, struct dentry *dentry)
4a4d8108
AM
5887+AuStubVoid(au_dbg_verify_dir_parent, struct dentry *dentry, unsigned int sigen)
5888+AuStubVoid(au_dbg_verify_nondir_parent, struct dentry *dentry,
5889+ unsigned int sigen)
5890+AuStubVoid(au_dbg_verify_gen, struct dentry *parent, unsigned int sigen)
5891+AuStubVoid(au_dbg_verify_kthread, void)
5892+AuStubInt0(__init au_debug_init, void)
5893+AuStubVoid(au_debug_sbinfo_init, struct au_sbinfo *sbinfo)
1facf9fc 5894+
1facf9fc 5895+#define AuDbgWhlist(w) do {} while (0)
5896+#define AuDbgVdir(v) do {} while (0)
5897+#define AuDbgInode(i) do {} while (0)
2cbb1c4b 5898+#define AuDbgDAlias(i) do {} while (0)
1facf9fc 5899+#define AuDbgDentry(d) do {} while (0)
5900+#define AuDbgFile(f) do {} while (0)
5901+#define AuDbgSb(sb) do {} while (0)
5902+#define AuDbgSleep(sec) do {} while (0)
5903+#define AuDbgSleepJiffy(jiffy) do {} while (0)
5904+#define AuDbgIAttr(ia) do {} while (0)
4a4d8108
AM
5905+#define AuDbgSym(addr) do {} while (0)
5906+#define AuInfoSym(addr) do {} while (0)
1facf9fc 5907+#endif /* CONFIG_AUFS_DEBUG */
5908+
5909+/* ---------------------------------------------------------------------- */
5910+
5911+#ifdef CONFIG_AUFS_MAGIC_SYSRQ
5912+int __init au_sysrq_init(void);
5913+void au_sysrq_fin(void);
5914+
5915+#ifdef CONFIG_HW_CONSOLE
5916+#define au_dbg_blocked() do { \
5917+ WARN_ON(1); \
0c5527e5 5918+ handle_sysrq('w'); \
1facf9fc 5919+} while (0)
5920+#else
4a4d8108 5921+AuStubVoid(au_dbg_blocked, void)
1facf9fc 5922+#endif
5923+
5924+#else
4a4d8108
AM
5925+AuStubInt0(__init au_sysrq_init, void)
5926+AuStubVoid(au_sysrq_fin, void)
5927+AuStubVoid(au_dbg_blocked, void)
1facf9fc 5928+#endif /* CONFIG_AUFS_MAGIC_SYSRQ */
5929+
5930+#endif /* __KERNEL__ */
5931+#endif /* __AUFS_DEBUG_H__ */
7f207e10
AM
5932diff -urN /usr/share/empty/fs/aufs/dentry.c linux/fs/aufs/dentry.c
5933--- /usr/share/empty/fs/aufs/dentry.c 1970-01-01 01:00:00.000000000 +0100
537831f9
AM
5934+++ linux/fs/aufs/dentry.c 2012-12-13 20:41:10.428126759 +0100
5935@@ -0,0 +1,1060 @@
1facf9fc 5936+/*
f6c5ef8b 5937+ * Copyright (C) 2005-2012 Junjiro R. Okajima
1facf9fc 5938+ *
5939+ * This program, aufs is free software; you can redistribute it and/or modify
5940+ * it under the terms of the GNU General Public License as published by
5941+ * the Free Software Foundation; either version 2 of the License, or
5942+ * (at your option) any later version.
dece6358
AM
5943+ *
5944+ * This program is distributed in the hope that it will be useful,
5945+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
5946+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
5947+ * GNU General Public License for more details.
5948+ *
5949+ * You should have received a copy of the GNU General Public License
5950+ * along with this program; if not, write to the Free Software
5951+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 5952+ */
5953+
5954+/*
5955+ * lookup and dentry operations
5956+ */
5957+
dece6358 5958+#include <linux/namei.h>
1facf9fc 5959+#include "aufs.h"
5960+
1facf9fc 5961+#define AuLkup_ALLOW_NEG 1
5962+#define au_ftest_lkup(flags, name) ((flags) & AuLkup_##name)
7f207e10
AM
5963+#define au_fset_lkup(flags, name) \
5964+ do { (flags) |= AuLkup_##name; } while (0)
5965+#define au_fclr_lkup(flags, name) \
5966+ do { (flags) &= ~AuLkup_##name; } while (0)
1facf9fc 5967+
5968+struct au_do_lookup_args {
5969+ unsigned int flags;
5970+ mode_t type;
1facf9fc 5971+};
5972+
5973+/*
5974+ * returns positive/negative dentry, NULL or an error.
5975+ * NULL means whiteout-ed or not-found.
5976+ */
5977+static struct dentry*
5978+au_do_lookup(struct dentry *h_parent, struct dentry *dentry,
5979+ aufs_bindex_t bindex, struct qstr *wh_name,
5980+ struct au_do_lookup_args *args)
5981+{
5982+ struct dentry *h_dentry;
5983+ struct inode *h_inode, *inode;
1facf9fc 5984+ struct au_branch *br;
5985+ int wh_found, opq;
5986+ unsigned char wh_able;
5987+ const unsigned char allow_neg = !!au_ftest_lkup(args->flags, ALLOW_NEG);
5988+
1facf9fc 5989+ wh_found = 0;
5990+ br = au_sbr(dentry->d_sb, bindex);
5991+ wh_able = !!au_br_whable(br->br_perm);
5992+ if (wh_able)
5993+ wh_found = au_wh_test(h_parent, wh_name, br, /*try_sio*/0);
5994+ h_dentry = ERR_PTR(wh_found);
5995+ if (!wh_found)
5996+ goto real_lookup;
5997+ if (unlikely(wh_found < 0))
5998+ goto out;
5999+
6000+ /* We found a whiteout */
6001+ /* au_set_dbend(dentry, bindex); */
6002+ au_set_dbwh(dentry, bindex);
6003+ if (!allow_neg)
6004+ return NULL; /* success */
6005+
4f0767ce 6006+real_lookup:
b4510431 6007+ h_dentry = vfsub_lkup_one(&dentry->d_name, h_parent);
1facf9fc 6008+ if (IS_ERR(h_dentry))
6009+ goto out;
6010+
6011+ h_inode = h_dentry->d_inode;
6012+ if (!h_inode) {
6013+ if (!allow_neg)
6014+ goto out_neg;
6015+ } else if (wh_found
6016+ || (args->type && args->type != (h_inode->i_mode & S_IFMT)))
6017+ goto out_neg;
6018+
6019+ if (au_dbend(dentry) <= bindex)
6020+ au_set_dbend(dentry, bindex);
6021+ if (au_dbstart(dentry) < 0 || bindex < au_dbstart(dentry))
6022+ au_set_dbstart(dentry, bindex);
6023+ au_set_h_dptr(dentry, bindex, h_dentry);
6024+
6025+ inode = dentry->d_inode;
6026+ if (!h_inode || !S_ISDIR(h_inode->i_mode) || !wh_able
6027+ || (inode && !S_ISDIR(inode->i_mode)))
6028+ goto out; /* success */
6029+
6030+ mutex_lock_nested(&h_inode->i_mutex, AuLsc_I_CHILD);
6031+ opq = au_diropq_test(h_dentry, br);
6032+ mutex_unlock(&h_inode->i_mutex);
6033+ if (opq > 0)
6034+ au_set_dbdiropq(dentry, bindex);
6035+ else if (unlikely(opq < 0)) {
6036+ au_set_h_dptr(dentry, bindex, NULL);
6037+ h_dentry = ERR_PTR(opq);
6038+ }
6039+ goto out;
6040+
4f0767ce 6041+out_neg:
1facf9fc 6042+ dput(h_dentry);
6043+ h_dentry = NULL;
4f0767ce 6044+out:
1facf9fc 6045+ return h_dentry;
6046+}
6047+
dece6358
AM
6048+static int au_test_shwh(struct super_block *sb, const struct qstr *name)
6049+{
6050+ if (unlikely(!au_opt_test(au_mntflags(sb), SHWH)
6051+ && !strncmp(name->name, AUFS_WH_PFX, AUFS_WH_PFX_LEN)))
6052+ return -EPERM;
6053+ return 0;
6054+}
6055+
1facf9fc 6056+/*
6057+ * returns the number of lower positive dentries,
6058+ * otherwise an error.
6059+ * can be called at unlinking with @type is zero.
6060+ */
537831f9 6061+int au_lkup_dentry(struct dentry *dentry, aufs_bindex_t bstart, mode_t type)
1facf9fc 6062+{
6063+ int npositive, err;
6064+ aufs_bindex_t bindex, btail, bdiropq;
6065+ unsigned char isdir;
6066+ struct qstr whname;
6067+ struct au_do_lookup_args args = {
b4510431 6068+ .flags = 0,
537831f9 6069+ .type = type
1facf9fc 6070+ };
6071+ const struct qstr *name = &dentry->d_name;
6072+ struct dentry *parent;
6073+ struct inode *inode;
6074+
dece6358
AM
6075+ err = au_test_shwh(dentry->d_sb, name);
6076+ if (unlikely(err))
1facf9fc 6077+ goto out;
6078+
6079+ err = au_wh_name_alloc(&whname, name);
6080+ if (unlikely(err))
6081+ goto out;
6082+
6083+ inode = dentry->d_inode;
6084+ isdir = !!(inode && S_ISDIR(inode->i_mode));
6085+ if (!type)
6086+ au_fset_lkup(args.flags, ALLOW_NEG);
6087+
6088+ npositive = 0;
4a4d8108 6089+ parent = dget_parent(dentry);
1facf9fc 6090+ btail = au_dbtaildir(parent);
6091+ for (bindex = bstart; bindex <= btail; bindex++) {
6092+ struct dentry *h_parent, *h_dentry;
6093+ struct inode *h_inode, *h_dir;
6094+
6095+ h_dentry = au_h_dptr(dentry, bindex);
6096+ if (h_dentry) {
6097+ if (h_dentry->d_inode)
6098+ npositive++;
6099+ if (type != S_IFDIR)
6100+ break;
6101+ continue;
6102+ }
6103+ h_parent = au_h_dptr(parent, bindex);
6104+ if (!h_parent)
6105+ continue;
6106+ h_dir = h_parent->d_inode;
6107+ if (!h_dir || !S_ISDIR(h_dir->i_mode))
6108+ continue;
6109+
6110+ mutex_lock_nested(&h_dir->i_mutex, AuLsc_I_PARENT);
6111+ h_dentry = au_do_lookup(h_parent, dentry, bindex, &whname,
6112+ &args);
6113+ mutex_unlock(&h_dir->i_mutex);
6114+ err = PTR_ERR(h_dentry);
6115+ if (IS_ERR(h_dentry))
4a4d8108 6116+ goto out_parent;
1facf9fc 6117+ au_fclr_lkup(args.flags, ALLOW_NEG);
6118+
6119+ if (au_dbwh(dentry) >= 0)
6120+ break;
6121+ if (!h_dentry)
6122+ continue;
6123+ h_inode = h_dentry->d_inode;
6124+ if (!h_inode)
6125+ continue;
6126+ npositive++;
6127+ if (!args.type)
6128+ args.type = h_inode->i_mode & S_IFMT;
6129+ if (args.type != S_IFDIR)
6130+ break;
6131+ else if (isdir) {
6132+ /* the type of lower may be different */
6133+ bdiropq = au_dbdiropq(dentry);
6134+ if (bdiropq >= 0 && bdiropq <= bindex)
6135+ break;
6136+ }
6137+ }
6138+
6139+ if (npositive) {
6140+ AuLabel(positive);
6141+ au_update_dbstart(dentry);
6142+ }
6143+ err = npositive;
6144+ if (unlikely(!au_opt_test(au_mntflags(dentry->d_sb), UDBA_NONE)
027c5e7a 6145+ && au_dbstart(dentry) < 0)) {
1facf9fc 6146+ err = -EIO;
027c5e7a
AM
6147+ AuIOErr("both of real entry and whiteout found, %.*s, err %d\n",
6148+ AuDLNPair(dentry), err);
6149+ }
1facf9fc 6150+
4f0767ce 6151+out_parent:
4a4d8108 6152+ dput(parent);
1facf9fc 6153+ kfree(whname.name);
4f0767ce 6154+out:
1facf9fc 6155+ return err;
6156+}
6157+
6158+struct dentry *au_sio_lkup_one(struct qstr *name, struct dentry *parent,
6159+ struct au_branch *br)
6160+{
6161+ struct dentry *dentry;
6162+ int wkq_err;
6163+
6164+ if (!au_test_h_perm_sio(parent->d_inode, MAY_EXEC))
b4510431 6165+ dentry = vfsub_lkup_one(name, parent);
1facf9fc 6166+ else {
b4510431
AM
6167+ struct vfsub_lkup_one_args args = {
6168+ .errp = &dentry,
6169+ .name = name,
6170+ .parent = parent
1facf9fc 6171+ };
6172+
b4510431 6173+ wkq_err = au_wkq_wait(vfsub_call_lkup_one, &args);
1facf9fc 6174+ if (unlikely(wkq_err))
6175+ dentry = ERR_PTR(wkq_err);
6176+ }
6177+
6178+ return dentry;
6179+}
6180+
6181+/*
6182+ * lookup @dentry on @bindex which should be negative.
6183+ */
6184+int au_lkup_neg(struct dentry *dentry, aufs_bindex_t bindex)
6185+{
6186+ int err;
6187+ struct dentry *parent, *h_parent, *h_dentry;
1facf9fc 6188+
1facf9fc 6189+ parent = dget_parent(dentry);
6190+ h_parent = au_h_dptr(parent, bindex);
4a4d8108 6191+ h_dentry = au_sio_lkup_one(&dentry->d_name, h_parent,
1facf9fc 6192+ au_sbr(dentry->d_sb, bindex));
6193+ err = PTR_ERR(h_dentry);
6194+ if (IS_ERR(h_dentry))
6195+ goto out;
6196+ if (unlikely(h_dentry->d_inode)) {
6197+ err = -EIO;
027c5e7a
AM
6198+ AuIOErr("%.*s should be negative on b%d.\n",
6199+ AuDLNPair(h_dentry), bindex);
1facf9fc 6200+ dput(h_dentry);
6201+ goto out;
6202+ }
6203+
4a4d8108 6204+ err = 0;
1facf9fc 6205+ if (bindex < au_dbstart(dentry))
6206+ au_set_dbstart(dentry, bindex);
6207+ if (au_dbend(dentry) < bindex)
6208+ au_set_dbend(dentry, bindex);
6209+ au_set_h_dptr(dentry, bindex, h_dentry);
1facf9fc 6210+
4f0767ce 6211+out:
1facf9fc 6212+ dput(parent);
6213+ return err;
6214+}
6215+
6216+/* ---------------------------------------------------------------------- */
6217+
6218+/* subset of struct inode */
6219+struct au_iattr {
6220+ unsigned long i_ino;
6221+ /* unsigned int i_nlink; */
0c3ec466
AM
6222+ kuid_t i_uid;
6223+ kgid_t i_gid;
1facf9fc 6224+ u64 i_version;
6225+/*
6226+ loff_t i_size;
6227+ blkcnt_t i_blocks;
6228+*/
6229+ umode_t i_mode;
6230+};
6231+
6232+static void au_iattr_save(struct au_iattr *ia, struct inode *h_inode)
6233+{
6234+ ia->i_ino = h_inode->i_ino;
6235+ /* ia->i_nlink = h_inode->i_nlink; */
6236+ ia->i_uid = h_inode->i_uid;
6237+ ia->i_gid = h_inode->i_gid;
6238+ ia->i_version = h_inode->i_version;
6239+/*
6240+ ia->i_size = h_inode->i_size;
6241+ ia->i_blocks = h_inode->i_blocks;
6242+*/
6243+ ia->i_mode = (h_inode->i_mode & S_IFMT);
6244+}
6245+
6246+static int au_iattr_test(struct au_iattr *ia, struct inode *h_inode)
6247+{
6248+ return ia->i_ino != h_inode->i_ino
6249+ /* || ia->i_nlink != h_inode->i_nlink */
0c3ec466 6250+ || !uid_eq(ia->i_uid, h_inode->i_uid)
2dfbb274 6251+ || !gid_eq(ia->i_gid, h_inode->i_gid)
1facf9fc 6252+ || ia->i_version != h_inode->i_version
6253+/*
6254+ || ia->i_size != h_inode->i_size
6255+ || ia->i_blocks != h_inode->i_blocks
6256+*/
6257+ || ia->i_mode != (h_inode->i_mode & S_IFMT);
6258+}
6259+
6260+static int au_h_verify_dentry(struct dentry *h_dentry, struct dentry *h_parent,
6261+ struct au_branch *br)
6262+{
6263+ int err;
6264+ struct au_iattr ia;
6265+ struct inode *h_inode;
6266+ struct dentry *h_d;
6267+ struct super_block *h_sb;
6268+
6269+ err = 0;
6270+ memset(&ia, -1, sizeof(ia));
6271+ h_sb = h_dentry->d_sb;
6272+ h_inode = h_dentry->d_inode;
6273+ if (h_inode)
6274+ au_iattr_save(&ia, h_inode);
6275+ else if (au_test_nfs(h_sb) || au_test_fuse(h_sb))
6276+ /* nfs d_revalidate may return 0 for negative dentry */
6277+ /* fuse d_revalidate always return 0 for negative dentry */
6278+ goto out;
6279+
6280+ /* main purpose is namei.c:cached_lookup() and d_revalidate */
b4510431 6281+ h_d = vfsub_lkup_one(&h_dentry->d_name, h_parent);
1facf9fc 6282+ err = PTR_ERR(h_d);
6283+ if (IS_ERR(h_d))
6284+ goto out;
6285+
6286+ err = 0;
6287+ if (unlikely(h_d != h_dentry
6288+ || h_d->d_inode != h_inode
6289+ || (h_inode && au_iattr_test(&ia, h_inode))))
6290+ err = au_busy_or_stale();
6291+ dput(h_d);
6292+
4f0767ce 6293+out:
1facf9fc 6294+ AuTraceErr(err);
6295+ return err;
6296+}
6297+
6298+int au_h_verify(struct dentry *h_dentry, unsigned int udba, struct inode *h_dir,
6299+ struct dentry *h_parent, struct au_branch *br)
6300+{
6301+ int err;
6302+
6303+ err = 0;
027c5e7a
AM
6304+ if (udba == AuOpt_UDBA_REVAL
6305+ && !au_test_fs_remote(h_dentry->d_sb)) {
1facf9fc 6306+ IMustLock(h_dir);
6307+ err = (h_dentry->d_parent->d_inode != h_dir);
027c5e7a 6308+ } else if (udba != AuOpt_UDBA_NONE)
1facf9fc 6309+ err = au_h_verify_dentry(h_dentry, h_parent, br);
6310+
6311+ return err;
6312+}
6313+
6314+/* ---------------------------------------------------------------------- */
6315+
027c5e7a 6316+static int au_do_refresh_hdentry(struct dentry *dentry, struct dentry *parent)
1facf9fc 6317+{
027c5e7a 6318+ int err;
1facf9fc 6319+ aufs_bindex_t new_bindex, bindex, bend, bwh, bdiropq;
027c5e7a
AM
6320+ struct au_hdentry tmp, *p, *q;
6321+ struct au_dinfo *dinfo;
6322+ struct super_block *sb;
1facf9fc 6323+
027c5e7a 6324+ DiMustWriteLock(dentry);
1308ab2a 6325+
027c5e7a
AM
6326+ sb = dentry->d_sb;
6327+ dinfo = au_di(dentry);
1facf9fc 6328+ bend = dinfo->di_bend;
6329+ bwh = dinfo->di_bwh;
6330+ bdiropq = dinfo->di_bdiropq;
027c5e7a 6331+ p = dinfo->di_hdentry + dinfo->di_bstart;
1facf9fc 6332+ for (bindex = dinfo->di_bstart; bindex <= bend; bindex++, p++) {
027c5e7a 6333+ if (!p->hd_dentry)
1facf9fc 6334+ continue;
6335+
027c5e7a
AM
6336+ new_bindex = au_br_index(sb, p->hd_id);
6337+ if (new_bindex == bindex)
1facf9fc 6338+ continue;
1facf9fc 6339+
1facf9fc 6340+ if (dinfo->di_bwh == bindex)
6341+ bwh = new_bindex;
6342+ if (dinfo->di_bdiropq == bindex)
6343+ bdiropq = new_bindex;
6344+ if (new_bindex < 0) {
6345+ au_hdput(p);
6346+ p->hd_dentry = NULL;
6347+ continue;
6348+ }
6349+
6350+ /* swap two lower dentries, and loop again */
6351+ q = dinfo->di_hdentry + new_bindex;
6352+ tmp = *q;
6353+ *q = *p;
6354+ *p = tmp;
6355+ if (tmp.hd_dentry) {
6356+ bindex--;
6357+ p--;
6358+ }
6359+ }
6360+
1facf9fc 6361+ dinfo->di_bwh = -1;
6362+ if (bwh >= 0 && bwh <= au_sbend(sb) && au_sbr_whable(sb, bwh))
6363+ dinfo->di_bwh = bwh;
6364+
6365+ dinfo->di_bdiropq = -1;
6366+ if (bdiropq >= 0
6367+ && bdiropq <= au_sbend(sb)
6368+ && au_sbr_whable(sb, bdiropq))
6369+ dinfo->di_bdiropq = bdiropq;
6370+
027c5e7a
AM
6371+ err = -EIO;
6372+ dinfo->di_bstart = -1;
6373+ dinfo->di_bend = -1;
1facf9fc 6374+ bend = au_dbend(parent);
6375+ p = dinfo->di_hdentry;
6376+ for (bindex = 0; bindex <= bend; bindex++, p++)
6377+ if (p->hd_dentry) {
6378+ dinfo->di_bstart = bindex;
6379+ break;
6380+ }
6381+
027c5e7a
AM
6382+ if (dinfo->di_bstart >= 0) {
6383+ p = dinfo->di_hdentry + bend;
6384+ for (bindex = bend; bindex >= 0; bindex--, p--)
6385+ if (p->hd_dentry) {
6386+ dinfo->di_bend = bindex;
6387+ err = 0;
6388+ break;
6389+ }
6390+ }
6391+
6392+ return err;
1facf9fc 6393+}
6394+
027c5e7a 6395+static void au_do_hide(struct dentry *dentry)
1facf9fc 6396+{
027c5e7a 6397+ struct inode *inode;
1facf9fc 6398+
027c5e7a
AM
6399+ inode = dentry->d_inode;
6400+ if (inode) {
6401+ if (!S_ISDIR(inode->i_mode)) {
6402+ if (inode->i_nlink && !d_unhashed(dentry))
6403+ drop_nlink(inode);
6404+ } else {
6405+ clear_nlink(inode);
6406+ /* stop next lookup */
6407+ inode->i_flags |= S_DEAD;
6408+ }
6409+ smp_mb(); /* necessary? */
6410+ }
6411+ d_drop(dentry);
6412+}
1308ab2a 6413+
027c5e7a
AM
6414+static int au_hide_children(struct dentry *parent)
6415+{
6416+ int err, i, j, ndentry;
6417+ struct au_dcsub_pages dpages;
6418+ struct au_dpage *dpage;
6419+ struct dentry *dentry;
1facf9fc 6420+
027c5e7a 6421+ err = au_dpages_init(&dpages, GFP_NOFS);
1facf9fc 6422+ if (unlikely(err))
6423+ goto out;
027c5e7a
AM
6424+ err = au_dcsub_pages(&dpages, parent, NULL, NULL);
6425+ if (unlikely(err))
6426+ goto out_dpages;
1facf9fc 6427+
027c5e7a
AM
6428+ /* in reverse order */
6429+ for (i = dpages.ndpage - 1; i >= 0; i--) {
6430+ dpage = dpages.dpages + i;
6431+ ndentry = dpage->ndentry;
6432+ for (j = ndentry - 1; j >= 0; j--) {
6433+ dentry = dpage->dentries[j];
6434+ if (dentry != parent)
6435+ au_do_hide(dentry);
6436+ }
6437+ }
1facf9fc 6438+
027c5e7a
AM
6439+out_dpages:
6440+ au_dpages_free(&dpages);
4f0767ce 6441+out:
027c5e7a 6442+ return err;
1facf9fc 6443+}
6444+
027c5e7a 6445+static void au_hide(struct dentry *dentry)
1facf9fc 6446+{
027c5e7a
AM
6447+ int err;
6448+ struct inode *inode;
1facf9fc 6449+
027c5e7a
AM
6450+ AuDbgDentry(dentry);
6451+ inode = dentry->d_inode;
6452+ if (inode && S_ISDIR(inode->i_mode)) {
6453+ /* shrink_dcache_parent(dentry); */
6454+ err = au_hide_children(dentry);
6455+ if (unlikely(err))
6456+ AuIOErr("%.*s, failed hiding children, ignored %d\n",
6457+ AuDLNPair(dentry), err);
6458+ }
6459+ au_do_hide(dentry);
6460+}
1facf9fc 6461+
027c5e7a
AM
6462+/*
6463+ * By adding a dirty branch, a cached dentry may be affected in various ways.
6464+ *
6465+ * a dirty branch is added
6466+ * - on the top of layers
6467+ * - in the middle of layers
6468+ * - to the bottom of layers
6469+ *
6470+ * on the added branch there exists
6471+ * - a whiteout
6472+ * - a diropq
6473+ * - a same named entry
6474+ * + exist
6475+ * * negative --> positive
6476+ * * positive --> positive
6477+ * - type is unchanged
6478+ * - type is changed
6479+ * + doesn't exist
6480+ * * negative --> negative
6481+ * * positive --> negative (rejected by au_br_del() for non-dir case)
6482+ * - none
6483+ */
6484+static int au_refresh_by_dinfo(struct dentry *dentry, struct au_dinfo *dinfo,
6485+ struct au_dinfo *tmp)
6486+{
6487+ int err;
6488+ aufs_bindex_t bindex, bend;
6489+ struct {
6490+ struct dentry *dentry;
6491+ struct inode *inode;
6492+ mode_t mode;
6493+ } orig_h, tmp_h;
6494+ struct au_hdentry *hd;
6495+ struct inode *inode, *h_inode;
6496+ struct dentry *h_dentry;
6497+
6498+ err = 0;
6499+ AuDebugOn(dinfo->di_bstart < 0);
6500+ orig_h.dentry = dinfo->di_hdentry[dinfo->di_bstart].hd_dentry;
6501+ orig_h.inode = orig_h.dentry->d_inode;
6502+ orig_h.mode = 0;
6503+ if (orig_h.inode)
6504+ orig_h.mode = orig_h.inode->i_mode & S_IFMT;
6505+ memset(&tmp_h, 0, sizeof(tmp_h));
6506+ if (tmp->di_bstart >= 0) {
6507+ tmp_h.dentry = tmp->di_hdentry[tmp->di_bstart].hd_dentry;
6508+ tmp_h.inode = tmp_h.dentry->d_inode;
6509+ if (tmp_h.inode)
6510+ tmp_h.mode = tmp_h.inode->i_mode & S_IFMT;
6511+ }
6512+
6513+ inode = dentry->d_inode;
6514+ if (!orig_h.inode) {
6515+ AuDbg("nagative originally\n");
6516+ if (inode) {
6517+ au_hide(dentry);
6518+ goto out;
6519+ }
6520+ AuDebugOn(inode);
6521+ AuDebugOn(dinfo->di_bstart != dinfo->di_bend);
6522+ AuDebugOn(dinfo->di_bdiropq != -1);
6523+
6524+ if (!tmp_h.inode) {
6525+ AuDbg("negative --> negative\n");
6526+ /* should have only one negative lower */
6527+ if (tmp->di_bstart >= 0
6528+ && tmp->di_bstart < dinfo->di_bstart) {
6529+ AuDebugOn(tmp->di_bstart != tmp->di_bend);
6530+ AuDebugOn(dinfo->di_bstart != dinfo->di_bend);
6531+ au_set_h_dptr(dentry, dinfo->di_bstart, NULL);
6532+ au_di_cp(dinfo, tmp);
6533+ hd = tmp->di_hdentry + tmp->di_bstart;
6534+ au_set_h_dptr(dentry, tmp->di_bstart,
6535+ dget(hd->hd_dentry));
6536+ }
6537+ au_dbg_verify_dinode(dentry);
6538+ } else {
6539+ AuDbg("negative --> positive\n");
6540+ /*
6541+ * similar to the behaviour of creating with bypassing
6542+ * aufs.
6543+ * unhash it in order to force an error in the
6544+ * succeeding create operation.
6545+ * we should not set S_DEAD here.
6546+ */
6547+ d_drop(dentry);
6548+ /* au_di_swap(tmp, dinfo); */
6549+ au_dbg_verify_dinode(dentry);
6550+ }
6551+ } else {
6552+ AuDbg("positive originally\n");
6553+ /* inode may be NULL */
6554+ AuDebugOn(inode && (inode->i_mode & S_IFMT) != orig_h.mode);
6555+ if (!tmp_h.inode) {
6556+ AuDbg("positive --> negative\n");
6557+ /* or bypassing aufs */
6558+ au_hide(dentry);
6559+ if (tmp->di_bwh >= 0 && tmp->di_bwh <= dinfo->di_bstart)
6560+ dinfo->di_bwh = tmp->di_bwh;
6561+ if (inode)
6562+ err = au_refresh_hinode_self(inode);
6563+ au_dbg_verify_dinode(dentry);
6564+ } else if (orig_h.mode == tmp_h.mode) {
6565+ AuDbg("positive --> positive, same type\n");
6566+ if (!S_ISDIR(orig_h.mode)
6567+ && dinfo->di_bstart > tmp->di_bstart) {
6568+ /*
6569+ * similar to the behaviour of removing and
6570+ * creating.
6571+ */
6572+ au_hide(dentry);
6573+ if (inode)
6574+ err = au_refresh_hinode_self(inode);
6575+ au_dbg_verify_dinode(dentry);
6576+ } else {
6577+ /* fill empty slots */
6578+ if (dinfo->di_bstart > tmp->di_bstart)
6579+ dinfo->di_bstart = tmp->di_bstart;
6580+ if (dinfo->di_bend < tmp->di_bend)
6581+ dinfo->di_bend = tmp->di_bend;
6582+ dinfo->di_bwh = tmp->di_bwh;
6583+ dinfo->di_bdiropq = tmp->di_bdiropq;
6584+ hd = tmp->di_hdentry;
6585+ bend = dinfo->di_bend;
6586+ for (bindex = tmp->di_bstart; bindex <= bend;
6587+ bindex++) {
6588+ if (au_h_dptr(dentry, bindex))
6589+ continue;
6590+ h_dentry = hd[bindex].hd_dentry;
6591+ if (!h_dentry)
6592+ continue;
6593+ h_inode = h_dentry->d_inode;
6594+ AuDebugOn(!h_inode);
6595+ AuDebugOn(orig_h.mode
6596+ != (h_inode->i_mode
6597+ & S_IFMT));
6598+ au_set_h_dptr(dentry, bindex,
6599+ dget(h_dentry));
6600+ }
6601+ err = au_refresh_hinode(inode, dentry);
6602+ au_dbg_verify_dinode(dentry);
6603+ }
6604+ } else {
6605+ AuDbg("positive --> positive, different type\n");
6606+ /* similar to the behaviour of removing and creating */
6607+ au_hide(dentry);
6608+ if (inode)
6609+ err = au_refresh_hinode_self(inode);
6610+ au_dbg_verify_dinode(dentry);
6611+ }
6612+ }
6613+
6614+out:
6615+ return err;
6616+}
6617+
6618+int au_refresh_dentry(struct dentry *dentry, struct dentry *parent)
6619+{
6620+ int err, ebrange;
6621+ unsigned int sigen;
6622+ struct au_dinfo *dinfo, *tmp;
6623+ struct super_block *sb;
6624+ struct inode *inode;
6625+
6626+ DiMustWriteLock(dentry);
6627+ AuDebugOn(IS_ROOT(dentry));
6628+ AuDebugOn(!parent->d_inode);
6629+
6630+ sb = dentry->d_sb;
6631+ inode = dentry->d_inode;
6632+ sigen = au_sigen(sb);
6633+ err = au_digen_test(parent, sigen);
6634+ if (unlikely(err))
6635+ goto out;
6636+
6637+ dinfo = au_di(dentry);
6638+ err = au_di_realloc(dinfo, au_sbend(sb) + 1);
6639+ if (unlikely(err))
6640+ goto out;
6641+ ebrange = au_dbrange_test(dentry);
6642+ if (!ebrange)
6643+ ebrange = au_do_refresh_hdentry(dentry, parent);
6644+
6645+ if (d_unhashed(dentry) || ebrange) {
6646+ AuDebugOn(au_dbstart(dentry) < 0 && au_dbend(dentry) >= 0);
6647+ if (inode)
6648+ err = au_refresh_hinode_self(inode);
6649+ au_dbg_verify_dinode(dentry);
6650+ if (!err)
6651+ goto out_dgen; /* success */
6652+ goto out;
6653+ }
6654+
6655+ /* temporary dinfo */
6656+ AuDbgDentry(dentry);
6657+ err = -ENOMEM;
6658+ tmp = au_di_alloc(sb, AuLsc_DI_TMP);
6659+ if (unlikely(!tmp))
6660+ goto out;
6661+ au_di_swap(tmp, dinfo);
6662+ /* returns the number of positive dentries */
6663+ /*
6664+ * if current working dir is removed, it returns an error.
6665+ * but the dentry is legal.
6666+ */
537831f9 6667+ err = au_lkup_dentry(dentry, /*bstart*/0, /*type*/0);
027c5e7a
AM
6668+ AuDbgDentry(dentry);
6669+ au_di_swap(tmp, dinfo);
6670+ if (err == -ENOENT)
6671+ err = 0;
6672+ if (err >= 0) {
6673+ /* compare/refresh by dinfo */
6674+ AuDbgDentry(dentry);
6675+ err = au_refresh_by_dinfo(dentry, dinfo, tmp);
6676+ au_dbg_verify_dinode(dentry);
6677+ AuTraceErr(err);
6678+ }
6679+ au_rw_write_unlock(&tmp->di_rwsem);
6680+ au_di_free(tmp);
6681+ if (unlikely(err))
6682+ goto out;
6683+
6684+out_dgen:
6685+ au_update_digen(dentry);
6686+out:
6687+ if (unlikely(err && !(dentry->d_flags & DCACHE_NFSFS_RENAMED))) {
6688+ AuIOErr("failed refreshing %.*s, %d\n",
6689+ AuDLNPair(dentry), err);
6690+ AuDbgDentry(dentry);
6691+ }
6692+ AuTraceErr(err);
6693+ return err;
6694+}
6695+
b4510431
AM
6696+static int au_do_h_d_reval(struct dentry *h_dentry, unsigned int flags,
6697+ struct dentry *dentry, aufs_bindex_t bindex)
027c5e7a
AM
6698+{
6699+ int err, valid;
027c5e7a
AM
6700+
6701+ err = 0;
6702+ if (!(h_dentry->d_flags & DCACHE_OP_REVALIDATE))
6703+ goto out;
027c5e7a
AM
6704+
6705+ AuDbg("b%d\n", bindex);
b4510431
AM
6706+ /*
6707+ * gave up supporting LOOKUP_CREATE/OPEN for lower fs,
6708+ * due to whiteout and branch permission.
6709+ */
6710+ flags &= ~(/*LOOKUP_PARENT |*/ LOOKUP_OPEN | LOOKUP_CREATE
6711+ | LOOKUP_FOLLOW | LOOKUP_EXCL);
6712+ /* it may return tri-state */
6713+ valid = h_dentry->d_op->d_revalidate(h_dentry, flags);
1facf9fc 6714+
6715+ if (unlikely(valid < 0))
6716+ err = valid;
6717+ else if (!valid)
6718+ err = -EINVAL;
6719+
4f0767ce 6720+out:
1facf9fc 6721+ AuTraceErr(err);
6722+ return err;
6723+}
6724+
6725+/* todo: remove this */
6726+static int h_d_revalidate(struct dentry *dentry, struct inode *inode,
b4510431 6727+ unsigned int flags, int do_udba)
1facf9fc 6728+{
6729+ int err;
6730+ umode_t mode, h_mode;
6731+ aufs_bindex_t bindex, btail, bstart, ibs, ibe;
6732+ unsigned char plus, unhashed, is_root, h_plus;
4a4d8108 6733+ struct inode *h_inode, *h_cached_inode;
1facf9fc 6734+ struct dentry *h_dentry;
6735+ struct qstr *name, *h_name;
6736+
6737+ err = 0;
6738+ plus = 0;
6739+ mode = 0;
1facf9fc 6740+ ibs = -1;
6741+ ibe = -1;
6742+ unhashed = !!d_unhashed(dentry);
6743+ is_root = !!IS_ROOT(dentry);
6744+ name = &dentry->d_name;
6745+
6746+ /*
7f207e10
AM
6747+ * Theoretically, REVAL test should be unnecessary in case of
6748+ * {FS,I}NOTIFY.
6749+ * But {fs,i}notify doesn't fire some necessary events,
1facf9fc 6750+ * IN_ATTRIB for atime/nlink/pageio
6751+ * IN_DELETE for NFS dentry
6752+ * Let's do REVAL test too.
6753+ */
6754+ if (do_udba && inode) {
6755+ mode = (inode->i_mode & S_IFMT);
6756+ plus = (inode->i_nlink > 0);
1facf9fc 6757+ ibs = au_ibstart(inode);
6758+ ibe = au_ibend(inode);
6759+ }
6760+
6761+ bstart = au_dbstart(dentry);
6762+ btail = bstart;
6763+ if (inode && S_ISDIR(inode->i_mode))
6764+ btail = au_dbtaildir(dentry);
6765+ for (bindex = bstart; bindex <= btail; bindex++) {
6766+ h_dentry = au_h_dptr(dentry, bindex);
6767+ if (!h_dentry)
6768+ continue;
6769+
6770+ AuDbg("b%d, %.*s\n", bindex, AuDLNPair(h_dentry));
027c5e7a 6771+ spin_lock(&h_dentry->d_lock);
1facf9fc 6772+ h_name = &h_dentry->d_name;
6773+ if (unlikely(do_udba
6774+ && !is_root
6775+ && (unhashed != !!d_unhashed(h_dentry)
6776+ || name->len != h_name->len
6777+ || memcmp(name->name, h_name->name, name->len))
6778+ )) {
6779+ AuDbg("unhash 0x%x 0x%x, %.*s %.*s\n",
6780+ unhashed, d_unhashed(h_dentry),
6781+ AuDLNPair(dentry), AuDLNPair(h_dentry));
027c5e7a 6782+ spin_unlock(&h_dentry->d_lock);
1facf9fc 6783+ goto err;
6784+ }
027c5e7a 6785+ spin_unlock(&h_dentry->d_lock);
1facf9fc 6786+
b4510431 6787+ err = au_do_h_d_reval(h_dentry, flags, dentry, bindex);
1facf9fc 6788+ if (unlikely(err))
6789+ /* do not goto err, to keep the errno */
6790+ break;
6791+
6792+ /* todo: plink too? */
6793+ if (!do_udba)
6794+ continue;
6795+
6796+ /* UDBA tests */
6797+ h_inode = h_dentry->d_inode;
6798+ if (unlikely(!!inode != !!h_inode))
6799+ goto err;
6800+
6801+ h_plus = plus;
6802+ h_mode = mode;
6803+ h_cached_inode = h_inode;
6804+ if (h_inode) {
6805+ h_mode = (h_inode->i_mode & S_IFMT);
6806+ h_plus = (h_inode->i_nlink > 0);
6807+ }
6808+ if (inode && ibs <= bindex && bindex <= ibe)
6809+ h_cached_inode = au_h_iptr(inode, bindex);
6810+
6811+ if (unlikely(plus != h_plus
6812+ || mode != h_mode
6813+ || h_cached_inode != h_inode))
6814+ goto err;
6815+ continue;
6816+
6817+ err:
6818+ err = -EINVAL;
6819+ break;
6820+ }
6821+
6822+ return err;
6823+}
6824+
027c5e7a 6825+/* todo: consolidate with do_refresh() and au_reval_for_attr() */
1facf9fc 6826+static int simple_reval_dpath(struct dentry *dentry, unsigned int sigen)
6827+{
6828+ int err;
6829+ struct dentry *parent;
1facf9fc 6830+
027c5e7a 6831+ if (!au_digen_test(dentry, sigen))
1facf9fc 6832+ return 0;
6833+
6834+ parent = dget_parent(dentry);
6835+ di_read_lock_parent(parent, AuLock_IR);
027c5e7a 6836+ AuDebugOn(au_digen_test(parent, sigen));
1facf9fc 6837+ au_dbg_verify_gen(parent, sigen);
027c5e7a 6838+ err = au_refresh_dentry(dentry, parent);
1facf9fc 6839+ di_read_unlock(parent, AuLock_IR);
6840+ dput(parent);
027c5e7a 6841+ AuTraceErr(err);
1facf9fc 6842+ return err;
6843+}
6844+
6845+int au_reval_dpath(struct dentry *dentry, unsigned int sigen)
6846+{
6847+ int err;
6848+ struct dentry *d, *parent;
6849+ struct inode *inode;
6850+
027c5e7a 6851+ if (!au_ftest_si(au_sbi(dentry->d_sb), FAILED_REFRESH_DIR))
1facf9fc 6852+ return simple_reval_dpath(dentry, sigen);
6853+
6854+ /* slow loop, keep it simple and stupid */
6855+ /* cf: au_cpup_dirs() */
6856+ err = 0;
6857+ parent = NULL;
027c5e7a 6858+ while (au_digen_test(dentry, sigen)) {
1facf9fc 6859+ d = dentry;
6860+ while (1) {
6861+ dput(parent);
6862+ parent = dget_parent(d);
027c5e7a 6863+ if (!au_digen_test(parent, sigen))
1facf9fc 6864+ break;
6865+ d = parent;
6866+ }
6867+
6868+ inode = d->d_inode;
6869+ if (d != dentry)
027c5e7a 6870+ di_write_lock_child2(d);
1facf9fc 6871+
6872+ /* someone might update our dentry while we were sleeping */
027c5e7a
AM
6873+ if (au_digen_test(d, sigen)) {
6874+ /*
6875+ * todo: consolidate with simple_reval_dpath(),
6876+ * do_refresh() and au_reval_for_attr().
6877+ */
1facf9fc 6878+ di_read_lock_parent(parent, AuLock_IR);
027c5e7a 6879+ err = au_refresh_dentry(d, parent);
1facf9fc 6880+ di_read_unlock(parent, AuLock_IR);
6881+ }
6882+
6883+ if (d != dentry)
6884+ di_write_unlock(d);
6885+ dput(parent);
6886+ if (unlikely(err))
6887+ break;
6888+ }
6889+
6890+ return err;
6891+}
6892+
6893+/*
6894+ * if valid returns 1, otherwise 0.
6895+ */
b4510431 6896+static int aufs_d_revalidate(struct dentry *dentry, unsigned int flags)
1facf9fc 6897+{
6898+ int valid, err;
6899+ unsigned int sigen;
6900+ unsigned char do_udba;
6901+ struct super_block *sb;
6902+ struct inode *inode;
6903+
027c5e7a 6904+ /* todo: support rcu-walk? */
b4510431 6905+ if (flags & LOOKUP_RCU)
027c5e7a
AM
6906+ return -ECHILD;
6907+
6908+ valid = 0;
6909+ if (unlikely(!au_di(dentry)))
6910+ goto out;
6911+
6912+ inode = dentry->d_inode;
6913+ if (inode && is_bad_inode(inode))
6914+ goto out;
6915+
e49829fe 6916+ valid = 1;
1facf9fc 6917+ sb = dentry->d_sb;
e49829fe
JR
6918+ /*
6919+ * todo: very ugly
6920+ * i_mutex of parent dir may be held,
6921+ * but we should not return 'invalid' due to busy.
6922+ */
6923+ err = aufs_read_lock(dentry, AuLock_FLUSH | AuLock_DW | AuLock_NOPLM);
6924+ if (unlikely(err)) {
6925+ valid = err;
027c5e7a 6926+ AuTraceErr(err);
e49829fe
JR
6927+ goto out;
6928+ }
027c5e7a
AM
6929+ if (unlikely(au_dbrange_test(dentry))) {
6930+ err = -EINVAL;
6931+ AuTraceErr(err);
6932+ goto out_dgrade;
1facf9fc 6933+ }
027c5e7a
AM
6934+
6935+ sigen = au_sigen(sb);
6936+ if (au_digen_test(dentry, sigen)) {
1facf9fc 6937+ AuDebugOn(IS_ROOT(dentry));
027c5e7a
AM
6938+ err = au_reval_dpath(dentry, sigen);
6939+ if (unlikely(err)) {
6940+ AuTraceErr(err);
1facf9fc 6941+ goto out_dgrade;
027c5e7a 6942+ }
1facf9fc 6943+ }
6944+ di_downgrade_lock(dentry, AuLock_IR);
6945+
1facf9fc 6946+ err = -EINVAL;
027c5e7a
AM
6947+ if (inode && (IS_DEADDIR(inode) || !inode->i_nlink))
6948+ goto out_inval;
6949+
1facf9fc 6950+ do_udba = !au_opt_test(au_mntflags(sb), UDBA_NONE);
6951+ if (do_udba && inode) {
6952+ aufs_bindex_t bstart = au_ibstart(inode);
027c5e7a 6953+ struct inode *h_inode;
1facf9fc 6954+
027c5e7a
AM
6955+ if (bstart >= 0) {
6956+ h_inode = au_h_iptr(inode, bstart);
6957+ if (h_inode && au_test_higen(inode, h_inode))
6958+ goto out_inval;
6959+ }
1facf9fc 6960+ }
6961+
b4510431 6962+ err = h_d_revalidate(dentry, inode, flags, do_udba);
027c5e7a 6963+ if (unlikely(!err && do_udba && au_dbstart(dentry) < 0)) {
1facf9fc 6964+ err = -EIO;
027c5e7a
AM
6965+ AuDbg("both of real entry and whiteout found, %.*s, err %d\n",
6966+ AuDLNPair(dentry), err);
6967+ }
e49829fe 6968+ goto out_inval;
1facf9fc 6969+
4f0767ce 6970+out_dgrade:
1facf9fc 6971+ di_downgrade_lock(dentry, AuLock_IR);
e49829fe 6972+out_inval:
1facf9fc 6973+ aufs_read_unlock(dentry, AuLock_IR);
6974+ AuTraceErr(err);
6975+ valid = !err;
e49829fe 6976+out:
027c5e7a 6977+ if (!valid) {
e49829fe 6978+ AuDbg("%.*s invalid, %d\n", AuDLNPair(dentry), valid);
027c5e7a
AM
6979+ d_drop(dentry);
6980+ }
1facf9fc 6981+ return valid;
6982+}
6983+
6984+static void aufs_d_release(struct dentry *dentry)
6985+{
027c5e7a 6986+ if (au_di(dentry)) {
4a4d8108
AM
6987+ au_di_fin(dentry);
6988+ au_hn_di_reinit(dentry);
1facf9fc 6989+ }
1facf9fc 6990+}
6991+
4a4d8108 6992+const struct dentry_operations aufs_dop = {
1facf9fc 6993+ .d_revalidate = aufs_d_revalidate,
6994+ .d_release = aufs_d_release
6995+};
7f207e10
AM
6996diff -urN /usr/share/empty/fs/aufs/dentry.h linux/fs/aufs/dentry.h
6997--- /usr/share/empty/fs/aufs/dentry.h 1970-01-01 01:00:00.000000000 +0100
537831f9
AM
6998+++ linux/fs/aufs/dentry.h 2012-12-13 20:41:10.428126759 +0100
6999@@ -0,0 +1,234 @@
1facf9fc 7000+/*
f6c5ef8b 7001+ * Copyright (C) 2005-2012 Junjiro R. Okajima
1facf9fc 7002+ *
7003+ * This program, aufs is free software; you can redistribute it and/or modify
7004+ * it under the terms of the GNU General Public License as published by
7005+ * the Free Software Foundation; either version 2 of the License, or
7006+ * (at your option) any later version.
dece6358
AM
7007+ *
7008+ * This program is distributed in the hope that it will be useful,
7009+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
7010+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
7011+ * GNU General Public License for more details.
7012+ *
7013+ * You should have received a copy of the GNU General Public License
7014+ * along with this program; if not, write to the Free Software
7015+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 7016+ */
7017+
7018+/*
7019+ * lookup and dentry operations
7020+ */
7021+
7022+#ifndef __AUFS_DENTRY_H__
7023+#define __AUFS_DENTRY_H__
7024+
7025+#ifdef __KERNEL__
7026+
dece6358 7027+#include <linux/dcache.h>
1facf9fc 7028+#include "rwsem.h"
7029+
1facf9fc 7030+struct au_hdentry {
7031+ struct dentry *hd_dentry;
027c5e7a 7032+ aufs_bindex_t hd_id;
1facf9fc 7033+};
7034+
7035+struct au_dinfo {
7036+ atomic_t di_generation;
7037+
dece6358 7038+ struct au_rwsem di_rwsem;
1facf9fc 7039+ aufs_bindex_t di_bstart, di_bend, di_bwh, di_bdiropq;
7040+ struct au_hdentry *di_hdentry;
4a4d8108 7041+} ____cacheline_aligned_in_smp;
1facf9fc 7042+
7043+/* ---------------------------------------------------------------------- */
7044+
7045+/* dentry.c */
4a4d8108 7046+extern const struct dentry_operations aufs_dop;
1facf9fc 7047+struct au_branch;
1facf9fc 7048+struct dentry *au_sio_lkup_one(struct qstr *name, struct dentry *parent,
7049+ struct au_branch *br);
7050+int au_h_verify(struct dentry *h_dentry, unsigned int udba, struct inode *h_dir,
7051+ struct dentry *h_parent, struct au_branch *br);
7052+
537831f9 7053+int au_lkup_dentry(struct dentry *dentry, aufs_bindex_t bstart, mode_t type);
1facf9fc 7054+int au_lkup_neg(struct dentry *dentry, aufs_bindex_t bindex);
027c5e7a 7055+int au_refresh_dentry(struct dentry *dentry, struct dentry *parent);
1facf9fc 7056+int au_reval_dpath(struct dentry *dentry, unsigned int sigen);
7057+
7058+/* dinfo.c */
4a4d8108 7059+void au_di_init_once(void *_di);
027c5e7a
AM
7060+struct au_dinfo *au_di_alloc(struct super_block *sb, unsigned int lsc);
7061+void au_di_free(struct au_dinfo *dinfo);
7062+void au_di_swap(struct au_dinfo *a, struct au_dinfo *b);
7063+void au_di_cp(struct au_dinfo *dst, struct au_dinfo *src);
4a4d8108
AM
7064+int au_di_init(struct dentry *dentry);
7065+void au_di_fin(struct dentry *dentry);
1facf9fc 7066+int au_di_realloc(struct au_dinfo *dinfo, int nbr);
7067+
7068+void di_read_lock(struct dentry *d, int flags, unsigned int lsc);
7069+void di_read_unlock(struct dentry *d, int flags);
7070+void di_downgrade_lock(struct dentry *d, int flags);
7071+void di_write_lock(struct dentry *d, unsigned int lsc);
7072+void di_write_unlock(struct dentry *d);
7073+void di_write_lock2_child(struct dentry *d1, struct dentry *d2, int isdir);
7074+void di_write_lock2_parent(struct dentry *d1, struct dentry *d2, int isdir);
7075+void di_write_unlock2(struct dentry *d1, struct dentry *d2);
7076+
7077+struct dentry *au_h_dptr(struct dentry *dentry, aufs_bindex_t bindex);
2cbb1c4b 7078+struct dentry *au_h_d_alias(struct dentry *dentry, aufs_bindex_t bindex);
1facf9fc 7079+aufs_bindex_t au_dbtail(struct dentry *dentry);
7080+aufs_bindex_t au_dbtaildir(struct dentry *dentry);
7081+
7082+void au_set_h_dptr(struct dentry *dentry, aufs_bindex_t bindex,
7083+ struct dentry *h_dentry);
027c5e7a
AM
7084+int au_digen_test(struct dentry *dentry, unsigned int sigen);
7085+int au_dbrange_test(struct dentry *dentry);
1facf9fc 7086+void au_update_digen(struct dentry *dentry);
7087+void au_update_dbrange(struct dentry *dentry, int do_put_zero);
7088+void au_update_dbstart(struct dentry *dentry);
7089+void au_update_dbend(struct dentry *dentry);
7090+int au_find_dbindex(struct dentry *dentry, struct dentry *h_dentry);
7091+
7092+/* ---------------------------------------------------------------------- */
7093+
7094+static inline struct au_dinfo *au_di(struct dentry *dentry)
7095+{
7096+ return dentry->d_fsdata;
7097+}
7098+
7099+/* ---------------------------------------------------------------------- */
7100+
7101+/* lock subclass for dinfo */
7102+enum {
7103+ AuLsc_DI_CHILD, /* child first */
4a4d8108 7104+ AuLsc_DI_CHILD2, /* rename(2), link(2), and cpup at hnotify */
1facf9fc 7105+ AuLsc_DI_CHILD3, /* copyup dirs */
7106+ AuLsc_DI_PARENT,
7107+ AuLsc_DI_PARENT2,
027c5e7a
AM
7108+ AuLsc_DI_PARENT3,
7109+ AuLsc_DI_TMP /* temp for replacing dinfo */
1facf9fc 7110+};
7111+
7112+/*
7113+ * di_read_lock_child, di_write_lock_child,
7114+ * di_read_lock_child2, di_write_lock_child2,
7115+ * di_read_lock_child3, di_write_lock_child3,
7116+ * di_read_lock_parent, di_write_lock_parent,
7117+ * di_read_lock_parent2, di_write_lock_parent2,
7118+ * di_read_lock_parent3, di_write_lock_parent3,
7119+ */
7120+#define AuReadLockFunc(name, lsc) \
7121+static inline void di_read_lock_##name(struct dentry *d, int flags) \
7122+{ di_read_lock(d, flags, AuLsc_DI_##lsc); }
7123+
7124+#define AuWriteLockFunc(name, lsc) \
7125+static inline void di_write_lock_##name(struct dentry *d) \
7126+{ di_write_lock(d, AuLsc_DI_##lsc); }
7127+
7128+#define AuRWLockFuncs(name, lsc) \
7129+ AuReadLockFunc(name, lsc) \
7130+ AuWriteLockFunc(name, lsc)
7131+
7132+AuRWLockFuncs(child, CHILD);
7133+AuRWLockFuncs(child2, CHILD2);
7134+AuRWLockFuncs(child3, CHILD3);
7135+AuRWLockFuncs(parent, PARENT);
7136+AuRWLockFuncs(parent2, PARENT2);
7137+AuRWLockFuncs(parent3, PARENT3);
7138+
7139+#undef AuReadLockFunc
7140+#undef AuWriteLockFunc
7141+#undef AuRWLockFuncs
7142+
7143+#define DiMustNoWaiters(d) AuRwMustNoWaiters(&au_di(d)->di_rwsem)
dece6358
AM
7144+#define DiMustAnyLock(d) AuRwMustAnyLock(&au_di(d)->di_rwsem)
7145+#define DiMustWriteLock(d) AuRwMustWriteLock(&au_di(d)->di_rwsem)
1facf9fc 7146+
7147+/* ---------------------------------------------------------------------- */
7148+
7149+/* todo: memory barrier? */
7150+static inline unsigned int au_digen(struct dentry *d)
7151+{
7152+ return atomic_read(&au_di(d)->di_generation);
7153+}
7154+
7155+static inline void au_h_dentry_init(struct au_hdentry *hdentry)
7156+{
7157+ hdentry->hd_dentry = NULL;
7158+}
7159+
7160+static inline void au_hdput(struct au_hdentry *hd)
7161+{
4a4d8108
AM
7162+ if (hd)
7163+ dput(hd->hd_dentry);
1facf9fc 7164+}
7165+
7166+static inline aufs_bindex_t au_dbstart(struct dentry *dentry)
7167+{
1308ab2a 7168+ DiMustAnyLock(dentry);
1facf9fc 7169+ return au_di(dentry)->di_bstart;
7170+}
7171+
7172+static inline aufs_bindex_t au_dbend(struct dentry *dentry)
7173+{
1308ab2a 7174+ DiMustAnyLock(dentry);
1facf9fc 7175+ return au_di(dentry)->di_bend;
7176+}
7177+
7178+static inline aufs_bindex_t au_dbwh(struct dentry *dentry)
7179+{
1308ab2a 7180+ DiMustAnyLock(dentry);
1facf9fc 7181+ return au_di(dentry)->di_bwh;
7182+}
7183+
7184+static inline aufs_bindex_t au_dbdiropq(struct dentry *dentry)
7185+{
1308ab2a 7186+ DiMustAnyLock(dentry);
1facf9fc 7187+ return au_di(dentry)->di_bdiropq;
7188+}
7189+
7190+/* todo: hard/soft set? */
7191+static inline void au_set_dbstart(struct dentry *dentry, aufs_bindex_t bindex)
7192+{
1308ab2a 7193+ DiMustWriteLock(dentry);
1facf9fc 7194+ au_di(dentry)->di_bstart = bindex;
7195+}
7196+
7197+static inline void au_set_dbend(struct dentry *dentry, aufs_bindex_t bindex)
7198+{
1308ab2a 7199+ DiMustWriteLock(dentry);
1facf9fc 7200+ au_di(dentry)->di_bend = bindex;
7201+}
7202+
7203+static inline void au_set_dbwh(struct dentry *dentry, aufs_bindex_t bindex)
7204+{
1308ab2a 7205+ DiMustWriteLock(dentry);
1facf9fc 7206+ /* dbwh can be outside of bstart - bend range */
7207+ au_di(dentry)->di_bwh = bindex;
7208+}
7209+
7210+static inline void au_set_dbdiropq(struct dentry *dentry, aufs_bindex_t bindex)
7211+{
1308ab2a 7212+ DiMustWriteLock(dentry);
1facf9fc 7213+ au_di(dentry)->di_bdiropq = bindex;
7214+}
7215+
7216+/* ---------------------------------------------------------------------- */
7217+
4a4d8108 7218+#ifdef CONFIG_AUFS_HNOTIFY
1facf9fc 7219+static inline void au_digen_dec(struct dentry *d)
7220+{
e49829fe 7221+ atomic_dec(&au_di(d)->di_generation);
1facf9fc 7222+}
7223+
4a4d8108 7224+static inline void au_hn_di_reinit(struct dentry *dentry)
1facf9fc 7225+{
7226+ dentry->d_fsdata = NULL;
7227+}
7228+#else
4a4d8108
AM
7229+AuStubVoid(au_hn_di_reinit, struct dentry *dentry __maybe_unused)
7230+#endif /* CONFIG_AUFS_HNOTIFY */
1facf9fc 7231+
7232+#endif /* __KERNEL__ */
7233+#endif /* __AUFS_DENTRY_H__ */
7f207e10
AM
7234diff -urN /usr/share/empty/fs/aufs/dinfo.c linux/fs/aufs/dinfo.c
7235--- /usr/share/empty/fs/aufs/dinfo.c 1970-01-01 01:00:00.000000000 +0100
537831f9 7236+++ linux/fs/aufs/dinfo.c 2012-12-13 20:41:10.428126759 +0100
2cbb1c4b 7237@@ -0,0 +1,543 @@
1facf9fc 7238+/*
f6c5ef8b 7239+ * Copyright (C) 2005-2012 Junjiro R. Okajima
1facf9fc 7240+ *
7241+ * This program, aufs is free software; you can redistribute it and/or modify
7242+ * it under the terms of the GNU General Public License as published by
7243+ * the Free Software Foundation; either version 2 of the License, or
7244+ * (at your option) any later version.
dece6358
AM
7245+ *
7246+ * This program is distributed in the hope that it will be useful,
7247+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
7248+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
7249+ * GNU General Public License for more details.
7250+ *
7251+ * You should have received a copy of the GNU General Public License
7252+ * along with this program; if not, write to the Free Software
7253+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 7254+ */
7255+
7256+/*
7257+ * dentry private data
7258+ */
7259+
7260+#include "aufs.h"
7261+
e49829fe 7262+void au_di_init_once(void *_dinfo)
4a4d8108 7263+{
e49829fe
JR
7264+ struct au_dinfo *dinfo = _dinfo;
7265+ static struct lock_class_key aufs_di;
4a4d8108 7266+
e49829fe
JR
7267+ au_rw_init(&dinfo->di_rwsem);
7268+ au_rw_class(&dinfo->di_rwsem, &aufs_di);
4a4d8108
AM
7269+}
7270+
027c5e7a 7271+struct au_dinfo *au_di_alloc(struct super_block *sb, unsigned int lsc)
1facf9fc 7272+{
7273+ struct au_dinfo *dinfo;
027c5e7a 7274+ int nbr, i;
1facf9fc 7275+
7276+ dinfo = au_cache_alloc_dinfo();
7277+ if (unlikely(!dinfo))
7278+ goto out;
7279+
1facf9fc 7280+ nbr = au_sbend(sb) + 1;
7281+ if (nbr <= 0)
7282+ nbr = 1;
7283+ dinfo->di_hdentry = kcalloc(nbr, sizeof(*dinfo->di_hdentry), GFP_NOFS);
027c5e7a
AM
7284+ if (dinfo->di_hdentry) {
7285+ au_rw_write_lock_nested(&dinfo->di_rwsem, lsc);
7286+ dinfo->di_bstart = -1;
7287+ dinfo->di_bend = -1;
7288+ dinfo->di_bwh = -1;
7289+ dinfo->di_bdiropq = -1;
7290+ for (i = 0; i < nbr; i++)
7291+ dinfo->di_hdentry[i].hd_id = -1;
7292+ goto out;
7293+ }
1facf9fc 7294+
1facf9fc 7295+ au_cache_free_dinfo(dinfo);
027c5e7a
AM
7296+ dinfo = NULL;
7297+
4f0767ce 7298+out:
027c5e7a 7299+ return dinfo;
1facf9fc 7300+}
7301+
027c5e7a 7302+void au_di_free(struct au_dinfo *dinfo)
4a4d8108 7303+{
4a4d8108
AM
7304+ struct au_hdentry *p;
7305+ aufs_bindex_t bend, bindex;
7306+
7307+ /* dentry may not be revalidated */
027c5e7a 7308+ bindex = dinfo->di_bstart;
4a4d8108 7309+ if (bindex >= 0) {
027c5e7a
AM
7310+ bend = dinfo->di_bend;
7311+ p = dinfo->di_hdentry + bindex;
4a4d8108
AM
7312+ while (bindex++ <= bend)
7313+ au_hdput(p++);
7314+ }
027c5e7a
AM
7315+ kfree(dinfo->di_hdentry);
7316+ au_cache_free_dinfo(dinfo);
7317+}
7318+
7319+void au_di_swap(struct au_dinfo *a, struct au_dinfo *b)
7320+{
7321+ struct au_hdentry *p;
7322+ aufs_bindex_t bi;
7323+
7324+ AuRwMustWriteLock(&a->di_rwsem);
7325+ AuRwMustWriteLock(&b->di_rwsem);
7326+
7327+#define DiSwap(v, name) \
7328+ do { \
7329+ v = a->di_##name; \
7330+ a->di_##name = b->di_##name; \
7331+ b->di_##name = v; \
7332+ } while (0)
7333+
7334+ DiSwap(p, hdentry);
7335+ DiSwap(bi, bstart);
7336+ DiSwap(bi, bend);
7337+ DiSwap(bi, bwh);
7338+ DiSwap(bi, bdiropq);
7339+ /* smp_mb(); */
7340+
7341+#undef DiSwap
7342+}
7343+
7344+void au_di_cp(struct au_dinfo *dst, struct au_dinfo *src)
7345+{
7346+ AuRwMustWriteLock(&dst->di_rwsem);
7347+ AuRwMustWriteLock(&src->di_rwsem);
7348+
7349+ dst->di_bstart = src->di_bstart;
7350+ dst->di_bend = src->di_bend;
7351+ dst->di_bwh = src->di_bwh;
7352+ dst->di_bdiropq = src->di_bdiropq;
7353+ /* smp_mb(); */
7354+}
7355+
7356+int au_di_init(struct dentry *dentry)
7357+{
7358+ int err;
7359+ struct super_block *sb;
7360+ struct au_dinfo *dinfo;
7361+
7362+ err = 0;
7363+ sb = dentry->d_sb;
7364+ dinfo = au_di_alloc(sb, AuLsc_DI_CHILD);
7365+ if (dinfo) {
7366+ atomic_set(&dinfo->di_generation, au_sigen(sb));
7367+ /* smp_mb(); */ /* atomic_set */
7368+ dentry->d_fsdata = dinfo;
7369+ } else
7370+ err = -ENOMEM;
7371+
7372+ return err;
7373+}
7374+
7375+void au_di_fin(struct dentry *dentry)
7376+{
7377+ struct au_dinfo *dinfo;
7378+
7379+ dinfo = au_di(dentry);
7380+ AuRwDestroy(&dinfo->di_rwsem);
7381+ au_di_free(dinfo);
4a4d8108
AM
7382+}
7383+
1facf9fc 7384+int au_di_realloc(struct au_dinfo *dinfo, int nbr)
7385+{
7386+ int err, sz;
7387+ struct au_hdentry *hdp;
7388+
1308ab2a 7389+ AuRwMustWriteLock(&dinfo->di_rwsem);
7390+
1facf9fc 7391+ err = -ENOMEM;
7392+ sz = sizeof(*hdp) * (dinfo->di_bend + 1);
7393+ if (!sz)
7394+ sz = sizeof(*hdp);
7395+ hdp = au_kzrealloc(dinfo->di_hdentry, sz, sizeof(*hdp) * nbr, GFP_NOFS);
7396+ if (hdp) {
7397+ dinfo->di_hdentry = hdp;
7398+ err = 0;
7399+ }
7400+
7401+ return err;
7402+}
7403+
7404+/* ---------------------------------------------------------------------- */
7405+
7406+static void do_ii_write_lock(struct inode *inode, unsigned int lsc)
7407+{
7408+ switch (lsc) {
7409+ case AuLsc_DI_CHILD:
7410+ ii_write_lock_child(inode);
7411+ break;
7412+ case AuLsc_DI_CHILD2:
7413+ ii_write_lock_child2(inode);
7414+ break;
7415+ case AuLsc_DI_CHILD3:
7416+ ii_write_lock_child3(inode);
7417+ break;
7418+ case AuLsc_DI_PARENT:
7419+ ii_write_lock_parent(inode);
7420+ break;
7421+ case AuLsc_DI_PARENT2:
7422+ ii_write_lock_parent2(inode);
7423+ break;
7424+ case AuLsc_DI_PARENT3:
7425+ ii_write_lock_parent3(inode);
7426+ break;
7427+ default:
7428+ BUG();
7429+ }
7430+}
7431+
7432+static void do_ii_read_lock(struct inode *inode, unsigned int lsc)
7433+{
7434+ switch (lsc) {
7435+ case AuLsc_DI_CHILD:
7436+ ii_read_lock_child(inode);
7437+ break;
7438+ case AuLsc_DI_CHILD2:
7439+ ii_read_lock_child2(inode);
7440+ break;
7441+ case AuLsc_DI_CHILD3:
7442+ ii_read_lock_child3(inode);
7443+ break;
7444+ case AuLsc_DI_PARENT:
7445+ ii_read_lock_parent(inode);
7446+ break;
7447+ case AuLsc_DI_PARENT2:
7448+ ii_read_lock_parent2(inode);
7449+ break;
7450+ case AuLsc_DI_PARENT3:
7451+ ii_read_lock_parent3(inode);
7452+ break;
7453+ default:
7454+ BUG();
7455+ }
7456+}
7457+
7458+void di_read_lock(struct dentry *d, int flags, unsigned int lsc)
7459+{
dece6358 7460+ au_rw_read_lock_nested(&au_di(d)->di_rwsem, lsc);
1facf9fc 7461+ if (d->d_inode) {
7462+ if (au_ftest_lock(flags, IW))
7463+ do_ii_write_lock(d->d_inode, lsc);
7464+ else if (au_ftest_lock(flags, IR))
7465+ do_ii_read_lock(d->d_inode, lsc);
7466+ }
7467+}
7468+
7469+void di_read_unlock(struct dentry *d, int flags)
7470+{
7471+ if (d->d_inode) {
027c5e7a
AM
7472+ if (au_ftest_lock(flags, IW)) {
7473+ au_dbg_verify_dinode(d);
1facf9fc 7474+ ii_write_unlock(d->d_inode);
027c5e7a
AM
7475+ } else if (au_ftest_lock(flags, IR)) {
7476+ au_dbg_verify_dinode(d);
1facf9fc 7477+ ii_read_unlock(d->d_inode);
027c5e7a 7478+ }
1facf9fc 7479+ }
dece6358 7480+ au_rw_read_unlock(&au_di(d)->di_rwsem);
1facf9fc 7481+}
7482+
7483+void di_downgrade_lock(struct dentry *d, int flags)
7484+{
1facf9fc 7485+ if (d->d_inode && au_ftest_lock(flags, IR))
7486+ ii_downgrade_lock(d->d_inode);
dece6358 7487+ au_rw_dgrade_lock(&au_di(d)->di_rwsem);
1facf9fc 7488+}
7489+
7490+void di_write_lock(struct dentry *d, unsigned int lsc)
7491+{
dece6358 7492+ au_rw_write_lock_nested(&au_di(d)->di_rwsem, lsc);
1facf9fc 7493+ if (d->d_inode)
7494+ do_ii_write_lock(d->d_inode, lsc);
7495+}
7496+
7497+void di_write_unlock(struct dentry *d)
7498+{
027c5e7a 7499+ au_dbg_verify_dinode(d);
1facf9fc 7500+ if (d->d_inode)
7501+ ii_write_unlock(d->d_inode);
dece6358 7502+ au_rw_write_unlock(&au_di(d)->di_rwsem);
1facf9fc 7503+}
7504+
7505+void di_write_lock2_child(struct dentry *d1, struct dentry *d2, int isdir)
7506+{
7507+ AuDebugOn(d1 == d2
7508+ || d1->d_inode == d2->d_inode
7509+ || d1->d_sb != d2->d_sb);
7510+
7511+ if (isdir && au_test_subdir(d1, d2)) {
7512+ di_write_lock_child(d1);
7513+ di_write_lock_child2(d2);
7514+ } else {
7515+ /* there should be no races */
7516+ di_write_lock_child(d2);
7517+ di_write_lock_child2(d1);
7518+ }
7519+}
7520+
7521+void di_write_lock2_parent(struct dentry *d1, struct dentry *d2, int isdir)
7522+{
7523+ AuDebugOn(d1 == d2
7524+ || d1->d_inode == d2->d_inode
7525+ || d1->d_sb != d2->d_sb);
7526+
7527+ if (isdir && au_test_subdir(d1, d2)) {
7528+ di_write_lock_parent(d1);
7529+ di_write_lock_parent2(d2);
7530+ } else {
7531+ /* there should be no races */
7532+ di_write_lock_parent(d2);
7533+ di_write_lock_parent2(d1);
7534+ }
7535+}
7536+
7537+void di_write_unlock2(struct dentry *d1, struct dentry *d2)
7538+{
7539+ di_write_unlock(d1);
7540+ if (d1->d_inode == d2->d_inode)
dece6358 7541+ au_rw_write_unlock(&au_di(d2)->di_rwsem);
1facf9fc 7542+ else
7543+ di_write_unlock(d2);
7544+}
7545+
7546+/* ---------------------------------------------------------------------- */
7547+
7548+struct dentry *au_h_dptr(struct dentry *dentry, aufs_bindex_t bindex)
7549+{
7550+ struct dentry *d;
7551+
1308ab2a 7552+ DiMustAnyLock(dentry);
7553+
1facf9fc 7554+ if (au_dbstart(dentry) < 0 || bindex < au_dbstart(dentry))
7555+ return NULL;
7556+ AuDebugOn(bindex < 0);
7557+ d = au_di(dentry)->di_hdentry[0 + bindex].hd_dentry;
027c5e7a 7558+ AuDebugOn(d && d->d_count <= 0);
1facf9fc 7559+ return d;
7560+}
7561+
2cbb1c4b
JR
7562+/*
7563+ * extended version of au_h_dptr().
7564+ * returns a hashed and positive h_dentry in bindex, NULL, or error.
7565+ */
7566+struct dentry *au_h_d_alias(struct dentry *dentry, aufs_bindex_t bindex)
7567+{
7568+ struct dentry *h_dentry;
7569+ struct inode *inode, *h_inode;
7570+
7571+ inode = dentry->d_inode;
7572+ AuDebugOn(!inode);
7573+
7574+ h_dentry = NULL;
7575+ if (au_dbstart(dentry) <= bindex
7576+ && bindex <= au_dbend(dentry))
7577+ h_dentry = au_h_dptr(dentry, bindex);
7578+ if (h_dentry && !au_d_hashed_positive(h_dentry)) {
7579+ dget(h_dentry);
7580+ goto out; /* success */
7581+ }
7582+
7583+ AuDebugOn(bindex < au_ibstart(inode));
7584+ AuDebugOn(au_ibend(inode) < bindex);
7585+ h_inode = au_h_iptr(inode, bindex);
7586+ h_dentry = d_find_alias(h_inode);
7587+ if (h_dentry) {
7588+ if (!IS_ERR(h_dentry)) {
7589+ if (!au_d_hashed_positive(h_dentry))
7590+ goto out; /* success */
7591+ dput(h_dentry);
7592+ } else
7593+ goto out;
7594+ }
7595+
7596+ if (au_opt_test(au_mntflags(dentry->d_sb), PLINK)) {
7597+ h_dentry = au_plink_lkup(inode, bindex);
7598+ AuDebugOn(!h_dentry);
7599+ if (!IS_ERR(h_dentry)) {
7600+ if (!au_d_hashed_positive(h_dentry))
7601+ goto out; /* success */
7602+ dput(h_dentry);
7603+ h_dentry = NULL;
7604+ }
7605+ }
7606+
7607+out:
7608+ AuDbgDentry(h_dentry);
7609+ return h_dentry;
7610+}
7611+
1facf9fc 7612+aufs_bindex_t au_dbtail(struct dentry *dentry)
7613+{
7614+ aufs_bindex_t bend, bwh;
7615+
7616+ bend = au_dbend(dentry);
7617+ if (0 <= bend) {
7618+ bwh = au_dbwh(dentry);
7619+ if (!bwh)
7620+ return bwh;
7621+ if (0 < bwh && bwh < bend)
7622+ return bwh - 1;
7623+ }
7624+ return bend;
7625+}
7626+
7627+aufs_bindex_t au_dbtaildir(struct dentry *dentry)
7628+{
7629+ aufs_bindex_t bend, bopq;
7630+
7631+ bend = au_dbtail(dentry);
7632+ if (0 <= bend) {
7633+ bopq = au_dbdiropq(dentry);
7634+ if (0 <= bopq && bopq < bend)
7635+ bend = bopq;
7636+ }
7637+ return bend;
7638+}
7639+
7640+/* ---------------------------------------------------------------------- */
7641+
7642+void au_set_h_dptr(struct dentry *dentry, aufs_bindex_t bindex,
7643+ struct dentry *h_dentry)
7644+{
7645+ struct au_hdentry *hd = au_di(dentry)->di_hdentry + bindex;
027c5e7a 7646+ struct au_branch *br;
1facf9fc 7647+
1308ab2a 7648+ DiMustWriteLock(dentry);
7649+
4a4d8108 7650+ au_hdput(hd);
1facf9fc 7651+ hd->hd_dentry = h_dentry;
027c5e7a
AM
7652+ if (h_dentry) {
7653+ br = au_sbr(dentry->d_sb, bindex);
7654+ hd->hd_id = br->br_id;
7655+ }
7656+}
7657+
7658+int au_dbrange_test(struct dentry *dentry)
7659+{
7660+ int err;
7661+ aufs_bindex_t bstart, bend;
7662+
7663+ err = 0;
7664+ bstart = au_dbstart(dentry);
7665+ bend = au_dbend(dentry);
7666+ if (bstart >= 0)
7667+ AuDebugOn(bend < 0 && bstart > bend);
7668+ else {
7669+ err = -EIO;
7670+ AuDebugOn(bend >= 0);
7671+ }
7672+
7673+ return err;
7674+}
7675+
7676+int au_digen_test(struct dentry *dentry, unsigned int sigen)
7677+{
7678+ int err;
7679+
7680+ err = 0;
7681+ if (unlikely(au_digen(dentry) != sigen
7682+ || au_iigen_test(dentry->d_inode, sigen)))
7683+ err = -EIO;
7684+
7685+ return err;
1facf9fc 7686+}
7687+
7688+void au_update_digen(struct dentry *dentry)
7689+{
7690+ atomic_set(&au_di(dentry)->di_generation, au_sigen(dentry->d_sb));
7691+ /* smp_mb(); */ /* atomic_set */
7692+}
7693+
7694+void au_update_dbrange(struct dentry *dentry, int do_put_zero)
7695+{
7696+ struct au_dinfo *dinfo;
7697+ struct dentry *h_d;
4a4d8108 7698+ struct au_hdentry *hdp;
1facf9fc 7699+
1308ab2a 7700+ DiMustWriteLock(dentry);
7701+
1facf9fc 7702+ dinfo = au_di(dentry);
7703+ if (!dinfo || dinfo->di_bstart < 0)
7704+ return;
7705+
4a4d8108 7706+ hdp = dinfo->di_hdentry;
1facf9fc 7707+ if (do_put_zero) {
7708+ aufs_bindex_t bindex, bend;
7709+
7710+ bend = dinfo->di_bend;
7711+ for (bindex = dinfo->di_bstart; bindex <= bend; bindex++) {
4a4d8108 7712+ h_d = hdp[0 + bindex].hd_dentry;
1facf9fc 7713+ if (h_d && !h_d->d_inode)
7714+ au_set_h_dptr(dentry, bindex, NULL);
7715+ }
7716+ }
7717+
7718+ dinfo->di_bstart = -1;
7719+ while (++dinfo->di_bstart <= dinfo->di_bend)
4a4d8108 7720+ if (hdp[0 + dinfo->di_bstart].hd_dentry)
1facf9fc 7721+ break;
7722+ if (dinfo->di_bstart > dinfo->di_bend) {
7723+ dinfo->di_bstart = -1;
7724+ dinfo->di_bend = -1;
7725+ return;
7726+ }
7727+
7728+ dinfo->di_bend++;
7729+ while (0 <= --dinfo->di_bend)
4a4d8108 7730+ if (hdp[0 + dinfo->di_bend].hd_dentry)
1facf9fc 7731+ break;
7732+ AuDebugOn(dinfo->di_bstart > dinfo->di_bend || dinfo->di_bend < 0);
7733+}
7734+
7735+void au_update_dbstart(struct dentry *dentry)
7736+{
7737+ aufs_bindex_t bindex, bend;
7738+ struct dentry *h_dentry;
7739+
7740+ bend = au_dbend(dentry);
7741+ for (bindex = au_dbstart(dentry); bindex <= bend; bindex++) {
7742+ h_dentry = au_h_dptr(dentry, bindex);
7743+ if (!h_dentry)
7744+ continue;
7745+ if (h_dentry->d_inode) {
7746+ au_set_dbstart(dentry, bindex);
7747+ return;
7748+ }
7749+ au_set_h_dptr(dentry, bindex, NULL);
7750+ }
7751+}
7752+
7753+void au_update_dbend(struct dentry *dentry)
7754+{
7755+ aufs_bindex_t bindex, bstart;
7756+ struct dentry *h_dentry;
7757+
7758+ bstart = au_dbstart(dentry);
7f207e10 7759+ for (bindex = au_dbend(dentry); bindex >= bstart; bindex--) {
1facf9fc 7760+ h_dentry = au_h_dptr(dentry, bindex);
7761+ if (!h_dentry)
7762+ continue;
7763+ if (h_dentry->d_inode) {
7764+ au_set_dbend(dentry, bindex);
7765+ return;
7766+ }
7767+ au_set_h_dptr(dentry, bindex, NULL);
7768+ }
7769+}
7770+
7771+int au_find_dbindex(struct dentry *dentry, struct dentry *h_dentry)
7772+{
7773+ aufs_bindex_t bindex, bend;
7774+
7775+ bend = au_dbend(dentry);
7776+ for (bindex = au_dbstart(dentry); bindex <= bend; bindex++)
7777+ if (au_h_dptr(dentry, bindex) == h_dentry)
7778+ return bindex;
7779+ return -1;
7780+}
7f207e10
AM
7781diff -urN /usr/share/empty/fs/aufs/dir.c linux/fs/aufs/dir.c
7782--- /usr/share/empty/fs/aufs/dir.c 1970-01-01 01:00:00.000000000 +0100
537831f9 7783+++ linux/fs/aufs/dir.c 2012-12-13 20:41:10.428126759 +0100
b4510431 7784@@ -0,0 +1,633 @@
1facf9fc 7785+/*
f6c5ef8b 7786+ * Copyright (C) 2005-2012 Junjiro R. Okajima
1facf9fc 7787+ *
7788+ * This program, aufs is free software; you can redistribute it and/or modify
7789+ * it under the terms of the GNU General Public License as published by
7790+ * the Free Software Foundation; either version 2 of the License, or
7791+ * (at your option) any later version.
dece6358
AM
7792+ *
7793+ * This program is distributed in the hope that it will be useful,
7794+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
7795+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
7796+ * GNU General Public License for more details.
7797+ *
7798+ * You should have received a copy of the GNU General Public License
7799+ * along with this program; if not, write to the Free Software
7800+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 7801+ */
7802+
7803+/*
7804+ * directory operations
7805+ */
7806+
7807+#include <linux/fs_stack.h>
7808+#include "aufs.h"
7809+
7810+void au_add_nlink(struct inode *dir, struct inode *h_dir)
7811+{
9dbd164d
AM
7812+ unsigned int nlink;
7813+
1facf9fc 7814+ AuDebugOn(!S_ISDIR(dir->i_mode) || !S_ISDIR(h_dir->i_mode));
7815+
9dbd164d
AM
7816+ nlink = dir->i_nlink;
7817+ nlink += h_dir->i_nlink - 2;
1facf9fc 7818+ if (h_dir->i_nlink < 2)
9dbd164d 7819+ nlink += 2;
7eafdf33 7820+ /* 0 can happen in revaliding */
92d182d2 7821+ set_nlink(dir, nlink);
1facf9fc 7822+}
7823+
7824+void au_sub_nlink(struct inode *dir, struct inode *h_dir)
7825+{
9dbd164d
AM
7826+ unsigned int nlink;
7827+
1facf9fc 7828+ AuDebugOn(!S_ISDIR(dir->i_mode) || !S_ISDIR(h_dir->i_mode));
7829+
9dbd164d
AM
7830+ nlink = dir->i_nlink;
7831+ nlink -= h_dir->i_nlink - 2;
1facf9fc 7832+ if (h_dir->i_nlink < 2)
9dbd164d 7833+ nlink -= 2;
92d182d2 7834+ /* nlink == 0 means the branch-fs is broken */
9dbd164d 7835+ set_nlink(dir, nlink);
1facf9fc 7836+}
7837+
1308ab2a 7838+loff_t au_dir_size(struct file *file, struct dentry *dentry)
7839+{
7840+ loff_t sz;
7841+ aufs_bindex_t bindex, bend;
7842+ struct file *h_file;
7843+ struct dentry *h_dentry;
7844+
7845+ sz = 0;
7846+ if (file) {
7847+ AuDebugOn(!file->f_dentry);
7848+ AuDebugOn(!file->f_dentry->d_inode);
7849+ AuDebugOn(!S_ISDIR(file->f_dentry->d_inode->i_mode));
7850+
4a4d8108 7851+ bend = au_fbend_dir(file);
1308ab2a 7852+ for (bindex = au_fbstart(file);
7853+ bindex <= bend && sz < KMALLOC_MAX_SIZE;
7854+ bindex++) {
4a4d8108 7855+ h_file = au_hf_dir(file, bindex);
1308ab2a 7856+ if (h_file
7857+ && h_file->f_dentry
7858+ && h_file->f_dentry->d_inode)
7859+ sz += i_size_read(h_file->f_dentry->d_inode);
7860+ }
7861+ } else {
7862+ AuDebugOn(!dentry);
7863+ AuDebugOn(!dentry->d_inode);
7864+ AuDebugOn(!S_ISDIR(dentry->d_inode->i_mode));
7865+
7866+ bend = au_dbtaildir(dentry);
7867+ for (bindex = au_dbstart(dentry);
7868+ bindex <= bend && sz < KMALLOC_MAX_SIZE;
7869+ bindex++) {
7870+ h_dentry = au_h_dptr(dentry, bindex);
7871+ if (h_dentry && h_dentry->d_inode)
7872+ sz += i_size_read(h_dentry->d_inode);
7873+ }
7874+ }
7875+ if (sz < KMALLOC_MAX_SIZE)
7876+ sz = roundup_pow_of_two(sz);
7877+ if (sz > KMALLOC_MAX_SIZE)
7878+ sz = KMALLOC_MAX_SIZE;
7879+ else if (sz < NAME_MAX) {
7880+ BUILD_BUG_ON(AUFS_RDBLK_DEF < NAME_MAX);
7881+ sz = AUFS_RDBLK_DEF;
7882+ }
7883+ return sz;
7884+}
7885+
1facf9fc 7886+/* ---------------------------------------------------------------------- */
7887+
7888+static int reopen_dir(struct file *file)
7889+{
7890+ int err;
7891+ unsigned int flags;
7892+ aufs_bindex_t bindex, btail, bstart;
7893+ struct dentry *dentry, *h_dentry;
7894+ struct file *h_file;
7895+
7896+ /* open all lower dirs */
7897+ dentry = file->f_dentry;
7898+ bstart = au_dbstart(dentry);
7899+ for (bindex = au_fbstart(file); bindex < bstart; bindex++)
7900+ au_set_h_fptr(file, bindex, NULL);
7901+ au_set_fbstart(file, bstart);
7902+
7903+ btail = au_dbtaildir(dentry);
4a4d8108 7904+ for (bindex = au_fbend_dir(file); btail < bindex; bindex--)
1facf9fc 7905+ au_set_h_fptr(file, bindex, NULL);
4a4d8108 7906+ au_set_fbend_dir(file, btail);
1facf9fc 7907+
4a4d8108 7908+ flags = vfsub_file_flags(file);
1facf9fc 7909+ for (bindex = bstart; bindex <= btail; bindex++) {
7910+ h_dentry = au_h_dptr(dentry, bindex);
7911+ if (!h_dentry)
7912+ continue;
4a4d8108 7913+ h_file = au_hf_dir(file, bindex);
1facf9fc 7914+ if (h_file)
7915+ continue;
7916+
7917+ h_file = au_h_open(dentry, bindex, flags, file);
7918+ err = PTR_ERR(h_file);
7919+ if (IS_ERR(h_file))
7920+ goto out; /* close all? */
7921+ au_set_h_fptr(file, bindex, h_file);
7922+ }
7923+ au_update_figen(file);
7924+ /* todo: necessary? */
7925+ /* file->f_ra = h_file->f_ra; */
7926+ err = 0;
7927+
4f0767ce 7928+out:
1facf9fc 7929+ return err;
7930+}
7931+
7932+static int do_open_dir(struct file *file, int flags)
7933+{
7934+ int err;
7935+ aufs_bindex_t bindex, btail;
7936+ struct dentry *dentry, *h_dentry;
7937+ struct file *h_file;
7938+
1308ab2a 7939+ FiMustWriteLock(file);
7940+
1facf9fc 7941+ dentry = file->f_dentry;
027c5e7a
AM
7942+ err = au_alive_dir(dentry);
7943+ if (unlikely(err))
7944+ goto out;
7945+
1facf9fc 7946+ file->f_version = dentry->d_inode->i_version;
7947+ bindex = au_dbstart(dentry);
7948+ au_set_fbstart(file, bindex);
7949+ btail = au_dbtaildir(dentry);
4a4d8108 7950+ au_set_fbend_dir(file, btail);
1facf9fc 7951+ for (; !err && bindex <= btail; bindex++) {
7952+ h_dentry = au_h_dptr(dentry, bindex);
7953+ if (!h_dentry)
7954+ continue;
7955+
7956+ h_file = au_h_open(dentry, bindex, flags, file);
7957+ if (IS_ERR(h_file)) {
7958+ err = PTR_ERR(h_file);
7959+ break;
7960+ }
7961+ au_set_h_fptr(file, bindex, h_file);
7962+ }
7963+ au_update_figen(file);
7964+ /* todo: necessary? */
7965+ /* file->f_ra = h_file->f_ra; */
7966+ if (!err)
7967+ return 0; /* success */
7968+
7969+ /* close all */
7970+ for (bindex = au_fbstart(file); bindex <= btail; bindex++)
7971+ au_set_h_fptr(file, bindex, NULL);
7972+ au_set_fbstart(file, -1);
4a4d8108
AM
7973+ au_set_fbend_dir(file, -1);
7974+
027c5e7a 7975+out:
1facf9fc 7976+ return err;
7977+}
7978+
7979+static int aufs_open_dir(struct inode *inode __maybe_unused,
7980+ struct file *file)
7981+{
4a4d8108
AM
7982+ int err;
7983+ struct super_block *sb;
7984+ struct au_fidir *fidir;
7985+
7986+ err = -ENOMEM;
7987+ sb = file->f_dentry->d_sb;
7988+ si_read_lock(sb, AuLock_FLUSH);
e49829fe 7989+ fidir = au_fidir_alloc(sb);
4a4d8108
AM
7990+ if (fidir) {
7991+ err = au_do_open(file, do_open_dir, fidir);
7992+ if (unlikely(err))
7993+ kfree(fidir);
7994+ }
7995+ si_read_unlock(sb);
7996+ return err;
1facf9fc 7997+}
7998+
7999+static int aufs_release_dir(struct inode *inode __maybe_unused,
8000+ struct file *file)
8001+{
8002+ struct au_vdir *vdir_cache;
4a4d8108
AM
8003+ struct au_finfo *finfo;
8004+ struct au_fidir *fidir;
8005+ aufs_bindex_t bindex, bend;
1facf9fc 8006+
4a4d8108
AM
8007+ finfo = au_fi(file);
8008+ fidir = finfo->fi_hdir;
8009+ if (fidir) {
8010+ vdir_cache = fidir->fd_vdir_cache; /* lock-free */
8011+ if (vdir_cache)
8012+ au_vdir_free(vdir_cache);
8013+
8014+ bindex = finfo->fi_btop;
8015+ if (bindex >= 0) {
8016+ /*
8017+ * calls fput() instead of filp_close(),
8018+ * since no dnotify or lock for the lower file.
8019+ */
8020+ bend = fidir->fd_bbot;
8021+ for (; bindex <= bend; bindex++)
8022+ au_set_h_fptr(file, bindex, NULL);
8023+ }
8024+ kfree(fidir);
8025+ finfo->fi_hdir = NULL;
1facf9fc 8026+ }
1facf9fc 8027+ au_finfo_fin(file);
1facf9fc 8028+ return 0;
8029+}
8030+
8031+/* ---------------------------------------------------------------------- */
8032+
4a4d8108
AM
8033+static int au_do_flush_dir(struct file *file, fl_owner_t id)
8034+{
8035+ int err;
8036+ aufs_bindex_t bindex, bend;
8037+ struct file *h_file;
8038+
8039+ err = 0;
8040+ bend = au_fbend_dir(file);
8041+ for (bindex = au_fbstart(file); !err && bindex <= bend; bindex++) {
8042+ h_file = au_hf_dir(file, bindex);
8043+ if (h_file)
8044+ err = vfsub_flush(h_file, id);
8045+ }
8046+ return err;
8047+}
8048+
8049+static int aufs_flush_dir(struct file *file, fl_owner_t id)
8050+{
8051+ return au_do_flush(file, id, au_do_flush_dir);
8052+}
8053+
8054+/* ---------------------------------------------------------------------- */
8055+
1facf9fc 8056+static int au_do_fsync_dir_no_file(struct dentry *dentry, int datasync)
8057+{
8058+ int err;
8059+ aufs_bindex_t bend, bindex;
8060+ struct inode *inode;
8061+ struct super_block *sb;
8062+
8063+ err = 0;
8064+ sb = dentry->d_sb;
8065+ inode = dentry->d_inode;
8066+ IMustLock(inode);
8067+ bend = au_dbend(dentry);
8068+ for (bindex = au_dbstart(dentry); !err && bindex <= bend; bindex++) {
8069+ struct path h_path;
1facf9fc 8070+
8071+ if (au_test_ro(sb, bindex, inode))
8072+ continue;
8073+ h_path.dentry = au_h_dptr(dentry, bindex);
8074+ if (!h_path.dentry)
8075+ continue;
1facf9fc 8076+
1facf9fc 8077+ h_path.mnt = au_sbr_mnt(sb, bindex);
53392da6 8078+ err = vfsub_fsync(NULL, &h_path, datasync);
1facf9fc 8079+ }
8080+
8081+ return err;
8082+}
8083+
8084+static int au_do_fsync_dir(struct file *file, int datasync)
8085+{
8086+ int err;
8087+ aufs_bindex_t bend, bindex;
8088+ struct file *h_file;
8089+ struct super_block *sb;
8090+ struct inode *inode;
1facf9fc 8091+
8092+ err = au_reval_and_lock_fdi(file, reopen_dir, /*wlock*/1);
8093+ if (unlikely(err))
8094+ goto out;
8095+
8096+ sb = file->f_dentry->d_sb;
8097+ inode = file->f_dentry->d_inode;
4a4d8108 8098+ bend = au_fbend_dir(file);
1facf9fc 8099+ for (bindex = au_fbstart(file); !err && bindex <= bend; bindex++) {
4a4d8108 8100+ h_file = au_hf_dir(file, bindex);
1facf9fc 8101+ if (!h_file || au_test_ro(sb, bindex, inode))
8102+ continue;
8103+
53392da6 8104+ err = vfsub_fsync(h_file, &h_file->f_path, datasync);
1facf9fc 8105+ }
8106+
4f0767ce 8107+out:
1facf9fc 8108+ return err;
8109+}
8110+
8111+/*
8112+ * @file may be NULL
8113+ */
1e00d052
AM
8114+static int aufs_fsync_dir(struct file *file, loff_t start, loff_t end,
8115+ int datasync)
1facf9fc 8116+{
8117+ int err;
b752ccd1 8118+ struct dentry *dentry;
1facf9fc 8119+ struct super_block *sb;
1e00d052 8120+ struct mutex *mtx;
1facf9fc 8121+
8122+ err = 0;
1e00d052
AM
8123+ dentry = file->f_dentry;
8124+ mtx = &dentry->d_inode->i_mutex;
8125+ mutex_lock(mtx);
1facf9fc 8126+ sb = dentry->d_sb;
8127+ si_noflush_read_lock(sb);
8128+ if (file)
8129+ err = au_do_fsync_dir(file, datasync);
8130+ else {
8131+ di_write_lock_child(dentry);
8132+ err = au_do_fsync_dir_no_file(dentry, datasync);
8133+ }
8134+ au_cpup_attr_timesizes(dentry->d_inode);
8135+ di_write_unlock(dentry);
8136+ if (file)
8137+ fi_write_unlock(file);
8138+
8139+ si_read_unlock(sb);
1e00d052 8140+ mutex_unlock(mtx);
1facf9fc 8141+ return err;
8142+}
8143+
8144+/* ---------------------------------------------------------------------- */
8145+
8146+static int aufs_readdir(struct file *file, void *dirent, filldir_t filldir)
8147+{
8148+ int err;
8149+ struct dentry *dentry;
9dbd164d 8150+ struct inode *inode, *h_inode;
1facf9fc 8151+ struct super_block *sb;
8152+
8153+ dentry = file->f_dentry;
8154+ inode = dentry->d_inode;
8155+ IMustLock(inode);
8156+
8157+ sb = dentry->d_sb;
8158+ si_read_lock(sb, AuLock_FLUSH);
8159+ err = au_reval_and_lock_fdi(file, reopen_dir, /*wlock*/1);
8160+ if (unlikely(err))
8161+ goto out;
027c5e7a
AM
8162+ err = au_alive_dir(dentry);
8163+ if (!err)
8164+ err = au_vdir_init(file);
1facf9fc 8165+ di_downgrade_lock(dentry, AuLock_IR);
8166+ if (unlikely(err))
8167+ goto out_unlock;
8168+
9dbd164d 8169+ h_inode = au_h_iptr(inode, au_ibstart(inode));
b752ccd1 8170+ if (!au_test_nfsd()) {
1facf9fc 8171+ err = au_vdir_fill_de(file, dirent, filldir);
9dbd164d 8172+ fsstack_copy_attr_atime(inode, h_inode);
1facf9fc 8173+ } else {
8174+ /*
8175+ * nfsd filldir may call lookup_one_len(), vfs_getattr(),
8176+ * encode_fh() and others.
8177+ */
9dbd164d 8178+ atomic_inc(&h_inode->i_count);
1facf9fc 8179+ di_read_unlock(dentry, AuLock_IR);
8180+ si_read_unlock(sb);
1facf9fc 8181+ err = au_vdir_fill_de(file, dirent, filldir);
1facf9fc 8182+ fsstack_copy_attr_atime(inode, h_inode);
8183+ fi_write_unlock(file);
9dbd164d 8184+ iput(h_inode);
1facf9fc 8185+
8186+ AuTraceErr(err);
8187+ return err;
8188+ }
8189+
4f0767ce 8190+out_unlock:
1facf9fc 8191+ di_read_unlock(dentry, AuLock_IR);
8192+ fi_write_unlock(file);
4f0767ce 8193+out:
1facf9fc 8194+ si_read_unlock(sb);
8195+ return err;
8196+}
8197+
8198+/* ---------------------------------------------------------------------- */
8199+
8200+#define AuTestEmpty_WHONLY 1
dece6358
AM
8201+#define AuTestEmpty_CALLED (1 << 1)
8202+#define AuTestEmpty_SHWH (1 << 2)
1facf9fc 8203+#define au_ftest_testempty(flags, name) ((flags) & AuTestEmpty_##name)
7f207e10
AM
8204+#define au_fset_testempty(flags, name) \
8205+ do { (flags) |= AuTestEmpty_##name; } while (0)
8206+#define au_fclr_testempty(flags, name) \
8207+ do { (flags) &= ~AuTestEmpty_##name; } while (0)
1facf9fc 8208+
dece6358
AM
8209+#ifndef CONFIG_AUFS_SHWH
8210+#undef AuTestEmpty_SHWH
8211+#define AuTestEmpty_SHWH 0
8212+#endif
8213+
1facf9fc 8214+struct test_empty_arg {
1308ab2a 8215+ struct au_nhash *whlist;
1facf9fc 8216+ unsigned int flags;
8217+ int err;
8218+ aufs_bindex_t bindex;
8219+};
8220+
8221+static int test_empty_cb(void *__arg, const char *__name, int namelen,
dece6358
AM
8222+ loff_t offset __maybe_unused, u64 ino,
8223+ unsigned int d_type)
1facf9fc 8224+{
8225+ struct test_empty_arg *arg = __arg;
8226+ char *name = (void *)__name;
8227+
8228+ arg->err = 0;
8229+ au_fset_testempty(arg->flags, CALLED);
8230+ /* smp_mb(); */
8231+ if (name[0] == '.'
8232+ && (namelen == 1 || (name[1] == '.' && namelen == 2)))
8233+ goto out; /* success */
8234+
8235+ if (namelen <= AUFS_WH_PFX_LEN
8236+ || memcmp(name, AUFS_WH_PFX, AUFS_WH_PFX_LEN)) {
8237+ if (au_ftest_testempty(arg->flags, WHONLY)
1308ab2a 8238+ && !au_nhash_test_known_wh(arg->whlist, name, namelen))
1facf9fc 8239+ arg->err = -ENOTEMPTY;
8240+ goto out;
8241+ }
8242+
8243+ name += AUFS_WH_PFX_LEN;
8244+ namelen -= AUFS_WH_PFX_LEN;
1308ab2a 8245+ if (!au_nhash_test_known_wh(arg->whlist, name, namelen))
1facf9fc 8246+ arg->err = au_nhash_append_wh
1308ab2a 8247+ (arg->whlist, name, namelen, ino, d_type, arg->bindex,
dece6358 8248+ au_ftest_testempty(arg->flags, SHWH));
1facf9fc 8249+
4f0767ce 8250+out:
1facf9fc 8251+ /* smp_mb(); */
8252+ AuTraceErr(arg->err);
8253+ return arg->err;
8254+}
8255+
8256+static int do_test_empty(struct dentry *dentry, struct test_empty_arg *arg)
8257+{
8258+ int err;
8259+ struct file *h_file;
8260+
8261+ h_file = au_h_open(dentry, arg->bindex,
8262+ O_RDONLY | O_NONBLOCK | O_DIRECTORY | O_LARGEFILE,
8263+ /*file*/NULL);
8264+ err = PTR_ERR(h_file);
8265+ if (IS_ERR(h_file))
8266+ goto out;
8267+
8268+ err = 0;
8269+ if (!au_opt_test(au_mntflags(dentry->d_sb), UDBA_NONE)
8270+ && !h_file->f_dentry->d_inode->i_nlink)
8271+ goto out_put;
8272+
8273+ do {
8274+ arg->err = 0;
8275+ au_fclr_testempty(arg->flags, CALLED);
8276+ /* smp_mb(); */
8277+ err = vfsub_readdir(h_file, test_empty_cb, arg);
8278+ if (err >= 0)
8279+ err = arg->err;
8280+ } while (!err && au_ftest_testempty(arg->flags, CALLED));
8281+
4f0767ce 8282+out_put:
1facf9fc 8283+ fput(h_file);
8284+ au_sbr_put(dentry->d_sb, arg->bindex);
4f0767ce 8285+out:
1facf9fc 8286+ return err;
8287+}
8288+
8289+struct do_test_empty_args {
8290+ int *errp;
8291+ struct dentry *dentry;
8292+ struct test_empty_arg *arg;
8293+};
8294+
8295+static void call_do_test_empty(void *args)
8296+{
8297+ struct do_test_empty_args *a = args;
8298+ *a->errp = do_test_empty(a->dentry, a->arg);
8299+}
8300+
8301+static int sio_test_empty(struct dentry *dentry, struct test_empty_arg *arg)
8302+{
8303+ int err, wkq_err;
8304+ struct dentry *h_dentry;
8305+ struct inode *h_inode;
8306+
8307+ h_dentry = au_h_dptr(dentry, arg->bindex);
8308+ h_inode = h_dentry->d_inode;
53392da6 8309+ /* todo: i_mode changes anytime? */
1facf9fc 8310+ mutex_lock_nested(&h_inode->i_mutex, AuLsc_I_CHILD);
8311+ err = au_test_h_perm_sio(h_inode, MAY_EXEC | MAY_READ);
8312+ mutex_unlock(&h_inode->i_mutex);
8313+ if (!err)
8314+ err = do_test_empty(dentry, arg);
8315+ else {
8316+ struct do_test_empty_args args = {
8317+ .errp = &err,
8318+ .dentry = dentry,
8319+ .arg = arg
8320+ };
8321+ unsigned int flags = arg->flags;
8322+
8323+ wkq_err = au_wkq_wait(call_do_test_empty, &args);
8324+ if (unlikely(wkq_err))
8325+ err = wkq_err;
8326+ arg->flags = flags;
8327+ }
8328+
8329+ return err;
8330+}
8331+
8332+int au_test_empty_lower(struct dentry *dentry)
8333+{
8334+ int err;
1308ab2a 8335+ unsigned int rdhash;
1facf9fc 8336+ aufs_bindex_t bindex, bstart, btail;
1308ab2a 8337+ struct au_nhash whlist;
1facf9fc 8338+ struct test_empty_arg arg;
1facf9fc 8339+
dece6358
AM
8340+ SiMustAnyLock(dentry->d_sb);
8341+
1308ab2a 8342+ rdhash = au_sbi(dentry->d_sb)->si_rdhash;
8343+ if (!rdhash)
8344+ rdhash = au_rdhash_est(au_dir_size(/*file*/NULL, dentry));
8345+ err = au_nhash_alloc(&whlist, rdhash, GFP_NOFS);
dece6358 8346+ if (unlikely(err))
1facf9fc 8347+ goto out;
8348+
1facf9fc 8349+ arg.flags = 0;
1308ab2a 8350+ arg.whlist = &whlist;
8351+ bstart = au_dbstart(dentry);
dece6358
AM
8352+ if (au_opt_test(au_mntflags(dentry->d_sb), SHWH))
8353+ au_fset_testempty(arg.flags, SHWH);
1facf9fc 8354+ arg.bindex = bstart;
8355+ err = do_test_empty(dentry, &arg);
8356+ if (unlikely(err))
8357+ goto out_whlist;
8358+
8359+ au_fset_testempty(arg.flags, WHONLY);
8360+ btail = au_dbtaildir(dentry);
8361+ for (bindex = bstart + 1; !err && bindex <= btail; bindex++) {
8362+ struct dentry *h_dentry;
8363+
8364+ h_dentry = au_h_dptr(dentry, bindex);
8365+ if (h_dentry && h_dentry->d_inode) {
8366+ arg.bindex = bindex;
8367+ err = do_test_empty(dentry, &arg);
8368+ }
8369+ }
8370+
4f0767ce 8371+out_whlist:
1308ab2a 8372+ au_nhash_wh_free(&whlist);
4f0767ce 8373+out:
1facf9fc 8374+ return err;
8375+}
8376+
8377+int au_test_empty(struct dentry *dentry, struct au_nhash *whlist)
8378+{
8379+ int err;
8380+ struct test_empty_arg arg;
8381+ aufs_bindex_t bindex, btail;
8382+
8383+ err = 0;
1308ab2a 8384+ arg.whlist = whlist;
1facf9fc 8385+ arg.flags = AuTestEmpty_WHONLY;
dece6358
AM
8386+ if (au_opt_test(au_mntflags(dentry->d_sb), SHWH))
8387+ au_fset_testempty(arg.flags, SHWH);
1facf9fc 8388+ btail = au_dbtaildir(dentry);
8389+ for (bindex = au_dbstart(dentry); !err && bindex <= btail; bindex++) {
8390+ struct dentry *h_dentry;
8391+
8392+ h_dentry = au_h_dptr(dentry, bindex);
8393+ if (h_dentry && h_dentry->d_inode) {
8394+ arg.bindex = bindex;
8395+ err = sio_test_empty(dentry, &arg);
8396+ }
8397+ }
8398+
8399+ return err;
8400+}
8401+
8402+/* ---------------------------------------------------------------------- */
8403+
8404+const struct file_operations aufs_dir_fop = {
4a4d8108 8405+ .owner = THIS_MODULE,
027c5e7a 8406+ .llseek = default_llseek,
1facf9fc 8407+ .read = generic_read_dir,
8408+ .readdir = aufs_readdir,
8409+ .unlocked_ioctl = aufs_ioctl_dir,
b752ccd1
AM
8410+#ifdef CONFIG_COMPAT
8411+ .compat_ioctl = aufs_compat_ioctl_dir,
8412+#endif
1facf9fc 8413+ .open = aufs_open_dir,
8414+ .release = aufs_release_dir,
4a4d8108 8415+ .flush = aufs_flush_dir,
1facf9fc 8416+ .fsync = aufs_fsync_dir
8417+};
7f207e10
AM
8418diff -urN /usr/share/empty/fs/aufs/dir.h linux/fs/aufs/dir.h
8419--- /usr/share/empty/fs/aufs/dir.h 1970-01-01 01:00:00.000000000 +0100
537831f9 8420+++ linux/fs/aufs/dir.h 2012-12-13 20:41:10.428126759 +0100
f6c5ef8b 8421@@ -0,0 +1,137 @@
1facf9fc 8422+/*
f6c5ef8b 8423+ * Copyright (C) 2005-2012 Junjiro R. Okajima
1facf9fc 8424+ *
8425+ * This program, aufs is free software; you can redistribute it and/or modify
8426+ * it under the terms of the GNU General Public License as published by
8427+ * the Free Software Foundation; either version 2 of the License, or
8428+ * (at your option) any later version.
dece6358
AM
8429+ *
8430+ * This program is distributed in the hope that it will be useful,
8431+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
8432+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
8433+ * GNU General Public License for more details.
8434+ *
8435+ * You should have received a copy of the GNU General Public License
8436+ * along with this program; if not, write to the Free Software
8437+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 8438+ */
8439+
8440+/*
8441+ * directory operations
8442+ */
8443+
8444+#ifndef __AUFS_DIR_H__
8445+#define __AUFS_DIR_H__
8446+
8447+#ifdef __KERNEL__
8448+
8449+#include <linux/fs.h>
1facf9fc 8450+
8451+/* ---------------------------------------------------------------------- */
8452+
8453+/* need to be faster and smaller */
8454+
8455+struct au_nhash {
dece6358
AM
8456+ unsigned int nh_num;
8457+ struct hlist_head *nh_head;
1facf9fc 8458+};
8459+
8460+struct au_vdir_destr {
8461+ unsigned char len;
8462+ unsigned char name[0];
8463+} __packed;
8464+
8465+struct au_vdir_dehstr {
8466+ struct hlist_node hash;
8467+ struct au_vdir_destr *str;
4a4d8108 8468+} ____cacheline_aligned_in_smp;
1facf9fc 8469+
8470+struct au_vdir_de {
8471+ ino_t de_ino;
8472+ unsigned char de_type;
8473+ /* caution: packed */
8474+ struct au_vdir_destr de_str;
8475+} __packed;
8476+
8477+struct au_vdir_wh {
8478+ struct hlist_node wh_hash;
dece6358
AM
8479+#ifdef CONFIG_AUFS_SHWH
8480+ ino_t wh_ino;
1facf9fc 8481+ aufs_bindex_t wh_bindex;
dece6358
AM
8482+ unsigned char wh_type;
8483+#else
8484+ aufs_bindex_t wh_bindex;
8485+#endif
8486+ /* caution: packed */
1facf9fc 8487+ struct au_vdir_destr wh_str;
8488+} __packed;
8489+
8490+union au_vdir_deblk_p {
8491+ unsigned char *deblk;
8492+ struct au_vdir_de *de;
8493+};
8494+
8495+struct au_vdir {
8496+ unsigned char **vd_deblk;
8497+ unsigned long vd_nblk;
1facf9fc 8498+ struct {
8499+ unsigned long ul;
8500+ union au_vdir_deblk_p p;
8501+ } vd_last;
8502+
8503+ unsigned long vd_version;
dece6358 8504+ unsigned int vd_deblk_sz;
1facf9fc 8505+ unsigned long vd_jiffy;
4a4d8108 8506+} ____cacheline_aligned_in_smp;
1facf9fc 8507+
8508+/* ---------------------------------------------------------------------- */
8509+
8510+/* dir.c */
8511+extern const struct file_operations aufs_dir_fop;
8512+void au_add_nlink(struct inode *dir, struct inode *h_dir);
8513+void au_sub_nlink(struct inode *dir, struct inode *h_dir);
1308ab2a 8514+loff_t au_dir_size(struct file *file, struct dentry *dentry);
1facf9fc 8515+int au_test_empty_lower(struct dentry *dentry);
8516+int au_test_empty(struct dentry *dentry, struct au_nhash *whlist);
8517+
8518+/* vdir.c */
1308ab2a 8519+unsigned int au_rdhash_est(loff_t sz);
dece6358
AM
8520+int au_nhash_alloc(struct au_nhash *nhash, unsigned int num_hash, gfp_t gfp);
8521+void au_nhash_wh_free(struct au_nhash *whlist);
1facf9fc 8522+int au_nhash_test_longer_wh(struct au_nhash *whlist, aufs_bindex_t btgt,
8523+ int limit);
dece6358
AM
8524+int au_nhash_test_known_wh(struct au_nhash *whlist, char *name, int nlen);
8525+int au_nhash_append_wh(struct au_nhash *whlist, char *name, int nlen, ino_t ino,
8526+ unsigned int d_type, aufs_bindex_t bindex,
8527+ unsigned char shwh);
1facf9fc 8528+void au_vdir_free(struct au_vdir *vdir);
8529+int au_vdir_init(struct file *file);
8530+int au_vdir_fill_de(struct file *file, void *dirent, filldir_t filldir);
8531+
8532+/* ioctl.c */
8533+long aufs_ioctl_dir(struct file *file, unsigned int cmd, unsigned long arg);
8534+
1308ab2a 8535+#ifdef CONFIG_AUFS_RDU
8536+/* rdu.c */
8537+long au_rdu_ioctl(struct file *file, unsigned int cmd, unsigned long arg);
b752ccd1
AM
8538+#ifdef CONFIG_COMPAT
8539+long au_rdu_compat_ioctl(struct file *file, unsigned int cmd,
8540+ unsigned long arg);
8541+#endif
1308ab2a 8542+#else
8543+static inline long au_rdu_ioctl(struct file *file, unsigned int cmd,
8544+ unsigned long arg)
8545+{
8546+ return -EINVAL;
8547+}
b752ccd1
AM
8548+#ifdef CONFIG_COMPAT
8549+static inline long au_rdu_compat_ioctl(struct file *file, unsigned int cmd,
8550+ unsigned long arg)
8551+{
8552+ return -EINVAL;
8553+}
8554+#endif
1308ab2a 8555+#endif
8556+
1facf9fc 8557+#endif /* __KERNEL__ */
8558+#endif /* __AUFS_DIR_H__ */
7f207e10
AM
8559diff -urN /usr/share/empty/fs/aufs/dynop.c linux/fs/aufs/dynop.c
8560--- /usr/share/empty/fs/aufs/dynop.c 1970-01-01 01:00:00.000000000 +0100
537831f9 8561+++ linux/fs/aufs/dynop.c 2012-12-13 20:41:10.428126759 +0100
b4510431 8562@@ -0,0 +1,379 @@
1facf9fc 8563+/*
f6c5ef8b 8564+ * Copyright (C) 2010-2012 Junjiro R. Okajima
1facf9fc 8565+ *
8566+ * This program, aufs is free software; you can redistribute it and/or modify
8567+ * it under the terms of the GNU General Public License as published by
8568+ * the Free Software Foundation; either version 2 of the License, or
8569+ * (at your option) any later version.
dece6358
AM
8570+ *
8571+ * This program is distributed in the hope that it will be useful,
8572+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
8573+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
8574+ * GNU General Public License for more details.
8575+ *
8576+ * You should have received a copy of the GNU General Public License
8577+ * along with this program; if not, write to the Free Software
8578+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 8579+ */
8580+
8581+/*
4a4d8108 8582+ * dynamically customizable operations for regular files
1facf9fc 8583+ */
8584+
1facf9fc 8585+#include "aufs.h"
8586+
4a4d8108 8587+#define DyPrSym(key) AuDbgSym(key->dk_op.dy_hop)
1facf9fc 8588+
4a4d8108
AM
8589+/*
8590+ * How large will these lists be?
8591+ * Usually just a few elements, 20-30 at most for each, I guess.
8592+ */
8593+static struct au_splhead dynop[AuDyLast];
8594+
8595+static struct au_dykey *dy_gfind_get(struct au_splhead *spl, const void *h_op)
1facf9fc 8596+{
4a4d8108
AM
8597+ struct au_dykey *key, *tmp;
8598+ struct list_head *head;
1facf9fc 8599+
4a4d8108
AM
8600+ key = NULL;
8601+ head = &spl->head;
8602+ rcu_read_lock();
8603+ list_for_each_entry_rcu(tmp, head, dk_list)
8604+ if (tmp->dk_op.dy_hop == h_op) {
8605+ key = tmp;
8606+ kref_get(&key->dk_kref);
8607+ break;
8608+ }
8609+ rcu_read_unlock();
8610+
8611+ return key;
1facf9fc 8612+}
8613+
4a4d8108 8614+static struct au_dykey *dy_bradd(struct au_branch *br, struct au_dykey *key)
1facf9fc 8615+{
4a4d8108
AM
8616+ struct au_dykey **k, *found;
8617+ const void *h_op = key->dk_op.dy_hop;
8618+ int i;
1facf9fc 8619+
4a4d8108
AM
8620+ found = NULL;
8621+ k = br->br_dykey;
8622+ for (i = 0; i < AuBrDynOp; i++)
8623+ if (k[i]) {
8624+ if (k[i]->dk_op.dy_hop == h_op) {
8625+ found = k[i];
8626+ break;
8627+ }
8628+ } else
8629+ break;
8630+ if (!found) {
8631+ spin_lock(&br->br_dykey_lock);
8632+ for (; i < AuBrDynOp; i++)
8633+ if (k[i]) {
8634+ if (k[i]->dk_op.dy_hop == h_op) {
8635+ found = k[i];
8636+ break;
8637+ }
8638+ } else {
8639+ k[i] = key;
8640+ break;
8641+ }
8642+ spin_unlock(&br->br_dykey_lock);
8643+ BUG_ON(i == AuBrDynOp); /* expand the array */
8644+ }
8645+
8646+ return found;
1facf9fc 8647+}
8648+
4a4d8108
AM
8649+/* kref_get() if @key is already added */
8650+static struct au_dykey *dy_gadd(struct au_splhead *spl, struct au_dykey *key)
8651+{
8652+ struct au_dykey *tmp, *found;
8653+ struct list_head *head;
8654+ const void *h_op = key->dk_op.dy_hop;
1facf9fc 8655+
4a4d8108
AM
8656+ found = NULL;
8657+ head = &spl->head;
8658+ spin_lock(&spl->spin);
8659+ list_for_each_entry(tmp, head, dk_list)
8660+ if (tmp->dk_op.dy_hop == h_op) {
8661+ kref_get(&tmp->dk_kref);
8662+ found = tmp;
8663+ break;
8664+ }
8665+ if (!found)
8666+ list_add_rcu(&key->dk_list, head);
8667+ spin_unlock(&spl->spin);
1facf9fc 8668+
4a4d8108
AM
8669+ if (!found)
8670+ DyPrSym(key);
8671+ return found;
8672+}
8673+
8674+static void dy_free_rcu(struct rcu_head *rcu)
1facf9fc 8675+{
4a4d8108
AM
8676+ struct au_dykey *key;
8677+
8678+ key = container_of(rcu, struct au_dykey, dk_rcu);
8679+ DyPrSym(key);
8680+ kfree(key);
1facf9fc 8681+}
8682+
4a4d8108
AM
8683+static void dy_free(struct kref *kref)
8684+{
8685+ struct au_dykey *key;
8686+ struct au_splhead *spl;
1facf9fc 8687+
4a4d8108
AM
8688+ key = container_of(kref, struct au_dykey, dk_kref);
8689+ spl = dynop + key->dk_op.dy_type;
8690+ au_spl_del_rcu(&key->dk_list, spl);
8691+ call_rcu(&key->dk_rcu, dy_free_rcu);
8692+}
8693+
8694+void au_dy_put(struct au_dykey *key)
1facf9fc 8695+{
4a4d8108
AM
8696+ kref_put(&key->dk_kref, dy_free);
8697+}
1facf9fc 8698+
4a4d8108
AM
8699+/* ---------------------------------------------------------------------- */
8700+
8701+#define DyDbgSize(cnt, op) AuDebugOn(cnt != sizeof(op)/sizeof(void *))
8702+
8703+#ifdef CONFIG_AUFS_DEBUG
8704+#define DyDbgDeclare(cnt) unsigned int cnt = 0
4f0767ce 8705+#define DyDbgInc(cnt) do { cnt++; } while (0)
4a4d8108
AM
8706+#else
8707+#define DyDbgDeclare(cnt) do {} while (0)
8708+#define DyDbgInc(cnt) do {} while (0)
8709+#endif
8710+
8711+#define DySet(func, dst, src, h_op, h_sb) do { \
8712+ DyDbgInc(cnt); \
8713+ if (h_op->func) { \
8714+ if (src.func) \
8715+ dst.func = src.func; \
8716+ else \
8717+ AuDbg("%s %s\n", au_sbtype(h_sb), #func); \
8718+ } \
8719+} while (0)
8720+
8721+#define DySetForce(func, dst, src) do { \
8722+ AuDebugOn(!src.func); \
8723+ DyDbgInc(cnt); \
8724+ dst.func = src.func; \
8725+} while (0)
8726+
8727+#define DySetAop(func) \
8728+ DySet(func, dyaop->da_op, aufs_aop, h_aop, h_sb)
8729+#define DySetAopForce(func) \
8730+ DySetForce(func, dyaop->da_op, aufs_aop)
8731+
8732+static void dy_aop(struct au_dykey *key, const void *h_op,
8733+ struct super_block *h_sb __maybe_unused)
8734+{
8735+ struct au_dyaop *dyaop = (void *)key;
8736+ const struct address_space_operations *h_aop = h_op;
8737+ DyDbgDeclare(cnt);
8738+
8739+ AuDbg("%s\n", au_sbtype(h_sb));
8740+
8741+ DySetAop(writepage);
8742+ DySetAopForce(readpage); /* force */
4a4d8108
AM
8743+ DySetAop(writepages);
8744+ DySetAop(set_page_dirty);
8745+ DySetAop(readpages);
8746+ DySetAop(write_begin);
8747+ DySetAop(write_end);
8748+ DySetAop(bmap);
8749+ DySetAop(invalidatepage);
8750+ DySetAop(releasepage);
027c5e7a 8751+ DySetAop(freepage);
4a4d8108
AM
8752+ /* these two will be changed according to an aufs mount option */
8753+ DySetAop(direct_IO);
8754+ DySetAop(get_xip_mem);
8755+ DySetAop(migratepage);
8756+ DySetAop(launder_page);
8757+ DySetAop(is_partially_uptodate);
8758+ DySetAop(error_remove_page);
b4510431
AM
8759+ DySetAop(swap_activate);
8760+ DySetAop(swap_deactivate);
4a4d8108
AM
8761+
8762+ DyDbgSize(cnt, *h_aop);
8763+ dyaop->da_get_xip_mem = h_aop->get_xip_mem;
8764+}
8765+
4a4d8108
AM
8766+/* ---------------------------------------------------------------------- */
8767+
8768+static void dy_bug(struct kref *kref)
8769+{
8770+ BUG();
8771+}
8772+
8773+static struct au_dykey *dy_get(struct au_dynop *op, struct au_branch *br)
8774+{
8775+ struct au_dykey *key, *old;
8776+ struct au_splhead *spl;
b752ccd1 8777+ struct op {
4a4d8108 8778+ unsigned int sz;
b752ccd1
AM
8779+ void (*set)(struct au_dykey *key, const void *h_op,
8780+ struct super_block *h_sb __maybe_unused);
8781+ };
8782+ static const struct op a[] = {
4a4d8108
AM
8783+ [AuDy_AOP] = {
8784+ .sz = sizeof(struct au_dyaop),
b752ccd1 8785+ .set = dy_aop
4a4d8108 8786+ }
b752ccd1
AM
8787+ };
8788+ const struct op *p;
4a4d8108
AM
8789+
8790+ spl = dynop + op->dy_type;
8791+ key = dy_gfind_get(spl, op->dy_hop);
8792+ if (key)
8793+ goto out_add; /* success */
8794+
8795+ p = a + op->dy_type;
8796+ key = kzalloc(p->sz, GFP_NOFS);
8797+ if (unlikely(!key)) {
8798+ key = ERR_PTR(-ENOMEM);
8799+ goto out;
8800+ }
8801+
8802+ key->dk_op.dy_hop = op->dy_hop;
8803+ kref_init(&key->dk_kref);
b752ccd1 8804+ p->set(key, op->dy_hop, br->br_mnt->mnt_sb);
4a4d8108
AM
8805+ old = dy_gadd(spl, key);
8806+ if (old) {
8807+ kfree(key);
8808+ key = old;
8809+ }
8810+
8811+out_add:
8812+ old = dy_bradd(br, key);
8813+ if (old)
8814+ /* its ref-count should never be zero here */
8815+ kref_put(&key->dk_kref, dy_bug);
8816+out:
8817+ return key;
8818+}
8819+
8820+/* ---------------------------------------------------------------------- */
8821+/*
8822+ * Aufs prohibits O_DIRECT by defaut even if the branch supports it.
8823+ * This behaviour is neccessary to return an error from open(O_DIRECT) instead
8824+ * of the succeeding I/O. The dio mount option enables O_DIRECT and makes
8825+ * open(O_DIRECT) always succeed, but the succeeding I/O may return an error.
8826+ * See the aufs manual in detail.
8827+ *
8828+ * To keep this behaviour, aufs has to set NULL to ->get_xip_mem too, and the
8829+ * performance of fadvise() and madvise() may be affected.
8830+ */
8831+static void dy_adx(struct au_dyaop *dyaop, int do_dx)
8832+{
8833+ if (!do_dx) {
8834+ dyaop->da_op.direct_IO = NULL;
8835+ dyaop->da_op.get_xip_mem = NULL;
8836+ } else {
8837+ dyaop->da_op.direct_IO = aufs_aop.direct_IO;
8838+ dyaop->da_op.get_xip_mem = aufs_aop.get_xip_mem;
8839+ if (!dyaop->da_get_xip_mem)
8840+ dyaop->da_op.get_xip_mem = NULL;
8841+ }
8842+}
8843+
8844+static struct au_dyaop *dy_aget(struct au_branch *br,
8845+ const struct address_space_operations *h_aop,
8846+ int do_dx)
8847+{
8848+ struct au_dyaop *dyaop;
8849+ struct au_dynop op;
8850+
8851+ op.dy_type = AuDy_AOP;
8852+ op.dy_haop = h_aop;
8853+ dyaop = (void *)dy_get(&op, br);
8854+ if (IS_ERR(dyaop))
8855+ goto out;
8856+ dy_adx(dyaop, do_dx);
8857+
8858+out:
8859+ return dyaop;
8860+}
8861+
8862+int au_dy_iaop(struct inode *inode, aufs_bindex_t bindex,
8863+ struct inode *h_inode)
8864+{
8865+ int err, do_dx;
8866+ struct super_block *sb;
8867+ struct au_branch *br;
8868+ struct au_dyaop *dyaop;
8869+
8870+ AuDebugOn(!S_ISREG(h_inode->i_mode));
8871+ IiMustWriteLock(inode);
8872+
8873+ sb = inode->i_sb;
8874+ br = au_sbr(sb, bindex);
8875+ do_dx = !!au_opt_test(au_mntflags(sb), DIO);
8876+ dyaop = dy_aget(br, h_inode->i_mapping->a_ops, do_dx);
8877+ err = PTR_ERR(dyaop);
8878+ if (IS_ERR(dyaop))
8879+ /* unnecessary to call dy_fput() */
8880+ goto out;
8881+
8882+ err = 0;
8883+ inode->i_mapping->a_ops = &dyaop->da_op;
8884+
8885+out:
8886+ return err;
8887+}
8888+
b752ccd1
AM
8889+/*
8890+ * Is it safe to replace a_ops during the inode/file is in operation?
8891+ * Yes, I hope so.
8892+ */
8893+int au_dy_irefresh(struct inode *inode)
8894+{
8895+ int err;
8896+ aufs_bindex_t bstart;
8897+ struct inode *h_inode;
8898+
8899+ err = 0;
8900+ if (S_ISREG(inode->i_mode)) {
8901+ bstart = au_ibstart(inode);
8902+ h_inode = au_h_iptr(inode, bstart);
8903+ err = au_dy_iaop(inode, bstart, h_inode);
8904+ }
8905+ return err;
8906+}
8907+
4a4d8108
AM
8908+void au_dy_arefresh(int do_dx)
8909+{
8910+ struct au_splhead *spl;
8911+ struct list_head *head;
8912+ struct au_dykey *key;
8913+
8914+ spl = dynop + AuDy_AOP;
8915+ head = &spl->head;
8916+ spin_lock(&spl->spin);
8917+ list_for_each_entry(key, head, dk_list)
8918+ dy_adx((void *)key, do_dx);
8919+ spin_unlock(&spl->spin);
8920+}
8921+
4a4d8108
AM
8922+/* ---------------------------------------------------------------------- */
8923+
8924+void __init au_dy_init(void)
8925+{
8926+ int i;
8927+
8928+ /* make sure that 'struct au_dykey *' can be any type */
8929+ BUILD_BUG_ON(offsetof(struct au_dyaop, da_key));
4a4d8108
AM
8930+
8931+ for (i = 0; i < AuDyLast; i++)
8932+ au_spl_init(dynop + i);
8933+}
8934+
8935+void au_dy_fin(void)
8936+{
8937+ int i;
8938+
8939+ for (i = 0; i < AuDyLast; i++)
8940+ WARN_ON(!list_empty(&dynop[i].head));
8941+}
7f207e10
AM
8942diff -urN /usr/share/empty/fs/aufs/dynop.h linux/fs/aufs/dynop.h
8943--- /usr/share/empty/fs/aufs/dynop.h 1970-01-01 01:00:00.000000000 +0100
537831f9 8944+++ linux/fs/aufs/dynop.h 2012-12-13 20:41:10.428126759 +0100
f6c5ef8b 8945@@ -0,0 +1,76 @@
4a4d8108 8946+/*
f6c5ef8b 8947+ * Copyright (C) 2010-2012 Junjiro R. Okajima
4a4d8108
AM
8948+ *
8949+ * This program, aufs is free software; you can redistribute it and/or modify
8950+ * it under the terms of the GNU General Public License as published by
8951+ * the Free Software Foundation; either version 2 of the License, or
8952+ * (at your option) any later version.
8953+ *
8954+ * This program is distributed in the hope that it will be useful,
8955+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
8956+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
8957+ * GNU General Public License for more details.
8958+ *
8959+ * You should have received a copy of the GNU General Public License
8960+ * along with this program; if not, write to the Free Software
8961+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
8962+ */
8963+
8964+/*
8965+ * dynamically customizable operations (for regular files only)
8966+ */
8967+
8968+#ifndef __AUFS_DYNOP_H__
8969+#define __AUFS_DYNOP_H__
8970+
8971+#ifdef __KERNEL__
8972+
4a4d8108
AM
8973+#include "inode.h"
8974+
2cbb1c4b 8975+enum {AuDy_AOP, AuDyLast};
4a4d8108
AM
8976+
8977+struct au_dynop {
8978+ int dy_type;
8979+ union {
8980+ const void *dy_hop;
8981+ const struct address_space_operations *dy_haop;
4a4d8108
AM
8982+ };
8983+};
8984+
8985+struct au_dykey {
8986+ union {
8987+ struct list_head dk_list;
8988+ struct rcu_head dk_rcu;
8989+ };
8990+ struct au_dynop dk_op;
8991+
8992+ /*
8993+ * during I am in the branch local array, kref is gotten. when the
8994+ * branch is removed, kref is put.
8995+ */
8996+ struct kref dk_kref;
8997+};
8998+
8999+/* stop unioning since their sizes are very different from each other */
9000+struct au_dyaop {
9001+ struct au_dykey da_key;
9002+ struct address_space_operations da_op; /* not const */
9003+ int (*da_get_xip_mem)(struct address_space *, pgoff_t, int,
9004+ void **, unsigned long *);
9005+};
9006+
4a4d8108
AM
9007+/* ---------------------------------------------------------------------- */
9008+
9009+/* dynop.c */
9010+struct au_branch;
9011+void au_dy_put(struct au_dykey *key);
9012+int au_dy_iaop(struct inode *inode, aufs_bindex_t bindex,
9013+ struct inode *h_inode);
b752ccd1 9014+int au_dy_irefresh(struct inode *inode);
4a4d8108 9015+void au_dy_arefresh(int do_dio);
4a4d8108
AM
9016+
9017+void __init au_dy_init(void);
9018+void au_dy_fin(void);
9019+
4a4d8108
AM
9020+#endif /* __KERNEL__ */
9021+#endif /* __AUFS_DYNOP_H__ */
7f207e10
AM
9022diff -urN /usr/share/empty/fs/aufs/export.c linux/fs/aufs/export.c
9023--- /usr/share/empty/fs/aufs/export.c 1970-01-01 01:00:00.000000000 +0100
537831f9 9024+++ linux/fs/aufs/export.c 2012-12-13 20:41:10.428126759 +0100
b4510431 9025@@ -0,0 +1,811 @@
4a4d8108 9026+/*
f6c5ef8b 9027+ * Copyright (C) 2005-2012 Junjiro R. Okajima
4a4d8108
AM
9028+ *
9029+ * This program, aufs is free software; you can redistribute it and/or modify
9030+ * it under the terms of the GNU General Public License as published by
9031+ * the Free Software Foundation; either version 2 of the License, or
9032+ * (at your option) any later version.
9033+ *
9034+ * This program is distributed in the hope that it will be useful,
9035+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
9036+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
9037+ * GNU General Public License for more details.
9038+ *
9039+ * You should have received a copy of the GNU General Public License
9040+ * along with this program; if not, write to the Free Software
9041+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
9042+ */
9043+
9044+/*
9045+ * export via nfs
9046+ */
9047+
9048+#include <linux/exportfs.h>
7eafdf33 9049+#include <linux/fs_struct.h>
4a4d8108
AM
9050+#include <linux/namei.h>
9051+#include <linux/nsproxy.h>
9052+#include <linux/random.h>
9053+#include <linux/writeback.h>
7eafdf33 9054+#include "../fs/mount.h"
4a4d8108
AM
9055+#include "aufs.h"
9056+
9057+union conv {
9058+#ifdef CONFIG_AUFS_INO_T_64
9059+ __u32 a[2];
9060+#else
9061+ __u32 a[1];
9062+#endif
9063+ ino_t ino;
9064+};
9065+
9066+static ino_t decode_ino(__u32 *a)
9067+{
9068+ union conv u;
9069+
9070+ BUILD_BUG_ON(sizeof(u.ino) != sizeof(u.a));
9071+ u.a[0] = a[0];
9072+#ifdef CONFIG_AUFS_INO_T_64
9073+ u.a[1] = a[1];
9074+#endif
9075+ return u.ino;
9076+}
9077+
9078+static void encode_ino(__u32 *a, ino_t ino)
9079+{
9080+ union conv u;
9081+
9082+ u.ino = ino;
9083+ a[0] = u.a[0];
9084+#ifdef CONFIG_AUFS_INO_T_64
9085+ a[1] = u.a[1];
9086+#endif
9087+}
9088+
9089+/* NFS file handle */
9090+enum {
9091+ Fh_br_id,
9092+ Fh_sigen,
9093+#ifdef CONFIG_AUFS_INO_T_64
9094+ /* support 64bit inode number */
9095+ Fh_ino1,
9096+ Fh_ino2,
9097+ Fh_dir_ino1,
9098+ Fh_dir_ino2,
9099+#else
9100+ Fh_ino1,
9101+ Fh_dir_ino1,
9102+#endif
9103+ Fh_igen,
9104+ Fh_h_type,
9105+ Fh_tail,
9106+
9107+ Fh_ino = Fh_ino1,
9108+ Fh_dir_ino = Fh_dir_ino1
9109+};
9110+
9111+static int au_test_anon(struct dentry *dentry)
9112+{
027c5e7a 9113+ /* note: read d_flags without d_lock */
4a4d8108
AM
9114+ return !!(dentry->d_flags & DCACHE_DISCONNECTED);
9115+}
9116+
9117+/* ---------------------------------------------------------------------- */
9118+/* inode generation external table */
9119+
b752ccd1 9120+void au_xigen_inc(struct inode *inode)
4a4d8108 9121+{
4a4d8108
AM
9122+ loff_t pos;
9123+ ssize_t sz;
9124+ __u32 igen;
9125+ struct super_block *sb;
9126+ struct au_sbinfo *sbinfo;
9127+
4a4d8108 9128+ sb = inode->i_sb;
b752ccd1 9129+ AuDebugOn(!au_opt_test(au_mntflags(sb), XINO));
1facf9fc 9130+
b752ccd1 9131+ sbinfo = au_sbi(sb);
1facf9fc 9132+ pos = inode->i_ino;
9133+ pos *= sizeof(igen);
9134+ igen = inode->i_generation + 1;
1facf9fc 9135+ sz = xino_fwrite(sbinfo->si_xwrite, sbinfo->si_xigen, &igen,
9136+ sizeof(igen), &pos);
9137+ if (sz == sizeof(igen))
b752ccd1 9138+ return; /* success */
1facf9fc 9139+
b752ccd1 9140+ if (unlikely(sz >= 0))
1facf9fc 9141+ AuIOErr("xigen error (%zd)\n", sz);
1facf9fc 9142+}
9143+
9144+int au_xigen_new(struct inode *inode)
9145+{
9146+ int err;
9147+ loff_t pos;
9148+ ssize_t sz;
9149+ struct super_block *sb;
9150+ struct au_sbinfo *sbinfo;
9151+ struct file *file;
9152+
9153+ err = 0;
9154+ /* todo: dirty, at mount time */
9155+ if (inode->i_ino == AUFS_ROOT_INO)
9156+ goto out;
9157+ sb = inode->i_sb;
dece6358 9158+ SiMustAnyLock(sb);
1facf9fc 9159+ if (unlikely(!au_opt_test(au_mntflags(sb), XINO)))
9160+ goto out;
9161+
9162+ err = -EFBIG;
9163+ pos = inode->i_ino;
9164+ if (unlikely(au_loff_max / sizeof(inode->i_generation) - 1 < pos)) {
9165+ AuIOErr1("too large i%lld\n", pos);
9166+ goto out;
9167+ }
9168+ pos *= sizeof(inode->i_generation);
9169+
9170+ err = 0;
9171+ sbinfo = au_sbi(sb);
9172+ file = sbinfo->si_xigen;
9173+ BUG_ON(!file);
9174+
9175+ if (i_size_read(file->f_dentry->d_inode)
9176+ < pos + sizeof(inode->i_generation)) {
9177+ inode->i_generation = atomic_inc_return(&sbinfo->si_xigen_next);
9178+ sz = xino_fwrite(sbinfo->si_xwrite, file, &inode->i_generation,
9179+ sizeof(inode->i_generation), &pos);
9180+ } else
9181+ sz = xino_fread(sbinfo->si_xread, file, &inode->i_generation,
9182+ sizeof(inode->i_generation), &pos);
9183+ if (sz == sizeof(inode->i_generation))
9184+ goto out; /* success */
9185+
9186+ err = sz;
9187+ if (unlikely(sz >= 0)) {
9188+ err = -EIO;
9189+ AuIOErr("xigen error (%zd)\n", sz);
9190+ }
9191+
4f0767ce 9192+out:
1facf9fc 9193+ return err;
9194+}
9195+
9196+int au_xigen_set(struct super_block *sb, struct file *base)
9197+{
9198+ int err;
9199+ struct au_sbinfo *sbinfo;
9200+ struct file *file;
9201+
dece6358
AM
9202+ SiMustWriteLock(sb);
9203+
1facf9fc 9204+ sbinfo = au_sbi(sb);
9205+ file = au_xino_create2(base, sbinfo->si_xigen);
9206+ err = PTR_ERR(file);
9207+ if (IS_ERR(file))
9208+ goto out;
9209+ err = 0;
9210+ if (sbinfo->si_xigen)
9211+ fput(sbinfo->si_xigen);
9212+ sbinfo->si_xigen = file;
9213+
4f0767ce 9214+out:
1facf9fc 9215+ return err;
9216+}
9217+
9218+void au_xigen_clr(struct super_block *sb)
9219+{
9220+ struct au_sbinfo *sbinfo;
9221+
dece6358
AM
9222+ SiMustWriteLock(sb);
9223+
1facf9fc 9224+ sbinfo = au_sbi(sb);
9225+ if (sbinfo->si_xigen) {
9226+ fput(sbinfo->si_xigen);
9227+ sbinfo->si_xigen = NULL;
9228+ }
9229+}
9230+
9231+/* ---------------------------------------------------------------------- */
9232+
9233+static struct dentry *decode_by_ino(struct super_block *sb, ino_t ino,
9234+ ino_t dir_ino)
9235+{
9236+ struct dentry *dentry, *d;
9237+ struct inode *inode;
9238+ unsigned int sigen;
b4510431 9239+ struct hlist_node *p;
1facf9fc 9240+
9241+ dentry = NULL;
9242+ inode = ilookup(sb, ino);
9243+ if (!inode)
9244+ goto out;
9245+
9246+ dentry = ERR_PTR(-ESTALE);
9247+ sigen = au_sigen(sb);
9248+ if (unlikely(is_bad_inode(inode)
9249+ || IS_DEADDIR(inode)
537831f9 9250+ || sigen != au_iigen(inode, NULL)))
1facf9fc 9251+ goto out_iput;
9252+
9253+ dentry = NULL;
9254+ if (!dir_ino || S_ISDIR(inode->i_mode))
9255+ dentry = d_find_alias(inode);
9256+ else {
027c5e7a 9257+ spin_lock(&inode->i_lock);
b4510431 9258+ hlist_for_each_entry(d, p, &inode->i_dentry, d_alias) {
027c5e7a 9259+ spin_lock(&d->d_lock);
1facf9fc 9260+ if (!au_test_anon(d)
9261+ && d->d_parent->d_inode->i_ino == dir_ino) {
027c5e7a
AM
9262+ dentry = dget_dlock(d);
9263+ spin_unlock(&d->d_lock);
1facf9fc 9264+ break;
9265+ }
027c5e7a
AM
9266+ spin_unlock(&d->d_lock);
9267+ }
9268+ spin_unlock(&inode->i_lock);
1facf9fc 9269+ }
027c5e7a 9270+ if (unlikely(dentry && au_digen_test(dentry, sigen))) {
2cbb1c4b 9271+ /* need to refresh */
1facf9fc 9272+ dput(dentry);
2cbb1c4b 9273+ dentry = NULL;
1facf9fc 9274+ }
9275+
4f0767ce 9276+out_iput:
1facf9fc 9277+ iput(inode);
4f0767ce 9278+out:
2cbb1c4b 9279+ AuTraceErrPtr(dentry);
1facf9fc 9280+ return dentry;
9281+}
9282+
9283+/* ---------------------------------------------------------------------- */
9284+
9285+/* todo: dirty? */
9286+/* if exportfs_decode_fh() passed vfsmount*, we could be happy */
4a4d8108
AM
9287+
9288+struct au_compare_mnt_args {
9289+ /* input */
9290+ struct super_block *sb;
9291+
9292+ /* output */
9293+ struct vfsmount *mnt;
9294+};
9295+
9296+static int au_compare_mnt(struct vfsmount *mnt, void *arg)
9297+{
9298+ struct au_compare_mnt_args *a = arg;
9299+
9300+ if (mnt->mnt_sb != a->sb)
9301+ return 0;
9302+ a->mnt = mntget(mnt);
9303+ return 1;
9304+}
9305+
1facf9fc 9306+static struct vfsmount *au_mnt_get(struct super_block *sb)
9307+{
4a4d8108 9308+ int err;
7eafdf33 9309+ struct path root;
4a4d8108
AM
9310+ struct au_compare_mnt_args args = {
9311+ .sb = sb
9312+ };
1facf9fc 9313+
7eafdf33 9314+ get_fs_root(current->fs, &root);
0c3ec466 9315+ br_read_lock(&vfsmount_lock);
7eafdf33 9316+ err = iterate_mounts(au_compare_mnt, &args, root.mnt);
0c3ec466 9317+ br_read_unlock(&vfsmount_lock);
7eafdf33 9318+ path_put(&root);
4a4d8108
AM
9319+ AuDebugOn(!err);
9320+ AuDebugOn(!args.mnt);
9321+ return args.mnt;
1facf9fc 9322+}
9323+
9324+struct au_nfsd_si_lock {
4a4d8108 9325+ unsigned int sigen;
027c5e7a 9326+ aufs_bindex_t bindex, br_id;
1facf9fc 9327+ unsigned char force_lock;
9328+};
9329+
027c5e7a
AM
9330+static int si_nfsd_read_lock(struct super_block *sb,
9331+ struct au_nfsd_si_lock *nsi_lock)
1facf9fc 9332+{
027c5e7a 9333+ int err;
1facf9fc 9334+ aufs_bindex_t bindex;
9335+
9336+ si_read_lock(sb, AuLock_FLUSH);
9337+
9338+ /* branch id may be wrapped around */
027c5e7a 9339+ err = 0;
1facf9fc 9340+ bindex = au_br_index(sb, nsi_lock->br_id);
9341+ if (bindex >= 0 && nsi_lock->sigen + AUFS_BRANCH_MAX > au_sigen(sb))
9342+ goto out; /* success */
9343+
027c5e7a
AM
9344+ err = -ESTALE;
9345+ bindex = -1;
1facf9fc 9346+ if (!nsi_lock->force_lock)
9347+ si_read_unlock(sb);
1facf9fc 9348+
4f0767ce 9349+out:
027c5e7a
AM
9350+ nsi_lock->bindex = bindex;
9351+ return err;
1facf9fc 9352+}
9353+
9354+struct find_name_by_ino {
9355+ int called, found;
9356+ ino_t ino;
9357+ char *name;
9358+ int namelen;
9359+};
9360+
9361+static int
9362+find_name_by_ino(void *arg, const char *name, int namelen, loff_t offset,
9363+ u64 ino, unsigned int d_type)
9364+{
9365+ struct find_name_by_ino *a = arg;
9366+
9367+ a->called++;
9368+ if (a->ino != ino)
9369+ return 0;
9370+
9371+ memcpy(a->name, name, namelen);
9372+ a->namelen = namelen;
9373+ a->found = 1;
9374+ return 1;
9375+}
9376+
9377+static struct dentry *au_lkup_by_ino(struct path *path, ino_t ino,
9378+ struct au_nfsd_si_lock *nsi_lock)
9379+{
9380+ struct dentry *dentry, *parent;
9381+ struct file *file;
9382+ struct inode *dir;
9383+ struct find_name_by_ino arg;
9384+ int err;
9385+
9386+ parent = path->dentry;
9387+ if (nsi_lock)
9388+ si_read_unlock(parent->d_sb);
4a4d8108 9389+ file = vfsub_dentry_open(path, au_dir_roflags);
1facf9fc 9390+ dentry = (void *)file;
9391+ if (IS_ERR(file))
9392+ goto out;
9393+
9394+ dentry = ERR_PTR(-ENOMEM);
537831f9 9395+ arg.name = (void *)__get_free_page(GFP_NOFS);
1facf9fc 9396+ if (unlikely(!arg.name))
9397+ goto out_file;
9398+ arg.ino = ino;
9399+ arg.found = 0;
9400+ do {
9401+ arg.called = 0;
9402+ /* smp_mb(); */
9403+ err = vfsub_readdir(file, find_name_by_ino, &arg);
9404+ } while (!err && !arg.found && arg.called);
9405+ dentry = ERR_PTR(err);
9406+ if (unlikely(err))
9407+ goto out_name;
9408+ dentry = ERR_PTR(-ENOENT);
9409+ if (!arg.found)
9410+ goto out_name;
9411+
b4510431 9412+ /* do not call vfsub_lkup_one() */
1facf9fc 9413+ dir = parent->d_inode;
9414+ mutex_lock(&dir->i_mutex);
9415+ dentry = vfsub_lookup_one_len(arg.name, parent, arg.namelen);
9416+ mutex_unlock(&dir->i_mutex);
9417+ AuTraceErrPtr(dentry);
9418+ if (IS_ERR(dentry))
9419+ goto out_name;
9420+ AuDebugOn(au_test_anon(dentry));
9421+ if (unlikely(!dentry->d_inode)) {
9422+ dput(dentry);
9423+ dentry = ERR_PTR(-ENOENT);
9424+ }
9425+
4f0767ce 9426+out_name:
537831f9 9427+ free_page((unsigned long)arg.name);
4f0767ce 9428+out_file:
1facf9fc 9429+ fput(file);
4f0767ce 9430+out:
1facf9fc 9431+ if (unlikely(nsi_lock
9432+ && si_nfsd_read_lock(parent->d_sb, nsi_lock) < 0))
9433+ if (!IS_ERR(dentry)) {
9434+ dput(dentry);
9435+ dentry = ERR_PTR(-ESTALE);
9436+ }
9437+ AuTraceErrPtr(dentry);
9438+ return dentry;
9439+}
9440+
9441+static struct dentry *decode_by_dir_ino(struct super_block *sb, ino_t ino,
9442+ ino_t dir_ino,
9443+ struct au_nfsd_si_lock *nsi_lock)
9444+{
9445+ struct dentry *dentry;
9446+ struct path path;
9447+
9448+ if (dir_ino != AUFS_ROOT_INO) {
9449+ path.dentry = decode_by_ino(sb, dir_ino, 0);
9450+ dentry = path.dentry;
9451+ if (!path.dentry || IS_ERR(path.dentry))
9452+ goto out;
9453+ AuDebugOn(au_test_anon(path.dentry));
9454+ } else
9455+ path.dentry = dget(sb->s_root);
9456+
9457+ path.mnt = au_mnt_get(sb);
9458+ dentry = au_lkup_by_ino(&path, ino, nsi_lock);
9459+ path_put(&path);
9460+
4f0767ce 9461+out:
1facf9fc 9462+ AuTraceErrPtr(dentry);
9463+ return dentry;
9464+}
9465+
9466+/* ---------------------------------------------------------------------- */
9467+
9468+static int h_acceptable(void *expv, struct dentry *dentry)
9469+{
9470+ return 1;
9471+}
9472+
9473+static char *au_build_path(struct dentry *h_parent, struct path *h_rootpath,
9474+ char *buf, int len, struct super_block *sb)
9475+{
9476+ char *p;
9477+ int n;
9478+ struct path path;
9479+
9480+ p = d_path(h_rootpath, buf, len);
9481+ if (IS_ERR(p))
9482+ goto out;
9483+ n = strlen(p);
9484+
9485+ path.mnt = h_rootpath->mnt;
9486+ path.dentry = h_parent;
9487+ p = d_path(&path, buf, len);
9488+ if (IS_ERR(p))
9489+ goto out;
9490+ if (n != 1)
9491+ p += n;
9492+
9493+ path.mnt = au_mnt_get(sb);
9494+ path.dentry = sb->s_root;
9495+ p = d_path(&path, buf, len - strlen(p));
9496+ mntput(path.mnt);
9497+ if (IS_ERR(p))
9498+ goto out;
9499+ if (n != 1)
9500+ p[strlen(p)] = '/';
9501+
4f0767ce 9502+out:
1facf9fc 9503+ AuTraceErrPtr(p);
9504+ return p;
9505+}
9506+
9507+static
027c5e7a
AM
9508+struct dentry *decode_by_path(struct super_block *sb, ino_t ino, __u32 *fh,
9509+ int fh_len, struct au_nfsd_si_lock *nsi_lock)
1facf9fc 9510+{
9511+ struct dentry *dentry, *h_parent, *root;
9512+ struct super_block *h_sb;
9513+ char *pathname, *p;
9514+ struct vfsmount *h_mnt;
9515+ struct au_branch *br;
9516+ int err;
9517+ struct path path;
9518+
027c5e7a 9519+ br = au_sbr(sb, nsi_lock->bindex);
1facf9fc 9520+ h_mnt = br->br_mnt;
9521+ h_sb = h_mnt->mnt_sb;
9522+ /* todo: call lower fh_to_dentry()? fh_to_parent()? */
9523+ h_parent = exportfs_decode_fh(h_mnt, (void *)(fh + Fh_tail),
9524+ fh_len - Fh_tail, fh[Fh_h_type],
9525+ h_acceptable, /*context*/NULL);
9526+ dentry = h_parent;
9527+ if (unlikely(!h_parent || IS_ERR(h_parent))) {
9528+ AuWarn1("%s decode_fh failed, %ld\n",
9529+ au_sbtype(h_sb), PTR_ERR(h_parent));
9530+ goto out;
9531+ }
9532+ dentry = NULL;
9533+ if (unlikely(au_test_anon(h_parent))) {
9534+ AuWarn1("%s decode_fh returned a disconnected dentry\n",
9535+ au_sbtype(h_sb));
9536+ goto out_h_parent;
9537+ }
9538+
9539+ dentry = ERR_PTR(-ENOMEM);
9540+ pathname = (void *)__get_free_page(GFP_NOFS);
9541+ if (unlikely(!pathname))
9542+ goto out_h_parent;
9543+
9544+ root = sb->s_root;
9545+ path.mnt = h_mnt;
9546+ di_read_lock_parent(root, !AuLock_IR);
027c5e7a 9547+ path.dentry = au_h_dptr(root, nsi_lock->bindex);
1facf9fc 9548+ di_read_unlock(root, !AuLock_IR);
9549+ p = au_build_path(h_parent, &path, pathname, PAGE_SIZE, sb);
9550+ dentry = (void *)p;
9551+ if (IS_ERR(p))
9552+ goto out_pathname;
9553+
9554+ si_read_unlock(sb);
9555+ err = vfsub_kern_path(p, LOOKUP_FOLLOW | LOOKUP_DIRECTORY, &path);
9556+ dentry = ERR_PTR(err);
9557+ if (unlikely(err))
9558+ goto out_relock;
9559+
9560+ dentry = ERR_PTR(-ENOENT);
9561+ AuDebugOn(au_test_anon(path.dentry));
9562+ if (unlikely(!path.dentry->d_inode))
9563+ goto out_path;
9564+
9565+ if (ino != path.dentry->d_inode->i_ino)
9566+ dentry = au_lkup_by_ino(&path, ino, /*nsi_lock*/NULL);
9567+ else
9568+ dentry = dget(path.dentry);
9569+
4f0767ce 9570+out_path:
1facf9fc 9571+ path_put(&path);
4f0767ce 9572+out_relock:
1facf9fc 9573+ if (unlikely(si_nfsd_read_lock(sb, nsi_lock) < 0))
9574+ if (!IS_ERR(dentry)) {
9575+ dput(dentry);
9576+ dentry = ERR_PTR(-ESTALE);
9577+ }
4f0767ce 9578+out_pathname:
1facf9fc 9579+ free_page((unsigned long)pathname);
4f0767ce 9580+out_h_parent:
1facf9fc 9581+ dput(h_parent);
4f0767ce 9582+out:
1facf9fc 9583+ AuTraceErrPtr(dentry);
9584+ return dentry;
9585+}
9586+
9587+/* ---------------------------------------------------------------------- */
9588+
9589+static struct dentry *
9590+aufs_fh_to_dentry(struct super_block *sb, struct fid *fid, int fh_len,
9591+ int fh_type)
9592+{
9593+ struct dentry *dentry;
9594+ __u32 *fh = fid->raw;
027c5e7a 9595+ struct au_branch *br;
1facf9fc 9596+ ino_t ino, dir_ino;
1facf9fc 9597+ struct au_nfsd_si_lock nsi_lock = {
1facf9fc 9598+ .force_lock = 0
9599+ };
9600+
1facf9fc 9601+ dentry = ERR_PTR(-ESTALE);
4a4d8108
AM
9602+ /* it should never happen, but the file handle is unreliable */
9603+ if (unlikely(fh_len < Fh_tail))
9604+ goto out;
9605+ nsi_lock.sigen = fh[Fh_sigen];
9606+ nsi_lock.br_id = fh[Fh_br_id];
9607+
1facf9fc 9608+ /* branch id may be wrapped around */
027c5e7a
AM
9609+ br = NULL;
9610+ if (unlikely(si_nfsd_read_lock(sb, &nsi_lock)))
1facf9fc 9611+ goto out;
9612+ nsi_lock.force_lock = 1;
9613+
9614+ /* is this inode still cached? */
9615+ ino = decode_ino(fh + Fh_ino);
4a4d8108
AM
9616+ /* it should never happen */
9617+ if (unlikely(ino == AUFS_ROOT_INO))
9618+ goto out;
9619+
1facf9fc 9620+ dir_ino = decode_ino(fh + Fh_dir_ino);
9621+ dentry = decode_by_ino(sb, ino, dir_ino);
9622+ if (IS_ERR(dentry))
9623+ goto out_unlock;
9624+ if (dentry)
9625+ goto accept;
9626+
9627+ /* is the parent dir cached? */
027c5e7a
AM
9628+ br = au_sbr(sb, nsi_lock.bindex);
9629+ atomic_inc(&br->br_count);
1facf9fc 9630+ dentry = decode_by_dir_ino(sb, ino, dir_ino, &nsi_lock);
9631+ if (IS_ERR(dentry))
9632+ goto out_unlock;
9633+ if (dentry)
9634+ goto accept;
9635+
9636+ /* lookup path */
027c5e7a 9637+ dentry = decode_by_path(sb, ino, fh, fh_len, &nsi_lock);
1facf9fc 9638+ if (IS_ERR(dentry))
9639+ goto out_unlock;
9640+ if (unlikely(!dentry))
9641+ /* todo?: make it ESTALE */
9642+ goto out_unlock;
9643+
4f0767ce 9644+accept:
027c5e7a
AM
9645+ if (!au_digen_test(dentry, au_sigen(sb))
9646+ && dentry->d_inode->i_generation == fh[Fh_igen])
1facf9fc 9647+ goto out_unlock; /* success */
9648+
9649+ dput(dentry);
9650+ dentry = ERR_PTR(-ESTALE);
4f0767ce 9651+out_unlock:
027c5e7a
AM
9652+ if (br)
9653+ atomic_dec(&br->br_count);
1facf9fc 9654+ si_read_unlock(sb);
4f0767ce 9655+out:
1facf9fc 9656+ AuTraceErrPtr(dentry);
9657+ return dentry;
9658+}
9659+
9660+#if 0 /* reserved for future use */
9661+/* support subtreecheck option */
9662+static struct dentry *aufs_fh_to_parent(struct super_block *sb, struct fid *fid,
9663+ int fh_len, int fh_type)
9664+{
9665+ struct dentry *parent;
9666+ __u32 *fh = fid->raw;
9667+ ino_t dir_ino;
9668+
9669+ dir_ino = decode_ino(fh + Fh_dir_ino);
9670+ parent = decode_by_ino(sb, dir_ino, 0);
9671+ if (IS_ERR(parent))
9672+ goto out;
9673+ if (!parent)
9674+ parent = decode_by_path(sb, au_br_index(sb, fh[Fh_br_id]),
9675+ dir_ino, fh, fh_len);
9676+
4f0767ce 9677+out:
1facf9fc 9678+ AuTraceErrPtr(parent);
9679+ return parent;
9680+}
9681+#endif
9682+
9683+/* ---------------------------------------------------------------------- */
9684+
0c3ec466
AM
9685+static int aufs_encode_fh(struct inode *inode, __u32 *fh, int *max_len,
9686+ struct inode *dir)
1facf9fc 9687+{
9688+ int err;
0c3ec466 9689+ aufs_bindex_t bindex;
1facf9fc 9690+ struct super_block *sb, *h_sb;
0c3ec466
AM
9691+ struct dentry *dentry, *parent, *h_parent;
9692+ struct inode *h_dir;
1facf9fc 9693+ struct au_branch *br;
9694+
1facf9fc 9695+ err = -ENOSPC;
9696+ if (unlikely(*max_len <= Fh_tail)) {
9697+ AuWarn1("NFSv2 client (max_len %d)?\n", *max_len);
9698+ goto out;
9699+ }
9700+
9701+ err = FILEID_ROOT;
0c3ec466
AM
9702+ if (inode->i_ino == AUFS_ROOT_INO) {
9703+ AuDebugOn(inode->i_ino != AUFS_ROOT_INO);
1facf9fc 9704+ goto out;
9705+ }
9706+
1facf9fc 9707+ h_parent = NULL;
0c3ec466
AM
9708+ sb = inode->i_sb;
9709+ err = si_read_lock(sb, AuLock_FLUSH);
027c5e7a
AM
9710+ if (unlikely(err))
9711+ goto out;
9712+
1facf9fc 9713+#ifdef CONFIG_AUFS_DEBUG
9714+ if (unlikely(!au_opt_test(au_mntflags(sb), XINO)))
9715+ AuWarn1("NFS-exporting requires xino\n");
9716+#endif
027c5e7a 9717+ err = -EIO;
0c3ec466
AM
9718+ parent = NULL;
9719+ ii_read_lock_child(inode);
9720+ bindex = au_ibstart(inode);
9721+ if (!dir) {
9722+ dentry = d_find_alias(inode);
9723+ if (unlikely(!dentry))
9724+ goto out_unlock;
9725+ AuDebugOn(au_test_anon(dentry));
9726+ parent = dget_parent(dentry);
9727+ dput(dentry);
9728+ if (unlikely(!parent))
9729+ goto out_unlock;
9730+ dir = parent->d_inode;
1facf9fc 9731+ }
0c3ec466
AM
9732+
9733+ ii_read_lock_parent(dir);
9734+ h_dir = au_h_iptr(dir, bindex);
9735+ ii_read_unlock(dir);
9736+ if (unlikely(!h_dir))
9737+ goto out_parent;
9738+ h_parent = d_find_alias(h_dir);
1facf9fc 9739+ if (unlikely(!h_parent))
0c3ec466 9740+ goto out_hparent;
1facf9fc 9741+
9742+ err = -EPERM;
9743+ br = au_sbr(sb, bindex);
9744+ h_sb = br->br_mnt->mnt_sb;
9745+ if (unlikely(!h_sb->s_export_op)) {
9746+ AuErr1("%s branch is not exportable\n", au_sbtype(h_sb));
0c3ec466 9747+ goto out_hparent;
1facf9fc 9748+ }
9749+
9750+ fh[Fh_br_id] = br->br_id;
9751+ fh[Fh_sigen] = au_sigen(sb);
9752+ encode_ino(fh + Fh_ino, inode->i_ino);
0c3ec466 9753+ encode_ino(fh + Fh_dir_ino, dir->i_ino);
1facf9fc 9754+ fh[Fh_igen] = inode->i_generation;
9755+
9756+ *max_len -= Fh_tail;
9757+ fh[Fh_h_type] = exportfs_encode_fh(h_parent, (void *)(fh + Fh_tail),
9758+ max_len,
9759+ /*connectable or subtreecheck*/0);
9760+ err = fh[Fh_h_type];
9761+ *max_len += Fh_tail;
9762+ /* todo: macros? */
9763+ if (err != 255)
9764+ err = 99;
9765+ else
9766+ AuWarn1("%s encode_fh failed\n", au_sbtype(h_sb));
9767+
0c3ec466 9768+out_hparent:
1facf9fc 9769+ dput(h_parent);
0c3ec466 9770+out_parent:
1facf9fc 9771+ dput(parent);
0c3ec466
AM
9772+out_unlock:
9773+ ii_read_unlock(inode);
9774+ si_read_unlock(sb);
4f0767ce 9775+out:
1facf9fc 9776+ if (unlikely(err < 0))
9777+ err = 255;
9778+ return err;
9779+}
9780+
9781+/* ---------------------------------------------------------------------- */
9782+
4a4d8108
AM
9783+static int aufs_commit_metadata(struct inode *inode)
9784+{
9785+ int err;
9786+ aufs_bindex_t bindex;
9787+ struct super_block *sb;
9788+ struct inode *h_inode;
9789+ int (*f)(struct inode *inode);
9790+
9791+ sb = inode->i_sb;
e49829fe 9792+ si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLMW);
4a4d8108
AM
9793+ ii_write_lock_child(inode);
9794+ bindex = au_ibstart(inode);
9795+ AuDebugOn(bindex < 0);
9796+ h_inode = au_h_iptr(inode, bindex);
9797+
9798+ f = h_inode->i_sb->s_export_op->commit_metadata;
9799+ if (f)
9800+ err = f(h_inode);
9801+ else {
9802+ struct writeback_control wbc = {
9803+ .sync_mode = WB_SYNC_ALL,
9804+ .nr_to_write = 0 /* metadata only */
9805+ };
9806+
9807+ err = sync_inode(h_inode, &wbc);
9808+ }
9809+
9810+ au_cpup_attr_timesizes(inode);
9811+ ii_write_unlock(inode);
9812+ si_read_unlock(sb);
9813+ return err;
9814+}
9815+
9816+/* ---------------------------------------------------------------------- */
9817+
1facf9fc 9818+static struct export_operations aufs_export_op = {
4a4d8108 9819+ .fh_to_dentry = aufs_fh_to_dentry,
1facf9fc 9820+ /* .fh_to_parent = aufs_fh_to_parent, */
4a4d8108
AM
9821+ .encode_fh = aufs_encode_fh,
9822+ .commit_metadata = aufs_commit_metadata
1facf9fc 9823+};
9824+
9825+void au_export_init(struct super_block *sb)
9826+{
9827+ struct au_sbinfo *sbinfo;
9828+ __u32 u;
9829+
9830+ sb->s_export_op = &aufs_export_op;
9831+ sbinfo = au_sbi(sb);
9832+ sbinfo->si_xigen = NULL;
9833+ get_random_bytes(&u, sizeof(u));
9834+ BUILD_BUG_ON(sizeof(u) != sizeof(int));
9835+ atomic_set(&sbinfo->si_xigen_next, u);
9836+}
7f207e10
AM
9837diff -urN /usr/share/empty/fs/aufs/file.c linux/fs/aufs/file.c
9838--- /usr/share/empty/fs/aufs/file.c 1970-01-01 01:00:00.000000000 +0100
537831f9 9839+++ linux/fs/aufs/file.c 2012-12-13 20:41:10.431460173 +0100
b4510431 9840@@ -0,0 +1,683 @@
1facf9fc 9841+/*
f6c5ef8b 9842+ * Copyright (C) 2005-2012 Junjiro R. Okajima
1facf9fc 9843+ *
9844+ * This program, aufs is free software; you can redistribute it and/or modify
9845+ * it under the terms of the GNU General Public License as published by
9846+ * the Free Software Foundation; either version 2 of the License, or
9847+ * (at your option) any later version.
dece6358
AM
9848+ *
9849+ * This program is distributed in the hope that it will be useful,
9850+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
9851+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
9852+ * GNU General Public License for more details.
9853+ *
9854+ * You should have received a copy of the GNU General Public License
9855+ * along with this program; if not, write to the Free Software
9856+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 9857+ */
9858+
9859+/*
4a4d8108 9860+ * handling file/dir, and address_space operation
1facf9fc 9861+ */
9862+
7eafdf33
AM
9863+#ifdef CONFIG_AUFS_DEBUG
9864+#include <linux/migrate.h>
9865+#endif
4a4d8108 9866+#include <linux/pagemap.h>
1facf9fc 9867+#include "aufs.h"
9868+
4a4d8108
AM
9869+/* drop flags for writing */
9870+unsigned int au_file_roflags(unsigned int flags)
9871+{
9872+ flags &= ~(O_WRONLY | O_RDWR | O_APPEND | O_CREAT | O_TRUNC);
9873+ flags |= O_RDONLY | O_NOATIME;
9874+ return flags;
9875+}
9876+
9877+/* common functions to regular file and dir */
9878+struct file *au_h_open(struct dentry *dentry, aufs_bindex_t bindex, int flags,
9879+ struct file *file)
1facf9fc 9880+{
1308ab2a 9881+ struct file *h_file;
4a4d8108
AM
9882+ struct dentry *h_dentry;
9883+ struct inode *h_inode;
9884+ struct super_block *sb;
9885+ struct au_branch *br;
9886+ struct path h_path;
9887+ int err, exec_flag;
1facf9fc 9888+
4a4d8108
AM
9889+ /* a race condition can happen between open and unlink/rmdir */
9890+ h_file = ERR_PTR(-ENOENT);
9891+ h_dentry = au_h_dptr(dentry, bindex);
b752ccd1 9892+ if (au_test_nfsd() && !h_dentry)
4a4d8108
AM
9893+ goto out;
9894+ h_inode = h_dentry->d_inode;
b752ccd1 9895+ if (au_test_nfsd() && !h_inode)
4a4d8108 9896+ goto out;
027c5e7a
AM
9897+ spin_lock(&h_dentry->d_lock);
9898+ err = (!d_unhashed(dentry) && d_unlinked(h_dentry))
9899+ || !h_inode
9900+ /* || !dentry->d_inode->i_nlink */
9901+ ;
9902+ spin_unlock(&h_dentry->d_lock);
9903+ if (unlikely(err))
4a4d8108 9904+ goto out;
1facf9fc 9905+
4a4d8108
AM
9906+ sb = dentry->d_sb;
9907+ br = au_sbr(sb, bindex);
9908+ h_file = ERR_PTR(-EACCES);
2cbb1c4b 9909+ exec_flag = flags & __FMODE_EXEC;
4a4d8108 9910+ if (exec_flag && (br->br_mnt->mnt_flags & MNT_NOEXEC))
027c5e7a 9911+ goto out;
1facf9fc 9912+
4a4d8108
AM
9913+ /* drop flags for writing */
9914+ if (au_test_ro(sb, bindex, dentry->d_inode))
9915+ flags = au_file_roflags(flags);
9916+ flags &= ~O_CREAT;
9917+ atomic_inc(&br->br_count);
9918+ h_path.dentry = h_dentry;
9919+ h_path.mnt = br->br_mnt;
9920+ if (!au_special_file(h_inode->i_mode))
9921+ h_file = vfsub_dentry_open(&h_path, flags);
9922+ else {
9923+ /* this block depends upon the configuration */
9924+ di_read_unlock(dentry, AuLock_IR);
9925+ fi_write_unlock(file);
9926+ si_read_unlock(sb);
9927+ h_file = vfsub_dentry_open(&h_path, flags);
9928+ si_noflush_read_lock(sb);
9929+ fi_write_lock(file);
9930+ di_read_lock_child(dentry, AuLock_IR);
dece6358 9931+ }
4a4d8108
AM
9932+ if (IS_ERR(h_file))
9933+ goto out_br;
dece6358 9934+
4a4d8108
AM
9935+ if (exec_flag) {
9936+ err = deny_write_access(h_file);
9937+ if (unlikely(err)) {
9938+ fput(h_file);
9939+ h_file = ERR_PTR(err);
9940+ goto out_br;
9941+ }
9942+ }
953406b4 9943+ fsnotify_open(h_file);
4a4d8108 9944+ goto out; /* success */
1facf9fc 9945+
4f0767ce 9946+out_br:
4a4d8108 9947+ atomic_dec(&br->br_count);
4f0767ce 9948+out:
4a4d8108
AM
9949+ return h_file;
9950+}
1308ab2a 9951+
4a4d8108
AM
9952+int au_do_open(struct file *file, int (*open)(struct file *file, int flags),
9953+ struct au_fidir *fidir)
1facf9fc 9954+{
dece6358 9955+ int err;
1facf9fc 9956+ struct dentry *dentry;
1308ab2a 9957+
4a4d8108
AM
9958+ err = au_finfo_init(file, fidir);
9959+ if (unlikely(err))
9960+ goto out;
1facf9fc 9961+
9962+ dentry = file->f_dentry;
4a4d8108
AM
9963+ di_read_lock_child(dentry, AuLock_IR);
9964+ err = open(file, vfsub_file_flags(file));
9965+ di_read_unlock(dentry, AuLock_IR);
1facf9fc 9966+
4a4d8108
AM
9967+ fi_write_unlock(file);
9968+ if (unlikely(err)) {
9969+ au_fi(file)->fi_hdir = NULL;
9970+ au_finfo_fin(file);
1308ab2a 9971+ }
4a4d8108 9972+
4f0767ce 9973+out:
1308ab2a 9974+ return err;
9975+}
dece6358 9976+
4a4d8108 9977+int au_reopen_nondir(struct file *file)
1308ab2a 9978+{
4a4d8108
AM
9979+ int err;
9980+ aufs_bindex_t bstart;
9981+ struct dentry *dentry;
9982+ struct file *h_file, *h_file_tmp;
1308ab2a 9983+
4a4d8108
AM
9984+ dentry = file->f_dentry;
9985+ AuDebugOn(au_special_file(dentry->d_inode->i_mode));
9986+ bstart = au_dbstart(dentry);
9987+ h_file_tmp = NULL;
9988+ if (au_fbstart(file) == bstart) {
9989+ h_file = au_hf_top(file);
9990+ if (file->f_mode == h_file->f_mode)
9991+ return 0; /* success */
9992+ h_file_tmp = h_file;
9993+ get_file(h_file_tmp);
9994+ au_set_h_fptr(file, bstart, NULL);
9995+ }
9996+ AuDebugOn(au_fi(file)->fi_hdir);
9997+ AuDebugOn(au_fbstart(file) < bstart);
1308ab2a 9998+
4a4d8108
AM
9999+ h_file = au_h_open(dentry, bstart, vfsub_file_flags(file) & ~O_TRUNC,
10000+ file);
10001+ err = PTR_ERR(h_file);
10002+ if (IS_ERR(h_file))
10003+ goto out; /* todo: close all? */
10004+
10005+ err = 0;
10006+ au_set_fbstart(file, bstart);
10007+ au_set_h_fptr(file, bstart, h_file);
10008+ au_update_figen(file);
10009+ /* todo: necessary? */
10010+ /* file->f_ra = h_file->f_ra; */
10011+
4f0767ce 10012+out:
4a4d8108
AM
10013+ if (h_file_tmp)
10014+ fput(h_file_tmp);
10015+ return err;
1facf9fc 10016+}
10017+
1308ab2a 10018+/* ---------------------------------------------------------------------- */
10019+
4a4d8108
AM
10020+static int au_reopen_wh(struct file *file, aufs_bindex_t btgt,
10021+ struct dentry *hi_wh)
1facf9fc 10022+{
4a4d8108
AM
10023+ int err;
10024+ aufs_bindex_t bstart;
10025+ struct au_dinfo *dinfo;
10026+ struct dentry *h_dentry;
10027+ struct au_hdentry *hdp;
1facf9fc 10028+
4a4d8108
AM
10029+ dinfo = au_di(file->f_dentry);
10030+ AuRwMustWriteLock(&dinfo->di_rwsem);
dece6358 10031+
4a4d8108
AM
10032+ bstart = dinfo->di_bstart;
10033+ dinfo->di_bstart = btgt;
10034+ hdp = dinfo->di_hdentry;
10035+ h_dentry = hdp[0 + btgt].hd_dentry;
10036+ hdp[0 + btgt].hd_dentry = hi_wh;
10037+ err = au_reopen_nondir(file);
10038+ hdp[0 + btgt].hd_dentry = h_dentry;
10039+ dinfo->di_bstart = bstart;
1facf9fc 10040+
1facf9fc 10041+ return err;
10042+}
10043+
4a4d8108
AM
10044+static int au_ready_to_write_wh(struct file *file, loff_t len,
10045+ aufs_bindex_t bcpup)
1facf9fc 10046+{
4a4d8108 10047+ int err;
027c5e7a
AM
10048+ struct inode *inode, *h_inode;
10049+ struct dentry *dentry, *h_dentry, *hi_wh;
1facf9fc 10050+
dece6358 10051+ dentry = file->f_dentry;
4a4d8108 10052+ au_update_dbstart(dentry);
dece6358 10053+ inode = dentry->d_inode;
027c5e7a
AM
10054+ h_inode = NULL;
10055+ if (au_dbstart(dentry) <= bcpup && au_dbend(dentry) >= bcpup) {
10056+ h_dentry = au_h_dptr(dentry, bcpup);
10057+ if (h_dentry)
10058+ h_inode = h_dentry->d_inode;
10059+ }
4a4d8108 10060+ hi_wh = au_hi_wh(inode, bcpup);
027c5e7a 10061+ if (!hi_wh && !h_inode)
4a4d8108
AM
10062+ err = au_sio_cpup_wh(dentry, bcpup, len, file);
10063+ else
10064+ /* already copied-up after unlink */
10065+ err = au_reopen_wh(file, bcpup, hi_wh);
1facf9fc 10066+
4a4d8108
AM
10067+ if (!err
10068+ && inode->i_nlink > 1
10069+ && au_opt_test(au_mntflags(dentry->d_sb), PLINK))
10070+ au_plink_append(inode, bcpup, au_h_dptr(dentry, bcpup));
1308ab2a 10071+
dece6358 10072+ return err;
1facf9fc 10073+}
10074+
4a4d8108
AM
10075+/*
10076+ * prepare the @file for writing.
10077+ */
10078+int au_ready_to_write(struct file *file, loff_t len, struct au_pin *pin)
1facf9fc 10079+{
4a4d8108 10080+ int err;
027c5e7a 10081+ aufs_bindex_t bstart, bcpup, dbstart;
4a4d8108
AM
10082+ struct dentry *dentry, *parent, *h_dentry;
10083+ struct inode *h_inode, *inode;
1facf9fc 10084+ struct super_block *sb;
4a4d8108 10085+ struct file *h_file;
1facf9fc 10086+
10087+ dentry = file->f_dentry;
1facf9fc 10088+ sb = dentry->d_sb;
4a4d8108
AM
10089+ inode = dentry->d_inode;
10090+ AuDebugOn(au_special_file(inode->i_mode));
10091+ bstart = au_fbstart(file);
10092+ err = au_test_ro(sb, bstart, inode);
10093+ if (!err && (au_hf_top(file)->f_mode & FMODE_WRITE)) {
10094+ err = au_pin(pin, dentry, bstart, AuOpt_UDBA_NONE, /*flags*/0);
1facf9fc 10095+ goto out;
4a4d8108 10096+ }
1facf9fc 10097+
027c5e7a 10098+ /* need to cpup or reopen */
4a4d8108
AM
10099+ parent = dget_parent(dentry);
10100+ di_write_lock_parent(parent);
10101+ err = AuWbrCopyup(au_sbi(sb), dentry);
10102+ bcpup = err;
10103+ if (unlikely(err < 0))
10104+ goto out_dgrade;
10105+ err = 0;
10106+
027c5e7a 10107+ if (!d_unhashed(dentry) && !au_h_dptr(parent, bcpup)) {
4a4d8108 10108+ err = au_cpup_dirs(dentry, bcpup);
1facf9fc 10109+ if (unlikely(err))
4a4d8108
AM
10110+ goto out_dgrade;
10111+ }
10112+
10113+ err = au_pin(pin, dentry, bcpup, AuOpt_UDBA_NONE,
10114+ AuPin_DI_LOCKED | AuPin_MNT_WRITE);
10115+ if (unlikely(err))
10116+ goto out_dgrade;
10117+
10118+ h_dentry = au_hf_top(file)->f_dentry;
10119+ h_inode = h_dentry->d_inode;
027c5e7a
AM
10120+ dbstart = au_dbstart(dentry);
10121+ if (dbstart <= bcpup) {
10122+ h_dentry = au_h_dptr(dentry, bcpup);
10123+ AuDebugOn(!h_dentry);
10124+ h_inode = h_dentry->d_inode;
10125+ AuDebugOn(!h_inode);
10126+ bstart = bcpup;
10127+ }
10128+
10129+ if (dbstart <= bcpup /* just reopen */
10130+ || !d_unhashed(dentry) /* copyup and reopen */
10131+ ) {
10132+ mutex_lock_nested(&h_inode->i_mutex, AuLsc_I_CHILD);
10133+ h_file = au_h_open_pre(dentry, bstart);
10134+ if (IS_ERR(h_file)) {
10135+ err = PTR_ERR(h_file);
10136+ h_file = NULL;
10137+ } else {
10138+ di_downgrade_lock(parent, AuLock_IR);
10139+ if (dbstart > bcpup)
10140+ err = au_sio_cpup_simple(dentry, bcpup, len,
10141+ AuCpup_DTIME);
10142+ if (!err)
10143+ err = au_reopen_nondir(file);
10144+ }
10145+ mutex_unlock(&h_inode->i_mutex);
10146+ au_h_open_post(dentry, bstart, h_file);
10147+ } else { /* copyup as wh and reopen */
10148+ /*
10149+ * since writable hfsplus branch is not supported,
10150+ * h_open_pre/post() are unnecessary.
10151+ */
10152+ mutex_lock_nested(&h_inode->i_mutex, AuLsc_I_CHILD);
4a4d8108
AM
10153+ err = au_ready_to_write_wh(file, len, bcpup);
10154+ di_downgrade_lock(parent, AuLock_IR);
027c5e7a 10155+ mutex_unlock(&h_inode->i_mutex);
4a4d8108 10156+ }
4a4d8108
AM
10157+
10158+ if (!err) {
10159+ au_pin_set_parent_lflag(pin, /*lflag*/0);
10160+ goto out_dput; /* success */
10161+ }
10162+ au_unpin(pin);
10163+ goto out_unlock;
1facf9fc 10164+
4f0767ce 10165+out_dgrade:
4a4d8108 10166+ di_downgrade_lock(parent, AuLock_IR);
4f0767ce 10167+out_unlock:
4a4d8108 10168+ di_read_unlock(parent, AuLock_IR);
4f0767ce 10169+out_dput:
4a4d8108 10170+ dput(parent);
4f0767ce 10171+out:
1facf9fc 10172+ return err;
10173+}
10174+
4a4d8108
AM
10175+/* ---------------------------------------------------------------------- */
10176+
10177+int au_do_flush(struct file *file, fl_owner_t id,
10178+ int (*flush)(struct file *file, fl_owner_t id))
1facf9fc 10179+{
4a4d8108 10180+ int err;
1308ab2a 10181+ struct dentry *dentry;
1facf9fc 10182+ struct super_block *sb;
4a4d8108 10183+ struct inode *inode;
1facf9fc 10184+
1facf9fc 10185+ dentry = file->f_dentry;
10186+ sb = dentry->d_sb;
dece6358 10187+ inode = dentry->d_inode;
4a4d8108
AM
10188+ si_noflush_read_lock(sb);
10189+ fi_read_lock(file);
b752ccd1 10190+ ii_read_lock_child(inode);
1facf9fc 10191+
4a4d8108
AM
10192+ err = flush(file, id);
10193+ au_cpup_attr_timesizes(inode);
1facf9fc 10194+
b752ccd1 10195+ ii_read_unlock(inode);
4a4d8108 10196+ fi_read_unlock(file);
1308ab2a 10197+ si_read_unlock(sb);
dece6358 10198+ return err;
1facf9fc 10199+}
10200+
4a4d8108
AM
10201+/* ---------------------------------------------------------------------- */
10202+
10203+static int au_file_refresh_by_inode(struct file *file, int *need_reopen)
1facf9fc 10204+{
4a4d8108
AM
10205+ int err;
10206+ aufs_bindex_t bstart;
10207+ struct au_pin pin;
10208+ struct au_finfo *finfo;
10209+ struct dentry *dentry, *parent, *hi_wh;
10210+ struct inode *inode;
1facf9fc 10211+ struct super_block *sb;
10212+
4a4d8108
AM
10213+ FiMustWriteLock(file);
10214+
10215+ err = 0;
10216+ finfo = au_fi(file);
1308ab2a 10217+ dentry = file->f_dentry;
10218+ sb = dentry->d_sb;
4a4d8108
AM
10219+ inode = dentry->d_inode;
10220+ bstart = au_ibstart(inode);
027c5e7a 10221+ if (bstart == finfo->fi_btop || IS_ROOT(dentry))
1308ab2a 10222+ goto out;
dece6358 10223+
4a4d8108
AM
10224+ parent = dget_parent(dentry);
10225+ if (au_test_ro(sb, bstart, inode)) {
10226+ di_read_lock_parent(parent, !AuLock_IR);
10227+ err = AuWbrCopyup(au_sbi(sb), dentry);
10228+ bstart = err;
10229+ di_read_unlock(parent, !AuLock_IR);
10230+ if (unlikely(err < 0))
10231+ goto out_parent;
10232+ err = 0;
1facf9fc 10233+ }
1facf9fc 10234+
4a4d8108
AM
10235+ di_read_lock_parent(parent, AuLock_IR);
10236+ hi_wh = au_hi_wh(inode, bstart);
7f207e10
AM
10237+ if (!S_ISDIR(inode->i_mode)
10238+ && au_opt_test(au_mntflags(sb), PLINK)
4a4d8108
AM
10239+ && au_plink_test(inode)
10240+ && !d_unhashed(dentry)) {
10241+ err = au_test_and_cpup_dirs(dentry, bstart);
10242+ if (unlikely(err))
10243+ goto out_unlock;
10244+
10245+ /* always superio. */
10246+ err = au_pin(&pin, dentry, bstart, AuOpt_UDBA_NONE,
10247+ AuPin_DI_LOCKED | AuPin_MNT_WRITE);
10248+ if (!err)
10249+ err = au_sio_cpup_simple(dentry, bstart, -1,
10250+ AuCpup_DTIME);
10251+ au_unpin(&pin);
10252+ } else if (hi_wh) {
10253+ /* already copied-up after unlink */
10254+ err = au_reopen_wh(file, bstart, hi_wh);
10255+ *need_reopen = 0;
10256+ }
1facf9fc 10257+
4f0767ce 10258+out_unlock:
4a4d8108 10259+ di_read_unlock(parent, AuLock_IR);
4f0767ce 10260+out_parent:
4a4d8108 10261+ dput(parent);
4f0767ce 10262+out:
1308ab2a 10263+ return err;
dece6358 10264+}
1facf9fc 10265+
4a4d8108 10266+static void au_do_refresh_dir(struct file *file)
dece6358 10267+{
4a4d8108
AM
10268+ aufs_bindex_t bindex, bend, new_bindex, brid;
10269+ struct au_hfile *p, tmp, *q;
10270+ struct au_finfo *finfo;
1308ab2a 10271+ struct super_block *sb;
4a4d8108 10272+ struct au_fidir *fidir;
1facf9fc 10273+
4a4d8108 10274+ FiMustWriteLock(file);
1facf9fc 10275+
4a4d8108
AM
10276+ sb = file->f_dentry->d_sb;
10277+ finfo = au_fi(file);
10278+ fidir = finfo->fi_hdir;
10279+ AuDebugOn(!fidir);
10280+ p = fidir->fd_hfile + finfo->fi_btop;
10281+ brid = p->hf_br->br_id;
10282+ bend = fidir->fd_bbot;
10283+ for (bindex = finfo->fi_btop; bindex <= bend; bindex++, p++) {
10284+ if (!p->hf_file)
10285+ continue;
1308ab2a 10286+
4a4d8108
AM
10287+ new_bindex = au_br_index(sb, p->hf_br->br_id);
10288+ if (new_bindex == bindex)
10289+ continue;
10290+ if (new_bindex < 0) {
10291+ au_set_h_fptr(file, bindex, NULL);
10292+ continue;
10293+ }
1308ab2a 10294+
4a4d8108
AM
10295+ /* swap two lower inode, and loop again */
10296+ q = fidir->fd_hfile + new_bindex;
10297+ tmp = *q;
10298+ *q = *p;
10299+ *p = tmp;
10300+ if (tmp.hf_file) {
10301+ bindex--;
10302+ p--;
10303+ }
10304+ }
1308ab2a 10305+
4a4d8108 10306+ p = fidir->fd_hfile;
027c5e7a 10307+ if (!au_test_mmapped(file) && !d_unlinked(file->f_dentry)) {
4a4d8108
AM
10308+ bend = au_sbend(sb);
10309+ for (finfo->fi_btop = 0; finfo->fi_btop <= bend;
10310+ finfo->fi_btop++, p++)
10311+ if (p->hf_file) {
10312+ if (p->hf_file->f_dentry
10313+ && p->hf_file->f_dentry->d_inode)
10314+ break;
10315+ else
10316+ au_hfput(p, file);
10317+ }
10318+ } else {
10319+ bend = au_br_index(sb, brid);
10320+ for (finfo->fi_btop = 0; finfo->fi_btop < bend;
10321+ finfo->fi_btop++, p++)
10322+ if (p->hf_file)
10323+ au_hfput(p, file);
10324+ bend = au_sbend(sb);
10325+ }
1308ab2a 10326+
4a4d8108
AM
10327+ p = fidir->fd_hfile + bend;
10328+ for (fidir->fd_bbot = bend; fidir->fd_bbot >= finfo->fi_btop;
10329+ fidir->fd_bbot--, p--)
10330+ if (p->hf_file) {
10331+ if (p->hf_file->f_dentry
10332+ && p->hf_file->f_dentry->d_inode)
10333+ break;
10334+ else
10335+ au_hfput(p, file);
10336+ }
10337+ AuDebugOn(fidir->fd_bbot < finfo->fi_btop);
1308ab2a 10338+}
10339+
4a4d8108
AM
10340+/*
10341+ * after branch manipulating, refresh the file.
10342+ */
10343+static int refresh_file(struct file *file, int (*reopen)(struct file *file))
1facf9fc 10344+{
4a4d8108
AM
10345+ int err, need_reopen;
10346+ aufs_bindex_t bend, bindex;
10347+ struct dentry *dentry;
1308ab2a 10348+ struct au_finfo *finfo;
4a4d8108 10349+ struct au_hfile *hfile;
1facf9fc 10350+
4a4d8108 10351+ dentry = file->f_dentry;
1308ab2a 10352+ finfo = au_fi(file);
4a4d8108
AM
10353+ if (!finfo->fi_hdir) {
10354+ hfile = &finfo->fi_htop;
10355+ AuDebugOn(!hfile->hf_file);
10356+ bindex = au_br_index(dentry->d_sb, hfile->hf_br->br_id);
10357+ AuDebugOn(bindex < 0);
10358+ if (bindex != finfo->fi_btop)
10359+ au_set_fbstart(file, bindex);
10360+ } else {
10361+ err = au_fidir_realloc(finfo, au_sbend(dentry->d_sb) + 1);
10362+ if (unlikely(err))
10363+ goto out;
10364+ au_do_refresh_dir(file);
10365+ }
1facf9fc 10366+
4a4d8108
AM
10367+ err = 0;
10368+ need_reopen = 1;
10369+ if (!au_test_mmapped(file))
10370+ err = au_file_refresh_by_inode(file, &need_reopen);
027c5e7a 10371+ if (!err && need_reopen && !d_unlinked(dentry))
4a4d8108
AM
10372+ err = reopen(file);
10373+ if (!err) {
10374+ au_update_figen(file);
10375+ goto out; /* success */
10376+ }
10377+
10378+ /* error, close all lower files */
10379+ if (finfo->fi_hdir) {
10380+ bend = au_fbend_dir(file);
10381+ for (bindex = au_fbstart(file); bindex <= bend; bindex++)
10382+ au_set_h_fptr(file, bindex, NULL);
10383+ }
1facf9fc 10384+
4f0767ce 10385+out:
1facf9fc 10386+ return err;
10387+}
10388+
4a4d8108
AM
10389+/* common function to regular file and dir */
10390+int au_reval_and_lock_fdi(struct file *file, int (*reopen)(struct file *file),
10391+ int wlock)
dece6358 10392+{
1308ab2a 10393+ int err;
4a4d8108
AM
10394+ unsigned int sigen, figen;
10395+ aufs_bindex_t bstart;
10396+ unsigned char pseudo_link;
10397+ struct dentry *dentry;
10398+ struct inode *inode;
1facf9fc 10399+
4a4d8108
AM
10400+ err = 0;
10401+ dentry = file->f_dentry;
10402+ inode = dentry->d_inode;
10403+ AuDebugOn(au_special_file(inode->i_mode));
10404+ sigen = au_sigen(dentry->d_sb);
10405+ fi_write_lock(file);
10406+ figen = au_figen(file);
10407+ di_write_lock_child(dentry);
10408+ bstart = au_dbstart(dentry);
10409+ pseudo_link = (bstart != au_ibstart(inode));
10410+ if (sigen == figen && !pseudo_link && au_fbstart(file) == bstart) {
10411+ if (!wlock) {
10412+ di_downgrade_lock(dentry, AuLock_IR);
10413+ fi_downgrade_lock(file);
10414+ }
10415+ goto out; /* success */
10416+ }
dece6358 10417+
4a4d8108 10418+ AuDbg("sigen %d, figen %d\n", sigen, figen);
027c5e7a 10419+ if (au_digen_test(dentry, sigen)) {
4a4d8108 10420+ err = au_reval_dpath(dentry, sigen);
027c5e7a 10421+ AuDebugOn(!err && au_digen_test(dentry, sigen));
4a4d8108 10422+ }
dece6358 10423+
027c5e7a
AM
10424+ if (!err)
10425+ err = refresh_file(file, reopen);
4a4d8108
AM
10426+ if (!err) {
10427+ if (!wlock) {
10428+ di_downgrade_lock(dentry, AuLock_IR);
10429+ fi_downgrade_lock(file);
10430+ }
10431+ } else {
10432+ di_write_unlock(dentry);
10433+ fi_write_unlock(file);
10434+ }
1facf9fc 10435+
4f0767ce 10436+out:
1308ab2a 10437+ return err;
10438+}
1facf9fc 10439+
4a4d8108
AM
10440+/* ---------------------------------------------------------------------- */
10441+
10442+/* cf. aufs_nopage() */
10443+/* for madvise(2) */
10444+static int aufs_readpage(struct file *file __maybe_unused, struct page *page)
1308ab2a 10445+{
4a4d8108
AM
10446+ unlock_page(page);
10447+ return 0;
10448+}
1facf9fc 10449+
4a4d8108
AM
10450+/* it will never be called, but necessary to support O_DIRECT */
10451+static ssize_t aufs_direct_IO(int rw, struct kiocb *iocb,
10452+ const struct iovec *iov, loff_t offset,
10453+ unsigned long nr_segs)
10454+{ BUG(); return 0; }
1facf9fc 10455+
4a4d8108
AM
10456+/*
10457+ * it will never be called, but madvise and fadvise behaves differently
10458+ * when get_xip_mem is defined
10459+ */
10460+static int aufs_get_xip_mem(struct address_space *mapping, pgoff_t pgoff,
10461+ int create, void **kmem, unsigned long *pfn)
10462+{ BUG(); return 0; }
1facf9fc 10463+
4a4d8108
AM
10464+/* they will never be called. */
10465+#ifdef CONFIG_AUFS_DEBUG
10466+static int aufs_write_begin(struct file *file, struct address_space *mapping,
10467+ loff_t pos, unsigned len, unsigned flags,
10468+ struct page **pagep, void **fsdata)
10469+{ AuUnsupport(); return 0; }
10470+static int aufs_write_end(struct file *file, struct address_space *mapping,
10471+ loff_t pos, unsigned len, unsigned copied,
10472+ struct page *page, void *fsdata)
10473+{ AuUnsupport(); return 0; }
10474+static int aufs_writepage(struct page *page, struct writeback_control *wbc)
10475+{ AuUnsupport(); return 0; }
1308ab2a 10476+
4a4d8108
AM
10477+static int aufs_set_page_dirty(struct page *page)
10478+{ AuUnsupport(); return 0; }
10479+static void aufs_invalidatepage(struct page *page, unsigned long offset)
10480+{ AuUnsupport(); }
10481+static int aufs_releasepage(struct page *page, gfp_t gfp)
10482+{ AuUnsupport(); return 0; }
10483+static int aufs_migratepage(struct address_space *mapping, struct page *newpage,
7eafdf33 10484+ struct page *page, enum migrate_mode mode)
4a4d8108
AM
10485+{ AuUnsupport(); return 0; }
10486+static int aufs_launder_page(struct page *page)
10487+{ AuUnsupport(); return 0; }
10488+static int aufs_is_partially_uptodate(struct page *page,
10489+ read_descriptor_t *desc,
10490+ unsigned long from)
10491+{ AuUnsupport(); return 0; }
10492+static int aufs_error_remove_page(struct address_space *mapping,
10493+ struct page *page)
10494+{ AuUnsupport(); return 0; }
b4510431
AM
10495+static int aufs_swap_activate(struct swap_info_struct *sis, struct file *file,
10496+ sector_t *span)
10497+{ AuUnsupport(); return 0; }
10498+static void aufs_swap_deactivate(struct file *file)
10499+{ AuUnsupport(); }
4a4d8108
AM
10500+#endif /* CONFIG_AUFS_DEBUG */
10501+
10502+const struct address_space_operations aufs_aop = {
10503+ .readpage = aufs_readpage,
10504+ .direct_IO = aufs_direct_IO,
10505+ .get_xip_mem = aufs_get_xip_mem,
10506+#ifdef CONFIG_AUFS_DEBUG
10507+ .writepage = aufs_writepage,
4a4d8108
AM
10508+ /* no writepages, because of writepage */
10509+ .set_page_dirty = aufs_set_page_dirty,
10510+ /* no readpages, because of readpage */
10511+ .write_begin = aufs_write_begin,
10512+ .write_end = aufs_write_end,
10513+ /* no bmap, no block device */
10514+ .invalidatepage = aufs_invalidatepage,
10515+ .releasepage = aufs_releasepage,
10516+ .migratepage = aufs_migratepage,
10517+ .launder_page = aufs_launder_page,
10518+ .is_partially_uptodate = aufs_is_partially_uptodate,
b4510431
AM
10519+ .error_remove_page = aufs_error_remove_page,
10520+ .swap_activate = aufs_swap_activate,
10521+ .swap_deactivate = aufs_swap_deactivate
4a4d8108 10522+#endif /* CONFIG_AUFS_DEBUG */
dece6358 10523+};
7f207e10
AM
10524diff -urN /usr/share/empty/fs/aufs/file.h linux/fs/aufs/file.h
10525--- /usr/share/empty/fs/aufs/file.h 1970-01-01 01:00:00.000000000 +0100
537831f9 10526+++ linux/fs/aufs/file.h 2012-12-13 20:41:10.431460173 +0100
2dfbb274 10527@@ -0,0 +1,298 @@
4a4d8108 10528+/*
f6c5ef8b 10529+ * Copyright (C) 2005-2012 Junjiro R. Okajima
4a4d8108
AM
10530+ *
10531+ * This program, aufs is free software; you can redistribute it and/or modify
10532+ * it under the terms of the GNU General Public License as published by
10533+ * the Free Software Foundation; either version 2 of the License, or
10534+ * (at your option) any later version.
10535+ *
10536+ * This program is distributed in the hope that it will be useful,
10537+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
10538+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10539+ * GNU General Public License for more details.
10540+ *
10541+ * You should have received a copy of the GNU General Public License
10542+ * along with this program; if not, write to the Free Software
10543+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
10544+ */
1facf9fc 10545+
4a4d8108
AM
10546+/*
10547+ * file operations
10548+ */
1facf9fc 10549+
4a4d8108
AM
10550+#ifndef __AUFS_FILE_H__
10551+#define __AUFS_FILE_H__
1facf9fc 10552+
4a4d8108 10553+#ifdef __KERNEL__
1facf9fc 10554+
2cbb1c4b 10555+#include <linux/file.h>
4a4d8108
AM
10556+#include <linux/fs.h>
10557+#include <linux/poll.h>
4a4d8108 10558+#include "rwsem.h"
1facf9fc 10559+
4a4d8108
AM
10560+struct au_branch;
10561+struct au_hfile {
10562+ struct file *hf_file;
10563+ struct au_branch *hf_br;
10564+};
1facf9fc 10565+
4a4d8108
AM
10566+struct au_vdir;
10567+struct au_fidir {
10568+ aufs_bindex_t fd_bbot;
10569+ aufs_bindex_t fd_nent;
10570+ struct au_vdir *fd_vdir_cache;
10571+ struct au_hfile fd_hfile[];
10572+};
1facf9fc 10573+
4a4d8108 10574+static inline int au_fidir_sz(int nent)
dece6358 10575+{
4f0767ce
JR
10576+ AuDebugOn(nent < 0);
10577+ return sizeof(struct au_fidir) + sizeof(struct au_hfile) * nent;
4a4d8108 10578+}
1facf9fc 10579+
4a4d8108
AM
10580+struct au_finfo {
10581+ atomic_t fi_generation;
dece6358 10582+
4a4d8108
AM
10583+ struct au_rwsem fi_rwsem;
10584+ aufs_bindex_t fi_btop;
10585+
10586+ /* do not union them */
10587+ struct { /* for non-dir */
10588+ struct au_hfile fi_htop;
2cbb1c4b 10589+ atomic_t fi_mmapped;
4a4d8108
AM
10590+ };
10591+ struct au_fidir *fi_hdir; /* for dir only */
10592+} ____cacheline_aligned_in_smp;
1facf9fc 10593+
4a4d8108 10594+/* ---------------------------------------------------------------------- */
1facf9fc 10595+
4a4d8108
AM
10596+/* file.c */
10597+extern const struct address_space_operations aufs_aop;
10598+unsigned int au_file_roflags(unsigned int flags);
10599+struct file *au_h_open(struct dentry *dentry, aufs_bindex_t bindex, int flags,
10600+ struct file *file);
10601+int au_do_open(struct file *file, int (*open)(struct file *file, int flags),
10602+ struct au_fidir *fidir);
10603+int au_reopen_nondir(struct file *file);
10604+struct au_pin;
10605+int au_ready_to_write(struct file *file, loff_t len, struct au_pin *pin);
10606+int au_reval_and_lock_fdi(struct file *file, int (*reopen)(struct file *file),
10607+ int wlock);
10608+int au_do_flush(struct file *file, fl_owner_t id,
10609+ int (*flush)(struct file *file, fl_owner_t id));
1facf9fc 10610+
4a4d8108
AM
10611+/* poll.c */
10612+#ifdef CONFIG_AUFS_POLL
10613+unsigned int aufs_poll(struct file *file, poll_table *wait);
10614+#endif
1facf9fc 10615+
4a4d8108
AM
10616+#ifdef CONFIG_AUFS_BR_HFSPLUS
10617+/* hfsplus.c */
10618+struct file *au_h_open_pre(struct dentry *dentry, aufs_bindex_t bindex);
10619+void au_h_open_post(struct dentry *dentry, aufs_bindex_t bindex,
10620+ struct file *h_file);
10621+#else
10622+static inline
10623+struct file *au_h_open_pre(struct dentry *dentry, aufs_bindex_t bindex)
dece6358 10624+{
4a4d8108
AM
10625+ return NULL;
10626+}
1facf9fc 10627+
4a4d8108
AM
10628+AuStubVoid(au_h_open_post, struct dentry *dentry, aufs_bindex_t bindex,
10629+ struct file *h_file);
10630+#endif
1facf9fc 10631+
4a4d8108
AM
10632+/* f_op.c */
10633+extern const struct file_operations aufs_file_fop;
4a4d8108
AM
10634+int au_do_open_nondir(struct file *file, int flags);
10635+int aufs_release_nondir(struct inode *inode __maybe_unused, struct file *file);
10636+
10637+#ifdef CONFIG_AUFS_SP_IATTR
10638+/* f_op_sp.c */
10639+int au_special_file(umode_t mode);
10640+void au_init_special_fop(struct inode *inode, umode_t mode, dev_t rdev);
10641+#else
10642+AuStubInt0(au_special_file, umode_t mode)
10643+static inline void au_init_special_fop(struct inode *inode, umode_t mode,
10644+ dev_t rdev)
10645+{
10646+ init_special_inode(inode, mode, rdev);
10647+}
10648+#endif
1facf9fc 10649+
4a4d8108
AM
10650+/* finfo.c */
10651+void au_hfput(struct au_hfile *hf, struct file *file);
10652+void au_set_h_fptr(struct file *file, aufs_bindex_t bindex,
10653+ struct file *h_file);
1facf9fc 10654+
4a4d8108 10655+void au_update_figen(struct file *file);
4a4d8108
AM
10656+struct au_fidir *au_fidir_alloc(struct super_block *sb);
10657+int au_fidir_realloc(struct au_finfo *finfo, int nbr);
1facf9fc 10658+
4a4d8108
AM
10659+void au_fi_init_once(void *_fi);
10660+void au_finfo_fin(struct file *file);
10661+int au_finfo_init(struct file *file, struct au_fidir *fidir);
1facf9fc 10662+
4a4d8108
AM
10663+/* ioctl.c */
10664+long aufs_ioctl_nondir(struct file *file, unsigned int cmd, unsigned long arg);
b752ccd1
AM
10665+#ifdef CONFIG_COMPAT
10666+long aufs_compat_ioctl_dir(struct file *file, unsigned int cmd,
10667+ unsigned long arg);
10668+#endif
1facf9fc 10669+
4a4d8108 10670+/* ---------------------------------------------------------------------- */
1facf9fc 10671+
4a4d8108
AM
10672+static inline struct au_finfo *au_fi(struct file *file)
10673+{
10674+ return file->private_data;
10675+}
1facf9fc 10676+
4a4d8108 10677+/* ---------------------------------------------------------------------- */
1facf9fc 10678+
4a4d8108
AM
10679+/*
10680+ * fi_read_lock, fi_write_lock,
10681+ * fi_read_unlock, fi_write_unlock, fi_downgrade_lock
10682+ */
10683+AuSimpleRwsemFuncs(fi, struct file *f, &au_fi(f)->fi_rwsem);
1308ab2a 10684+
4a4d8108
AM
10685+#define FiMustNoWaiters(f) AuRwMustNoWaiters(&au_fi(f)->fi_rwsem)
10686+#define FiMustAnyLock(f) AuRwMustAnyLock(&au_fi(f)->fi_rwsem)
10687+#define FiMustWriteLock(f) AuRwMustWriteLock(&au_fi(f)->fi_rwsem)
1facf9fc 10688+
1308ab2a 10689+/* ---------------------------------------------------------------------- */
10690+
4a4d8108
AM
10691+/* todo: hard/soft set? */
10692+static inline aufs_bindex_t au_fbstart(struct file *file)
dece6358 10693+{
4a4d8108
AM
10694+ FiMustAnyLock(file);
10695+ return au_fi(file)->fi_btop;
10696+}
dece6358 10697+
4a4d8108
AM
10698+static inline aufs_bindex_t au_fbend_dir(struct file *file)
10699+{
10700+ FiMustAnyLock(file);
10701+ AuDebugOn(!au_fi(file)->fi_hdir);
10702+ return au_fi(file)->fi_hdir->fd_bbot;
10703+}
1facf9fc 10704+
4a4d8108
AM
10705+static inline struct au_vdir *au_fvdir_cache(struct file *file)
10706+{
10707+ FiMustAnyLock(file);
10708+ AuDebugOn(!au_fi(file)->fi_hdir);
10709+ return au_fi(file)->fi_hdir->fd_vdir_cache;
10710+}
1facf9fc 10711+
4a4d8108
AM
10712+static inline void au_set_fbstart(struct file *file, aufs_bindex_t bindex)
10713+{
10714+ FiMustWriteLock(file);
10715+ au_fi(file)->fi_btop = bindex;
10716+}
1facf9fc 10717+
4a4d8108
AM
10718+static inline void au_set_fbend_dir(struct file *file, aufs_bindex_t bindex)
10719+{
10720+ FiMustWriteLock(file);
10721+ AuDebugOn(!au_fi(file)->fi_hdir);
10722+ au_fi(file)->fi_hdir->fd_bbot = bindex;
10723+}
1308ab2a 10724+
4a4d8108
AM
10725+static inline void au_set_fvdir_cache(struct file *file,
10726+ struct au_vdir *vdir_cache)
10727+{
10728+ FiMustWriteLock(file);
10729+ AuDebugOn(!au_fi(file)->fi_hdir);
10730+ au_fi(file)->fi_hdir->fd_vdir_cache = vdir_cache;
10731+}
dece6358 10732+
4a4d8108
AM
10733+static inline struct file *au_hf_top(struct file *file)
10734+{
10735+ FiMustAnyLock(file);
10736+ AuDebugOn(au_fi(file)->fi_hdir);
10737+ return au_fi(file)->fi_htop.hf_file;
10738+}
1facf9fc 10739+
4a4d8108
AM
10740+static inline struct file *au_hf_dir(struct file *file, aufs_bindex_t bindex)
10741+{
10742+ FiMustAnyLock(file);
10743+ AuDebugOn(!au_fi(file)->fi_hdir);
10744+ return au_fi(file)->fi_hdir->fd_hfile[0 + bindex].hf_file;
dece6358
AM
10745+}
10746+
4a4d8108
AM
10747+/* todo: memory barrier? */
10748+static inline unsigned int au_figen(struct file *f)
dece6358 10749+{
4a4d8108
AM
10750+ return atomic_read(&au_fi(f)->fi_generation);
10751+}
dece6358 10752+
2cbb1c4b
JR
10753+static inline void au_set_mmapped(struct file *f)
10754+{
10755+ if (atomic_inc_return(&au_fi(f)->fi_mmapped))
10756+ return;
0c3ec466 10757+ pr_warn("fi_mmapped wrapped around\n");
2cbb1c4b
JR
10758+ while (!atomic_inc_return(&au_fi(f)->fi_mmapped))
10759+ ;
10760+}
10761+
10762+static inline void au_unset_mmapped(struct file *f)
10763+{
10764+ atomic_dec(&au_fi(f)->fi_mmapped);
10765+}
10766+
4a4d8108
AM
10767+static inline int au_test_mmapped(struct file *f)
10768+{
2cbb1c4b
JR
10769+ return atomic_read(&au_fi(f)->fi_mmapped);
10770+}
10771+
10772+/* customize vma->vm_file */
10773+
10774+static inline void au_do_vm_file_reset(struct vm_area_struct *vma,
10775+ struct file *file)
10776+{
53392da6
AM
10777+ struct file *f;
10778+
10779+ f = vma->vm_file;
2cbb1c4b
JR
10780+ get_file(file);
10781+ vma->vm_file = file;
53392da6 10782+ fput(f);
2cbb1c4b
JR
10783+}
10784+
10785+#ifdef CONFIG_MMU
10786+#define AuDbgVmRegion(file, vma) do {} while (0)
10787+
10788+static inline void au_vm_file_reset(struct vm_area_struct *vma,
10789+ struct file *file)
10790+{
10791+ au_do_vm_file_reset(vma, file);
10792+}
10793+#else
10794+#define AuDbgVmRegion(file, vma) \
10795+ AuDebugOn((vma)->vm_region && (vma)->vm_region->vm_file != (file))
10796+
10797+static inline void au_vm_file_reset(struct vm_area_struct *vma,
10798+ struct file *file)
10799+{
53392da6
AM
10800+ struct file *f;
10801+
2cbb1c4b 10802+ au_do_vm_file_reset(vma, file);
53392da6 10803+ f = vma->vm_region->vm_file;
2cbb1c4b
JR
10804+ get_file(file);
10805+ vma->vm_region->vm_file = file;
53392da6 10806+ fput(f);
2cbb1c4b
JR
10807+}
10808+#endif /* CONFIG_MMU */
10809+
10810+/* handle vma->vm_prfile */
10811+static inline void au_vm_prfile_set(struct vm_area_struct *vma,
10812+ struct file *file)
10813+{
10814+#ifdef CONFIG_AUFS_PROC_MAP
10815+ get_file(file);
10816+ vma->vm_prfile = file;
10817+#ifndef CONFIG_MMU
10818+ get_file(file);
10819+ vma->vm_region->vm_prfile = file;
10820+#endif
10821+#endif
4a4d8108 10822+}
1308ab2a 10823+
4a4d8108
AM
10824+#endif /* __KERNEL__ */
10825+#endif /* __AUFS_FILE_H__ */
7f207e10
AM
10826diff -urN /usr/share/empty/fs/aufs/finfo.c linux/fs/aufs/finfo.c
10827--- /usr/share/empty/fs/aufs/finfo.c 1970-01-01 01:00:00.000000000 +0100
537831f9 10828+++ linux/fs/aufs/finfo.c 2012-12-13 20:41:10.431460173 +0100
f6c5ef8b 10829@@ -0,0 +1,156 @@
4a4d8108 10830+/*
f6c5ef8b 10831+ * Copyright (C) 2005-2012 Junjiro R. Okajima
4a4d8108
AM
10832+ *
10833+ * This program, aufs is free software; you can redistribute it and/or modify
10834+ * it under the terms of the GNU General Public License as published by
10835+ * the Free Software Foundation; either version 2 of the License, or
10836+ * (at your option) any later version.
10837+ *
10838+ * This program is distributed in the hope that it will be useful,
10839+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
10840+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10841+ * GNU General Public License for more details.
10842+ *
10843+ * You should have received a copy of the GNU General Public License
10844+ * along with this program; if not, write to the Free Software
10845+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
10846+ */
1308ab2a 10847+
4a4d8108
AM
10848+/*
10849+ * file private data
10850+ */
1facf9fc 10851+
4a4d8108 10852+#include "aufs.h"
1facf9fc 10853+
4a4d8108
AM
10854+void au_hfput(struct au_hfile *hf, struct file *file)
10855+{
10856+ /* todo: direct access f_flags */
2cbb1c4b 10857+ if (vfsub_file_flags(file) & __FMODE_EXEC)
4a4d8108
AM
10858+ allow_write_access(hf->hf_file);
10859+ fput(hf->hf_file);
10860+ hf->hf_file = NULL;
e49829fe 10861+ atomic_dec(&hf->hf_br->br_count);
4a4d8108
AM
10862+ hf->hf_br = NULL;
10863+}
1facf9fc 10864+
4a4d8108
AM
10865+void au_set_h_fptr(struct file *file, aufs_bindex_t bindex, struct file *val)
10866+{
10867+ struct au_finfo *finfo = au_fi(file);
10868+ struct au_hfile *hf;
10869+ struct au_fidir *fidir;
10870+
10871+ fidir = finfo->fi_hdir;
10872+ if (!fidir) {
10873+ AuDebugOn(finfo->fi_btop != bindex);
10874+ hf = &finfo->fi_htop;
10875+ } else
10876+ hf = fidir->fd_hfile + bindex;
10877+
10878+ if (hf && hf->hf_file)
10879+ au_hfput(hf, file);
10880+ if (val) {
10881+ FiMustWriteLock(file);
10882+ hf->hf_file = val;
10883+ hf->hf_br = au_sbr(file->f_dentry->d_sb, bindex);
1308ab2a 10884+ }
4a4d8108 10885+}
1facf9fc 10886+
4a4d8108
AM
10887+void au_update_figen(struct file *file)
10888+{
10889+ atomic_set(&au_fi(file)->fi_generation, au_digen(file->f_dentry));
10890+ /* smp_mb(); */ /* atomic_set */
1facf9fc 10891+}
10892+
4a4d8108
AM
10893+/* ---------------------------------------------------------------------- */
10894+
4a4d8108
AM
10895+struct au_fidir *au_fidir_alloc(struct super_block *sb)
10896+{
10897+ struct au_fidir *fidir;
10898+ int nbr;
10899+
10900+ nbr = au_sbend(sb) + 1;
10901+ if (nbr < 2)
10902+ nbr = 2; /* initial allocate for 2 branches */
10903+ fidir = kzalloc(au_fidir_sz(nbr), GFP_NOFS);
10904+ if (fidir) {
10905+ fidir->fd_bbot = -1;
10906+ fidir->fd_nent = nbr;
10907+ fidir->fd_vdir_cache = NULL;
10908+ }
10909+
10910+ return fidir;
10911+}
10912+
10913+int au_fidir_realloc(struct au_finfo *finfo, int nbr)
10914+{
10915+ int err;
10916+ struct au_fidir *fidir, *p;
10917+
10918+ AuRwMustWriteLock(&finfo->fi_rwsem);
10919+ fidir = finfo->fi_hdir;
10920+ AuDebugOn(!fidir);
10921+
10922+ err = -ENOMEM;
10923+ p = au_kzrealloc(fidir, au_fidir_sz(fidir->fd_nent), au_fidir_sz(nbr),
10924+ GFP_NOFS);
10925+ if (p) {
10926+ p->fd_nent = nbr;
10927+ finfo->fi_hdir = p;
10928+ err = 0;
10929+ }
1facf9fc 10930+
dece6358 10931+ return err;
1facf9fc 10932+}
1308ab2a 10933+
10934+/* ---------------------------------------------------------------------- */
10935+
4a4d8108 10936+void au_finfo_fin(struct file *file)
1308ab2a 10937+{
4a4d8108
AM
10938+ struct au_finfo *finfo;
10939+
7f207e10
AM
10940+ au_nfiles_dec(file->f_dentry->d_sb);
10941+
4a4d8108
AM
10942+ finfo = au_fi(file);
10943+ AuDebugOn(finfo->fi_hdir);
10944+ AuRwDestroy(&finfo->fi_rwsem);
10945+ au_cache_free_finfo(finfo);
1308ab2a 10946+}
1308ab2a 10947+
e49829fe 10948+void au_fi_init_once(void *_finfo)
4a4d8108 10949+{
e49829fe 10950+ struct au_finfo *finfo = _finfo;
2cbb1c4b 10951+ static struct lock_class_key aufs_fi;
1308ab2a 10952+
e49829fe
JR
10953+ au_rw_init(&finfo->fi_rwsem);
10954+ au_rw_class(&finfo->fi_rwsem, &aufs_fi);
4a4d8108 10955+}
1308ab2a 10956+
4a4d8108
AM
10957+int au_finfo_init(struct file *file, struct au_fidir *fidir)
10958+{
9dbd164d 10959+ int err, lc_idx;
4a4d8108
AM
10960+ struct au_finfo *finfo;
10961+ struct dentry *dentry;
10962+
10963+ err = -ENOMEM;
10964+ dentry = file->f_dentry;
10965+ finfo = au_cache_alloc_finfo();
10966+ if (unlikely(!finfo))
10967+ goto out;
10968+
10969+ err = 0;
7f207e10 10970+ au_nfiles_inc(dentry->d_sb);
9dbd164d
AM
10971+ lc_idx = AuLcNonDir_FIINFO;
10972+ if (fidir)
10973+ lc_idx = AuLcDir_FIINFO;
10974+ au_rw_class(&finfo->fi_rwsem, au_lc_key + lc_idx);
4a4d8108
AM
10975+ au_rw_write_lock(&finfo->fi_rwsem);
10976+ finfo->fi_btop = -1;
10977+ finfo->fi_hdir = fidir;
10978+ atomic_set(&finfo->fi_generation, au_digen(dentry));
10979+ /* smp_mb(); */ /* atomic_set */
10980+
10981+ file->private_data = finfo;
10982+
10983+out:
10984+ return err;
10985+}
7f207e10
AM
10986diff -urN /usr/share/empty/fs/aufs/f_op.c linux/fs/aufs/f_op.c
10987--- /usr/share/empty/fs/aufs/f_op.c 1970-01-01 01:00:00.000000000 +0100
537831f9
AM
10988+++ linux/fs/aufs/f_op.c 2012-12-13 20:41:10.428126759 +0100
10989@@ -0,0 +1,723 @@
dece6358 10990+/*
f6c5ef8b 10991+ * Copyright (C) 2005-2012 Junjiro R. Okajima
dece6358
AM
10992+ *
10993+ * This program, aufs is free software; you can redistribute it and/or modify
10994+ * it under the terms of the GNU General Public License as published by
10995+ * the Free Software Foundation; either version 2 of the License, or
10996+ * (at your option) any later version.
10997+ *
10998+ * This program is distributed in the hope that it will be useful,
10999+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
11000+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11001+ * GNU General Public License for more details.
11002+ *
11003+ * You should have received a copy of the GNU General Public License
11004+ * along with this program; if not, write to the Free Software
11005+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
11006+ */
1facf9fc 11007+
11008+/*
4a4d8108 11009+ * file and vm operations
1facf9fc 11010+ */
dece6358 11011+
4a4d8108
AM
11012+#include <linux/fs_stack.h>
11013+#include <linux/mman.h>
4a4d8108 11014+#include <linux/security.h>
dece6358
AM
11015+#include "aufs.h"
11016+
4a4d8108 11017+int au_do_open_nondir(struct file *file, int flags)
1facf9fc 11018+{
4a4d8108
AM
11019+ int err;
11020+ aufs_bindex_t bindex;
11021+ struct file *h_file;
11022+ struct dentry *dentry;
11023+ struct au_finfo *finfo;
11024+
11025+ FiMustWriteLock(file);
11026+
4a4d8108 11027+ dentry = file->f_dentry;
027c5e7a
AM
11028+ err = au_d_alive(dentry);
11029+ if (unlikely(err))
11030+ goto out;
11031+
4a4d8108
AM
11032+ finfo = au_fi(file);
11033+ memset(&finfo->fi_htop, 0, sizeof(finfo->fi_htop));
2cbb1c4b 11034+ atomic_set(&finfo->fi_mmapped, 0);
4a4d8108
AM
11035+ bindex = au_dbstart(dentry);
11036+ h_file = au_h_open(dentry, bindex, flags, file);
11037+ if (IS_ERR(h_file))
11038+ err = PTR_ERR(h_file);
11039+ else {
11040+ au_set_fbstart(file, bindex);
11041+ au_set_h_fptr(file, bindex, h_file);
11042+ au_update_figen(file);
11043+ /* todo: necessary? */
11044+ /* file->f_ra = h_file->f_ra; */
11045+ }
027c5e7a
AM
11046+
11047+out:
4a4d8108 11048+ return err;
1facf9fc 11049+}
11050+
4a4d8108
AM
11051+static int aufs_open_nondir(struct inode *inode __maybe_unused,
11052+ struct file *file)
1facf9fc 11053+{
4a4d8108 11054+ int err;
1308ab2a 11055+ struct super_block *sb;
1facf9fc 11056+
2cbb1c4b 11057+ AuDbg("%.*s, f_flags 0x%x, f_mode 0x%x\n",
4a4d8108
AM
11058+ AuDLNPair(file->f_dentry), vfsub_file_flags(file),
11059+ file->f_mode);
1facf9fc 11060+
4a4d8108
AM
11061+ sb = file->f_dentry->d_sb;
11062+ si_read_lock(sb, AuLock_FLUSH);
11063+ err = au_do_open(file, au_do_open_nondir, /*fidir*/NULL);
11064+ si_read_unlock(sb);
11065+ return err;
11066+}
1facf9fc 11067+
4a4d8108
AM
11068+int aufs_release_nondir(struct inode *inode __maybe_unused, struct file *file)
11069+{
11070+ struct au_finfo *finfo;
11071+ aufs_bindex_t bindex;
1facf9fc 11072+
4a4d8108
AM
11073+ finfo = au_fi(file);
11074+ bindex = finfo->fi_btop;
b4510431 11075+ if (bindex >= 0)
4a4d8108 11076+ au_set_h_fptr(file, bindex, NULL);
7f207e10 11077+
4a4d8108
AM
11078+ au_finfo_fin(file);
11079+ return 0;
1facf9fc 11080+}
11081+
4a4d8108
AM
11082+/* ---------------------------------------------------------------------- */
11083+
11084+static int au_do_flush_nondir(struct file *file, fl_owner_t id)
dece6358 11085+{
1308ab2a 11086+ int err;
4a4d8108
AM
11087+ struct file *h_file;
11088+
11089+ err = 0;
11090+ h_file = au_hf_top(file);
11091+ if (h_file)
11092+ err = vfsub_flush(h_file, id);
11093+ return err;
11094+}
11095+
11096+static int aufs_flush_nondir(struct file *file, fl_owner_t id)
11097+{
11098+ return au_do_flush(file, id, au_do_flush_nondir);
11099+}
11100+
11101+/* ---------------------------------------------------------------------- */
9dbd164d
AM
11102+/*
11103+ * read and write functions acquire [fdi]_rwsem once, but release before
11104+ * mmap_sem. This is because to stop a race condition between mmap(2).
11105+ * Releasing these aufs-rwsem should be safe, no branch-mamagement (by keeping
11106+ * si_rwsem), no harmful copy-up should happen. Actually copy-up may happen in
11107+ * read functions after [fdi]_rwsem are released, but it should be harmless.
11108+ */
4a4d8108
AM
11109+
11110+static ssize_t aufs_read(struct file *file, char __user *buf, size_t count,
11111+ loff_t *ppos)
11112+{
11113+ ssize_t err;
dece6358 11114+ struct dentry *dentry;
4a4d8108 11115+ struct file *h_file;
dece6358 11116+ struct super_block *sb;
1facf9fc 11117+
dece6358
AM
11118+ dentry = file->f_dentry;
11119+ sb = dentry->d_sb;
e49829fe 11120+ si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLMW);
4a4d8108 11121+ err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/0);
dece6358
AM
11122+ if (unlikely(err))
11123+ goto out;
1facf9fc 11124+
4a4d8108 11125+ h_file = au_hf_top(file);
9dbd164d
AM
11126+ get_file(h_file);
11127+ di_read_unlock(dentry, AuLock_IR);
11128+ fi_read_unlock(file);
11129+
11130+ /* filedata may be obsoleted by concurrent copyup, but no problem */
4a4d8108
AM
11131+ err = vfsub_read_u(h_file, buf, count, ppos);
11132+ /* todo: necessary? */
11133+ /* file->f_ra = h_file->f_ra; */
9dbd164d 11134+ /* update without lock, I don't think it a problem */
4a4d8108 11135+ fsstack_copy_attr_atime(dentry->d_inode, h_file->f_dentry->d_inode);
9dbd164d 11136+ fput(h_file);
1308ab2a 11137+
4f0767ce 11138+out:
dece6358
AM
11139+ si_read_unlock(sb);
11140+ return err;
11141+}
1facf9fc 11142+
e49829fe
JR
11143+/*
11144+ * todo: very ugly
11145+ * it locks both of i_mutex and si_rwsem for read in safe.
11146+ * if the plink maintenance mode continues forever (that is the problem),
11147+ * may loop forever.
11148+ */
11149+static void au_mtx_and_read_lock(struct inode *inode)
11150+{
11151+ int err;
11152+ struct super_block *sb = inode->i_sb;
11153+
11154+ while (1) {
11155+ mutex_lock(&inode->i_mutex);
11156+ err = si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLM);
11157+ if (!err)
11158+ break;
11159+ mutex_unlock(&inode->i_mutex);
11160+ si_read_lock(sb, AuLock_NOPLMW);
11161+ si_read_unlock(sb);
11162+ }
11163+}
11164+
4a4d8108
AM
11165+static ssize_t aufs_write(struct file *file, const char __user *ubuf,
11166+ size_t count, loff_t *ppos)
dece6358 11167+{
4a4d8108
AM
11168+ ssize_t err;
11169+ struct au_pin pin;
dece6358 11170+ struct dentry *dentry;
9dbd164d 11171+ struct super_block *sb;
4a4d8108 11172+ struct inode *inode;
4a4d8108
AM
11173+ struct file *h_file;
11174+ char __user *buf = (char __user *)ubuf;
1facf9fc 11175+
dece6358 11176+ dentry = file->f_dentry;
9dbd164d 11177+ sb = dentry->d_sb;
4a4d8108 11178+ inode = dentry->d_inode;
e49829fe 11179+ au_mtx_and_read_lock(inode);
1facf9fc 11180+
4a4d8108
AM
11181+ err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/1);
11182+ if (unlikely(err))
11183+ goto out;
1facf9fc 11184+
4a4d8108
AM
11185+ err = au_ready_to_write(file, -1, &pin);
11186+ di_downgrade_lock(dentry, AuLock_IR);
9dbd164d
AM
11187+ if (unlikely(err)) {
11188+ di_read_unlock(dentry, AuLock_IR);
11189+ fi_write_unlock(file);
11190+ goto out;
11191+ }
1facf9fc 11192+
4a4d8108 11193+ h_file = au_hf_top(file);
9dbd164d 11194+ get_file(h_file);
4a4d8108 11195+ au_unpin(&pin);
9dbd164d
AM
11196+ di_read_unlock(dentry, AuLock_IR);
11197+ fi_write_unlock(file);
11198+
4a4d8108 11199+ err = vfsub_write_u(h_file, buf, count, ppos);
9dbd164d 11200+ ii_write_lock_child(inode);
4a4d8108
AM
11201+ au_cpup_attr_timesizes(inode);
11202+ inode->i_mode = h_file->f_dentry->d_inode->i_mode;
9dbd164d
AM
11203+ ii_write_unlock(inode);
11204+ fput(h_file);
1facf9fc 11205+
4f0767ce 11206+out:
9dbd164d 11207+ si_read_unlock(sb);
4a4d8108 11208+ mutex_unlock(&inode->i_mutex);
dece6358
AM
11209+ return err;
11210+}
1facf9fc 11211+
4a4d8108
AM
11212+static ssize_t au_do_aio(struct file *h_file, int rw, struct kiocb *kio,
11213+ const struct iovec *iov, unsigned long nv, loff_t pos)
dece6358 11214+{
4a4d8108
AM
11215+ ssize_t err;
11216+ struct file *file;
11217+ ssize_t (*func)(struct kiocb *, const struct iovec *, unsigned long,
11218+ loff_t);
1facf9fc 11219+
4a4d8108
AM
11220+ err = security_file_permission(h_file, rw);
11221+ if (unlikely(err))
11222+ goto out;
1facf9fc 11223+
4a4d8108
AM
11224+ err = -ENOSYS;
11225+ func = NULL;
11226+ if (rw == MAY_READ)
11227+ func = h_file->f_op->aio_read;
11228+ else if (rw == MAY_WRITE)
11229+ func = h_file->f_op->aio_write;
11230+ if (func) {
11231+ file = kio->ki_filp;
11232+ kio->ki_filp = h_file;
2cbb1c4b 11233+ lockdep_off();
4a4d8108 11234+ err = func(kio, iov, nv, pos);
2cbb1c4b 11235+ lockdep_on();
4a4d8108
AM
11236+ kio->ki_filp = file;
11237+ } else
11238+ /* currently there is no such fs */
11239+ WARN_ON_ONCE(1);
1facf9fc 11240+
4f0767ce 11241+out:
dece6358
AM
11242+ return err;
11243+}
1facf9fc 11244+
4a4d8108
AM
11245+static ssize_t aufs_aio_read(struct kiocb *kio, const struct iovec *iov,
11246+ unsigned long nv, loff_t pos)
1facf9fc 11247+{
4a4d8108
AM
11248+ ssize_t err;
11249+ struct file *file, *h_file;
11250+ struct dentry *dentry;
dece6358 11251+ struct super_block *sb;
1facf9fc 11252+
4a4d8108 11253+ file = kio->ki_filp;
dece6358 11254+ dentry = file->f_dentry;
1308ab2a 11255+ sb = dentry->d_sb;
e49829fe 11256+ si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLMW);
4a4d8108
AM
11257+ err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/0);
11258+ if (unlikely(err))
11259+ goto out;
11260+
11261+ h_file = au_hf_top(file);
9dbd164d
AM
11262+ get_file(h_file);
11263+ di_read_unlock(dentry, AuLock_IR);
11264+ fi_read_unlock(file);
11265+
4a4d8108
AM
11266+ err = au_do_aio(h_file, MAY_READ, kio, iov, nv, pos);
11267+ /* todo: necessary? */
11268+ /* file->f_ra = h_file->f_ra; */
9dbd164d 11269+ /* update without lock, I don't think it a problem */
4a4d8108 11270+ fsstack_copy_attr_atime(dentry->d_inode, h_file->f_dentry->d_inode);
9dbd164d 11271+ fput(h_file);
1facf9fc 11272+
4f0767ce 11273+out:
4a4d8108 11274+ si_read_unlock(sb);
1308ab2a 11275+ return err;
11276+}
1facf9fc 11277+
4a4d8108
AM
11278+static ssize_t aufs_aio_write(struct kiocb *kio, const struct iovec *iov,
11279+ unsigned long nv, loff_t pos)
1308ab2a 11280+{
4a4d8108
AM
11281+ ssize_t err;
11282+ struct au_pin pin;
11283+ struct dentry *dentry;
11284+ struct inode *inode;
4a4d8108 11285+ struct file *file, *h_file;
9dbd164d 11286+ struct super_block *sb;
1308ab2a 11287+
4a4d8108 11288+ file = kio->ki_filp;
1308ab2a 11289+ dentry = file->f_dentry;
9dbd164d 11290+ sb = dentry->d_sb;
1308ab2a 11291+ inode = dentry->d_inode;
e49829fe
JR
11292+ au_mtx_and_read_lock(inode);
11293+
4a4d8108
AM
11294+ err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/1);
11295+ if (unlikely(err))
1308ab2a 11296+ goto out;
1facf9fc 11297+
4a4d8108
AM
11298+ err = au_ready_to_write(file, -1, &pin);
11299+ di_downgrade_lock(dentry, AuLock_IR);
9dbd164d
AM
11300+ if (unlikely(err)) {
11301+ di_read_unlock(dentry, AuLock_IR);
11302+ fi_write_unlock(file);
11303+ goto out;
11304+ }
1facf9fc 11305+
4a4d8108 11306+ h_file = au_hf_top(file);
9dbd164d
AM
11307+ get_file(h_file);
11308+ au_unpin(&pin);
11309+ di_read_unlock(dentry, AuLock_IR);
11310+ fi_write_unlock(file);
11311+
4a4d8108 11312+ err = au_do_aio(h_file, MAY_WRITE, kio, iov, nv, pos);
9dbd164d 11313+ ii_write_lock_child(inode);
4a4d8108
AM
11314+ au_cpup_attr_timesizes(inode);
11315+ inode->i_mode = h_file->f_dentry->d_inode->i_mode;
9dbd164d
AM
11316+ ii_write_unlock(inode);
11317+ fput(h_file);
1facf9fc 11318+
4f0767ce 11319+out:
9dbd164d 11320+ si_read_unlock(sb);
4a4d8108 11321+ mutex_unlock(&inode->i_mutex);
dece6358 11322+ return err;
1facf9fc 11323+}
11324+
4a4d8108
AM
11325+static ssize_t aufs_splice_read(struct file *file, loff_t *ppos,
11326+ struct pipe_inode_info *pipe, size_t len,
11327+ unsigned int flags)
1facf9fc 11328+{
4a4d8108
AM
11329+ ssize_t err;
11330+ struct file *h_file;
11331+ struct dentry *dentry;
dece6358 11332+ struct super_block *sb;
1facf9fc 11333+
dece6358 11334+ dentry = file->f_dentry;
dece6358 11335+ sb = dentry->d_sb;
e49829fe 11336+ si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLMW);
4a4d8108
AM
11337+ err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/0);
11338+ if (unlikely(err))
dece6358 11339+ goto out;
1facf9fc 11340+
4a4d8108
AM
11341+ err = -EINVAL;
11342+ h_file = au_hf_top(file);
9dbd164d 11343+ get_file(h_file);
4a4d8108 11344+ if (au_test_loopback_kthread()) {
87a755f4
AM
11345+ au_warn_loopback(h_file->f_dentry->d_sb);
11346+ if (file->f_mapping != h_file->f_mapping) {
11347+ file->f_mapping = h_file->f_mapping;
11348+ smp_mb(); /* unnecessary? */
11349+ }
1308ab2a 11350+ }
9dbd164d
AM
11351+ di_read_unlock(dentry, AuLock_IR);
11352+ fi_read_unlock(file);
11353+
4a4d8108
AM
11354+ err = vfsub_splice_to(h_file, ppos, pipe, len, flags);
11355+ /* todo: necessasry? */
11356+ /* file->f_ra = h_file->f_ra; */
9dbd164d 11357+ /* update without lock, I don't think it a problem */
4a4d8108 11358+ fsstack_copy_attr_atime(dentry->d_inode, h_file->f_dentry->d_inode);
9dbd164d 11359+ fput(h_file);
1facf9fc 11360+
4f0767ce 11361+out:
4a4d8108 11362+ si_read_unlock(sb);
dece6358 11363+ return err;
1facf9fc 11364+}
11365+
4a4d8108
AM
11366+static ssize_t
11367+aufs_splice_write(struct pipe_inode_info *pipe, struct file *file, loff_t *ppos,
11368+ size_t len, unsigned int flags)
1facf9fc 11369+{
4a4d8108
AM
11370+ ssize_t err;
11371+ struct au_pin pin;
11372+ struct dentry *dentry;
11373+ struct inode *inode;
4a4d8108 11374+ struct file *h_file;
9dbd164d 11375+ struct super_block *sb;
1facf9fc 11376+
4a4d8108 11377+ dentry = file->f_dentry;
9dbd164d 11378+ sb = dentry->d_sb;
4a4d8108 11379+ inode = dentry->d_inode;
e49829fe 11380+ au_mtx_and_read_lock(inode);
9dbd164d 11381+
4a4d8108
AM
11382+ err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/1);
11383+ if (unlikely(err))
11384+ goto out;
1facf9fc 11385+
4a4d8108
AM
11386+ err = au_ready_to_write(file, -1, &pin);
11387+ di_downgrade_lock(dentry, AuLock_IR);
9dbd164d
AM
11388+ if (unlikely(err)) {
11389+ di_read_unlock(dentry, AuLock_IR);
11390+ fi_write_unlock(file);
11391+ goto out;
11392+ }
1facf9fc 11393+
4a4d8108 11394+ h_file = au_hf_top(file);
9dbd164d 11395+ get_file(h_file);
4a4d8108 11396+ au_unpin(&pin);
9dbd164d
AM
11397+ di_read_unlock(dentry, AuLock_IR);
11398+ fi_write_unlock(file);
11399+
4a4d8108 11400+ err = vfsub_splice_from(pipe, h_file, ppos, len, flags);
9dbd164d 11401+ ii_write_lock_child(inode);
4a4d8108
AM
11402+ au_cpup_attr_timesizes(inode);
11403+ inode->i_mode = h_file->f_dentry->d_inode->i_mode;
9dbd164d
AM
11404+ ii_write_unlock(inode);
11405+ fput(h_file);
1facf9fc 11406+
4f0767ce 11407+out:
9dbd164d 11408+ si_read_unlock(sb);
4a4d8108
AM
11409+ mutex_unlock(&inode->i_mutex);
11410+ return err;
11411+}
1facf9fc 11412+
4a4d8108
AM
11413+/* ---------------------------------------------------------------------- */
11414+
9dbd164d
AM
11415+/*
11416+ * The locking order around current->mmap_sem.
11417+ * - in most and regular cases
11418+ * file I/O syscall -- aufs_read() or something
11419+ * -- si_rwsem for read -- mmap_sem
11420+ * (Note that [fdi]i_rwsem are released before mmap_sem).
11421+ * - in mmap case
11422+ * mmap(2) -- mmap_sem -- aufs_mmap() -- si_rwsem for read -- [fdi]i_rwsem
11423+ * This AB-BA order is definitly bad, but is not a problem since "si_rwsem for
11424+ * read" allows muliple processes to acquire it and [fdi]i_rwsem are not held in
11425+ * file I/O. Aufs needs to stop lockdep in aufs_mmap() though.
11426+ * It means that when aufs acquires si_rwsem for write, the process should never
11427+ * acquire mmap_sem.
11428+ *
11429+ * Actually aufs_readdir() holds [fdi]i_rwsem before mmap_sem, but this is not a
11430+ * problem either since any directory is not able to be mmap-ed.
11431+ * The similar scenario is applied to aufs_readlink() too.
11432+ */
11433+
2dfbb274
AM
11434+/* cf. linux/include/linux/mman.h: calc_vm_prot_bits() */
11435+#define AuConv_VM_PROT(f, b) _calc_vm_trans(f, VM_##b, PROT_##b)
11436+
11437+static unsigned long au_arch_prot_conv(unsigned long flags)
11438+{
11439+ /* currently ppc64 only */
11440+#ifdef CONFIG_PPC64
11441+ /* cf. linux/arch/powerpc/include/asm/mman.h */
11442+ AuDebugOn(arch_calc_vm_prot_bits(-1) != VM_SAO);
11443+ return AuConv_VM_PROT(flags, SAO);
11444+#else
11445+ AuDebugOn(arch_calc_vm_prot_bits(-1));
11446+ return 0;
11447+#endif
11448+}
11449+
11450+static unsigned long au_prot_conv(unsigned long flags)
11451+{
11452+ return AuConv_VM_PROT(flags, READ)
11453+ | AuConv_VM_PROT(flags, WRITE)
11454+ | AuConv_VM_PROT(flags, EXEC)
11455+ | au_arch_prot_conv(flags);
11456+}
11457+
11458+/* cf. linux/include/linux/mman.h: calc_vm_flag_bits() */
11459+#define AuConv_VM_MAP(f, b) _calc_vm_trans(f, VM_##b, MAP_##b)
11460+
11461+static unsigned long au_flag_conv(unsigned long flags)
11462+{
11463+ return AuConv_VM_MAP(flags, GROWSDOWN)
11464+ | AuConv_VM_MAP(flags, DENYWRITE)
2dfbb274
AM
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
537831f9 11715+++ linux/fs/aufs/f_op_sp.c 2012-12-13 20:41:10.431460173 +0100
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
537831f9 12014+++ linux/fs/aufs/fstype.h 2012-12-13 20:41:10.431460173 +0100
b4510431 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
537831f9 12499+++ linux/fs/aufs/hfsnotify.c 2012-12-13 20:41:10.431460173 +0100
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
537831f9 12760+++ linux/fs/aufs/hfsplus.c 2012-12-13 20:41:10.431460173 +0100
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
537831f9 12821+++ linux/fs/aufs/hnotify.c 2012-12-13 20:41:10.431460173 +0100
b4510431 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
537831f9
AM
13538+++ linux/fs/aufs/iinfo.c 2012-12-13 20:41:10.431460173 +0100
13539@@ -0,0 +1,276 @@
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+
537831f9 13652+void au_update_iigen(struct inode *inode, int half)
1308ab2a 13653+{
537831f9
AM
13654+ struct au_iinfo *iinfo;
13655+ struct au_iigen *iigen;
13656+ unsigned int sigen;
13657+
13658+ sigen = au_sigen(inode->i_sb);
13659+ iinfo = au_ii(inode);
13660+ iigen = &iinfo->ii_generation;
13661+ spin_lock(&iinfo->ii_genspin);
13662+ iigen->ig_generation = sigen;
13663+ if (half)
13664+ au_ig_fset(iigen->ig_flags, HALF_REFRESHED);
13665+ else
13666+ au_ig_fclr(iigen->ig_flags, HALF_REFRESHED);
13667+ spin_unlock(&iinfo->ii_genspin);
4a4d8108 13668+}
1facf9fc 13669+
4a4d8108
AM
13670+/* it may be called at remount time, too */
13671+void au_update_ibrange(struct inode *inode, int do_put_zero)
13672+{
13673+ struct au_iinfo *iinfo;
027c5e7a 13674+ aufs_bindex_t bindex, bend;
1facf9fc 13675+
4a4d8108 13676+ iinfo = au_ii(inode);
027c5e7a 13677+ if (!iinfo)
4a4d8108 13678+ return;
1facf9fc 13679+
4a4d8108 13680+ IiMustWriteLock(inode);
1facf9fc 13681+
027c5e7a 13682+ if (do_put_zero && iinfo->ii_bstart >= 0) {
4a4d8108
AM
13683+ for (bindex = iinfo->ii_bstart; bindex <= iinfo->ii_bend;
13684+ bindex++) {
13685+ struct inode *h_i;
1facf9fc 13686+
4a4d8108 13687+ h_i = iinfo->ii_hinode[0 + bindex].hi_inode;
027c5e7a
AM
13688+ if (h_i && !h_i->i_nlink)
13689+ au_set_h_iptr(inode, bindex, NULL, 0);
13690+ }
4a4d8108
AM
13691+ }
13692+
027c5e7a
AM
13693+ iinfo->ii_bstart = -1;
13694+ iinfo->ii_bend = -1;
13695+ bend = au_sbend(inode->i_sb);
13696+ for (bindex = 0; bindex <= bend; bindex++)
13697+ if (iinfo->ii_hinode[0 + bindex].hi_inode) {
13698+ iinfo->ii_bstart = bindex;
4a4d8108 13699+ break;
027c5e7a
AM
13700+ }
13701+ if (iinfo->ii_bstart >= 0)
13702+ for (bindex = bend; bindex >= iinfo->ii_bstart; bindex--)
13703+ if (iinfo->ii_hinode[0 + bindex].hi_inode) {
13704+ iinfo->ii_bend = bindex;
13705+ break;
13706+ }
13707+ AuDebugOn(iinfo->ii_bstart > iinfo->ii_bend);
1308ab2a 13708+}
1facf9fc 13709+
dece6358 13710+/* ---------------------------------------------------------------------- */
1facf9fc 13711+
4a4d8108 13712+void au_icntnr_init_once(void *_c)
dece6358 13713+{
4a4d8108
AM
13714+ struct au_icntnr *c = _c;
13715+ struct au_iinfo *iinfo = &c->iinfo;
e49829fe 13716+ static struct lock_class_key aufs_ii;
1facf9fc 13717+
537831f9 13718+ spin_lock_init(&iinfo->ii_genspin);
4a4d8108 13719+ au_rw_init(&iinfo->ii_rwsem);
e49829fe 13720+ au_rw_class(&iinfo->ii_rwsem, &aufs_ii);
4a4d8108
AM
13721+ inode_init_once(&c->vfs_inode);
13722+}
1facf9fc 13723+
4a4d8108
AM
13724+int au_iinfo_init(struct inode *inode)
13725+{
13726+ struct au_iinfo *iinfo;
13727+ struct super_block *sb;
13728+ int nbr, i;
1facf9fc 13729+
4a4d8108
AM
13730+ sb = inode->i_sb;
13731+ iinfo = &(container_of(inode, struct au_icntnr, vfs_inode)->iinfo);
13732+ nbr = au_sbend(sb) + 1;
13733+ if (unlikely(nbr <= 0))
13734+ nbr = 1;
13735+ iinfo->ii_hinode = kcalloc(nbr, sizeof(*iinfo->ii_hinode), GFP_NOFS);
13736+ if (iinfo->ii_hinode) {
7f207e10 13737+ au_ninodes_inc(sb);
4a4d8108
AM
13738+ for (i = 0; i < nbr; i++)
13739+ iinfo->ii_hinode[i].hi_id = -1;
1facf9fc 13740+
537831f9 13741+ iinfo->ii_generation.ig_generation = au_sigen(sb);
4a4d8108
AM
13742+ iinfo->ii_bstart = -1;
13743+ iinfo->ii_bend = -1;
13744+ iinfo->ii_vdir = NULL;
13745+ return 0;
1308ab2a 13746+ }
4a4d8108
AM
13747+ return -ENOMEM;
13748+}
1facf9fc 13749+
4a4d8108
AM
13750+int au_ii_realloc(struct au_iinfo *iinfo, int nbr)
13751+{
13752+ int err, sz;
13753+ struct au_hinode *hip;
1facf9fc 13754+
4a4d8108
AM
13755+ AuRwMustWriteLock(&iinfo->ii_rwsem);
13756+
13757+ err = -ENOMEM;
13758+ sz = sizeof(*hip) * (iinfo->ii_bend + 1);
13759+ if (!sz)
13760+ sz = sizeof(*hip);
13761+ hip = au_kzrealloc(iinfo->ii_hinode, sz, sizeof(*hip) * nbr, GFP_NOFS);
13762+ if (hip) {
13763+ iinfo->ii_hinode = hip;
13764+ err = 0;
1308ab2a 13765+ }
4a4d8108 13766+
1308ab2a 13767+ return err;
1facf9fc 13768+}
13769+
4a4d8108 13770+void au_iinfo_fin(struct inode *inode)
1facf9fc 13771+{
4a4d8108
AM
13772+ struct au_iinfo *iinfo;
13773+ struct au_hinode *hi;
13774+ struct super_block *sb;
b752ccd1
AM
13775+ aufs_bindex_t bindex, bend;
13776+ const unsigned char unlinked = !inode->i_nlink;
1308ab2a 13777+
4a4d8108
AM
13778+ iinfo = au_ii(inode);
13779+ /* bad_inode case */
13780+ if (!iinfo)
13781+ return;
1308ab2a 13782+
b752ccd1 13783+ sb = inode->i_sb;
7f207e10 13784+ au_ninodes_dec(sb);
b752ccd1
AM
13785+ if (si_pid_test(sb))
13786+ au_xino_delete_inode(inode, unlinked);
13787+ else {
13788+ /*
13789+ * it is safe to hide the dependency between sbinfo and
13790+ * sb->s_umount.
13791+ */
13792+ lockdep_off();
13793+ si_noflush_read_lock(sb);
13794+ au_xino_delete_inode(inode, unlinked);
13795+ si_read_unlock(sb);
13796+ lockdep_on();
13797+ }
13798+
4a4d8108
AM
13799+ if (iinfo->ii_vdir)
13800+ au_vdir_free(iinfo->ii_vdir);
1308ab2a 13801+
b752ccd1
AM
13802+ bindex = iinfo->ii_bstart;
13803+ if (bindex >= 0) {
13804+ hi = iinfo->ii_hinode + bindex;
4a4d8108 13805+ bend = iinfo->ii_bend;
b752ccd1
AM
13806+ while (bindex++ <= bend) {
13807+ if (hi->hi_inode)
4a4d8108 13808+ au_hiput(hi);
4a4d8108
AM
13809+ hi++;
13810+ }
13811+ }
4a4d8108 13812+ kfree(iinfo->ii_hinode);
027c5e7a 13813+ iinfo->ii_hinode = NULL;
4a4d8108 13814+ AuRwDestroy(&iinfo->ii_rwsem);
dece6358 13815+}
7f207e10
AM
13816diff -urN /usr/share/empty/fs/aufs/inode.c linux/fs/aufs/inode.c
13817--- /usr/share/empty/fs/aufs/inode.c 1970-01-01 01:00:00.000000000 +0100
537831f9
AM
13818+++ linux/fs/aufs/inode.c 2012-12-13 20:41:10.431460173 +0100
13819@@ -0,0 +1,488 @@
4a4d8108 13820+/*
f6c5ef8b 13821+ * Copyright (C) 2005-2012 Junjiro R. Okajima
4a4d8108
AM
13822+ *
13823+ * This program, aufs is free software; you can redistribute it and/or modify
13824+ * it under the terms of the GNU General Public License as published by
13825+ * the Free Software Foundation; either version 2 of the License, or
13826+ * (at your option) any later version.
13827+ *
13828+ * This program is distributed in the hope that it will be useful,
13829+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
13830+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13831+ * GNU General Public License for more details.
13832+ *
13833+ * You should have received a copy of the GNU General Public License
13834+ * along with this program; if not, write to the Free Software
13835+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
13836+ */
1facf9fc 13837+
4a4d8108
AM
13838+/*
13839+ * inode functions
13840+ */
1facf9fc 13841+
4a4d8108 13842+#include "aufs.h"
1308ab2a 13843+
4a4d8108
AM
13844+struct inode *au_igrab(struct inode *inode)
13845+{
13846+ if (inode) {
13847+ AuDebugOn(!atomic_read(&inode->i_count));
027c5e7a 13848+ ihold(inode);
1facf9fc 13849+ }
4a4d8108
AM
13850+ return inode;
13851+}
1facf9fc 13852+
4a4d8108
AM
13853+static void au_refresh_hinode_attr(struct inode *inode, int do_version)
13854+{
13855+ au_cpup_attr_all(inode, /*force*/0);
537831f9 13856+ au_update_iigen(inode, /*half*/1);
4a4d8108
AM
13857+ if (do_version)
13858+ inode->i_version++;
dece6358 13859+}
1facf9fc 13860+
027c5e7a 13861+static int au_ii_refresh(struct inode *inode, int *update)
dece6358 13862+{
4a4d8108 13863+ int err, e;
027c5e7a 13864+ umode_t type;
4a4d8108 13865+ aufs_bindex_t bindex, new_bindex;
1308ab2a 13866+ struct super_block *sb;
4a4d8108 13867+ struct au_iinfo *iinfo;
027c5e7a 13868+ struct au_hinode *p, *q, tmp;
1facf9fc 13869+
4a4d8108 13870+ IiMustWriteLock(inode);
1facf9fc 13871+
027c5e7a 13872+ *update = 0;
4a4d8108 13873+ sb = inode->i_sb;
027c5e7a 13874+ type = inode->i_mode & S_IFMT;
4a4d8108
AM
13875+ iinfo = au_ii(inode);
13876+ err = au_ii_realloc(iinfo, au_sbend(sb) + 1);
13877+ if (unlikely(err))
1308ab2a 13878+ goto out;
1facf9fc 13879+
027c5e7a 13880+ AuDebugOn(iinfo->ii_bstart < 0);
4a4d8108 13881+ p = iinfo->ii_hinode + iinfo->ii_bstart;
4a4d8108
AM
13882+ for (bindex = iinfo->ii_bstart; bindex <= iinfo->ii_bend;
13883+ bindex++, p++) {
13884+ if (!p->hi_inode)
13885+ continue;
1facf9fc 13886+
027c5e7a 13887+ AuDebugOn(type != (p->hi_inode->i_mode & S_IFMT));
4a4d8108
AM
13888+ new_bindex = au_br_index(sb, p->hi_id);
13889+ if (new_bindex == bindex)
13890+ continue;
1facf9fc 13891+
4a4d8108 13892+ if (new_bindex < 0) {
027c5e7a 13893+ *update = 1;
4a4d8108
AM
13894+ au_hiput(p);
13895+ p->hi_inode = NULL;
13896+ continue;
1308ab2a 13897+ }
4a4d8108
AM
13898+
13899+ if (new_bindex < iinfo->ii_bstart)
13900+ iinfo->ii_bstart = new_bindex;
13901+ if (iinfo->ii_bend < new_bindex)
13902+ iinfo->ii_bend = new_bindex;
13903+ /* swap two lower inode, and loop again */
13904+ q = iinfo->ii_hinode + new_bindex;
13905+ tmp = *q;
13906+ *q = *p;
13907+ *p = tmp;
13908+ if (tmp.hi_inode) {
13909+ bindex--;
13910+ p--;
1308ab2a 13911+ }
13912+ }
4a4d8108
AM
13913+ au_update_ibrange(inode, /*do_put_zero*/0);
13914+ e = au_dy_irefresh(inode);
13915+ if (unlikely(e && !err))
13916+ err = e;
1facf9fc 13917+
4f0767ce 13918+out:
027c5e7a
AM
13919+ AuTraceErr(err);
13920+ return err;
13921+}
13922+
13923+int au_refresh_hinode_self(struct inode *inode)
13924+{
13925+ int err, update;
13926+
13927+ err = au_ii_refresh(inode, &update);
13928+ if (!err)
13929+ au_refresh_hinode_attr(inode, update && S_ISDIR(inode->i_mode));
13930+
13931+ AuTraceErr(err);
4a4d8108
AM
13932+ return err;
13933+}
1facf9fc 13934+
4a4d8108
AM
13935+int au_refresh_hinode(struct inode *inode, struct dentry *dentry)
13936+{
027c5e7a 13937+ int err, e, update;
4a4d8108 13938+ unsigned int flags;
027c5e7a 13939+ umode_t mode;
4a4d8108 13940+ aufs_bindex_t bindex, bend;
027c5e7a 13941+ unsigned char isdir;
4a4d8108
AM
13942+ struct au_hinode *p;
13943+ struct au_iinfo *iinfo;
1facf9fc 13944+
027c5e7a 13945+ err = au_ii_refresh(inode, &update);
4a4d8108
AM
13946+ if (unlikely(err))
13947+ goto out;
13948+
13949+ update = 0;
13950+ iinfo = au_ii(inode);
13951+ p = iinfo->ii_hinode + iinfo->ii_bstart;
027c5e7a
AM
13952+ mode = (inode->i_mode & S_IFMT);
13953+ isdir = S_ISDIR(mode);
4a4d8108
AM
13954+ flags = au_hi_flags(inode, isdir);
13955+ bend = au_dbend(dentry);
13956+ for (bindex = au_dbstart(dentry); bindex <= bend; bindex++) {
13957+ struct inode *h_i;
13958+ struct dentry *h_d;
13959+
13960+ h_d = au_h_dptr(dentry, bindex);
13961+ if (!h_d || !h_d->d_inode)
13962+ continue;
13963+
027c5e7a 13964+ AuDebugOn(mode != (h_d->d_inode->i_mode & S_IFMT));
4a4d8108
AM
13965+ if (iinfo->ii_bstart <= bindex && bindex <= iinfo->ii_bend) {
13966+ h_i = au_h_iptr(inode, bindex);
13967+ if (h_i) {
13968+ if (h_i == h_d->d_inode)
13969+ continue;
13970+ err = -EIO;
13971+ break;
13972+ }
13973+ }
13974+ if (bindex < iinfo->ii_bstart)
13975+ iinfo->ii_bstart = bindex;
13976+ if (iinfo->ii_bend < bindex)
13977+ iinfo->ii_bend = bindex;
13978+ au_set_h_iptr(inode, bindex, au_igrab(h_d->d_inode), flags);
13979+ update = 1;
1308ab2a 13980+ }
4a4d8108
AM
13981+ au_update_ibrange(inode, /*do_put_zero*/0);
13982+ e = au_dy_irefresh(inode);
13983+ if (unlikely(e && !err))
13984+ err = e;
027c5e7a
AM
13985+ if (!err)
13986+ au_refresh_hinode_attr(inode, update && isdir);
4a4d8108 13987+
4f0767ce 13988+out:
4a4d8108 13989+ AuTraceErr(err);
1308ab2a 13990+ return err;
dece6358
AM
13991+}
13992+
4a4d8108 13993+static int set_inode(struct inode *inode, struct dentry *dentry)
dece6358 13994+{
4a4d8108
AM
13995+ int err;
13996+ unsigned int flags;
13997+ umode_t mode;
13998+ aufs_bindex_t bindex, bstart, btail;
13999+ unsigned char isdir;
14000+ struct dentry *h_dentry;
14001+ struct inode *h_inode;
14002+ struct au_iinfo *iinfo;
dece6358 14003+
4a4d8108 14004+ IiMustWriteLock(inode);
dece6358 14005+
4a4d8108
AM
14006+ err = 0;
14007+ isdir = 0;
14008+ bstart = au_dbstart(dentry);
14009+ h_inode = au_h_dptr(dentry, bstart)->d_inode;
14010+ mode = h_inode->i_mode;
14011+ switch (mode & S_IFMT) {
14012+ case S_IFREG:
14013+ btail = au_dbtail(dentry);
14014+ inode->i_op = &aufs_iop;
14015+ inode->i_fop = &aufs_file_fop;
14016+ err = au_dy_iaop(inode, bstart, h_inode);
14017+ if (unlikely(err))
14018+ goto out;
14019+ break;
14020+ case S_IFDIR:
14021+ isdir = 1;
14022+ btail = au_dbtaildir(dentry);
14023+ inode->i_op = &aufs_dir_iop;
14024+ inode->i_fop = &aufs_dir_fop;
14025+ break;
14026+ case S_IFLNK:
14027+ btail = au_dbtail(dentry);
14028+ inode->i_op = &aufs_symlink_iop;
14029+ break;
14030+ case S_IFBLK:
14031+ case S_IFCHR:
14032+ case S_IFIFO:
14033+ case S_IFSOCK:
14034+ btail = au_dbtail(dentry);
14035+ inode->i_op = &aufs_iop;
14036+ au_init_special_fop(inode, mode, h_inode->i_rdev);
14037+ break;
14038+ default:
14039+ AuIOErr("Unknown file type 0%o\n", mode);
14040+ err = -EIO;
1308ab2a 14041+ goto out;
4a4d8108 14042+ }
dece6358 14043+
4a4d8108
AM
14044+ /* do not set hnotify for whiteouted dirs (SHWH mode) */
14045+ flags = au_hi_flags(inode, isdir);
14046+ if (au_opt_test(au_mntflags(dentry->d_sb), SHWH)
14047+ && au_ftest_hi(flags, HNOTIFY)
14048+ && dentry->d_name.len > AUFS_WH_PFX_LEN
14049+ && !memcmp(dentry->d_name.name, AUFS_WH_PFX, AUFS_WH_PFX_LEN))
14050+ au_fclr_hi(flags, HNOTIFY);
14051+ iinfo = au_ii(inode);
14052+ iinfo->ii_bstart = bstart;
14053+ iinfo->ii_bend = btail;
14054+ for (bindex = bstart; bindex <= btail; bindex++) {
14055+ h_dentry = au_h_dptr(dentry, bindex);
14056+ if (h_dentry)
14057+ au_set_h_iptr(inode, bindex,
14058+ au_igrab(h_dentry->d_inode), flags);
14059+ }
14060+ au_cpup_attr_all(inode, /*force*/1);
dece6358 14061+
4f0767ce 14062+out:
4a4d8108
AM
14063+ return err;
14064+}
dece6358 14065+
027c5e7a
AM
14066+/*
14067+ * successful returns with iinfo write_locked
14068+ * minus: errno
14069+ * zero: success, matched
14070+ * plus: no error, but unmatched
14071+ */
14072+static int reval_inode(struct inode *inode, struct dentry *dentry)
4a4d8108
AM
14073+{
14074+ int err;
537831f9
AM
14075+ unsigned int gen;
14076+ struct au_iigen iigen;
4a4d8108
AM
14077+ aufs_bindex_t bindex, bend;
14078+ struct inode *h_inode, *h_dinode;
dece6358 14079+
4a4d8108
AM
14080+ /*
14081+ * before this function, if aufs got any iinfo lock, it must be only
14082+ * one, the parent dir.
14083+ * it can happen by UDBA and the obsoleted inode number.
14084+ */
14085+ err = -EIO;
14086+ if (unlikely(inode->i_ino == parent_ino(dentry)))
14087+ goto out;
14088+
027c5e7a 14089+ err = 1;
4a4d8108
AM
14090+ ii_write_lock_new_child(inode);
14091+ h_dinode = au_h_dptr(dentry, au_dbstart(dentry))->d_inode;
14092+ bend = au_ibend(inode);
14093+ for (bindex = au_ibstart(inode); bindex <= bend; bindex++) {
14094+ h_inode = au_h_iptr(inode, bindex);
537831f9
AM
14095+ if (!h_inode || h_inode != h_dinode)
14096+ continue;
14097+
14098+ err = 0;
14099+ gen = au_iigen(inode, &iigen);
14100+ if (gen == au_digen(dentry)
14101+ && !au_ig_ftest(iigen.ig_flags, HALF_REFRESHED))
4a4d8108 14102+ break;
537831f9
AM
14103+
14104+ /* fully refresh inode using dentry */
14105+ err = au_refresh_hinode(inode, dentry);
14106+ if (!err)
14107+ au_update_iigen(inode, /*half*/0);
14108+ break;
1facf9fc 14109+ }
dece6358 14110+
4a4d8108
AM
14111+ if (unlikely(err))
14112+ ii_write_unlock(inode);
4f0767ce 14113+out:
1facf9fc 14114+ return err;
14115+}
1facf9fc 14116+
4a4d8108
AM
14117+int au_ino(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino,
14118+ unsigned int d_type, ino_t *ino)
1facf9fc 14119+{
4a4d8108
AM
14120+ int err;
14121+ struct mutex *mtx;
1facf9fc 14122+
b752ccd1 14123+ /* prevent hardlinked inode number from race condition */
4a4d8108 14124+ mtx = NULL;
b752ccd1 14125+ if (d_type != DT_DIR) {
4a4d8108
AM
14126+ mtx = &au_sbr(sb, bindex)->br_xino.xi_nondir_mtx;
14127+ mutex_lock(mtx);
14128+ }
14129+ err = au_xino_read(sb, bindex, h_ino, ino);
14130+ if (unlikely(err))
14131+ goto out;
1308ab2a 14132+
4a4d8108
AM
14133+ if (!*ino) {
14134+ err = -EIO;
14135+ *ino = au_xino_new_ino(sb);
14136+ if (unlikely(!*ino))
1facf9fc 14137+ goto out;
4a4d8108
AM
14138+ err = au_xino_write(sb, bindex, h_ino, *ino);
14139+ if (unlikely(err))
1308ab2a 14140+ goto out;
1308ab2a 14141+ }
1facf9fc 14142+
4f0767ce 14143+out:
b752ccd1 14144+ if (mtx)
4a4d8108 14145+ mutex_unlock(mtx);
1facf9fc 14146+ return err;
14147+}
14148+
4a4d8108
AM
14149+/* successful returns with iinfo write_locked */
14150+/* todo: return with unlocked? */
14151+struct inode *au_new_inode(struct dentry *dentry, int must_new)
1facf9fc 14152+{
b752ccd1 14153+ struct inode *inode, *h_inode;
4a4d8108
AM
14154+ struct dentry *h_dentry;
14155+ struct super_block *sb;
b752ccd1 14156+ struct mutex *mtx;
4a4d8108 14157+ ino_t h_ino, ino;
2dfbb274 14158+ int err, lc_idx;
4a4d8108 14159+ aufs_bindex_t bstart;
1facf9fc 14160+
4a4d8108
AM
14161+ sb = dentry->d_sb;
14162+ bstart = au_dbstart(dentry);
14163+ h_dentry = au_h_dptr(dentry, bstart);
b752ccd1
AM
14164+ h_inode = h_dentry->d_inode;
14165+ h_ino = h_inode->i_ino;
14166+
14167+ /*
14168+ * stop 'race'-ing between hardlinks under different
14169+ * parents.
14170+ */
14171+ mtx = NULL;
14172+ if (!S_ISDIR(h_inode->i_mode))
14173+ mtx = &au_sbr(sb, bstart)->br_xino.xi_nondir_mtx;
14174+
4f0767ce 14175+new_ino:
b752ccd1
AM
14176+ if (mtx)
14177+ mutex_lock(mtx);
4a4d8108
AM
14178+ err = au_xino_read(sb, bstart, h_ino, &ino);
14179+ inode = ERR_PTR(err);
14180+ if (unlikely(err))
14181+ goto out;
b752ccd1 14182+
4a4d8108
AM
14183+ if (!ino) {
14184+ ino = au_xino_new_ino(sb);
14185+ if (unlikely(!ino)) {
14186+ inode = ERR_PTR(-EIO);
dece6358
AM
14187+ goto out;
14188+ }
14189+ }
1facf9fc 14190+
4a4d8108
AM
14191+ AuDbg("i%lu\n", (unsigned long)ino);
14192+ inode = au_iget_locked(sb, ino);
14193+ err = PTR_ERR(inode);
14194+ if (IS_ERR(inode))
1facf9fc 14195+ goto out;
1facf9fc 14196+
4a4d8108
AM
14197+ AuDbg("%lx, new %d\n", inode->i_state, !!(inode->i_state & I_NEW));
14198+ if (inode->i_state & I_NEW) {
2dfbb274
AM
14199+ lc_idx = AuLcNonDir_IIINFO;
14200+ if (S_ISLNK(h_inode->i_mode))
14201+ lc_idx = AuLcSymlink_IIINFO;
14202+ else if (S_ISDIR(h_inode->i_mode))
14203+ lc_idx = AuLcDir_IIINFO;
14204+ au_rw_class(&au_ii(inode)->ii_rwsem, au_lc_key + lc_idx);
14205+
4a4d8108
AM
14206+ ii_write_lock_new_child(inode);
14207+ err = set_inode(inode, dentry);
14208+ if (!err) {
14209+ unlock_new_inode(inode);
14210+ goto out; /* success */
14211+ }
1308ab2a 14212+
027c5e7a
AM
14213+ /*
14214+ * iget_failed() calls iput(), but we need to call
14215+ * ii_write_unlock() after iget_failed(). so dirty hack for
14216+ * i_count.
14217+ */
14218+ atomic_inc(&inode->i_count);
4a4d8108 14219+ iget_failed(inode);
027c5e7a
AM
14220+ ii_write_unlock(inode);
14221+ au_xino_write(sb, bstart, h_ino, /*ino*/0);
14222+ /* ignore this error */
14223+ goto out_iput;
14224+ } else if (!must_new && !IS_DEADDIR(inode) && inode->i_nlink) {
b752ccd1
AM
14225+ /*
14226+ * horrible race condition between lookup, readdir and copyup
14227+ * (or something).
14228+ */
14229+ if (mtx)
14230+ mutex_unlock(mtx);
027c5e7a
AM
14231+ err = reval_inode(inode, dentry);
14232+ if (unlikely(err < 0)) {
14233+ mtx = NULL;
14234+ goto out_iput;
14235+ }
14236+
b752ccd1
AM
14237+ if (!err) {
14238+ mtx = NULL;
4a4d8108 14239+ goto out; /* success */
b752ccd1
AM
14240+ } else if (mtx)
14241+ mutex_lock(mtx);
4a4d8108
AM
14242+ }
14243+
14244+ if (unlikely(au_test_fs_unique_ino(h_dentry->d_inode)))
14245+ AuWarn1("Warning: Un-notified UDBA or repeatedly renamed dir,"
14246+ " b%d, %s, %.*s, hi%lu, i%lu.\n",
14247+ bstart, au_sbtype(h_dentry->d_sb), AuDLNPair(dentry),
14248+ (unsigned long)h_ino, (unsigned long)ino);
14249+ ino = 0;
14250+ err = au_xino_write(sb, bstart, h_ino, /*ino*/0);
14251+ if (!err) {
14252+ iput(inode);
b752ccd1
AM
14253+ if (mtx)
14254+ mutex_unlock(mtx);
4a4d8108
AM
14255+ goto new_ino;
14256+ }
1308ab2a 14257+
4f0767ce 14258+out_iput:
4a4d8108 14259+ iput(inode);
4a4d8108 14260+ inode = ERR_PTR(err);
4f0767ce 14261+out:
b752ccd1
AM
14262+ if (mtx)
14263+ mutex_unlock(mtx);
4a4d8108 14264+ return inode;
1facf9fc 14265+}
14266+
4a4d8108 14267+/* ---------------------------------------------------------------------- */
1facf9fc 14268+
4a4d8108
AM
14269+int au_test_ro(struct super_block *sb, aufs_bindex_t bindex,
14270+ struct inode *inode)
14271+{
14272+ int err;
1facf9fc 14273+
4a4d8108 14274+ err = au_br_rdonly(au_sbr(sb, bindex));
1facf9fc 14275+
4a4d8108
AM
14276+ /* pseudo-link after flushed may happen out of bounds */
14277+ if (!err
14278+ && inode
14279+ && au_ibstart(inode) <= bindex
14280+ && bindex <= au_ibend(inode)) {
14281+ /*
14282+ * permission check is unnecessary since vfsub routine
14283+ * will be called later
14284+ */
14285+ struct inode *hi = au_h_iptr(inode, bindex);
14286+ if (hi)
14287+ err = IS_IMMUTABLE(hi) ? -EROFS : 0;
1facf9fc 14288+ }
14289+
4a4d8108
AM
14290+ return err;
14291+}
dece6358 14292+
4a4d8108
AM
14293+int au_test_h_perm(struct inode *h_inode, int mask)
14294+{
2dfbb274 14295+ if (uid_eq(current_fsuid(), GLOBAL_ROOT_UID))
4a4d8108
AM
14296+ return 0;
14297+ return inode_permission(h_inode, mask);
14298+}
1facf9fc 14299+
4a4d8108
AM
14300+int au_test_h_perm_sio(struct inode *h_inode, int mask)
14301+{
14302+ if (au_test_nfs(h_inode->i_sb)
14303+ && (mask & MAY_WRITE)
14304+ && S_ISDIR(h_inode->i_mode))
14305+ mask |= MAY_READ; /* force permission check */
14306+ return au_test_h_perm(h_inode, mask);
1facf9fc 14307+}
7f207e10
AM
14308diff -urN /usr/share/empty/fs/aufs/inode.h linux/fs/aufs/inode.h
14309--- /usr/share/empty/fs/aufs/inode.h 1970-01-01 01:00:00.000000000 +0100
537831f9
AM
14310+++ linux/fs/aufs/inode.h 2012-12-13 20:41:10.431460173 +0100
14311@@ -0,0 +1,588 @@
4a4d8108 14312+/*
f6c5ef8b 14313+ * Copyright (C) 2005-2012 Junjiro R. Okajima
4a4d8108
AM
14314+ *
14315+ * This program, aufs is free software; you can redistribute it and/or modify
14316+ * it under the terms of the GNU General Public License as published by
14317+ * the Free Software Foundation; either version 2 of the License, or
14318+ * (at your option) any later version.
14319+ *
14320+ * This program is distributed in the hope that it will be useful,
14321+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
14322+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14323+ * GNU General Public License for more details.
14324+ *
14325+ * You should have received a copy of the GNU General Public License
14326+ * along with this program; if not, write to the Free Software
14327+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
14328+ */
1facf9fc 14329+
1308ab2a 14330+/*
4a4d8108 14331+ * inode operations
1308ab2a 14332+ */
dece6358 14333+
4a4d8108
AM
14334+#ifndef __AUFS_INODE_H__
14335+#define __AUFS_INODE_H__
dece6358 14336+
4a4d8108 14337+#ifdef __KERNEL__
1308ab2a 14338+
4a4d8108 14339+#include <linux/fsnotify.h>
4a4d8108 14340+#include "rwsem.h"
1308ab2a 14341+
4a4d8108 14342+struct vfsmount;
1facf9fc 14343+
4a4d8108
AM
14344+struct au_hnotify {
14345+#ifdef CONFIG_AUFS_HNOTIFY
14346+#ifdef CONFIG_AUFS_HFSNOTIFY
7f207e10 14347+ /* never use fsnotify_add_vfsmount_mark() */
0c5527e5 14348+ struct fsnotify_mark hn_mark;
4a4d8108 14349+#endif
7f207e10 14350+ struct inode *hn_aufs_inode; /* no get/put */
4a4d8108
AM
14351+#endif
14352+} ____cacheline_aligned_in_smp;
1facf9fc 14353+
4a4d8108
AM
14354+struct au_hinode {
14355+ struct inode *hi_inode;
14356+ aufs_bindex_t hi_id;
14357+#ifdef CONFIG_AUFS_HNOTIFY
14358+ struct au_hnotify *hi_notify;
14359+#endif
dece6358 14360+
4a4d8108
AM
14361+ /* reference to the copied-up whiteout with get/put */
14362+ struct dentry *hi_whdentry;
14363+};
dece6358 14364+
537831f9
AM
14365+/* ig_flags */
14366+#define AuIG_HALF_REFRESHED 1
14367+#define au_ig_ftest(flags, name) ((flags) & AuIG_##name)
14368+#define au_ig_fset(flags, name) \
14369+ do { (flags) |= AuIG_##name; } while (0)
14370+#define au_ig_fclr(flags, name) \
14371+ do { (flags) &= ~AuIG_##name; } while (0)
14372+
14373+struct au_iigen {
14374+ __u32 ig_generation, ig_flags;
14375+};
14376+
4a4d8108
AM
14377+struct au_vdir;
14378+struct au_iinfo {
537831f9
AM
14379+ spinlock_t ii_genspin;
14380+ struct au_iigen ii_generation;
4a4d8108 14381+ struct super_block *ii_hsb1; /* no get/put */
1facf9fc 14382+
4a4d8108
AM
14383+ struct au_rwsem ii_rwsem;
14384+ aufs_bindex_t ii_bstart, ii_bend;
14385+ __u32 ii_higen;
14386+ struct au_hinode *ii_hinode;
14387+ struct au_vdir *ii_vdir;
14388+};
1facf9fc 14389+
4a4d8108
AM
14390+struct au_icntnr {
14391+ struct au_iinfo iinfo;
14392+ struct inode vfs_inode;
14393+} ____cacheline_aligned_in_smp;
1308ab2a 14394+
4a4d8108
AM
14395+/* au_pin flags */
14396+#define AuPin_DI_LOCKED 1
14397+#define AuPin_MNT_WRITE (1 << 1)
14398+#define au_ftest_pin(flags, name) ((flags) & AuPin_##name)
7f207e10
AM
14399+#define au_fset_pin(flags, name) \
14400+ do { (flags) |= AuPin_##name; } while (0)
14401+#define au_fclr_pin(flags, name) \
14402+ do { (flags) &= ~AuPin_##name; } while (0)
4a4d8108
AM
14403+
14404+struct au_pin {
14405+ /* input */
14406+ struct dentry *dentry;
14407+ unsigned int udba;
14408+ unsigned char lsc_di, lsc_hi, flags;
14409+ aufs_bindex_t bindex;
14410+
14411+ /* output */
14412+ struct dentry *parent;
14413+ struct au_hinode *hdir;
14414+ struct vfsmount *h_mnt;
14415+};
1facf9fc 14416+
1308ab2a 14417+/* ---------------------------------------------------------------------- */
14418+
4a4d8108 14419+static inline struct au_iinfo *au_ii(struct inode *inode)
1facf9fc 14420+{
4a4d8108 14421+ struct au_iinfo *iinfo;
1facf9fc 14422+
4a4d8108
AM
14423+ iinfo = &(container_of(inode, struct au_icntnr, vfs_inode)->iinfo);
14424+ if (iinfo->ii_hinode)
14425+ return iinfo;
14426+ return NULL; /* debugging bad_inode case */
14427+}
1facf9fc 14428+
4a4d8108 14429+/* ---------------------------------------------------------------------- */
1facf9fc 14430+
4a4d8108
AM
14431+/* inode.c */
14432+struct inode *au_igrab(struct inode *inode);
027c5e7a 14433+int au_refresh_hinode_self(struct inode *inode);
4a4d8108
AM
14434+int au_refresh_hinode(struct inode *inode, struct dentry *dentry);
14435+int au_ino(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino,
14436+ unsigned int d_type, ino_t *ino);
14437+struct inode *au_new_inode(struct dentry *dentry, int must_new);
14438+int au_test_ro(struct super_block *sb, aufs_bindex_t bindex,
14439+ struct inode *inode);
14440+int au_test_h_perm(struct inode *h_inode, int mask);
14441+int au_test_h_perm_sio(struct inode *h_inode, int mask);
1facf9fc 14442+
4a4d8108
AM
14443+static inline int au_wh_ino(struct super_block *sb, aufs_bindex_t bindex,
14444+ ino_t h_ino, unsigned int d_type, ino_t *ino)
14445+{
14446+#ifdef CONFIG_AUFS_SHWH
14447+ return au_ino(sb, bindex, h_ino, d_type, ino);
14448+#else
14449+ return 0;
14450+#endif
14451+}
1facf9fc 14452+
4a4d8108
AM
14453+/* i_op.c */
14454+extern struct inode_operations aufs_iop, aufs_symlink_iop, aufs_dir_iop;
1308ab2a 14455+
4a4d8108
AM
14456+/* au_wr_dir flags */
14457+#define AuWrDir_ADD_ENTRY 1
14458+#define AuWrDir_ISDIR (1 << 1)
14459+#define au_ftest_wrdir(flags, name) ((flags) & AuWrDir_##name)
7f207e10
AM
14460+#define au_fset_wrdir(flags, name) \
14461+ do { (flags) |= AuWrDir_##name; } while (0)
14462+#define au_fclr_wrdir(flags, name) \
14463+ do { (flags) &= ~AuWrDir_##name; } while (0)
1facf9fc 14464+
4a4d8108
AM
14465+struct au_wr_dir_args {
14466+ aufs_bindex_t force_btgt;
14467+ unsigned char flags;
14468+};
14469+int au_wr_dir(struct dentry *dentry, struct dentry *src_dentry,
14470+ struct au_wr_dir_args *args);
dece6358 14471+
4a4d8108
AM
14472+struct dentry *au_pinned_h_parent(struct au_pin *pin);
14473+void au_pin_init(struct au_pin *pin, struct dentry *dentry,
14474+ aufs_bindex_t bindex, int lsc_di, int lsc_hi,
14475+ unsigned int udba, unsigned char flags);
14476+int au_pin(struct au_pin *pin, struct dentry *dentry, aufs_bindex_t bindex,
14477+ unsigned int udba, unsigned char flags) __must_check;
14478+int au_do_pin(struct au_pin *pin) __must_check;
14479+void au_unpin(struct au_pin *pin);
1facf9fc 14480+
4a4d8108
AM
14481+/* i_op_add.c */
14482+int au_may_add(struct dentry *dentry, aufs_bindex_t bindex,
14483+ struct dentry *h_parent, int isdir);
7eafdf33
AM
14484+int aufs_mknod(struct inode *dir, struct dentry *dentry, umode_t mode,
14485+ dev_t dev);
4a4d8108 14486+int aufs_symlink(struct inode *dir, struct dentry *dentry, const char *symname);
7eafdf33 14487+int aufs_create(struct inode *dir, struct dentry *dentry, umode_t mode,
b4510431 14488+ bool want_excl);
4a4d8108
AM
14489+int aufs_link(struct dentry *src_dentry, struct inode *dir,
14490+ struct dentry *dentry);
7eafdf33 14491+int aufs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode);
1facf9fc 14492+
4a4d8108
AM
14493+/* i_op_del.c */
14494+int au_wr_dir_need_wh(struct dentry *dentry, int isdir, aufs_bindex_t *bcpup);
14495+int au_may_del(struct dentry *dentry, aufs_bindex_t bindex,
14496+ struct dentry *h_parent, int isdir);
14497+int aufs_unlink(struct inode *dir, struct dentry *dentry);
14498+int aufs_rmdir(struct inode *dir, struct dentry *dentry);
1308ab2a 14499+
4a4d8108
AM
14500+/* i_op_ren.c */
14501+int au_wbr(struct dentry *dentry, aufs_bindex_t btgt);
14502+int aufs_rename(struct inode *src_dir, struct dentry *src_dentry,
14503+ struct inode *dir, struct dentry *dentry);
1facf9fc 14504+
4a4d8108
AM
14505+/* iinfo.c */
14506+struct inode *au_h_iptr(struct inode *inode, aufs_bindex_t bindex);
14507+void au_hiput(struct au_hinode *hinode);
14508+void au_set_hi_wh(struct inode *inode, aufs_bindex_t bindex,
14509+ struct dentry *h_wh);
14510+unsigned int au_hi_flags(struct inode *inode, int isdir);
1308ab2a 14511+
4a4d8108
AM
14512+/* hinode flags */
14513+#define AuHi_XINO 1
14514+#define AuHi_HNOTIFY (1 << 1)
14515+#define au_ftest_hi(flags, name) ((flags) & AuHi_##name)
7f207e10
AM
14516+#define au_fset_hi(flags, name) \
14517+ do { (flags) |= AuHi_##name; } while (0)
14518+#define au_fclr_hi(flags, name) \
14519+ do { (flags) &= ~AuHi_##name; } while (0)
1facf9fc 14520+
4a4d8108
AM
14521+#ifndef CONFIG_AUFS_HNOTIFY
14522+#undef AuHi_HNOTIFY
14523+#define AuHi_HNOTIFY 0
14524+#endif
1facf9fc 14525+
4a4d8108
AM
14526+void au_set_h_iptr(struct inode *inode, aufs_bindex_t bindex,
14527+ struct inode *h_inode, unsigned int flags);
1facf9fc 14528+
537831f9 14529+void au_update_iigen(struct inode *inode, int half);
4a4d8108 14530+void au_update_ibrange(struct inode *inode, int do_put_zero);
1facf9fc 14531+
4a4d8108
AM
14532+void au_icntnr_init_once(void *_c);
14533+int au_iinfo_init(struct inode *inode);
14534+void au_iinfo_fin(struct inode *inode);
14535+int au_ii_realloc(struct au_iinfo *iinfo, int nbr);
1308ab2a 14536+
e49829fe 14537+#ifdef CONFIG_PROC_FS
4a4d8108 14538+/* plink.c */
e49829fe
JR
14539+int au_plink_maint(struct super_block *sb, int flags);
14540+void au_plink_maint_leave(struct au_sbinfo *sbinfo);
14541+int au_plink_maint_enter(struct super_block *sb);
4a4d8108
AM
14542+#ifdef CONFIG_AUFS_DEBUG
14543+void au_plink_list(struct super_block *sb);
14544+#else
14545+AuStubVoid(au_plink_list, struct super_block *sb)
14546+#endif
14547+int au_plink_test(struct inode *inode);
14548+struct dentry *au_plink_lkup(struct inode *inode, aufs_bindex_t bindex);
14549+void au_plink_append(struct inode *inode, aufs_bindex_t bindex,
14550+ struct dentry *h_dentry);
e49829fe
JR
14551+void au_plink_put(struct super_block *sb, int verbose);
14552+void au_plink_clean(struct super_block *sb, int verbose);
4a4d8108 14553+void au_plink_half_refresh(struct super_block *sb, aufs_bindex_t br_id);
e49829fe
JR
14554+#else
14555+AuStubInt0(au_plink_maint, struct super_block *sb, int flags);
14556+AuStubVoid(au_plink_maint_leave, struct au_sbinfo *sbinfo);
14557+AuStubInt0(au_plink_maint_enter, struct super_block *sb);
14558+AuStubVoid(au_plink_list, struct super_block *sb);
14559+AuStubInt0(au_plink_test, struct inode *inode);
14560+AuStub(struct dentry *, au_plink_lkup, return NULL,
14561+ struct inode *inode, aufs_bindex_t bindex);
14562+AuStubVoid(au_plink_append, struct inode *inode, aufs_bindex_t bindex,
14563+ struct dentry *h_dentry);
14564+AuStubVoid(au_plink_put, struct super_block *sb, int verbose);
14565+AuStubVoid(au_plink_clean, struct super_block *sb, int verbose);
14566+AuStubVoid(au_plink_half_refresh, struct super_block *sb, aufs_bindex_t br_id);
14567+#endif /* CONFIG_PROC_FS */
1facf9fc 14568+
4a4d8108 14569+/* ---------------------------------------------------------------------- */
1308ab2a 14570+
4a4d8108
AM
14571+/* lock subclass for iinfo */
14572+enum {
14573+ AuLsc_II_CHILD, /* child first */
14574+ AuLsc_II_CHILD2, /* rename(2), link(2), and cpup at hnotify */
14575+ AuLsc_II_CHILD3, /* copyup dirs */
14576+ AuLsc_II_PARENT, /* see AuLsc_I_PARENT in vfsub.h */
14577+ AuLsc_II_PARENT2,
14578+ AuLsc_II_PARENT3, /* copyup dirs */
14579+ AuLsc_II_NEW_CHILD
14580+};
1308ab2a 14581+
1facf9fc 14582+/*
4a4d8108
AM
14583+ * ii_read_lock_child, ii_write_lock_child,
14584+ * ii_read_lock_child2, ii_write_lock_child2,
14585+ * ii_read_lock_child3, ii_write_lock_child3,
14586+ * ii_read_lock_parent, ii_write_lock_parent,
14587+ * ii_read_lock_parent2, ii_write_lock_parent2,
14588+ * ii_read_lock_parent3, ii_write_lock_parent3,
14589+ * ii_read_lock_new_child, ii_write_lock_new_child,
1facf9fc 14590+ */
4a4d8108
AM
14591+#define AuReadLockFunc(name, lsc) \
14592+static inline void ii_read_lock_##name(struct inode *i) \
14593+{ \
14594+ au_rw_read_lock_nested(&au_ii(i)->ii_rwsem, AuLsc_II_##lsc); \
14595+}
14596+
14597+#define AuWriteLockFunc(name, lsc) \
14598+static inline void ii_write_lock_##name(struct inode *i) \
14599+{ \
14600+ au_rw_write_lock_nested(&au_ii(i)->ii_rwsem, AuLsc_II_##lsc); \
14601+}
14602+
14603+#define AuRWLockFuncs(name, lsc) \
14604+ AuReadLockFunc(name, lsc) \
14605+ AuWriteLockFunc(name, lsc)
14606+
14607+AuRWLockFuncs(child, CHILD);
14608+AuRWLockFuncs(child2, CHILD2);
14609+AuRWLockFuncs(child3, CHILD3);
14610+AuRWLockFuncs(parent, PARENT);
14611+AuRWLockFuncs(parent2, PARENT2);
14612+AuRWLockFuncs(parent3, PARENT3);
14613+AuRWLockFuncs(new_child, NEW_CHILD);
14614+
14615+#undef AuReadLockFunc
14616+#undef AuWriteLockFunc
14617+#undef AuRWLockFuncs
1facf9fc 14618+
14619+/*
4a4d8108 14620+ * ii_read_unlock, ii_write_unlock, ii_downgrade_lock
1facf9fc 14621+ */
4a4d8108 14622+AuSimpleUnlockRwsemFuncs(ii, struct inode *i, &au_ii(i)->ii_rwsem);
1facf9fc 14623+
4a4d8108
AM
14624+#define IiMustNoWaiters(i) AuRwMustNoWaiters(&au_ii(i)->ii_rwsem)
14625+#define IiMustAnyLock(i) AuRwMustAnyLock(&au_ii(i)->ii_rwsem)
14626+#define IiMustWriteLock(i) AuRwMustWriteLock(&au_ii(i)->ii_rwsem)
1facf9fc 14627+
4a4d8108 14628+/* ---------------------------------------------------------------------- */
1308ab2a 14629+
027c5e7a
AM
14630+static inline void au_icntnr_init(struct au_icntnr *c)
14631+{
14632+#ifdef CONFIG_AUFS_DEBUG
14633+ c->vfs_inode.i_mode = 0;
14634+#endif
14635+}
14636+
537831f9 14637+static inline unsigned int au_iigen(struct inode *inode, struct au_iigen *iigen)
4a4d8108 14638+{
537831f9
AM
14639+ unsigned int gen;
14640+ struct au_iinfo *iinfo;
14641+
14642+ iinfo = au_ii(inode);
14643+ spin_lock(&iinfo->ii_genspin);
14644+ if (iigen)
14645+ *iigen = iinfo->ii_generation;
14646+ gen = iinfo->ii_generation.ig_generation;
14647+ spin_unlock(&iinfo->ii_genspin);
14648+
14649+ return gen;
4a4d8108 14650+}
1308ab2a 14651+
4a4d8108
AM
14652+/* tiny test for inode number */
14653+/* tmpfs generation is too rough */
14654+static inline int au_test_higen(struct inode *inode, struct inode *h_inode)
14655+{
14656+ struct au_iinfo *iinfo;
1308ab2a 14657+
4a4d8108
AM
14658+ iinfo = au_ii(inode);
14659+ AuRwMustAnyLock(&iinfo->ii_rwsem);
14660+ return !(iinfo->ii_hsb1 == h_inode->i_sb
14661+ && iinfo->ii_higen == h_inode->i_generation);
14662+}
1308ab2a 14663+
4a4d8108
AM
14664+static inline void au_iigen_dec(struct inode *inode)
14665+{
537831f9
AM
14666+ struct au_iinfo *iinfo;
14667+
14668+ iinfo = au_ii(inode);
14669+ spin_lock(&iinfo->ii_genspin);
14670+ iinfo->ii_generation.ig_generation--;
14671+ spin_unlock(&iinfo->ii_genspin);
027c5e7a
AM
14672+}
14673+
14674+static inline int au_iigen_test(struct inode *inode, unsigned int sigen)
14675+{
14676+ int err;
14677+
14678+ err = 0;
537831f9 14679+ if (unlikely(inode && au_iigen(inode, NULL) != sigen))
027c5e7a
AM
14680+ err = -EIO;
14681+
14682+ return err;
4a4d8108 14683+}
1308ab2a 14684+
4a4d8108 14685+/* ---------------------------------------------------------------------- */
1308ab2a 14686+
4a4d8108
AM
14687+static inline aufs_bindex_t au_ii_br_id(struct inode *inode,
14688+ aufs_bindex_t bindex)
14689+{
14690+ IiMustAnyLock(inode);
14691+ return au_ii(inode)->ii_hinode[0 + bindex].hi_id;
14692+}
1308ab2a 14693+
4a4d8108
AM
14694+static inline aufs_bindex_t au_ibstart(struct inode *inode)
14695+{
14696+ IiMustAnyLock(inode);
14697+ return au_ii(inode)->ii_bstart;
14698+}
1308ab2a 14699+
4a4d8108
AM
14700+static inline aufs_bindex_t au_ibend(struct inode *inode)
14701+{
14702+ IiMustAnyLock(inode);
14703+ return au_ii(inode)->ii_bend;
14704+}
1308ab2a 14705+
4a4d8108
AM
14706+static inline struct au_vdir *au_ivdir(struct inode *inode)
14707+{
14708+ IiMustAnyLock(inode);
14709+ return au_ii(inode)->ii_vdir;
14710+}
1308ab2a 14711+
4a4d8108
AM
14712+static inline struct dentry *au_hi_wh(struct inode *inode, aufs_bindex_t bindex)
14713+{
14714+ IiMustAnyLock(inode);
14715+ return au_ii(inode)->ii_hinode[0 + bindex].hi_whdentry;
14716+}
1308ab2a 14717+
4a4d8108 14718+static inline void au_set_ibstart(struct inode *inode, aufs_bindex_t bindex)
1308ab2a 14719+{
4a4d8108
AM
14720+ IiMustWriteLock(inode);
14721+ au_ii(inode)->ii_bstart = bindex;
14722+}
1308ab2a 14723+
4a4d8108
AM
14724+static inline void au_set_ibend(struct inode *inode, aufs_bindex_t bindex)
14725+{
14726+ IiMustWriteLock(inode);
14727+ au_ii(inode)->ii_bend = bindex;
1308ab2a 14728+}
14729+
4a4d8108
AM
14730+static inline void au_set_ivdir(struct inode *inode, struct au_vdir *vdir)
14731+{
14732+ IiMustWriteLock(inode);
14733+ au_ii(inode)->ii_vdir = vdir;
14734+}
1facf9fc 14735+
4a4d8108 14736+static inline struct au_hinode *au_hi(struct inode *inode, aufs_bindex_t bindex)
1308ab2a 14737+{
4a4d8108
AM
14738+ IiMustAnyLock(inode);
14739+ return au_ii(inode)->ii_hinode + bindex;
14740+}
dece6358 14741+
4a4d8108 14742+/* ---------------------------------------------------------------------- */
1facf9fc 14743+
4a4d8108
AM
14744+static inline struct dentry *au_pinned_parent(struct au_pin *pin)
14745+{
14746+ if (pin)
14747+ return pin->parent;
14748+ return NULL;
1facf9fc 14749+}
14750+
4a4d8108 14751+static inline struct inode *au_pinned_h_dir(struct au_pin *pin)
1facf9fc 14752+{
4a4d8108
AM
14753+ if (pin && pin->hdir)
14754+ return pin->hdir->hi_inode;
14755+ return NULL;
1308ab2a 14756+}
1facf9fc 14757+
4a4d8108
AM
14758+static inline struct au_hinode *au_pinned_hdir(struct au_pin *pin)
14759+{
14760+ if (pin)
14761+ return pin->hdir;
14762+ return NULL;
14763+}
1facf9fc 14764+
4a4d8108 14765+static inline void au_pin_set_dentry(struct au_pin *pin, struct dentry *dentry)
1308ab2a 14766+{
4a4d8108
AM
14767+ if (pin)
14768+ pin->dentry = dentry;
14769+}
1308ab2a 14770+
4a4d8108
AM
14771+static inline void au_pin_set_parent_lflag(struct au_pin *pin,
14772+ unsigned char lflag)
14773+{
14774+ if (pin) {
7f207e10 14775+ if (lflag)
4a4d8108 14776+ au_fset_pin(pin->flags, DI_LOCKED);
7f207e10 14777+ else
4a4d8108 14778+ au_fclr_pin(pin->flags, DI_LOCKED);
1308ab2a 14779+ }
4a4d8108
AM
14780+}
14781+
14782+static inline void au_pin_set_parent(struct au_pin *pin, struct dentry *parent)
14783+{
14784+ if (pin) {
14785+ dput(pin->parent);
14786+ pin->parent = dget(parent);
1facf9fc 14787+ }
4a4d8108 14788+}
1facf9fc 14789+
4a4d8108
AM
14790+/* ---------------------------------------------------------------------- */
14791+
027c5e7a 14792+struct au_branch;
4a4d8108
AM
14793+#ifdef CONFIG_AUFS_HNOTIFY
14794+struct au_hnotify_op {
14795+ void (*ctl)(struct au_hinode *hinode, int do_set);
027c5e7a 14796+ int (*alloc)(struct au_hinode *hinode);
7eafdf33
AM
14797+
14798+ /*
14799+ * if it returns true, the the caller should free hinode->hi_notify,
14800+ * otherwise ->free() frees it.
14801+ */
14802+ int (*free)(struct au_hinode *hinode,
14803+ struct au_hnotify *hn) __must_check;
4a4d8108
AM
14804+
14805+ void (*fin)(void);
14806+ int (*init)(void);
027c5e7a
AM
14807+
14808+ int (*reset_br)(unsigned int udba, struct au_branch *br, int perm);
14809+ void (*fin_br)(struct au_branch *br);
14810+ int (*init_br)(struct au_branch *br, int perm);
4a4d8108
AM
14811+};
14812+
14813+/* hnotify.c */
027c5e7a 14814+int au_hn_alloc(struct au_hinode *hinode, struct inode *inode);
4a4d8108
AM
14815+void au_hn_free(struct au_hinode *hinode);
14816+void au_hn_ctl(struct au_hinode *hinode, int do_set);
14817+void au_hn_reset(struct inode *inode, unsigned int flags);
14818+int au_hnotify(struct inode *h_dir, struct au_hnotify *hnotify, u32 mask,
14819+ struct qstr *h_child_qstr, struct inode *h_child_inode);
027c5e7a
AM
14820+int au_hnotify_reset_br(unsigned int udba, struct au_branch *br, int perm);
14821+int au_hnotify_init_br(struct au_branch *br, int perm);
14822+void au_hnotify_fin_br(struct au_branch *br);
4a4d8108
AM
14823+int __init au_hnotify_init(void);
14824+void au_hnotify_fin(void);
14825+
7f207e10 14826+/* hfsnotify.c */
4a4d8108
AM
14827+extern const struct au_hnotify_op au_hnotify_op;
14828+
14829+static inline
14830+void au_hn_init(struct au_hinode *hinode)
14831+{
14832+ hinode->hi_notify = NULL;
1308ab2a 14833+}
14834+
53392da6
AM
14835+static inline struct au_hnotify *au_hn(struct au_hinode *hinode)
14836+{
14837+ return hinode->hi_notify;
14838+}
14839+
4a4d8108
AM
14840+#else
14841+static inline
14842+int au_hn_alloc(struct au_hinode *hinode __maybe_unused,
027c5e7a 14843+ struct inode *inode __maybe_unused)
1308ab2a 14844+{
4a4d8108
AM
14845+ return -EOPNOTSUPP;
14846+}
1308ab2a 14847+
53392da6
AM
14848+static inline struct au_hnotify *au_hn(struct au_hinode *hinode)
14849+{
14850+ return NULL;
14851+}
14852+
4a4d8108
AM
14853+AuStubVoid(au_hn_free, struct au_hinode *hinode __maybe_unused)
14854+AuStubVoid(au_hn_ctl, struct au_hinode *hinode __maybe_unused,
14855+ int do_set __maybe_unused)
14856+AuStubVoid(au_hn_reset, struct inode *inode __maybe_unused,
14857+ unsigned int flags __maybe_unused)
027c5e7a
AM
14858+AuStubInt0(au_hnotify_reset_br, unsigned int udba __maybe_unused,
14859+ struct au_branch *br __maybe_unused,
14860+ int perm __maybe_unused)
14861+AuStubInt0(au_hnotify_init_br, struct au_branch *br __maybe_unused,
14862+ int perm __maybe_unused)
14863+AuStubVoid(au_hnotify_fin_br, struct au_branch *br __maybe_unused)
4a4d8108
AM
14864+AuStubInt0(__init au_hnotify_init, void)
14865+AuStubVoid(au_hnotify_fin, void)
14866+AuStubVoid(au_hn_init, struct au_hinode *hinode __maybe_unused)
14867+#endif /* CONFIG_AUFS_HNOTIFY */
14868+
14869+static inline void au_hn_suspend(struct au_hinode *hdir)
14870+{
14871+ au_hn_ctl(hdir, /*do_set*/0);
1308ab2a 14872+}
14873+
4a4d8108 14874+static inline void au_hn_resume(struct au_hinode *hdir)
1308ab2a 14875+{
4a4d8108
AM
14876+ au_hn_ctl(hdir, /*do_set*/1);
14877+}
1308ab2a 14878+
4a4d8108
AM
14879+static inline void au_hn_imtx_lock(struct au_hinode *hdir)
14880+{
14881+ mutex_lock(&hdir->hi_inode->i_mutex);
14882+ au_hn_suspend(hdir);
14883+}
dece6358 14884+
4a4d8108
AM
14885+static inline void au_hn_imtx_lock_nested(struct au_hinode *hdir,
14886+ unsigned int sc __maybe_unused)
14887+{
14888+ mutex_lock_nested(&hdir->hi_inode->i_mutex, sc);
14889+ au_hn_suspend(hdir);
1facf9fc 14890+}
1facf9fc 14891+
4a4d8108
AM
14892+static inline void au_hn_imtx_unlock(struct au_hinode *hdir)
14893+{
14894+ au_hn_resume(hdir);
14895+ mutex_unlock(&hdir->hi_inode->i_mutex);
14896+}
14897+
14898+#endif /* __KERNEL__ */
14899+#endif /* __AUFS_INODE_H__ */
7f207e10
AM
14900diff -urN /usr/share/empty/fs/aufs/ioctl.c linux/fs/aufs/ioctl.c
14901--- /usr/share/empty/fs/aufs/ioctl.c 1970-01-01 01:00:00.000000000 +0100
537831f9 14902+++ linux/fs/aufs/ioctl.c 2012-12-13 20:41:10.431460173 +0100
f6c5ef8b 14903@@ -0,0 +1,196 @@
4a4d8108 14904+/*
f6c5ef8b 14905+ * Copyright (C) 2005-2012 Junjiro R. Okajima
4a4d8108
AM
14906+ *
14907+ * This program, aufs is free software; you can redistribute it and/or modify
14908+ * it under the terms of the GNU General Public License as published by
14909+ * the Free Software Foundation; either version 2 of the License, or
14910+ * (at your option) any later version.
14911+ *
14912+ * This program is distributed in the hope that it will be useful,
14913+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
14914+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14915+ * GNU General Public License for more details.
14916+ *
14917+ * You should have received a copy of the GNU General Public License
14918+ * along with this program; if not, write to the Free Software
14919+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
14920+ */
14921+
14922+/*
14923+ * ioctl
14924+ * plink-management and readdir in userspace.
14925+ * assist the pathconf(3) wrapper library.
14926+ */
14927+
4a4d8108
AM
14928+#include "aufs.h"
14929+
1e00d052 14930+static int au_wbr_fd(struct path *path, struct aufs_wbr_fd __user *arg)
4a4d8108
AM
14931+{
14932+ int err, fd;
14933+ aufs_bindex_t wbi, bindex, bend;
14934+ struct file *h_file;
14935+ struct super_block *sb;
14936+ struct dentry *root;
1e00d052
AM
14937+ struct au_branch *br;
14938+ struct aufs_wbr_fd wbrfd = {
14939+ .oflags = au_dir_roflags,
14940+ .brid = -1
14941+ };
14942+ const int valid = O_RDONLY | O_NONBLOCK | O_LARGEFILE | O_DIRECTORY
14943+ | O_NOATIME | O_CLOEXEC;
4a4d8108 14944+
1e00d052
AM
14945+ AuDebugOn(wbrfd.oflags & ~valid);
14946+
14947+ if (arg) {
14948+ err = copy_from_user(&wbrfd, arg, sizeof(wbrfd));
14949+ if (unlikely(err)) {
14950+ err = -EFAULT;
14951+ goto out;
14952+ }
14953+
14954+ err = -EINVAL;
14955+ AuDbg("wbrfd{0%o, %d}\n", wbrfd.oflags, wbrfd.brid);
14956+ wbrfd.oflags |= au_dir_roflags;
14957+ AuDbg("0%o\n", wbrfd.oflags);
14958+ if (unlikely(wbrfd.oflags & ~valid))
14959+ goto out;
14960+ }
14961+
14962+ fd = get_unused_fd();
14963+ err = fd;
14964+ if (unlikely(fd < 0))
4a4d8108 14965+ goto out;
4a4d8108 14966+
1e00d052 14967+ h_file = ERR_PTR(-EINVAL);
4a4d8108 14968+ wbi = 0;
1e00d052 14969+ br = NULL;
4a4d8108
AM
14970+ sb = path->dentry->d_sb;
14971+ root = sb->s_root;
14972+ aufs_read_lock(root, AuLock_IR);
1e00d052
AM
14973+ bend = au_sbend(sb);
14974+ if (wbrfd.brid >= 0) {
14975+ wbi = au_br_index(sb, wbrfd.brid);
14976+ if (unlikely(wbi < 0 || wbi > bend))
14977+ goto out_unlock;
14978+ }
14979+
14980+ h_file = ERR_PTR(-ENOENT);
14981+ br = au_sbr(sb, wbi);
14982+ if (!au_br_writable(br->br_perm)) {
14983+ if (arg)
14984+ goto out_unlock;
14985+
14986+ bindex = wbi + 1;
14987+ wbi = -1;
14988+ for (; bindex <= bend; bindex++) {
14989+ br = au_sbr(sb, bindex);
14990+ if (au_br_writable(br->br_perm)) {
4a4d8108 14991+ wbi = bindex;
1e00d052 14992+ br = au_sbr(sb, wbi);
4a4d8108
AM
14993+ break;
14994+ }
14995+ }
4a4d8108
AM
14996+ }
14997+ AuDbg("wbi %d\n", wbi);
1e00d052
AM
14998+ if (wbi >= 0)
14999+ h_file = au_h_open(root, wbi, wbrfd.oflags, NULL);
15000+
15001+out_unlock:
4a4d8108
AM
15002+ aufs_read_unlock(root, AuLock_IR);
15003+ err = PTR_ERR(h_file);
15004+ if (IS_ERR(h_file))
15005+ goto out_fd;
15006+
1e00d052 15007+ atomic_dec(&br->br_count); /* cf. au_h_open() */
4a4d8108
AM
15008+ fd_install(fd, h_file);
15009+ err = fd;
15010+ goto out; /* success */
15011+
4f0767ce 15012+out_fd:
4a4d8108 15013+ put_unused_fd(fd);
4f0767ce 15014+out:
1e00d052 15015+ AuTraceErr(err);
4a4d8108
AM
15016+ return err;
15017+}
15018+
15019+/* ---------------------------------------------------------------------- */
15020+
15021+long aufs_ioctl_dir(struct file *file, unsigned int cmd, unsigned long arg)
15022+{
15023+ long err;
15024+
15025+ switch (cmd) {
4a4d8108
AM
15026+ case AUFS_CTL_RDU:
15027+ case AUFS_CTL_RDU_INO:
15028+ err = au_rdu_ioctl(file, cmd, arg);
15029+ break;
15030+
15031+ case AUFS_CTL_WBR_FD:
1e00d052 15032+ err = au_wbr_fd(&file->f_path, (void __user *)arg);
4a4d8108
AM
15033+ break;
15034+
027c5e7a
AM
15035+ case AUFS_CTL_IBUSY:
15036+ err = au_ibusy_ioctl(file, arg);
15037+ break;
15038+
4a4d8108
AM
15039+ default:
15040+ /* do not call the lower */
15041+ AuDbg("0x%x\n", cmd);
15042+ err = -ENOTTY;
15043+ }
15044+
15045+ AuTraceErr(err);
15046+ return err;
15047+}
15048+
15049+long aufs_ioctl_nondir(struct file *file, unsigned int cmd, unsigned long arg)
15050+{
15051+ long err;
15052+
15053+ switch (cmd) {
15054+ case AUFS_CTL_WBR_FD:
1e00d052 15055+ err = au_wbr_fd(&file->f_path, (void __user *)arg);
4a4d8108
AM
15056+ break;
15057+
15058+ default:
15059+ /* do not call the lower */
15060+ AuDbg("0x%x\n", cmd);
15061+ err = -ENOTTY;
15062+ }
15063+
15064+ AuTraceErr(err);
15065+ return err;
15066+}
b752ccd1
AM
15067+
15068+#ifdef CONFIG_COMPAT
15069+long aufs_compat_ioctl_dir(struct file *file, unsigned int cmd,
15070+ unsigned long arg)
15071+{
15072+ long err;
15073+
15074+ switch (cmd) {
15075+ case AUFS_CTL_RDU:
15076+ case AUFS_CTL_RDU_INO:
15077+ err = au_rdu_compat_ioctl(file, cmd, arg);
15078+ break;
15079+
027c5e7a
AM
15080+ case AUFS_CTL_IBUSY:
15081+ err = au_ibusy_compat_ioctl(file, arg);
15082+ break;
15083+
b752ccd1
AM
15084+ default:
15085+ err = aufs_ioctl_dir(file, cmd, arg);
15086+ }
15087+
15088+ AuTraceErr(err);
15089+ return err;
15090+}
15091+
15092+#if 0 /* unused yet */
15093+long aufs_compat_ioctl_nondir(struct file *file, unsigned int cmd,
15094+ unsigned long arg)
15095+{
15096+ return aufs_ioctl_nondir(file, cmd, (unsigned long)compat_ptr(arg));
15097+}
15098+#endif
15099+#endif
7f207e10
AM
15100diff -urN /usr/share/empty/fs/aufs/i_op_add.c linux/fs/aufs/i_op_add.c
15101--- /usr/share/empty/fs/aufs/i_op_add.c 1970-01-01 01:00:00.000000000 +0100
537831f9
AM
15102+++ linux/fs/aufs/i_op_add.c 2012-12-13 20:41:10.431460173 +0100
15103@@ -0,0 +1,713 @@
4a4d8108 15104+/*
f6c5ef8b 15105+ * Copyright (C) 2005-2012 Junjiro R. Okajima
4a4d8108
AM
15106+ *
15107+ * This program, aufs is free software; you can redistribute it and/or modify
15108+ * it under the terms of the GNU General Public License as published by
15109+ * the Free Software Foundation; either version 2 of the License, or
15110+ * (at your option) any later version.
15111+ *
15112+ * This program is distributed in the hope that it will be useful,
15113+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
15114+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15115+ * GNU General Public License for more details.
15116+ *
15117+ * You should have received a copy of the GNU General Public License
15118+ * along with this program; if not, write to the Free Software
15119+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
15120+ */
15121+
15122+/*
15123+ * inode operations (add entry)
15124+ */
15125+
15126+#include "aufs.h"
15127+
15128+/*
15129+ * final procedure of adding a new entry, except link(2).
15130+ * remove whiteout, instantiate, copyup the parent dir's times and size
15131+ * and update version.
15132+ * if it failed, re-create the removed whiteout.
15133+ */
15134+static int epilog(struct inode *dir, aufs_bindex_t bindex,
15135+ struct dentry *wh_dentry, struct dentry *dentry)
15136+{
15137+ int err, rerr;
15138+ aufs_bindex_t bwh;
15139+ struct path h_path;
15140+ struct inode *inode, *h_dir;
15141+ struct dentry *wh;
15142+
15143+ bwh = -1;
15144+ if (wh_dentry) {
15145+ h_dir = wh_dentry->d_parent->d_inode; /* dir inode is locked */
15146+ IMustLock(h_dir);
15147+ AuDebugOn(au_h_iptr(dir, bindex) != h_dir);
15148+ bwh = au_dbwh(dentry);
15149+ h_path.dentry = wh_dentry;
15150+ h_path.mnt = au_sbr_mnt(dir->i_sb, bindex);
15151+ err = au_wh_unlink_dentry(au_h_iptr(dir, bindex), &h_path,
15152+ dentry);
15153+ if (unlikely(err))
15154+ goto out;
15155+ }
15156+
15157+ inode = au_new_inode(dentry, /*must_new*/1);
15158+ if (!IS_ERR(inode)) {
15159+ d_instantiate(dentry, inode);
15160+ dir = dentry->d_parent->d_inode; /* dir inode is locked */
15161+ IMustLock(dir);
15162+ if (au_ibstart(dir) == au_dbstart(dentry))
15163+ au_cpup_attr_timesizes(dir);
15164+ dir->i_version++;
15165+ return 0; /* success */
15166+ }
15167+
15168+ err = PTR_ERR(inode);
15169+ if (!wh_dentry)
15170+ goto out;
15171+
15172+ /* revert */
15173+ /* dir inode is locked */
15174+ wh = au_wh_create(dentry, bwh, wh_dentry->d_parent);
15175+ rerr = PTR_ERR(wh);
15176+ if (IS_ERR(wh)) {
15177+ AuIOErr("%.*s reverting whiteout failed(%d, %d)\n",
15178+ AuDLNPair(dentry), err, rerr);
15179+ err = -EIO;
15180+ } else
15181+ dput(wh);
15182+
4f0767ce 15183+out:
4a4d8108
AM
15184+ return err;
15185+}
15186+
027c5e7a
AM
15187+static int au_d_may_add(struct dentry *dentry)
15188+{
15189+ int err;
15190+
15191+ err = 0;
15192+ if (unlikely(d_unhashed(dentry)))
15193+ err = -ENOENT;
15194+ if (unlikely(dentry->d_inode))
15195+ err = -EEXIST;
15196+ return err;
15197+}
15198+
4a4d8108
AM
15199+/*
15200+ * simple tests for the adding inode operations.
15201+ * following the checks in vfs, plus the parent-child relationship.
15202+ */
15203+int au_may_add(struct dentry *dentry, aufs_bindex_t bindex,
15204+ struct dentry *h_parent, int isdir)
15205+{
15206+ int err;
15207+ umode_t h_mode;
15208+ struct dentry *h_dentry;
15209+ struct inode *h_inode;
15210+
15211+ err = -ENAMETOOLONG;
15212+ if (unlikely(dentry->d_name.len > AUFS_MAX_NAMELEN))
15213+ goto out;
15214+
15215+ h_dentry = au_h_dptr(dentry, bindex);
15216+ h_inode = h_dentry->d_inode;
15217+ if (!dentry->d_inode) {
15218+ err = -EEXIST;
15219+ if (unlikely(h_inode))
15220+ goto out;
15221+ } else {
15222+ /* rename(2) case */
15223+ err = -EIO;
15224+ if (unlikely(!h_inode || !h_inode->i_nlink))
15225+ goto out;
15226+
15227+ h_mode = h_inode->i_mode;
15228+ if (!isdir) {
15229+ err = -EISDIR;
15230+ if (unlikely(S_ISDIR(h_mode)))
15231+ goto out;
15232+ } else if (unlikely(!S_ISDIR(h_mode))) {
15233+ err = -ENOTDIR;
15234+ goto out;
15235+ }
15236+ }
15237+
15238+ err = 0;
15239+ /* expected parent dir is locked */
15240+ if (unlikely(h_parent != h_dentry->d_parent))
15241+ err = -EIO;
15242+
4f0767ce 15243+out:
4a4d8108
AM
15244+ AuTraceErr(err);
15245+ return err;
15246+}
15247+
15248+/*
15249+ * initial procedure of adding a new entry.
15250+ * prepare writable branch and the parent dir, lock it,
15251+ * and lookup whiteout for the new entry.
15252+ */
15253+static struct dentry*
15254+lock_hdir_lkup_wh(struct dentry *dentry, struct au_dtime *dt,
15255+ struct dentry *src_dentry, struct au_pin *pin,
15256+ struct au_wr_dir_args *wr_dir_args)
15257+{
15258+ struct dentry *wh_dentry, *h_parent;
15259+ struct super_block *sb;
15260+ struct au_branch *br;
15261+ int err;
15262+ unsigned int udba;
15263+ aufs_bindex_t bcpup;
15264+
15265+ AuDbg("%.*s\n", AuDLNPair(dentry));
15266+
15267+ err = au_wr_dir(dentry, src_dentry, wr_dir_args);
15268+ bcpup = err;
15269+ wh_dentry = ERR_PTR(err);
15270+ if (unlikely(err < 0))
15271+ goto out;
15272+
15273+ sb = dentry->d_sb;
15274+ udba = au_opt_udba(sb);
15275+ err = au_pin(pin, dentry, bcpup, udba,
15276+ AuPin_DI_LOCKED | AuPin_MNT_WRITE);
15277+ wh_dentry = ERR_PTR(err);
15278+ if (unlikely(err))
15279+ goto out;
15280+
15281+ h_parent = au_pinned_h_parent(pin);
15282+ if (udba != AuOpt_UDBA_NONE
15283+ && au_dbstart(dentry) == bcpup)
15284+ err = au_may_add(dentry, bcpup, h_parent,
15285+ au_ftest_wrdir(wr_dir_args->flags, ISDIR));
15286+ else if (unlikely(dentry->d_name.len > AUFS_MAX_NAMELEN))
15287+ err = -ENAMETOOLONG;
15288+ wh_dentry = ERR_PTR(err);
15289+ if (unlikely(err))
15290+ goto out_unpin;
15291+
15292+ br = au_sbr(sb, bcpup);
15293+ if (dt) {
15294+ struct path tmp = {
15295+ .dentry = h_parent,
15296+ .mnt = br->br_mnt
15297+ };
15298+ au_dtime_store(dt, au_pinned_parent(pin), &tmp);
15299+ }
15300+
15301+ wh_dentry = NULL;
15302+ if (bcpup != au_dbwh(dentry))
15303+ goto out; /* success */
15304+
15305+ wh_dentry = au_wh_lkup(h_parent, &dentry->d_name, br);
15306+
4f0767ce 15307+out_unpin:
4a4d8108
AM
15308+ if (IS_ERR(wh_dentry))
15309+ au_unpin(pin);
4f0767ce 15310+out:
4a4d8108
AM
15311+ return wh_dentry;
15312+}
15313+
15314+/* ---------------------------------------------------------------------- */
15315+
15316+enum { Mknod, Symlink, Creat };
15317+struct simple_arg {
15318+ int type;
15319+ union {
15320+ struct {
7eafdf33 15321+ umode_t mode;
b4510431 15322+ bool want_excl;
4a4d8108
AM
15323+ } c;
15324+ struct {
15325+ const char *symname;
15326+ } s;
15327+ struct {
7eafdf33 15328+ umode_t mode;
4a4d8108
AM
15329+ dev_t dev;
15330+ } m;
15331+ } u;
15332+};
15333+
15334+static int add_simple(struct inode *dir, struct dentry *dentry,
15335+ struct simple_arg *arg)
15336+{
15337+ int err;
15338+ aufs_bindex_t bstart;
15339+ unsigned char created;
15340+ struct au_dtime dt;
15341+ struct au_pin pin;
15342+ struct path h_path;
15343+ struct dentry *wh_dentry, *parent;
15344+ struct inode *h_dir;
15345+ struct au_wr_dir_args wr_dir_args = {
15346+ .force_btgt = -1,
15347+ .flags = AuWrDir_ADD_ENTRY
15348+ };
15349+
15350+ AuDbg("%.*s\n", AuDLNPair(dentry));
15351+ IMustLock(dir);
15352+
15353+ parent = dentry->d_parent; /* dir inode is locked */
027c5e7a
AM
15354+ err = aufs_read_lock(dentry, AuLock_DW | AuLock_GEN);
15355+ if (unlikely(err))
15356+ goto out;
15357+ err = au_d_may_add(dentry);
15358+ if (unlikely(err))
15359+ goto out_unlock;
4a4d8108
AM
15360+ di_write_lock_parent(parent);
15361+ wh_dentry = lock_hdir_lkup_wh(dentry, &dt, /*src_dentry*/NULL, &pin,
15362+ &wr_dir_args);
15363+ err = PTR_ERR(wh_dentry);
15364+ if (IS_ERR(wh_dentry))
027c5e7a 15365+ goto out_parent;
4a4d8108
AM
15366+
15367+ bstart = au_dbstart(dentry);
15368+ h_path.dentry = au_h_dptr(dentry, bstart);
15369+ h_path.mnt = au_sbr_mnt(dentry->d_sb, bstart);
15370+ h_dir = au_pinned_h_dir(&pin);
15371+ switch (arg->type) {
15372+ case Creat:
537831f9
AM
15373+ err = vfsub_create(h_dir, &h_path, arg->u.c.mode,
15374+ arg->u.c.want_excl);
4a4d8108
AM
15375+ break;
15376+ case Symlink:
15377+ err = vfsub_symlink(h_dir, &h_path, arg->u.s.symname);
15378+ break;
15379+ case Mknod:
15380+ err = vfsub_mknod(h_dir, &h_path, arg->u.m.mode, arg->u.m.dev);
15381+ break;
15382+ default:
15383+ BUG();
15384+ }
15385+ created = !err;
15386+ if (!err)
15387+ err = epilog(dir, bstart, wh_dentry, dentry);
15388+
15389+ /* revert */
15390+ if (unlikely(created && err && h_path.dentry->d_inode)) {
15391+ int rerr;
15392+ rerr = vfsub_unlink(h_dir, &h_path, /*force*/0);
15393+ if (rerr) {
15394+ AuIOErr("%.*s revert failure(%d, %d)\n",
15395+ AuDLNPair(dentry), err, rerr);
15396+ err = -EIO;
15397+ }
15398+ au_dtime_revert(&dt);
4a4d8108
AM
15399+ }
15400+
15401+ au_unpin(&pin);
15402+ dput(wh_dentry);
15403+
027c5e7a
AM
15404+out_parent:
15405+ di_write_unlock(parent);
15406+out_unlock:
4a4d8108
AM
15407+ if (unlikely(err)) {
15408+ au_update_dbstart(dentry);
15409+ d_drop(dentry);
15410+ }
4a4d8108 15411+ aufs_read_unlock(dentry, AuLock_DW);
027c5e7a 15412+out:
4a4d8108
AM
15413+ return err;
15414+}
15415+
7eafdf33
AM
15416+int aufs_mknod(struct inode *dir, struct dentry *dentry, umode_t mode,
15417+ dev_t dev)
4a4d8108
AM
15418+{
15419+ struct simple_arg arg = {
15420+ .type = Mknod,
15421+ .u.m = {
15422+ .mode = mode,
15423+ .dev = dev
15424+ }
15425+ };
15426+ return add_simple(dir, dentry, &arg);
15427+}
15428+
15429+int aufs_symlink(struct inode *dir, struct dentry *dentry, const char *symname)
15430+{
15431+ struct simple_arg arg = {
15432+ .type = Symlink,
15433+ .u.s.symname = symname
15434+ };
15435+ return add_simple(dir, dentry, &arg);
15436+}
15437+
7eafdf33 15438+int aufs_create(struct inode *dir, struct dentry *dentry, umode_t mode,
b4510431 15439+ bool want_excl)
4a4d8108
AM
15440+{
15441+ struct simple_arg arg = {
15442+ .type = Creat,
15443+ .u.c = {
b4510431
AM
15444+ .mode = mode,
15445+ .want_excl = want_excl
4a4d8108
AM
15446+ }
15447+ };
15448+ return add_simple(dir, dentry, &arg);
15449+}
15450+
15451+/* ---------------------------------------------------------------------- */
15452+
15453+struct au_link_args {
15454+ aufs_bindex_t bdst, bsrc;
15455+ struct au_pin pin;
15456+ struct path h_path;
15457+ struct dentry *src_parent, *parent;
15458+};
15459+
15460+static int au_cpup_before_link(struct dentry *src_dentry,
15461+ struct au_link_args *a)
15462+{
15463+ int err;
15464+ struct dentry *h_src_dentry;
15465+ struct mutex *h_mtx;
15466+ struct file *h_file;
15467+
15468+ di_read_lock_parent(a->src_parent, AuLock_IR);
15469+ err = au_test_and_cpup_dirs(src_dentry, a->bdst);
15470+ if (unlikely(err))
15471+ goto out;
15472+
15473+ h_src_dentry = au_h_dptr(src_dentry, a->bsrc);
15474+ h_mtx = &h_src_dentry->d_inode->i_mutex;
15475+ err = au_pin(&a->pin, src_dentry, a->bdst,
15476+ au_opt_udba(src_dentry->d_sb),
15477+ AuPin_DI_LOCKED | AuPin_MNT_WRITE);
15478+ if (unlikely(err))
15479+ goto out;
15480+ mutex_lock_nested(h_mtx, AuLsc_I_CHILD);
15481+ h_file = au_h_open_pre(src_dentry, a->bsrc);
15482+ if (IS_ERR(h_file)) {
15483+ err = PTR_ERR(h_file);
15484+ h_file = NULL;
15485+ } else
1e00d052 15486+ err = au_sio_cpup_simple(src_dentry, a->bdst, -1,
4a4d8108
AM
15487+ AuCpup_DTIME /* | AuCpup_KEEPLINO */);
15488+ mutex_unlock(h_mtx);
15489+ au_h_open_post(src_dentry, a->bsrc, h_file);
15490+ au_unpin(&a->pin);
15491+
4f0767ce 15492+out:
4a4d8108
AM
15493+ di_read_unlock(a->src_parent, AuLock_IR);
15494+ return err;
15495+}
15496+
15497+static int au_cpup_or_link(struct dentry *src_dentry, struct au_link_args *a)
15498+{
15499+ int err;
15500+ unsigned char plink;
15501+ struct inode *h_inode, *inode;
15502+ struct dentry *h_src_dentry;
15503+ struct super_block *sb;
15504+ struct file *h_file;
15505+
15506+ plink = 0;
15507+ h_inode = NULL;
15508+ sb = src_dentry->d_sb;
15509+ inode = src_dentry->d_inode;
15510+ if (au_ibstart(inode) <= a->bdst)
15511+ h_inode = au_h_iptr(inode, a->bdst);
15512+ if (!h_inode || !h_inode->i_nlink) {
15513+ /* copyup src_dentry as the name of dentry. */
15514+ au_set_dbstart(src_dentry, a->bdst);
15515+ au_set_h_dptr(src_dentry, a->bdst, dget(a->h_path.dentry));
15516+ h_inode = au_h_dptr(src_dentry, a->bsrc)->d_inode;
15517+ mutex_lock_nested(&h_inode->i_mutex, AuLsc_I_CHILD);
15518+ h_file = au_h_open_pre(src_dentry, a->bsrc);
15519+ if (IS_ERR(h_file)) {
15520+ err = PTR_ERR(h_file);
15521+ h_file = NULL;
15522+ } else
15523+ err = au_sio_cpup_single(src_dentry, a->bdst, a->bsrc,
15524+ -1, AuCpup_KEEPLINO,
15525+ a->parent);
15526+ mutex_unlock(&h_inode->i_mutex);
15527+ au_h_open_post(src_dentry, a->bsrc, h_file);
15528+ au_set_h_dptr(src_dentry, a->bdst, NULL);
15529+ au_set_dbstart(src_dentry, a->bsrc);
15530+ } else {
15531+ /* the inode of src_dentry already exists on a.bdst branch */
15532+ h_src_dentry = d_find_alias(h_inode);
15533+ if (!h_src_dentry && au_plink_test(inode)) {
15534+ plink = 1;
15535+ h_src_dentry = au_plink_lkup(inode, a->bdst);
15536+ err = PTR_ERR(h_src_dentry);
15537+ if (IS_ERR(h_src_dentry))
15538+ goto out;
15539+
15540+ if (unlikely(!h_src_dentry->d_inode)) {
15541+ dput(h_src_dentry);
15542+ h_src_dentry = NULL;
15543+ }
15544+
15545+ }
15546+ if (h_src_dentry) {
15547+ err = vfsub_link(h_src_dentry, au_pinned_h_dir(&a->pin),
15548+ &a->h_path);
15549+ dput(h_src_dentry);
15550+ } else {
15551+ AuIOErr("no dentry found for hi%lu on b%d\n",
15552+ h_inode->i_ino, a->bdst);
15553+ err = -EIO;
15554+ }
15555+ }
15556+
15557+ if (!err && !plink)
15558+ au_plink_append(inode, a->bdst, a->h_path.dentry);
15559+
15560+out:
2cbb1c4b 15561+ AuTraceErr(err);
4a4d8108
AM
15562+ return err;
15563+}
15564+
15565+int aufs_link(struct dentry *src_dentry, struct inode *dir,
15566+ struct dentry *dentry)
15567+{
15568+ int err, rerr;
15569+ struct au_dtime dt;
15570+ struct au_link_args *a;
15571+ struct dentry *wh_dentry, *h_src_dentry;
15572+ struct inode *inode;
15573+ struct super_block *sb;
15574+ struct au_wr_dir_args wr_dir_args = {
15575+ /* .force_btgt = -1, */
15576+ .flags = AuWrDir_ADD_ENTRY
15577+ };
15578+
15579+ IMustLock(dir);
15580+ inode = src_dentry->d_inode;
15581+ IMustLock(inode);
15582+
4a4d8108
AM
15583+ err = -ENOMEM;
15584+ a = kzalloc(sizeof(*a), GFP_NOFS);
15585+ if (unlikely(!a))
15586+ goto out;
15587+
15588+ a->parent = dentry->d_parent; /* dir inode is locked */
027c5e7a
AM
15589+ err = aufs_read_and_write_lock2(dentry, src_dentry,
15590+ AuLock_NOPLM | AuLock_GEN);
e49829fe
JR
15591+ if (unlikely(err))
15592+ goto out_kfree;
027c5e7a
AM
15593+ err = au_d_hashed_positive(src_dentry);
15594+ if (unlikely(err))
15595+ goto out_unlock;
15596+ err = au_d_may_add(dentry);
15597+ if (unlikely(err))
15598+ goto out_unlock;
e49829fe 15599+
4a4d8108 15600+ a->src_parent = dget_parent(src_dentry);
2cbb1c4b 15601+ wr_dir_args.force_btgt = au_ibstart(inode);
4a4d8108
AM
15602+
15603+ di_write_lock_parent(a->parent);
15604+ wr_dir_args.force_btgt = au_wbr(dentry, wr_dir_args.force_btgt);
15605+ wh_dentry = lock_hdir_lkup_wh(dentry, &dt, src_dentry, &a->pin,
15606+ &wr_dir_args);
15607+ err = PTR_ERR(wh_dentry);
15608+ if (IS_ERR(wh_dentry))
027c5e7a 15609+ goto out_parent;
4a4d8108
AM
15610+
15611+ err = 0;
15612+ sb = dentry->d_sb;
15613+ a->bdst = au_dbstart(dentry);
15614+ a->h_path.dentry = au_h_dptr(dentry, a->bdst);
15615+ a->h_path.mnt = au_sbr_mnt(sb, a->bdst);
2cbb1c4b
JR
15616+ a->bsrc = au_ibstart(inode);
15617+ h_src_dentry = au_h_d_alias(src_dentry, a->bsrc);
15618+ if (!h_src_dentry) {
15619+ a->bsrc = au_dbstart(src_dentry);
15620+ h_src_dentry = au_h_d_alias(src_dentry, a->bsrc);
15621+ AuDebugOn(!h_src_dentry);
15622+ } else if (IS_ERR(h_src_dentry))
15623+ goto out_parent;
15624+
4a4d8108
AM
15625+ if (au_opt_test(au_mntflags(sb), PLINK)) {
15626+ if (a->bdst < a->bsrc
15627+ /* && h_src_dentry->d_sb != a->h_path.dentry->d_sb */)
15628+ err = au_cpup_or_link(src_dentry, a);
2cbb1c4b 15629+ else
4a4d8108
AM
15630+ err = vfsub_link(h_src_dentry, au_pinned_h_dir(&a->pin),
15631+ &a->h_path);
2cbb1c4b 15632+ dput(h_src_dentry);
4a4d8108
AM
15633+ } else {
15634+ /*
15635+ * copyup src_dentry to the branch we process,
15636+ * and then link(2) to it.
15637+ */
2cbb1c4b 15638+ dput(h_src_dentry);
4a4d8108
AM
15639+ if (a->bdst < a->bsrc
15640+ /* && h_src_dentry->d_sb != a->h_path.dentry->d_sb */) {
15641+ au_unpin(&a->pin);
15642+ di_write_unlock(a->parent);
15643+ err = au_cpup_before_link(src_dentry, a);
15644+ di_write_lock_parent(a->parent);
15645+ if (!err)
15646+ err = au_pin(&a->pin, dentry, a->bdst,
15647+ au_opt_udba(sb),
15648+ AuPin_DI_LOCKED | AuPin_MNT_WRITE);
15649+ if (unlikely(err))
15650+ goto out_wh;
15651+ }
15652+ if (!err) {
15653+ h_src_dentry = au_h_dptr(src_dentry, a->bdst);
15654+ err = -ENOENT;
15655+ if (h_src_dentry && h_src_dentry->d_inode)
15656+ err = vfsub_link(h_src_dentry,
15657+ au_pinned_h_dir(&a->pin),
15658+ &a->h_path);
15659+ }
15660+ }
15661+ if (unlikely(err))
15662+ goto out_unpin;
15663+
15664+ if (wh_dentry) {
15665+ a->h_path.dentry = wh_dentry;
15666+ err = au_wh_unlink_dentry(au_pinned_h_dir(&a->pin), &a->h_path,
15667+ dentry);
15668+ if (unlikely(err))
15669+ goto out_revert;
15670+ }
15671+
15672+ dir->i_version++;
15673+ if (au_ibstart(dir) == au_dbstart(dentry))
15674+ au_cpup_attr_timesizes(dir);
15675+ inc_nlink(inode);
15676+ inode->i_ctime = dir->i_ctime;
027c5e7a
AM
15677+ d_instantiate(dentry, au_igrab(inode));
15678+ if (d_unhashed(a->h_path.dentry))
4a4d8108
AM
15679+ /* some filesystem calls d_drop() */
15680+ d_drop(dentry);
15681+ goto out_unpin; /* success */
15682+
4f0767ce 15683+out_revert:
4a4d8108 15684+ rerr = vfsub_unlink(au_pinned_h_dir(&a->pin), &a->h_path, /*force*/0);
027c5e7a
AM
15685+ if (unlikely(rerr)) {
15686+ AuIOErr("%.*s reverting failed(%d, %d)\n",
15687+ AuDLNPair(dentry), err, rerr);
15688+ err = -EIO;
15689+ }
4a4d8108 15690+ au_dtime_revert(&dt);
4f0767ce 15691+out_unpin:
4a4d8108 15692+ au_unpin(&a->pin);
4f0767ce 15693+out_wh:
4a4d8108 15694+ dput(wh_dentry);
027c5e7a
AM
15695+out_parent:
15696+ di_write_unlock(a->parent);
15697+ dput(a->src_parent);
4f0767ce 15698+out_unlock:
4a4d8108
AM
15699+ if (unlikely(err)) {
15700+ au_update_dbstart(dentry);
15701+ d_drop(dentry);
15702+ }
4a4d8108 15703+ aufs_read_and_write_unlock2(dentry, src_dentry);
e49829fe 15704+out_kfree:
4a4d8108 15705+ kfree(a);
4f0767ce 15706+out:
4a4d8108
AM
15707+ return err;
15708+}
15709+
7eafdf33 15710+int aufs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
4a4d8108
AM
15711+{
15712+ int err, rerr;
15713+ aufs_bindex_t bindex;
15714+ unsigned char diropq;
15715+ struct path h_path;
15716+ struct dentry *wh_dentry, *parent, *opq_dentry;
15717+ struct mutex *h_mtx;
15718+ struct super_block *sb;
15719+ struct {
15720+ struct au_pin pin;
15721+ struct au_dtime dt;
15722+ } *a; /* reduce the stack usage */
15723+ struct au_wr_dir_args wr_dir_args = {
15724+ .force_btgt = -1,
15725+ .flags = AuWrDir_ADD_ENTRY | AuWrDir_ISDIR
15726+ };
15727+
15728+ IMustLock(dir);
15729+
15730+ err = -ENOMEM;
15731+ a = kmalloc(sizeof(*a), GFP_NOFS);
15732+ if (unlikely(!a))
15733+ goto out;
15734+
027c5e7a
AM
15735+ err = aufs_read_lock(dentry, AuLock_DW | AuLock_GEN);
15736+ if (unlikely(err))
15737+ goto out_free;
15738+ err = au_d_may_add(dentry);
15739+ if (unlikely(err))
15740+ goto out_unlock;
15741+
4a4d8108
AM
15742+ parent = dentry->d_parent; /* dir inode is locked */
15743+ di_write_lock_parent(parent);
15744+ wh_dentry = lock_hdir_lkup_wh(dentry, &a->dt, /*src_dentry*/NULL,
15745+ &a->pin, &wr_dir_args);
15746+ err = PTR_ERR(wh_dentry);
15747+ if (IS_ERR(wh_dentry))
027c5e7a 15748+ goto out_parent;
4a4d8108
AM
15749+
15750+ sb = dentry->d_sb;
15751+ bindex = au_dbstart(dentry);
15752+ h_path.dentry = au_h_dptr(dentry, bindex);
15753+ h_path.mnt = au_sbr_mnt(sb, bindex);
15754+ err = vfsub_mkdir(au_pinned_h_dir(&a->pin), &h_path, mode);
15755+ if (unlikely(err))
027c5e7a 15756+ goto out_unpin;
4a4d8108
AM
15757+
15758+ /* make the dir opaque */
15759+ diropq = 0;
15760+ h_mtx = &h_path.dentry->d_inode->i_mutex;
15761+ if (wh_dentry
15762+ || au_opt_test(au_mntflags(sb), ALWAYS_DIROPQ)) {
15763+ mutex_lock_nested(h_mtx, AuLsc_I_CHILD);
15764+ opq_dentry = au_diropq_create(dentry, bindex);
15765+ mutex_unlock(h_mtx);
15766+ err = PTR_ERR(opq_dentry);
15767+ if (IS_ERR(opq_dentry))
15768+ goto out_dir;
15769+ dput(opq_dentry);
15770+ diropq = 1;
15771+ }
15772+
15773+ err = epilog(dir, bindex, wh_dentry, dentry);
15774+ if (!err) {
15775+ inc_nlink(dir);
027c5e7a 15776+ goto out_unpin; /* success */
4a4d8108
AM
15777+ }
15778+
15779+ /* revert */
15780+ if (diropq) {
15781+ AuLabel(revert opq);
15782+ mutex_lock_nested(h_mtx, AuLsc_I_CHILD);
15783+ rerr = au_diropq_remove(dentry, bindex);
15784+ mutex_unlock(h_mtx);
15785+ if (rerr) {
15786+ AuIOErr("%.*s reverting diropq failed(%d, %d)\n",
15787+ AuDLNPair(dentry), err, rerr);
15788+ err = -EIO;
15789+ }
15790+ }
15791+
4f0767ce 15792+out_dir:
4a4d8108
AM
15793+ AuLabel(revert dir);
15794+ rerr = vfsub_rmdir(au_pinned_h_dir(&a->pin), &h_path);
15795+ if (rerr) {
15796+ AuIOErr("%.*s reverting dir failed(%d, %d)\n",
15797+ AuDLNPair(dentry), err, rerr);
15798+ err = -EIO;
15799+ }
4a4d8108 15800+ au_dtime_revert(&a->dt);
027c5e7a 15801+out_unpin:
4a4d8108
AM
15802+ au_unpin(&a->pin);
15803+ dput(wh_dentry);
027c5e7a
AM
15804+out_parent:
15805+ di_write_unlock(parent);
15806+out_unlock:
4a4d8108
AM
15807+ if (unlikely(err)) {
15808+ au_update_dbstart(dentry);
15809+ d_drop(dentry);
15810+ }
4a4d8108 15811+ aufs_read_unlock(dentry, AuLock_DW);
027c5e7a 15812+out_free:
4a4d8108 15813+ kfree(a);
4f0767ce 15814+out:
4a4d8108
AM
15815+ return err;
15816+}
7f207e10
AM
15817diff -urN /usr/share/empty/fs/aufs/i_op.c linux/fs/aufs/i_op.c
15818--- /usr/share/empty/fs/aufs/i_op.c 1970-01-01 01:00:00.000000000 +0100
537831f9
AM
15819+++ linux/fs/aufs/i_op.c 2012-12-13 20:41:10.431460173 +0100
15820@@ -0,0 +1,1026 @@
4a4d8108 15821+/*
f6c5ef8b 15822+ * Copyright (C) 2005-2012 Junjiro R. Okajima
4a4d8108
AM
15823+ *
15824+ * This program, aufs is free software; you can redistribute it and/or modify
15825+ * it under the terms of the GNU General Public License as published by
15826+ * the Free Software Foundation; either version 2 of the License, or
15827+ * (at your option) any later version.
15828+ *
15829+ * This program is distributed in the hope that it will be useful,
15830+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
15831+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15832+ * GNU General Public License for more details.
15833+ *
15834+ * You should have received a copy of the GNU General Public License
15835+ * along with this program; if not, write to the Free Software
15836+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
15837+ */
1facf9fc 15838+
1308ab2a 15839+/*
4a4d8108 15840+ * inode operations (except add/del/rename)
1308ab2a 15841+ */
4a4d8108
AM
15842+
15843+#include <linux/device_cgroup.h>
15844+#include <linux/fs_stack.h>
92d182d2 15845+#include <linux/mm.h>
4a4d8108
AM
15846+#include <linux/namei.h>
15847+#include <linux/security.h>
4a4d8108
AM
15848+#include "aufs.h"
15849+
1e00d052 15850+static int h_permission(struct inode *h_inode, int mask,
4a4d8108 15851+ struct vfsmount *h_mnt, int brperm)
1facf9fc 15852+{
1308ab2a 15853+ int err;
4a4d8108 15854+ const unsigned char write_mask = !!(mask & (MAY_WRITE | MAY_APPEND));
1facf9fc 15855+
4a4d8108
AM
15856+ err = -EACCES;
15857+ if ((write_mask && IS_IMMUTABLE(h_inode))
15858+ || ((mask & MAY_EXEC)
15859+ && S_ISREG(h_inode->i_mode)
15860+ && ((h_mnt->mnt_flags & MNT_NOEXEC)
15861+ || !(h_inode->i_mode & S_IXUGO))))
15862+ goto out;
15863+
15864+ /*
15865+ * - skip the lower fs test in the case of write to ro branch.
15866+ * - nfs dir permission write check is optimized, but a policy for
15867+ * link/rename requires a real check.
15868+ */
15869+ if ((write_mask && !au_br_writable(brperm))
15870+ || (au_test_nfs(h_inode->i_sb) && S_ISDIR(h_inode->i_mode)
15871+ && write_mask && !(mask & MAY_READ))
15872+ || !h_inode->i_op->permission) {
15873+ /* AuLabel(generic_permission); */
1e00d052 15874+ err = generic_permission(h_inode, mask);
1308ab2a 15875+ } else {
4a4d8108 15876+ /* AuLabel(h_inode->permission); */
1e00d052 15877+ err = h_inode->i_op->permission(h_inode, mask);
4a4d8108
AM
15878+ AuTraceErr(err);
15879+ }
1facf9fc 15880+
4a4d8108
AM
15881+ if (!err)
15882+ err = devcgroup_inode_permission(h_inode, mask);
7f207e10 15883+ if (!err)
4a4d8108 15884+ err = security_inode_permission(h_inode, mask);
4a4d8108
AM
15885+
15886+#if 0
15887+ if (!err) {
15888+ /* todo: do we need to call ima_path_check()? */
15889+ struct path h_path = {
15890+ .dentry =
15891+ .mnt = h_mnt
15892+ };
15893+ err = ima_path_check(&h_path,
15894+ mask & (MAY_READ | MAY_WRITE | MAY_EXEC),
15895+ IMA_COUNT_LEAVE);
1308ab2a 15896+ }
4a4d8108 15897+#endif
dece6358 15898+
4f0767ce 15899+out:
1308ab2a 15900+ return err;
15901+}
dece6358 15902+
1e00d052 15903+static int aufs_permission(struct inode *inode, int mask)
1308ab2a 15904+{
15905+ int err;
4a4d8108
AM
15906+ aufs_bindex_t bindex, bend;
15907+ const unsigned char isdir = !!S_ISDIR(inode->i_mode),
15908+ write_mask = !!(mask & (MAY_WRITE | MAY_APPEND));
15909+ struct inode *h_inode;
15910+ struct super_block *sb;
15911+ struct au_branch *br;
1facf9fc 15912+
027c5e7a 15913+ /* todo: support rcu-walk? */
1e00d052 15914+ if (mask & MAY_NOT_BLOCK)
027c5e7a
AM
15915+ return -ECHILD;
15916+
4a4d8108
AM
15917+ sb = inode->i_sb;
15918+ si_read_lock(sb, AuLock_FLUSH);
15919+ ii_read_lock_child(inode);
027c5e7a
AM
15920+#if 0
15921+ err = au_iigen_test(inode, au_sigen(sb));
15922+ if (unlikely(err))
15923+ goto out;
15924+#endif
dece6358 15925+
4a4d8108
AM
15926+ if (!isdir || write_mask) {
15927+ err = au_busy_or_stale();
15928+ h_inode = au_h_iptr(inode, au_ibstart(inode));
15929+ if (unlikely(!h_inode
15930+ || (h_inode->i_mode & S_IFMT)
15931+ != (inode->i_mode & S_IFMT)))
15932+ goto out;
1facf9fc 15933+
4a4d8108
AM
15934+ err = 0;
15935+ bindex = au_ibstart(inode);
15936+ br = au_sbr(sb, bindex);
1e00d052 15937+ err = h_permission(h_inode, mask, br->br_mnt, br->br_perm);
4a4d8108
AM
15938+ if (write_mask
15939+ && !err
15940+ && !special_file(h_inode->i_mode)) {
15941+ /* test whether the upper writable branch exists */
15942+ err = -EROFS;
15943+ for (; bindex >= 0; bindex--)
15944+ if (!au_br_rdonly(au_sbr(sb, bindex))) {
15945+ err = 0;
15946+ break;
15947+ }
15948+ }
15949+ goto out;
15950+ }
dece6358 15951+
4a4d8108 15952+ /* non-write to dir */
1308ab2a 15953+ err = 0;
4a4d8108
AM
15954+ bend = au_ibend(inode);
15955+ for (bindex = au_ibstart(inode); !err && bindex <= bend; bindex++) {
15956+ h_inode = au_h_iptr(inode, bindex);
15957+ if (h_inode) {
15958+ err = au_busy_or_stale();
15959+ if (unlikely(!S_ISDIR(h_inode->i_mode)))
15960+ break;
15961+
15962+ br = au_sbr(sb, bindex);
1e00d052 15963+ err = h_permission(h_inode, mask, br->br_mnt,
4a4d8108
AM
15964+ br->br_perm);
15965+ }
15966+ }
1308ab2a 15967+
4f0767ce 15968+out:
4a4d8108
AM
15969+ ii_read_unlock(inode);
15970+ si_read_unlock(sb);
1308ab2a 15971+ return err;
15972+}
15973+
4a4d8108 15974+/* ---------------------------------------------------------------------- */
1facf9fc 15975+
4a4d8108 15976+static struct dentry *aufs_lookup(struct inode *dir, struct dentry *dentry,
b4510431 15977+ unsigned int flags)
4a4d8108
AM
15978+{
15979+ struct dentry *ret, *parent;
b752ccd1 15980+ struct inode *inode;
4a4d8108 15981+ struct super_block *sb;
9dbd164d 15982+ int err, npositive, lc_idx;
dece6358 15983+
4a4d8108 15984+ IMustLock(dir);
1308ab2a 15985+
537831f9
AM
15986+ /* todo: support rcu-walk? */
15987+ ret = ERR_PTR(-ECHILD);
15988+ if (flags & LOOKUP_RCU)
15989+ goto out;
15990+
15991+ ret = ERR_PTR(-ENAMETOOLONG);
15992+ if (unlikely(dentry->d_name.len > AUFS_MAX_NAMELEN))
15993+ goto out;
15994+
4a4d8108 15995+ sb = dir->i_sb;
7f207e10
AM
15996+ err = si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLM);
15997+ ret = ERR_PTR(err);
15998+ if (unlikely(err))
15999+ goto out;
16000+
4a4d8108
AM
16001+ err = au_di_init(dentry);
16002+ ret = ERR_PTR(err);
16003+ if (unlikely(err))
7f207e10 16004+ goto out_si;
1308ab2a 16005+
9dbd164d 16006+ inode = NULL;
027c5e7a 16007+ npositive = 0; /* suppress a warning */
4a4d8108
AM
16008+ parent = dentry->d_parent; /* dir inode is locked */
16009+ di_read_lock_parent(parent, AuLock_IR);
027c5e7a
AM
16010+ err = au_alive_dir(parent);
16011+ if (!err)
16012+ err = au_digen_test(parent, au_sigen(sb));
16013+ if (!err) {
16014+ npositive = au_lkup_dentry(dentry, au_dbstart(parent),
537831f9 16015+ /*type*/0);
027c5e7a
AM
16016+ err = npositive;
16017+ }
4a4d8108 16018+ di_read_unlock(parent, AuLock_IR);
4a4d8108
AM
16019+ ret = ERR_PTR(err);
16020+ if (unlikely(err < 0))
16021+ goto out_unlock;
1308ab2a 16022+
4a4d8108 16023+ if (npositive) {
b752ccd1 16024+ inode = au_new_inode(dentry, /*must_new*/0);
4a4d8108 16025+ ret = (void *)inode;
1facf9fc 16026+ }
9dbd164d
AM
16027+ if (IS_ERR(inode)) {
16028+ inode = NULL;
4a4d8108 16029+ goto out_unlock;
9dbd164d 16030+ }
4a4d8108
AM
16031+
16032+ ret = d_splice_alias(inode, dentry);
537831f9
AM
16033+#if 0
16034+ if (unlikely(d_need_lookup(dentry))) {
16035+ spin_lock(&dentry->d_lock);
16036+ dentry->d_flags &= ~DCACHE_NEED_LOOKUP;
16037+ spin_unlock(&dentry->d_lock);
16038+ } else
16039+#endif
7f207e10 16040+ if (unlikely(IS_ERR(ret) && inode)) {
4a4d8108 16041+ ii_write_unlock(inode);
7f207e10 16042+ iput(inode);
2dfbb274 16043+ inode = NULL;
7f207e10 16044+ }
1facf9fc 16045+
4f0767ce 16046+out_unlock:
4a4d8108 16047+ di_write_unlock(dentry);
2dfbb274 16048+ if (inode) {
9dbd164d
AM
16049+ lc_idx = AuLcNonDir_DIINFO;
16050+ if (S_ISLNK(inode->i_mode))
16051+ lc_idx = AuLcSymlink_DIINFO;
16052+ else if (S_ISDIR(inode->i_mode))
16053+ lc_idx = AuLcDir_DIINFO;
16054+ au_rw_class(&au_di(dentry)->di_rwsem, au_lc_key + lc_idx);
16055+ }
7f207e10 16056+out_si:
4a4d8108 16057+ si_read_unlock(sb);
7f207e10 16058+out:
4a4d8108
AM
16059+ return ret;
16060+}
1facf9fc 16061+
4a4d8108 16062+/* ---------------------------------------------------------------------- */
1facf9fc 16063+
4a4d8108
AM
16064+static int au_wr_dir_cpup(struct dentry *dentry, struct dentry *parent,
16065+ const unsigned char add_entry, aufs_bindex_t bcpup,
16066+ aufs_bindex_t bstart)
16067+{
16068+ int err;
16069+ struct dentry *h_parent;
16070+ struct inode *h_dir;
1facf9fc 16071+
027c5e7a 16072+ if (add_entry)
4a4d8108 16073+ IMustLock(parent->d_inode);
027c5e7a 16074+ else
4a4d8108
AM
16075+ di_write_lock_parent(parent);
16076+
16077+ err = 0;
16078+ if (!au_h_dptr(parent, bcpup)) {
16079+ if (bstart < bcpup)
16080+ err = au_cpdown_dirs(dentry, bcpup);
16081+ else
16082+ err = au_cpup_dirs(dentry, bcpup);
16083+ }
16084+ if (!err && add_entry) {
16085+ h_parent = au_h_dptr(parent, bcpup);
16086+ h_dir = h_parent->d_inode;
16087+ mutex_lock_nested(&h_dir->i_mutex, AuLsc_I_PARENT);
16088+ err = au_lkup_neg(dentry, bcpup);
16089+ /* todo: no unlock here */
16090+ mutex_unlock(&h_dir->i_mutex);
027c5e7a
AM
16091+
16092+ AuDbg("bcpup %d\n", bcpup);
16093+ if (!err) {
16094+ if (!dentry->d_inode)
16095+ au_set_h_dptr(dentry, bstart, NULL);
4a4d8108
AM
16096+ au_update_dbrange(dentry, /*do_put_zero*/0);
16097+ }
1308ab2a 16098+ }
1facf9fc 16099+
4a4d8108
AM
16100+ if (!add_entry)
16101+ di_write_unlock(parent);
16102+ if (!err)
16103+ err = bcpup; /* success */
1308ab2a 16104+
027c5e7a 16105+ AuTraceErr(err);
4a4d8108
AM
16106+ return err;
16107+}
1facf9fc 16108+
4a4d8108
AM
16109+/*
16110+ * decide the branch and the parent dir where we will create a new entry.
16111+ * returns new bindex or an error.
16112+ * copyup the parent dir if needed.
16113+ */
16114+int au_wr_dir(struct dentry *dentry, struct dentry *src_dentry,
16115+ struct au_wr_dir_args *args)
16116+{
16117+ int err;
16118+ aufs_bindex_t bcpup, bstart, src_bstart;
16119+ const unsigned char add_entry = !!au_ftest_wrdir(args->flags,
16120+ ADD_ENTRY);
16121+ struct super_block *sb;
16122+ struct dentry *parent;
16123+ struct au_sbinfo *sbinfo;
1facf9fc 16124+
4a4d8108
AM
16125+ sb = dentry->d_sb;
16126+ sbinfo = au_sbi(sb);
16127+ parent = dget_parent(dentry);
16128+ bstart = au_dbstart(dentry);
16129+ bcpup = bstart;
16130+ if (args->force_btgt < 0) {
16131+ if (src_dentry) {
16132+ src_bstart = au_dbstart(src_dentry);
16133+ if (src_bstart < bstart)
16134+ bcpup = src_bstart;
16135+ } else if (add_entry) {
16136+ err = AuWbrCreate(sbinfo, dentry,
16137+ au_ftest_wrdir(args->flags, ISDIR));
16138+ bcpup = err;
16139+ }
1facf9fc 16140+
4a4d8108
AM
16141+ if (bcpup < 0 || au_test_ro(sb, bcpup, dentry->d_inode)) {
16142+ if (add_entry)
16143+ err = AuWbrCopyup(sbinfo, dentry);
16144+ else {
16145+ if (!IS_ROOT(dentry)) {
16146+ di_read_lock_parent(parent, !AuLock_IR);
16147+ err = AuWbrCopyup(sbinfo, dentry);
16148+ di_read_unlock(parent, !AuLock_IR);
16149+ } else
16150+ err = AuWbrCopyup(sbinfo, dentry);
16151+ }
16152+ bcpup = err;
16153+ if (unlikely(err < 0))
16154+ goto out;
16155+ }
16156+ } else {
16157+ bcpup = args->force_btgt;
16158+ AuDebugOn(au_test_ro(sb, bcpup, dentry->d_inode));
1308ab2a 16159+ }
027c5e7a 16160+
4a4d8108
AM
16161+ AuDbg("bstart %d, bcpup %d\n", bstart, bcpup);
16162+ err = bcpup;
16163+ if (bcpup == bstart)
16164+ goto out; /* success */
4a4d8108
AM
16165+
16166+ /* copyup the new parent into the branch we process */
16167+ err = au_wr_dir_cpup(dentry, parent, add_entry, bcpup, bstart);
027c5e7a
AM
16168+ if (err >= 0) {
16169+ if (!dentry->d_inode) {
16170+ au_set_h_dptr(dentry, bstart, NULL);
16171+ au_set_dbstart(dentry, bcpup);
16172+ au_set_dbend(dentry, bcpup);
16173+ }
16174+ AuDebugOn(add_entry && !au_h_dptr(dentry, bcpup));
16175+ }
4a4d8108 16176+
4f0767ce 16177+out:
4a4d8108 16178+ dput(parent);
dece6358
AM
16179+ return err;
16180+}
1facf9fc 16181+
1308ab2a 16182+/* ---------------------------------------------------------------------- */
16183+
4a4d8108 16184+struct dentry *au_pinned_h_parent(struct au_pin *pin)
1308ab2a 16185+{
4a4d8108
AM
16186+ if (pin && pin->parent)
16187+ return au_h_dptr(pin->parent, pin->bindex);
16188+ return NULL;
dece6358 16189+}
1facf9fc 16190+
4a4d8108 16191+void au_unpin(struct au_pin *p)
dece6358 16192+{
e49829fe 16193+ if (p->h_mnt && au_ftest_pin(p->flags, MNT_WRITE))
b4510431 16194+ vfsub_mnt_drop_write(p->h_mnt);
4a4d8108
AM
16195+ if (!p->hdir)
16196+ return;
1facf9fc 16197+
4a4d8108
AM
16198+ au_hn_imtx_unlock(p->hdir);
16199+ if (!au_ftest_pin(p->flags, DI_LOCKED))
16200+ di_read_unlock(p->parent, AuLock_IR);
16201+ iput(p->hdir->hi_inode);
16202+ dput(p->parent);
16203+ p->parent = NULL;
16204+ p->hdir = NULL;
16205+ p->h_mnt = NULL;
16206+}
1308ab2a 16207+
4a4d8108
AM
16208+int au_do_pin(struct au_pin *p)
16209+{
16210+ int err;
16211+ struct super_block *sb;
16212+ struct dentry *h_dentry, *h_parent;
16213+ struct au_branch *br;
16214+ struct inode *h_dir;
16215+
16216+ err = 0;
16217+ sb = p->dentry->d_sb;
16218+ br = au_sbr(sb, p->bindex);
16219+ if (IS_ROOT(p->dentry)) {
16220+ if (au_ftest_pin(p->flags, MNT_WRITE)) {
16221+ p->h_mnt = br->br_mnt;
b4510431 16222+ err = vfsub_mnt_want_write(p->h_mnt);
4a4d8108
AM
16223+ if (unlikely(err)) {
16224+ au_fclr_pin(p->flags, MNT_WRITE);
16225+ goto out_err;
16226+ }
16227+ }
dece6358 16228+ goto out;
1facf9fc 16229+ }
16230+
4a4d8108
AM
16231+ h_dentry = NULL;
16232+ if (p->bindex <= au_dbend(p->dentry))
16233+ h_dentry = au_h_dptr(p->dentry, p->bindex);
dece6358 16234+
4a4d8108
AM
16235+ p->parent = dget_parent(p->dentry);
16236+ if (!au_ftest_pin(p->flags, DI_LOCKED))
16237+ di_read_lock(p->parent, AuLock_IR, p->lsc_di);
dece6358 16238+
4a4d8108
AM
16239+ h_dir = NULL;
16240+ h_parent = au_h_dptr(p->parent, p->bindex);
16241+ p->hdir = au_hi(p->parent->d_inode, p->bindex);
16242+ if (p->hdir)
16243+ h_dir = p->hdir->hi_inode;
dece6358 16244+
b752ccd1
AM
16245+ /*
16246+ * udba case, or
16247+ * if DI_LOCKED is not set, then p->parent may be different
16248+ * and h_parent can be NULL.
16249+ */
16250+ if (unlikely(!p->hdir || !h_dir || !h_parent)) {
e49829fe 16251+ err = -EBUSY;
4a4d8108
AM
16252+ if (!au_ftest_pin(p->flags, DI_LOCKED))
16253+ di_read_unlock(p->parent, AuLock_IR);
16254+ dput(p->parent);
16255+ p->parent = NULL;
16256+ goto out_err;
16257+ }
1308ab2a 16258+
4a4d8108
AM
16259+ au_igrab(h_dir);
16260+ au_hn_imtx_lock_nested(p->hdir, p->lsc_hi);
1308ab2a 16261+
4a4d8108
AM
16262+ if (unlikely(p->hdir->hi_inode != h_parent->d_inode)) {
16263+ err = -EBUSY;
16264+ goto out_unpin;
16265+ }
16266+ if (h_dentry) {
16267+ err = au_h_verify(h_dentry, p->udba, h_dir, h_parent, br);
16268+ if (unlikely(err)) {
16269+ au_fclr_pin(p->flags, MNT_WRITE);
16270+ goto out_unpin;
16271+ }
1facf9fc 16272+ }
dece6358 16273+
4a4d8108
AM
16274+ if (au_ftest_pin(p->flags, MNT_WRITE)) {
16275+ p->h_mnt = br->br_mnt;
b4510431 16276+ err = vfsub_mnt_want_write(p->h_mnt);
dece6358 16277+ if (unlikely(err)) {
4a4d8108
AM
16278+ au_fclr_pin(p->flags, MNT_WRITE);
16279+ goto out_unpin;
dece6358
AM
16280+ }
16281+ }
4a4d8108
AM
16282+ goto out; /* success */
16283+
4f0767ce 16284+out_unpin:
4a4d8108 16285+ au_unpin(p);
4f0767ce 16286+out_err:
4a4d8108
AM
16287+ pr_err("err %d\n", err);
16288+ err = au_busy_or_stale();
4f0767ce 16289+out:
1facf9fc 16290+ return err;
16291+}
16292+
4a4d8108
AM
16293+void au_pin_init(struct au_pin *p, struct dentry *dentry,
16294+ aufs_bindex_t bindex, int lsc_di, int lsc_hi,
16295+ unsigned int udba, unsigned char flags)
16296+{
16297+ p->dentry = dentry;
16298+ p->udba = udba;
16299+ p->lsc_di = lsc_di;
16300+ p->lsc_hi = lsc_hi;
16301+ p->flags = flags;
16302+ p->bindex = bindex;
16303+
16304+ p->parent = NULL;
16305+ p->hdir = NULL;
16306+ p->h_mnt = NULL;
16307+}
16308+
16309+int au_pin(struct au_pin *pin, struct dentry *dentry, aufs_bindex_t bindex,
16310+ unsigned int udba, unsigned char flags)
16311+{
16312+ au_pin_init(pin, dentry, bindex, AuLsc_DI_PARENT, AuLsc_I_PARENT2,
16313+ udba, flags);
16314+ return au_do_pin(pin);
16315+}
16316+
dece6358
AM
16317+/* ---------------------------------------------------------------------- */
16318+
1308ab2a 16319+/*
4a4d8108
AM
16320+ * ->setattr() and ->getattr() are called in various cases.
16321+ * chmod, stat: dentry is revalidated.
16322+ * fchmod, fstat: file and dentry are not revalidated, additionally they may be
16323+ * unhashed.
16324+ * for ->setattr(), ia->ia_file is passed from ftruncate only.
1308ab2a 16325+ */
027c5e7a 16326+/* todo: consolidate with do_refresh() and simple_reval_dpath() */
4a4d8108 16327+static int au_reval_for_attr(struct dentry *dentry, unsigned int sigen)
1facf9fc 16328+{
4a4d8108
AM
16329+ int err;
16330+ struct inode *inode;
16331+ struct dentry *parent;
1facf9fc 16332+
1308ab2a 16333+ err = 0;
4a4d8108 16334+ inode = dentry->d_inode;
027c5e7a 16335+ if (au_digen_test(dentry, sigen)) {
4a4d8108
AM
16336+ parent = dget_parent(dentry);
16337+ di_read_lock_parent(parent, AuLock_IR);
027c5e7a 16338+ err = au_refresh_dentry(dentry, parent);
4a4d8108
AM
16339+ di_read_unlock(parent, AuLock_IR);
16340+ dput(parent);
dece6358 16341+ }
1facf9fc 16342+
4a4d8108 16343+ AuTraceErr(err);
1308ab2a 16344+ return err;
16345+}
dece6358 16346+
4a4d8108
AM
16347+#define AuIcpup_DID_CPUP 1
16348+#define au_ftest_icpup(flags, name) ((flags) & AuIcpup_##name)
7f207e10
AM
16349+#define au_fset_icpup(flags, name) \
16350+ do { (flags) |= AuIcpup_##name; } while (0)
16351+#define au_fclr_icpup(flags, name) \
16352+ do { (flags) &= ~AuIcpup_##name; } while (0)
1308ab2a 16353+
4a4d8108
AM
16354+struct au_icpup_args {
16355+ unsigned char flags;
16356+ unsigned char pin_flags;
16357+ aufs_bindex_t btgt;
16358+ unsigned int udba;
16359+ struct au_pin pin;
16360+ struct path h_path;
16361+ struct inode *h_inode;
16362+};
1308ab2a 16363+
4a4d8108
AM
16364+static int au_pin_and_icpup(struct dentry *dentry, struct iattr *ia,
16365+ struct au_icpup_args *a)
1308ab2a 16366+{
16367+ int err;
4a4d8108 16368+ loff_t sz;
e49829fe 16369+ aufs_bindex_t bstart, ibstart;
4a4d8108
AM
16370+ struct dentry *hi_wh, *parent;
16371+ struct inode *inode;
16372+ struct file *h_file;
16373+ struct au_wr_dir_args wr_dir_args = {
16374+ .force_btgt = -1,
16375+ .flags = 0
16376+ };
16377+
16378+ bstart = au_dbstart(dentry);
16379+ inode = dentry->d_inode;
16380+ if (S_ISDIR(inode->i_mode))
16381+ au_fset_wrdir(wr_dir_args.flags, ISDIR);
16382+ /* plink or hi_wh() case */
e49829fe 16383+ ibstart = au_ibstart(inode);
027c5e7a 16384+ if (bstart != ibstart && !au_test_ro(inode->i_sb, ibstart, inode))
e49829fe 16385+ wr_dir_args.force_btgt = ibstart;
4a4d8108
AM
16386+ err = au_wr_dir(dentry, /*src_dentry*/NULL, &wr_dir_args);
16387+ if (unlikely(err < 0))
16388+ goto out;
16389+ a->btgt = err;
16390+ if (err != bstart)
16391+ au_fset_icpup(a->flags, DID_CPUP);
16392+
16393+ err = 0;
16394+ a->pin_flags = AuPin_MNT_WRITE;
16395+ parent = NULL;
16396+ if (!IS_ROOT(dentry)) {
16397+ au_fset_pin(a->pin_flags, DI_LOCKED);
16398+ parent = dget_parent(dentry);
16399+ di_write_lock_parent(parent);
16400+ }
16401+
16402+ err = au_pin(&a->pin, dentry, a->btgt, a->udba, a->pin_flags);
16403+ if (unlikely(err))
16404+ goto out_parent;
16405+
16406+ a->h_path.dentry = au_h_dptr(dentry, bstart);
16407+ a->h_inode = a->h_path.dentry->d_inode;
16408+ mutex_lock_nested(&a->h_inode->i_mutex, AuLsc_I_CHILD);
16409+ sz = -1;
16410+ if ((ia->ia_valid & ATTR_SIZE) && ia->ia_size < i_size_read(a->h_inode))
16411+ sz = ia->ia_size;
16412+
16413+ h_file = NULL;
16414+ hi_wh = NULL;
027c5e7a 16415+ if (au_ftest_icpup(a->flags, DID_CPUP) && d_unlinked(dentry)) {
4a4d8108
AM
16416+ hi_wh = au_hi_wh(inode, a->btgt);
16417+ if (!hi_wh) {
16418+ err = au_sio_cpup_wh(dentry, a->btgt, sz, /*file*/NULL);
16419+ if (unlikely(err))
16420+ goto out_unlock;
16421+ hi_wh = au_hi_wh(inode, a->btgt);
16422+ /* todo: revalidate hi_wh? */
16423+ }
16424+ }
16425+
16426+ if (parent) {
16427+ au_pin_set_parent_lflag(&a->pin, /*lflag*/0);
16428+ di_downgrade_lock(parent, AuLock_IR);
16429+ dput(parent);
16430+ parent = NULL;
16431+ }
16432+ if (!au_ftest_icpup(a->flags, DID_CPUP))
16433+ goto out; /* success */
16434+
16435+ if (!d_unhashed(dentry)) {
16436+ h_file = au_h_open_pre(dentry, bstart);
16437+ if (IS_ERR(h_file)) {
16438+ err = PTR_ERR(h_file);
16439+ h_file = NULL;
16440+ } else
16441+ err = au_sio_cpup_simple(dentry, a->btgt, sz,
16442+ AuCpup_DTIME);
16443+ if (!err)
16444+ a->h_path.dentry = au_h_dptr(dentry, a->btgt);
16445+ } else if (!hi_wh)
16446+ a->h_path.dentry = au_h_dptr(dentry, a->btgt);
16447+ else
16448+ a->h_path.dentry = hi_wh; /* do not dget here */
1308ab2a 16449+
4f0767ce 16450+out_unlock:
4a4d8108
AM
16451+ mutex_unlock(&a->h_inode->i_mutex);
16452+ au_h_open_post(dentry, bstart, h_file);
16453+ a->h_inode = a->h_path.dentry->d_inode;
dece6358 16454+ if (!err) {
4a4d8108 16455+ mutex_lock_nested(&a->h_inode->i_mutex, AuLsc_I_CHILD);
dece6358 16456+ goto out; /* success */
1facf9fc 16457+ }
dece6358 16458+
4a4d8108 16459+ au_unpin(&a->pin);
4f0767ce 16460+out_parent:
4a4d8108
AM
16461+ if (parent) {
16462+ di_write_unlock(parent);
16463+ dput(parent);
16464+ }
4f0767ce 16465+out:
1facf9fc 16466+ return err;
16467+}
16468+
4a4d8108 16469+static int aufs_setattr(struct dentry *dentry, struct iattr *ia)
1facf9fc 16470+{
4a4d8108
AM
16471+ int err;
16472+ struct inode *inode;
16473+ struct super_block *sb;
16474+ struct file *file;
16475+ struct au_icpup_args *a;
1facf9fc 16476+
4a4d8108
AM
16477+ inode = dentry->d_inode;
16478+ IMustLock(inode);
dece6358 16479+
4a4d8108
AM
16480+ err = -ENOMEM;
16481+ a = kzalloc(sizeof(*a), GFP_NOFS);
16482+ if (unlikely(!a))
16483+ goto out;
1facf9fc 16484+
4a4d8108
AM
16485+ if (ia->ia_valid & (ATTR_KILL_SUID | ATTR_KILL_SGID))
16486+ ia->ia_valid &= ~ATTR_MODE;
dece6358 16487+
4a4d8108
AM
16488+ file = NULL;
16489+ sb = dentry->d_sb;
e49829fe
JR
16490+ err = si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLM);
16491+ if (unlikely(err))
16492+ goto out_kfree;
16493+
4a4d8108
AM
16494+ if (ia->ia_valid & ATTR_FILE) {
16495+ /* currently ftruncate(2) only */
16496+ AuDebugOn(!S_ISREG(inode->i_mode));
16497+ file = ia->ia_file;
16498+ err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/1);
16499+ if (unlikely(err))
16500+ goto out_si;
16501+ ia->ia_file = au_hf_top(file);
16502+ a->udba = AuOpt_UDBA_NONE;
16503+ } else {
16504+ /* fchmod() doesn't pass ia_file */
16505+ a->udba = au_opt_udba(sb);
027c5e7a
AM
16506+ di_write_lock_child(dentry);
16507+ /* no d_unlinked(), to set UDBA_NONE for root */
4a4d8108
AM
16508+ if (d_unhashed(dentry))
16509+ a->udba = AuOpt_UDBA_NONE;
4a4d8108
AM
16510+ if (a->udba != AuOpt_UDBA_NONE) {
16511+ AuDebugOn(IS_ROOT(dentry));
16512+ err = au_reval_for_attr(dentry, au_sigen(sb));
16513+ if (unlikely(err))
16514+ goto out_dentry;
16515+ }
dece6358 16516+ }
dece6358 16517+
4a4d8108
AM
16518+ err = au_pin_and_icpup(dentry, ia, a);
16519+ if (unlikely(err < 0))
16520+ goto out_dentry;
16521+ if (au_ftest_icpup(a->flags, DID_CPUP)) {
16522+ ia->ia_file = NULL;
16523+ ia->ia_valid &= ~ATTR_FILE;
1308ab2a 16524+ }
dece6358 16525+
4a4d8108
AM
16526+ a->h_path.mnt = au_sbr_mnt(sb, a->btgt);
16527+ if ((ia->ia_valid & (ATTR_MODE | ATTR_CTIME))
16528+ == (ATTR_MODE | ATTR_CTIME)) {
7eafdf33 16529+ err = security_path_chmod(&a->h_path, ia->ia_mode);
4a4d8108
AM
16530+ if (unlikely(err))
16531+ goto out_unlock;
16532+ } else if ((ia->ia_valid & (ATTR_UID | ATTR_GID))
16533+ && (ia->ia_valid & ATTR_CTIME)) {
0c3ec466
AM
16534+ err = security_path_chown(&a->h_path, vfsub_ia_uid(ia),
16535+ vfsub_ia_gid(ia));
4a4d8108
AM
16536+ if (unlikely(err))
16537+ goto out_unlock;
16538+ }
dece6358 16539+
4a4d8108
AM
16540+ if (ia->ia_valid & ATTR_SIZE) {
16541+ struct file *f;
1308ab2a 16542+
953406b4 16543+ if (ia->ia_size < i_size_read(inode))
4a4d8108 16544+ /* unmap only */
953406b4 16545+ truncate_setsize(inode, ia->ia_size);
1308ab2a 16546+
4a4d8108
AM
16547+ f = NULL;
16548+ if (ia->ia_valid & ATTR_FILE)
16549+ f = ia->ia_file;
16550+ mutex_unlock(&a->h_inode->i_mutex);
16551+ err = vfsub_trunc(&a->h_path, ia->ia_size, ia->ia_valid, f);
16552+ mutex_lock_nested(&a->h_inode->i_mutex, AuLsc_I_CHILD);
16553+ } else
16554+ err = vfsub_notify_change(&a->h_path, ia);
16555+ if (!err)
16556+ au_cpup_attr_changeable(inode);
1308ab2a 16557+
4f0767ce 16558+out_unlock:
4a4d8108
AM
16559+ mutex_unlock(&a->h_inode->i_mutex);
16560+ au_unpin(&a->pin);
027c5e7a
AM
16561+ if (unlikely(err))
16562+ au_update_dbstart(dentry);
4f0767ce 16563+out_dentry:
4a4d8108
AM
16564+ di_write_unlock(dentry);
16565+ if (file) {
16566+ fi_write_unlock(file);
16567+ ia->ia_file = file;
16568+ ia->ia_valid |= ATTR_FILE;
16569+ }
4f0767ce 16570+out_si:
4a4d8108 16571+ si_read_unlock(sb);
e49829fe 16572+out_kfree:
4a4d8108 16573+ kfree(a);
4f0767ce 16574+out:
4a4d8108
AM
16575+ AuTraceErr(err);
16576+ return err;
1facf9fc 16577+}
16578+
4a4d8108
AM
16579+static void au_refresh_iattr(struct inode *inode, struct kstat *st,
16580+ unsigned int nlink)
1facf9fc 16581+{
9dbd164d
AM
16582+ unsigned int n;
16583+
4a4d8108 16584+ inode->i_mode = st->mode;
0c3ec466
AM
16585+ i_uid_write(inode, st->uid);
16586+ i_gid_write(inode, st->gid);
4a4d8108
AM
16587+ inode->i_atime = st->atime;
16588+ inode->i_mtime = st->mtime;
16589+ inode->i_ctime = st->ctime;
1facf9fc 16590+
4a4d8108
AM
16591+ au_cpup_attr_nlink(inode, /*force*/0);
16592+ if (S_ISDIR(inode->i_mode)) {
9dbd164d
AM
16593+ n = inode->i_nlink;
16594+ n -= nlink;
16595+ n += st->nlink;
7eafdf33 16596+ /* 0 can happen */
92d182d2 16597+ set_nlink(inode, n);
4a4d8108 16598+ }
1facf9fc 16599+
4a4d8108
AM
16600+ spin_lock(&inode->i_lock);
16601+ inode->i_blocks = st->blocks;
16602+ i_size_write(inode, st->size);
16603+ spin_unlock(&inode->i_lock);
1facf9fc 16604+}
16605+
4a4d8108
AM
16606+static int aufs_getattr(struct vfsmount *mnt __maybe_unused,
16607+ struct dentry *dentry, struct kstat *st)
1facf9fc 16608+{
4a4d8108
AM
16609+ int err;
16610+ unsigned int mnt_flags;
16611+ aufs_bindex_t bindex;
16612+ unsigned char udba_none, positive;
16613+ struct super_block *sb, *h_sb;
16614+ struct inode *inode;
16615+ struct vfsmount *h_mnt;
16616+ struct dentry *h_dentry;
1facf9fc 16617+
4a4d8108
AM
16618+ sb = dentry->d_sb;
16619+ inode = dentry->d_inode;
7f207e10
AM
16620+ err = si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLM);
16621+ if (unlikely(err))
16622+ goto out;
4a4d8108
AM
16623+ mnt_flags = au_mntflags(sb);
16624+ udba_none = !!au_opt_test(mnt_flags, UDBA_NONE);
1facf9fc 16625+
4a4d8108 16626+ /* support fstat(2) */
027c5e7a 16627+ if (!d_unlinked(dentry) && !udba_none) {
4a4d8108 16628+ unsigned int sigen = au_sigen(sb);
027c5e7a
AM
16629+ err = au_digen_test(dentry, sigen);
16630+ if (!err) {
4a4d8108 16631+ di_read_lock_child(dentry, AuLock_IR);
027c5e7a
AM
16632+ err = au_dbrange_test(dentry);
16633+ if (unlikely(err))
16634+ goto out_unlock;
16635+ } else {
4a4d8108
AM
16636+ AuDebugOn(IS_ROOT(dentry));
16637+ di_write_lock_child(dentry);
027c5e7a
AM
16638+ err = au_dbrange_test(dentry);
16639+ if (!err)
16640+ err = au_reval_for_attr(dentry, sigen);
4a4d8108
AM
16641+ di_downgrade_lock(dentry, AuLock_IR);
16642+ if (unlikely(err))
7f207e10 16643+ goto out_unlock;
4a4d8108
AM
16644+ }
16645+ } else
16646+ di_read_lock_child(dentry, AuLock_IR);
1facf9fc 16647+
4a4d8108
AM
16648+ bindex = au_ibstart(inode);
16649+ h_mnt = au_sbr_mnt(sb, bindex);
16650+ h_sb = h_mnt->mnt_sb;
16651+ if (!au_test_fs_bad_iattr(h_sb) && udba_none)
16652+ goto out_fill; /* success */
1facf9fc 16653+
4a4d8108
AM
16654+ h_dentry = NULL;
16655+ if (au_dbstart(dentry) == bindex)
16656+ h_dentry = dget(au_h_dptr(dentry, bindex));
16657+ else if (au_opt_test(mnt_flags, PLINK) && au_plink_test(inode)) {
16658+ h_dentry = au_plink_lkup(inode, bindex);
16659+ if (IS_ERR(h_dentry))
16660+ goto out_fill; /* pretending success */
16661+ }
16662+ /* illegally overlapped or something */
16663+ if (unlikely(!h_dentry))
16664+ goto out_fill; /* pretending success */
16665+
16666+ positive = !!h_dentry->d_inode;
16667+ if (positive)
16668+ err = vfs_getattr(h_mnt, h_dentry, st);
16669+ dput(h_dentry);
16670+ if (!err) {
16671+ if (positive)
16672+ au_refresh_iattr(inode, st, h_dentry->d_inode->i_nlink);
16673+ goto out_fill; /* success */
1facf9fc 16674+ }
7f207e10
AM
16675+ AuTraceErr(err);
16676+ goto out_unlock;
4a4d8108 16677+
4f0767ce 16678+out_fill:
4a4d8108 16679+ generic_fillattr(inode, st);
7f207e10 16680+out_unlock:
4a4d8108
AM
16681+ di_read_unlock(dentry, AuLock_IR);
16682+ si_read_unlock(sb);
7f207e10
AM
16683+out:
16684+ AuTraceErr(err);
4a4d8108 16685+ return err;
1facf9fc 16686+}
16687+
16688+/* ---------------------------------------------------------------------- */
16689+
4a4d8108
AM
16690+static int h_readlink(struct dentry *dentry, int bindex, char __user *buf,
16691+ int bufsiz)
1facf9fc 16692+{
16693+ int err;
4a4d8108
AM
16694+ struct super_block *sb;
16695+ struct dentry *h_dentry;
1facf9fc 16696+
4a4d8108
AM
16697+ err = -EINVAL;
16698+ h_dentry = au_h_dptr(dentry, bindex);
16699+ if (unlikely(!h_dentry->d_inode->i_op->readlink))
16700+ goto out;
1facf9fc 16701+
4a4d8108
AM
16702+ err = security_inode_readlink(h_dentry);
16703+ if (unlikely(err))
dece6358 16704+ goto out;
1facf9fc 16705+
4a4d8108
AM
16706+ sb = dentry->d_sb;
16707+ if (!au_test_ro(sb, bindex, dentry->d_inode)) {
16708+ vfsub_touch_atime(au_sbr_mnt(sb, bindex), h_dentry);
16709+ fsstack_copy_attr_atime(dentry->d_inode, h_dentry->d_inode);
1facf9fc 16710+ }
4a4d8108 16711+ err = h_dentry->d_inode->i_op->readlink(h_dentry, buf, bufsiz);
1facf9fc 16712+
4f0767ce 16713+out:
4a4d8108
AM
16714+ return err;
16715+}
1facf9fc 16716+
4a4d8108
AM
16717+static int aufs_readlink(struct dentry *dentry, char __user *buf, int bufsiz)
16718+{
16719+ int err;
1facf9fc 16720+
027c5e7a
AM
16721+ err = aufs_read_lock(dentry, AuLock_IR | AuLock_GEN);
16722+ if (unlikely(err))
16723+ goto out;
16724+ err = au_d_hashed_positive(dentry);
16725+ if (!err)
16726+ err = h_readlink(dentry, au_dbstart(dentry), buf, bufsiz);
4a4d8108 16727+ aufs_read_unlock(dentry, AuLock_IR);
1facf9fc 16728+
027c5e7a 16729+out:
4a4d8108
AM
16730+ return err;
16731+}
1facf9fc 16732+
4a4d8108
AM
16733+static void *aufs_follow_link(struct dentry *dentry, struct nameidata *nd)
16734+{
16735+ int err;
4a4d8108 16736+ mm_segment_t old_fs;
b752ccd1
AM
16737+ union {
16738+ char *k;
16739+ char __user *u;
16740+ } buf;
1facf9fc 16741+
4a4d8108 16742+ err = -ENOMEM;
537831f9 16743+ buf.k = (void *)__get_free_page(GFP_NOFS);
b752ccd1 16744+ if (unlikely(!buf.k))
4a4d8108 16745+ goto out;
1facf9fc 16746+
027c5e7a
AM
16747+ err = aufs_read_lock(dentry, AuLock_IR | AuLock_GEN);
16748+ if (unlikely(err))
16749+ goto out_name;
16750+
16751+ err = au_d_hashed_positive(dentry);
16752+ if (!err) {
16753+ old_fs = get_fs();
16754+ set_fs(KERNEL_DS);
16755+ err = h_readlink(dentry, au_dbstart(dentry), buf.u, PATH_MAX);
16756+ set_fs(old_fs);
16757+ }
4a4d8108 16758+ aufs_read_unlock(dentry, AuLock_IR);
1facf9fc 16759+
4a4d8108 16760+ if (err >= 0) {
b752ccd1 16761+ buf.k[err] = 0;
4a4d8108 16762+ /* will be freed by put_link */
b752ccd1 16763+ nd_set_link(nd, buf.k);
4a4d8108 16764+ return NULL; /* success */
1308ab2a 16765+ }
1facf9fc 16766+
027c5e7a 16767+out_name:
537831f9 16768+ free_page((unsigned long)buf.k);
4f0767ce 16769+out:
4a4d8108
AM
16770+ AuTraceErr(err);
16771+ return ERR_PTR(err);
16772+}
1facf9fc 16773+
4a4d8108
AM
16774+static void aufs_put_link(struct dentry *dentry __maybe_unused,
16775+ struct nameidata *nd, void *cookie __maybe_unused)
16776+{
537831f9
AM
16777+ char *p;
16778+
16779+ p = nd_get_link(nd);
16780+ if (!IS_ERR_OR_NULL(p))
16781+ free_page((unsigned long)p);
4a4d8108 16782+}
1facf9fc 16783+
4a4d8108 16784+/* ---------------------------------------------------------------------- */
1facf9fc 16785+
0c3ec466 16786+static int aufs_update_time(struct inode *inode, struct timespec *ts, int flags)
4a4d8108 16787+{
0c3ec466
AM
16788+ int err;
16789+ struct super_block *sb;
16790+ struct inode *h_inode;
16791+
16792+ sb = inode->i_sb;
16793+ /* mmap_sem might be acquired already, cf. aufs_mmap() */
16794+ lockdep_off();
16795+ si_read_lock(sb, AuLock_FLUSH);
16796+ ii_write_lock_child(inode);
16797+ lockdep_on();
16798+ h_inode = au_h_iptr(inode, au_ibstart(inode));
16799+ err = vfsub_update_time(h_inode, ts, flags);
16800+ lockdep_off();
16801+ ii_write_unlock(inode);
16802+ si_read_unlock(sb);
16803+ lockdep_on();
16804+ return err;
4a4d8108 16805+}
1facf9fc 16806+
4a4d8108 16807+/* ---------------------------------------------------------------------- */
1308ab2a 16808+
4a4d8108
AM
16809+struct inode_operations aufs_symlink_iop = {
16810+ .permission = aufs_permission,
16811+ .setattr = aufs_setattr,
16812+ .getattr = aufs_getattr,
0c3ec466 16813+
4a4d8108
AM
16814+ .readlink = aufs_readlink,
16815+ .follow_link = aufs_follow_link,
0c3ec466
AM
16816+ .put_link = aufs_put_link,
16817+
16818+ /* .update_time = aufs_update_time */
4a4d8108
AM
16819+};
16820+
16821+struct inode_operations aufs_dir_iop = {
16822+ .create = aufs_create,
16823+ .lookup = aufs_lookup,
16824+ .link = aufs_link,
16825+ .unlink = aufs_unlink,
16826+ .symlink = aufs_symlink,
16827+ .mkdir = aufs_mkdir,
16828+ .rmdir = aufs_rmdir,
16829+ .mknod = aufs_mknod,
16830+ .rename = aufs_rename,
16831+
16832+ .permission = aufs_permission,
16833+ .setattr = aufs_setattr,
0c3ec466
AM
16834+ .getattr = aufs_getattr,
16835+
16836+ .update_time = aufs_update_time
b4510431 16837+ /* no support for atomic_open() */
4a4d8108
AM
16838+};
16839+
16840+struct inode_operations aufs_iop = {
16841+ .permission = aufs_permission,
16842+ .setattr = aufs_setattr,
16843+ .getattr = aufs_getattr,
0c3ec466
AM
16844+
16845+ .update_time = aufs_update_time
4a4d8108 16846+};
7f207e10
AM
16847diff -urN /usr/share/empty/fs/aufs/i_op_del.c linux/fs/aufs/i_op_del.c
16848--- /usr/share/empty/fs/aufs/i_op_del.c 1970-01-01 01:00:00.000000000 +0100
537831f9
AM
16849+++ linux/fs/aufs/i_op_del.c 2012-12-13 20:41:10.431460173 +0100
16850@@ -0,0 +1,477 @@
1facf9fc 16851+/*
f6c5ef8b 16852+ * Copyright (C) 2005-2012 Junjiro R. Okajima
1facf9fc 16853+ *
16854+ * This program, aufs is free software; you can redistribute it and/or modify
16855+ * it under the terms of the GNU General Public License as published by
16856+ * the Free Software Foundation; either version 2 of the License, or
16857+ * (at your option) any later version.
dece6358
AM
16858+ *
16859+ * This program is distributed in the hope that it will be useful,
16860+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
16861+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16862+ * GNU General Public License for more details.
16863+ *
16864+ * You should have received a copy of the GNU General Public License
16865+ * along with this program; if not, write to the Free Software
16866+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 16867+ */
16868+
16869+/*
4a4d8108 16870+ * inode operations (del entry)
1308ab2a 16871+ */
dece6358 16872+
1308ab2a 16873+#include "aufs.h"
dece6358 16874+
4a4d8108
AM
16875+/*
16876+ * decide if a new whiteout for @dentry is necessary or not.
16877+ * when it is necessary, prepare the parent dir for the upper branch whose
16878+ * branch index is @bcpup for creation. the actual creation of the whiteout will
16879+ * be done by caller.
16880+ * return value:
16881+ * 0: wh is unnecessary
16882+ * plus: wh is necessary
16883+ * minus: error
16884+ */
16885+int au_wr_dir_need_wh(struct dentry *dentry, int isdir, aufs_bindex_t *bcpup)
1308ab2a 16886+{
4a4d8108
AM
16887+ int need_wh, err;
16888+ aufs_bindex_t bstart;
16889+ struct super_block *sb;
dece6358 16890+
4a4d8108
AM
16891+ sb = dentry->d_sb;
16892+ bstart = au_dbstart(dentry);
16893+ if (*bcpup < 0) {
16894+ *bcpup = bstart;
16895+ if (au_test_ro(sb, bstart, dentry->d_inode)) {
16896+ err = AuWbrCopyup(au_sbi(sb), dentry);
16897+ *bcpup = err;
16898+ if (unlikely(err < 0))
16899+ goto out;
16900+ }
16901+ } else
16902+ AuDebugOn(bstart < *bcpup
16903+ || au_test_ro(sb, *bcpup, dentry->d_inode));
16904+ AuDbg("bcpup %d, bstart %d\n", *bcpup, bstart);
1308ab2a 16905+
4a4d8108
AM
16906+ if (*bcpup != bstart) {
16907+ err = au_cpup_dirs(dentry, *bcpup);
16908+ if (unlikely(err))
16909+ goto out;
16910+ need_wh = 1;
16911+ } else {
027c5e7a 16912+ struct au_dinfo *dinfo, *tmp;
4a4d8108 16913+
027c5e7a
AM
16914+ need_wh = -ENOMEM;
16915+ dinfo = au_di(dentry);
16916+ tmp = au_di_alloc(sb, AuLsc_DI_TMP);
16917+ if (tmp) {
16918+ au_di_cp(tmp, dinfo);
16919+ au_di_swap(tmp, dinfo);
16920+ /* returns the number of positive dentries */
537831f9 16921+ need_wh = au_lkup_dentry(dentry, bstart + 1, /*type*/0);
027c5e7a
AM
16922+ au_di_swap(tmp, dinfo);
16923+ au_rw_write_unlock(&tmp->di_rwsem);
16924+ au_di_free(tmp);
4a4d8108
AM
16925+ }
16926+ }
16927+ AuDbg("need_wh %d\n", need_wh);
16928+ err = need_wh;
16929+
4f0767ce 16930+out:
4a4d8108 16931+ return err;
1facf9fc 16932+}
16933+
4a4d8108
AM
16934+/*
16935+ * simple tests for the del-entry operations.
16936+ * following the checks in vfs, plus the parent-child relationship.
16937+ */
16938+int au_may_del(struct dentry *dentry, aufs_bindex_t bindex,
16939+ struct dentry *h_parent, int isdir)
1facf9fc 16940+{
4a4d8108
AM
16941+ int err;
16942+ umode_t h_mode;
16943+ struct dentry *h_dentry, *h_latest;
1308ab2a 16944+ struct inode *h_inode;
1facf9fc 16945+
4a4d8108
AM
16946+ h_dentry = au_h_dptr(dentry, bindex);
16947+ h_inode = h_dentry->d_inode;
16948+ if (dentry->d_inode) {
16949+ err = -ENOENT;
16950+ if (unlikely(!h_inode || !h_inode->i_nlink))
16951+ goto out;
1facf9fc 16952+
4a4d8108
AM
16953+ h_mode = h_inode->i_mode;
16954+ if (!isdir) {
16955+ err = -EISDIR;
16956+ if (unlikely(S_ISDIR(h_mode)))
16957+ goto out;
16958+ } else if (unlikely(!S_ISDIR(h_mode))) {
16959+ err = -ENOTDIR;
16960+ goto out;
16961+ }
16962+ } else {
16963+ /* rename(2) case */
16964+ err = -EIO;
16965+ if (unlikely(h_inode))
16966+ goto out;
16967+ }
1facf9fc 16968+
4a4d8108
AM
16969+ err = -ENOENT;
16970+ /* expected parent dir is locked */
16971+ if (unlikely(h_parent != h_dentry->d_parent))
16972+ goto out;
16973+ err = 0;
16974+
16975+ /*
16976+ * rmdir a dir may break the consistency on some filesystem.
16977+ * let's try heavy test.
16978+ */
16979+ err = -EACCES;
16980+ if (unlikely(au_test_h_perm(h_parent->d_inode, MAY_EXEC | MAY_WRITE)))
16981+ goto out;
16982+
16983+ h_latest = au_sio_lkup_one(&dentry->d_name, h_parent,
16984+ au_sbr(dentry->d_sb, bindex));
16985+ err = -EIO;
16986+ if (IS_ERR(h_latest))
16987+ goto out;
16988+ if (h_latest == h_dentry)
16989+ err = 0;
16990+ dput(h_latest);
16991+
4f0767ce 16992+out:
4a4d8108 16993+ return err;
1308ab2a 16994+}
1facf9fc 16995+
4a4d8108
AM
16996+/*
16997+ * decide the branch where we operate for @dentry. the branch index will be set
16998+ * @rbcpup. after diciding it, 'pin' it and store the timestamps of the parent
16999+ * dir for reverting.
17000+ * when a new whiteout is necessary, create it.
17001+ */
17002+static struct dentry*
17003+lock_hdir_create_wh(struct dentry *dentry, int isdir, aufs_bindex_t *rbcpup,
17004+ struct au_dtime *dt, struct au_pin *pin)
1308ab2a 17005+{
4a4d8108
AM
17006+ struct dentry *wh_dentry;
17007+ struct super_block *sb;
17008+ struct path h_path;
17009+ int err, need_wh;
17010+ unsigned int udba;
17011+ aufs_bindex_t bcpup;
dece6358 17012+
4a4d8108
AM
17013+ need_wh = au_wr_dir_need_wh(dentry, isdir, rbcpup);
17014+ wh_dentry = ERR_PTR(need_wh);
17015+ if (unlikely(need_wh < 0))
17016+ goto out;
17017+
17018+ sb = dentry->d_sb;
17019+ udba = au_opt_udba(sb);
17020+ bcpup = *rbcpup;
17021+ err = au_pin(pin, dentry, bcpup, udba,
17022+ AuPin_DI_LOCKED | AuPin_MNT_WRITE);
17023+ wh_dentry = ERR_PTR(err);
17024+ if (unlikely(err))
17025+ goto out;
17026+
17027+ h_path.dentry = au_pinned_h_parent(pin);
17028+ if (udba != AuOpt_UDBA_NONE
17029+ && au_dbstart(dentry) == bcpup) {
17030+ err = au_may_del(dentry, bcpup, h_path.dentry, isdir);
17031+ wh_dentry = ERR_PTR(err);
17032+ if (unlikely(err))
17033+ goto out_unpin;
17034+ }
17035+
17036+ h_path.mnt = au_sbr_mnt(sb, bcpup);
17037+ au_dtime_store(dt, au_pinned_parent(pin), &h_path);
17038+ wh_dentry = NULL;
17039+ if (!need_wh)
17040+ goto out; /* success, no need to create whiteout */
17041+
17042+ wh_dentry = au_wh_create(dentry, bcpup, h_path.dentry);
17043+ if (IS_ERR(wh_dentry))
17044+ goto out_unpin;
17045+
17046+ /* returns with the parent is locked and wh_dentry is dget-ed */
17047+ goto out; /* success */
17048+
4f0767ce 17049+out_unpin:
4a4d8108 17050+ au_unpin(pin);
4f0767ce 17051+out:
4a4d8108 17052+ return wh_dentry;
1facf9fc 17053+}
17054+
4a4d8108
AM
17055+/*
17056+ * when removing a dir, rename it to a unique temporary whiteout-ed name first
17057+ * in order to be revertible and save time for removing many child whiteouts
17058+ * under the dir.
17059+ * returns 1 when there are too many child whiteout and caller should remove
17060+ * them asynchronously. returns 0 when the number of children is enough small to
17061+ * remove now or the branch fs is a remote fs.
17062+ * otherwise return an error.
17063+ */
17064+static int renwh_and_rmdir(struct dentry *dentry, aufs_bindex_t bindex,
17065+ struct au_nhash *whlist, struct inode *dir)
1facf9fc 17066+{
4a4d8108
AM
17067+ int rmdir_later, err, dirwh;
17068+ struct dentry *h_dentry;
17069+ struct super_block *sb;
17070+
17071+ sb = dentry->d_sb;
17072+ SiMustAnyLock(sb);
17073+ h_dentry = au_h_dptr(dentry, bindex);
17074+ err = au_whtmp_ren(h_dentry, au_sbr(sb, bindex));
17075+ if (unlikely(err))
17076+ goto out;
17077+
17078+ /* stop monitoring */
17079+ au_hn_free(au_hi(dentry->d_inode, bindex));
17080+
17081+ if (!au_test_fs_remote(h_dentry->d_sb)) {
17082+ dirwh = au_sbi(sb)->si_dirwh;
17083+ rmdir_later = (dirwh <= 1);
17084+ if (!rmdir_later)
17085+ rmdir_later = au_nhash_test_longer_wh(whlist, bindex,
17086+ dirwh);
17087+ if (rmdir_later)
17088+ return rmdir_later;
17089+ }
1facf9fc 17090+
4a4d8108
AM
17091+ err = au_whtmp_rmdir(dir, bindex, h_dentry, whlist);
17092+ if (unlikely(err)) {
17093+ AuIOErr("rmdir %.*s, b%d failed, %d. ignored\n",
17094+ AuDLNPair(h_dentry), bindex, err);
17095+ err = 0;
17096+ }
dece6358 17097+
4f0767ce 17098+out:
4a4d8108
AM
17099+ AuTraceErr(err);
17100+ return err;
17101+}
1308ab2a 17102+
4a4d8108
AM
17103+/*
17104+ * final procedure for deleting a entry.
17105+ * maintain dentry and iattr.
17106+ */
17107+static void epilog(struct inode *dir, struct dentry *dentry,
17108+ aufs_bindex_t bindex)
17109+{
17110+ struct inode *inode;
1308ab2a 17111+
4a4d8108
AM
17112+ inode = dentry->d_inode;
17113+ d_drop(dentry);
17114+ inode->i_ctime = dir->i_ctime;
1308ab2a 17115+
4a4d8108
AM
17116+ if (au_ibstart(dir) == bindex)
17117+ au_cpup_attr_timesizes(dir);
17118+ dir->i_version++;
1facf9fc 17119+}
17120+
4a4d8108
AM
17121+/*
17122+ * when an error happened, remove the created whiteout and revert everything.
17123+ */
7f207e10
AM
17124+static int do_revert(int err, struct inode *dir, aufs_bindex_t bindex,
17125+ aufs_bindex_t bwh, struct dentry *wh_dentry,
17126+ struct dentry *dentry, struct au_dtime *dt)
1facf9fc 17127+{
4a4d8108
AM
17128+ int rerr;
17129+ struct path h_path = {
17130+ .dentry = wh_dentry,
7f207e10 17131+ .mnt = au_sbr_mnt(dir->i_sb, bindex)
4a4d8108 17132+ };
dece6358 17133+
7f207e10 17134+ rerr = au_wh_unlink_dentry(au_h_iptr(dir, bindex), &h_path, dentry);
4a4d8108
AM
17135+ if (!rerr) {
17136+ au_set_dbwh(dentry, bwh);
17137+ au_dtime_revert(dt);
17138+ return 0;
17139+ }
dece6358 17140+
4a4d8108
AM
17141+ AuIOErr("%.*s reverting whiteout failed(%d, %d)\n",
17142+ AuDLNPair(dentry), err, rerr);
17143+ return -EIO;
1facf9fc 17144+}
17145+
4a4d8108 17146+/* ---------------------------------------------------------------------- */
1facf9fc 17147+
4a4d8108 17148+int aufs_unlink(struct inode *dir, struct dentry *dentry)
1308ab2a 17149+{
4a4d8108
AM
17150+ int err;
17151+ aufs_bindex_t bwh, bindex, bstart;
17152+ struct au_dtime dt;
17153+ struct au_pin pin;
17154+ struct path h_path;
17155+ struct inode *inode, *h_dir;
17156+ struct dentry *parent, *wh_dentry;
1facf9fc 17157+
4a4d8108 17158+ IMustLock(dir);
027c5e7a
AM
17159+
17160+ err = aufs_read_lock(dentry, AuLock_DW | AuLock_GEN);
17161+ if (unlikely(err))
17162+ goto out;
17163+ err = au_d_hashed_positive(dentry);
17164+ if (unlikely(err))
17165+ goto out_unlock;
4a4d8108 17166+ inode = dentry->d_inode;
4a4d8108 17167+ IMustLock(inode);
027c5e7a
AM
17168+ err = -EISDIR;
17169+ if (unlikely(S_ISDIR(inode->i_mode)))
17170+ goto out_unlock; /* possible? */
1facf9fc 17171+
4a4d8108
AM
17172+ bstart = au_dbstart(dentry);
17173+ bwh = au_dbwh(dentry);
17174+ bindex = -1;
027c5e7a
AM
17175+ parent = dentry->d_parent; /* dir inode is locked */
17176+ di_write_lock_parent(parent);
4a4d8108
AM
17177+ wh_dentry = lock_hdir_create_wh(dentry, /*isdir*/0, &bindex, &dt, &pin);
17178+ err = PTR_ERR(wh_dentry);
17179+ if (IS_ERR(wh_dentry))
027c5e7a 17180+ goto out_parent;
1facf9fc 17181+
4a4d8108
AM
17182+ h_path.mnt = au_sbr_mnt(dentry->d_sb, bstart);
17183+ h_path.dentry = au_h_dptr(dentry, bstart);
17184+ dget(h_path.dentry);
17185+ if (bindex == bstart) {
17186+ h_dir = au_pinned_h_dir(&pin);
17187+ err = vfsub_unlink(h_dir, &h_path, /*force*/0);
17188+ } else {
17189+ /* dir inode is locked */
17190+ h_dir = wh_dentry->d_parent->d_inode;
17191+ IMustLock(h_dir);
17192+ err = 0;
17193+ }
dece6358 17194+
4a4d8108 17195+ if (!err) {
7f207e10 17196+ vfsub_drop_nlink(inode);
4a4d8108
AM
17197+ epilog(dir, dentry, bindex);
17198+
17199+ /* update target timestamps */
17200+ if (bindex == bstart) {
17201+ vfsub_update_h_iattr(&h_path, /*did*/NULL); /*ignore*/
17202+ inode->i_ctime = h_path.dentry->d_inode->i_ctime;
17203+ } else
17204+ /* todo: this timestamp may be reverted later */
17205+ inode->i_ctime = h_dir->i_ctime;
027c5e7a 17206+ goto out_unpin; /* success */
1facf9fc 17207+ }
17208+
4a4d8108
AM
17209+ /* revert */
17210+ if (wh_dentry) {
17211+ int rerr;
17212+
7f207e10 17213+ rerr = do_revert(err, dir, bindex, bwh, wh_dentry, dentry, &dt);
4a4d8108
AM
17214+ if (rerr)
17215+ err = rerr;
dece6358 17216+ }
1facf9fc 17217+
027c5e7a 17218+out_unpin:
4a4d8108
AM
17219+ au_unpin(&pin);
17220+ dput(wh_dentry);
17221+ dput(h_path.dentry);
027c5e7a 17222+out_parent:
4a4d8108 17223+ di_write_unlock(parent);
027c5e7a 17224+out_unlock:
4a4d8108 17225+ aufs_read_unlock(dentry, AuLock_DW);
027c5e7a 17226+out:
4a4d8108 17227+ return err;
dece6358
AM
17228+}
17229+
4a4d8108 17230+int aufs_rmdir(struct inode *dir, struct dentry *dentry)
1308ab2a 17231+{
4a4d8108
AM
17232+ int err, rmdir_later;
17233+ aufs_bindex_t bwh, bindex, bstart;
17234+ struct au_dtime dt;
17235+ struct au_pin pin;
17236+ struct inode *inode;
17237+ struct dentry *parent, *wh_dentry, *h_dentry;
17238+ struct au_whtmp_rmdir *args;
1facf9fc 17239+
4a4d8108 17240+ IMustLock(dir);
027c5e7a
AM
17241+
17242+ err = aufs_read_lock(dentry, AuLock_DW | AuLock_FLUSH | AuLock_GEN);
17243+ if (unlikely(err))
4a4d8108 17244+ goto out;
53392da6
AM
17245+ err = au_alive_dir(dentry);
17246+ if (unlikely(err))
027c5e7a 17247+ goto out_unlock;
53392da6 17248+ inode = dentry->d_inode;
4a4d8108 17249+ IMustLock(inode);
027c5e7a
AM
17250+ err = -ENOTDIR;
17251+ if (unlikely(!S_ISDIR(inode->i_mode)))
17252+ goto out_unlock; /* possible? */
dece6358 17253+
4a4d8108
AM
17254+ err = -ENOMEM;
17255+ args = au_whtmp_rmdir_alloc(dir->i_sb, GFP_NOFS);
17256+ if (unlikely(!args))
17257+ goto out_unlock;
dece6358 17258+
4a4d8108
AM
17259+ parent = dentry->d_parent; /* dir inode is locked */
17260+ di_write_lock_parent(parent);
17261+ err = au_test_empty(dentry, &args->whlist);
17262+ if (unlikely(err))
027c5e7a 17263+ goto out_parent;
1facf9fc 17264+
4a4d8108
AM
17265+ bstart = au_dbstart(dentry);
17266+ bwh = au_dbwh(dentry);
17267+ bindex = -1;
17268+ wh_dentry = lock_hdir_create_wh(dentry, /*isdir*/1, &bindex, &dt, &pin);
17269+ err = PTR_ERR(wh_dentry);
17270+ if (IS_ERR(wh_dentry))
027c5e7a 17271+ goto out_parent;
1facf9fc 17272+
4a4d8108
AM
17273+ h_dentry = au_h_dptr(dentry, bstart);
17274+ dget(h_dentry);
17275+ rmdir_later = 0;
17276+ if (bindex == bstart) {
17277+ err = renwh_and_rmdir(dentry, bstart, &args->whlist, dir);
17278+ if (err > 0) {
17279+ rmdir_later = err;
17280+ err = 0;
17281+ }
17282+ } else {
17283+ /* stop monitoring */
17284+ au_hn_free(au_hi(inode, bstart));
17285+
17286+ /* dir inode is locked */
17287+ IMustLock(wh_dentry->d_parent->d_inode);
1facf9fc 17288+ err = 0;
17289+ }
17290+
4a4d8108 17291+ if (!err) {
027c5e7a 17292+ vfsub_dead_dir(inode);
4a4d8108
AM
17293+ au_set_dbdiropq(dentry, -1);
17294+ epilog(dir, dentry, bindex);
1308ab2a 17295+
4a4d8108
AM
17296+ if (rmdir_later) {
17297+ au_whtmp_kick_rmdir(dir, bstart, h_dentry, args);
17298+ args = NULL;
17299+ }
1308ab2a 17300+
4a4d8108 17301+ goto out_unpin; /* success */
1facf9fc 17302+ }
17303+
4a4d8108
AM
17304+ /* revert */
17305+ AuLabel(revert);
17306+ if (wh_dentry) {
17307+ int rerr;
1308ab2a 17308+
7f207e10 17309+ rerr = do_revert(err, dir, bindex, bwh, wh_dentry, dentry, &dt);
4a4d8108
AM
17310+ if (rerr)
17311+ err = rerr;
1facf9fc 17312+ }
17313+
4f0767ce 17314+out_unpin:
4a4d8108
AM
17315+ au_unpin(&pin);
17316+ dput(wh_dentry);
17317+ dput(h_dentry);
027c5e7a 17318+out_parent:
4a4d8108
AM
17319+ di_write_unlock(parent);
17320+ if (args)
17321+ au_whtmp_rmdir_free(args);
4f0767ce 17322+out_unlock:
4a4d8108 17323+ aufs_read_unlock(dentry, AuLock_DW);
4f0767ce 17324+out:
4a4d8108
AM
17325+ AuTraceErr(err);
17326+ return err;
dece6358 17327+}
7f207e10
AM
17328diff -urN /usr/share/empty/fs/aufs/i_op_ren.c linux/fs/aufs/i_op_ren.c
17329--- /usr/share/empty/fs/aufs/i_op_ren.c 1970-01-01 01:00:00.000000000 +0100
537831f9 17330+++ linux/fs/aufs/i_op_ren.c 2012-12-13 20:41:10.431460173 +0100
7eafdf33 17331@@ -0,0 +1,1026 @@
1facf9fc 17332+/*
f6c5ef8b 17333+ * Copyright (C) 2005-2012 Junjiro R. Okajima
1facf9fc 17334+ *
17335+ * This program, aufs is free software; you can redistribute it and/or modify
17336+ * it under the terms of the GNU General Public License as published by
17337+ * the Free Software Foundation; either version 2 of the License, or
17338+ * (at your option) any later version.
dece6358
AM
17339+ *
17340+ * This program is distributed in the hope that it will be useful,
17341+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
17342+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17343+ * GNU General Public License for more details.
17344+ *
17345+ * You should have received a copy of the GNU General Public License
17346+ * along with this program; if not, write to the Free Software
17347+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 17348+ */
17349+
17350+/*
4a4d8108
AM
17351+ * inode operation (rename entry)
17352+ * todo: this is crazy monster
1facf9fc 17353+ */
17354+
17355+#include "aufs.h"
17356+
4a4d8108
AM
17357+enum { AuSRC, AuDST, AuSrcDst };
17358+enum { AuPARENT, AuCHILD, AuParentChild };
1facf9fc 17359+
4a4d8108
AM
17360+#define AuRen_ISDIR 1
17361+#define AuRen_ISSAMEDIR (1 << 1)
17362+#define AuRen_WHSRC (1 << 2)
17363+#define AuRen_WHDST (1 << 3)
17364+#define AuRen_MNT_WRITE (1 << 4)
17365+#define AuRen_DT_DSTDIR (1 << 5)
17366+#define AuRen_DIROPQ (1 << 6)
17367+#define AuRen_CPUP (1 << 7)
17368+#define au_ftest_ren(flags, name) ((flags) & AuRen_##name)
7f207e10
AM
17369+#define au_fset_ren(flags, name) \
17370+ do { (flags) |= AuRen_##name; } while (0)
17371+#define au_fclr_ren(flags, name) \
17372+ do { (flags) &= ~AuRen_##name; } while (0)
1facf9fc 17373+
4a4d8108
AM
17374+struct au_ren_args {
17375+ struct {
17376+ struct dentry *dentry, *h_dentry, *parent, *h_parent,
17377+ *wh_dentry;
17378+ struct inode *dir, *inode;
17379+ struct au_hinode *hdir;
17380+ struct au_dtime dt[AuParentChild];
17381+ aufs_bindex_t bstart;
17382+ } sd[AuSrcDst];
1facf9fc 17383+
4a4d8108
AM
17384+#define src_dentry sd[AuSRC].dentry
17385+#define src_dir sd[AuSRC].dir
17386+#define src_inode sd[AuSRC].inode
17387+#define src_h_dentry sd[AuSRC].h_dentry
17388+#define src_parent sd[AuSRC].parent
17389+#define src_h_parent sd[AuSRC].h_parent
17390+#define src_wh_dentry sd[AuSRC].wh_dentry
17391+#define src_hdir sd[AuSRC].hdir
17392+#define src_h_dir sd[AuSRC].hdir->hi_inode
17393+#define src_dt sd[AuSRC].dt
17394+#define src_bstart sd[AuSRC].bstart
1facf9fc 17395+
4a4d8108
AM
17396+#define dst_dentry sd[AuDST].dentry
17397+#define dst_dir sd[AuDST].dir
17398+#define dst_inode sd[AuDST].inode
17399+#define dst_h_dentry sd[AuDST].h_dentry
17400+#define dst_parent sd[AuDST].parent
17401+#define dst_h_parent sd[AuDST].h_parent
17402+#define dst_wh_dentry sd[AuDST].wh_dentry
17403+#define dst_hdir sd[AuDST].hdir
17404+#define dst_h_dir sd[AuDST].hdir->hi_inode
17405+#define dst_dt sd[AuDST].dt
17406+#define dst_bstart sd[AuDST].bstart
17407+
17408+ struct dentry *h_trap;
17409+ struct au_branch *br;
17410+ struct au_hinode *src_hinode;
17411+ struct path h_path;
17412+ struct au_nhash whlist;
027c5e7a 17413+ aufs_bindex_t btgt, src_bwh, src_bdiropq;
1facf9fc 17414+
1308ab2a 17415+ unsigned int flags;
1facf9fc 17416+
4a4d8108
AM
17417+ struct au_whtmp_rmdir *thargs;
17418+ struct dentry *h_dst;
17419+};
1308ab2a 17420+
4a4d8108 17421+/* ---------------------------------------------------------------------- */
1308ab2a 17422+
4a4d8108
AM
17423+/*
17424+ * functions for reverting.
17425+ * when an error happened in a single rename systemcall, we should revert
17426+ * everything as if nothing happend.
17427+ * we don't need to revert the copied-up/down the parent dir since they are
17428+ * harmless.
17429+ */
1facf9fc 17430+
4a4d8108
AM
17431+#define RevertFailure(fmt, ...) do { \
17432+ AuIOErr("revert failure: " fmt " (%d, %d)\n", \
17433+ ##__VA_ARGS__, err, rerr); \
17434+ err = -EIO; \
17435+} while (0)
1facf9fc 17436+
4a4d8108 17437+static void au_ren_rev_diropq(int err, struct au_ren_args *a)
1facf9fc 17438+{
4a4d8108 17439+ int rerr;
1facf9fc 17440+
4a4d8108
AM
17441+ au_hn_imtx_lock_nested(a->src_hinode, AuLsc_I_CHILD);
17442+ rerr = au_diropq_remove(a->src_dentry, a->btgt);
17443+ au_hn_imtx_unlock(a->src_hinode);
027c5e7a 17444+ au_set_dbdiropq(a->src_dentry, a->src_bdiropq);
4a4d8108
AM
17445+ if (rerr)
17446+ RevertFailure("remove diropq %.*s", AuDLNPair(a->src_dentry));
17447+}
1facf9fc 17448+
4a4d8108
AM
17449+static void au_ren_rev_rename(int err, struct au_ren_args *a)
17450+{
17451+ int rerr;
1facf9fc 17452+
b4510431
AM
17453+ a->h_path.dentry = vfsub_lkup_one(&a->src_dentry->d_name,
17454+ a->src_h_parent);
4a4d8108
AM
17455+ rerr = PTR_ERR(a->h_path.dentry);
17456+ if (IS_ERR(a->h_path.dentry)) {
b4510431 17457+ RevertFailure("lkup one %.*s", AuDLNPair(a->src_dentry));
4a4d8108 17458+ return;
1facf9fc 17459+ }
17460+
4a4d8108
AM
17461+ rerr = vfsub_rename(a->dst_h_dir,
17462+ au_h_dptr(a->src_dentry, a->btgt),
17463+ a->src_h_dir, &a->h_path);
17464+ d_drop(a->h_path.dentry);
17465+ dput(a->h_path.dentry);
17466+ /* au_set_h_dptr(a->src_dentry, a->btgt, NULL); */
17467+ if (rerr)
17468+ RevertFailure("rename %.*s", AuDLNPair(a->src_dentry));
1facf9fc 17469+}
17470+
4a4d8108 17471+static void au_ren_rev_cpup(int err, struct au_ren_args *a)
1facf9fc 17472+{
4a4d8108 17473+ int rerr;
1facf9fc 17474+
4a4d8108
AM
17475+ a->h_path.dentry = a->dst_h_dentry;
17476+ rerr = vfsub_unlink(a->dst_h_dir, &a->h_path, /*force*/0);
17477+ au_set_h_dptr(a->src_dentry, a->btgt, NULL);
17478+ au_set_dbstart(a->src_dentry, a->src_bstart);
17479+ if (rerr)
17480+ RevertFailure("unlink %.*s", AuDLNPair(a->dst_h_dentry));
1facf9fc 17481+}
17482+
4a4d8108 17483+static void au_ren_rev_whtmp(int err, struct au_ren_args *a)
1facf9fc 17484+{
4a4d8108 17485+ int rerr;
dece6358 17486+
b4510431
AM
17487+ a->h_path.dentry = vfsub_lkup_one(&a->dst_dentry->d_name,
17488+ a->dst_h_parent);
4a4d8108
AM
17489+ rerr = PTR_ERR(a->h_path.dentry);
17490+ if (IS_ERR(a->h_path.dentry)) {
b4510431 17491+ RevertFailure("lkup one %.*s", AuDLNPair(a->dst_dentry));
4a4d8108
AM
17492+ return;
17493+ }
17494+ if (a->h_path.dentry->d_inode) {
17495+ d_drop(a->h_path.dentry);
17496+ dput(a->h_path.dentry);
17497+ return;
dece6358
AM
17498+ }
17499+
4a4d8108
AM
17500+ rerr = vfsub_rename(a->dst_h_dir, a->h_dst, a->dst_h_dir, &a->h_path);
17501+ d_drop(a->h_path.dentry);
17502+ dput(a->h_path.dentry);
17503+ if (!rerr)
17504+ au_set_h_dptr(a->dst_dentry, a->btgt, dget(a->h_dst));
17505+ else
17506+ RevertFailure("rename %.*s", AuDLNPair(a->h_dst));
17507+}
1308ab2a 17508+
4a4d8108
AM
17509+static void au_ren_rev_whsrc(int err, struct au_ren_args *a)
17510+{
17511+ int rerr;
1308ab2a 17512+
4a4d8108
AM
17513+ a->h_path.dentry = a->src_wh_dentry;
17514+ rerr = au_wh_unlink_dentry(a->src_h_dir, &a->h_path, a->src_dentry);
027c5e7a 17515+ au_set_dbwh(a->src_dentry, a->src_bwh);
4a4d8108
AM
17516+ if (rerr)
17517+ RevertFailure("unlink %.*s", AuDLNPair(a->src_wh_dentry));
17518+}
4a4d8108 17519+#undef RevertFailure
1facf9fc 17520+
1308ab2a 17521+/* ---------------------------------------------------------------------- */
17522+
4a4d8108
AM
17523+/*
17524+ * when we have to copyup the renaming entry, do it with the rename-target name
17525+ * in order to minimize the cost (the later actual rename is unnecessary).
17526+ * otherwise rename it on the target branch.
17527+ */
17528+static int au_ren_or_cpup(struct au_ren_args *a)
1facf9fc 17529+{
dece6358 17530+ int err;
4a4d8108 17531+ struct dentry *d;
1facf9fc 17532+
4a4d8108
AM
17533+ d = a->src_dentry;
17534+ if (au_dbstart(d) == a->btgt) {
17535+ a->h_path.dentry = a->dst_h_dentry;
17536+ if (au_ftest_ren(a->flags, DIROPQ)
17537+ && au_dbdiropq(d) == a->btgt)
17538+ au_fclr_ren(a->flags, DIROPQ);
17539+ AuDebugOn(au_dbstart(d) != a->btgt);
17540+ err = vfsub_rename(a->src_h_dir, au_h_dptr(d, a->btgt),
17541+ a->dst_h_dir, &a->h_path);
17542+ } else {
17543+ struct mutex *h_mtx = &a->src_h_dentry->d_inode->i_mutex;
17544+ struct file *h_file;
1308ab2a 17545+
4a4d8108
AM
17546+ au_fset_ren(a->flags, CPUP);
17547+ mutex_lock_nested(h_mtx, AuLsc_I_CHILD);
17548+ au_set_dbstart(d, a->btgt);
17549+ au_set_h_dptr(d, a->btgt, dget(a->dst_h_dentry));
17550+ h_file = au_h_open_pre(d, a->src_bstart);
17551+ if (IS_ERR(h_file)) {
17552+ err = PTR_ERR(h_file);
17553+ h_file = NULL;
17554+ } else
17555+ err = au_sio_cpup_single(d, a->btgt, a->src_bstart, -1,
17556+ !AuCpup_DTIME, a->dst_parent);
17557+ mutex_unlock(h_mtx);
17558+ au_h_open_post(d, a->src_bstart, h_file);
17559+ if (!err) {
17560+ d = a->dst_dentry;
17561+ au_set_h_dptr(d, a->btgt, NULL);
17562+ au_update_dbstart(d);
17563+ } else {
17564+ au_set_h_dptr(d, a->btgt, NULL);
17565+ au_set_dbstart(d, a->src_bstart);
17566+ }
1308ab2a 17567+ }
027c5e7a
AM
17568+ if (!err && a->h_dst)
17569+ /* it will be set to dinfo later */
17570+ dget(a->h_dst);
1facf9fc 17571+
dece6358
AM
17572+ return err;
17573+}
1facf9fc 17574+
4a4d8108
AM
17575+/* cf. aufs_rmdir() */
17576+static int au_ren_del_whtmp(struct au_ren_args *a)
dece6358 17577+{
4a4d8108
AM
17578+ int err;
17579+ struct inode *dir;
1facf9fc 17580+
4a4d8108
AM
17581+ dir = a->dst_dir;
17582+ SiMustAnyLock(dir->i_sb);
17583+ if (!au_nhash_test_longer_wh(&a->whlist, a->btgt,
17584+ au_sbi(dir->i_sb)->si_dirwh)
17585+ || au_test_fs_remote(a->h_dst->d_sb)) {
17586+ err = au_whtmp_rmdir(dir, a->btgt, a->h_dst, &a->whlist);
17587+ if (unlikely(err))
0c3ec466
AM
17588+ pr_warn("failed removing whtmp dir %.*s (%d), "
17589+ "ignored.\n", AuDLNPair(a->h_dst), err);
4a4d8108
AM
17590+ } else {
17591+ au_nhash_wh_free(&a->thargs->whlist);
17592+ a->thargs->whlist = a->whlist;
17593+ a->whlist.nh_num = 0;
17594+ au_whtmp_kick_rmdir(dir, a->btgt, a->h_dst, a->thargs);
17595+ dput(a->h_dst);
17596+ a->thargs = NULL;
17597+ }
17598+
17599+ return 0;
1308ab2a 17600+}
1facf9fc 17601+
4a4d8108
AM
17602+/* make it 'opaque' dir. */
17603+static int au_ren_diropq(struct au_ren_args *a)
17604+{
17605+ int err;
17606+ struct dentry *diropq;
1facf9fc 17607+
4a4d8108 17608+ err = 0;
027c5e7a 17609+ a->src_bdiropq = au_dbdiropq(a->src_dentry);
4a4d8108
AM
17610+ a->src_hinode = au_hi(a->src_inode, a->btgt);
17611+ au_hn_imtx_lock_nested(a->src_hinode, AuLsc_I_CHILD);
17612+ diropq = au_diropq_create(a->src_dentry, a->btgt);
17613+ au_hn_imtx_unlock(a->src_hinode);
17614+ if (IS_ERR(diropq))
17615+ err = PTR_ERR(diropq);
17616+ dput(diropq);
1facf9fc 17617+
4a4d8108
AM
17618+ return err;
17619+}
1facf9fc 17620+
4a4d8108
AM
17621+static int do_rename(struct au_ren_args *a)
17622+{
17623+ int err;
17624+ struct dentry *d, *h_d;
1facf9fc 17625+
4a4d8108
AM
17626+ /* prepare workqueue args for asynchronous rmdir */
17627+ h_d = a->dst_h_dentry;
17628+ if (au_ftest_ren(a->flags, ISDIR) && h_d->d_inode) {
17629+ err = -ENOMEM;
17630+ a->thargs = au_whtmp_rmdir_alloc(a->src_dentry->d_sb, GFP_NOFS);
17631+ if (unlikely(!a->thargs))
17632+ goto out;
17633+ a->h_dst = dget(h_d);
17634+ }
1facf9fc 17635+
4a4d8108
AM
17636+ /* create whiteout for src_dentry */
17637+ if (au_ftest_ren(a->flags, WHSRC)) {
027c5e7a
AM
17638+ a->src_bwh = au_dbwh(a->src_dentry);
17639+ AuDebugOn(a->src_bwh >= 0);
4a4d8108
AM
17640+ a->src_wh_dentry
17641+ = au_wh_create(a->src_dentry, a->btgt, a->src_h_parent);
17642+ err = PTR_ERR(a->src_wh_dentry);
17643+ if (IS_ERR(a->src_wh_dentry))
17644+ goto out_thargs;
17645+ }
1facf9fc 17646+
4a4d8108
AM
17647+ /* lookup whiteout for dentry */
17648+ if (au_ftest_ren(a->flags, WHDST)) {
17649+ h_d = au_wh_lkup(a->dst_h_parent, &a->dst_dentry->d_name,
17650+ a->br);
17651+ err = PTR_ERR(h_d);
17652+ if (IS_ERR(h_d))
17653+ goto out_whsrc;
17654+ if (!h_d->d_inode)
17655+ dput(h_d);
17656+ else
17657+ a->dst_wh_dentry = h_d;
17658+ }
1facf9fc 17659+
4a4d8108
AM
17660+ /* rename dentry to tmpwh */
17661+ if (a->thargs) {
17662+ err = au_whtmp_ren(a->dst_h_dentry, a->br);
17663+ if (unlikely(err))
17664+ goto out_whdst;
dece6358 17665+
4a4d8108
AM
17666+ d = a->dst_dentry;
17667+ au_set_h_dptr(d, a->btgt, NULL);
17668+ err = au_lkup_neg(d, a->btgt);
17669+ if (unlikely(err))
17670+ goto out_whtmp;
17671+ a->dst_h_dentry = au_h_dptr(d, a->btgt);
17672+ }
1facf9fc 17673+
4a4d8108
AM
17674+ /* cpup src */
17675+ if (a->dst_h_dentry->d_inode && a->src_bstart != a->btgt) {
17676+ struct mutex *h_mtx = &a->src_h_dentry->d_inode->i_mutex;
17677+ struct file *h_file;
1facf9fc 17678+
4a4d8108
AM
17679+ mutex_lock_nested(h_mtx, AuLsc_I_CHILD);
17680+ AuDebugOn(au_dbstart(a->src_dentry) != a->src_bstart);
17681+ h_file = au_h_open_pre(a->src_dentry, a->src_bstart);
17682+ if (IS_ERR(h_file)) {
17683+ err = PTR_ERR(h_file);
17684+ h_file = NULL;
17685+ } else
17686+ err = au_sio_cpup_simple(a->src_dentry, a->btgt, -1,
17687+ !AuCpup_DTIME);
17688+ mutex_unlock(h_mtx);
17689+ au_h_open_post(a->src_dentry, a->src_bstart, h_file);
17690+ if (unlikely(err))
17691+ goto out_whtmp;
17692+ }
1facf9fc 17693+
4a4d8108
AM
17694+ /* rename by vfs_rename or cpup */
17695+ d = a->dst_dentry;
17696+ if (au_ftest_ren(a->flags, ISDIR)
17697+ && (a->dst_wh_dentry
17698+ || au_dbdiropq(d) == a->btgt
17699+ /* hide the lower to keep xino */
17700+ || a->btgt < au_dbend(d)
17701+ || au_opt_test(au_mntflags(d->d_sb), ALWAYS_DIROPQ)))
17702+ au_fset_ren(a->flags, DIROPQ);
17703+ err = au_ren_or_cpup(a);
17704+ if (unlikely(err))
17705+ /* leave the copied-up one */
17706+ goto out_whtmp;
1308ab2a 17707+
4a4d8108
AM
17708+ /* make dir opaque */
17709+ if (au_ftest_ren(a->flags, DIROPQ)) {
17710+ err = au_ren_diropq(a);
17711+ if (unlikely(err))
17712+ goto out_rename;
17713+ }
1308ab2a 17714+
4a4d8108
AM
17715+ /* update target timestamps */
17716+ AuDebugOn(au_dbstart(a->src_dentry) != a->btgt);
17717+ a->h_path.dentry = au_h_dptr(a->src_dentry, a->btgt);
17718+ vfsub_update_h_iattr(&a->h_path, /*did*/NULL); /*ignore*/
17719+ a->src_inode->i_ctime = a->h_path.dentry->d_inode->i_ctime;
1facf9fc 17720+
4a4d8108
AM
17721+ /* remove whiteout for dentry */
17722+ if (a->dst_wh_dentry) {
17723+ a->h_path.dentry = a->dst_wh_dentry;
17724+ err = au_wh_unlink_dentry(a->dst_h_dir, &a->h_path,
17725+ a->dst_dentry);
17726+ if (unlikely(err))
17727+ goto out_diropq;
17728+ }
1facf9fc 17729+
4a4d8108
AM
17730+ /* remove whtmp */
17731+ if (a->thargs)
17732+ au_ren_del_whtmp(a); /* ignore this error */
1308ab2a 17733+
4a4d8108
AM
17734+ err = 0;
17735+ goto out_success;
17736+
4f0767ce 17737+out_diropq:
4a4d8108
AM
17738+ if (au_ftest_ren(a->flags, DIROPQ))
17739+ au_ren_rev_diropq(err, a);
4f0767ce 17740+out_rename:
4a4d8108
AM
17741+ if (!au_ftest_ren(a->flags, CPUP))
17742+ au_ren_rev_rename(err, a);
17743+ else
17744+ au_ren_rev_cpup(err, a);
027c5e7a 17745+ dput(a->h_dst);
4f0767ce 17746+out_whtmp:
4a4d8108
AM
17747+ if (a->thargs)
17748+ au_ren_rev_whtmp(err, a);
4f0767ce 17749+out_whdst:
4a4d8108
AM
17750+ dput(a->dst_wh_dentry);
17751+ a->dst_wh_dentry = NULL;
4f0767ce 17752+out_whsrc:
4a4d8108
AM
17753+ if (a->src_wh_dentry)
17754+ au_ren_rev_whsrc(err, a);
4f0767ce 17755+out_success:
4a4d8108
AM
17756+ dput(a->src_wh_dentry);
17757+ dput(a->dst_wh_dentry);
4f0767ce 17758+out_thargs:
4a4d8108
AM
17759+ if (a->thargs) {
17760+ dput(a->h_dst);
17761+ au_whtmp_rmdir_free(a->thargs);
17762+ a->thargs = NULL;
17763+ }
4f0767ce 17764+out:
4a4d8108 17765+ return err;
dece6358 17766+}
1facf9fc 17767+
1308ab2a 17768+/* ---------------------------------------------------------------------- */
1facf9fc 17769+
4a4d8108
AM
17770+/*
17771+ * test if @dentry dir can be rename destination or not.
17772+ * success means, it is a logically empty dir.
17773+ */
17774+static int may_rename_dstdir(struct dentry *dentry, struct au_nhash *whlist)
1308ab2a 17775+{
4a4d8108 17776+ return au_test_empty(dentry, whlist);
1308ab2a 17777+}
1facf9fc 17778+
4a4d8108
AM
17779+/*
17780+ * test if @dentry dir can be rename source or not.
17781+ * if it can, return 0 and @children is filled.
17782+ * success means,
17783+ * - it is a logically empty dir.
17784+ * - or, it exists on writable branch and has no children including whiteouts
17785+ * on the lower branch.
17786+ */
17787+static int may_rename_srcdir(struct dentry *dentry, aufs_bindex_t btgt)
17788+{
17789+ int err;
17790+ unsigned int rdhash;
17791+ aufs_bindex_t bstart;
1facf9fc 17792+
4a4d8108
AM
17793+ bstart = au_dbstart(dentry);
17794+ if (bstart != btgt) {
17795+ struct au_nhash whlist;
dece6358 17796+
4a4d8108
AM
17797+ SiMustAnyLock(dentry->d_sb);
17798+ rdhash = au_sbi(dentry->d_sb)->si_rdhash;
17799+ if (!rdhash)
17800+ rdhash = au_rdhash_est(au_dir_size(/*file*/NULL,
17801+ dentry));
17802+ err = au_nhash_alloc(&whlist, rdhash, GFP_NOFS);
17803+ if (unlikely(err))
17804+ goto out;
17805+ err = au_test_empty(dentry, &whlist);
17806+ au_nhash_wh_free(&whlist);
17807+ goto out;
17808+ }
dece6358 17809+
4a4d8108
AM
17810+ if (bstart == au_dbtaildir(dentry))
17811+ return 0; /* success */
dece6358 17812+
4a4d8108 17813+ err = au_test_empty_lower(dentry);
1facf9fc 17814+
4f0767ce 17815+out:
4a4d8108
AM
17816+ if (err == -ENOTEMPTY) {
17817+ AuWarn1("renaming dir who has child(ren) on multiple branches,"
17818+ " is not supported\n");
17819+ err = -EXDEV;
17820+ }
17821+ return err;
17822+}
1308ab2a 17823+
4a4d8108
AM
17824+/* side effect: sets whlist and h_dentry */
17825+static int au_ren_may_dir(struct au_ren_args *a)
1308ab2a 17826+{
4a4d8108
AM
17827+ int err;
17828+ unsigned int rdhash;
17829+ struct dentry *d;
1facf9fc 17830+
4a4d8108
AM
17831+ d = a->dst_dentry;
17832+ SiMustAnyLock(d->d_sb);
1facf9fc 17833+
4a4d8108
AM
17834+ err = 0;
17835+ if (au_ftest_ren(a->flags, ISDIR) && a->dst_inode) {
17836+ rdhash = au_sbi(d->d_sb)->si_rdhash;
17837+ if (!rdhash)
17838+ rdhash = au_rdhash_est(au_dir_size(/*file*/NULL, d));
17839+ err = au_nhash_alloc(&a->whlist, rdhash, GFP_NOFS);
17840+ if (unlikely(err))
17841+ goto out;
1308ab2a 17842+
4a4d8108
AM
17843+ au_set_dbstart(d, a->dst_bstart);
17844+ err = may_rename_dstdir(d, &a->whlist);
17845+ au_set_dbstart(d, a->btgt);
17846+ }
17847+ a->dst_h_dentry = au_h_dptr(d, au_dbstart(d));
17848+ if (unlikely(err))
17849+ goto out;
17850+
17851+ d = a->src_dentry;
17852+ a->src_h_dentry = au_h_dptr(d, au_dbstart(d));
17853+ if (au_ftest_ren(a->flags, ISDIR)) {
17854+ err = may_rename_srcdir(d, a->btgt);
17855+ if (unlikely(err)) {
17856+ au_nhash_wh_free(&a->whlist);
17857+ a->whlist.nh_num = 0;
17858+ }
17859+ }
4f0767ce 17860+out:
4a4d8108 17861+ return err;
1facf9fc 17862+}
17863+
4a4d8108 17864+/* ---------------------------------------------------------------------- */
1facf9fc 17865+
4a4d8108
AM
17866+/*
17867+ * simple tests for rename.
17868+ * following the checks in vfs, plus the parent-child relationship.
17869+ */
17870+static int au_may_ren(struct au_ren_args *a)
17871+{
17872+ int err, isdir;
17873+ struct inode *h_inode;
1facf9fc 17874+
4a4d8108
AM
17875+ if (a->src_bstart == a->btgt) {
17876+ err = au_may_del(a->src_dentry, a->btgt, a->src_h_parent,
17877+ au_ftest_ren(a->flags, ISDIR));
17878+ if (unlikely(err))
17879+ goto out;
17880+ err = -EINVAL;
17881+ if (unlikely(a->src_h_dentry == a->h_trap))
17882+ goto out;
17883+ }
1facf9fc 17884+
4a4d8108
AM
17885+ err = 0;
17886+ if (a->dst_bstart != a->btgt)
17887+ goto out;
1facf9fc 17888+
027c5e7a
AM
17889+ err = -ENOTEMPTY;
17890+ if (unlikely(a->dst_h_dentry == a->h_trap))
17891+ goto out;
17892+
4a4d8108
AM
17893+ err = -EIO;
17894+ h_inode = a->dst_h_dentry->d_inode;
17895+ isdir = !!au_ftest_ren(a->flags, ISDIR);
17896+ if (!a->dst_dentry->d_inode) {
17897+ if (unlikely(h_inode))
17898+ goto out;
17899+ err = au_may_add(a->dst_dentry, a->btgt, a->dst_h_parent,
17900+ isdir);
17901+ } else {
17902+ if (unlikely(!h_inode || !h_inode->i_nlink))
17903+ goto out;
17904+ err = au_may_del(a->dst_dentry, a->btgt, a->dst_h_parent,
17905+ isdir);
17906+ if (unlikely(err))
17907+ goto out;
4a4d8108 17908+ }
1facf9fc 17909+
4f0767ce 17910+out:
4a4d8108
AM
17911+ if (unlikely(err == -ENOENT || err == -EEXIST))
17912+ err = -EIO;
17913+ AuTraceErr(err);
17914+ return err;
17915+}
1facf9fc 17916+
1308ab2a 17917+/* ---------------------------------------------------------------------- */
1facf9fc 17918+
4a4d8108
AM
17919+/*
17920+ * locking order
17921+ * (VFS)
17922+ * - src_dir and dir by lock_rename()
17923+ * - inode if exitsts
17924+ * (aufs)
17925+ * - lock all
17926+ * + src_dentry and dentry by aufs_read_and_write_lock2() which calls,
17927+ * + si_read_lock
17928+ * + di_write_lock2_child()
17929+ * + di_write_lock_child()
17930+ * + ii_write_lock_child()
17931+ * + di_write_lock_child2()
17932+ * + ii_write_lock_child2()
17933+ * + src_parent and parent
17934+ * + di_write_lock_parent()
17935+ * + ii_write_lock_parent()
17936+ * + di_write_lock_parent2()
17937+ * + ii_write_lock_parent2()
17938+ * + lower src_dir and dir by vfsub_lock_rename()
17939+ * + verify the every relationships between child and parent. if any
17940+ * of them failed, unlock all and return -EBUSY.
17941+ */
17942+static void au_ren_unlock(struct au_ren_args *a)
1308ab2a 17943+{
4a4d8108
AM
17944+ struct super_block *sb;
17945+
17946+ sb = a->dst_dentry->d_sb;
17947+ if (au_ftest_ren(a->flags, MNT_WRITE))
b4510431 17948+ vfsub_mnt_drop_write(a->br->br_mnt);
4a4d8108
AM
17949+ vfsub_unlock_rename(a->src_h_parent, a->src_hdir,
17950+ a->dst_h_parent, a->dst_hdir);
1308ab2a 17951+}
17952+
4a4d8108 17953+static int au_ren_lock(struct au_ren_args *a)
1308ab2a 17954+{
4a4d8108
AM
17955+ int err;
17956+ unsigned int udba;
1308ab2a 17957+
4a4d8108
AM
17958+ err = 0;
17959+ a->src_h_parent = au_h_dptr(a->src_parent, a->btgt);
17960+ a->src_hdir = au_hi(a->src_dir, a->btgt);
17961+ a->dst_h_parent = au_h_dptr(a->dst_parent, a->btgt);
17962+ a->dst_hdir = au_hi(a->dst_dir, a->btgt);
17963+ a->h_trap = vfsub_lock_rename(a->src_h_parent, a->src_hdir,
17964+ a->dst_h_parent, a->dst_hdir);
17965+ udba = au_opt_udba(a->src_dentry->d_sb);
17966+ if (unlikely(a->src_hdir->hi_inode != a->src_h_parent->d_inode
17967+ || a->dst_hdir->hi_inode != a->dst_h_parent->d_inode))
17968+ err = au_busy_or_stale();
17969+ if (!err && au_dbstart(a->src_dentry) == a->btgt)
17970+ err = au_h_verify(a->src_h_dentry, udba,
17971+ a->src_h_parent->d_inode, a->src_h_parent,
17972+ a->br);
17973+ if (!err && au_dbstart(a->dst_dentry) == a->btgt)
17974+ err = au_h_verify(a->dst_h_dentry, udba,
17975+ a->dst_h_parent->d_inode, a->dst_h_parent,
17976+ a->br);
17977+ if (!err) {
b4510431 17978+ err = vfsub_mnt_want_write(a->br->br_mnt);
4a4d8108
AM
17979+ if (unlikely(err))
17980+ goto out_unlock;
17981+ au_fset_ren(a->flags, MNT_WRITE);
17982+ goto out; /* success */
17983+ }
17984+
17985+ err = au_busy_or_stale();
17986+
4f0767ce 17987+out_unlock:
4a4d8108 17988+ au_ren_unlock(a);
4f0767ce 17989+out:
4a4d8108 17990+ return err;
1facf9fc 17991+}
17992+
17993+/* ---------------------------------------------------------------------- */
17994+
4a4d8108 17995+static void au_ren_refresh_dir(struct au_ren_args *a)
1facf9fc 17996+{
4a4d8108 17997+ struct inode *dir;
dece6358 17998+
4a4d8108
AM
17999+ dir = a->dst_dir;
18000+ dir->i_version++;
18001+ if (au_ftest_ren(a->flags, ISDIR)) {
18002+ /* is this updating defined in POSIX? */
18003+ au_cpup_attr_timesizes(a->src_inode);
18004+ au_cpup_attr_nlink(dir, /*force*/1);
4a4d8108 18005+ }
027c5e7a 18006+
4a4d8108
AM
18007+ if (au_ibstart(dir) == a->btgt)
18008+ au_cpup_attr_timesizes(dir);
dece6358 18009+
4a4d8108
AM
18010+ if (au_ftest_ren(a->flags, ISSAMEDIR))
18011+ return;
dece6358 18012+
4a4d8108
AM
18013+ dir = a->src_dir;
18014+ dir->i_version++;
18015+ if (au_ftest_ren(a->flags, ISDIR))
18016+ au_cpup_attr_nlink(dir, /*force*/1);
18017+ if (au_ibstart(dir) == a->btgt)
18018+ au_cpup_attr_timesizes(dir);
1facf9fc 18019+}
18020+
4a4d8108 18021+static void au_ren_refresh(struct au_ren_args *a)
1facf9fc 18022+{
4a4d8108
AM
18023+ aufs_bindex_t bend, bindex;
18024+ struct dentry *d, *h_d;
18025+ struct inode *i, *h_i;
18026+ struct super_block *sb;
dece6358 18027+
027c5e7a
AM
18028+ d = a->dst_dentry;
18029+ d_drop(d);
18030+ if (a->h_dst)
18031+ /* already dget-ed by au_ren_or_cpup() */
18032+ au_set_h_dptr(d, a->btgt, a->h_dst);
18033+
18034+ i = a->dst_inode;
18035+ if (i) {
18036+ if (!au_ftest_ren(a->flags, ISDIR))
18037+ vfsub_drop_nlink(i);
18038+ else {
18039+ vfsub_dead_dir(i);
18040+ au_cpup_attr_timesizes(i);
18041+ }
18042+ au_update_dbrange(d, /*do_put_zero*/1);
18043+ } else {
18044+ bend = a->btgt;
18045+ for (bindex = au_dbstart(d); bindex < bend; bindex++)
18046+ au_set_h_dptr(d, bindex, NULL);
18047+ bend = au_dbend(d);
18048+ for (bindex = a->btgt + 1; bindex <= bend; bindex++)
18049+ au_set_h_dptr(d, bindex, NULL);
18050+ au_update_dbrange(d, /*do_put_zero*/0);
18051+ }
18052+
4a4d8108
AM
18053+ d = a->src_dentry;
18054+ au_set_dbwh(d, -1);
18055+ bend = au_dbend(d);
18056+ for (bindex = a->btgt + 1; bindex <= bend; bindex++) {
18057+ h_d = au_h_dptr(d, bindex);
18058+ if (h_d)
18059+ au_set_h_dptr(d, bindex, NULL);
18060+ }
18061+ au_set_dbend(d, a->btgt);
18062+
18063+ sb = d->d_sb;
18064+ i = a->src_inode;
18065+ if (au_opt_test(au_mntflags(sb), PLINK) && au_plink_test(i))
18066+ return; /* success */
18067+
18068+ bend = au_ibend(i);
18069+ for (bindex = a->btgt + 1; bindex <= bend; bindex++) {
18070+ h_i = au_h_iptr(i, bindex);
18071+ if (h_i) {
18072+ au_xino_write(sb, bindex, h_i->i_ino, /*ino*/0);
18073+ /* ignore this error */
18074+ au_set_h_iptr(i, bindex, NULL, 0);
18075+ }
18076+ }
18077+ au_set_ibend(i, a->btgt);
1308ab2a 18078+}
dece6358 18079+
4a4d8108
AM
18080+/* ---------------------------------------------------------------------- */
18081+
18082+/* mainly for link(2) and rename(2) */
18083+int au_wbr(struct dentry *dentry, aufs_bindex_t btgt)
1308ab2a 18084+{
4a4d8108
AM
18085+ aufs_bindex_t bdiropq, bwh;
18086+ struct dentry *parent;
18087+ struct au_branch *br;
18088+
18089+ parent = dentry->d_parent;
18090+ IMustLock(parent->d_inode); /* dir is locked */
18091+
18092+ bdiropq = au_dbdiropq(parent);
18093+ bwh = au_dbwh(dentry);
18094+ br = au_sbr(dentry->d_sb, btgt);
18095+ if (au_br_rdonly(br)
18096+ || (0 <= bdiropq && bdiropq < btgt)
18097+ || (0 <= bwh && bwh < btgt))
18098+ btgt = -1;
18099+
18100+ AuDbg("btgt %d\n", btgt);
18101+ return btgt;
1facf9fc 18102+}
18103+
4a4d8108
AM
18104+/* sets src_bstart, dst_bstart and btgt */
18105+static int au_ren_wbr(struct au_ren_args *a)
1facf9fc 18106+{
4a4d8108
AM
18107+ int err;
18108+ struct au_wr_dir_args wr_dir_args = {
18109+ /* .force_btgt = -1, */
18110+ .flags = AuWrDir_ADD_ENTRY
18111+ };
dece6358 18112+
4a4d8108
AM
18113+ a->src_bstart = au_dbstart(a->src_dentry);
18114+ a->dst_bstart = au_dbstart(a->dst_dentry);
18115+ if (au_ftest_ren(a->flags, ISDIR))
18116+ au_fset_wrdir(wr_dir_args.flags, ISDIR);
18117+ wr_dir_args.force_btgt = a->src_bstart;
18118+ if (a->dst_inode && a->dst_bstart < a->src_bstart)
18119+ wr_dir_args.force_btgt = a->dst_bstart;
18120+ wr_dir_args.force_btgt = au_wbr(a->dst_dentry, wr_dir_args.force_btgt);
18121+ err = au_wr_dir(a->dst_dentry, a->src_dentry, &wr_dir_args);
18122+ a->btgt = err;
dece6358 18123+
4a4d8108 18124+ return err;
1facf9fc 18125+}
18126+
4a4d8108 18127+static void au_ren_dt(struct au_ren_args *a)
1facf9fc 18128+{
4a4d8108
AM
18129+ a->h_path.dentry = a->src_h_parent;
18130+ au_dtime_store(a->src_dt + AuPARENT, a->src_parent, &a->h_path);
18131+ if (!au_ftest_ren(a->flags, ISSAMEDIR)) {
18132+ a->h_path.dentry = a->dst_h_parent;
18133+ au_dtime_store(a->dst_dt + AuPARENT, a->dst_parent, &a->h_path);
18134+ }
1facf9fc 18135+
4a4d8108
AM
18136+ au_fclr_ren(a->flags, DT_DSTDIR);
18137+ if (!au_ftest_ren(a->flags, ISDIR))
18138+ return;
dece6358 18139+
4a4d8108
AM
18140+ a->h_path.dentry = a->src_h_dentry;
18141+ au_dtime_store(a->src_dt + AuCHILD, a->src_dentry, &a->h_path);
18142+ if (a->dst_h_dentry->d_inode) {
18143+ au_fset_ren(a->flags, DT_DSTDIR);
18144+ a->h_path.dentry = a->dst_h_dentry;
18145+ au_dtime_store(a->dst_dt + AuCHILD, a->dst_dentry, &a->h_path);
18146+ }
1308ab2a 18147+}
dece6358 18148+
4a4d8108 18149+static void au_ren_rev_dt(int err, struct au_ren_args *a)
1308ab2a 18150+{
4a4d8108
AM
18151+ struct dentry *h_d;
18152+ struct mutex *h_mtx;
18153+
18154+ au_dtime_revert(a->src_dt + AuPARENT);
18155+ if (!au_ftest_ren(a->flags, ISSAMEDIR))
18156+ au_dtime_revert(a->dst_dt + AuPARENT);
18157+
18158+ if (au_ftest_ren(a->flags, ISDIR) && err != -EIO) {
18159+ h_d = a->src_dt[AuCHILD].dt_h_path.dentry;
18160+ h_mtx = &h_d->d_inode->i_mutex;
18161+ mutex_lock_nested(h_mtx, AuLsc_I_CHILD);
18162+ au_dtime_revert(a->src_dt + AuCHILD);
18163+ mutex_unlock(h_mtx);
18164+
18165+ if (au_ftest_ren(a->flags, DT_DSTDIR)) {
18166+ h_d = a->dst_dt[AuCHILD].dt_h_path.dentry;
18167+ h_mtx = &h_d->d_inode->i_mutex;
18168+ mutex_lock_nested(h_mtx, AuLsc_I_CHILD);
18169+ au_dtime_revert(a->dst_dt + AuCHILD);
18170+ mutex_unlock(h_mtx);
1facf9fc 18171+ }
18172+ }
18173+}
18174+
4a4d8108
AM
18175+/* ---------------------------------------------------------------------- */
18176+
18177+int aufs_rename(struct inode *_src_dir, struct dentry *_src_dentry,
18178+ struct inode *_dst_dir, struct dentry *_dst_dentry)
1facf9fc 18179+{
e49829fe 18180+ int err, flags;
4a4d8108
AM
18181+ /* reduce stack space */
18182+ struct au_ren_args *a;
18183+
18184+ AuDbg("%.*s, %.*s\n", AuDLNPair(_src_dentry), AuDLNPair(_dst_dentry));
18185+ IMustLock(_src_dir);
18186+ IMustLock(_dst_dir);
18187+
18188+ err = -ENOMEM;
18189+ BUILD_BUG_ON(sizeof(*a) > PAGE_SIZE);
18190+ a = kzalloc(sizeof(*a), GFP_NOFS);
18191+ if (unlikely(!a))
18192+ goto out;
18193+
18194+ a->src_dir = _src_dir;
18195+ a->src_dentry = _src_dentry;
18196+ a->src_inode = a->src_dentry->d_inode;
18197+ a->src_parent = a->src_dentry->d_parent; /* dir inode is locked */
18198+ a->dst_dir = _dst_dir;
18199+ a->dst_dentry = _dst_dentry;
18200+ a->dst_inode = a->dst_dentry->d_inode;
18201+ a->dst_parent = a->dst_dentry->d_parent; /* dir inode is locked */
18202+ if (a->dst_inode) {
18203+ IMustLock(a->dst_inode);
18204+ au_igrab(a->dst_inode);
1facf9fc 18205+ }
1facf9fc 18206+
4a4d8108 18207+ err = -ENOTDIR;
027c5e7a 18208+ flags = AuLock_FLUSH | AuLock_NOPLM | AuLock_GEN;
4a4d8108
AM
18209+ if (S_ISDIR(a->src_inode->i_mode)) {
18210+ au_fset_ren(a->flags, ISDIR);
18211+ if (unlikely(a->dst_inode && !S_ISDIR(a->dst_inode->i_mode)))
18212+ goto out_free;
e49829fe
JR
18213+ err = aufs_read_and_write_lock2(a->dst_dentry, a->src_dentry,
18214+ AuLock_DIR | flags);
4a4d8108 18215+ } else
e49829fe
JR
18216+ err = aufs_read_and_write_lock2(a->dst_dentry, a->src_dentry,
18217+ flags);
18218+ if (unlikely(err))
18219+ goto out_free;
1facf9fc 18220+
027c5e7a
AM
18221+ err = au_d_hashed_positive(a->src_dentry);
18222+ if (unlikely(err))
18223+ goto out_unlock;
18224+ err = -ENOENT;
18225+ if (a->dst_inode) {
18226+ /*
18227+ * If it is a dir, VFS unhash dst_dentry before this
18228+ * function. It means we cannot rely upon d_unhashed().
18229+ */
18230+ if (unlikely(!a->dst_inode->i_nlink))
18231+ goto out_unlock;
18232+ if (!S_ISDIR(a->dst_inode->i_mode)) {
18233+ err = au_d_hashed_positive(a->dst_dentry);
18234+ if (unlikely(err))
18235+ goto out_unlock;
18236+ } else if (unlikely(IS_DEADDIR(a->dst_inode)))
18237+ goto out_unlock;
18238+ } else if (unlikely(d_unhashed(a->dst_dentry)))
18239+ goto out_unlock;
18240+
7eafdf33
AM
18241+ /*
18242+ * is it possible?
18243+ * yes, it happend (in linux-3.3-rcN) but I don't know why.
18244+ * there may exist a problem somewhere else.
18245+ */
18246+ err = -EINVAL;
18247+ if (unlikely(a->dst_parent->d_inode == a->src_dentry->d_inode))
18248+ goto out_unlock;
18249+
4a4d8108
AM
18250+ au_fset_ren(a->flags, ISSAMEDIR); /* temporary */
18251+ di_write_lock_parent(a->dst_parent);
1facf9fc 18252+
4a4d8108
AM
18253+ /* which branch we process */
18254+ err = au_ren_wbr(a);
18255+ if (unlikely(err < 0))
027c5e7a 18256+ goto out_parent;
4a4d8108
AM
18257+ a->br = au_sbr(a->dst_dentry->d_sb, a->btgt);
18258+ a->h_path.mnt = a->br->br_mnt;
1facf9fc 18259+
4a4d8108
AM
18260+ /* are they available to be renamed */
18261+ err = au_ren_may_dir(a);
18262+ if (unlikely(err))
18263+ goto out_children;
1facf9fc 18264+
4a4d8108
AM
18265+ /* prepare the writable parent dir on the same branch */
18266+ if (a->dst_bstart == a->btgt) {
18267+ au_fset_ren(a->flags, WHDST);
18268+ } else {
18269+ err = au_cpup_dirs(a->dst_dentry, a->btgt);
18270+ if (unlikely(err))
18271+ goto out_children;
18272+ }
1facf9fc 18273+
4a4d8108
AM
18274+ if (a->src_dir != a->dst_dir) {
18275+ /*
18276+ * this temporary unlock is safe,
18277+ * because both dir->i_mutex are locked.
18278+ */
18279+ di_write_unlock(a->dst_parent);
18280+ di_write_lock_parent(a->src_parent);
18281+ err = au_wr_dir_need_wh(a->src_dentry,
18282+ au_ftest_ren(a->flags, ISDIR),
18283+ &a->btgt);
18284+ di_write_unlock(a->src_parent);
18285+ di_write_lock2_parent(a->src_parent, a->dst_parent, /*isdir*/1);
18286+ au_fclr_ren(a->flags, ISSAMEDIR);
18287+ } else
18288+ err = au_wr_dir_need_wh(a->src_dentry,
18289+ au_ftest_ren(a->flags, ISDIR),
18290+ &a->btgt);
18291+ if (unlikely(err < 0))
18292+ goto out_children;
18293+ if (err)
18294+ au_fset_ren(a->flags, WHSRC);
1facf9fc 18295+
4a4d8108
AM
18296+ /* lock them all */
18297+ err = au_ren_lock(a);
18298+ if (unlikely(err))
18299+ goto out_children;
1facf9fc 18300+
4a4d8108
AM
18301+ if (!au_opt_test(au_mntflags(a->dst_dir->i_sb), UDBA_NONE))
18302+ err = au_may_ren(a);
18303+ else if (unlikely(a->dst_dentry->d_name.len > AUFS_MAX_NAMELEN))
18304+ err = -ENAMETOOLONG;
18305+ if (unlikely(err))
18306+ goto out_hdir;
1facf9fc 18307+
4a4d8108
AM
18308+ /* store timestamps to be revertible */
18309+ au_ren_dt(a);
1facf9fc 18310+
4a4d8108
AM
18311+ /* here we go */
18312+ err = do_rename(a);
18313+ if (unlikely(err))
18314+ goto out_dt;
18315+
18316+ /* update dir attributes */
18317+ au_ren_refresh_dir(a);
18318+
18319+ /* dput/iput all lower dentries */
18320+ au_ren_refresh(a);
18321+
18322+ goto out_hdir; /* success */
18323+
4f0767ce 18324+out_dt:
4a4d8108 18325+ au_ren_rev_dt(err, a);
4f0767ce 18326+out_hdir:
4a4d8108 18327+ au_ren_unlock(a);
4f0767ce 18328+out_children:
4a4d8108 18329+ au_nhash_wh_free(&a->whlist);
027c5e7a
AM
18330+ if (err && a->dst_inode && a->dst_bstart != a->btgt) {
18331+ AuDbg("bstart %d, btgt %d\n", a->dst_bstart, a->btgt);
18332+ au_set_h_dptr(a->dst_dentry, a->btgt, NULL);
18333+ au_set_dbstart(a->dst_dentry, a->dst_bstart);
4a4d8108 18334+ }
027c5e7a 18335+out_parent:
4a4d8108
AM
18336+ if (!err)
18337+ d_move(a->src_dentry, a->dst_dentry);
027c5e7a
AM
18338+ else {
18339+ au_update_dbstart(a->dst_dentry);
18340+ if (!a->dst_inode)
18341+ d_drop(a->dst_dentry);
18342+ }
4a4d8108
AM
18343+ if (au_ftest_ren(a->flags, ISSAMEDIR))
18344+ di_write_unlock(a->dst_parent);
18345+ else
18346+ di_write_unlock2(a->src_parent, a->dst_parent);
027c5e7a 18347+out_unlock:
4a4d8108 18348+ aufs_read_and_write_unlock2(a->dst_dentry, a->src_dentry);
4f0767ce 18349+out_free:
4a4d8108
AM
18350+ iput(a->dst_inode);
18351+ if (a->thargs)
18352+ au_whtmp_rmdir_free(a->thargs);
18353+ kfree(a);
4f0767ce 18354+out:
4a4d8108
AM
18355+ AuTraceErr(err);
18356+ return err;
1308ab2a 18357+}
7f207e10
AM
18358diff -urN /usr/share/empty/fs/aufs/Kconfig linux/fs/aufs/Kconfig
18359--- /usr/share/empty/fs/aufs/Kconfig 1970-01-01 01:00:00.000000000 +0100
537831f9 18360+++ linux/fs/aufs/Kconfig 2012-12-13 20:41:10.428126759 +0100
2cbb1c4b 18361@@ -0,0 +1,203 @@
4a4d8108
AM
18362+config AUFS_FS
18363+ tristate "Aufs (Advanced multi layered unification filesystem) support"
18364+ depends on EXPERIMENTAL
18365+ help
18366+ Aufs is a stackable unification filesystem such as Unionfs,
18367+ which unifies several directories and provides a merged single
18368+ directory.
18369+ In the early days, aufs was entirely re-designed and
18370+ re-implemented Unionfs Version 1.x series. Introducing many
18371+ original ideas, approaches and improvements, it becomes totally
18372+ different from Unionfs while keeping the basic features.
1facf9fc 18373+
4a4d8108
AM
18374+if AUFS_FS
18375+choice
18376+ prompt "Maximum number of branches"
18377+ default AUFS_BRANCH_MAX_127
18378+ help
18379+ Specifies the maximum number of branches (or member directories)
18380+ in a single aufs. The larger value consumes more system
18381+ resources and has a minor impact to performance.
18382+config AUFS_BRANCH_MAX_127
18383+ bool "127"
18384+ help
18385+ Specifies the maximum number of branches (or member directories)
18386+ in a single aufs. The larger value consumes more system
18387+ resources and has a minor impact to performance.
18388+config AUFS_BRANCH_MAX_511
18389+ bool "511"
18390+ help
18391+ Specifies the maximum number of branches (or member directories)
18392+ in a single aufs. The larger value consumes more system
18393+ resources and has a minor impact to performance.
18394+config AUFS_BRANCH_MAX_1023
18395+ bool "1023"
18396+ help
18397+ Specifies the maximum number of branches (or member directories)
18398+ in a single aufs. The larger value consumes more system
18399+ resources and has a minor impact to performance.
18400+config AUFS_BRANCH_MAX_32767
18401+ bool "32767"
18402+ help
18403+ Specifies the maximum number of branches (or member directories)
18404+ in a single aufs. The larger value consumes more system
18405+ resources and has a minor impact to performance.
18406+endchoice
1facf9fc 18407+
e49829fe
JR
18408+config AUFS_SBILIST
18409+ bool
18410+ depends on AUFS_MAGIC_SYSRQ || PROC_FS
18411+ default y
18412+ help
18413+ Automatic configuration for internal use.
18414+ When aufs supports Magic SysRq or /proc, enabled automatically.
18415+
4a4d8108
AM
18416+config AUFS_HNOTIFY
18417+ bool "Detect direct branch access (bypassing aufs)"
18418+ help
18419+ If you want to modify files on branches directly, eg. bypassing aufs,
18420+ and want aufs to detect the changes of them fully, then enable this
18421+ option and use 'udba=notify' mount option.
7f207e10 18422+ Currently there is only one available configuration, "fsnotify".
4a4d8108
AM
18423+ It will have a negative impact to the performance.
18424+ See detail in aufs.5.
dece6358 18425+
4a4d8108
AM
18426+choice
18427+ prompt "method" if AUFS_HNOTIFY
18428+ default AUFS_HFSNOTIFY
18429+config AUFS_HFSNOTIFY
18430+ bool "fsnotify"
18431+ select FSNOTIFY
4a4d8108 18432+endchoice
1facf9fc 18433+
4a4d8108
AM
18434+config AUFS_EXPORT
18435+ bool "NFS-exportable aufs"
2cbb1c4b 18436+ depends on EXPORTFS
4a4d8108
AM
18437+ help
18438+ If you want to export your mounted aufs via NFS, then enable this
18439+ option. There are several requirements for this configuration.
18440+ See detail in aufs.5.
1facf9fc 18441+
4a4d8108
AM
18442+config AUFS_INO_T_64
18443+ bool
18444+ depends on AUFS_EXPORT
18445+ depends on 64BIT && !(ALPHA || S390)
18446+ default y
18447+ help
18448+ Automatic configuration for internal use.
18449+ /* typedef unsigned long/int __kernel_ino_t */
18450+ /* alpha and s390x are int */
1facf9fc 18451+
4a4d8108
AM
18452+config AUFS_RDU
18453+ bool "Readdir in userspace"
18454+ help
18455+ Aufs has two methods to provide a merged view for a directory,
18456+ by a user-space library and by kernel-space natively. The latter
18457+ is always enabled but sometimes large and slow.
18458+ If you enable this option, install the library in aufs2-util
18459+ package, and set some environment variables for your readdir(3),
18460+ then the work will be handled in user-space which generally
18461+ shows better performance in most cases.
18462+ See detail in aufs.5.
1facf9fc 18463+
2cbb1c4b
JR
18464+config AUFS_PROC_MAP
18465+ bool "support for /proc/maps and lsof(1)"
18466+ depends on PROC_FS
18467+ help
18468+ When you issue mmap(2) in aufs, it is actually a direct mmap(2)
18469+ call to the file on the branch fs since the file in aufs is
18470+ purely virtual. And the file path printed in /proc/maps (and
18471+ others) will be the path on the branch fs. In most cases, it
18472+ does no harm. But some utilities like lsof(1) may confuse since
18473+ the utility or user may expect the file path in aufs to be
18474+ printed.
18475+ To address this issue, aufs provides a patch which introduces a
18476+ new member called vm_prfile into struct vm_are_struct. The patch
18477+ is meaningless without enabling this configuration since nobody
18478+ sets the new vm_prfile member.
18479+ If you don't apply the patch, then enabling this configuration
18480+ will cause a compile error.
18481+ This approach is fragile since if someone else make some changes
18482+ around vm_file, then vm_prfile may not work anymore. As a
18483+ workaround such case, aufs provides this configuration. If you
18484+ disable it, then lsof(1) may produce incorrect result but the
18485+ problem will be gone even if the aufs patch is applied (I hope).
18486+
4a4d8108
AM
18487+config AUFS_SP_IATTR
18488+ bool "Respect the attributes (mtime/ctime mainly) of special files"
18489+ help
18490+ When you write something to a special file, some attributes of it
18491+ (mtime/ctime mainly) may be updated. Generally such updates are
18492+ less important (actually some device drivers and NFS ignore
18493+ it). But some applications (such like test program) requires
18494+ such updates. If you need these updates, then enable this
18495+ configuration which introduces some overhead.
18496+ Currently this configuration handles FIFO only.
1facf9fc 18497+
4a4d8108
AM
18498+config AUFS_SHWH
18499+ bool "Show whiteouts"
18500+ help
18501+ If you want to make the whiteouts in aufs visible, then enable
18502+ this option and specify 'shwh' mount option. Although it may
18503+ sounds like philosophy or something, but in technically it
18504+ simply shows the name of whiteout with keeping its behaviour.
1facf9fc 18505+
4a4d8108
AM
18506+config AUFS_BR_RAMFS
18507+ bool "Ramfs (initramfs/rootfs) as an aufs branch"
18508+ help
18509+ If you want to use ramfs as an aufs branch fs, then enable this
18510+ option. Generally tmpfs is recommended.
18511+ Aufs prohibited them to be a branch fs by default, because
18512+ initramfs becomes unusable after switch_root or something
18513+ generally. If you sets initramfs as an aufs branch and boot your
18514+ system by switch_root, you will meet a problem easily since the
18515+ files in initramfs may be inaccessible.
18516+ Unless you are going to use ramfs as an aufs branch fs without
18517+ switch_root or something, leave it N.
1facf9fc 18518+
4a4d8108
AM
18519+config AUFS_BR_FUSE
18520+ bool "Fuse fs as an aufs branch"
18521+ depends on FUSE_FS
18522+ select AUFS_POLL
18523+ help
18524+ If you want to use fuse-based userspace filesystem as an aufs
18525+ branch fs, then enable this option.
18526+ It implements the internal poll(2) operation which is
18527+ implemented by fuse only (curretnly).
1facf9fc 18528+
4a4d8108
AM
18529+config AUFS_POLL
18530+ bool
18531+ help
18532+ Automatic configuration for internal use.
1facf9fc 18533+
4a4d8108
AM
18534+config AUFS_BR_HFSPLUS
18535+ bool "Hfsplus as an aufs branch"
18536+ depends on HFSPLUS_FS
18537+ default y
18538+ help
18539+ If you want to use hfsplus fs as an aufs branch fs, then enable
18540+ this option. This option introduces a small overhead at
18541+ copying-up a file on hfsplus.
1facf9fc 18542+
4a4d8108
AM
18543+config AUFS_BDEV_LOOP
18544+ bool
18545+ depends on BLK_DEV_LOOP
18546+ default y
18547+ help
18548+ Automatic configuration for internal use.
18549+ Convert =[ym] into =y.
1308ab2a 18550+
4a4d8108
AM
18551+config AUFS_DEBUG
18552+ bool "Debug aufs"
18553+ help
18554+ Enable this to compile aufs internal debug code.
18555+ It will have a negative impact to the performance.
18556+
18557+config AUFS_MAGIC_SYSRQ
18558+ bool
18559+ depends on AUFS_DEBUG && MAGIC_SYSRQ
18560+ default y
18561+ help
18562+ Automatic configuration for internal use.
18563+ When aufs supports Magic SysRq, enabled automatically.
18564+endif
7f207e10
AM
18565diff -urN /usr/share/empty/fs/aufs/loop.c linux/fs/aufs/loop.c
18566--- /usr/share/empty/fs/aufs/loop.c 1970-01-01 01:00:00.000000000 +0100
537831f9 18567+++ linux/fs/aufs/loop.c 2012-12-13 20:41:10.431460173 +0100
87a755f4 18568@@ -0,0 +1,133 @@
1facf9fc 18569+/*
f6c5ef8b 18570+ * Copyright (C) 2005-2012 Junjiro R. Okajima
1facf9fc 18571+ *
18572+ * This program, aufs is free software; you can redistribute it and/or modify
18573+ * it under the terms of the GNU General Public License as published by
18574+ * the Free Software Foundation; either version 2 of the License, or
18575+ * (at your option) any later version.
dece6358
AM
18576+ *
18577+ * This program is distributed in the hope that it will be useful,
18578+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
18579+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18580+ * GNU General Public License for more details.
18581+ *
18582+ * You should have received a copy of the GNU General Public License
18583+ * along with this program; if not, write to the Free Software
18584+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 18585+ */
18586+
18587+/*
18588+ * support for loopback block device as a branch
18589+ */
18590+
18591+#include <linux/loop.h>
18592+#include "aufs.h"
18593+
18594+/*
18595+ * test if two lower dentries have overlapping branches.
18596+ */
b752ccd1 18597+int au_test_loopback_overlap(struct super_block *sb, struct dentry *h_adding)
1facf9fc 18598+{
b752ccd1 18599+ struct super_block *h_sb;
1facf9fc 18600+ struct loop_device *l;
18601+
b752ccd1
AM
18602+ h_sb = h_adding->d_sb;
18603+ if (MAJOR(h_sb->s_dev) != LOOP_MAJOR)
1facf9fc 18604+ return 0;
18605+
b752ccd1
AM
18606+ l = h_sb->s_bdev->bd_disk->private_data;
18607+ h_adding = l->lo_backing_file->f_dentry;
18608+ /*
18609+ * h_adding can be local NFS.
18610+ * in this case aufs cannot detect the loop.
18611+ */
18612+ if (unlikely(h_adding->d_sb == sb))
1facf9fc 18613+ return 1;
b752ccd1 18614+ return !!au_test_subdir(h_adding, sb->s_root);
1facf9fc 18615+}
18616+
18617+/* true if a kernel thread named 'loop[0-9].*' accesses a file */
18618+int au_test_loopback_kthread(void)
18619+{
b752ccd1
AM
18620+ int ret;
18621+ struct task_struct *tsk = current;
18622+
18623+ ret = 0;
18624+ if (tsk->flags & PF_KTHREAD) {
18625+ const char c = tsk->comm[4];
18626+ ret = ('0' <= c && c <= '9'
18627+ && !strncmp(tsk->comm, "loop", 4));
18628+ }
1facf9fc 18629+
b752ccd1 18630+ return ret;
1facf9fc 18631+}
87a755f4
AM
18632+
18633+/* ---------------------------------------------------------------------- */
18634+
18635+#define au_warn_loopback_step 16
18636+static int au_warn_loopback_nelem = au_warn_loopback_step;
18637+static unsigned long *au_warn_loopback_array;
18638+
18639+void au_warn_loopback(struct super_block *h_sb)
18640+{
18641+ int i, new_nelem;
18642+ unsigned long *a, magic;
18643+ static DEFINE_SPINLOCK(spin);
18644+
18645+ magic = h_sb->s_magic;
18646+ spin_lock(&spin);
18647+ a = au_warn_loopback_array;
18648+ for (i = 0; i < au_warn_loopback_nelem && *a; i++)
18649+ if (a[i] == magic) {
18650+ spin_unlock(&spin);
18651+ return;
18652+ }
18653+
18654+ /* h_sb is new to us, print it */
18655+ if (i < au_warn_loopback_nelem) {
18656+ a[i] = magic;
18657+ goto pr;
18658+ }
18659+
18660+ /* expand the array */
18661+ new_nelem = au_warn_loopback_nelem + au_warn_loopback_step;
18662+ a = au_kzrealloc(au_warn_loopback_array,
18663+ au_warn_loopback_nelem * sizeof(unsigned long),
18664+ new_nelem * sizeof(unsigned long), GFP_ATOMIC);
18665+ if (a) {
18666+ au_warn_loopback_nelem = new_nelem;
18667+ au_warn_loopback_array = a;
18668+ a[i] = magic;
18669+ goto pr;
18670+ }
18671+
18672+ spin_unlock(&spin);
18673+ AuWarn1("realloc failed, ignored\n");
18674+ return;
18675+
18676+pr:
18677+ spin_unlock(&spin);
0c3ec466
AM
18678+ pr_warn("you may want to try another patch for loopback file "
18679+ "on %s(0x%lx) branch\n", au_sbtype(h_sb), magic);
87a755f4
AM
18680+}
18681+
18682+int au_loopback_init(void)
18683+{
18684+ int err;
18685+ struct super_block *sb __maybe_unused;
18686+
18687+ AuDebugOn(sizeof(sb->s_magic) != sizeof(unsigned long));
18688+
18689+ err = 0;
18690+ au_warn_loopback_array = kcalloc(au_warn_loopback_step,
18691+ sizeof(unsigned long), GFP_NOFS);
18692+ if (unlikely(!au_warn_loopback_array))
18693+ err = -ENOMEM;
18694+
18695+ return err;
18696+}
18697+
18698+void au_loopback_fin(void)
18699+{
18700+ kfree(au_warn_loopback_array);
18701+}
7f207e10
AM
18702diff -urN /usr/share/empty/fs/aufs/loop.h linux/fs/aufs/loop.h
18703--- /usr/share/empty/fs/aufs/loop.h 1970-01-01 01:00:00.000000000 +0100
537831f9 18704+++ linux/fs/aufs/loop.h 2012-12-13 20:41:10.431460173 +0100
87a755f4 18705@@ -0,0 +1,50 @@
1facf9fc 18706+/*
f6c5ef8b 18707+ * Copyright (C) 2005-2012 Junjiro R. Okajima
1facf9fc 18708+ *
18709+ * This program, aufs is free software; you can redistribute it and/or modify
18710+ * it under the terms of the GNU General Public License as published by
18711+ * the Free Software Foundation; either version 2 of the License, or
18712+ * (at your option) any later version.
dece6358
AM
18713+ *
18714+ * This program is distributed in the hope that it will be useful,
18715+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
18716+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18717+ * GNU General Public License for more details.
18718+ *
18719+ * You should have received a copy of the GNU General Public License
18720+ * along with this program; if not, write to the Free Software
18721+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 18722+ */
18723+
18724+/*
18725+ * support for loopback mount as a branch
18726+ */
18727+
18728+#ifndef __AUFS_LOOP_H__
18729+#define __AUFS_LOOP_H__
18730+
18731+#ifdef __KERNEL__
18732+
dece6358
AM
18733+struct dentry;
18734+struct super_block;
1facf9fc 18735+
18736+#ifdef CONFIG_AUFS_BDEV_LOOP
18737+/* loop.c */
b752ccd1 18738+int au_test_loopback_overlap(struct super_block *sb, struct dentry *h_adding);
1facf9fc 18739+int au_test_loopback_kthread(void);
87a755f4
AM
18740+void au_warn_loopback(struct super_block *h_sb);
18741+
18742+int au_loopback_init(void);
18743+void au_loopback_fin(void);
1facf9fc 18744+#else
4a4d8108 18745+AuStubInt0(au_test_loopback_overlap, struct super_block *sb,
b752ccd1 18746+ struct dentry *h_adding)
4a4d8108 18747+AuStubInt0(au_test_loopback_kthread, void)
87a755f4
AM
18748+AuStubVoid(au_warn_loopback, struct super_block *h_sb)
18749+
18750+AuStubInt0(au_loopback_init, void)
18751+AuStubVoid(au_loopback_fin, void)
1facf9fc 18752+#endif /* BLK_DEV_LOOP */
18753+
18754+#endif /* __KERNEL__ */
18755+#endif /* __AUFS_LOOP_H__ */
7f207e10
AM
18756diff -urN /usr/share/empty/fs/aufs/magic.mk linux/fs/aufs/magic.mk
18757--- /usr/share/empty/fs/aufs/magic.mk 1970-01-01 01:00:00.000000000 +0100
537831f9 18758+++ linux/fs/aufs/magic.mk 2012-12-13 20:41:10.431460173 +0100
4a4d8108 18759@@ -0,0 +1,54 @@
1facf9fc 18760+
18761+# defined in ${srctree}/fs/fuse/inode.c
18762+# tristate
18763+ifdef CONFIG_FUSE_FS
18764+ccflags-y += -DFUSE_SUPER_MAGIC=0x65735546
18765+endif
18766+
18767+# defined in ${srctree}/fs/ocfs2/ocfs2_fs.h
18768+# tristate
18769+ifdef CONFIG_OCFS2_FS
18770+ccflags-y += -DOCFS2_SUPER_MAGIC=0x7461636f
18771+endif
18772+
18773+# defined in ${srctree}/fs/ocfs2/dlm/userdlm.h
18774+# tristate
18775+ifdef CONFIG_OCFS2_FS_O2CB
18776+ccflags-y += -DDLMFS_MAGIC=0x76a9f425
18777+endif
18778+
1facf9fc 18779+# defined in ${srctree}/fs/cifs/cifsfs.c
18780+# tristate
18781+ifdef CONFIG_CIFS_FS
18782+ccflags-y += -DCIFS_MAGIC_NUMBER=0xFF534D42
18783+endif
18784+
18785+# defined in ${srctree}/fs/xfs/xfs_sb.h
18786+# tristate
18787+ifdef CONFIG_XFS_FS
18788+ccflags-y += -DXFS_SB_MAGIC=0x58465342
18789+endif
18790+
18791+# defined in ${srctree}/fs/configfs/mount.c
18792+# tristate
18793+ifdef CONFIG_CONFIGFS_FS
18794+ccflags-y += -DCONFIGFS_MAGIC=0x62656570
18795+endif
18796+
18797+# defined in ${srctree}/fs/9p/v9fs.h
18798+# tristate
18799+ifdef CONFIG_9P_FS
18800+ccflags-y += -DV9FS_MAGIC=0x01021997
18801+endif
18802+
18803+# defined in ${srctree}/fs/ubifs/ubifs.h
18804+# tristate
18805+ifdef CONFIG_UBIFS_FS
18806+ccflags-y += -DUBIFS_SUPER_MAGIC=0x24051905
18807+endif
4a4d8108
AM
18808+
18809+# defined in ${srctree}/fs/hfsplus/hfsplus_raw.h
18810+# tristate
18811+ifdef CONFIG_HFSPLUS_FS
18812+ccflags-y += -DHFSPLUS_SUPER_MAGIC=0x482b
18813+endif
7f207e10
AM
18814diff -urN /usr/share/empty/fs/aufs/Makefile linux/fs/aufs/Makefile
18815--- /usr/share/empty/fs/aufs/Makefile 1970-01-01 01:00:00.000000000 +0100
537831f9 18816+++ linux/fs/aufs/Makefile 2012-12-13 20:41:10.428126759 +0100
2dfbb274 18817@@ -0,0 +1,42 @@
4a4d8108
AM
18818+
18819+include ${src}/magic.mk
18820+ifeq (${CONFIG_AUFS_FS},m)
18821+include ${src}/conf.mk
18822+endif
18823+-include ${src}/priv_def.mk
18824+
18825+# cf. include/linux/kernel.h
18826+# enable pr_debug
18827+ccflags-y += -DDEBUG
f6c5ef8b
AM
18828+# sparse requires the full pathname
18829+ifdef M
18830+ccflags-y += -include ${M}/../../include/linux/aufs_type.h
18831+else
18832+ccflags-y += -include ${srctree}/include/linux/aufs_type.h
18833+endif
4a4d8108
AM
18834+
18835+obj-$(CONFIG_AUFS_FS) += aufs.o
18836+aufs-y := module.o sbinfo.o super.o branch.o xino.o sysaufs.o opts.o \
18837+ wkq.o vfsub.o dcsub.o \
e49829fe 18838+ cpup.o whout.o wbr_policy.o \
4a4d8108
AM
18839+ dinfo.o dentry.o \
18840+ dynop.o \
18841+ finfo.o file.o f_op.o \
18842+ dir.o vdir.o \
18843+ iinfo.o inode.o i_op.o i_op_add.o i_op_del.o i_op_ren.o \
18844+ ioctl.o
18845+
18846+# all are boolean
e49829fe 18847+aufs-$(CONFIG_PROC_FS) += procfs.o plink.o
4a4d8108
AM
18848+aufs-$(CONFIG_SYSFS) += sysfs.o
18849+aufs-$(CONFIG_DEBUG_FS) += dbgaufs.o
18850+aufs-$(CONFIG_AUFS_BDEV_LOOP) += loop.o
18851+aufs-$(CONFIG_AUFS_HNOTIFY) += hnotify.o
18852+aufs-$(CONFIG_AUFS_HFSNOTIFY) += hfsnotify.o
4a4d8108
AM
18853+aufs-$(CONFIG_AUFS_EXPORT) += export.o
18854+aufs-$(CONFIG_AUFS_POLL) += poll.o
18855+aufs-$(CONFIG_AUFS_RDU) += rdu.o
18856+aufs-$(CONFIG_AUFS_SP_IATTR) += f_op_sp.o
18857+aufs-$(CONFIG_AUFS_BR_HFSPLUS) += hfsplus.o
18858+aufs-$(CONFIG_AUFS_DEBUG) += debug.o
18859+aufs-$(CONFIG_AUFS_MAGIC_SYSRQ) += sysrq.o
7f207e10
AM
18860diff -urN /usr/share/empty/fs/aufs/module.c linux/fs/aufs/module.c
18861--- /usr/share/empty/fs/aufs/module.c 1970-01-01 01:00:00.000000000 +0100
537831f9
AM
18862+++ linux/fs/aufs/module.c 2012-12-13 20:41:10.431460173 +0100
18863@@ -0,0 +1,202 @@
1facf9fc 18864+/*
f6c5ef8b 18865+ * Copyright (C) 2005-2012 Junjiro R. Okajima
1facf9fc 18866+ *
18867+ * This program, aufs is free software; you can redistribute it and/or modify
18868+ * it under the terms of the GNU General Public License as published by
18869+ * the Free Software Foundation; either version 2 of the License, or
18870+ * (at your option) any later version.
dece6358
AM
18871+ *
18872+ * This program is distributed in the hope that it will be useful,
18873+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
18874+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18875+ * GNU General Public License for more details.
18876+ *
18877+ * You should have received a copy of the GNU General Public License
18878+ * along with this program; if not, write to the Free Software
18879+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 18880+ */
18881+
18882+/*
18883+ * module global variables and operations
18884+ */
18885+
18886+#include <linux/module.h>
18887+#include <linux/seq_file.h>
18888+#include "aufs.h"
18889+
18890+void *au_kzrealloc(void *p, unsigned int nused, unsigned int new_sz, gfp_t gfp)
18891+{
18892+ if (new_sz <= nused)
18893+ return p;
18894+
18895+ p = krealloc(p, new_sz, gfp);
18896+ if (p)
18897+ memset(p + nused, 0, new_sz - nused);
18898+ return p;
18899+}
18900+
18901+/* ---------------------------------------------------------------------- */
18902+
18903+/*
18904+ * aufs caches
18905+ */
18906+struct kmem_cache *au_cachep[AuCache_Last];
18907+static int __init au_cache_init(void)
18908+{
4a4d8108 18909+ au_cachep[AuCache_DINFO] = AuCacheCtor(au_dinfo, au_di_init_once);
1facf9fc 18910+ if (au_cachep[AuCache_DINFO])
027c5e7a 18911+ /* SLAB_DESTROY_BY_RCU */
4a4d8108
AM
18912+ au_cachep[AuCache_ICNTNR] = AuCacheCtor(au_icntnr,
18913+ au_icntnr_init_once);
1facf9fc 18914+ if (au_cachep[AuCache_ICNTNR])
4a4d8108
AM
18915+ au_cachep[AuCache_FINFO] = AuCacheCtor(au_finfo,
18916+ au_fi_init_once);
1facf9fc 18917+ if (au_cachep[AuCache_FINFO])
18918+ au_cachep[AuCache_VDIR] = AuCache(au_vdir);
18919+ if (au_cachep[AuCache_VDIR])
18920+ au_cachep[AuCache_DEHSTR] = AuCache(au_vdir_dehstr);
18921+ if (au_cachep[AuCache_DEHSTR])
18922+ return 0;
18923+
18924+ return -ENOMEM;
18925+}
18926+
18927+static void au_cache_fin(void)
18928+{
18929+ int i;
4a4d8108 18930+
537831f9
AM
18931+ /*
18932+ * Make sure all delayed rcu free inodes are flushed before we
18933+ * destroy cache.
18934+ */
18935+ rcu_barrier();
18936+
7eafdf33
AM
18937+ /* excluding AuCache_HNOTIFY */
18938+ BUILD_BUG_ON(AuCache_HNOTIFY + 1 != AuCache_Last);
18939+ for (i = 0; i < AuCache_HNOTIFY; i++)
1facf9fc 18940+ if (au_cachep[i]) {
18941+ kmem_cache_destroy(au_cachep[i]);
18942+ au_cachep[i] = NULL;
18943+ }
18944+}
18945+
18946+/* ---------------------------------------------------------------------- */
18947+
18948+int au_dir_roflags;
18949+
e49829fe 18950+#ifdef CONFIG_AUFS_SBILIST
1e00d052
AM
18951+/*
18952+ * iterate_supers_type() doesn't protect us from
18953+ * remounting (branch management)
18954+ */
e49829fe
JR
18955+struct au_splhead au_sbilist;
18956+#endif
18957+
9dbd164d
AM
18958+struct lock_class_key au_lc_key[AuLcKey_Last];
18959+
1facf9fc 18960+/*
18961+ * functions for module interface.
18962+ */
18963+MODULE_LICENSE("GPL");
18964+/* MODULE_LICENSE("GPL v2"); */
dece6358 18965+MODULE_AUTHOR("Junjiro R. Okajima <aufs-users@lists.sourceforge.net>");
1facf9fc 18966+MODULE_DESCRIPTION(AUFS_NAME
18967+ " -- Advanced multi layered unification filesystem");
18968+MODULE_VERSION(AUFS_VERSION);
18969+
1facf9fc 18970+/* this module parameter has no meaning when SYSFS is disabled */
18971+int sysaufs_brs = 1;
18972+MODULE_PARM_DESC(brs, "use <sysfs>/fs/aufs/si_*/brN");
18973+module_param_named(brs, sysaufs_brs, int, S_IRUGO);
18974+
18975+/* ---------------------------------------------------------------------- */
18976+
18977+static char au_esc_chars[0x20 + 3]; /* 0x01-0x20, backslash, del, and NULL */
18978+
18979+int au_seq_path(struct seq_file *seq, struct path *path)
18980+{
18981+ return seq_path(seq, path, au_esc_chars);
18982+}
18983+
18984+/* ---------------------------------------------------------------------- */
18985+
18986+static int __init aufs_init(void)
18987+{
18988+ int err, i;
18989+ char *p;
18990+
18991+ p = au_esc_chars;
18992+ for (i = 1; i <= ' '; i++)
18993+ *p++ = i;
18994+ *p++ = '\\';
18995+ *p++ = '\x7f';
18996+ *p = 0;
18997+
18998+ au_dir_roflags = au_file_roflags(O_DIRECTORY | O_LARGEFILE);
18999+
e49829fe 19000+ au_sbilist_init();
1facf9fc 19001+ sysaufs_brs_init();
19002+ au_debug_init();
4a4d8108 19003+ au_dy_init();
1facf9fc 19004+ err = sysaufs_init();
19005+ if (unlikely(err))
19006+ goto out;
e49829fe 19007+ err = au_procfs_init();
4f0767ce 19008+ if (unlikely(err))
953406b4 19009+ goto out_sysaufs;
e49829fe
JR
19010+ err = au_wkq_init();
19011+ if (unlikely(err))
19012+ goto out_procfs;
87a755f4 19013+ err = au_loopback_init();
1facf9fc 19014+ if (unlikely(err))
19015+ goto out_wkq;
87a755f4
AM
19016+ err = au_hnotify_init();
19017+ if (unlikely(err))
19018+ goto out_loopback;
1facf9fc 19019+ err = au_sysrq_init();
19020+ if (unlikely(err))
19021+ goto out_hin;
19022+ err = au_cache_init();
19023+ if (unlikely(err))
19024+ goto out_sysrq;
19025+ err = register_filesystem(&aufs_fs_type);
19026+ if (unlikely(err))
19027+ goto out_cache;
4a4d8108
AM
19028+ /* since we define pr_fmt, call printk directly */
19029+ printk(KERN_INFO AUFS_NAME " " AUFS_VERSION "\n");
1facf9fc 19030+ goto out; /* success */
19031+
4f0767ce 19032+out_cache:
1facf9fc 19033+ au_cache_fin();
4f0767ce 19034+out_sysrq:
1facf9fc 19035+ au_sysrq_fin();
4f0767ce 19036+out_hin:
4a4d8108 19037+ au_hnotify_fin();
87a755f4
AM
19038+out_loopback:
19039+ au_loopback_fin();
4f0767ce 19040+out_wkq:
1facf9fc 19041+ au_wkq_fin();
e49829fe
JR
19042+out_procfs:
19043+ au_procfs_fin();
4f0767ce 19044+out_sysaufs:
1facf9fc 19045+ sysaufs_fin();
4a4d8108 19046+ au_dy_fin();
4f0767ce 19047+out:
1facf9fc 19048+ return err;
19049+}
19050+
19051+static void __exit aufs_exit(void)
19052+{
19053+ unregister_filesystem(&aufs_fs_type);
19054+ au_cache_fin();
19055+ au_sysrq_fin();
4a4d8108 19056+ au_hnotify_fin();
87a755f4 19057+ au_loopback_fin();
1facf9fc 19058+ au_wkq_fin();
e49829fe 19059+ au_procfs_fin();
1facf9fc 19060+ sysaufs_fin();
4a4d8108 19061+ au_dy_fin();
1facf9fc 19062+}
19063+
19064+module_init(aufs_init);
19065+module_exit(aufs_exit);
7f207e10
AM
19066diff -urN /usr/share/empty/fs/aufs/module.h linux/fs/aufs/module.h
19067--- /usr/share/empty/fs/aufs/module.h 1970-01-01 01:00:00.000000000 +0100
537831f9 19068+++ linux/fs/aufs/module.h 2012-12-13 20:41:10.431460173 +0100
7eafdf33 19069@@ -0,0 +1,105 @@
1facf9fc 19070+/*
f6c5ef8b 19071+ * Copyright (C) 2005-2012 Junjiro R. Okajima
1facf9fc 19072+ *
19073+ * This program, aufs is free software; you can redistribute it and/or modify
19074+ * it under the terms of the GNU General Public License as published by
19075+ * the Free Software Foundation; either version 2 of the License, or
19076+ * (at your option) any later version.
dece6358
AM
19077+ *
19078+ * This program is distributed in the hope that it will be useful,
19079+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
19080+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19081+ * GNU General Public License for more details.
19082+ *
19083+ * You should have received a copy of the GNU General Public License
19084+ * along with this program; if not, write to the Free Software
19085+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 19086+ */
19087+
19088+/*
19089+ * module initialization and module-global
19090+ */
19091+
19092+#ifndef __AUFS_MODULE_H__
19093+#define __AUFS_MODULE_H__
19094+
19095+#ifdef __KERNEL__
19096+
19097+#include <linux/slab.h>
19098+
dece6358
AM
19099+struct path;
19100+struct seq_file;
19101+
1facf9fc 19102+/* module parameters */
1facf9fc 19103+extern int sysaufs_brs;
19104+
19105+/* ---------------------------------------------------------------------- */
19106+
19107+extern int au_dir_roflags;
19108+
9dbd164d
AM
19109+enum {
19110+ AuLcNonDir_FIINFO,
19111+ AuLcNonDir_DIINFO,
19112+ AuLcNonDir_IIINFO,
19113+
19114+ AuLcDir_FIINFO,
19115+ AuLcDir_DIINFO,
19116+ AuLcDir_IIINFO,
19117+
19118+ AuLcSymlink_DIINFO,
19119+ AuLcSymlink_IIINFO,
19120+
19121+ AuLcKey_Last
19122+};
19123+extern struct lock_class_key au_lc_key[AuLcKey_Last];
19124+
1facf9fc 19125+void *au_kzrealloc(void *p, unsigned int nused, unsigned int new_sz, gfp_t gfp);
19126+int au_seq_path(struct seq_file *seq, struct path *path);
19127+
e49829fe
JR
19128+#ifdef CONFIG_PROC_FS
19129+/* procfs.c */
19130+int __init au_procfs_init(void);
19131+void au_procfs_fin(void);
19132+#else
19133+AuStubInt0(au_procfs_init, void);
19134+AuStubVoid(au_procfs_fin, void);
19135+#endif
19136+
4f0767ce
JR
19137+/* ---------------------------------------------------------------------- */
19138+
19139+/* kmem cache */
1facf9fc 19140+enum {
19141+ AuCache_DINFO,
19142+ AuCache_ICNTNR,
19143+ AuCache_FINFO,
19144+ AuCache_VDIR,
19145+ AuCache_DEHSTR,
7eafdf33 19146+ AuCache_HNOTIFY, /* must be last */
1facf9fc 19147+ AuCache_Last
19148+};
19149+
4a4d8108
AM
19150+#define AuCacheFlags (SLAB_RECLAIM_ACCOUNT | SLAB_MEM_SPREAD)
19151+#define AuCache(type) KMEM_CACHE(type, AuCacheFlags)
19152+#define AuCacheCtor(type, ctor) \
19153+ kmem_cache_create(#type, sizeof(struct type), \
19154+ __alignof__(struct type), AuCacheFlags, ctor)
1facf9fc 19155+
19156+extern struct kmem_cache *au_cachep[];
19157+
19158+#define AuCacheFuncs(name, index) \
4a4d8108 19159+static inline struct au_##name *au_cache_alloc_##name(void) \
1facf9fc 19160+{ return kmem_cache_alloc(au_cachep[AuCache_##index], GFP_NOFS); } \
4a4d8108 19161+static inline void au_cache_free_##name(struct au_##name *p) \
1facf9fc 19162+{ kmem_cache_free(au_cachep[AuCache_##index], p); }
19163+
19164+AuCacheFuncs(dinfo, DINFO);
19165+AuCacheFuncs(icntnr, ICNTNR);
19166+AuCacheFuncs(finfo, FINFO);
19167+AuCacheFuncs(vdir, VDIR);
4a4d8108
AM
19168+AuCacheFuncs(vdir_dehstr, DEHSTR);
19169+#ifdef CONFIG_AUFS_HNOTIFY
19170+AuCacheFuncs(hnotify, HNOTIFY);
19171+#endif
1facf9fc 19172+
4a4d8108
AM
19173+#endif /* __KERNEL__ */
19174+#endif /* __AUFS_MODULE_H__ */
7f207e10
AM
19175diff -urN /usr/share/empty/fs/aufs/opts.c linux/fs/aufs/opts.c
19176--- /usr/share/empty/fs/aufs/opts.c 1970-01-01 01:00:00.000000000 +0100
537831f9 19177+++ linux/fs/aufs/opts.c 2012-12-13 20:41:10.431460173 +0100
f6c5ef8b 19178@@ -0,0 +1,1677 @@
1facf9fc 19179+/*
f6c5ef8b 19180+ * Copyright (C) 2005-2012 Junjiro R. Okajima
1facf9fc 19181+ *
19182+ * This program, aufs is free software; you can redistribute it and/or modify
19183+ * it under the terms of the GNU General Public License as published by
19184+ * the Free Software Foundation; either version 2 of the License, or
19185+ * (at your option) any later version.
dece6358
AM
19186+ *
19187+ * This program is distributed in the hope that it will be useful,
19188+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
19189+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19190+ * GNU General Public License for more details.
19191+ *
19192+ * You should have received a copy of the GNU General Public License
19193+ * along with this program; if not, write to the Free Software
19194+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 19195+ */
19196+
19197+/*
19198+ * mount options/flags
19199+ */
19200+
dece6358 19201+#include <linux/namei.h>
1facf9fc 19202+#include <linux/types.h> /* a distribution requires */
19203+#include <linux/parser.h>
19204+#include "aufs.h"
19205+
19206+/* ---------------------------------------------------------------------- */
19207+
19208+enum {
19209+ Opt_br,
19210+ Opt_add, Opt_del, Opt_mod, Opt_reorder, Opt_append, Opt_prepend,
19211+ Opt_idel, Opt_imod, Opt_ireorder,
19212+ Opt_dirwh, Opt_rdcache, Opt_rdblk, Opt_rdhash, Opt_rendir,
dece6358 19213+ Opt_rdblk_def, Opt_rdhash_def,
1facf9fc 19214+ Opt_xino, Opt_zxino, Opt_noxino,
19215+ Opt_trunc_xino, Opt_trunc_xino_v, Opt_notrunc_xino,
19216+ Opt_trunc_xino_path, Opt_itrunc_xino,
19217+ Opt_trunc_xib, Opt_notrunc_xib,
dece6358 19218+ Opt_shwh, Opt_noshwh,
1facf9fc 19219+ Opt_plink, Opt_noplink, Opt_list_plink,
19220+ Opt_udba,
4a4d8108 19221+ Opt_dio, Opt_nodio,
1facf9fc 19222+ /* Opt_lock, Opt_unlock, */
19223+ Opt_cmd, Opt_cmd_args,
19224+ Opt_diropq_a, Opt_diropq_w,
19225+ Opt_warn_perm, Opt_nowarn_perm,
19226+ Opt_wbr_copyup, Opt_wbr_create,
19227+ Opt_refrof, Opt_norefrof,
19228+ Opt_verbose, Opt_noverbose,
19229+ Opt_sum, Opt_nosum, Opt_wsum,
19230+ Opt_tail, Opt_ignore, Opt_ignore_silent, Opt_err
19231+};
19232+
19233+static match_table_t options = {
19234+ {Opt_br, "br=%s"},
19235+ {Opt_br, "br:%s"},
19236+
19237+ {Opt_add, "add=%d:%s"},
19238+ {Opt_add, "add:%d:%s"},
19239+ {Opt_add, "ins=%d:%s"},
19240+ {Opt_add, "ins:%d:%s"},
19241+ {Opt_append, "append=%s"},
19242+ {Opt_append, "append:%s"},
19243+ {Opt_prepend, "prepend=%s"},
19244+ {Opt_prepend, "prepend:%s"},
19245+
19246+ {Opt_del, "del=%s"},
19247+ {Opt_del, "del:%s"},
19248+ /* {Opt_idel, "idel:%d"}, */
19249+ {Opt_mod, "mod=%s"},
19250+ {Opt_mod, "mod:%s"},
19251+ /* {Opt_imod, "imod:%d:%s"}, */
19252+
19253+ {Opt_dirwh, "dirwh=%d"},
19254+
19255+ {Opt_xino, "xino=%s"},
19256+ {Opt_noxino, "noxino"},
19257+ {Opt_trunc_xino, "trunc_xino"},
19258+ {Opt_trunc_xino_v, "trunc_xino_v=%d:%d"},
19259+ {Opt_notrunc_xino, "notrunc_xino"},
19260+ {Opt_trunc_xino_path, "trunc_xino=%s"},
19261+ {Opt_itrunc_xino, "itrunc_xino=%d"},
19262+ /* {Opt_zxino, "zxino=%s"}, */
19263+ {Opt_trunc_xib, "trunc_xib"},
19264+ {Opt_notrunc_xib, "notrunc_xib"},
19265+
e49829fe 19266+#ifdef CONFIG_PROC_FS
1facf9fc 19267+ {Opt_plink, "plink"},
e49829fe
JR
19268+#else
19269+ {Opt_ignore_silent, "plink"},
19270+#endif
19271+
1facf9fc 19272+ {Opt_noplink, "noplink"},
e49829fe 19273+
1facf9fc 19274+#ifdef CONFIG_AUFS_DEBUG
19275+ {Opt_list_plink, "list_plink"},
19276+#endif
19277+
19278+ {Opt_udba, "udba=%s"},
19279+
4a4d8108
AM
19280+ {Opt_dio, "dio"},
19281+ {Opt_nodio, "nodio"},
19282+
1facf9fc 19283+ {Opt_diropq_a, "diropq=always"},
19284+ {Opt_diropq_a, "diropq=a"},
19285+ {Opt_diropq_w, "diropq=whiteouted"},
19286+ {Opt_diropq_w, "diropq=w"},
19287+
19288+ {Opt_warn_perm, "warn_perm"},
19289+ {Opt_nowarn_perm, "nowarn_perm"},
19290+
19291+ /* keep them temporary */
19292+ {Opt_ignore_silent, "coo=%s"},
19293+ {Opt_ignore_silent, "nodlgt"},
19294+ {Opt_ignore_silent, "nodirperm1"},
1facf9fc 19295+ {Opt_ignore_silent, "clean_plink"},
19296+
dece6358
AM
19297+#ifdef CONFIG_AUFS_SHWH
19298+ {Opt_shwh, "shwh"},
19299+#endif
19300+ {Opt_noshwh, "noshwh"},
19301+
1facf9fc 19302+ {Opt_rendir, "rendir=%d"},
19303+
19304+ {Opt_refrof, "refrof"},
19305+ {Opt_norefrof, "norefrof"},
19306+
19307+ {Opt_verbose, "verbose"},
19308+ {Opt_verbose, "v"},
19309+ {Opt_noverbose, "noverbose"},
19310+ {Opt_noverbose, "quiet"},
19311+ {Opt_noverbose, "q"},
19312+ {Opt_noverbose, "silent"},
19313+
19314+ {Opt_sum, "sum"},
19315+ {Opt_nosum, "nosum"},
19316+ {Opt_wsum, "wsum"},
19317+
19318+ {Opt_rdcache, "rdcache=%d"},
19319+ {Opt_rdblk, "rdblk=%d"},
dece6358 19320+ {Opt_rdblk_def, "rdblk=def"},
1facf9fc 19321+ {Opt_rdhash, "rdhash=%d"},
dece6358 19322+ {Opt_rdhash_def, "rdhash=def"},
1facf9fc 19323+
19324+ {Opt_wbr_create, "create=%s"},
19325+ {Opt_wbr_create, "create_policy=%s"},
19326+ {Opt_wbr_copyup, "cpup=%s"},
19327+ {Opt_wbr_copyup, "copyup=%s"},
19328+ {Opt_wbr_copyup, "copyup_policy=%s"},
19329+
19330+ /* internal use for the scripts */
19331+ {Opt_ignore_silent, "si=%s"},
19332+
19333+ {Opt_br, "dirs=%s"},
19334+ {Opt_ignore, "debug=%d"},
19335+ {Opt_ignore, "delete=whiteout"},
19336+ {Opt_ignore, "delete=all"},
19337+ {Opt_ignore, "imap=%s"},
19338+
1308ab2a 19339+ /* temporary workaround, due to old mount(8)? */
19340+ {Opt_ignore_silent, "relatime"},
19341+
1facf9fc 19342+ {Opt_err, NULL}
19343+};
19344+
19345+/* ---------------------------------------------------------------------- */
19346+
19347+static const char *au_parser_pattern(int val, struct match_token *token)
19348+{
19349+ while (token->pattern) {
19350+ if (token->token == val)
19351+ return token->pattern;
19352+ token++;
19353+ }
19354+ BUG();
19355+ return "??";
19356+}
19357+
19358+/* ---------------------------------------------------------------------- */
19359+
1e00d052 19360+static match_table_t brperm = {
1facf9fc 19361+ {AuBrPerm_RO, AUFS_BRPERM_RO},
19362+ {AuBrPerm_RR, AUFS_BRPERM_RR},
19363+ {AuBrPerm_RW, AUFS_BRPERM_RW},
1e00d052
AM
19364+ {0, NULL}
19365+};
1facf9fc 19366+
1e00d052
AM
19367+static match_table_t brrattr = {
19368+ {AuBrRAttr_WH, AUFS_BRRATTR_WH},
19369+ {0, NULL}
19370+};
1facf9fc 19371+
1e00d052
AM
19372+static match_table_t brwattr = {
19373+ {AuBrWAttr_NoLinkWH, AUFS_BRWATTR_NLWH},
19374+ {0, NULL}
1facf9fc 19375+};
19376+
1e00d052
AM
19377+#define AuBrStr_LONGEST AUFS_BRPERM_RW "+" AUFS_BRWATTR_NLWH
19378+
19379+static int br_attr_val(char *str, match_table_t table, substring_t args[])
19380+{
19381+ int attr, v;
19382+ char *p;
19383+
19384+ attr = 0;
19385+ do {
19386+ p = strchr(str, '+');
19387+ if (p)
19388+ *p = 0;
19389+ v = match_token(str, table, args);
19390+ if (v)
19391+ attr |= v;
19392+ else {
19393+ if (p)
19394+ *p = '+';
0c3ec466 19395+ pr_warn("ignored branch attribute %s\n", str);
1e00d052
AM
19396+ break;
19397+ }
19398+ if (p)
19399+ str = p + 1;
19400+ } while (p);
19401+
19402+ return attr;
19403+}
19404+
4a4d8108 19405+static int noinline_for_stack br_perm_val(char *perm)
1facf9fc 19406+{
19407+ int val;
1e00d052 19408+ char *p;
1facf9fc 19409+ substring_t args[MAX_OPT_ARGS];
19410+
1e00d052
AM
19411+ p = strchr(perm, '+');
19412+ if (p)
19413+ *p = 0;
19414+ val = match_token(perm, brperm, args);
19415+ if (!val) {
19416+ if (p)
19417+ *p = '+';
0c3ec466 19418+ pr_warn("ignored branch permission %s\n", perm);
1e00d052
AM
19419+ val = AuBrPerm_RO;
19420+ goto out;
19421+ }
19422+ if (!p)
19423+ goto out;
19424+
19425+ switch (val) {
19426+ case AuBrPerm_RO:
19427+ case AuBrPerm_RR:
19428+ val |= br_attr_val(p + 1, brrattr, args);
19429+ break;
19430+ case AuBrPerm_RW:
19431+ val |= br_attr_val(p + 1, brwattr, args);
19432+ break;
19433+ }
19434+
19435+out:
1facf9fc 19436+ return val;
19437+}
19438+
1e00d052
AM
19439+/* Caller should free the return value */
19440+char *au_optstr_br_perm(int brperm)
1facf9fc 19441+{
1e00d052
AM
19442+ char *p, a[sizeof(AuBrStr_LONGEST)];
19443+ int sz;
19444+
19445+#define SetPerm(str) do { \
19446+ sz = sizeof(str); \
19447+ memcpy(a, str, sz); \
19448+ p = a + sz - 1; \
19449+ } while (0)
19450+
19451+#define AppendAttr(flag, str) do { \
19452+ if (brperm & flag) { \
19453+ sz = sizeof(str); \
19454+ *p++ = '+'; \
19455+ memcpy(p, str, sz); \
19456+ p += sz - 1; \
19457+ } \
19458+ } while (0)
19459+
19460+ switch (brperm & AuBrPerm_Mask) {
19461+ case AuBrPerm_RO:
19462+ SetPerm(AUFS_BRPERM_RO);
19463+ break;
19464+ case AuBrPerm_RR:
19465+ SetPerm(AUFS_BRPERM_RR);
19466+ break;
19467+ case AuBrPerm_RW:
19468+ SetPerm(AUFS_BRPERM_RW);
19469+ break;
19470+ default:
19471+ AuDebugOn(1);
19472+ }
19473+
19474+ AppendAttr(AuBrRAttr_WH, AUFS_BRRATTR_WH);
19475+ AppendAttr(AuBrWAttr_NoLinkWH, AUFS_BRWATTR_NLWH);
19476+
19477+ AuDebugOn(strlen(a) >= sizeof(a));
19478+ return kstrdup(a, GFP_NOFS);
19479+#undef SetPerm
19480+#undef AppendAttr
1facf9fc 19481+}
19482+
19483+/* ---------------------------------------------------------------------- */
19484+
19485+static match_table_t udbalevel = {
19486+ {AuOpt_UDBA_REVAL, "reval"},
19487+ {AuOpt_UDBA_NONE, "none"},
4a4d8108
AM
19488+#ifdef CONFIG_AUFS_HNOTIFY
19489+ {AuOpt_UDBA_HNOTIFY, "notify"}, /* abstraction */
19490+#ifdef CONFIG_AUFS_HFSNOTIFY
19491+ {AuOpt_UDBA_HNOTIFY, "fsnotify"},
4a4d8108 19492+#endif
1facf9fc 19493+#endif
19494+ {-1, NULL}
19495+};
19496+
4a4d8108 19497+static int noinline_for_stack udba_val(char *str)
1facf9fc 19498+{
19499+ substring_t args[MAX_OPT_ARGS];
19500+
7f207e10 19501+ return match_token(str, udbalevel, args);
1facf9fc 19502+}
19503+
19504+const char *au_optstr_udba(int udba)
19505+{
19506+ return au_parser_pattern(udba, (void *)udbalevel);
19507+}
19508+
19509+/* ---------------------------------------------------------------------- */
19510+
19511+static match_table_t au_wbr_create_policy = {
19512+ {AuWbrCreate_TDP, "tdp"},
19513+ {AuWbrCreate_TDP, "top-down-parent"},
19514+ {AuWbrCreate_RR, "rr"},
19515+ {AuWbrCreate_RR, "round-robin"},
19516+ {AuWbrCreate_MFS, "mfs"},
19517+ {AuWbrCreate_MFS, "most-free-space"},
19518+ {AuWbrCreate_MFSV, "mfs:%d"},
19519+ {AuWbrCreate_MFSV, "most-free-space:%d"},
19520+
19521+ {AuWbrCreate_MFSRR, "mfsrr:%d"},
19522+ {AuWbrCreate_MFSRRV, "mfsrr:%d:%d"},
19523+ {AuWbrCreate_PMFS, "pmfs"},
19524+ {AuWbrCreate_PMFSV, "pmfs:%d"},
19525+
19526+ {-1, NULL}
19527+};
19528+
dece6358
AM
19529+/*
19530+ * cf. linux/lib/parser.c and cmdline.c
19531+ * gave up calling memparse() since it uses simple_strtoull() instead of
9dbd164d 19532+ * kstrto...().
dece6358 19533+ */
4a4d8108
AM
19534+static int noinline_for_stack
19535+au_match_ull(substring_t *s, unsigned long long *result)
1facf9fc 19536+{
19537+ int err;
19538+ unsigned int len;
19539+ char a[32];
19540+
19541+ err = -ERANGE;
19542+ len = s->to - s->from;
19543+ if (len + 1 <= sizeof(a)) {
19544+ memcpy(a, s->from, len);
19545+ a[len] = '\0';
9dbd164d 19546+ err = kstrtoull(a, 0, result);
1facf9fc 19547+ }
19548+ return err;
19549+}
19550+
19551+static int au_wbr_mfs_wmark(substring_t *arg, char *str,
19552+ struct au_opt_wbr_create *create)
19553+{
19554+ int err;
19555+ unsigned long long ull;
19556+
19557+ err = 0;
19558+ if (!au_match_ull(arg, &ull))
19559+ create->mfsrr_watermark = ull;
19560+ else {
4a4d8108 19561+ pr_err("bad integer in %s\n", str);
1facf9fc 19562+ err = -EINVAL;
19563+ }
19564+
19565+ return err;
19566+}
19567+
19568+static int au_wbr_mfs_sec(substring_t *arg, char *str,
19569+ struct au_opt_wbr_create *create)
19570+{
19571+ int n, err;
19572+
19573+ err = 0;
027c5e7a 19574+ if (!match_int(arg, &n) && 0 <= n && n <= AUFS_MFS_MAX_SEC)
1facf9fc 19575+ create->mfs_second = n;
19576+ else {
4a4d8108 19577+ pr_err("bad integer in %s\n", str);
1facf9fc 19578+ err = -EINVAL;
19579+ }
19580+
19581+ return err;
19582+}
19583+
4a4d8108
AM
19584+static int noinline_for_stack
19585+au_wbr_create_val(char *str, struct au_opt_wbr_create *create)
1facf9fc 19586+{
19587+ int err, e;
19588+ substring_t args[MAX_OPT_ARGS];
19589+
19590+ err = match_token(str, au_wbr_create_policy, args);
19591+ create->wbr_create = err;
19592+ switch (err) {
19593+ case AuWbrCreate_MFSRRV:
19594+ e = au_wbr_mfs_wmark(&args[0], str, create);
19595+ if (!e)
19596+ e = au_wbr_mfs_sec(&args[1], str, create);
19597+ if (unlikely(e))
19598+ err = e;
19599+ break;
19600+ case AuWbrCreate_MFSRR:
19601+ e = au_wbr_mfs_wmark(&args[0], str, create);
19602+ if (unlikely(e)) {
19603+ err = e;
19604+ break;
19605+ }
19606+ /*FALLTHROUGH*/
19607+ case AuWbrCreate_MFS:
19608+ case AuWbrCreate_PMFS:
027c5e7a 19609+ create->mfs_second = AUFS_MFS_DEF_SEC;
1facf9fc 19610+ break;
19611+ case AuWbrCreate_MFSV:
19612+ case AuWbrCreate_PMFSV:
19613+ e = au_wbr_mfs_sec(&args[0], str, create);
19614+ if (unlikely(e))
19615+ err = e;
19616+ break;
19617+ }
19618+
19619+ return err;
19620+}
19621+
19622+const char *au_optstr_wbr_create(int wbr_create)
19623+{
19624+ return au_parser_pattern(wbr_create, (void *)au_wbr_create_policy);
19625+}
19626+
19627+static match_table_t au_wbr_copyup_policy = {
19628+ {AuWbrCopyup_TDP, "tdp"},
19629+ {AuWbrCopyup_TDP, "top-down-parent"},
19630+ {AuWbrCopyup_BUP, "bup"},
19631+ {AuWbrCopyup_BUP, "bottom-up-parent"},
19632+ {AuWbrCopyup_BU, "bu"},
19633+ {AuWbrCopyup_BU, "bottom-up"},
19634+ {-1, NULL}
19635+};
19636+
4a4d8108 19637+static int noinline_for_stack au_wbr_copyup_val(char *str)
1facf9fc 19638+{
19639+ substring_t args[MAX_OPT_ARGS];
19640+
19641+ return match_token(str, au_wbr_copyup_policy, args);
19642+}
19643+
19644+const char *au_optstr_wbr_copyup(int wbr_copyup)
19645+{
19646+ return au_parser_pattern(wbr_copyup, (void *)au_wbr_copyup_policy);
19647+}
19648+
19649+/* ---------------------------------------------------------------------- */
19650+
19651+static const int lkup_dirflags = LOOKUP_FOLLOW | LOOKUP_DIRECTORY;
19652+
19653+static void dump_opts(struct au_opts *opts)
19654+{
19655+#ifdef CONFIG_AUFS_DEBUG
19656+ /* reduce stack space */
19657+ union {
19658+ struct au_opt_add *add;
19659+ struct au_opt_del *del;
19660+ struct au_opt_mod *mod;
19661+ struct au_opt_xino *xino;
19662+ struct au_opt_xino_itrunc *xino_itrunc;
19663+ struct au_opt_wbr_create *create;
19664+ } u;
19665+ struct au_opt *opt;
19666+
19667+ opt = opts->opt;
19668+ while (opt->type != Opt_tail) {
19669+ switch (opt->type) {
19670+ case Opt_add:
19671+ u.add = &opt->add;
19672+ AuDbg("add {b%d, %s, 0x%x, %p}\n",
19673+ u.add->bindex, u.add->pathname, u.add->perm,
19674+ u.add->path.dentry);
19675+ break;
19676+ case Opt_del:
19677+ case Opt_idel:
19678+ u.del = &opt->del;
19679+ AuDbg("del {%s, %p}\n",
19680+ u.del->pathname, u.del->h_path.dentry);
19681+ break;
19682+ case Opt_mod:
19683+ case Opt_imod:
19684+ u.mod = &opt->mod;
19685+ AuDbg("mod {%s, 0x%x, %p}\n",
19686+ u.mod->path, u.mod->perm, u.mod->h_root);
19687+ break;
19688+ case Opt_append:
19689+ u.add = &opt->add;
19690+ AuDbg("append {b%d, %s, 0x%x, %p}\n",
19691+ u.add->bindex, u.add->pathname, u.add->perm,
19692+ u.add->path.dentry);
19693+ break;
19694+ case Opt_prepend:
19695+ u.add = &opt->add;
19696+ AuDbg("prepend {b%d, %s, 0x%x, %p}\n",
19697+ u.add->bindex, u.add->pathname, u.add->perm,
19698+ u.add->path.dentry);
19699+ break;
19700+ case Opt_dirwh:
19701+ AuDbg("dirwh %d\n", opt->dirwh);
19702+ break;
19703+ case Opt_rdcache:
19704+ AuDbg("rdcache %d\n", opt->rdcache);
19705+ break;
19706+ case Opt_rdblk:
19707+ AuDbg("rdblk %u\n", opt->rdblk);
19708+ break;
dece6358
AM
19709+ case Opt_rdblk_def:
19710+ AuDbg("rdblk_def\n");
19711+ break;
1facf9fc 19712+ case Opt_rdhash:
19713+ AuDbg("rdhash %u\n", opt->rdhash);
19714+ break;
dece6358
AM
19715+ case Opt_rdhash_def:
19716+ AuDbg("rdhash_def\n");
19717+ break;
1facf9fc 19718+ case Opt_xino:
19719+ u.xino = &opt->xino;
19720+ AuDbg("xino {%s %.*s}\n",
19721+ u.xino->path,
19722+ AuDLNPair(u.xino->file->f_dentry));
19723+ break;
19724+ case Opt_trunc_xino:
19725+ AuLabel(trunc_xino);
19726+ break;
19727+ case Opt_notrunc_xino:
19728+ AuLabel(notrunc_xino);
19729+ break;
19730+ case Opt_trunc_xino_path:
19731+ case Opt_itrunc_xino:
19732+ u.xino_itrunc = &opt->xino_itrunc;
19733+ AuDbg("trunc_xino %d\n", u.xino_itrunc->bindex);
19734+ break;
19735+
19736+ case Opt_noxino:
19737+ AuLabel(noxino);
19738+ break;
19739+ case Opt_trunc_xib:
19740+ AuLabel(trunc_xib);
19741+ break;
19742+ case Opt_notrunc_xib:
19743+ AuLabel(notrunc_xib);
19744+ break;
dece6358
AM
19745+ case Opt_shwh:
19746+ AuLabel(shwh);
19747+ break;
19748+ case Opt_noshwh:
19749+ AuLabel(noshwh);
19750+ break;
1facf9fc 19751+ case Opt_plink:
19752+ AuLabel(plink);
19753+ break;
19754+ case Opt_noplink:
19755+ AuLabel(noplink);
19756+ break;
19757+ case Opt_list_plink:
19758+ AuLabel(list_plink);
19759+ break;
19760+ case Opt_udba:
19761+ AuDbg("udba %d, %s\n",
19762+ opt->udba, au_optstr_udba(opt->udba));
19763+ break;
4a4d8108
AM
19764+ case Opt_dio:
19765+ AuLabel(dio);
19766+ break;
19767+ case Opt_nodio:
19768+ AuLabel(nodio);
19769+ break;
1facf9fc 19770+ case Opt_diropq_a:
19771+ AuLabel(diropq_a);
19772+ break;
19773+ case Opt_diropq_w:
19774+ AuLabel(diropq_w);
19775+ break;
19776+ case Opt_warn_perm:
19777+ AuLabel(warn_perm);
19778+ break;
19779+ case Opt_nowarn_perm:
19780+ AuLabel(nowarn_perm);
19781+ break;
19782+ case Opt_refrof:
19783+ AuLabel(refrof);
19784+ break;
19785+ case Opt_norefrof:
19786+ AuLabel(norefrof);
19787+ break;
19788+ case Opt_verbose:
19789+ AuLabel(verbose);
19790+ break;
19791+ case Opt_noverbose:
19792+ AuLabel(noverbose);
19793+ break;
19794+ case Opt_sum:
19795+ AuLabel(sum);
19796+ break;
19797+ case Opt_nosum:
19798+ AuLabel(nosum);
19799+ break;
19800+ case Opt_wsum:
19801+ AuLabel(wsum);
19802+ break;
19803+ case Opt_wbr_create:
19804+ u.create = &opt->wbr_create;
19805+ AuDbg("create %d, %s\n", u.create->wbr_create,
19806+ au_optstr_wbr_create(u.create->wbr_create));
19807+ switch (u.create->wbr_create) {
19808+ case AuWbrCreate_MFSV:
19809+ case AuWbrCreate_PMFSV:
19810+ AuDbg("%d sec\n", u.create->mfs_second);
19811+ break;
19812+ case AuWbrCreate_MFSRR:
19813+ AuDbg("%llu watermark\n",
19814+ u.create->mfsrr_watermark);
19815+ break;
19816+ case AuWbrCreate_MFSRRV:
19817+ AuDbg("%llu watermark, %d sec\n",
19818+ u.create->mfsrr_watermark,
19819+ u.create->mfs_second);
19820+ break;
19821+ }
19822+ break;
19823+ case Opt_wbr_copyup:
19824+ AuDbg("copyup %d, %s\n", opt->wbr_copyup,
19825+ au_optstr_wbr_copyup(opt->wbr_copyup));
19826+ break;
19827+ default:
19828+ BUG();
19829+ }
19830+ opt++;
19831+ }
19832+#endif
19833+}
19834+
19835+void au_opts_free(struct au_opts *opts)
19836+{
19837+ struct au_opt *opt;
19838+
19839+ opt = opts->opt;
19840+ while (opt->type != Opt_tail) {
19841+ switch (opt->type) {
19842+ case Opt_add:
19843+ case Opt_append:
19844+ case Opt_prepend:
19845+ path_put(&opt->add.path);
19846+ break;
19847+ case Opt_del:
19848+ case Opt_idel:
19849+ path_put(&opt->del.h_path);
19850+ break;
19851+ case Opt_mod:
19852+ case Opt_imod:
19853+ dput(opt->mod.h_root);
19854+ break;
19855+ case Opt_xino:
19856+ fput(opt->xino.file);
19857+ break;
19858+ }
19859+ opt++;
19860+ }
19861+}
19862+
19863+static int opt_add(struct au_opt *opt, char *opt_str, unsigned long sb_flags,
19864+ aufs_bindex_t bindex)
19865+{
19866+ int err;
19867+ struct au_opt_add *add = &opt->add;
19868+ char *p;
19869+
19870+ add->bindex = bindex;
1e00d052 19871+ add->perm = AuBrPerm_RO;
1facf9fc 19872+ add->pathname = opt_str;
19873+ p = strchr(opt_str, '=');
19874+ if (p) {
19875+ *p++ = 0;
19876+ if (*p)
19877+ add->perm = br_perm_val(p);
19878+ }
19879+
19880+ err = vfsub_kern_path(add->pathname, lkup_dirflags, &add->path);
19881+ if (!err) {
19882+ if (!p) {
19883+ add->perm = AuBrPerm_RO;
19884+ if (au_test_fs_rr(add->path.dentry->d_sb))
19885+ add->perm = AuBrPerm_RR;
19886+ else if (!bindex && !(sb_flags & MS_RDONLY))
19887+ add->perm = AuBrPerm_RW;
19888+ }
19889+ opt->type = Opt_add;
19890+ goto out;
19891+ }
4a4d8108 19892+ pr_err("lookup failed %s (%d)\n", add->pathname, err);
1facf9fc 19893+ err = -EINVAL;
19894+
4f0767ce 19895+out:
1facf9fc 19896+ return err;
19897+}
19898+
19899+static int au_opts_parse_del(struct au_opt_del *del, substring_t args[])
19900+{
19901+ int err;
19902+
19903+ del->pathname = args[0].from;
19904+ AuDbg("del path %s\n", del->pathname);
19905+
19906+ err = vfsub_kern_path(del->pathname, lkup_dirflags, &del->h_path);
19907+ if (unlikely(err))
4a4d8108 19908+ pr_err("lookup failed %s (%d)\n", del->pathname, err);
1facf9fc 19909+
19910+ return err;
19911+}
19912+
19913+#if 0 /* reserved for future use */
19914+static int au_opts_parse_idel(struct super_block *sb, aufs_bindex_t bindex,
19915+ struct au_opt_del *del, substring_t args[])
19916+{
19917+ int err;
19918+ struct dentry *root;
19919+
19920+ err = -EINVAL;
19921+ root = sb->s_root;
19922+ aufs_read_lock(root, AuLock_FLUSH);
19923+ if (bindex < 0 || au_sbend(sb) < bindex) {
4a4d8108 19924+ pr_err("out of bounds, %d\n", bindex);
1facf9fc 19925+ goto out;
19926+ }
19927+
19928+ err = 0;
19929+ del->h_path.dentry = dget(au_h_dptr(root, bindex));
19930+ del->h_path.mnt = mntget(au_sbr_mnt(sb, bindex));
19931+
4f0767ce 19932+out:
1facf9fc 19933+ aufs_read_unlock(root, !AuLock_IR);
19934+ return err;
19935+}
19936+#endif
19937+
4a4d8108
AM
19938+static int noinline_for_stack
19939+au_opts_parse_mod(struct au_opt_mod *mod, substring_t args[])
1facf9fc 19940+{
19941+ int err;
19942+ struct path path;
19943+ char *p;
19944+
19945+ err = -EINVAL;
19946+ mod->path = args[0].from;
19947+ p = strchr(mod->path, '=');
19948+ if (unlikely(!p)) {
4a4d8108 19949+ pr_err("no permssion %s\n", args[0].from);
1facf9fc 19950+ goto out;
19951+ }
19952+
19953+ *p++ = 0;
19954+ err = vfsub_kern_path(mod->path, lkup_dirflags, &path);
19955+ if (unlikely(err)) {
4a4d8108 19956+ pr_err("lookup failed %s (%d)\n", mod->path, err);
1facf9fc 19957+ goto out;
19958+ }
19959+
19960+ mod->perm = br_perm_val(p);
19961+ AuDbg("mod path %s, perm 0x%x, %s\n", mod->path, mod->perm, p);
19962+ mod->h_root = dget(path.dentry);
19963+ path_put(&path);
19964+
4f0767ce 19965+out:
1facf9fc 19966+ return err;
19967+}
19968+
19969+#if 0 /* reserved for future use */
19970+static int au_opts_parse_imod(struct super_block *sb, aufs_bindex_t bindex,
19971+ struct au_opt_mod *mod, substring_t args[])
19972+{
19973+ int err;
19974+ struct dentry *root;
19975+
19976+ err = -EINVAL;
19977+ root = sb->s_root;
19978+ aufs_read_lock(root, AuLock_FLUSH);
19979+ if (bindex < 0 || au_sbend(sb) < bindex) {
4a4d8108 19980+ pr_err("out of bounds, %d\n", bindex);
1facf9fc 19981+ goto out;
19982+ }
19983+
19984+ err = 0;
19985+ mod->perm = br_perm_val(args[1].from);
19986+ AuDbg("mod path %s, perm 0x%x, %s\n",
19987+ mod->path, mod->perm, args[1].from);
19988+ mod->h_root = dget(au_h_dptr(root, bindex));
19989+
4f0767ce 19990+out:
1facf9fc 19991+ aufs_read_unlock(root, !AuLock_IR);
19992+ return err;
19993+}
19994+#endif
19995+
19996+static int au_opts_parse_xino(struct super_block *sb, struct au_opt_xino *xino,
19997+ substring_t args[])
19998+{
19999+ int err;
20000+ struct file *file;
20001+
20002+ file = au_xino_create(sb, args[0].from, /*silent*/0);
20003+ err = PTR_ERR(file);
20004+ if (IS_ERR(file))
20005+ goto out;
20006+
20007+ err = -EINVAL;
20008+ if (unlikely(file->f_dentry->d_sb == sb)) {
20009+ fput(file);
4a4d8108 20010+ pr_err("%s must be outside\n", args[0].from);
1facf9fc 20011+ goto out;
20012+ }
20013+
20014+ err = 0;
20015+ xino->file = file;
20016+ xino->path = args[0].from;
20017+
4f0767ce 20018+out:
1facf9fc 20019+ return err;
20020+}
20021+
4a4d8108
AM
20022+static int noinline_for_stack
20023+au_opts_parse_xino_itrunc_path(struct super_block *sb,
20024+ struct au_opt_xino_itrunc *xino_itrunc,
20025+ substring_t args[])
1facf9fc 20026+{
20027+ int err;
20028+ aufs_bindex_t bend, bindex;
20029+ struct path path;
20030+ struct dentry *root;
20031+
20032+ err = vfsub_kern_path(args[0].from, lkup_dirflags, &path);
20033+ if (unlikely(err)) {
4a4d8108 20034+ pr_err("lookup failed %s (%d)\n", args[0].from, err);
1facf9fc 20035+ goto out;
20036+ }
20037+
20038+ xino_itrunc->bindex = -1;
20039+ root = sb->s_root;
20040+ aufs_read_lock(root, AuLock_FLUSH);
20041+ bend = au_sbend(sb);
20042+ for (bindex = 0; bindex <= bend; bindex++) {
20043+ if (au_h_dptr(root, bindex) == path.dentry) {
20044+ xino_itrunc->bindex = bindex;
20045+ break;
20046+ }
20047+ }
20048+ aufs_read_unlock(root, !AuLock_IR);
20049+ path_put(&path);
20050+
20051+ if (unlikely(xino_itrunc->bindex < 0)) {
4a4d8108 20052+ pr_err("no such branch %s\n", args[0].from);
1facf9fc 20053+ err = -EINVAL;
20054+ }
20055+
4f0767ce 20056+out:
1facf9fc 20057+ return err;
20058+}
20059+
20060+/* called without aufs lock */
20061+int au_opts_parse(struct super_block *sb, char *str, struct au_opts *opts)
20062+{
20063+ int err, n, token;
20064+ aufs_bindex_t bindex;
20065+ unsigned char skipped;
20066+ struct dentry *root;
20067+ struct au_opt *opt, *opt_tail;
20068+ char *opt_str;
20069+ /* reduce the stack space */
20070+ union {
20071+ struct au_opt_xino_itrunc *xino_itrunc;
20072+ struct au_opt_wbr_create *create;
20073+ } u;
20074+ struct {
20075+ substring_t args[MAX_OPT_ARGS];
20076+ } *a;
20077+
20078+ err = -ENOMEM;
20079+ a = kmalloc(sizeof(*a), GFP_NOFS);
20080+ if (unlikely(!a))
20081+ goto out;
20082+
20083+ root = sb->s_root;
20084+ err = 0;
20085+ bindex = 0;
20086+ opt = opts->opt;
20087+ opt_tail = opt + opts->max_opt - 1;
20088+ opt->type = Opt_tail;
20089+ while (!err && (opt_str = strsep(&str, ",")) && *opt_str) {
20090+ err = -EINVAL;
20091+ skipped = 0;
20092+ token = match_token(opt_str, options, a->args);
20093+ switch (token) {
20094+ case Opt_br:
20095+ err = 0;
20096+ while (!err && (opt_str = strsep(&a->args[0].from, ":"))
20097+ && *opt_str) {
20098+ err = opt_add(opt, opt_str, opts->sb_flags,
20099+ bindex++);
20100+ if (unlikely(!err && ++opt > opt_tail)) {
20101+ err = -E2BIG;
20102+ break;
20103+ }
20104+ opt->type = Opt_tail;
20105+ skipped = 1;
20106+ }
20107+ break;
20108+ case Opt_add:
20109+ if (unlikely(match_int(&a->args[0], &n))) {
4a4d8108 20110+ pr_err("bad integer in %s\n", opt_str);
1facf9fc 20111+ break;
20112+ }
20113+ bindex = n;
20114+ err = opt_add(opt, a->args[1].from, opts->sb_flags,
20115+ bindex);
20116+ if (!err)
20117+ opt->type = token;
20118+ break;
20119+ case Opt_append:
20120+ err = opt_add(opt, a->args[0].from, opts->sb_flags,
20121+ /*dummy bindex*/1);
20122+ if (!err)
20123+ opt->type = token;
20124+ break;
20125+ case Opt_prepend:
20126+ err = opt_add(opt, a->args[0].from, opts->sb_flags,
20127+ /*bindex*/0);
20128+ if (!err)
20129+ opt->type = token;
20130+ break;
20131+ case Opt_del:
20132+ err = au_opts_parse_del(&opt->del, a->args);
20133+ if (!err)
20134+ opt->type = token;
20135+ break;
20136+#if 0 /* reserved for future use */
20137+ case Opt_idel:
20138+ del->pathname = "(indexed)";
20139+ if (unlikely(match_int(&args[0], &n))) {
4a4d8108 20140+ pr_err("bad integer in %s\n", opt_str);
1facf9fc 20141+ break;
20142+ }
20143+ err = au_opts_parse_idel(sb, n, &opt->del, a->args);
20144+ if (!err)
20145+ opt->type = token;
20146+ break;
20147+#endif
20148+ case Opt_mod:
20149+ err = au_opts_parse_mod(&opt->mod, a->args);
20150+ if (!err)
20151+ opt->type = token;
20152+ break;
20153+#ifdef IMOD /* reserved for future use */
20154+ case Opt_imod:
20155+ u.mod->path = "(indexed)";
20156+ if (unlikely(match_int(&a->args[0], &n))) {
4a4d8108 20157+ pr_err("bad integer in %s\n", opt_str);
1facf9fc 20158+ break;
20159+ }
20160+ err = au_opts_parse_imod(sb, n, &opt->mod, a->args);
20161+ if (!err)
20162+ opt->type = token;
20163+ break;
20164+#endif
20165+ case Opt_xino:
20166+ err = au_opts_parse_xino(sb, &opt->xino, a->args);
20167+ if (!err)
20168+ opt->type = token;
20169+ break;
20170+
20171+ case Opt_trunc_xino_path:
20172+ err = au_opts_parse_xino_itrunc_path
20173+ (sb, &opt->xino_itrunc, a->args);
20174+ if (!err)
20175+ opt->type = token;
20176+ break;
20177+
20178+ case Opt_itrunc_xino:
20179+ u.xino_itrunc = &opt->xino_itrunc;
20180+ if (unlikely(match_int(&a->args[0], &n))) {
4a4d8108 20181+ pr_err("bad integer in %s\n", opt_str);
1facf9fc 20182+ break;
20183+ }
20184+ u.xino_itrunc->bindex = n;
20185+ aufs_read_lock(root, AuLock_FLUSH);
20186+ if (n < 0 || au_sbend(sb) < n) {
4a4d8108 20187+ pr_err("out of bounds, %d\n", n);
1facf9fc 20188+ aufs_read_unlock(root, !AuLock_IR);
20189+ break;
20190+ }
20191+ aufs_read_unlock(root, !AuLock_IR);
20192+ err = 0;
20193+ opt->type = token;
20194+ break;
20195+
20196+ case Opt_dirwh:
20197+ if (unlikely(match_int(&a->args[0], &opt->dirwh)))
20198+ break;
20199+ err = 0;
20200+ opt->type = token;
20201+ break;
20202+
20203+ case Opt_rdcache:
027c5e7a
AM
20204+ if (unlikely(match_int(&a->args[0], &n))) {
20205+ pr_err("bad integer in %s\n", opt_str);
1facf9fc 20206+ break;
027c5e7a
AM
20207+ }
20208+ if (unlikely(n > AUFS_RDCACHE_MAX)) {
20209+ pr_err("rdcache must be smaller than %d\n",
20210+ AUFS_RDCACHE_MAX);
20211+ break;
20212+ }
20213+ opt->rdcache = n;
1facf9fc 20214+ err = 0;
20215+ opt->type = token;
20216+ break;
20217+ case Opt_rdblk:
20218+ if (unlikely(match_int(&a->args[0], &n)
1308ab2a 20219+ || n < 0
1facf9fc 20220+ || n > KMALLOC_MAX_SIZE)) {
4a4d8108 20221+ pr_err("bad integer in %s\n", opt_str);
1facf9fc 20222+ break;
20223+ }
1308ab2a 20224+ if (unlikely(n && n < NAME_MAX)) {
4a4d8108
AM
20225+ pr_err("rdblk must be larger than %d\n",
20226+ NAME_MAX);
1facf9fc 20227+ break;
20228+ }
20229+ opt->rdblk = n;
20230+ err = 0;
20231+ opt->type = token;
20232+ break;
20233+ case Opt_rdhash:
20234+ if (unlikely(match_int(&a->args[0], &n)
1308ab2a 20235+ || n < 0
1facf9fc 20236+ || n * sizeof(struct hlist_head)
20237+ > KMALLOC_MAX_SIZE)) {
4a4d8108 20238+ pr_err("bad integer in %s\n", opt_str);
1facf9fc 20239+ break;
20240+ }
20241+ opt->rdhash = n;
20242+ err = 0;
20243+ opt->type = token;
20244+ break;
20245+
20246+ case Opt_trunc_xino:
20247+ case Opt_notrunc_xino:
20248+ case Opt_noxino:
20249+ case Opt_trunc_xib:
20250+ case Opt_notrunc_xib:
dece6358
AM
20251+ case Opt_shwh:
20252+ case Opt_noshwh:
1facf9fc 20253+ case Opt_plink:
20254+ case Opt_noplink:
20255+ case Opt_list_plink:
4a4d8108
AM
20256+ case Opt_dio:
20257+ case Opt_nodio:
1facf9fc 20258+ case Opt_diropq_a:
20259+ case Opt_diropq_w:
20260+ case Opt_warn_perm:
20261+ case Opt_nowarn_perm:
20262+ case Opt_refrof:
20263+ case Opt_norefrof:
20264+ case Opt_verbose:
20265+ case Opt_noverbose:
20266+ case Opt_sum:
20267+ case Opt_nosum:
20268+ case Opt_wsum:
dece6358
AM
20269+ case Opt_rdblk_def:
20270+ case Opt_rdhash_def:
1facf9fc 20271+ err = 0;
20272+ opt->type = token;
20273+ break;
20274+
20275+ case Opt_udba:
20276+ opt->udba = udba_val(a->args[0].from);
20277+ if (opt->udba >= 0) {
20278+ err = 0;
20279+ opt->type = token;
20280+ } else
4a4d8108 20281+ pr_err("wrong value, %s\n", opt_str);
1facf9fc 20282+ break;
20283+
20284+ case Opt_wbr_create:
20285+ u.create = &opt->wbr_create;
20286+ u.create->wbr_create
20287+ = au_wbr_create_val(a->args[0].from, u.create);
20288+ if (u.create->wbr_create >= 0) {
20289+ err = 0;
20290+ opt->type = token;
20291+ } else
4a4d8108 20292+ pr_err("wrong value, %s\n", opt_str);
1facf9fc 20293+ break;
20294+ case Opt_wbr_copyup:
20295+ opt->wbr_copyup = au_wbr_copyup_val(a->args[0].from);
20296+ if (opt->wbr_copyup >= 0) {
20297+ err = 0;
20298+ opt->type = token;
20299+ } else
4a4d8108 20300+ pr_err("wrong value, %s\n", opt_str);
1facf9fc 20301+ break;
20302+
20303+ case Opt_ignore:
0c3ec466 20304+ pr_warn("ignored %s\n", opt_str);
1facf9fc 20305+ /*FALLTHROUGH*/
20306+ case Opt_ignore_silent:
20307+ skipped = 1;
20308+ err = 0;
20309+ break;
20310+ case Opt_err:
4a4d8108 20311+ pr_err("unknown option %s\n", opt_str);
1facf9fc 20312+ break;
20313+ }
20314+
20315+ if (!err && !skipped) {
20316+ if (unlikely(++opt > opt_tail)) {
20317+ err = -E2BIG;
20318+ opt--;
20319+ opt->type = Opt_tail;
20320+ break;
20321+ }
20322+ opt->type = Opt_tail;
20323+ }
20324+ }
20325+
20326+ kfree(a);
20327+ dump_opts(opts);
20328+ if (unlikely(err))
20329+ au_opts_free(opts);
20330+
4f0767ce 20331+out:
1facf9fc 20332+ return err;
20333+}
20334+
20335+static int au_opt_wbr_create(struct super_block *sb,
20336+ struct au_opt_wbr_create *create)
20337+{
20338+ int err;
20339+ struct au_sbinfo *sbinfo;
20340+
dece6358
AM
20341+ SiMustWriteLock(sb);
20342+
1facf9fc 20343+ err = 1; /* handled */
20344+ sbinfo = au_sbi(sb);
20345+ if (sbinfo->si_wbr_create_ops->fin) {
20346+ err = sbinfo->si_wbr_create_ops->fin(sb);
20347+ if (!err)
20348+ err = 1;
20349+ }
20350+
20351+ sbinfo->si_wbr_create = create->wbr_create;
20352+ sbinfo->si_wbr_create_ops = au_wbr_create_ops + create->wbr_create;
20353+ switch (create->wbr_create) {
20354+ case AuWbrCreate_MFSRRV:
20355+ case AuWbrCreate_MFSRR:
20356+ sbinfo->si_wbr_mfs.mfsrr_watermark = create->mfsrr_watermark;
20357+ /*FALLTHROUGH*/
20358+ case AuWbrCreate_MFS:
20359+ case AuWbrCreate_MFSV:
20360+ case AuWbrCreate_PMFS:
20361+ case AuWbrCreate_PMFSV:
e49829fe
JR
20362+ sbinfo->si_wbr_mfs.mfs_expire
20363+ = msecs_to_jiffies(create->mfs_second * MSEC_PER_SEC);
1facf9fc 20364+ break;
20365+ }
20366+
20367+ if (sbinfo->si_wbr_create_ops->init)
20368+ sbinfo->si_wbr_create_ops->init(sb); /* ignore */
20369+
20370+ return err;
20371+}
20372+
20373+/*
20374+ * returns,
20375+ * plus: processed without an error
20376+ * zero: unprocessed
20377+ */
20378+static int au_opt_simple(struct super_block *sb, struct au_opt *opt,
20379+ struct au_opts *opts)
20380+{
20381+ int err;
20382+ struct au_sbinfo *sbinfo;
20383+
dece6358
AM
20384+ SiMustWriteLock(sb);
20385+
1facf9fc 20386+ err = 1; /* handled */
20387+ sbinfo = au_sbi(sb);
20388+ switch (opt->type) {
20389+ case Opt_udba:
20390+ sbinfo->si_mntflags &= ~AuOptMask_UDBA;
20391+ sbinfo->si_mntflags |= opt->udba;
20392+ opts->given_udba |= opt->udba;
20393+ break;
20394+
20395+ case Opt_plink:
20396+ au_opt_set(sbinfo->si_mntflags, PLINK);
20397+ break;
20398+ case Opt_noplink:
20399+ if (au_opt_test(sbinfo->si_mntflags, PLINK))
e49829fe 20400+ au_plink_put(sb, /*verbose*/1);
1facf9fc 20401+ au_opt_clr(sbinfo->si_mntflags, PLINK);
20402+ break;
20403+ case Opt_list_plink:
20404+ if (au_opt_test(sbinfo->si_mntflags, PLINK))
20405+ au_plink_list(sb);
20406+ break;
20407+
4a4d8108
AM
20408+ case Opt_dio:
20409+ au_opt_set(sbinfo->si_mntflags, DIO);
20410+ au_fset_opts(opts->flags, REFRESH_DYAOP);
20411+ break;
20412+ case Opt_nodio:
20413+ au_opt_clr(sbinfo->si_mntflags, DIO);
20414+ au_fset_opts(opts->flags, REFRESH_DYAOP);
20415+ break;
20416+
1facf9fc 20417+ case Opt_diropq_a:
20418+ au_opt_set(sbinfo->si_mntflags, ALWAYS_DIROPQ);
20419+ break;
20420+ case Opt_diropq_w:
20421+ au_opt_clr(sbinfo->si_mntflags, ALWAYS_DIROPQ);
20422+ break;
20423+
20424+ case Opt_warn_perm:
20425+ au_opt_set(sbinfo->si_mntflags, WARN_PERM);
20426+ break;
20427+ case Opt_nowarn_perm:
20428+ au_opt_clr(sbinfo->si_mntflags, WARN_PERM);
20429+ break;
20430+
20431+ case Opt_refrof:
20432+ au_opt_set(sbinfo->si_mntflags, REFROF);
20433+ break;
20434+ case Opt_norefrof:
20435+ au_opt_clr(sbinfo->si_mntflags, REFROF);
20436+ break;
20437+
20438+ case Opt_verbose:
20439+ au_opt_set(sbinfo->si_mntflags, VERBOSE);
20440+ break;
20441+ case Opt_noverbose:
20442+ au_opt_clr(sbinfo->si_mntflags, VERBOSE);
20443+ break;
20444+
20445+ case Opt_sum:
20446+ au_opt_set(sbinfo->si_mntflags, SUM);
20447+ break;
20448+ case Opt_wsum:
20449+ au_opt_clr(sbinfo->si_mntflags, SUM);
20450+ au_opt_set(sbinfo->si_mntflags, SUM_W);
20451+ case Opt_nosum:
20452+ au_opt_clr(sbinfo->si_mntflags, SUM);
20453+ au_opt_clr(sbinfo->si_mntflags, SUM_W);
20454+ break;
20455+
20456+ case Opt_wbr_create:
20457+ err = au_opt_wbr_create(sb, &opt->wbr_create);
20458+ break;
20459+ case Opt_wbr_copyup:
20460+ sbinfo->si_wbr_copyup = opt->wbr_copyup;
20461+ sbinfo->si_wbr_copyup_ops = au_wbr_copyup_ops + opt->wbr_copyup;
20462+ break;
20463+
20464+ case Opt_dirwh:
20465+ sbinfo->si_dirwh = opt->dirwh;
20466+ break;
20467+
20468+ case Opt_rdcache:
e49829fe
JR
20469+ sbinfo->si_rdcache
20470+ = msecs_to_jiffies(opt->rdcache * MSEC_PER_SEC);
1facf9fc 20471+ break;
20472+ case Opt_rdblk:
20473+ sbinfo->si_rdblk = opt->rdblk;
20474+ break;
dece6358
AM
20475+ case Opt_rdblk_def:
20476+ sbinfo->si_rdblk = AUFS_RDBLK_DEF;
20477+ break;
1facf9fc 20478+ case Opt_rdhash:
20479+ sbinfo->si_rdhash = opt->rdhash;
20480+ break;
dece6358
AM
20481+ case Opt_rdhash_def:
20482+ sbinfo->si_rdhash = AUFS_RDHASH_DEF;
20483+ break;
20484+
20485+ case Opt_shwh:
20486+ au_opt_set(sbinfo->si_mntflags, SHWH);
20487+ break;
20488+ case Opt_noshwh:
20489+ au_opt_clr(sbinfo->si_mntflags, SHWH);
20490+ break;
1facf9fc 20491+
20492+ case Opt_trunc_xino:
20493+ au_opt_set(sbinfo->si_mntflags, TRUNC_XINO);
20494+ break;
20495+ case Opt_notrunc_xino:
20496+ au_opt_clr(sbinfo->si_mntflags, TRUNC_XINO);
20497+ break;
20498+
20499+ case Opt_trunc_xino_path:
20500+ case Opt_itrunc_xino:
20501+ err = au_xino_trunc(sb, opt->xino_itrunc.bindex);
20502+ if (!err)
20503+ err = 1;
20504+ break;
20505+
20506+ case Opt_trunc_xib:
20507+ au_fset_opts(opts->flags, TRUNC_XIB);
20508+ break;
20509+ case Opt_notrunc_xib:
20510+ au_fclr_opts(opts->flags, TRUNC_XIB);
20511+ break;
20512+
20513+ default:
20514+ err = 0;
20515+ break;
20516+ }
20517+
20518+ return err;
20519+}
20520+
20521+/*
20522+ * returns tri-state.
20523+ * plus: processed without an error
20524+ * zero: unprocessed
20525+ * minus: error
20526+ */
20527+static int au_opt_br(struct super_block *sb, struct au_opt *opt,
20528+ struct au_opts *opts)
20529+{
20530+ int err, do_refresh;
20531+
20532+ err = 0;
20533+ switch (opt->type) {
20534+ case Opt_append:
20535+ opt->add.bindex = au_sbend(sb) + 1;
20536+ if (opt->add.bindex < 0)
20537+ opt->add.bindex = 0;
20538+ goto add;
20539+ case Opt_prepend:
20540+ opt->add.bindex = 0;
20541+ add:
20542+ case Opt_add:
20543+ err = au_br_add(sb, &opt->add,
20544+ au_ftest_opts(opts->flags, REMOUNT));
20545+ if (!err) {
20546+ err = 1;
027c5e7a 20547+ au_fset_opts(opts->flags, REFRESH);
1facf9fc 20548+ }
20549+ break;
20550+
20551+ case Opt_del:
20552+ case Opt_idel:
20553+ err = au_br_del(sb, &opt->del,
20554+ au_ftest_opts(opts->flags, REMOUNT));
20555+ if (!err) {
20556+ err = 1;
20557+ au_fset_opts(opts->flags, TRUNC_XIB);
027c5e7a 20558+ au_fset_opts(opts->flags, REFRESH);
1facf9fc 20559+ }
20560+ break;
20561+
20562+ case Opt_mod:
20563+ case Opt_imod:
20564+ err = au_br_mod(sb, &opt->mod,
20565+ au_ftest_opts(opts->flags, REMOUNT),
20566+ &do_refresh);
20567+ if (!err) {
20568+ err = 1;
027c5e7a
AM
20569+ if (do_refresh)
20570+ au_fset_opts(opts->flags, REFRESH);
1facf9fc 20571+ }
20572+ break;
20573+ }
20574+
20575+ return err;
20576+}
20577+
20578+static int au_opt_xino(struct super_block *sb, struct au_opt *opt,
20579+ struct au_opt_xino **opt_xino,
20580+ struct au_opts *opts)
20581+{
20582+ int err;
20583+ aufs_bindex_t bend, bindex;
20584+ struct dentry *root, *parent, *h_root;
20585+
20586+ err = 0;
20587+ switch (opt->type) {
20588+ case Opt_xino:
20589+ err = au_xino_set(sb, &opt->xino,
20590+ !!au_ftest_opts(opts->flags, REMOUNT));
20591+ if (unlikely(err))
20592+ break;
20593+
20594+ *opt_xino = &opt->xino;
20595+ au_xino_brid_set(sb, -1);
20596+
20597+ /* safe d_parent access */
20598+ parent = opt->xino.file->f_dentry->d_parent;
20599+ root = sb->s_root;
20600+ bend = au_sbend(sb);
20601+ for (bindex = 0; bindex <= bend; bindex++) {
20602+ h_root = au_h_dptr(root, bindex);
20603+ if (h_root == parent) {
20604+ au_xino_brid_set(sb, au_sbr_id(sb, bindex));
20605+ break;
20606+ }
20607+ }
20608+ break;
20609+
20610+ case Opt_noxino:
20611+ au_xino_clr(sb);
20612+ au_xino_brid_set(sb, -1);
20613+ *opt_xino = (void *)-1;
20614+ break;
20615+ }
20616+
20617+ return err;
20618+}
20619+
20620+int au_opts_verify(struct super_block *sb, unsigned long sb_flags,
20621+ unsigned int pending)
20622+{
20623+ int err;
20624+ aufs_bindex_t bindex, bend;
20625+ unsigned char do_plink, skip, do_free;
20626+ struct au_branch *br;
20627+ struct au_wbr *wbr;
20628+ struct dentry *root;
20629+ struct inode *dir, *h_dir;
20630+ struct au_sbinfo *sbinfo;
20631+ struct au_hinode *hdir;
20632+
dece6358
AM
20633+ SiMustAnyLock(sb);
20634+
1facf9fc 20635+ sbinfo = au_sbi(sb);
20636+ AuDebugOn(!(sbinfo->si_mntflags & AuOptMask_UDBA));
20637+
dece6358
AM
20638+ if (!(sb_flags & MS_RDONLY)) {
20639+ if (unlikely(!au_br_writable(au_sbr_perm(sb, 0))))
0c3ec466 20640+ pr_warn("first branch should be rw\n");
dece6358 20641+ if (unlikely(au_opt_test(sbinfo->si_mntflags, SHWH)))
0c3ec466 20642+ pr_warn("shwh should be used with ro\n");
dece6358 20643+ }
1facf9fc 20644+
4a4d8108 20645+ if (au_opt_test((sbinfo->si_mntflags | pending), UDBA_HNOTIFY)
1facf9fc 20646+ && !au_opt_test(sbinfo->si_mntflags, XINO))
0c3ec466 20647+ pr_warn("udba=*notify requires xino\n");
1facf9fc 20648+
20649+ err = 0;
20650+ root = sb->s_root;
4a4d8108 20651+ dir = root->d_inode;
1facf9fc 20652+ do_plink = !!au_opt_test(sbinfo->si_mntflags, PLINK);
20653+ bend = au_sbend(sb);
20654+ for (bindex = 0; !err && bindex <= bend; bindex++) {
20655+ skip = 0;
20656+ h_dir = au_h_iptr(dir, bindex);
20657+ br = au_sbr(sb, bindex);
20658+ do_free = 0;
20659+
20660+ wbr = br->br_wbr;
20661+ if (wbr)
20662+ wbr_wh_read_lock(wbr);
20663+
1e00d052 20664+ if (!au_br_writable(br->br_perm)) {
1facf9fc 20665+ do_free = !!wbr;
20666+ skip = (!wbr
20667+ || (!wbr->wbr_whbase
20668+ && !wbr->wbr_plink
20669+ && !wbr->wbr_orph));
1e00d052 20670+ } else if (!au_br_wh_linkable(br->br_perm)) {
1facf9fc 20671+ /* skip = (!br->br_whbase && !br->br_orph); */
20672+ skip = (!wbr || !wbr->wbr_whbase);
20673+ if (skip && wbr) {
20674+ if (do_plink)
20675+ skip = !!wbr->wbr_plink;
20676+ else
20677+ skip = !wbr->wbr_plink;
20678+ }
1e00d052 20679+ } else {
1facf9fc 20680+ /* skip = (br->br_whbase && br->br_ohph); */
20681+ skip = (wbr && wbr->wbr_whbase);
20682+ if (skip) {
20683+ if (do_plink)
20684+ skip = !!wbr->wbr_plink;
20685+ else
20686+ skip = !wbr->wbr_plink;
20687+ }
1facf9fc 20688+ }
20689+ if (wbr)
20690+ wbr_wh_read_unlock(wbr);
20691+
20692+ if (skip)
20693+ continue;
20694+
20695+ hdir = au_hi(dir, bindex);
4a4d8108 20696+ au_hn_imtx_lock_nested(hdir, AuLsc_I_PARENT);
1facf9fc 20697+ if (wbr)
20698+ wbr_wh_write_lock(wbr);
20699+ err = au_wh_init(au_h_dptr(root, bindex), br, sb);
20700+ if (wbr)
20701+ wbr_wh_write_unlock(wbr);
4a4d8108 20702+ au_hn_imtx_unlock(hdir);
1facf9fc 20703+
20704+ if (!err && do_free) {
20705+ kfree(wbr);
20706+ br->br_wbr = NULL;
20707+ }
20708+ }
20709+
20710+ return err;
20711+}
20712+
20713+int au_opts_mount(struct super_block *sb, struct au_opts *opts)
20714+{
20715+ int err;
20716+ unsigned int tmp;
027c5e7a 20717+ aufs_bindex_t bindex, bend;
1facf9fc 20718+ struct au_opt *opt;
20719+ struct au_opt_xino *opt_xino, xino;
20720+ struct au_sbinfo *sbinfo;
027c5e7a 20721+ struct au_branch *br;
1facf9fc 20722+
dece6358
AM
20723+ SiMustWriteLock(sb);
20724+
1facf9fc 20725+ err = 0;
20726+ opt_xino = NULL;
20727+ opt = opts->opt;
20728+ while (err >= 0 && opt->type != Opt_tail)
20729+ err = au_opt_simple(sb, opt++, opts);
20730+ if (err > 0)
20731+ err = 0;
20732+ else if (unlikely(err < 0))
20733+ goto out;
20734+
20735+ /* disable xino and udba temporary */
20736+ sbinfo = au_sbi(sb);
20737+ tmp = sbinfo->si_mntflags;
20738+ au_opt_clr(sbinfo->si_mntflags, XINO);
20739+ au_opt_set_udba(sbinfo->si_mntflags, UDBA_REVAL);
20740+
20741+ opt = opts->opt;
20742+ while (err >= 0 && opt->type != Opt_tail)
20743+ err = au_opt_br(sb, opt++, opts);
20744+ if (err > 0)
20745+ err = 0;
20746+ else if (unlikely(err < 0))
20747+ goto out;
20748+
20749+ bend = au_sbend(sb);
20750+ if (unlikely(bend < 0)) {
20751+ err = -EINVAL;
4a4d8108 20752+ pr_err("no branches\n");
1facf9fc 20753+ goto out;
20754+ }
20755+
20756+ if (au_opt_test(tmp, XINO))
20757+ au_opt_set(sbinfo->si_mntflags, XINO);
20758+ opt = opts->opt;
20759+ while (!err && opt->type != Opt_tail)
20760+ err = au_opt_xino(sb, opt++, &opt_xino, opts);
20761+ if (unlikely(err))
20762+ goto out;
20763+
20764+ err = au_opts_verify(sb, sb->s_flags, tmp);
20765+ if (unlikely(err))
20766+ goto out;
20767+
20768+ /* restore xino */
20769+ if (au_opt_test(tmp, XINO) && !opt_xino) {
20770+ xino.file = au_xino_def(sb);
20771+ err = PTR_ERR(xino.file);
20772+ if (IS_ERR(xino.file))
20773+ goto out;
20774+
20775+ err = au_xino_set(sb, &xino, /*remount*/0);
20776+ fput(xino.file);
20777+ if (unlikely(err))
20778+ goto out;
20779+ }
20780+
20781+ /* restore udba */
027c5e7a 20782+ tmp &= AuOptMask_UDBA;
1facf9fc 20783+ sbinfo->si_mntflags &= ~AuOptMask_UDBA;
027c5e7a
AM
20784+ sbinfo->si_mntflags |= tmp;
20785+ bend = au_sbend(sb);
20786+ for (bindex = 0; bindex <= bend; bindex++) {
20787+ br = au_sbr(sb, bindex);
20788+ err = au_hnotify_reset_br(tmp, br, br->br_perm);
20789+ if (unlikely(err))
20790+ AuIOErr("hnotify failed on br %d, %d, ignored\n",
20791+ bindex, err);
20792+ /* go on even if err */
20793+ }
4a4d8108 20794+ if (au_opt_test(tmp, UDBA_HNOTIFY)) {
1facf9fc 20795+ struct inode *dir = sb->s_root->d_inode;
4a4d8108 20796+ au_hn_reset(dir, au_hi_flags(dir, /*isdir*/1) & ~AuHi_XINO);
1facf9fc 20797+ }
20798+
4f0767ce 20799+out:
1facf9fc 20800+ return err;
20801+}
20802+
20803+int au_opts_remount(struct super_block *sb, struct au_opts *opts)
20804+{
20805+ int err, rerr;
20806+ struct inode *dir;
20807+ struct au_opt_xino *opt_xino;
20808+ struct au_opt *opt;
20809+ struct au_sbinfo *sbinfo;
20810+
dece6358
AM
20811+ SiMustWriteLock(sb);
20812+
1facf9fc 20813+ dir = sb->s_root->d_inode;
20814+ sbinfo = au_sbi(sb);
20815+ err = 0;
20816+ opt_xino = NULL;
20817+ opt = opts->opt;
20818+ while (err >= 0 && opt->type != Opt_tail) {
20819+ err = au_opt_simple(sb, opt, opts);
20820+ if (!err)
20821+ err = au_opt_br(sb, opt, opts);
20822+ if (!err)
20823+ err = au_opt_xino(sb, opt, &opt_xino, opts);
20824+ opt++;
20825+ }
20826+ if (err > 0)
20827+ err = 0;
20828+ AuTraceErr(err);
20829+ /* go on even err */
20830+
20831+ rerr = au_opts_verify(sb, opts->sb_flags, /*pending*/0);
20832+ if (unlikely(rerr && !err))
20833+ err = rerr;
20834+
20835+ if (au_ftest_opts(opts->flags, TRUNC_XIB)) {
20836+ rerr = au_xib_trunc(sb);
20837+ if (unlikely(rerr && !err))
20838+ err = rerr;
20839+ }
20840+
20841+ /* will be handled by the caller */
027c5e7a 20842+ if (!au_ftest_opts(opts->flags, REFRESH)
1facf9fc 20843+ && (opts->given_udba || au_opt_test(sbinfo->si_mntflags, XINO)))
027c5e7a 20844+ au_fset_opts(opts->flags, REFRESH);
1facf9fc 20845+
20846+ AuDbg("status 0x%x\n", opts->flags);
20847+ return err;
20848+}
20849+
20850+/* ---------------------------------------------------------------------- */
20851+
20852+unsigned int au_opt_udba(struct super_block *sb)
20853+{
20854+ return au_mntflags(sb) & AuOptMask_UDBA;
20855+}
7f207e10
AM
20856diff -urN /usr/share/empty/fs/aufs/opts.h linux/fs/aufs/opts.h
20857--- /usr/share/empty/fs/aufs/opts.h 1970-01-01 01:00:00.000000000 +0100
537831f9 20858+++ linux/fs/aufs/opts.h 2012-12-13 20:41:10.431460173 +0100
f6c5ef8b 20859@@ -0,0 +1,209 @@
1facf9fc 20860+/*
f6c5ef8b 20861+ * Copyright (C) 2005-2012 Junjiro R. Okajima
1facf9fc 20862+ *
20863+ * This program, aufs is free software; you can redistribute it and/or modify
20864+ * it under the terms of the GNU General Public License as published by
20865+ * the Free Software Foundation; either version 2 of the License, or
20866+ * (at your option) any later version.
dece6358
AM
20867+ *
20868+ * This program is distributed in the hope that it will be useful,
20869+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
20870+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20871+ * GNU General Public License for more details.
20872+ *
20873+ * You should have received a copy of the GNU General Public License
20874+ * along with this program; if not, write to the Free Software
20875+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 20876+ */
20877+
20878+/*
20879+ * mount options/flags
20880+ */
20881+
20882+#ifndef __AUFS_OPTS_H__
20883+#define __AUFS_OPTS_H__
20884+
20885+#ifdef __KERNEL__
20886+
dece6358 20887+#include <linux/path.h>
1facf9fc 20888+
dece6358
AM
20889+struct file;
20890+struct super_block;
20891+
1facf9fc 20892+/* ---------------------------------------------------------------------- */
20893+
20894+/* mount flags */
20895+#define AuOpt_XINO 1 /* external inode number bitmap
20896+ and translation table */
20897+#define AuOpt_TRUNC_XINO (1 << 1) /* truncate xino files */
20898+#define AuOpt_UDBA_NONE (1 << 2) /* users direct branch access */
20899+#define AuOpt_UDBA_REVAL (1 << 3)
4a4d8108 20900+#define AuOpt_UDBA_HNOTIFY (1 << 4)
dece6358
AM
20901+#define AuOpt_SHWH (1 << 5) /* show whiteout */
20902+#define AuOpt_PLINK (1 << 6) /* pseudo-link */
20903+#define AuOpt_DIRPERM1 (1 << 7) /* unimplemented */
20904+#define AuOpt_REFROF (1 << 8) /* unimplemented */
20905+#define AuOpt_ALWAYS_DIROPQ (1 << 9) /* policy to creating diropq */
20906+#define AuOpt_SUM (1 << 10) /* summation for statfs(2) */
20907+#define AuOpt_SUM_W (1 << 11) /* unimplemented */
20908+#define AuOpt_WARN_PERM (1 << 12) /* warn when add-branch */
20909+#define AuOpt_VERBOSE (1 << 13) /* busy inode when del-branch */
4a4d8108 20910+#define AuOpt_DIO (1 << 14) /* direct io */
1facf9fc 20911+
4a4d8108
AM
20912+#ifndef CONFIG_AUFS_HNOTIFY
20913+#undef AuOpt_UDBA_HNOTIFY
20914+#define AuOpt_UDBA_HNOTIFY 0
1facf9fc 20915+#endif
dece6358
AM
20916+#ifndef CONFIG_AUFS_SHWH
20917+#undef AuOpt_SHWH
20918+#define AuOpt_SHWH 0
20919+#endif
1facf9fc 20920+
20921+#define AuOpt_Def (AuOpt_XINO \
20922+ | AuOpt_UDBA_REVAL \
20923+ | AuOpt_PLINK \
20924+ /* | AuOpt_DIRPERM1 */ \
20925+ | AuOpt_WARN_PERM)
20926+#define AuOptMask_UDBA (AuOpt_UDBA_NONE \
20927+ | AuOpt_UDBA_REVAL \
4a4d8108 20928+ | AuOpt_UDBA_HNOTIFY)
1facf9fc 20929+
20930+#define au_opt_test(flags, name) (flags & AuOpt_##name)
20931+#define au_opt_set(flags, name) do { \
20932+ BUILD_BUG_ON(AuOpt_##name & AuOptMask_UDBA); \
20933+ ((flags) |= AuOpt_##name); \
20934+} while (0)
20935+#define au_opt_set_udba(flags, name) do { \
20936+ (flags) &= ~AuOptMask_UDBA; \
20937+ ((flags) |= AuOpt_##name); \
20938+} while (0)
7f207e10
AM
20939+#define au_opt_clr(flags, name) do { \
20940+ ((flags) &= ~AuOpt_##name); \
20941+} while (0)
1facf9fc 20942+
e49829fe
JR
20943+static inline unsigned int au_opts_plink(unsigned int mntflags)
20944+{
20945+#ifdef CONFIG_PROC_FS
20946+ return mntflags;
20947+#else
20948+ return mntflags & ~AuOpt_PLINK;
20949+#endif
20950+}
20951+
1facf9fc 20952+/* ---------------------------------------------------------------------- */
20953+
20954+/* policies to select one among multiple writable branches */
20955+enum {
20956+ AuWbrCreate_TDP, /* top down parent */
20957+ AuWbrCreate_RR, /* round robin */
20958+ AuWbrCreate_MFS, /* most free space */
20959+ AuWbrCreate_MFSV, /* mfs with seconds */
20960+ AuWbrCreate_MFSRR, /* mfs then rr */
20961+ AuWbrCreate_MFSRRV, /* mfs then rr with seconds */
20962+ AuWbrCreate_PMFS, /* parent and mfs */
20963+ AuWbrCreate_PMFSV, /* parent and mfs with seconds */
20964+
20965+ AuWbrCreate_Def = AuWbrCreate_TDP
20966+};
20967+
20968+enum {
20969+ AuWbrCopyup_TDP, /* top down parent */
20970+ AuWbrCopyup_BUP, /* bottom up parent */
20971+ AuWbrCopyup_BU, /* bottom up */
20972+
20973+ AuWbrCopyup_Def = AuWbrCopyup_TDP
20974+};
20975+
20976+/* ---------------------------------------------------------------------- */
20977+
20978+struct au_opt_add {
20979+ aufs_bindex_t bindex;
20980+ char *pathname;
20981+ int perm;
20982+ struct path path;
20983+};
20984+
20985+struct au_opt_del {
20986+ char *pathname;
20987+ struct path h_path;
20988+};
20989+
20990+struct au_opt_mod {
20991+ char *path;
20992+ int perm;
20993+ struct dentry *h_root;
20994+};
20995+
20996+struct au_opt_xino {
20997+ char *path;
20998+ struct file *file;
20999+};
21000+
21001+struct au_opt_xino_itrunc {
21002+ aufs_bindex_t bindex;
21003+};
21004+
21005+struct au_opt_wbr_create {
21006+ int wbr_create;
21007+ int mfs_second;
21008+ unsigned long long mfsrr_watermark;
21009+};
21010+
21011+struct au_opt {
21012+ int type;
21013+ union {
21014+ struct au_opt_xino xino;
21015+ struct au_opt_xino_itrunc xino_itrunc;
21016+ struct au_opt_add add;
21017+ struct au_opt_del del;
21018+ struct au_opt_mod mod;
21019+ int dirwh;
21020+ int rdcache;
21021+ unsigned int rdblk;
21022+ unsigned int rdhash;
21023+ int udba;
21024+ struct au_opt_wbr_create wbr_create;
21025+ int wbr_copyup;
21026+ };
21027+};
21028+
21029+/* opts flags */
21030+#define AuOpts_REMOUNT 1
027c5e7a
AM
21031+#define AuOpts_REFRESH (1 << 1)
21032+#define AuOpts_TRUNC_XIB (1 << 2)
21033+#define AuOpts_REFRESH_DYAOP (1 << 3)
1facf9fc 21034+#define au_ftest_opts(flags, name) ((flags) & AuOpts_##name)
7f207e10
AM
21035+#define au_fset_opts(flags, name) \
21036+ do { (flags) |= AuOpts_##name; } while (0)
21037+#define au_fclr_opts(flags, name) \
21038+ do { (flags) &= ~AuOpts_##name; } while (0)
1facf9fc 21039+
21040+struct au_opts {
21041+ struct au_opt *opt;
21042+ int max_opt;
21043+
21044+ unsigned int given_udba;
21045+ unsigned int flags;
21046+ unsigned long sb_flags;
21047+};
21048+
21049+/* ---------------------------------------------------------------------- */
21050+
1e00d052 21051+char *au_optstr_br_perm(int brperm);
1facf9fc 21052+const char *au_optstr_udba(int udba);
21053+const char *au_optstr_wbr_copyup(int wbr_copyup);
21054+const char *au_optstr_wbr_create(int wbr_create);
21055+
21056+void au_opts_free(struct au_opts *opts);
21057+int au_opts_parse(struct super_block *sb, char *str, struct au_opts *opts);
21058+int au_opts_verify(struct super_block *sb, unsigned long sb_flags,
21059+ unsigned int pending);
21060+int au_opts_mount(struct super_block *sb, struct au_opts *opts);
21061+int au_opts_remount(struct super_block *sb, struct au_opts *opts);
21062+
21063+unsigned int au_opt_udba(struct super_block *sb);
21064+
21065+/* ---------------------------------------------------------------------- */
21066+
21067+#endif /* __KERNEL__ */
21068+#endif /* __AUFS_OPTS_H__ */
7f207e10
AM
21069diff -urN /usr/share/empty/fs/aufs/plink.c linux/fs/aufs/plink.c
21070--- /usr/share/empty/fs/aufs/plink.c 1970-01-01 01:00:00.000000000 +0100
537831f9 21071+++ linux/fs/aufs/plink.c 2012-12-13 20:41:10.431460173 +0100
0c3ec466 21072@@ -0,0 +1,511 @@
1facf9fc 21073+/*
f6c5ef8b 21074+ * Copyright (C) 2005-2012 Junjiro R. Okajima
1facf9fc 21075+ *
21076+ * This program, aufs is free software; you can redistribute it and/or modify
21077+ * it under the terms of the GNU General Public License as published by
21078+ * the Free Software Foundation; either version 2 of the License, or
21079+ * (at your option) any later version.
dece6358
AM
21080+ *
21081+ * This program is distributed in the hope that it will be useful,
21082+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
21083+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21084+ * GNU General Public License for more details.
21085+ *
21086+ * You should have received a copy of the GNU General Public License
21087+ * along with this program; if not, write to the Free Software
21088+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 21089+ */
21090+
21091+/*
21092+ * pseudo-link
21093+ */
21094+
21095+#include "aufs.h"
21096+
21097+/*
e49829fe 21098+ * the pseudo-link maintenance mode.
1facf9fc 21099+ * during a user process maintains the pseudo-links,
21100+ * prohibit adding a new plink and branch manipulation.
e49829fe
JR
21101+ *
21102+ * Flags
21103+ * NOPLM:
21104+ * For entry functions which will handle plink, and i_mutex is already held
21105+ * in VFS.
21106+ * They cannot wait and should return an error at once.
21107+ * Callers has to check the error.
21108+ * NOPLMW:
21109+ * For entry functions which will handle plink, but i_mutex is not held
21110+ * in VFS.
21111+ * They can wait the plink maintenance mode to finish.
21112+ *
21113+ * They behave like F_SETLK and F_SETLKW.
21114+ * If the caller never handle plink, then both flags are unnecessary.
1facf9fc 21115+ */
e49829fe
JR
21116+
21117+int au_plink_maint(struct super_block *sb, int flags)
1facf9fc 21118+{
e49829fe
JR
21119+ int err;
21120+ pid_t pid, ppid;
21121+ struct au_sbinfo *sbi;
dece6358
AM
21122+
21123+ SiMustAnyLock(sb);
21124+
e49829fe
JR
21125+ err = 0;
21126+ if (!au_opt_test(au_mntflags(sb), PLINK))
21127+ goto out;
21128+
21129+ sbi = au_sbi(sb);
21130+ pid = sbi->si_plink_maint_pid;
21131+ if (!pid || pid == current->pid)
21132+ goto out;
21133+
21134+ /* todo: it highly depends upon /sbin/mount.aufs */
21135+ rcu_read_lock();
21136+ ppid = task_pid_vnr(rcu_dereference(current->real_parent));
21137+ rcu_read_unlock();
21138+ if (pid == ppid)
21139+ goto out;
21140+
21141+ if (au_ftest_lock(flags, NOPLMW)) {
027c5e7a
AM
21142+ /* if there is no i_mutex lock in VFS, we don't need to wait */
21143+ /* AuDebugOn(!lockdep_depth(current)); */
e49829fe
JR
21144+ while (sbi->si_plink_maint_pid) {
21145+ si_read_unlock(sb);
21146+ /* gave up wake_up_bit() */
21147+ wait_event(sbi->si_plink_wq, !sbi->si_plink_maint_pid);
21148+
21149+ if (au_ftest_lock(flags, FLUSH))
21150+ au_nwt_flush(&sbi->si_nowait);
21151+ si_noflush_read_lock(sb);
21152+ }
21153+ } else if (au_ftest_lock(flags, NOPLM)) {
21154+ AuDbg("ppid %d, pid %d\n", ppid, pid);
21155+ err = -EAGAIN;
21156+ }
21157+
21158+out:
21159+ return err;
4a4d8108
AM
21160+}
21161+
e49829fe 21162+void au_plink_maint_leave(struct au_sbinfo *sbinfo)
4a4d8108 21163+{
4a4d8108 21164+ spin_lock(&sbinfo->si_plink_maint_lock);
027c5e7a 21165+ sbinfo->si_plink_maint_pid = 0;
4a4d8108 21166+ spin_unlock(&sbinfo->si_plink_maint_lock);
027c5e7a 21167+ wake_up_all(&sbinfo->si_plink_wq);
4a4d8108
AM
21168+}
21169+
e49829fe 21170+int au_plink_maint_enter(struct super_block *sb)
4a4d8108
AM
21171+{
21172+ int err;
4a4d8108
AM
21173+ struct au_sbinfo *sbinfo;
21174+
21175+ err = 0;
4a4d8108
AM
21176+ sbinfo = au_sbi(sb);
21177+ /* make sure i am the only one in this fs */
e49829fe
JR
21178+ si_write_lock(sb, AuLock_FLUSH);
21179+ if (au_opt_test(au_mntflags(sb), PLINK)) {
21180+ spin_lock(&sbinfo->si_plink_maint_lock);
21181+ if (!sbinfo->si_plink_maint_pid)
21182+ sbinfo->si_plink_maint_pid = current->pid;
21183+ else
21184+ err = -EBUSY;
21185+ spin_unlock(&sbinfo->si_plink_maint_lock);
21186+ }
4a4d8108
AM
21187+ si_write_unlock(sb);
21188+
21189+ return err;
1facf9fc 21190+}
21191+
21192+/* ---------------------------------------------------------------------- */
21193+
21194+struct pseudo_link {
4a4d8108
AM
21195+ union {
21196+ struct list_head list;
21197+ struct rcu_head rcu;
21198+ };
1facf9fc 21199+ struct inode *inode;
21200+};
21201+
21202+#ifdef CONFIG_AUFS_DEBUG
21203+void au_plink_list(struct super_block *sb)
21204+{
21205+ struct au_sbinfo *sbinfo;
21206+ struct list_head *plink_list;
21207+ struct pseudo_link *plink;
21208+
dece6358
AM
21209+ SiMustAnyLock(sb);
21210+
1facf9fc 21211+ sbinfo = au_sbi(sb);
21212+ AuDebugOn(!au_opt_test(au_mntflags(sb), PLINK));
e49829fe 21213+ AuDebugOn(au_plink_maint(sb, AuLock_NOPLM));
1facf9fc 21214+
21215+ plink_list = &sbinfo->si_plink.head;
4a4d8108
AM
21216+ rcu_read_lock();
21217+ list_for_each_entry_rcu(plink, plink_list, list)
1facf9fc 21218+ AuDbg("%lu\n", plink->inode->i_ino);
4a4d8108 21219+ rcu_read_unlock();
1facf9fc 21220+}
21221+#endif
21222+
21223+/* is the inode pseudo-linked? */
21224+int au_plink_test(struct inode *inode)
21225+{
21226+ int found;
21227+ struct au_sbinfo *sbinfo;
21228+ struct list_head *plink_list;
21229+ struct pseudo_link *plink;
21230+
21231+ sbinfo = au_sbi(inode->i_sb);
dece6358 21232+ AuRwMustAnyLock(&sbinfo->si_rwsem);
1facf9fc 21233+ AuDebugOn(!au_opt_test(au_mntflags(inode->i_sb), PLINK));
e49829fe 21234+ AuDebugOn(au_plink_maint(inode->i_sb, AuLock_NOPLM));
1facf9fc 21235+
21236+ found = 0;
21237+ plink_list = &sbinfo->si_plink.head;
4a4d8108
AM
21238+ rcu_read_lock();
21239+ list_for_each_entry_rcu(plink, plink_list, list)
1facf9fc 21240+ if (plink->inode == inode) {
21241+ found = 1;
21242+ break;
21243+ }
4a4d8108 21244+ rcu_read_unlock();
1facf9fc 21245+ return found;
21246+}
21247+
21248+/* ---------------------------------------------------------------------- */
21249+
21250+/*
21251+ * generate a name for plink.
21252+ * the file will be stored under AUFS_WH_PLINKDIR.
21253+ */
21254+/* 20 is max digits length of ulong 64 */
21255+#define PLINK_NAME_LEN ((20 + 1) * 2)
21256+
21257+static int plink_name(char *name, int len, struct inode *inode,
21258+ aufs_bindex_t bindex)
21259+{
21260+ int rlen;
21261+ struct inode *h_inode;
21262+
21263+ h_inode = au_h_iptr(inode, bindex);
21264+ rlen = snprintf(name, len, "%lu.%lu", inode->i_ino, h_inode->i_ino);
21265+ return rlen;
21266+}
21267+
7f207e10
AM
21268+struct au_do_plink_lkup_args {
21269+ struct dentry **errp;
21270+ struct qstr *tgtname;
21271+ struct dentry *h_parent;
21272+ struct au_branch *br;
21273+};
21274+
21275+static struct dentry *au_do_plink_lkup(struct qstr *tgtname,
21276+ struct dentry *h_parent,
21277+ struct au_branch *br)
21278+{
21279+ struct dentry *h_dentry;
21280+ struct mutex *h_mtx;
21281+
21282+ h_mtx = &h_parent->d_inode->i_mutex;
21283+ mutex_lock_nested(h_mtx, AuLsc_I_CHILD2);
b4510431 21284+ h_dentry = vfsub_lkup_one(tgtname, h_parent);
7f207e10
AM
21285+ mutex_unlock(h_mtx);
21286+ return h_dentry;
21287+}
21288+
21289+static void au_call_do_plink_lkup(void *args)
21290+{
21291+ struct au_do_plink_lkup_args *a = args;
21292+ *a->errp = au_do_plink_lkup(a->tgtname, a->h_parent, a->br);
21293+}
21294+
1facf9fc 21295+/* lookup the plink-ed @inode under the branch at @bindex */
21296+struct dentry *au_plink_lkup(struct inode *inode, aufs_bindex_t bindex)
21297+{
21298+ struct dentry *h_dentry, *h_parent;
21299+ struct au_branch *br;
21300+ struct inode *h_dir;
7f207e10 21301+ int wkq_err;
1facf9fc 21302+ char a[PLINK_NAME_LEN];
0c3ec466 21303+ struct qstr tgtname = QSTR_INIT(a, 0);
1facf9fc 21304+
e49829fe
JR
21305+ AuDebugOn(au_plink_maint(inode->i_sb, AuLock_NOPLM));
21306+
1facf9fc 21307+ br = au_sbr(inode->i_sb, bindex);
21308+ h_parent = br->br_wbr->wbr_plink;
21309+ h_dir = h_parent->d_inode;
21310+ tgtname.len = plink_name(a, sizeof(a), inode, bindex);
21311+
2dfbb274 21312+ if (!uid_eq(current_fsuid(), GLOBAL_ROOT_UID)) {
7f207e10
AM
21313+ struct au_do_plink_lkup_args args = {
21314+ .errp = &h_dentry,
21315+ .tgtname = &tgtname,
21316+ .h_parent = h_parent,
21317+ .br = br
21318+ };
21319+
21320+ wkq_err = au_wkq_wait(au_call_do_plink_lkup, &args);
21321+ if (unlikely(wkq_err))
21322+ h_dentry = ERR_PTR(wkq_err);
21323+ } else
21324+ h_dentry = au_do_plink_lkup(&tgtname, h_parent, br);
21325+
1facf9fc 21326+ return h_dentry;
21327+}
21328+
21329+/* create a pseudo-link */
21330+static int do_whplink(struct qstr *tgt, struct dentry *h_parent,
21331+ struct dentry *h_dentry, struct au_branch *br)
21332+{
21333+ int err;
21334+ struct path h_path = {
21335+ .mnt = br->br_mnt
21336+ };
21337+ struct inode *h_dir;
21338+
21339+ h_dir = h_parent->d_inode;
7f207e10 21340+ mutex_lock_nested(&h_dir->i_mutex, AuLsc_I_CHILD2);
4f0767ce 21341+again:
b4510431 21342+ h_path.dentry = vfsub_lkup_one(tgt, h_parent);
1facf9fc 21343+ err = PTR_ERR(h_path.dentry);
21344+ if (IS_ERR(h_path.dentry))
21345+ goto out;
21346+
21347+ err = 0;
21348+ /* wh.plink dir is not monitored */
7f207e10 21349+ /* todo: is it really safe? */
1facf9fc 21350+ if (h_path.dentry->d_inode
21351+ && h_path.dentry->d_inode != h_dentry->d_inode) {
21352+ err = vfsub_unlink(h_dir, &h_path, /*force*/0);
21353+ dput(h_path.dentry);
21354+ h_path.dentry = NULL;
21355+ if (!err)
21356+ goto again;
21357+ }
21358+ if (!err && !h_path.dentry->d_inode)
21359+ err = vfsub_link(h_dentry, h_dir, &h_path);
21360+ dput(h_path.dentry);
21361+
4f0767ce 21362+out:
7f207e10 21363+ mutex_unlock(&h_dir->i_mutex);
1facf9fc 21364+ return err;
21365+}
21366+
21367+struct do_whplink_args {
21368+ int *errp;
21369+ struct qstr *tgt;
21370+ struct dentry *h_parent;
21371+ struct dentry *h_dentry;
21372+ struct au_branch *br;
21373+};
21374+
21375+static void call_do_whplink(void *args)
21376+{
21377+ struct do_whplink_args *a = args;
21378+ *a->errp = do_whplink(a->tgt, a->h_parent, a->h_dentry, a->br);
21379+}
21380+
21381+static int whplink(struct dentry *h_dentry, struct inode *inode,
21382+ aufs_bindex_t bindex, struct au_branch *br)
21383+{
21384+ int err, wkq_err;
21385+ struct au_wbr *wbr;
21386+ struct dentry *h_parent;
21387+ struct inode *h_dir;
21388+ char a[PLINK_NAME_LEN];
0c3ec466 21389+ struct qstr tgtname = QSTR_INIT(a, 0);
1facf9fc 21390+
21391+ wbr = au_sbr(inode->i_sb, bindex)->br_wbr;
21392+ h_parent = wbr->wbr_plink;
21393+ h_dir = h_parent->d_inode;
21394+ tgtname.len = plink_name(a, sizeof(a), inode, bindex);
21395+
21396+ /* always superio. */
2dfbb274 21397+ if (!uid_eq(current_fsuid(), GLOBAL_ROOT_UID)) {
1facf9fc 21398+ struct do_whplink_args args = {
21399+ .errp = &err,
21400+ .tgt = &tgtname,
21401+ .h_parent = h_parent,
21402+ .h_dentry = h_dentry,
21403+ .br = br
21404+ };
21405+ wkq_err = au_wkq_wait(call_do_whplink, &args);
21406+ if (unlikely(wkq_err))
21407+ err = wkq_err;
21408+ } else
21409+ err = do_whplink(&tgtname, h_parent, h_dentry, br);
1facf9fc 21410+
21411+ return err;
21412+}
21413+
21414+/* free a single plink */
21415+static void do_put_plink(struct pseudo_link *plink, int do_del)
21416+{
1facf9fc 21417+ if (do_del)
21418+ list_del(&plink->list);
4a4d8108
AM
21419+ iput(plink->inode);
21420+ kfree(plink);
21421+}
21422+
21423+static void do_put_plink_rcu(struct rcu_head *rcu)
21424+{
21425+ struct pseudo_link *plink;
21426+
21427+ plink = container_of(rcu, struct pseudo_link, rcu);
21428+ iput(plink->inode);
1facf9fc 21429+ kfree(plink);
21430+}
21431+
21432+/*
21433+ * create a new pseudo-link for @h_dentry on @bindex.
21434+ * the linked inode is held in aufs @inode.
21435+ */
21436+void au_plink_append(struct inode *inode, aufs_bindex_t bindex,
21437+ struct dentry *h_dentry)
21438+{
21439+ struct super_block *sb;
21440+ struct au_sbinfo *sbinfo;
21441+ struct list_head *plink_list;
4a4d8108 21442+ struct pseudo_link *plink, *tmp;
1facf9fc 21443+ int found, err, cnt;
21444+
21445+ sb = inode->i_sb;
21446+ sbinfo = au_sbi(sb);
21447+ AuDebugOn(!au_opt_test(au_mntflags(sb), PLINK));
e49829fe 21448+ AuDebugOn(au_plink_maint(sb, AuLock_NOPLM));
1facf9fc 21449+
1facf9fc 21450+ cnt = 0;
21451+ found = 0;
21452+ plink_list = &sbinfo->si_plink.head;
4a4d8108
AM
21453+ rcu_read_lock();
21454+ list_for_each_entry_rcu(plink, plink_list, list) {
1facf9fc 21455+ cnt++;
21456+ if (plink->inode == inode) {
21457+ found = 1;
21458+ break;
21459+ }
21460+ }
4a4d8108
AM
21461+ rcu_read_unlock();
21462+ if (found)
1facf9fc 21463+ return;
4a4d8108
AM
21464+
21465+ tmp = kmalloc(sizeof(*plink), GFP_NOFS);
21466+ if (tmp)
21467+ tmp->inode = au_igrab(inode);
21468+ else {
21469+ err = -ENOMEM;
21470+ goto out;
1facf9fc 21471+ }
21472+
4a4d8108
AM
21473+ spin_lock(&sbinfo->si_plink.spin);
21474+ list_for_each_entry(plink, plink_list, list) {
21475+ if (plink->inode == inode) {
21476+ found = 1;
21477+ break;
21478+ }
1facf9fc 21479+ }
4a4d8108
AM
21480+ if (!found)
21481+ list_add_rcu(&tmp->list, plink_list);
1facf9fc 21482+ spin_unlock(&sbinfo->si_plink.spin);
4a4d8108
AM
21483+ if (!found) {
21484+ cnt++;
21485+ WARN_ONCE(cnt > AUFS_PLINK_WARN,
21486+ "unexpectedly many pseudo links, %d\n", cnt);
1facf9fc 21487+ err = whplink(h_dentry, inode, bindex, au_sbr(sb, bindex));
4a4d8108
AM
21488+ } else {
21489+ do_put_plink(tmp, 0);
21490+ return;
1facf9fc 21491+ }
21492+
4a4d8108 21493+out:
1facf9fc 21494+ if (unlikely(err)) {
0c3ec466 21495+ pr_warn("err %d, damaged pseudo link.\n", err);
4a4d8108
AM
21496+ if (tmp) {
21497+ au_spl_del_rcu(&tmp->list, &sbinfo->si_plink);
21498+ call_rcu(&tmp->rcu, do_put_plink_rcu);
21499+ }
1facf9fc 21500+ }
21501+}
21502+
21503+/* free all plinks */
e49829fe 21504+void au_plink_put(struct super_block *sb, int verbose)
1facf9fc 21505+{
21506+ struct au_sbinfo *sbinfo;
21507+ struct list_head *plink_list;
21508+ struct pseudo_link *plink, *tmp;
21509+
dece6358
AM
21510+ SiMustWriteLock(sb);
21511+
1facf9fc 21512+ sbinfo = au_sbi(sb);
21513+ AuDebugOn(!au_opt_test(au_mntflags(sb), PLINK));
e49829fe 21514+ AuDebugOn(au_plink_maint(sb, AuLock_NOPLM));
1facf9fc 21515+
21516+ plink_list = &sbinfo->si_plink.head;
21517+ /* no spin_lock since sbinfo is write-locked */
e49829fe 21518+ WARN(verbose && !list_empty(plink_list), "pseudo-link is not flushed");
1facf9fc 21519+ list_for_each_entry_safe(plink, tmp, plink_list, list)
21520+ do_put_plink(plink, 0);
21521+ INIT_LIST_HEAD(plink_list);
21522+}
21523+
e49829fe
JR
21524+void au_plink_clean(struct super_block *sb, int verbose)
21525+{
21526+ struct dentry *root;
21527+
21528+ root = sb->s_root;
21529+ aufs_write_lock(root);
21530+ if (au_opt_test(au_mntflags(sb), PLINK))
21531+ au_plink_put(sb, verbose);
21532+ aufs_write_unlock(root);
21533+}
21534+
1facf9fc 21535+/* free the plinks on a branch specified by @br_id */
21536+void au_plink_half_refresh(struct super_block *sb, aufs_bindex_t br_id)
21537+{
21538+ struct au_sbinfo *sbinfo;
21539+ struct list_head *plink_list;
21540+ struct pseudo_link *plink, *tmp;
21541+ struct inode *inode;
21542+ aufs_bindex_t bstart, bend, bindex;
21543+ unsigned char do_put;
21544+
dece6358
AM
21545+ SiMustWriteLock(sb);
21546+
1facf9fc 21547+ sbinfo = au_sbi(sb);
21548+ AuDebugOn(!au_opt_test(au_mntflags(sb), PLINK));
e49829fe 21549+ AuDebugOn(au_plink_maint(sb, AuLock_NOPLM));
1facf9fc 21550+
21551+ plink_list = &sbinfo->si_plink.head;
21552+ /* no spin_lock since sbinfo is write-locked */
21553+ list_for_each_entry_safe(plink, tmp, plink_list, list) {
21554+ do_put = 0;
21555+ inode = au_igrab(plink->inode);
21556+ ii_write_lock_child(inode);
21557+ bstart = au_ibstart(inode);
21558+ bend = au_ibend(inode);
21559+ if (bstart >= 0) {
21560+ for (bindex = bstart; bindex <= bend; bindex++) {
21561+ if (!au_h_iptr(inode, bindex)
21562+ || au_ii_br_id(inode, bindex) != br_id)
21563+ continue;
21564+ au_set_h_iptr(inode, bindex, NULL, 0);
21565+ do_put = 1;
21566+ break;
21567+ }
21568+ } else
21569+ do_put_plink(plink, 1);
21570+
dece6358
AM
21571+ if (do_put) {
21572+ for (bindex = bstart; bindex <= bend; bindex++)
21573+ if (au_h_iptr(inode, bindex)) {
21574+ do_put = 0;
21575+ break;
21576+ }
21577+ if (do_put)
21578+ do_put_plink(plink, 1);
21579+ }
21580+ ii_write_unlock(inode);
21581+ iput(inode);
21582+ }
21583+}
7f207e10
AM
21584diff -urN /usr/share/empty/fs/aufs/poll.c linux/fs/aufs/poll.c
21585--- /usr/share/empty/fs/aufs/poll.c 1970-01-01 01:00:00.000000000 +0100
537831f9 21586+++ linux/fs/aufs/poll.c 2012-12-13 20:41:10.431460173 +0100
dece6358
AM
21587@@ -0,0 +1,56 @@
21588+/*
f6c5ef8b 21589+ * Copyright (C) 2005-2012 Junjiro R. Okajima
dece6358
AM
21590+ *
21591+ * This program, aufs is free software; you can redistribute it and/or modify
21592+ * it under the terms of the GNU General Public License as published by
21593+ * the Free Software Foundation; either version 2 of the License, or
21594+ * (at your option) any later version.
21595+ *
21596+ * This program is distributed in the hope that it will be useful,
21597+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
21598+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21599+ * GNU General Public License for more details.
21600+ *
21601+ * You should have received a copy of the GNU General Public License
21602+ * along with this program; if not, write to the Free Software
21603+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
21604+ */
21605+
1308ab2a 21606+/*
21607+ * poll operation
21608+ * There is only one filesystem which implements ->poll operation, currently.
21609+ */
21610+
21611+#include "aufs.h"
21612+
21613+unsigned int aufs_poll(struct file *file, poll_table *wait)
21614+{
21615+ unsigned int mask;
21616+ int err;
21617+ struct file *h_file;
21618+ struct dentry *dentry;
21619+ struct super_block *sb;
21620+
21621+ /* We should pretend an error happened. */
21622+ mask = POLLERR /* | POLLIN | POLLOUT */;
21623+ dentry = file->f_dentry;
21624+ sb = dentry->d_sb;
e49829fe 21625+ si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLMW);
1308ab2a 21626+ err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/0);
21627+ if (unlikely(err))
21628+ goto out;
21629+
21630+ /* it is not an error if h_file has no operation */
21631+ mask = DEFAULT_POLLMASK;
4a4d8108 21632+ h_file = au_hf_top(file);
1308ab2a 21633+ if (h_file->f_op && h_file->f_op->poll)
21634+ mask = h_file->f_op->poll(h_file, wait);
21635+
21636+ di_read_unlock(dentry, AuLock_IR);
21637+ fi_read_unlock(file);
21638+
4f0767ce 21639+out:
1308ab2a 21640+ si_read_unlock(sb);
21641+ AuTraceErr((int)mask);
21642+ return mask;
21643+}
7f207e10
AM
21644diff -urN /usr/share/empty/fs/aufs/procfs.c linux/fs/aufs/procfs.c
21645--- /usr/share/empty/fs/aufs/procfs.c 1970-01-01 01:00:00.000000000 +0100
537831f9 21646+++ linux/fs/aufs/procfs.c 2012-12-13 20:41:10.431460173 +0100
53392da6 21647@@ -0,0 +1,170 @@
e49829fe 21648+/*
f6c5ef8b 21649+ * Copyright (C) 2010-2012 Junjiro R. Okajima
e49829fe
JR
21650+ *
21651+ * This program, aufs is free software; you can redistribute it and/or modify
21652+ * it under the terms of the GNU General Public License as published by
21653+ * the Free Software Foundation; either version 2 of the License, or
21654+ * (at your option) any later version.
21655+ *
21656+ * This program is distributed in the hope that it will be useful,
21657+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
21658+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21659+ * GNU General Public License for more details.
21660+ *
21661+ * You should have received a copy of the GNU General Public License
21662+ * along with this program; if not, write to the Free Software
21663+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
21664+ */
21665+
21666+/*
21667+ * procfs interfaces
21668+ */
21669+
21670+#include <linux/proc_fs.h>
21671+#include "aufs.h"
21672+
21673+static int au_procfs_plm_release(struct inode *inode, struct file *file)
21674+{
21675+ struct au_sbinfo *sbinfo;
21676+
21677+ sbinfo = file->private_data;
21678+ if (sbinfo) {
21679+ au_plink_maint_leave(sbinfo);
21680+ kobject_put(&sbinfo->si_kobj);
21681+ }
21682+
21683+ return 0;
21684+}
21685+
21686+static void au_procfs_plm_write_clean(struct file *file)
21687+{
21688+ struct au_sbinfo *sbinfo;
21689+
21690+ sbinfo = file->private_data;
21691+ if (sbinfo)
21692+ au_plink_clean(sbinfo->si_sb, /*verbose*/0);
21693+}
21694+
21695+static int au_procfs_plm_write_si(struct file *file, unsigned long id)
21696+{
21697+ int err;
21698+ struct super_block *sb;
21699+ struct au_sbinfo *sbinfo;
21700+
21701+ err = -EBUSY;
21702+ if (unlikely(file->private_data))
21703+ goto out;
21704+
21705+ sb = NULL;
53392da6 21706+ /* don't use au_sbilist_lock() here */
e49829fe
JR
21707+ spin_lock(&au_sbilist.spin);
21708+ list_for_each_entry(sbinfo, &au_sbilist.head, si_list)
21709+ if (id == sysaufs_si_id(sbinfo)) {
21710+ kobject_get(&sbinfo->si_kobj);
21711+ sb = sbinfo->si_sb;
21712+ break;
21713+ }
21714+ spin_unlock(&au_sbilist.spin);
21715+
21716+ err = -EINVAL;
21717+ if (unlikely(!sb))
21718+ goto out;
21719+
21720+ err = au_plink_maint_enter(sb);
21721+ if (!err)
21722+ /* keep kobject_get() */
21723+ file->private_data = sbinfo;
21724+ else
21725+ kobject_put(&sbinfo->si_kobj);
21726+out:
21727+ return err;
21728+}
21729+
21730+/*
21731+ * Accept a valid "si=xxxx" only.
21732+ * Once it is accepted successfully, accept "clean" too.
21733+ */
21734+static ssize_t au_procfs_plm_write(struct file *file, const char __user *ubuf,
21735+ size_t count, loff_t *ppos)
21736+{
21737+ ssize_t err;
21738+ unsigned long id;
21739+ /* last newline is allowed */
21740+ char buf[3 + sizeof(unsigned long) * 2 + 1];
21741+
21742+ err = -EACCES;
21743+ if (unlikely(!capable(CAP_SYS_ADMIN)))
21744+ goto out;
21745+
21746+ err = -EINVAL;
21747+ if (unlikely(count > sizeof(buf)))
21748+ goto out;
21749+
21750+ err = copy_from_user(buf, ubuf, count);
21751+ if (unlikely(err)) {
21752+ err = -EFAULT;
21753+ goto out;
21754+ }
21755+ buf[count] = 0;
21756+
21757+ err = -EINVAL;
21758+ if (!strcmp("clean", buf)) {
21759+ au_procfs_plm_write_clean(file);
21760+ goto out_success;
21761+ } else if (unlikely(strncmp("si=", buf, 3)))
21762+ goto out;
21763+
9dbd164d 21764+ err = kstrtoul(buf + 3, 16, &id);
e49829fe
JR
21765+ if (unlikely(err))
21766+ goto out;
21767+
21768+ err = au_procfs_plm_write_si(file, id);
21769+ if (unlikely(err))
21770+ goto out;
21771+
21772+out_success:
21773+ err = count; /* success */
21774+out:
21775+ return err;
21776+}
21777+
21778+static const struct file_operations au_procfs_plm_fop = {
21779+ .write = au_procfs_plm_write,
21780+ .release = au_procfs_plm_release,
21781+ .owner = THIS_MODULE
21782+};
21783+
21784+/* ---------------------------------------------------------------------- */
21785+
21786+static struct proc_dir_entry *au_procfs_dir;
21787+
21788+void au_procfs_fin(void)
21789+{
21790+ remove_proc_entry(AUFS_PLINK_MAINT_NAME, au_procfs_dir);
21791+ remove_proc_entry(AUFS_PLINK_MAINT_DIR, NULL);
21792+}
21793+
21794+int __init au_procfs_init(void)
21795+{
21796+ int err;
21797+ struct proc_dir_entry *entry;
21798+
21799+ err = -ENOMEM;
21800+ au_procfs_dir = proc_mkdir(AUFS_PLINK_MAINT_DIR, NULL);
21801+ if (unlikely(!au_procfs_dir))
21802+ goto out;
21803+
21804+ entry = proc_create(AUFS_PLINK_MAINT_NAME, S_IFREG | S_IWUSR,
21805+ au_procfs_dir, &au_procfs_plm_fop);
21806+ if (unlikely(!entry))
21807+ goto out_dir;
21808+
21809+ err = 0;
21810+ goto out; /* success */
21811+
21812+
21813+out_dir:
21814+ remove_proc_entry(AUFS_PLINK_MAINT_DIR, NULL);
21815+out:
21816+ return err;
21817+}
7f207e10
AM
21818diff -urN /usr/share/empty/fs/aufs/rdu.c linux/fs/aufs/rdu.c
21819--- /usr/share/empty/fs/aufs/rdu.c 1970-01-01 01:00:00.000000000 +0100
537831f9 21820+++ linux/fs/aufs/rdu.c 2012-12-13 20:41:10.431460173 +0100
92d182d2 21821@@ -0,0 +1,384 @@
1308ab2a 21822+/*
f6c5ef8b 21823+ * Copyright (C) 2005-2012 Junjiro R. Okajima
1308ab2a 21824+ *
21825+ * This program, aufs is free software; you can redistribute it and/or modify
21826+ * it under the terms of the GNU General Public License as published by
21827+ * the Free Software Foundation; either version 2 of the License, or
21828+ * (at your option) any later version.
21829+ *
21830+ * This program is distributed in the hope that it will be useful,
21831+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
21832+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21833+ * GNU General Public License for more details.
21834+ *
21835+ * You should have received a copy of the GNU General Public License
21836+ * along with this program; if not, write to the Free Software
21837+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
21838+ */
21839+
21840+/*
21841+ * readdir in userspace.
21842+ */
21843+
b752ccd1 21844+#include <linux/compat.h>
4a4d8108 21845+#include <linux/fs_stack.h>
1308ab2a 21846+#include <linux/security.h>
1308ab2a 21847+#include "aufs.h"
21848+
21849+/* bits for struct aufs_rdu.flags */
21850+#define AuRdu_CALLED 1
21851+#define AuRdu_CONT (1 << 1)
21852+#define AuRdu_FULL (1 << 2)
21853+#define au_ftest_rdu(flags, name) ((flags) & AuRdu_##name)
7f207e10
AM
21854+#define au_fset_rdu(flags, name) \
21855+ do { (flags) |= AuRdu_##name; } while (0)
21856+#define au_fclr_rdu(flags, name) \
21857+ do { (flags) &= ~AuRdu_##name; } while (0)
1308ab2a 21858+
21859+struct au_rdu_arg {
21860+ struct aufs_rdu *rdu;
21861+ union au_rdu_ent_ul ent;
21862+ unsigned long end;
21863+
21864+ struct super_block *sb;
21865+ int err;
21866+};
21867+
21868+static int au_rdu_fill(void *__arg, const char *name, int nlen,
21869+ loff_t offset, u64 h_ino, unsigned int d_type)
21870+{
21871+ int err, len;
21872+ struct au_rdu_arg *arg = __arg;
21873+ struct aufs_rdu *rdu = arg->rdu;
21874+ struct au_rdu_ent ent;
21875+
21876+ err = 0;
21877+ arg->err = 0;
21878+ au_fset_rdu(rdu->cookie.flags, CALLED);
21879+ len = au_rdu_len(nlen);
21880+ if (arg->ent.ul + len < arg->end) {
21881+ ent.ino = h_ino;
21882+ ent.bindex = rdu->cookie.bindex;
21883+ ent.type = d_type;
21884+ ent.nlen = nlen;
4a4d8108
AM
21885+ if (unlikely(nlen > AUFS_MAX_NAMELEN))
21886+ ent.type = DT_UNKNOWN;
1308ab2a 21887+
9dbd164d 21888+ /* unnecessary to support mmap_sem since this is a dir */
1308ab2a 21889+ err = -EFAULT;
21890+ if (copy_to_user(arg->ent.e, &ent, sizeof(ent)))
21891+ goto out;
21892+ if (copy_to_user(arg->ent.e->name, name, nlen))
21893+ goto out;
21894+ /* the terminating NULL */
21895+ if (__put_user(0, arg->ent.e->name + nlen))
21896+ goto out;
21897+ err = 0;
21898+ /* AuDbg("%p, %.*s\n", arg->ent.p, nlen, name); */
21899+ arg->ent.ul += len;
21900+ rdu->rent++;
21901+ } else {
21902+ err = -EFAULT;
21903+ au_fset_rdu(rdu->cookie.flags, FULL);
21904+ rdu->full = 1;
21905+ rdu->tail = arg->ent;
21906+ }
21907+
4f0767ce 21908+out:
1308ab2a 21909+ /* AuTraceErr(err); */
21910+ return err;
21911+}
21912+
21913+static int au_rdu_do(struct file *h_file, struct au_rdu_arg *arg)
21914+{
21915+ int err;
21916+ loff_t offset;
21917+ struct au_rdu_cookie *cookie = &arg->rdu->cookie;
21918+
92d182d2 21919+ /* we don't have to care (FMODE_32BITHASH | FMODE_64BITHASH) for ext4 */
1308ab2a 21920+ offset = vfsub_llseek(h_file, cookie->h_pos, SEEK_SET);
21921+ err = offset;
21922+ if (unlikely(offset != cookie->h_pos))
21923+ goto out;
21924+
21925+ err = 0;
21926+ do {
21927+ arg->err = 0;
21928+ au_fclr_rdu(cookie->flags, CALLED);
21929+ /* smp_mb(); */
21930+ err = vfsub_readdir(h_file, au_rdu_fill, arg);
21931+ if (err >= 0)
21932+ err = arg->err;
21933+ } while (!err
21934+ && au_ftest_rdu(cookie->flags, CALLED)
21935+ && !au_ftest_rdu(cookie->flags, FULL));
21936+ cookie->h_pos = h_file->f_pos;
21937+
4f0767ce 21938+out:
1308ab2a 21939+ AuTraceErr(err);
21940+ return err;
21941+}
21942+
21943+static int au_rdu(struct file *file, struct aufs_rdu *rdu)
21944+{
21945+ int err;
21946+ aufs_bindex_t bend;
21947+ struct au_rdu_arg arg;
21948+ struct dentry *dentry;
21949+ struct inode *inode;
21950+ struct file *h_file;
21951+ struct au_rdu_cookie *cookie = &rdu->cookie;
21952+
21953+ err = !access_ok(VERIFY_WRITE, rdu->ent.e, rdu->sz);
21954+ if (unlikely(err)) {
21955+ err = -EFAULT;
21956+ AuTraceErr(err);
21957+ goto out;
21958+ }
21959+ rdu->rent = 0;
21960+ rdu->tail = rdu->ent;
21961+ rdu->full = 0;
21962+ arg.rdu = rdu;
21963+ arg.ent = rdu->ent;
21964+ arg.end = arg.ent.ul;
21965+ arg.end += rdu->sz;
21966+
21967+ err = -ENOTDIR;
21968+ if (unlikely(!file->f_op || !file->f_op->readdir))
21969+ goto out;
21970+
21971+ err = security_file_permission(file, MAY_READ);
21972+ AuTraceErr(err);
21973+ if (unlikely(err))
21974+ goto out;
21975+
21976+ dentry = file->f_dentry;
21977+ inode = dentry->d_inode;
21978+#if 1
21979+ mutex_lock(&inode->i_mutex);
21980+#else
21981+ err = mutex_lock_killable(&inode->i_mutex);
21982+ AuTraceErr(err);
21983+ if (unlikely(err))
21984+ goto out;
21985+#endif
1308ab2a 21986+
21987+ arg.sb = inode->i_sb;
e49829fe
JR
21988+ err = si_read_lock(arg.sb, AuLock_FLUSH | AuLock_NOPLM);
21989+ if (unlikely(err))
21990+ goto out_mtx;
027c5e7a
AM
21991+ err = au_alive_dir(dentry);
21992+ if (unlikely(err))
21993+ goto out_si;
e49829fe 21994+ /* todo: reval? */
1308ab2a 21995+ fi_read_lock(file);
21996+
21997+ err = -EAGAIN;
21998+ if (unlikely(au_ftest_rdu(cookie->flags, CONT)
21999+ && cookie->generation != au_figen(file)))
22000+ goto out_unlock;
22001+
22002+ err = 0;
22003+ if (!rdu->blk) {
22004+ rdu->blk = au_sbi(arg.sb)->si_rdblk;
22005+ if (!rdu->blk)
22006+ rdu->blk = au_dir_size(file, /*dentry*/NULL);
22007+ }
22008+ bend = au_fbstart(file);
22009+ if (cookie->bindex < bend)
22010+ cookie->bindex = bend;
4a4d8108 22011+ bend = au_fbend_dir(file);
1308ab2a 22012+ /* AuDbg("b%d, b%d\n", cookie->bindex, bend); */
22013+ for (; !err && cookie->bindex <= bend;
22014+ cookie->bindex++, cookie->h_pos = 0) {
4a4d8108 22015+ h_file = au_hf_dir(file, cookie->bindex);
1308ab2a 22016+ if (!h_file)
22017+ continue;
22018+
22019+ au_fclr_rdu(cookie->flags, FULL);
22020+ err = au_rdu_do(h_file, &arg);
22021+ AuTraceErr(err);
22022+ if (unlikely(au_ftest_rdu(cookie->flags, FULL) || err))
22023+ break;
22024+ }
22025+ AuDbg("rent %llu\n", rdu->rent);
22026+
22027+ if (!err && !au_ftest_rdu(cookie->flags, CONT)) {
22028+ rdu->shwh = !!au_opt_test(au_sbi(arg.sb)->si_mntflags, SHWH);
22029+ au_fset_rdu(cookie->flags, CONT);
22030+ cookie->generation = au_figen(file);
22031+ }
22032+
22033+ ii_read_lock_child(inode);
22034+ fsstack_copy_attr_atime(inode, au_h_iptr(inode, au_ibstart(inode)));
22035+ ii_read_unlock(inode);
22036+
4f0767ce 22037+out_unlock:
1308ab2a 22038+ fi_read_unlock(file);
027c5e7a 22039+out_si:
1308ab2a 22040+ si_read_unlock(arg.sb);
4f0767ce 22041+out_mtx:
1308ab2a 22042+ mutex_unlock(&inode->i_mutex);
4f0767ce 22043+out:
1308ab2a 22044+ AuTraceErr(err);
22045+ return err;
22046+}
22047+
22048+static int au_rdu_ino(struct file *file, struct aufs_rdu *rdu)
22049+{
22050+ int err;
22051+ ino_t ino;
22052+ unsigned long long nent;
22053+ union au_rdu_ent_ul *u;
22054+ struct au_rdu_ent ent;
22055+ struct super_block *sb;
22056+
22057+ err = 0;
22058+ nent = rdu->nent;
22059+ u = &rdu->ent;
22060+ sb = file->f_dentry->d_sb;
22061+ si_read_lock(sb, AuLock_FLUSH);
22062+ while (nent-- > 0) {
9dbd164d 22063+ /* unnecessary to support mmap_sem since this is a dir */
1308ab2a 22064+ err = copy_from_user(&ent, u->e, sizeof(ent));
4a4d8108
AM
22065+ if (!err)
22066+ err = !access_ok(VERIFY_WRITE, &u->e->ino, sizeof(ino));
1308ab2a 22067+ if (unlikely(err)) {
22068+ err = -EFAULT;
22069+ AuTraceErr(err);
22070+ break;
22071+ }
22072+
22073+ /* AuDbg("b%d, i%llu\n", ent.bindex, ent.ino); */
22074+ if (!ent.wh)
22075+ err = au_ino(sb, ent.bindex, ent.ino, ent.type, &ino);
22076+ else
22077+ err = au_wh_ino(sb, ent.bindex, ent.ino, ent.type,
22078+ &ino);
22079+ if (unlikely(err)) {
22080+ AuTraceErr(err);
22081+ break;
22082+ }
22083+
22084+ err = __put_user(ino, &u->e->ino);
22085+ if (unlikely(err)) {
22086+ err = -EFAULT;
22087+ AuTraceErr(err);
22088+ break;
22089+ }
22090+ u->ul += au_rdu_len(ent.nlen);
22091+ }
22092+ si_read_unlock(sb);
22093+
22094+ return err;
22095+}
22096+
22097+/* ---------------------------------------------------------------------- */
22098+
22099+static int au_rdu_verify(struct aufs_rdu *rdu)
22100+{
b752ccd1 22101+ AuDbg("rdu{%llu, %p, %u | %u | %llu, %u, %u | "
1308ab2a 22102+ "%llu, b%d, 0x%x, g%u}\n",
b752ccd1 22103+ rdu->sz, rdu->ent.e, rdu->verify[AufsCtlRduV_SZ],
1308ab2a 22104+ rdu->blk,
22105+ rdu->rent, rdu->shwh, rdu->full,
22106+ rdu->cookie.h_pos, rdu->cookie.bindex, rdu->cookie.flags,
22107+ rdu->cookie.generation);
dece6358 22108+
b752ccd1 22109+ if (rdu->verify[AufsCtlRduV_SZ] == sizeof(*rdu))
1308ab2a 22110+ return 0;
dece6358 22111+
b752ccd1
AM
22112+ AuDbg("%u:%u\n",
22113+ rdu->verify[AufsCtlRduV_SZ], (unsigned int)sizeof(*rdu));
1308ab2a 22114+ return -EINVAL;
22115+}
22116+
22117+long au_rdu_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
dece6358 22118+{
1308ab2a 22119+ long err, e;
22120+ struct aufs_rdu rdu;
22121+ void __user *p = (void __user *)arg;
dece6358 22122+
1308ab2a 22123+ err = copy_from_user(&rdu, p, sizeof(rdu));
22124+ if (unlikely(err)) {
22125+ err = -EFAULT;
22126+ AuTraceErr(err);
22127+ goto out;
22128+ }
22129+ err = au_rdu_verify(&rdu);
dece6358
AM
22130+ if (unlikely(err))
22131+ goto out;
22132+
1308ab2a 22133+ switch (cmd) {
22134+ case AUFS_CTL_RDU:
22135+ err = au_rdu(file, &rdu);
22136+ if (unlikely(err))
22137+ break;
dece6358 22138+
1308ab2a 22139+ e = copy_to_user(p, &rdu, sizeof(rdu));
22140+ if (unlikely(e)) {
22141+ err = -EFAULT;
22142+ AuTraceErr(err);
22143+ }
22144+ break;
22145+ case AUFS_CTL_RDU_INO:
22146+ err = au_rdu_ino(file, &rdu);
22147+ break;
22148+
22149+ default:
4a4d8108 22150+ /* err = -ENOTTY; */
1308ab2a 22151+ err = -EINVAL;
22152+ }
dece6358 22153+
4f0767ce 22154+out:
1308ab2a 22155+ AuTraceErr(err);
22156+ return err;
1facf9fc 22157+}
b752ccd1
AM
22158+
22159+#ifdef CONFIG_COMPAT
22160+long au_rdu_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
22161+{
22162+ long err, e;
22163+ struct aufs_rdu rdu;
22164+ void __user *p = compat_ptr(arg);
22165+
22166+ /* todo: get_user()? */
22167+ err = copy_from_user(&rdu, p, sizeof(rdu));
22168+ if (unlikely(err)) {
22169+ err = -EFAULT;
22170+ AuTraceErr(err);
22171+ goto out;
22172+ }
22173+ rdu.ent.e = compat_ptr(rdu.ent.ul);
22174+ err = au_rdu_verify(&rdu);
22175+ if (unlikely(err))
22176+ goto out;
22177+
22178+ switch (cmd) {
22179+ case AUFS_CTL_RDU:
22180+ err = au_rdu(file, &rdu);
22181+ if (unlikely(err))
22182+ break;
22183+
22184+ rdu.ent.ul = ptr_to_compat(rdu.ent.e);
22185+ rdu.tail.ul = ptr_to_compat(rdu.tail.e);
22186+ e = copy_to_user(p, &rdu, sizeof(rdu));
22187+ if (unlikely(e)) {
22188+ err = -EFAULT;
22189+ AuTraceErr(err);
22190+ }
22191+ break;
22192+ case AUFS_CTL_RDU_INO:
22193+ err = au_rdu_ino(file, &rdu);
22194+ break;
22195+
22196+ default:
22197+ /* err = -ENOTTY; */
22198+ err = -EINVAL;
22199+ }
22200+
4f0767ce 22201+out:
b752ccd1
AM
22202+ AuTraceErr(err);
22203+ return err;
22204+}
22205+#endif
7f207e10
AM
22206diff -urN /usr/share/empty/fs/aufs/rwsem.h linux/fs/aufs/rwsem.h
22207--- /usr/share/empty/fs/aufs/rwsem.h 1970-01-01 01:00:00.000000000 +0100
537831f9 22208+++ linux/fs/aufs/rwsem.h 2012-12-13 20:41:10.431460173 +0100
f6c5ef8b 22209@@ -0,0 +1,188 @@
1facf9fc 22210+/*
f6c5ef8b 22211+ * Copyright (C) 2005-2012 Junjiro R. Okajima
1facf9fc 22212+ *
22213+ * This program, aufs is free software; you can redistribute it and/or modify
22214+ * it under the terms of the GNU General Public License as published by
22215+ * the Free Software Foundation; either version 2 of the License, or
22216+ * (at your option) any later version.
dece6358
AM
22217+ *
22218+ * This program is distributed in the hope that it will be useful,
22219+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
22220+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22221+ * GNU General Public License for more details.
22222+ *
22223+ * You should have received a copy of the GNU General Public License
22224+ * along with this program; if not, write to the Free Software
22225+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 22226+ */
22227+
22228+/*
22229+ * simple read-write semaphore wrappers
22230+ */
22231+
22232+#ifndef __AUFS_RWSEM_H__
22233+#define __AUFS_RWSEM_H__
22234+
22235+#ifdef __KERNEL__
22236+
4a4d8108 22237+#include "debug.h"
dece6358
AM
22238+
22239+struct au_rwsem {
22240+ struct rw_semaphore rwsem;
22241+#ifdef CONFIG_AUFS_DEBUG
22242+ /* just for debugging, not almighty counter */
22243+ atomic_t rcnt, wcnt;
22244+#endif
22245+};
22246+
22247+#ifdef CONFIG_AUFS_DEBUG
22248+#define AuDbgCntInit(rw) do { \
22249+ atomic_set(&(rw)->rcnt, 0); \
22250+ atomic_set(&(rw)->wcnt, 0); \
22251+ smp_mb(); /* atomic set */ \
22252+} while (0)
22253+
e49829fe 22254+#define AuDbgRcntInc(rw) atomic_inc(&(rw)->rcnt)
dece6358 22255+#define AuDbgRcntDec(rw) WARN_ON(atomic_dec_return(&(rw)->rcnt) < 0)
e49829fe 22256+#define AuDbgWcntInc(rw) atomic_inc(&(rw)->wcnt)
dece6358
AM
22257+#define AuDbgWcntDec(rw) WARN_ON(atomic_dec_return(&(rw)->wcnt) < 0)
22258+#else
22259+#define AuDbgCntInit(rw) do {} while (0)
22260+#define AuDbgRcntInc(rw) do {} while (0)
22261+#define AuDbgRcntDec(rw) do {} while (0)
22262+#define AuDbgWcntInc(rw) do {} while (0)
22263+#define AuDbgWcntDec(rw) do {} while (0)
22264+#endif /* CONFIG_AUFS_DEBUG */
22265+
22266+/* to debug easier, do not make them inlined functions */
22267+#define AuRwMustNoWaiters(rw) AuDebugOn(!list_empty(&(rw)->rwsem.wait_list))
22268+/* rwsem_is_locked() is unusable */
22269+#define AuRwMustReadLock(rw) AuDebugOn(atomic_read(&(rw)->rcnt) <= 0)
22270+#define AuRwMustWriteLock(rw) AuDebugOn(atomic_read(&(rw)->wcnt) <= 0)
22271+#define AuRwMustAnyLock(rw) AuDebugOn(atomic_read(&(rw)->rcnt) <= 0 \
22272+ && atomic_read(&(rw)->wcnt) <= 0)
22273+#define AuRwDestroy(rw) AuDebugOn(atomic_read(&(rw)->rcnt) \
22274+ || atomic_read(&(rw)->wcnt))
22275+
e49829fe
JR
22276+#define au_rw_class(rw, key) lockdep_set_class(&(rw)->rwsem, key)
22277+
dece6358
AM
22278+static inline void au_rw_init(struct au_rwsem *rw)
22279+{
22280+ AuDbgCntInit(rw);
22281+ init_rwsem(&rw->rwsem);
22282+}
22283+
22284+static inline void au_rw_init_wlock(struct au_rwsem *rw)
22285+{
22286+ au_rw_init(rw);
22287+ down_write(&rw->rwsem);
22288+ AuDbgWcntInc(rw);
22289+}
22290+
22291+static inline void au_rw_init_wlock_nested(struct au_rwsem *rw,
22292+ unsigned int lsc)
22293+{
22294+ au_rw_init(rw);
22295+ down_write_nested(&rw->rwsem, lsc);
22296+ AuDbgWcntInc(rw);
22297+}
22298+
22299+static inline void au_rw_read_lock(struct au_rwsem *rw)
22300+{
22301+ down_read(&rw->rwsem);
22302+ AuDbgRcntInc(rw);
22303+}
22304+
22305+static inline void au_rw_read_lock_nested(struct au_rwsem *rw, unsigned int lsc)
22306+{
22307+ down_read_nested(&rw->rwsem, lsc);
22308+ AuDbgRcntInc(rw);
22309+}
22310+
22311+static inline void au_rw_read_unlock(struct au_rwsem *rw)
22312+{
22313+ AuRwMustReadLock(rw);
22314+ AuDbgRcntDec(rw);
22315+ up_read(&rw->rwsem);
22316+}
22317+
22318+static inline void au_rw_dgrade_lock(struct au_rwsem *rw)
22319+{
22320+ AuRwMustWriteLock(rw);
22321+ AuDbgRcntInc(rw);
22322+ AuDbgWcntDec(rw);
22323+ downgrade_write(&rw->rwsem);
22324+}
22325+
22326+static inline void au_rw_write_lock(struct au_rwsem *rw)
22327+{
22328+ down_write(&rw->rwsem);
22329+ AuDbgWcntInc(rw);
22330+}
22331+
22332+static inline void au_rw_write_lock_nested(struct au_rwsem *rw,
22333+ unsigned int lsc)
22334+{
22335+ down_write_nested(&rw->rwsem, lsc);
22336+ AuDbgWcntInc(rw);
22337+}
1facf9fc 22338+
dece6358
AM
22339+static inline void au_rw_write_unlock(struct au_rwsem *rw)
22340+{
22341+ AuRwMustWriteLock(rw);
22342+ AuDbgWcntDec(rw);
22343+ up_write(&rw->rwsem);
22344+}
22345+
22346+/* why is not _nested version defined */
22347+static inline int au_rw_read_trylock(struct au_rwsem *rw)
22348+{
22349+ int ret = down_read_trylock(&rw->rwsem);
22350+ if (ret)
22351+ AuDbgRcntInc(rw);
22352+ return ret;
22353+}
22354+
22355+static inline int au_rw_write_trylock(struct au_rwsem *rw)
22356+{
22357+ int ret = down_write_trylock(&rw->rwsem);
22358+ if (ret)
22359+ AuDbgWcntInc(rw);
22360+ return ret;
22361+}
22362+
22363+#undef AuDbgCntInit
22364+#undef AuDbgRcntInc
22365+#undef AuDbgRcntDec
22366+#undef AuDbgWcntInc
22367+#undef AuDbgWcntDec
1facf9fc 22368+
22369+#define AuSimpleLockRwsemFuncs(prefix, param, rwsem) \
22370+static inline void prefix##_read_lock(param) \
dece6358 22371+{ au_rw_read_lock(rwsem); } \
1facf9fc 22372+static inline void prefix##_write_lock(param) \
dece6358 22373+{ au_rw_write_lock(rwsem); } \
1facf9fc 22374+static inline int prefix##_read_trylock(param) \
dece6358 22375+{ return au_rw_read_trylock(rwsem); } \
1facf9fc 22376+static inline int prefix##_write_trylock(param) \
dece6358 22377+{ return au_rw_write_trylock(rwsem); }
1facf9fc 22378+/* why is not _nested version defined */
22379+/* static inline void prefix##_read_trylock_nested(param, lsc)
dece6358 22380+{ au_rw_read_trylock_nested(rwsem, lsc)); }
1facf9fc 22381+static inline void prefix##_write_trylock_nestd(param, lsc)
dece6358 22382+{ au_rw_write_trylock_nested(rwsem, lsc); } */
1facf9fc 22383+
22384+#define AuSimpleUnlockRwsemFuncs(prefix, param, rwsem) \
22385+static inline void prefix##_read_unlock(param) \
dece6358 22386+{ au_rw_read_unlock(rwsem); } \
1facf9fc 22387+static inline void prefix##_write_unlock(param) \
dece6358 22388+{ au_rw_write_unlock(rwsem); } \
1facf9fc 22389+static inline void prefix##_downgrade_lock(param) \
dece6358 22390+{ au_rw_dgrade_lock(rwsem); }
1facf9fc 22391+
22392+#define AuSimpleRwsemFuncs(prefix, param, rwsem) \
22393+ AuSimpleLockRwsemFuncs(prefix, param, rwsem) \
22394+ AuSimpleUnlockRwsemFuncs(prefix, param, rwsem)
22395+
22396+#endif /* __KERNEL__ */
22397+#endif /* __AUFS_RWSEM_H__ */
7f207e10
AM
22398diff -urN /usr/share/empty/fs/aufs/sbinfo.c linux/fs/aufs/sbinfo.c
22399--- /usr/share/empty/fs/aufs/sbinfo.c 1970-01-01 01:00:00.000000000 +0100
537831f9 22400+++ linux/fs/aufs/sbinfo.c 2012-12-13 20:41:10.431460173 +0100
f6c5ef8b 22401@@ -0,0 +1,343 @@
1facf9fc 22402+/*
f6c5ef8b 22403+ * Copyright (C) 2005-2012 Junjiro R. Okajima
1facf9fc 22404+ *
22405+ * This program, aufs is free software; you can redistribute it and/or modify
22406+ * it under the terms of the GNU General Public License as published by
22407+ * the Free Software Foundation; either version 2 of the License, or
22408+ * (at your option) any later version.
dece6358
AM
22409+ *
22410+ * This program is distributed in the hope that it will be useful,
22411+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
22412+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22413+ * GNU General Public License for more details.
22414+ *
22415+ * You should have received a copy of the GNU General Public License
22416+ * along with this program; if not, write to the Free Software
22417+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 22418+ */
22419+
22420+/*
22421+ * superblock private data
22422+ */
22423+
22424+#include "aufs.h"
22425+
22426+/*
22427+ * they are necessary regardless sysfs is disabled.
22428+ */
22429+void au_si_free(struct kobject *kobj)
22430+{
22431+ struct au_sbinfo *sbinfo;
b752ccd1 22432+ char *locked __maybe_unused; /* debug only */
1facf9fc 22433+
22434+ sbinfo = container_of(kobj, struct au_sbinfo, si_kobj);
22435+ AuDebugOn(!list_empty(&sbinfo->si_plink.head));
e49829fe 22436+ AuDebugOn(atomic_read(&sbinfo->si_nowait.nw_len));
1facf9fc 22437+
e49829fe 22438+ au_rw_write_lock(&sbinfo->si_rwsem);
1facf9fc 22439+ au_br_free(sbinfo);
e49829fe 22440+ au_rw_write_unlock(&sbinfo->si_rwsem);
b752ccd1
AM
22441+
22442+ AuDebugOn(radix_tree_gang_lookup
22443+ (&sbinfo->au_si_pid.tree, (void **)&locked,
22444+ /*first_index*/PID_MAX_DEFAULT - 1,
22445+ /*max_items*/sizeof(locked)/sizeof(*locked)));
22446+
1facf9fc 22447+ kfree(sbinfo->si_branch);
b752ccd1 22448+ kfree(sbinfo->au_si_pid.bitmap);
1facf9fc 22449+ mutex_destroy(&sbinfo->si_xib_mtx);
dece6358 22450+ AuRwDestroy(&sbinfo->si_rwsem);
1facf9fc 22451+
22452+ kfree(sbinfo);
22453+}
22454+
22455+int au_si_alloc(struct super_block *sb)
22456+{
22457+ int err;
22458+ struct au_sbinfo *sbinfo;
e49829fe 22459+ static struct lock_class_key aufs_si;
1facf9fc 22460+
22461+ err = -ENOMEM;
4a4d8108 22462+ sbinfo = kzalloc(sizeof(*sbinfo), GFP_NOFS);
1facf9fc 22463+ if (unlikely(!sbinfo))
22464+ goto out;
22465+
b752ccd1
AM
22466+ BUILD_BUG_ON(sizeof(unsigned long) !=
22467+ sizeof(*sbinfo->au_si_pid.bitmap));
22468+ sbinfo->au_si_pid.bitmap = kcalloc(BITS_TO_LONGS(PID_MAX_DEFAULT),
22469+ sizeof(*sbinfo->au_si_pid.bitmap),
22470+ GFP_NOFS);
22471+ if (unlikely(!sbinfo->au_si_pid.bitmap))
22472+ goto out_sbinfo;
22473+
1facf9fc 22474+ /* will be reallocated separately */
22475+ sbinfo->si_branch = kzalloc(sizeof(*sbinfo->si_branch), GFP_NOFS);
22476+ if (unlikely(!sbinfo->si_branch))
b752ccd1 22477+ goto out_pidmap;
1facf9fc 22478+
1facf9fc 22479+ err = sysaufs_si_init(sbinfo);
22480+ if (unlikely(err))
22481+ goto out_br;
22482+
22483+ au_nwt_init(&sbinfo->si_nowait);
dece6358 22484+ au_rw_init_wlock(&sbinfo->si_rwsem);
e49829fe 22485+ au_rw_class(&sbinfo->si_rwsem, &aufs_si);
b752ccd1
AM
22486+ spin_lock_init(&sbinfo->au_si_pid.tree_lock);
22487+ INIT_RADIX_TREE(&sbinfo->au_si_pid.tree, GFP_ATOMIC | __GFP_NOFAIL);
22488+
7f207e10 22489+ atomic_long_set(&sbinfo->si_ninodes, 0);
7f207e10
AM
22490+ atomic_long_set(&sbinfo->si_nfiles, 0);
22491+
1facf9fc 22492+ sbinfo->si_bend = -1;
1facf9fc 22493+
22494+ sbinfo->si_wbr_copyup = AuWbrCopyup_Def;
22495+ sbinfo->si_wbr_create = AuWbrCreate_Def;
4a4d8108
AM
22496+ sbinfo->si_wbr_copyup_ops = au_wbr_copyup_ops + sbinfo->si_wbr_copyup;
22497+ sbinfo->si_wbr_create_ops = au_wbr_create_ops + sbinfo->si_wbr_create;
1facf9fc 22498+
e49829fe 22499+ sbinfo->si_mntflags = au_opts_plink(AuOpt_Def);
1facf9fc 22500+
1facf9fc 22501+ mutex_init(&sbinfo->si_xib_mtx);
1facf9fc 22502+ sbinfo->si_xino_brid = -1;
22503+ /* leave si_xib_last_pindex and si_xib_next_bit */
22504+
e49829fe 22505+ sbinfo->si_rdcache = msecs_to_jiffies(AUFS_RDCACHE_DEF * MSEC_PER_SEC);
1facf9fc 22506+ sbinfo->si_rdblk = AUFS_RDBLK_DEF;
22507+ sbinfo->si_rdhash = AUFS_RDHASH_DEF;
22508+ sbinfo->si_dirwh = AUFS_DIRWH_DEF;
22509+
22510+ au_spl_init(&sbinfo->si_plink);
22511+ init_waitqueue_head(&sbinfo->si_plink_wq);
4a4d8108 22512+ spin_lock_init(&sbinfo->si_plink_maint_lock);
1facf9fc 22513+
22514+ /* leave other members for sysaufs and si_mnt. */
22515+ sbinfo->si_sb = sb;
22516+ sb->s_fs_info = sbinfo;
b752ccd1 22517+ si_pid_set(sb);
1facf9fc 22518+ au_debug_sbinfo_init(sbinfo);
22519+ return 0; /* success */
22520+
4f0767ce 22521+out_br:
1facf9fc 22522+ kfree(sbinfo->si_branch);
4f0767ce 22523+out_pidmap:
b752ccd1 22524+ kfree(sbinfo->au_si_pid.bitmap);
4f0767ce 22525+out_sbinfo:
1facf9fc 22526+ kfree(sbinfo);
4f0767ce 22527+out:
1facf9fc 22528+ return err;
22529+}
22530+
22531+int au_sbr_realloc(struct au_sbinfo *sbinfo, int nbr)
22532+{
22533+ int err, sz;
22534+ struct au_branch **brp;
22535+
dece6358
AM
22536+ AuRwMustWriteLock(&sbinfo->si_rwsem);
22537+
1facf9fc 22538+ err = -ENOMEM;
22539+ sz = sizeof(*brp) * (sbinfo->si_bend + 1);
22540+ if (unlikely(!sz))
22541+ sz = sizeof(*brp);
22542+ brp = au_kzrealloc(sbinfo->si_branch, sz, sizeof(*brp) * nbr, GFP_NOFS);
22543+ if (brp) {
22544+ sbinfo->si_branch = brp;
22545+ err = 0;
22546+ }
22547+
22548+ return err;
22549+}
22550+
22551+/* ---------------------------------------------------------------------- */
22552+
22553+unsigned int au_sigen_inc(struct super_block *sb)
22554+{
22555+ unsigned int gen;
22556+
dece6358
AM
22557+ SiMustWriteLock(sb);
22558+
1facf9fc 22559+ gen = ++au_sbi(sb)->si_generation;
22560+ au_update_digen(sb->s_root);
537831f9 22561+ au_update_iigen(sb->s_root->d_inode, /*half*/0);
1facf9fc 22562+ sb->s_root->d_inode->i_version++;
22563+ return gen;
22564+}
22565+
22566+aufs_bindex_t au_new_br_id(struct super_block *sb)
22567+{
22568+ aufs_bindex_t br_id;
22569+ int i;
22570+ struct au_sbinfo *sbinfo;
22571+
dece6358
AM
22572+ SiMustWriteLock(sb);
22573+
1facf9fc 22574+ sbinfo = au_sbi(sb);
22575+ for (i = 0; i <= AUFS_BRANCH_MAX; i++) {
22576+ br_id = ++sbinfo->si_last_br_id;
7f207e10 22577+ AuDebugOn(br_id < 0);
1facf9fc 22578+ if (br_id && au_br_index(sb, br_id) < 0)
22579+ return br_id;
22580+ }
22581+
22582+ return -1;
22583+}
22584+
22585+/* ---------------------------------------------------------------------- */
22586+
e49829fe
JR
22587+/* it is ok that new 'nwt' tasks are appended while we are sleeping */
22588+int si_read_lock(struct super_block *sb, int flags)
22589+{
22590+ int err;
22591+
22592+ err = 0;
22593+ if (au_ftest_lock(flags, FLUSH))
22594+ au_nwt_flush(&au_sbi(sb)->si_nowait);
22595+
22596+ si_noflush_read_lock(sb);
22597+ err = au_plink_maint(sb, flags);
22598+ if (unlikely(err))
22599+ si_read_unlock(sb);
22600+
22601+ return err;
22602+}
22603+
22604+int si_write_lock(struct super_block *sb, int flags)
22605+{
22606+ int err;
22607+
22608+ if (au_ftest_lock(flags, FLUSH))
22609+ au_nwt_flush(&au_sbi(sb)->si_nowait);
22610+
22611+ si_noflush_write_lock(sb);
22612+ err = au_plink_maint(sb, flags);
22613+ if (unlikely(err))
22614+ si_write_unlock(sb);
22615+
22616+ return err;
22617+}
22618+
1facf9fc 22619+/* dentry and super_block lock. call at entry point */
e49829fe 22620+int aufs_read_lock(struct dentry *dentry, int flags)
1facf9fc 22621+{
e49829fe 22622+ int err;
027c5e7a 22623+ struct super_block *sb;
e49829fe 22624+
027c5e7a
AM
22625+ sb = dentry->d_sb;
22626+ err = si_read_lock(sb, flags);
22627+ if (unlikely(err))
22628+ goto out;
22629+
22630+ if (au_ftest_lock(flags, DW))
22631+ di_write_lock_child(dentry);
22632+ else
22633+ di_read_lock_child(dentry, flags);
22634+
22635+ if (au_ftest_lock(flags, GEN)) {
22636+ err = au_digen_test(dentry, au_sigen(sb));
22637+ AuDebugOn(!err && au_dbrange_test(dentry));
22638+ if (unlikely(err))
22639+ aufs_read_unlock(dentry, flags);
e49829fe
JR
22640+ }
22641+
027c5e7a 22642+out:
e49829fe 22643+ return err;
1facf9fc 22644+}
22645+
22646+void aufs_read_unlock(struct dentry *dentry, int flags)
22647+{
22648+ if (au_ftest_lock(flags, DW))
22649+ di_write_unlock(dentry);
22650+ else
22651+ di_read_unlock(dentry, flags);
22652+ si_read_unlock(dentry->d_sb);
22653+}
22654+
22655+void aufs_write_lock(struct dentry *dentry)
22656+{
e49829fe 22657+ si_write_lock(dentry->d_sb, AuLock_FLUSH | AuLock_NOPLMW);
1facf9fc 22658+ di_write_lock_child(dentry);
22659+}
22660+
22661+void aufs_write_unlock(struct dentry *dentry)
22662+{
22663+ di_write_unlock(dentry);
22664+ si_write_unlock(dentry->d_sb);
22665+}
22666+
e49829fe 22667+int aufs_read_and_write_lock2(struct dentry *d1, struct dentry *d2, int flags)
1facf9fc 22668+{
e49829fe 22669+ int err;
027c5e7a
AM
22670+ unsigned int sigen;
22671+ struct super_block *sb;
e49829fe 22672+
027c5e7a
AM
22673+ sb = d1->d_sb;
22674+ err = si_read_lock(sb, flags);
22675+ if (unlikely(err))
22676+ goto out;
22677+
22678+ di_write_lock2_child(d1, d2, au_ftest_lock(flags, DIR));
22679+
22680+ if (au_ftest_lock(flags, GEN)) {
22681+ sigen = au_sigen(sb);
22682+ err = au_digen_test(d1, sigen);
22683+ AuDebugOn(!err && au_dbrange_test(d1));
22684+ if (!err) {
22685+ err = au_digen_test(d2, sigen);
22686+ AuDebugOn(!err && au_dbrange_test(d2));
22687+ }
22688+ if (unlikely(err))
22689+ aufs_read_and_write_unlock2(d1, d2);
22690+ }
22691+
22692+out:
e49829fe 22693+ return err;
1facf9fc 22694+}
22695+
22696+void aufs_read_and_write_unlock2(struct dentry *d1, struct dentry *d2)
22697+{
22698+ di_write_unlock2(d1, d2);
22699+ si_read_unlock(d1->d_sb);
22700+}
b752ccd1
AM
22701+
22702+/* ---------------------------------------------------------------------- */
22703+
22704+int si_pid_test_slow(struct super_block *sb)
22705+{
22706+ void *p;
22707+
22708+ rcu_read_lock();
22709+ p = radix_tree_lookup(&au_sbi(sb)->au_si_pid.tree, current->pid);
22710+ rcu_read_unlock();
22711+
027c5e7a 22712+ return (long)!!p;
b752ccd1
AM
22713+}
22714+
22715+void si_pid_set_slow(struct super_block *sb)
22716+{
22717+ int err;
22718+ struct au_sbinfo *sbinfo;
22719+
22720+ AuDebugOn(si_pid_test_slow(sb));
22721+
22722+ sbinfo = au_sbi(sb);
22723+ err = radix_tree_preload(GFP_NOFS | __GFP_NOFAIL);
22724+ AuDebugOn(err);
22725+ spin_lock(&sbinfo->au_si_pid.tree_lock);
22726+ err = radix_tree_insert(&sbinfo->au_si_pid.tree, current->pid,
027c5e7a 22727+ /*any valid ptr*/sb);
b752ccd1
AM
22728+ spin_unlock(&sbinfo->au_si_pid.tree_lock);
22729+ AuDebugOn(err);
22730+ radix_tree_preload_end();
22731+}
22732+
22733+void si_pid_clr_slow(struct super_block *sb)
22734+{
22735+ void *p;
22736+ struct au_sbinfo *sbinfo;
22737+
22738+ AuDebugOn(!si_pid_test_slow(sb));
22739+
22740+ sbinfo = au_sbi(sb);
22741+ spin_lock(&sbinfo->au_si_pid.tree_lock);
22742+ p = radix_tree_delete(&sbinfo->au_si_pid.tree, current->pid);
22743+ spin_unlock(&sbinfo->au_si_pid.tree_lock);
b752ccd1 22744+}
7f207e10
AM
22745diff -urN /usr/share/empty/fs/aufs/spl.h linux/fs/aufs/spl.h
22746--- /usr/share/empty/fs/aufs/spl.h 1970-01-01 01:00:00.000000000 +0100
537831f9 22747+++ linux/fs/aufs/spl.h 2012-12-13 20:41:10.431460173 +0100
f6c5ef8b 22748@@ -0,0 +1,62 @@
1facf9fc 22749+/*
f6c5ef8b 22750+ * Copyright (C) 2005-2012 Junjiro R. Okajima
1facf9fc 22751+ *
22752+ * This program, aufs is free software; you can redistribute it and/or modify
22753+ * it under the terms of the GNU General Public License as published by
22754+ * the Free Software Foundation; either version 2 of the License, or
22755+ * (at your option) any later version.
dece6358
AM
22756+ *
22757+ * This program is distributed in the hope that it will be useful,
22758+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
22759+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22760+ * GNU General Public License for more details.
22761+ *
22762+ * You should have received a copy of the GNU General Public License
22763+ * along with this program; if not, write to the Free Software
22764+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 22765+ */
22766+
22767+/*
22768+ * simple list protected by a spinlock
22769+ */
22770+
22771+#ifndef __AUFS_SPL_H__
22772+#define __AUFS_SPL_H__
22773+
22774+#ifdef __KERNEL__
22775+
1facf9fc 22776+struct au_splhead {
22777+ spinlock_t spin;
22778+ struct list_head head;
22779+};
22780+
22781+static inline void au_spl_init(struct au_splhead *spl)
22782+{
22783+ spin_lock_init(&spl->spin);
22784+ INIT_LIST_HEAD(&spl->head);
22785+}
22786+
22787+static inline void au_spl_add(struct list_head *list, struct au_splhead *spl)
22788+{
22789+ spin_lock(&spl->spin);
22790+ list_add(list, &spl->head);
22791+ spin_unlock(&spl->spin);
22792+}
22793+
22794+static inline void au_spl_del(struct list_head *list, struct au_splhead *spl)
22795+{
22796+ spin_lock(&spl->spin);
22797+ list_del(list);
22798+ spin_unlock(&spl->spin);
22799+}
22800+
4a4d8108
AM
22801+static inline void au_spl_del_rcu(struct list_head *list,
22802+ struct au_splhead *spl)
22803+{
22804+ spin_lock(&spl->spin);
22805+ list_del_rcu(list);
22806+ spin_unlock(&spl->spin);
22807+}
22808+
1facf9fc 22809+#endif /* __KERNEL__ */
22810+#endif /* __AUFS_SPL_H__ */
7f207e10
AM
22811diff -urN /usr/share/empty/fs/aufs/super.c linux/fs/aufs/super.c
22812--- /usr/share/empty/fs/aufs/super.c 1970-01-01 01:00:00.000000000 +0100
537831f9
AM
22813+++ linux/fs/aufs/super.c 2012-12-13 20:41:10.431460173 +0100
22814@@ -0,0 +1,993 @@
1facf9fc 22815+/*
f6c5ef8b 22816+ * Copyright (C) 2005-2012 Junjiro R. Okajima
1facf9fc 22817+ *
22818+ * This program, aufs is free software; you can redistribute it and/or modify
22819+ * it under the terms of the GNU General Public License as published by
22820+ * the Free Software Foundation; either version 2 of the License, or
22821+ * (at your option) any later version.
dece6358
AM
22822+ *
22823+ * This program is distributed in the hope that it will be useful,
22824+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
22825+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22826+ * GNU General Public License for more details.
22827+ *
22828+ * You should have received a copy of the GNU General Public License
22829+ * along with this program; if not, write to the Free Software
22830+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 22831+ */
22832+
22833+/*
22834+ * mount and super_block operations
22835+ */
22836+
f6c5ef8b 22837+#include <linux/mm.h>
dece6358 22838+#include <linux/module.h>
1facf9fc 22839+#include <linux/seq_file.h>
22840+#include <linux/statfs.h>
7f207e10
AM
22841+#include <linux/vmalloc.h>
22842+#include <linux/writeback.h>
1facf9fc 22843+#include "aufs.h"
22844+
22845+/*
22846+ * super_operations
22847+ */
22848+static struct inode *aufs_alloc_inode(struct super_block *sb __maybe_unused)
22849+{
22850+ struct au_icntnr *c;
22851+
22852+ c = au_cache_alloc_icntnr();
22853+ if (c) {
027c5e7a 22854+ au_icntnr_init(c);
1facf9fc 22855+ c->vfs_inode.i_version = 1; /* sigen(sb); */
22856+ c->iinfo.ii_hinode = NULL;
22857+ return &c->vfs_inode;
22858+ }
22859+ return NULL;
22860+}
22861+
027c5e7a
AM
22862+static void aufs_destroy_inode_cb(struct rcu_head *head)
22863+{
22864+ struct inode *inode = container_of(head, struct inode, i_rcu);
22865+
b4510431 22866+ INIT_HLIST_HEAD(&inode->i_dentry);
027c5e7a
AM
22867+ au_cache_free_icntnr(container_of(inode, struct au_icntnr, vfs_inode));
22868+}
22869+
1facf9fc 22870+static void aufs_destroy_inode(struct inode *inode)
22871+{
22872+ au_iinfo_fin(inode);
027c5e7a 22873+ call_rcu(&inode->i_rcu, aufs_destroy_inode_cb);
1facf9fc 22874+}
22875+
22876+struct inode *au_iget_locked(struct super_block *sb, ino_t ino)
22877+{
22878+ struct inode *inode;
22879+ int err;
22880+
22881+ inode = iget_locked(sb, ino);
22882+ if (unlikely(!inode)) {
22883+ inode = ERR_PTR(-ENOMEM);
22884+ goto out;
22885+ }
22886+ if (!(inode->i_state & I_NEW))
22887+ goto out;
22888+
22889+ err = au_xigen_new(inode);
22890+ if (!err)
22891+ err = au_iinfo_init(inode);
22892+ if (!err)
22893+ inode->i_version++;
22894+ else {
22895+ iget_failed(inode);
22896+ inode = ERR_PTR(err);
22897+ }
22898+
4f0767ce 22899+out:
1facf9fc 22900+ /* never return NULL */
22901+ AuDebugOn(!inode);
22902+ AuTraceErrPtr(inode);
22903+ return inode;
22904+}
22905+
22906+/* lock free root dinfo */
22907+static int au_show_brs(struct seq_file *seq, struct super_block *sb)
22908+{
22909+ int err;
22910+ aufs_bindex_t bindex, bend;
22911+ struct path path;
4a4d8108 22912+ struct au_hdentry *hdp;
1facf9fc 22913+ struct au_branch *br;
1e00d052 22914+ char *perm;
1facf9fc 22915+
22916+ err = 0;
22917+ bend = au_sbend(sb);
4a4d8108 22918+ hdp = au_di(sb->s_root)->di_hdentry;
1facf9fc 22919+ for (bindex = 0; !err && bindex <= bend; bindex++) {
22920+ br = au_sbr(sb, bindex);
22921+ path.mnt = br->br_mnt;
4a4d8108 22922+ path.dentry = hdp[bindex].hd_dentry;
1facf9fc 22923+ err = au_seq_path(seq, &path);
1e00d052
AM
22924+ if (err > 0) {
22925+ perm = au_optstr_br_perm(br->br_perm);
22926+ if (perm) {
22927+ err = seq_printf(seq, "=%s", perm);
22928+ kfree(perm);
22929+ if (err == -1)
22930+ err = -E2BIG;
22931+ } else
22932+ err = -ENOMEM;
22933+ }
1facf9fc 22934+ if (!err && bindex != bend)
22935+ err = seq_putc(seq, ':');
22936+ }
22937+
22938+ return err;
22939+}
22940+
22941+static void au_show_wbr_create(struct seq_file *m, int v,
22942+ struct au_sbinfo *sbinfo)
22943+{
22944+ const char *pat;
22945+
dece6358
AM
22946+ AuRwMustAnyLock(&sbinfo->si_rwsem);
22947+
1facf9fc 22948+ seq_printf(m, ",create=");
22949+ pat = au_optstr_wbr_create(v);
22950+ switch (v) {
22951+ case AuWbrCreate_TDP:
22952+ case AuWbrCreate_RR:
22953+ case AuWbrCreate_MFS:
22954+ case AuWbrCreate_PMFS:
22955+ seq_printf(m, pat);
22956+ break;
22957+ case AuWbrCreate_MFSV:
22958+ seq_printf(m, /*pat*/"mfs:%lu",
e49829fe
JR
22959+ jiffies_to_msecs(sbinfo->si_wbr_mfs.mfs_expire)
22960+ / MSEC_PER_SEC);
1facf9fc 22961+ break;
22962+ case AuWbrCreate_PMFSV:
22963+ seq_printf(m, /*pat*/"pmfs:%lu",
e49829fe
JR
22964+ jiffies_to_msecs(sbinfo->si_wbr_mfs.mfs_expire)
22965+ / MSEC_PER_SEC);
1facf9fc 22966+ break;
22967+ case AuWbrCreate_MFSRR:
22968+ seq_printf(m, /*pat*/"mfsrr:%llu",
22969+ sbinfo->si_wbr_mfs.mfsrr_watermark);
22970+ break;
22971+ case AuWbrCreate_MFSRRV:
22972+ seq_printf(m, /*pat*/"mfsrr:%llu:%lu",
22973+ sbinfo->si_wbr_mfs.mfsrr_watermark,
e49829fe
JR
22974+ jiffies_to_msecs(sbinfo->si_wbr_mfs.mfs_expire)
22975+ / MSEC_PER_SEC);
1facf9fc 22976+ break;
22977+ }
22978+}
22979+
7eafdf33 22980+static int au_show_xino(struct seq_file *seq, struct super_block *sb)
1facf9fc 22981+{
22982+#ifdef CONFIG_SYSFS
22983+ return 0;
22984+#else
22985+ int err;
22986+ const int len = sizeof(AUFS_XINO_FNAME) - 1;
22987+ aufs_bindex_t bindex, brid;
1facf9fc 22988+ struct qstr *name;
22989+ struct file *f;
22990+ struct dentry *d, *h_root;
4a4d8108 22991+ struct au_hdentry *hdp;
1facf9fc 22992+
dece6358
AM
22993+ AuRwMustAnyLock(&sbinfo->si_rwsem);
22994+
1facf9fc 22995+ err = 0;
1facf9fc 22996+ f = au_sbi(sb)->si_xib;
22997+ if (!f)
22998+ goto out;
22999+
23000+ /* stop printing the default xino path on the first writable branch */
23001+ h_root = NULL;
23002+ brid = au_xino_brid(sb);
23003+ if (brid >= 0) {
23004+ bindex = au_br_index(sb, brid);
4a4d8108
AM
23005+ hdp = au_di(sb->s_root)->di_hdentry;
23006+ h_root = hdp[0 + bindex].hd_dentry;
1facf9fc 23007+ }
23008+ d = f->f_dentry;
23009+ name = &d->d_name;
23010+ /* safe ->d_parent because the file is unlinked */
23011+ if (d->d_parent == h_root
23012+ && name->len == len
23013+ && !memcmp(name->name, AUFS_XINO_FNAME, len))
23014+ goto out;
23015+
23016+ seq_puts(seq, ",xino=");
23017+ err = au_xino_path(seq, f);
23018+
4f0767ce 23019+out:
1facf9fc 23020+ return err;
23021+#endif
23022+}
23023+
23024+/* seq_file will re-call me in case of too long string */
7eafdf33 23025+static int aufs_show_options(struct seq_file *m, struct dentry *dentry)
1facf9fc 23026+{
027c5e7a 23027+ int err;
1facf9fc 23028+ unsigned int mnt_flags, v;
23029+ struct super_block *sb;
23030+ struct au_sbinfo *sbinfo;
23031+
23032+#define AuBool(name, str) do { \
23033+ v = au_opt_test(mnt_flags, name); \
23034+ if (v != au_opt_test(AuOpt_Def, name)) \
23035+ seq_printf(m, ",%s" #str, v ? "" : "no"); \
23036+} while (0)
23037+
23038+#define AuStr(name, str) do { \
23039+ v = mnt_flags & AuOptMask_##name; \
23040+ if (v != (AuOpt_Def & AuOptMask_##name)) \
23041+ seq_printf(m, "," #str "=%s", au_optstr_##str(v)); \
23042+} while (0)
23043+
23044+#define AuUInt(name, str, val) do { \
23045+ if (val != AUFS_##name##_DEF) \
23046+ seq_printf(m, "," #str "=%u", val); \
23047+} while (0)
23048+
23049+ /* lock free root dinfo */
7eafdf33 23050+ sb = dentry->d_sb;
1facf9fc 23051+ si_noflush_read_lock(sb);
23052+ sbinfo = au_sbi(sb);
23053+ seq_printf(m, ",si=%lx", sysaufs_si_id(sbinfo));
23054+
23055+ mnt_flags = au_mntflags(sb);
23056+ if (au_opt_test(mnt_flags, XINO)) {
7eafdf33 23057+ err = au_show_xino(m, sb);
1facf9fc 23058+ if (unlikely(err))
23059+ goto out;
23060+ } else
23061+ seq_puts(m, ",noxino");
23062+
23063+ AuBool(TRUNC_XINO, trunc_xino);
23064+ AuStr(UDBA, udba);
dece6358 23065+ AuBool(SHWH, shwh);
1facf9fc 23066+ AuBool(PLINK, plink);
4a4d8108 23067+ AuBool(DIO, dio);
1facf9fc 23068+ /* AuBool(DIRPERM1, dirperm1); */
23069+ /* AuBool(REFROF, refrof); */
23070+
23071+ v = sbinfo->si_wbr_create;
23072+ if (v != AuWbrCreate_Def)
23073+ au_show_wbr_create(m, v, sbinfo);
23074+
23075+ v = sbinfo->si_wbr_copyup;
23076+ if (v != AuWbrCopyup_Def)
23077+ seq_printf(m, ",cpup=%s", au_optstr_wbr_copyup(v));
23078+
23079+ v = au_opt_test(mnt_flags, ALWAYS_DIROPQ);
23080+ if (v != au_opt_test(AuOpt_Def, ALWAYS_DIROPQ))
23081+ seq_printf(m, ",diropq=%c", v ? 'a' : 'w');
23082+
23083+ AuUInt(DIRWH, dirwh, sbinfo->si_dirwh);
23084+
027c5e7a
AM
23085+ v = jiffies_to_msecs(sbinfo->si_rdcache) / MSEC_PER_SEC;
23086+ AuUInt(RDCACHE, rdcache, v);
1facf9fc 23087+
23088+ AuUInt(RDBLK, rdblk, sbinfo->si_rdblk);
23089+ AuUInt(RDHASH, rdhash, sbinfo->si_rdhash);
23090+
23091+ AuBool(SUM, sum);
23092+ /* AuBool(SUM_W, wsum); */
23093+ AuBool(WARN_PERM, warn_perm);
23094+ AuBool(VERBOSE, verbose);
23095+
4f0767ce 23096+out:
1facf9fc 23097+ /* be sure to print "br:" last */
23098+ if (!sysaufs_brs) {
23099+ seq_puts(m, ",br:");
23100+ au_show_brs(m, sb);
23101+ }
23102+ si_read_unlock(sb);
23103+ return 0;
23104+
1facf9fc 23105+#undef AuBool
23106+#undef AuStr
4a4d8108 23107+#undef AuUInt
1facf9fc 23108+}
23109+
23110+/* ---------------------------------------------------------------------- */
23111+
23112+/* sum mode which returns the summation for statfs(2) */
23113+
23114+static u64 au_add_till_max(u64 a, u64 b)
23115+{
23116+ u64 old;
23117+
23118+ old = a;
23119+ a += b;
92d182d2
AM
23120+ if (old <= a)
23121+ return a;
23122+ return ULLONG_MAX;
23123+}
23124+
23125+static u64 au_mul_till_max(u64 a, long mul)
23126+{
23127+ u64 old;
23128+
23129+ old = a;
23130+ a *= mul;
23131+ if (old <= a)
1facf9fc 23132+ return a;
23133+ return ULLONG_MAX;
23134+}
23135+
23136+static int au_statfs_sum(struct super_block *sb, struct kstatfs *buf)
23137+{
23138+ int err;
92d182d2 23139+ long bsize, factor;
1facf9fc 23140+ u64 blocks, bfree, bavail, files, ffree;
23141+ aufs_bindex_t bend, bindex, i;
23142+ unsigned char shared;
7f207e10 23143+ struct path h_path;
1facf9fc 23144+ struct super_block *h_sb;
23145+
92d182d2
AM
23146+ err = 0;
23147+ bsize = LONG_MAX;
23148+ files = 0;
23149+ ffree = 0;
1facf9fc 23150+ blocks = 0;
23151+ bfree = 0;
23152+ bavail = 0;
1facf9fc 23153+ bend = au_sbend(sb);
92d182d2 23154+ for (bindex = 0; bindex <= bend; bindex++) {
7f207e10
AM
23155+ h_path.mnt = au_sbr_mnt(sb, bindex);
23156+ h_sb = h_path.mnt->mnt_sb;
1facf9fc 23157+ shared = 0;
92d182d2 23158+ for (i = 0; !shared && i < bindex; i++)
1facf9fc 23159+ shared = (au_sbr_sb(sb, i) == h_sb);
23160+ if (shared)
23161+ continue;
23162+
23163+ /* sb->s_root for NFS is unreliable */
7f207e10
AM
23164+ h_path.dentry = h_path.mnt->mnt_root;
23165+ err = vfs_statfs(&h_path, buf);
1facf9fc 23166+ if (unlikely(err))
23167+ goto out;
23168+
92d182d2
AM
23169+ if (bsize > buf->f_bsize) {
23170+ /*
23171+ * we will reduce bsize, so we have to expand blocks
23172+ * etc. to match them again
23173+ */
23174+ factor = (bsize / buf->f_bsize);
23175+ blocks = au_mul_till_max(blocks, factor);
23176+ bfree = au_mul_till_max(bfree, factor);
23177+ bavail = au_mul_till_max(bavail, factor);
23178+ bsize = buf->f_bsize;
23179+ }
23180+
23181+ factor = (buf->f_bsize / bsize);
23182+ blocks = au_add_till_max(blocks,
23183+ au_mul_till_max(buf->f_blocks, factor));
23184+ bfree = au_add_till_max(bfree,
23185+ au_mul_till_max(buf->f_bfree, factor));
23186+ bavail = au_add_till_max(bavail,
23187+ au_mul_till_max(buf->f_bavail, factor));
1facf9fc 23188+ files = au_add_till_max(files, buf->f_files);
23189+ ffree = au_add_till_max(ffree, buf->f_ffree);
23190+ }
23191+
92d182d2 23192+ buf->f_bsize = bsize;
1facf9fc 23193+ buf->f_blocks = blocks;
23194+ buf->f_bfree = bfree;
23195+ buf->f_bavail = bavail;
23196+ buf->f_files = files;
23197+ buf->f_ffree = ffree;
92d182d2 23198+ buf->f_frsize = 0;
1facf9fc 23199+
4f0767ce 23200+out:
1facf9fc 23201+ return err;
23202+}
23203+
23204+static int aufs_statfs(struct dentry *dentry, struct kstatfs *buf)
23205+{
23206+ int err;
7f207e10 23207+ struct path h_path;
1facf9fc 23208+ struct super_block *sb;
23209+
23210+ /* lock free root dinfo */
23211+ sb = dentry->d_sb;
23212+ si_noflush_read_lock(sb);
7f207e10 23213+ if (!au_opt_test(au_mntflags(sb), SUM)) {
1facf9fc 23214+ /* sb->s_root for NFS is unreliable */
7f207e10
AM
23215+ h_path.mnt = au_sbr_mnt(sb, 0);
23216+ h_path.dentry = h_path.mnt->mnt_root;
23217+ err = vfs_statfs(&h_path, buf);
23218+ } else
1facf9fc 23219+ err = au_statfs_sum(sb, buf);
23220+ si_read_unlock(sb);
23221+
23222+ if (!err) {
23223+ buf->f_type = AUFS_SUPER_MAGIC;
4a4d8108 23224+ buf->f_namelen = AUFS_MAX_NAMELEN;
1facf9fc 23225+ memset(&buf->f_fsid, 0, sizeof(buf->f_fsid));
23226+ }
23227+ /* buf->f_bsize = buf->f_blocks = buf->f_bfree = buf->f_bavail = -1; */
23228+
23229+ return err;
23230+}
23231+
23232+/* ---------------------------------------------------------------------- */
23233+
537831f9
AM
23234+static int aufs_sync_fs(struct super_block *sb, int wait)
23235+{
23236+ int err, e;
23237+ aufs_bindex_t bend, bindex;
23238+ struct au_branch *br;
23239+ struct super_block *h_sb;
23240+
23241+ err = 0;
23242+ si_noflush_read_lock(sb);
23243+ bend = au_sbend(sb);
23244+ for (bindex = 0; bindex <= bend; bindex++) {
23245+ br = au_sbr(sb, bindex);
23246+ if (!au_br_writable(br->br_perm))
23247+ continue;
23248+
23249+ h_sb = au_sbr_sb(sb, bindex);
23250+ if (h_sb->s_op->sync_fs) {
23251+ e = h_sb->s_op->sync_fs(h_sb, wait);
23252+ if (unlikely(e && !err))
23253+ err = e;
23254+ /* go on even if an error happens */
23255+ }
23256+ }
23257+ si_read_unlock(sb);
23258+
23259+ return err;
23260+}
23261+
23262+/* ---------------------------------------------------------------------- */
23263+
1facf9fc 23264+/* final actions when unmounting a file system */
23265+static void aufs_put_super(struct super_block *sb)
23266+{
23267+ struct au_sbinfo *sbinfo;
23268+
23269+ sbinfo = au_sbi(sb);
23270+ if (!sbinfo)
23271+ return;
23272+
1facf9fc 23273+ dbgaufs_si_fin(sbinfo);
23274+ kobject_put(&sbinfo->si_kobj);
23275+}
23276+
23277+/* ---------------------------------------------------------------------- */
23278+
7f207e10
AM
23279+void au_array_free(void *array)
23280+{
23281+ if (array) {
23282+ if (!is_vmalloc_addr(array))
23283+ kfree(array);
23284+ else
23285+ vfree(array);
23286+ }
23287+}
23288+
23289+void *au_array_alloc(unsigned long long *hint, au_arraycb_t cb, void *arg)
23290+{
23291+ void *array;
23292+ unsigned long long n;
23293+
23294+ array = NULL;
23295+ n = 0;
23296+ if (!*hint)
23297+ goto out;
23298+
23299+ if (*hint > ULLONG_MAX / sizeof(array)) {
23300+ array = ERR_PTR(-EMFILE);
23301+ pr_err("hint %llu\n", *hint);
23302+ goto out;
23303+ }
23304+
23305+ array = kmalloc(sizeof(array) * *hint, GFP_NOFS);
23306+ if (unlikely(!array))
23307+ array = vmalloc(sizeof(array) * *hint);
23308+ if (unlikely(!array)) {
23309+ array = ERR_PTR(-ENOMEM);
23310+ goto out;
23311+ }
23312+
23313+ n = cb(array, *hint, arg);
23314+ AuDebugOn(n > *hint);
23315+
23316+out:
23317+ *hint = n;
23318+ return array;
23319+}
23320+
23321+static unsigned long long au_iarray_cb(void *a,
23322+ unsigned long long max __maybe_unused,
23323+ void *arg)
23324+{
23325+ unsigned long long n;
23326+ struct inode **p, *inode;
23327+ struct list_head *head;
23328+
23329+ n = 0;
23330+ p = a;
23331+ head = arg;
2cbb1c4b 23332+ spin_lock(&inode_sb_list_lock);
7f207e10
AM
23333+ list_for_each_entry(inode, head, i_sb_list) {
23334+ if (!is_bad_inode(inode)
23335+ && au_ii(inode)->ii_bstart >= 0) {
2cbb1c4b
JR
23336+ spin_lock(&inode->i_lock);
23337+ if (atomic_read(&inode->i_count)) {
23338+ au_igrab(inode);
23339+ *p++ = inode;
23340+ n++;
23341+ AuDebugOn(n > max);
23342+ }
23343+ spin_unlock(&inode->i_lock);
7f207e10
AM
23344+ }
23345+ }
2cbb1c4b 23346+ spin_unlock(&inode_sb_list_lock);
7f207e10
AM
23347+
23348+ return n;
23349+}
23350+
23351+struct inode **au_iarray_alloc(struct super_block *sb, unsigned long long *max)
23352+{
23353+ *max = atomic_long_read(&au_sbi(sb)->si_ninodes);
23354+ return au_array_alloc(max, au_iarray_cb, &sb->s_inodes);
23355+}
23356+
23357+void au_iarray_free(struct inode **a, unsigned long long max)
23358+{
23359+ unsigned long long ull;
23360+
23361+ for (ull = 0; ull < max; ull++)
23362+ iput(a[ull]);
23363+ au_array_free(a);
23364+}
23365+
23366+/* ---------------------------------------------------------------------- */
23367+
1facf9fc 23368+/*
23369+ * refresh dentry and inode at remount time.
23370+ */
027c5e7a
AM
23371+/* todo: consolidate with simple_reval_dpath() and au_reval_for_attr() */
23372+static int au_do_refresh(struct dentry *dentry, unsigned int dir_flags,
23373+ struct dentry *parent)
1facf9fc 23374+{
23375+ int err;
1facf9fc 23376+
23377+ di_write_lock_child(dentry);
1facf9fc 23378+ di_read_lock_parent(parent, AuLock_IR);
027c5e7a
AM
23379+ err = au_refresh_dentry(dentry, parent);
23380+ if (!err && dir_flags)
23381+ au_hn_reset(dentry->d_inode, dir_flags);
1facf9fc 23382+ di_read_unlock(parent, AuLock_IR);
1facf9fc 23383+ di_write_unlock(dentry);
23384+
23385+ return err;
23386+}
23387+
027c5e7a
AM
23388+static int au_do_refresh_d(struct dentry *dentry, unsigned int sigen,
23389+ struct au_sbinfo *sbinfo,
23390+ const unsigned int dir_flags)
1facf9fc 23391+{
027c5e7a
AM
23392+ int err;
23393+ struct dentry *parent;
23394+ struct inode *inode;
23395+
23396+ err = 0;
23397+ parent = dget_parent(dentry);
23398+ if (!au_digen_test(parent, sigen) && au_digen_test(dentry, sigen)) {
23399+ inode = dentry->d_inode;
23400+ if (inode) {
23401+ if (!S_ISDIR(inode->i_mode))
23402+ err = au_do_refresh(dentry, /*dir_flags*/0,
23403+ parent);
23404+ else {
23405+ err = au_do_refresh(dentry, dir_flags, parent);
23406+ if (unlikely(err))
23407+ au_fset_si(sbinfo, FAILED_REFRESH_DIR);
23408+ }
23409+ } else
23410+ err = au_do_refresh(dentry, /*dir_flags*/0, parent);
23411+ AuDbgDentry(dentry);
23412+ }
23413+ dput(parent);
23414+
23415+ AuTraceErr(err);
23416+ return err;
1facf9fc 23417+}
23418+
027c5e7a 23419+static int au_refresh_d(struct super_block *sb)
1facf9fc 23420+{
23421+ int err, i, j, ndentry, e;
027c5e7a 23422+ unsigned int sigen;
1facf9fc 23423+ struct au_dcsub_pages dpages;
23424+ struct au_dpage *dpage;
027c5e7a
AM
23425+ struct dentry **dentries, *d;
23426+ struct au_sbinfo *sbinfo;
23427+ struct dentry *root = sb->s_root;
23428+ const unsigned int dir_flags = au_hi_flags(root->d_inode, /*isdir*/1);
1facf9fc 23429+
027c5e7a
AM
23430+ err = au_dpages_init(&dpages, GFP_NOFS);
23431+ if (unlikely(err))
1facf9fc 23432+ goto out;
027c5e7a
AM
23433+ err = au_dcsub_pages(&dpages, root, NULL, NULL);
23434+ if (unlikely(err))
1facf9fc 23435+ goto out_dpages;
1facf9fc 23436+
027c5e7a
AM
23437+ sigen = au_sigen(sb);
23438+ sbinfo = au_sbi(sb);
23439+ for (i = 0; i < dpages.ndpage; i++) {
1facf9fc 23440+ dpage = dpages.dpages + i;
23441+ dentries = dpage->dentries;
23442+ ndentry = dpage->ndentry;
027c5e7a 23443+ for (j = 0; j < ndentry; j++) {
1facf9fc 23444+ d = dentries[j];
027c5e7a
AM
23445+ e = au_do_refresh_d(d, sigen, sbinfo, dir_flags);
23446+ if (unlikely(e && !err))
23447+ err = e;
23448+ /* go on even err */
1facf9fc 23449+ }
23450+ }
23451+
4f0767ce 23452+out_dpages:
1facf9fc 23453+ au_dpages_free(&dpages);
4f0767ce 23454+out:
1facf9fc 23455+ return err;
23456+}
23457+
027c5e7a 23458+static int au_refresh_i(struct super_block *sb)
1facf9fc 23459+{
027c5e7a
AM
23460+ int err, e;
23461+ unsigned int sigen;
23462+ unsigned long long max, ull;
23463+ struct inode *inode, **array;
1facf9fc 23464+
027c5e7a
AM
23465+ array = au_iarray_alloc(sb, &max);
23466+ err = PTR_ERR(array);
23467+ if (IS_ERR(array))
23468+ goto out;
1facf9fc 23469+
23470+ err = 0;
027c5e7a
AM
23471+ sigen = au_sigen(sb);
23472+ for (ull = 0; ull < max; ull++) {
23473+ inode = array[ull];
537831f9 23474+ if (au_iigen(inode, NULL) != sigen) {
1facf9fc 23475+ ii_write_lock_child(inode);
027c5e7a 23476+ e = au_refresh_hinode_self(inode);
1facf9fc 23477+ ii_write_unlock(inode);
23478+ if (unlikely(e)) {
027c5e7a 23479+ pr_err("error %d, i%lu\n", e, inode->i_ino);
1facf9fc 23480+ if (!err)
23481+ err = e;
23482+ /* go on even if err */
23483+ }
23484+ }
1facf9fc 23485+ }
23486+
027c5e7a 23487+ au_iarray_free(array, max);
1facf9fc 23488+
4f0767ce 23489+out:
1facf9fc 23490+ return err;
23491+}
23492+
027c5e7a 23493+static void au_remount_refresh(struct super_block *sb)
1facf9fc 23494+{
027c5e7a
AM
23495+ int err, e;
23496+ unsigned int udba;
23497+ aufs_bindex_t bindex, bend;
1facf9fc 23498+ struct dentry *root;
23499+ struct inode *inode;
027c5e7a 23500+ struct au_branch *br;
1facf9fc 23501+
23502+ au_sigen_inc(sb);
027c5e7a 23503+ au_fclr_si(au_sbi(sb), FAILED_REFRESH_DIR);
1facf9fc 23504+
23505+ root = sb->s_root;
23506+ DiMustNoWaiters(root);
23507+ inode = root->d_inode;
23508+ IiMustNoWaiters(inode);
1facf9fc 23509+
027c5e7a
AM
23510+ udba = au_opt_udba(sb);
23511+ bend = au_sbend(sb);
23512+ for (bindex = 0; bindex <= bend; bindex++) {
23513+ br = au_sbr(sb, bindex);
23514+ err = au_hnotify_reset_br(udba, br, br->br_perm);
1facf9fc 23515+ if (unlikely(err))
027c5e7a
AM
23516+ AuIOErr("hnotify failed on br %d, %d, ignored\n",
23517+ bindex, err);
23518+ /* go on even if err */
1facf9fc 23519+ }
027c5e7a 23520+ au_hn_reset(inode, au_hi_flags(inode, /*isdir*/1));
1facf9fc 23521+
027c5e7a
AM
23522+ di_write_unlock(root);
23523+ err = au_refresh_d(sb);
23524+ e = au_refresh_i(sb);
23525+ if (unlikely(e && !err))
23526+ err = e;
1facf9fc 23527+ /* aufs_write_lock() calls ..._child() */
23528+ di_write_lock_child(root);
027c5e7a
AM
23529+
23530+ au_cpup_attr_all(inode, /*force*/1);
23531+
23532+ if (unlikely(err))
23533+ AuIOErr("refresh failed, ignored, %d\n", err);
1facf9fc 23534+}
23535+
23536+/* stop extra interpretation of errno in mount(8), and strange error messages */
23537+static int cvt_err(int err)
23538+{
23539+ AuTraceErr(err);
23540+
23541+ switch (err) {
23542+ case -ENOENT:
23543+ case -ENOTDIR:
23544+ case -EEXIST:
23545+ case -EIO:
23546+ err = -EINVAL;
23547+ }
23548+ return err;
23549+}
23550+
23551+static int aufs_remount_fs(struct super_block *sb, int *flags, char *data)
23552+{
4a4d8108
AM
23553+ int err, do_dx;
23554+ unsigned int mntflags;
1facf9fc 23555+ struct au_opts opts;
23556+ struct dentry *root;
23557+ struct inode *inode;
23558+ struct au_sbinfo *sbinfo;
23559+
23560+ err = 0;
23561+ root = sb->s_root;
23562+ if (!data || !*data) {
e49829fe
JR
23563+ err = si_write_lock(sb, AuLock_FLUSH | AuLock_NOPLM);
23564+ if (!err) {
23565+ di_write_lock_child(root);
23566+ err = au_opts_verify(sb, *flags, /*pending*/0);
23567+ aufs_write_unlock(root);
23568+ }
1facf9fc 23569+ goto out;
23570+ }
23571+
23572+ err = -ENOMEM;
23573+ memset(&opts, 0, sizeof(opts));
23574+ opts.opt = (void *)__get_free_page(GFP_NOFS);
23575+ if (unlikely(!opts.opt))
23576+ goto out;
23577+ opts.max_opt = PAGE_SIZE / sizeof(*opts.opt);
23578+ opts.flags = AuOpts_REMOUNT;
23579+ opts.sb_flags = *flags;
23580+
23581+ /* parse it before aufs lock */
23582+ err = au_opts_parse(sb, data, &opts);
23583+ if (unlikely(err))
23584+ goto out_opts;
23585+
23586+ sbinfo = au_sbi(sb);
23587+ inode = root->d_inode;
23588+ mutex_lock(&inode->i_mutex);
e49829fe
JR
23589+ err = si_write_lock(sb, AuLock_FLUSH | AuLock_NOPLM);
23590+ if (unlikely(err))
23591+ goto out_mtx;
23592+ di_write_lock_child(root);
1facf9fc 23593+
23594+ /* au_opts_remount() may return an error */
23595+ err = au_opts_remount(sb, &opts);
23596+ au_opts_free(&opts);
23597+
027c5e7a
AM
23598+ if (au_ftest_opts(opts.flags, REFRESH))
23599+ au_remount_refresh(sb);
1facf9fc 23600+
4a4d8108
AM
23601+ if (au_ftest_opts(opts.flags, REFRESH_DYAOP)) {
23602+ mntflags = au_mntflags(sb);
23603+ do_dx = !!au_opt_test(mntflags, DIO);
23604+ au_dy_arefresh(do_dx);
23605+ }
23606+
1facf9fc 23607+ aufs_write_unlock(root);
953406b4 23608+
e49829fe
JR
23609+out_mtx:
23610+ mutex_unlock(&inode->i_mutex);
4f0767ce 23611+out_opts:
1facf9fc 23612+ free_page((unsigned long)opts.opt);
4f0767ce 23613+out:
1facf9fc 23614+ err = cvt_err(err);
23615+ AuTraceErr(err);
23616+ return err;
23617+}
23618+
4a4d8108 23619+static const struct super_operations aufs_sop = {
1facf9fc 23620+ .alloc_inode = aufs_alloc_inode,
23621+ .destroy_inode = aufs_destroy_inode,
b752ccd1 23622+ /* always deleting, no clearing */
1facf9fc 23623+ .drop_inode = generic_delete_inode,
23624+ .show_options = aufs_show_options,
23625+ .statfs = aufs_statfs,
23626+ .put_super = aufs_put_super,
537831f9 23627+ .sync_fs = aufs_sync_fs,
1facf9fc 23628+ .remount_fs = aufs_remount_fs
23629+};
23630+
23631+/* ---------------------------------------------------------------------- */
23632+
23633+static int alloc_root(struct super_block *sb)
23634+{
23635+ int err;
23636+ struct inode *inode;
23637+ struct dentry *root;
23638+
23639+ err = -ENOMEM;
23640+ inode = au_iget_locked(sb, AUFS_ROOT_INO);
23641+ err = PTR_ERR(inode);
23642+ if (IS_ERR(inode))
23643+ goto out;
23644+
23645+ inode->i_op = &aufs_dir_iop;
23646+ inode->i_fop = &aufs_dir_fop;
23647+ inode->i_mode = S_IFDIR;
9dbd164d 23648+ set_nlink(inode, 2);
1facf9fc 23649+ unlock_new_inode(inode);
23650+
92d182d2 23651+ root = d_make_root(inode);
1facf9fc 23652+ if (unlikely(!root))
92d182d2 23653+ goto out;
1facf9fc 23654+ err = PTR_ERR(root);
23655+ if (IS_ERR(root))
92d182d2 23656+ goto out;
1facf9fc 23657+
4a4d8108 23658+ err = au_di_init(root);
1facf9fc 23659+ if (!err) {
23660+ sb->s_root = root;
23661+ return 0; /* success */
23662+ }
23663+ dput(root);
1facf9fc 23664+
4f0767ce 23665+out:
1facf9fc 23666+ return err;
1facf9fc 23667+}
23668+
23669+static int aufs_fill_super(struct super_block *sb, void *raw_data,
23670+ int silent __maybe_unused)
23671+{
23672+ int err;
23673+ struct au_opts opts;
23674+ struct dentry *root;
23675+ struct inode *inode;
23676+ char *arg = raw_data;
23677+
23678+ if (unlikely(!arg || !*arg)) {
23679+ err = -EINVAL;
4a4d8108 23680+ pr_err("no arg\n");
1facf9fc 23681+ goto out;
23682+ }
23683+
23684+ err = -ENOMEM;
23685+ memset(&opts, 0, sizeof(opts));
23686+ opts.opt = (void *)__get_free_page(GFP_NOFS);
23687+ if (unlikely(!opts.opt))
23688+ goto out;
23689+ opts.max_opt = PAGE_SIZE / sizeof(*opts.opt);
23690+ opts.sb_flags = sb->s_flags;
23691+
23692+ err = au_si_alloc(sb);
23693+ if (unlikely(err))
23694+ goto out_opts;
23695+
23696+ /* all timestamps always follow the ones on the branch */
23697+ sb->s_flags |= MS_NOATIME | MS_NODIRATIME;
23698+ sb->s_op = &aufs_sop;
027c5e7a 23699+ sb->s_d_op = &aufs_dop;
1facf9fc 23700+ sb->s_magic = AUFS_SUPER_MAGIC;
23701+ sb->s_maxbytes = 0;
23702+ au_export_init(sb);
23703+
23704+ err = alloc_root(sb);
23705+ if (unlikely(err)) {
23706+ si_write_unlock(sb);
23707+ goto out_info;
23708+ }
23709+ root = sb->s_root;
23710+ inode = root->d_inode;
23711+
23712+ /*
23713+ * actually we can parse options regardless aufs lock here.
23714+ * but at remount time, parsing must be done before aufs lock.
23715+ * so we follow the same rule.
23716+ */
23717+ ii_write_lock_parent(inode);
23718+ aufs_write_unlock(root);
23719+ err = au_opts_parse(sb, arg, &opts);
23720+ if (unlikely(err))
23721+ goto out_root;
23722+
23723+ /* lock vfs_inode first, then aufs. */
23724+ mutex_lock(&inode->i_mutex);
1facf9fc 23725+ aufs_write_lock(root);
23726+ err = au_opts_mount(sb, &opts);
23727+ au_opts_free(&opts);
1facf9fc 23728+ aufs_write_unlock(root);
23729+ mutex_unlock(&inode->i_mutex);
4a4d8108
AM
23730+ if (!err)
23731+ goto out_opts; /* success */
1facf9fc 23732+
4f0767ce 23733+out_root:
1facf9fc 23734+ dput(root);
23735+ sb->s_root = NULL;
4f0767ce 23736+out_info:
2cbb1c4b 23737+ dbgaufs_si_fin(au_sbi(sb));
1facf9fc 23738+ kobject_put(&au_sbi(sb)->si_kobj);
23739+ sb->s_fs_info = NULL;
4f0767ce 23740+out_opts:
1facf9fc 23741+ free_page((unsigned long)opts.opt);
4f0767ce 23742+out:
1facf9fc 23743+ AuTraceErr(err);
23744+ err = cvt_err(err);
23745+ AuTraceErr(err);
23746+ return err;
23747+}
23748+
23749+/* ---------------------------------------------------------------------- */
23750+
027c5e7a
AM
23751+static struct dentry *aufs_mount(struct file_system_type *fs_type, int flags,
23752+ const char *dev_name __maybe_unused,
23753+ void *raw_data)
1facf9fc 23754+{
027c5e7a 23755+ struct dentry *root;
1facf9fc 23756+ struct super_block *sb;
23757+
23758+ /* all timestamps always follow the ones on the branch */
23759+ /* mnt->mnt_flags |= MNT_NOATIME | MNT_NODIRATIME; */
027c5e7a
AM
23760+ root = mount_nodev(fs_type, flags, raw_data, aufs_fill_super);
23761+ if (IS_ERR(root))
23762+ goto out;
23763+
23764+ sb = root->d_sb;
23765+ si_write_lock(sb, !AuLock_FLUSH);
23766+ sysaufs_brs_add(sb, 0);
23767+ si_write_unlock(sb);
23768+ au_sbilist_add(sb);
23769+
23770+out:
23771+ return root;
1facf9fc 23772+}
23773+
e49829fe
JR
23774+static void aufs_kill_sb(struct super_block *sb)
23775+{
23776+ struct au_sbinfo *sbinfo;
23777+
23778+ sbinfo = au_sbi(sb);
23779+ if (sbinfo) {
23780+ au_sbilist_del(sb);
23781+ aufs_write_lock(sb->s_root);
23782+ if (sbinfo->si_wbr_create_ops->fin)
23783+ sbinfo->si_wbr_create_ops->fin(sb);
23784+ if (au_opt_test(sbinfo->si_mntflags, UDBA_HNOTIFY)) {
23785+ au_opt_set_udba(sbinfo->si_mntflags, UDBA_NONE);
027c5e7a 23786+ au_remount_refresh(sb);
e49829fe
JR
23787+ }
23788+ if (au_opt_test(sbinfo->si_mntflags, PLINK))
23789+ au_plink_put(sb, /*verbose*/1);
23790+ au_xino_clr(sb);
1e00d052 23791+ sbinfo->si_sb = NULL;
e49829fe 23792+ aufs_write_unlock(sb->s_root);
e49829fe
JR
23793+ au_nwt_flush(&sbinfo->si_nowait);
23794+ }
23795+ generic_shutdown_super(sb);
23796+}
23797+
1facf9fc 23798+struct file_system_type aufs_fs_type = {
23799+ .name = AUFS_FSTYPE,
23800+ .fs_flags =
23801+ FS_RENAME_DOES_D_MOVE /* a race between rename and others */
23802+ | FS_REVAL_DOT, /* for NFS branch and udba */
027c5e7a 23803+ .mount = aufs_mount,
e49829fe 23804+ .kill_sb = aufs_kill_sb,
1facf9fc 23805+ /* no need to __module_get() and module_put(). */
23806+ .owner = THIS_MODULE,
23807+};
7f207e10
AM
23808diff -urN /usr/share/empty/fs/aufs/super.h linux/fs/aufs/super.h
23809--- /usr/share/empty/fs/aufs/super.h 1970-01-01 01:00:00.000000000 +0100
537831f9 23810+++ linux/fs/aufs/super.h 2012-12-13 20:41:10.431460173 +0100
f6c5ef8b 23811@@ -0,0 +1,546 @@
1facf9fc 23812+/*
f6c5ef8b 23813+ * Copyright (C) 2005-2012 Junjiro R. Okajima
1facf9fc 23814+ *
23815+ * This program, aufs is free software; you can redistribute it and/or modify
23816+ * it under the terms of the GNU General Public License as published by
23817+ * the Free Software Foundation; either version 2 of the License, or
23818+ * (at your option) any later version.
dece6358
AM
23819+ *
23820+ * This program is distributed in the hope that it will be useful,
23821+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
23822+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23823+ * GNU General Public License for more details.
23824+ *
23825+ * You should have received a copy of the GNU General Public License
23826+ * along with this program; if not, write to the Free Software
23827+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 23828+ */
23829+
23830+/*
23831+ * super_block operations
23832+ */
23833+
23834+#ifndef __AUFS_SUPER_H__
23835+#define __AUFS_SUPER_H__
23836+
23837+#ifdef __KERNEL__
23838+
23839+#include <linux/fs.h>
1facf9fc 23840+#include "rwsem.h"
23841+#include "spl.h"
23842+#include "wkq.h"
23843+
23844+typedef ssize_t (*au_readf_t)(struct file *, char __user *, size_t, loff_t *);
23845+typedef ssize_t (*au_writef_t)(struct file *, const char __user *, size_t,
23846+ loff_t *);
23847+
23848+/* policies to select one among multiple writable branches */
23849+struct au_wbr_copyup_operations {
23850+ int (*copyup)(struct dentry *dentry);
23851+};
23852+
23853+struct au_wbr_create_operations {
23854+ int (*create)(struct dentry *dentry, int isdir);
23855+ int (*init)(struct super_block *sb);
23856+ int (*fin)(struct super_block *sb);
23857+};
23858+
23859+struct au_wbr_mfs {
23860+ struct mutex mfs_lock; /* protect this structure */
23861+ unsigned long mfs_jiffy;
23862+ unsigned long mfs_expire;
23863+ aufs_bindex_t mfs_bindex;
23864+
23865+ unsigned long long mfsrr_bytes;
23866+ unsigned long long mfsrr_watermark;
23867+};
23868+
1facf9fc 23869+struct au_branch;
23870+struct au_sbinfo {
23871+ /* nowait tasks in the system-wide workqueue */
23872+ struct au_nowait_tasks si_nowait;
23873+
b752ccd1
AM
23874+ /*
23875+ * tried sb->s_umount, but failed due to the dependecy between i_mutex.
23876+ * rwsem for au_sbinfo is necessary.
23877+ */
dece6358 23878+ struct au_rwsem si_rwsem;
1facf9fc 23879+
b752ccd1
AM
23880+ /* prevent recursive locking in deleting inode */
23881+ struct {
23882+ unsigned long *bitmap;
23883+ spinlock_t tree_lock;
23884+ struct radix_tree_root tree;
23885+ } au_si_pid;
23886+
7f207e10
AM
23887+ /*
23888+ * dirty approach to protect sb->sb_inodes and ->s_files from remount.
23889+ */
23890+ atomic_long_t si_ninodes, si_nfiles;
23891+
1facf9fc 23892+ /* branch management */
23893+ unsigned int si_generation;
23894+
23895+ /* see above flags */
23896+ unsigned char au_si_status;
23897+
23898+ aufs_bindex_t si_bend;
7f207e10
AM
23899+
23900+ /* dirty trick to keep br_id plus */
23901+ unsigned int si_last_br_id :
23902+ sizeof(aufs_bindex_t) * BITS_PER_BYTE - 1;
1facf9fc 23903+ struct au_branch **si_branch;
23904+
23905+ /* policy to select a writable branch */
23906+ unsigned char si_wbr_copyup;
23907+ unsigned char si_wbr_create;
23908+ struct au_wbr_copyup_operations *si_wbr_copyup_ops;
23909+ struct au_wbr_create_operations *si_wbr_create_ops;
23910+
23911+ /* round robin */
23912+ atomic_t si_wbr_rr_next;
23913+
23914+ /* most free space */
23915+ struct au_wbr_mfs si_wbr_mfs;
23916+
23917+ /* mount flags */
23918+ /* include/asm-ia64/siginfo.h defines a macro named si_flags */
23919+ unsigned int si_mntflags;
23920+
23921+ /* external inode number (bitmap and translation table) */
23922+ au_readf_t si_xread;
23923+ au_writef_t si_xwrite;
23924+ struct file *si_xib;
23925+ struct mutex si_xib_mtx; /* protect xib members */
23926+ unsigned long *si_xib_buf;
23927+ unsigned long si_xib_last_pindex;
23928+ int si_xib_next_bit;
23929+ aufs_bindex_t si_xino_brid;
23930+ /* reserved for future use */
23931+ /* unsigned long long si_xib_limit; */ /* Max xib file size */
23932+
23933+#ifdef CONFIG_AUFS_EXPORT
23934+ /* i_generation */
23935+ struct file *si_xigen;
23936+ atomic_t si_xigen_next;
23937+#endif
23938+
23939+ /* vdir parameters */
e49829fe 23940+ unsigned long si_rdcache; /* max cache time in jiffies */
1facf9fc 23941+ unsigned int si_rdblk; /* deblk size */
23942+ unsigned int si_rdhash; /* hash size */
23943+
23944+ /*
23945+ * If the number of whiteouts are larger than si_dirwh, leave all of
23946+ * them after au_whtmp_ren to reduce the cost of rmdir(2).
23947+ * future fsck.aufs or kernel thread will remove them later.
23948+ * Otherwise, remove all whiteouts and the dir in rmdir(2).
23949+ */
23950+ unsigned int si_dirwh;
23951+
23952+ /*
23953+ * rename(2) a directory with all children.
23954+ */
23955+ /* reserved for future use */
23956+ /* int si_rendir; */
23957+
23958+ /* pseudo_link list */
23959+ struct au_splhead si_plink;
23960+ wait_queue_head_t si_plink_wq;
4a4d8108 23961+ spinlock_t si_plink_maint_lock;
e49829fe 23962+ pid_t si_plink_maint_pid;
1facf9fc 23963+
23964+ /*
23965+ * sysfs and lifetime management.
23966+ * this is not a small structure and it may be a waste of memory in case
23967+ * of sysfs is disabled, particulary when many aufs-es are mounted.
23968+ * but using sysfs is majority.
23969+ */
23970+ struct kobject si_kobj;
23971+#ifdef CONFIG_DEBUG_FS
23972+ struct dentry *si_dbgaufs, *si_dbgaufs_xib;
23973+#ifdef CONFIG_AUFS_EXPORT
23974+ struct dentry *si_dbgaufs_xigen;
23975+#endif
23976+#endif
23977+
e49829fe
JR
23978+#ifdef CONFIG_AUFS_SBILIST
23979+ struct list_head si_list;
23980+#endif
23981+
1facf9fc 23982+ /* dirty, necessary for unmounting, sysfs and sysrq */
23983+ struct super_block *si_sb;
23984+};
23985+
dece6358
AM
23986+/* sbinfo status flags */
23987+/*
23988+ * set true when refresh_dirs() failed at remount time.
23989+ * then try refreshing dirs at access time again.
23990+ * if it is false, refreshing dirs at access time is unnecesary
23991+ */
027c5e7a 23992+#define AuSi_FAILED_REFRESH_DIR 1
dece6358
AM
23993+static inline unsigned char au_do_ftest_si(struct au_sbinfo *sbi,
23994+ unsigned int flag)
23995+{
23996+ AuRwMustAnyLock(&sbi->si_rwsem);
23997+ return sbi->au_si_status & flag;
23998+}
23999+#define au_ftest_si(sbinfo, name) au_do_ftest_si(sbinfo, AuSi_##name)
24000+#define au_fset_si(sbinfo, name) do { \
24001+ AuRwMustWriteLock(&(sbinfo)->si_rwsem); \
24002+ (sbinfo)->au_si_status |= AuSi_##name; \
24003+} while (0)
24004+#define au_fclr_si(sbinfo, name) do { \
24005+ AuRwMustWriteLock(&(sbinfo)->si_rwsem); \
24006+ (sbinfo)->au_si_status &= ~AuSi_##name; \
24007+} while (0)
24008+
1facf9fc 24009+/* ---------------------------------------------------------------------- */
24010+
24011+/* policy to select one among writable branches */
4a4d8108
AM
24012+#define AuWbrCopyup(sbinfo, ...) \
24013+ ((sbinfo)->si_wbr_copyup_ops->copyup(__VA_ARGS__))
24014+#define AuWbrCreate(sbinfo, ...) \
24015+ ((sbinfo)->si_wbr_create_ops->create(__VA_ARGS__))
1facf9fc 24016+
24017+/* flags for si_read_lock()/aufs_read_lock()/di_read_lock() */
24018+#define AuLock_DW 1 /* write-lock dentry */
24019+#define AuLock_IR (1 << 1) /* read-lock inode */
24020+#define AuLock_IW (1 << 2) /* write-lock inode */
24021+#define AuLock_FLUSH (1 << 3) /* wait for 'nowait' tasks */
24022+#define AuLock_DIR (1 << 4) /* target is a dir */
e49829fe
JR
24023+#define AuLock_NOPLM (1 << 5) /* return err in plm mode */
24024+#define AuLock_NOPLMW (1 << 6) /* wait for plm mode ends */
027c5e7a 24025+#define AuLock_GEN (1 << 7) /* test digen/iigen */
1facf9fc 24026+#define au_ftest_lock(flags, name) ((flags) & AuLock_##name)
7f207e10
AM
24027+#define au_fset_lock(flags, name) \
24028+ do { (flags) |= AuLock_##name; } while (0)
24029+#define au_fclr_lock(flags, name) \
24030+ do { (flags) &= ~AuLock_##name; } while (0)
1facf9fc 24031+
24032+/* ---------------------------------------------------------------------- */
24033+
24034+/* super.c */
24035+extern struct file_system_type aufs_fs_type;
24036+struct inode *au_iget_locked(struct super_block *sb, ino_t ino);
7f207e10
AM
24037+typedef unsigned long long (*au_arraycb_t)(void *array, unsigned long long max,
24038+ void *arg);
24039+void au_array_free(void *array);
24040+void *au_array_alloc(unsigned long long *hint, au_arraycb_t cb, void *arg);
24041+struct inode **au_iarray_alloc(struct super_block *sb, unsigned long long *max);
24042+void au_iarray_free(struct inode **a, unsigned long long max);
1facf9fc 24043+
24044+/* sbinfo.c */
24045+void au_si_free(struct kobject *kobj);
24046+int au_si_alloc(struct super_block *sb);
24047+int au_sbr_realloc(struct au_sbinfo *sbinfo, int nbr);
24048+
24049+unsigned int au_sigen_inc(struct super_block *sb);
24050+aufs_bindex_t au_new_br_id(struct super_block *sb);
24051+
e49829fe
JR
24052+int si_read_lock(struct super_block *sb, int flags);
24053+int si_write_lock(struct super_block *sb, int flags);
24054+int aufs_read_lock(struct dentry *dentry, int flags);
1facf9fc 24055+void aufs_read_unlock(struct dentry *dentry, int flags);
24056+void aufs_write_lock(struct dentry *dentry);
24057+void aufs_write_unlock(struct dentry *dentry);
e49829fe 24058+int aufs_read_and_write_lock2(struct dentry *d1, struct dentry *d2, int flags);
1facf9fc 24059+void aufs_read_and_write_unlock2(struct dentry *d1, struct dentry *d2);
24060+
b752ccd1
AM
24061+int si_pid_test_slow(struct super_block *sb);
24062+void si_pid_set_slow(struct super_block *sb);
24063+void si_pid_clr_slow(struct super_block *sb);
24064+
1facf9fc 24065+/* wbr_policy.c */
24066+extern struct au_wbr_copyup_operations au_wbr_copyup_ops[];
24067+extern struct au_wbr_create_operations au_wbr_create_ops[];
24068+int au_cpdown_dirs(struct dentry *dentry, aufs_bindex_t bdst);
24069+
24070+/* ---------------------------------------------------------------------- */
24071+
24072+static inline struct au_sbinfo *au_sbi(struct super_block *sb)
24073+{
24074+ return sb->s_fs_info;
24075+}
24076+
24077+/* ---------------------------------------------------------------------- */
24078+
24079+#ifdef CONFIG_AUFS_EXPORT
24080+void au_export_init(struct super_block *sb);
24081+
b752ccd1 24082+static inline int au_test_nfsd(void)
1facf9fc 24083+{
b752ccd1
AM
24084+ struct task_struct *tsk = current;
24085+
24086+ return (tsk->flags & PF_KTHREAD)
24087+ && !strcmp(tsk->comm, "nfsd");
1facf9fc 24088+}
24089+
b752ccd1 24090+void au_xigen_inc(struct inode *inode);
1facf9fc 24091+int au_xigen_new(struct inode *inode);
24092+int au_xigen_set(struct super_block *sb, struct file *base);
24093+void au_xigen_clr(struct super_block *sb);
24094+
24095+static inline int au_busy_or_stale(void)
24096+{
b752ccd1 24097+ if (!au_test_nfsd())
1facf9fc 24098+ return -EBUSY;
24099+ return -ESTALE;
24100+}
24101+#else
4a4d8108 24102+AuStubVoid(au_export_init, struct super_block *sb)
b752ccd1
AM
24103+AuStubInt0(au_test_nfsd, void)
24104+AuStubVoid(au_xigen_inc, struct inode *inode)
4a4d8108
AM
24105+AuStubInt0(au_xigen_new, struct inode *inode)
24106+AuStubInt0(au_xigen_set, struct super_block *sb, struct file *base)
24107+AuStubVoid(au_xigen_clr, struct super_block *sb)
1facf9fc 24108+static inline int au_busy_or_stale(void)
24109+{
24110+ return -EBUSY;
24111+}
24112+#endif /* CONFIG_AUFS_EXPORT */
24113+
24114+/* ---------------------------------------------------------------------- */
24115+
e49829fe
JR
24116+#ifdef CONFIG_AUFS_SBILIST
24117+/* module.c */
24118+extern struct au_splhead au_sbilist;
24119+
24120+static inline void au_sbilist_init(void)
24121+{
24122+ au_spl_init(&au_sbilist);
24123+}
24124+
24125+static inline void au_sbilist_add(struct super_block *sb)
24126+{
24127+ au_spl_add(&au_sbi(sb)->si_list, &au_sbilist);
24128+}
24129+
24130+static inline void au_sbilist_del(struct super_block *sb)
24131+{
24132+ au_spl_del(&au_sbi(sb)->si_list, &au_sbilist);
24133+}
53392da6
AM
24134+
24135+#ifdef CONFIG_AUFS_MAGIC_SYSRQ
24136+static inline void au_sbilist_lock(void)
24137+{
24138+ spin_lock(&au_sbilist.spin);
24139+}
24140+
24141+static inline void au_sbilist_unlock(void)
24142+{
24143+ spin_unlock(&au_sbilist.spin);
24144+}
24145+#define AuGFP_SBILIST GFP_ATOMIC
24146+#else
24147+AuStubVoid(au_sbilist_lock, void)
24148+AuStubVoid(au_sbilist_unlock, void)
24149+#define AuGFP_SBILIST GFP_NOFS
24150+#endif /* CONFIG_AUFS_MAGIC_SYSRQ */
e49829fe
JR
24151+#else
24152+AuStubVoid(au_sbilist_init, void)
24153+AuStubVoid(au_sbilist_add, struct super_block*)
24154+AuStubVoid(au_sbilist_del, struct super_block*)
53392da6
AM
24155+AuStubVoid(au_sbilist_lock, void)
24156+AuStubVoid(au_sbilist_unlock, void)
24157+#define AuGFP_SBILIST GFP_NOFS
e49829fe
JR
24158+#endif
24159+
24160+/* ---------------------------------------------------------------------- */
24161+
1facf9fc 24162+static inline void dbgaufs_si_null(struct au_sbinfo *sbinfo)
24163+{
dece6358
AM
24164+ /*
24165+ * This function is a dynamic '__init' fucntion actually,
24166+ * so the tiny check for si_rwsem is unnecessary.
24167+ */
24168+ /* AuRwMustWriteLock(&sbinfo->si_rwsem); */
1facf9fc 24169+#ifdef CONFIG_DEBUG_FS
24170+ sbinfo->si_dbgaufs = NULL;
24171+ sbinfo->si_dbgaufs_xib = NULL;
24172+#ifdef CONFIG_AUFS_EXPORT
24173+ sbinfo->si_dbgaufs_xigen = NULL;
24174+#endif
24175+#endif
24176+}
24177+
24178+/* ---------------------------------------------------------------------- */
24179+
b752ccd1
AM
24180+static inline pid_t si_pid_bit(void)
24181+{
24182+ /* the origin of pid is 1, but the bitmap's is 0 */
24183+ return current->pid - 1;
24184+}
24185+
24186+static inline int si_pid_test(struct super_block *sb)
24187+{
24188+ pid_t bit = si_pid_bit();
24189+ if (bit < PID_MAX_DEFAULT)
24190+ return test_bit(bit, au_sbi(sb)->au_si_pid.bitmap);
24191+ else
24192+ return si_pid_test_slow(sb);
24193+}
24194+
24195+static inline void si_pid_set(struct super_block *sb)
24196+{
24197+ pid_t bit = si_pid_bit();
24198+ if (bit < PID_MAX_DEFAULT) {
24199+ AuDebugOn(test_bit(bit, au_sbi(sb)->au_si_pid.bitmap));
24200+ set_bit(bit, au_sbi(sb)->au_si_pid.bitmap);
24201+ /* smp_mb(); */
24202+ } else
24203+ si_pid_set_slow(sb);
24204+}
24205+
24206+static inline void si_pid_clr(struct super_block *sb)
24207+{
24208+ pid_t bit = si_pid_bit();
24209+ if (bit < PID_MAX_DEFAULT) {
24210+ AuDebugOn(!test_bit(bit, au_sbi(sb)->au_si_pid.bitmap));
24211+ clear_bit(bit, au_sbi(sb)->au_si_pid.bitmap);
24212+ /* smp_mb(); */
24213+ } else
24214+ si_pid_clr_slow(sb);
24215+}
24216+
24217+/* ---------------------------------------------------------------------- */
24218+
1facf9fc 24219+/* lock superblock. mainly for entry point functions */
24220+/*
b752ccd1
AM
24221+ * __si_read_lock, __si_write_lock,
24222+ * __si_read_unlock, __si_write_unlock, __si_downgrade_lock
1facf9fc 24223+ */
b752ccd1 24224+AuSimpleRwsemFuncs(__si, struct super_block *sb, &au_sbi(sb)->si_rwsem);
1facf9fc 24225+
dece6358
AM
24226+#define SiMustNoWaiters(sb) AuRwMustNoWaiters(&au_sbi(sb)->si_rwsem)
24227+#define SiMustAnyLock(sb) AuRwMustAnyLock(&au_sbi(sb)->si_rwsem)
24228+#define SiMustWriteLock(sb) AuRwMustWriteLock(&au_sbi(sb)->si_rwsem)
24229+
b752ccd1
AM
24230+static inline void si_noflush_read_lock(struct super_block *sb)
24231+{
24232+ __si_read_lock(sb);
24233+ si_pid_set(sb);
24234+}
24235+
24236+static inline int si_noflush_read_trylock(struct super_block *sb)
24237+{
24238+ int locked = __si_read_trylock(sb);
24239+ if (locked)
24240+ si_pid_set(sb);
24241+ return locked;
24242+}
24243+
24244+static inline void si_noflush_write_lock(struct super_block *sb)
24245+{
24246+ __si_write_lock(sb);
24247+ si_pid_set(sb);
24248+}
24249+
24250+static inline int si_noflush_write_trylock(struct super_block *sb)
24251+{
24252+ int locked = __si_write_trylock(sb);
24253+ if (locked)
24254+ si_pid_set(sb);
24255+ return locked;
24256+}
24257+
e49829fe 24258+#if 0 /* unused */
1facf9fc 24259+static inline int si_read_trylock(struct super_block *sb, int flags)
24260+{
24261+ if (au_ftest_lock(flags, FLUSH))
24262+ au_nwt_flush(&au_sbi(sb)->si_nowait);
24263+ return si_noflush_read_trylock(sb);
24264+}
e49829fe 24265+#endif
1facf9fc 24266+
b752ccd1
AM
24267+static inline void si_read_unlock(struct super_block *sb)
24268+{
24269+ si_pid_clr(sb);
24270+ __si_read_unlock(sb);
24271+}
24272+
b752ccd1 24273+#if 0 /* unused */
1facf9fc 24274+static inline int si_write_trylock(struct super_block *sb, int flags)
24275+{
24276+ if (au_ftest_lock(flags, FLUSH))
24277+ au_nwt_flush(&au_sbi(sb)->si_nowait);
24278+ return si_noflush_write_trylock(sb);
24279+}
b752ccd1
AM
24280+#endif
24281+
24282+static inline void si_write_unlock(struct super_block *sb)
24283+{
24284+ si_pid_clr(sb);
24285+ __si_write_unlock(sb);
24286+}
24287+
24288+#if 0 /* unused */
24289+static inline void si_downgrade_lock(struct super_block *sb)
24290+{
24291+ __si_downgrade_lock(sb);
24292+}
24293+#endif
1facf9fc 24294+
24295+/* ---------------------------------------------------------------------- */
24296+
24297+static inline aufs_bindex_t au_sbend(struct super_block *sb)
24298+{
dece6358 24299+ SiMustAnyLock(sb);
1facf9fc 24300+ return au_sbi(sb)->si_bend;
24301+}
24302+
24303+static inline unsigned int au_mntflags(struct super_block *sb)
24304+{
dece6358 24305+ SiMustAnyLock(sb);
1facf9fc 24306+ return au_sbi(sb)->si_mntflags;
24307+}
24308+
24309+static inline unsigned int au_sigen(struct super_block *sb)
24310+{
dece6358 24311+ SiMustAnyLock(sb);
1facf9fc 24312+ return au_sbi(sb)->si_generation;
24313+}
24314+
7f207e10
AM
24315+static inline void au_ninodes_inc(struct super_block *sb)
24316+{
24317+ atomic_long_inc(&au_sbi(sb)->si_ninodes);
24318+}
24319+
24320+static inline void au_ninodes_dec(struct super_block *sb)
24321+{
24322+ AuDebugOn(!atomic_long_read(&au_sbi(sb)->si_ninodes));
24323+ atomic_long_dec(&au_sbi(sb)->si_ninodes);
24324+}
24325+
24326+static inline void au_nfiles_inc(struct super_block *sb)
24327+{
24328+ atomic_long_inc(&au_sbi(sb)->si_nfiles);
24329+}
24330+
24331+static inline void au_nfiles_dec(struct super_block *sb)
24332+{
24333+ AuDebugOn(!atomic_long_read(&au_sbi(sb)->si_nfiles));
24334+ atomic_long_dec(&au_sbi(sb)->si_nfiles);
24335+}
24336+
1facf9fc 24337+static inline struct au_branch *au_sbr(struct super_block *sb,
24338+ aufs_bindex_t bindex)
24339+{
dece6358 24340+ SiMustAnyLock(sb);
1facf9fc 24341+ return au_sbi(sb)->si_branch[0 + bindex];
24342+}
24343+
24344+static inline void au_xino_brid_set(struct super_block *sb, aufs_bindex_t brid)
24345+{
dece6358 24346+ SiMustWriteLock(sb);
1facf9fc 24347+ au_sbi(sb)->si_xino_brid = brid;
24348+}
24349+
24350+static inline aufs_bindex_t au_xino_brid(struct super_block *sb)
24351+{
dece6358 24352+ SiMustAnyLock(sb);
1facf9fc 24353+ return au_sbi(sb)->si_xino_brid;
24354+}
24355+
24356+#endif /* __KERNEL__ */
24357+#endif /* __AUFS_SUPER_H__ */
7f207e10
AM
24358diff -urN /usr/share/empty/fs/aufs/sysaufs.c linux/fs/aufs/sysaufs.c
24359--- /usr/share/empty/fs/aufs/sysaufs.c 1970-01-01 01:00:00.000000000 +0100
537831f9 24360+++ linux/fs/aufs/sysaufs.c 2012-12-13 20:41:10.431460173 +0100
f6c5ef8b 24361@@ -0,0 +1,105 @@
1facf9fc 24362+/*
f6c5ef8b 24363+ * Copyright (C) 2005-2012 Junjiro R. Okajima
1facf9fc 24364+ *
24365+ * This program, aufs is free software; you can redistribute it and/or modify
24366+ * it under the terms of the GNU General Public License as published by
24367+ * the Free Software Foundation; either version 2 of the License, or
24368+ * (at your option) any later version.
dece6358
AM
24369+ *
24370+ * This program is distributed in the hope that it will be useful,
24371+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
24372+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24373+ * GNU General Public License for more details.
24374+ *
24375+ * You should have received a copy of the GNU General Public License
24376+ * along with this program; if not, write to the Free Software
24377+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 24378+ */
24379+
24380+/*
24381+ * sysfs interface and lifetime management
24382+ * they are necessary regardless sysfs is disabled.
24383+ */
24384+
1facf9fc 24385+#include <linux/random.h>
1facf9fc 24386+#include "aufs.h"
24387+
24388+unsigned long sysaufs_si_mask;
e49829fe 24389+struct kset *sysaufs_kset;
1facf9fc 24390+
24391+#define AuSiAttr(_name) { \
24392+ .attr = { .name = __stringify(_name), .mode = 0444 }, \
24393+ .show = sysaufs_si_##_name, \
24394+}
24395+
24396+static struct sysaufs_si_attr sysaufs_si_attr_xi_path = AuSiAttr(xi_path);
24397+struct attribute *sysaufs_si_attrs[] = {
24398+ &sysaufs_si_attr_xi_path.attr,
24399+ NULL,
24400+};
24401+
4a4d8108 24402+static const struct sysfs_ops au_sbi_ops = {
1facf9fc 24403+ .show = sysaufs_si_show
24404+};
24405+
24406+static struct kobj_type au_sbi_ktype = {
24407+ .release = au_si_free,
24408+ .sysfs_ops = &au_sbi_ops,
24409+ .default_attrs = sysaufs_si_attrs
24410+};
24411+
24412+/* ---------------------------------------------------------------------- */
24413+
24414+int sysaufs_si_init(struct au_sbinfo *sbinfo)
24415+{
24416+ int err;
24417+
e49829fe 24418+ sbinfo->si_kobj.kset = sysaufs_kset;
1facf9fc 24419+ /* cf. sysaufs_name() */
24420+ err = kobject_init_and_add
e49829fe 24421+ (&sbinfo->si_kobj, &au_sbi_ktype, /*&sysaufs_kset->kobj*/NULL,
1facf9fc 24422+ SysaufsSiNamePrefix "%lx", sysaufs_si_id(sbinfo));
24423+
24424+ dbgaufs_si_null(sbinfo);
24425+ if (!err) {
24426+ err = dbgaufs_si_init(sbinfo);
24427+ if (unlikely(err))
24428+ kobject_put(&sbinfo->si_kobj);
24429+ }
24430+ return err;
24431+}
24432+
24433+void sysaufs_fin(void)
24434+{
24435+ dbgaufs_fin();
e49829fe
JR
24436+ sysfs_remove_group(&sysaufs_kset->kobj, sysaufs_attr_group);
24437+ kset_unregister(sysaufs_kset);
1facf9fc 24438+}
24439+
24440+int __init sysaufs_init(void)
24441+{
24442+ int err;
24443+
24444+ do {
24445+ get_random_bytes(&sysaufs_si_mask, sizeof(sysaufs_si_mask));
24446+ } while (!sysaufs_si_mask);
24447+
4a4d8108 24448+ err = -EINVAL;
e49829fe
JR
24449+ sysaufs_kset = kset_create_and_add(AUFS_NAME, NULL, fs_kobj);
24450+ if (unlikely(!sysaufs_kset))
4a4d8108 24451+ goto out;
e49829fe
JR
24452+ err = PTR_ERR(sysaufs_kset);
24453+ if (IS_ERR(sysaufs_kset))
1facf9fc 24454+ goto out;
e49829fe 24455+ err = sysfs_create_group(&sysaufs_kset->kobj, sysaufs_attr_group);
1facf9fc 24456+ if (unlikely(err)) {
e49829fe 24457+ kset_unregister(sysaufs_kset);
1facf9fc 24458+ goto out;
24459+ }
24460+
24461+ err = dbgaufs_init();
24462+ if (unlikely(err))
24463+ sysaufs_fin();
4f0767ce 24464+out:
1facf9fc 24465+ return err;
24466+}
7f207e10
AM
24467diff -urN /usr/share/empty/fs/aufs/sysaufs.h linux/fs/aufs/sysaufs.h
24468--- /usr/share/empty/fs/aufs/sysaufs.h 1970-01-01 01:00:00.000000000 +0100
537831f9 24469+++ linux/fs/aufs/sysaufs.h 2012-12-13 20:41:10.431460173 +0100
f6c5ef8b 24470@@ -0,0 +1,104 @@
1facf9fc 24471+/*
f6c5ef8b 24472+ * Copyright (C) 2005-2012 Junjiro R. Okajima
1facf9fc 24473+ *
24474+ * This program, aufs is free software; you can redistribute it and/or modify
24475+ * it under the terms of the GNU General Public License as published by
24476+ * the Free Software Foundation; either version 2 of the License, or
24477+ * (at your option) any later version.
dece6358
AM
24478+ *
24479+ * This program is distributed in the hope that it will be useful,
24480+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
24481+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24482+ * GNU General Public License for more details.
24483+ *
24484+ * You should have received a copy of the GNU General Public License
24485+ * along with this program; if not, write to the Free Software
24486+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 24487+ */
24488+
24489+/*
24490+ * sysfs interface and mount lifetime management
24491+ */
24492+
24493+#ifndef __SYSAUFS_H__
24494+#define __SYSAUFS_H__
24495+
24496+#ifdef __KERNEL__
24497+
1facf9fc 24498+#include <linux/sysfs.h>
1facf9fc 24499+#include "module.h"
24500+
dece6358
AM
24501+struct super_block;
24502+struct au_sbinfo;
24503+
1facf9fc 24504+struct sysaufs_si_attr {
24505+ struct attribute attr;
24506+ int (*show)(struct seq_file *seq, struct super_block *sb);
24507+};
24508+
24509+/* ---------------------------------------------------------------------- */
24510+
24511+/* sysaufs.c */
24512+extern unsigned long sysaufs_si_mask;
e49829fe 24513+extern struct kset *sysaufs_kset;
1facf9fc 24514+extern struct attribute *sysaufs_si_attrs[];
24515+int sysaufs_si_init(struct au_sbinfo *sbinfo);
24516+int __init sysaufs_init(void);
24517+void sysaufs_fin(void);
24518+
24519+/* ---------------------------------------------------------------------- */
24520+
24521+/* some people doesn't like to show a pointer in kernel */
24522+static inline unsigned long sysaufs_si_id(struct au_sbinfo *sbinfo)
24523+{
24524+ return sysaufs_si_mask ^ (unsigned long)sbinfo;
24525+}
24526+
24527+#define SysaufsSiNamePrefix "si_"
24528+#define SysaufsSiNameLen (sizeof(SysaufsSiNamePrefix) + 16)
24529+static inline void sysaufs_name(struct au_sbinfo *sbinfo, char *name)
24530+{
24531+ snprintf(name, SysaufsSiNameLen, SysaufsSiNamePrefix "%lx",
24532+ sysaufs_si_id(sbinfo));
24533+}
24534+
24535+struct au_branch;
24536+#ifdef CONFIG_SYSFS
24537+/* sysfs.c */
24538+extern struct attribute_group *sysaufs_attr_group;
24539+
24540+int sysaufs_si_xi_path(struct seq_file *seq, struct super_block *sb);
24541+ssize_t sysaufs_si_show(struct kobject *kobj, struct attribute *attr,
24542+ char *buf);
24543+
24544+void sysaufs_br_init(struct au_branch *br);
24545+void sysaufs_brs_add(struct super_block *sb, aufs_bindex_t bindex);
24546+void sysaufs_brs_del(struct super_block *sb, aufs_bindex_t bindex);
24547+
24548+#define sysaufs_brs_init() do {} while (0)
24549+
24550+#else
24551+#define sysaufs_attr_group NULL
24552+
4a4d8108 24553+AuStubInt0(sysaufs_si_xi_path, struct seq_file *seq, struct super_block *sb)
1facf9fc 24554+
24555+static inline
24556+ssize_t sysaufs_si_show(struct kobject *kobj, struct attribute *attr,
24557+ char *buf)
24558+{
24559+ return 0;
24560+}
24561+
4a4d8108
AM
24562+AuStubVoid(sysaufs_br_init, struct au_branch *br)
24563+AuStubVoid(sysaufs_brs_add, struct super_block *sb, aufs_bindex_t bindex)
24564+AuStubVoid(sysaufs_brs_del, struct super_block *sb, aufs_bindex_t bindex)
1facf9fc 24565+
24566+static inline void sysaufs_brs_init(void)
24567+{
24568+ sysaufs_brs = 0;
24569+}
24570+
24571+#endif /* CONFIG_SYSFS */
24572+
24573+#endif /* __KERNEL__ */
24574+#endif /* __SYSAUFS_H__ */
7f207e10
AM
24575diff -urN /usr/share/empty/fs/aufs/sysfs.c linux/fs/aufs/sysfs.c
24576--- /usr/share/empty/fs/aufs/sysfs.c 1970-01-01 01:00:00.000000000 +0100
537831f9 24577+++ linux/fs/aufs/sysfs.c 2012-12-13 20:41:10.431460173 +0100
f6c5ef8b 24578@@ -0,0 +1,257 @@
1facf9fc 24579+/*
f6c5ef8b 24580+ * Copyright (C) 2005-2012 Junjiro R. Okajima
1facf9fc 24581+ *
24582+ * This program, aufs is free software; you can redistribute it and/or modify
24583+ * it under the terms of the GNU General Public License as published by
24584+ * the Free Software Foundation; either version 2 of the License, or
24585+ * (at your option) any later version.
dece6358
AM
24586+ *
24587+ * This program is distributed in the hope that it will be useful,
24588+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
24589+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24590+ * GNU General Public License for more details.
24591+ *
24592+ * You should have received a copy of the GNU General Public License
24593+ * along with this program; if not, write to the Free Software
24594+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 24595+ */
24596+
24597+/*
24598+ * sysfs interface
24599+ */
24600+
1facf9fc 24601+#include <linux/seq_file.h>
1facf9fc 24602+#include "aufs.h"
24603+
4a4d8108
AM
24604+#ifdef CONFIG_AUFS_FS_MODULE
24605+/* this entry violates the "one line per file" policy of sysfs */
24606+static ssize_t config_show(struct kobject *kobj, struct kobj_attribute *attr,
24607+ char *buf)
24608+{
24609+ ssize_t err;
24610+ static char *conf =
24611+/* this file is generated at compiling */
24612+#include "conf.str"
24613+ ;
24614+
24615+ err = snprintf(buf, PAGE_SIZE, conf);
24616+ if (unlikely(err >= PAGE_SIZE))
24617+ err = -EFBIG;
24618+ return err;
24619+}
24620+
24621+static struct kobj_attribute au_config_attr = __ATTR_RO(config);
24622+#endif
24623+
1facf9fc 24624+static struct attribute *au_attr[] = {
4a4d8108
AM
24625+#ifdef CONFIG_AUFS_FS_MODULE
24626+ &au_config_attr.attr,
24627+#endif
1facf9fc 24628+ NULL, /* need to NULL terminate the list of attributes */
24629+};
24630+
24631+static struct attribute_group sysaufs_attr_group_body = {
24632+ .attrs = au_attr
24633+};
24634+
24635+struct attribute_group *sysaufs_attr_group = &sysaufs_attr_group_body;
24636+
24637+/* ---------------------------------------------------------------------- */
24638+
24639+int sysaufs_si_xi_path(struct seq_file *seq, struct super_block *sb)
24640+{
24641+ int err;
24642+
dece6358
AM
24643+ SiMustAnyLock(sb);
24644+
1facf9fc 24645+ err = 0;
24646+ if (au_opt_test(au_mntflags(sb), XINO)) {
24647+ err = au_xino_path(seq, au_sbi(sb)->si_xib);
24648+ seq_putc(seq, '\n');
24649+ }
24650+ return err;
24651+}
24652+
24653+/*
24654+ * the lifetime of branch is independent from the entry under sysfs.
24655+ * sysfs handles the lifetime of the entry, and never call ->show() after it is
24656+ * unlinked.
24657+ */
24658+static int sysaufs_si_br(struct seq_file *seq, struct super_block *sb,
24659+ aufs_bindex_t bindex)
24660+{
1e00d052 24661+ int err;
1facf9fc 24662+ struct path path;
24663+ struct dentry *root;
24664+ struct au_branch *br;
1e00d052 24665+ char *perm;
1facf9fc 24666+
24667+ AuDbg("b%d\n", bindex);
24668+
1e00d052 24669+ err = 0;
1facf9fc 24670+ root = sb->s_root;
24671+ di_read_lock_parent(root, !AuLock_IR);
24672+ br = au_sbr(sb, bindex);
24673+ path.mnt = br->br_mnt;
24674+ path.dentry = au_h_dptr(root, bindex);
24675+ au_seq_path(seq, &path);
24676+ di_read_unlock(root, !AuLock_IR);
1e00d052
AM
24677+ perm = au_optstr_br_perm(br->br_perm);
24678+ if (perm) {
24679+ err = seq_printf(seq, "=%s\n", perm);
24680+ kfree(perm);
24681+ if (err == -1)
24682+ err = -E2BIG;
24683+ } else
24684+ err = -ENOMEM;
24685+ return err;
1facf9fc 24686+}
24687+
24688+/* ---------------------------------------------------------------------- */
24689+
24690+static struct seq_file *au_seq(char *p, ssize_t len)
24691+{
24692+ struct seq_file *seq;
24693+
24694+ seq = kzalloc(sizeof(*seq), GFP_NOFS);
24695+ if (seq) {
24696+ /* mutex_init(&seq.lock); */
24697+ seq->buf = p;
24698+ seq->size = len;
24699+ return seq; /* success */
24700+ }
24701+
24702+ seq = ERR_PTR(-ENOMEM);
24703+ return seq;
24704+}
24705+
24706+#define SysaufsBr_PREFIX "br"
24707+
24708+/* todo: file size may exceed PAGE_SIZE */
24709+ssize_t sysaufs_si_show(struct kobject *kobj, struct attribute *attr,
1308ab2a 24710+ char *buf)
1facf9fc 24711+{
24712+ ssize_t err;
24713+ long l;
24714+ aufs_bindex_t bend;
24715+ struct au_sbinfo *sbinfo;
24716+ struct super_block *sb;
24717+ struct seq_file *seq;
24718+ char *name;
24719+ struct attribute **cattr;
24720+
24721+ sbinfo = container_of(kobj, struct au_sbinfo, si_kobj);
24722+ sb = sbinfo->si_sb;
1308ab2a 24723+
24724+ /*
24725+ * prevent a race condition between sysfs and aufs.
24726+ * for instance, sysfs_file_read() calls sysfs_get_active_two() which
24727+ * prohibits maintaining the sysfs entries.
24728+ * hew we acquire read lock after sysfs_get_active_two().
24729+ * on the other hand, the remount process may maintain the sysfs/aufs
24730+ * entries after acquiring write lock.
24731+ * it can cause a deadlock.
24732+ * simply we gave up processing read here.
24733+ */
24734+ err = -EBUSY;
24735+ if (unlikely(!si_noflush_read_trylock(sb)))
24736+ goto out;
1facf9fc 24737+
24738+ seq = au_seq(buf, PAGE_SIZE);
24739+ err = PTR_ERR(seq);
24740+ if (IS_ERR(seq))
1308ab2a 24741+ goto out_unlock;
1facf9fc 24742+
24743+ name = (void *)attr->name;
24744+ cattr = sysaufs_si_attrs;
24745+ while (*cattr) {
24746+ if (!strcmp(name, (*cattr)->name)) {
24747+ err = container_of(*cattr, struct sysaufs_si_attr, attr)
24748+ ->show(seq, sb);
24749+ goto out_seq;
24750+ }
24751+ cattr++;
24752+ }
24753+
24754+ bend = au_sbend(sb);
24755+ if (!strncmp(name, SysaufsBr_PREFIX, sizeof(SysaufsBr_PREFIX) - 1)) {
24756+ name += sizeof(SysaufsBr_PREFIX) - 1;
9dbd164d 24757+ err = kstrtol(name, 10, &l);
1facf9fc 24758+ if (!err) {
24759+ if (l <= bend)
24760+ err = sysaufs_si_br(seq, sb, (aufs_bindex_t)l);
24761+ else
24762+ err = -ENOENT;
24763+ }
24764+ goto out_seq;
24765+ }
24766+ BUG();
24767+
4f0767ce 24768+out_seq:
1facf9fc 24769+ if (!err) {
24770+ err = seq->count;
24771+ /* sysfs limit */
24772+ if (unlikely(err == PAGE_SIZE))
24773+ err = -EFBIG;
24774+ }
24775+ kfree(seq);
4f0767ce 24776+out_unlock:
1facf9fc 24777+ si_read_unlock(sb);
4f0767ce 24778+out:
1facf9fc 24779+ return err;
24780+}
24781+
24782+/* ---------------------------------------------------------------------- */
24783+
24784+void sysaufs_br_init(struct au_branch *br)
24785+{
4a4d8108
AM
24786+ struct attribute *attr = &br->br_attr;
24787+
24788+ sysfs_attr_init(attr);
24789+ attr->name = br->br_name;
24790+ attr->mode = S_IRUGO;
1facf9fc 24791+}
24792+
24793+void sysaufs_brs_del(struct super_block *sb, aufs_bindex_t bindex)
24794+{
24795+ struct au_branch *br;
24796+ struct kobject *kobj;
24797+ aufs_bindex_t bend;
24798+
24799+ dbgaufs_brs_del(sb, bindex);
24800+
24801+ if (!sysaufs_brs)
24802+ return;
24803+
24804+ kobj = &au_sbi(sb)->si_kobj;
24805+ bend = au_sbend(sb);
24806+ for (; bindex <= bend; bindex++) {
24807+ br = au_sbr(sb, bindex);
24808+ sysfs_remove_file(kobj, &br->br_attr);
24809+ }
24810+}
24811+
24812+void sysaufs_brs_add(struct super_block *sb, aufs_bindex_t bindex)
24813+{
24814+ int err;
24815+ aufs_bindex_t bend;
24816+ struct kobject *kobj;
24817+ struct au_branch *br;
24818+
24819+ dbgaufs_brs_add(sb, bindex);
24820+
24821+ if (!sysaufs_brs)
24822+ return;
24823+
24824+ kobj = &au_sbi(sb)->si_kobj;
24825+ bend = au_sbend(sb);
24826+ for (; bindex <= bend; bindex++) {
24827+ br = au_sbr(sb, bindex);
24828+ snprintf(br->br_name, sizeof(br->br_name), SysaufsBr_PREFIX
24829+ "%d", bindex);
24830+ err = sysfs_create_file(kobj, &br->br_attr);
24831+ if (unlikely(err))
0c3ec466
AM
24832+ pr_warn("failed %s under sysfs(%d)\n",
24833+ br->br_name, err);
1facf9fc 24834+ }
24835+}
7f207e10
AM
24836diff -urN /usr/share/empty/fs/aufs/sysrq.c linux/fs/aufs/sysrq.c
24837--- /usr/share/empty/fs/aufs/sysrq.c 1970-01-01 01:00:00.000000000 +0100
537831f9 24838+++ linux/fs/aufs/sysrq.c 2012-12-13 20:41:10.431460173 +0100
f6c5ef8b 24839@@ -0,0 +1,148 @@
1facf9fc 24840+/*
f6c5ef8b 24841+ * Copyright (C) 2005-2012 Junjiro R. Okajima
1facf9fc 24842+ *
24843+ * This program, aufs is free software; you can redistribute it and/or modify
24844+ * it under the terms of the GNU General Public License as published by
24845+ * the Free Software Foundation; either version 2 of the License, or
24846+ * (at your option) any later version.
dece6358
AM
24847+ *
24848+ * This program is distributed in the hope that it will be useful,
24849+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
24850+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24851+ * GNU General Public License for more details.
24852+ *
24853+ * You should have received a copy of the GNU General Public License
24854+ * along with this program; if not, write to the Free Software
24855+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 24856+ */
24857+
24858+/*
24859+ * magic sysrq hanlder
24860+ */
24861+
1facf9fc 24862+/* #include <linux/sysrq.h> */
027c5e7a 24863+#include <linux/writeback.h>
1facf9fc 24864+#include "aufs.h"
24865+
24866+/* ---------------------------------------------------------------------- */
24867+
24868+static void sysrq_sb(struct super_block *sb)
24869+{
24870+ char *plevel;
24871+ struct au_sbinfo *sbinfo;
24872+ struct file *file;
24873+
24874+ plevel = au_plevel;
24875+ au_plevel = KERN_WARNING;
1facf9fc 24876+
24877+ sbinfo = au_sbi(sb);
4a4d8108
AM
24878+ /* since we define pr_fmt, call printk directly */
24879+ printk(KERN_WARNING "si=%lx\n", sysaufs_si_id(sbinfo));
24880+ printk(KERN_WARNING AUFS_NAME ": superblock\n");
1facf9fc 24881+ au_dpri_sb(sb);
027c5e7a
AM
24882+
24883+#if 0
4a4d8108 24884+ printk(KERN_WARNING AUFS_NAME ": root dentry\n");
1facf9fc 24885+ au_dpri_dentry(sb->s_root);
4a4d8108 24886+ printk(KERN_WARNING AUFS_NAME ": root inode\n");
1facf9fc 24887+ au_dpri_inode(sb->s_root->d_inode);
027c5e7a
AM
24888+#endif
24889+
1facf9fc 24890+#if 0
027c5e7a
AM
24891+ do {
24892+ int err, i, j, ndentry;
24893+ struct au_dcsub_pages dpages;
24894+ struct au_dpage *dpage;
24895+
24896+ err = au_dpages_init(&dpages, GFP_ATOMIC);
24897+ if (unlikely(err))
24898+ break;
24899+ err = au_dcsub_pages(&dpages, sb->s_root, NULL, NULL);
24900+ if (!err)
24901+ for (i = 0; i < dpages.ndpage; i++) {
24902+ dpage = dpages.dpages + i;
24903+ ndentry = dpage->ndentry;
24904+ for (j = 0; j < ndentry; j++)
24905+ au_dpri_dentry(dpage->dentries[j]);
24906+ }
24907+ au_dpages_free(&dpages);
24908+ } while (0);
24909+#endif
24910+
24911+#if 1
24912+ {
24913+ struct inode *i;
24914+ printk(KERN_WARNING AUFS_NAME ": isolated inode\n");
2cbb1c4b
JR
24915+ spin_lock(&inode_sb_list_lock);
24916+ list_for_each_entry(i, &sb->s_inodes, i_sb_list) {
24917+ spin_lock(&i->i_lock);
b4510431 24918+ if (1 || hlist_empty(&i->i_dentry))
027c5e7a 24919+ au_dpri_inode(i);
2cbb1c4b
JR
24920+ spin_unlock(&i->i_lock);
24921+ }
24922+ spin_unlock(&inode_sb_list_lock);
027c5e7a 24923+ }
1facf9fc 24924+#endif
4a4d8108 24925+ printk(KERN_WARNING AUFS_NAME ": files\n");
0c3ec466 24926+ lg_global_lock(&files_lglock);
0c5527e5 24927+ do_file_list_for_each_entry(sb, file) {
4a4d8108
AM
24928+ umode_t mode;
24929+ mode = file->f_dentry->d_inode->i_mode;
24930+ if (!special_file(mode) || au_special_file(mode))
1facf9fc 24931+ au_dpri_file(file);
0c5527e5 24932+ } while_file_list_for_each_entry;
0c3ec466 24933+ lg_global_unlock(&files_lglock);
e49829fe 24934+ printk(KERN_WARNING AUFS_NAME ": done\n");
1facf9fc 24935+
24936+ au_plevel = plevel;
1facf9fc 24937+}
24938+
24939+/* ---------------------------------------------------------------------- */
24940+
24941+/* module parameter */
24942+static char *aufs_sysrq_key = "a";
24943+module_param_named(sysrq, aufs_sysrq_key, charp, S_IRUGO);
24944+MODULE_PARM_DESC(sysrq, "MagicSysRq key for " AUFS_NAME);
24945+
0c5527e5 24946+static void au_sysrq(int key __maybe_unused)
1facf9fc 24947+{
1facf9fc 24948+ struct au_sbinfo *sbinfo;
24949+
027c5e7a 24950+ lockdep_off();
53392da6 24951+ au_sbilist_lock();
e49829fe 24952+ list_for_each_entry(sbinfo, &au_sbilist.head, si_list)
1facf9fc 24953+ sysrq_sb(sbinfo->si_sb);
53392da6 24954+ au_sbilist_unlock();
027c5e7a 24955+ lockdep_on();
1facf9fc 24956+}
24957+
24958+static struct sysrq_key_op au_sysrq_op = {
24959+ .handler = au_sysrq,
24960+ .help_msg = "Aufs",
24961+ .action_msg = "Aufs",
24962+ .enable_mask = SYSRQ_ENABLE_DUMP
24963+};
24964+
24965+/* ---------------------------------------------------------------------- */
24966+
24967+int __init au_sysrq_init(void)
24968+{
24969+ int err;
24970+ char key;
24971+
24972+ err = -1;
24973+ key = *aufs_sysrq_key;
24974+ if ('a' <= key && key <= 'z')
24975+ err = register_sysrq_key(key, &au_sysrq_op);
24976+ if (unlikely(err))
4a4d8108 24977+ pr_err("err %d, sysrq=%c\n", err, key);
1facf9fc 24978+ return err;
24979+}
24980+
24981+void au_sysrq_fin(void)
24982+{
24983+ int err;
24984+ err = unregister_sysrq_key(*aufs_sysrq_key, &au_sysrq_op);
24985+ if (unlikely(err))
4a4d8108 24986+ pr_err("err %d (ignored)\n", err);
1facf9fc 24987+}
7f207e10
AM
24988diff -urN /usr/share/empty/fs/aufs/vdir.c linux/fs/aufs/vdir.c
24989--- /usr/share/empty/fs/aufs/vdir.c 1970-01-01 01:00:00.000000000 +0100
537831f9 24990+++ linux/fs/aufs/vdir.c 2012-12-13 20:41:10.434793588 +0100
f6c5ef8b 24991@@ -0,0 +1,885 @@
1facf9fc 24992+/*
f6c5ef8b 24993+ * Copyright (C) 2005-2012 Junjiro R. Okajima
1facf9fc 24994+ *
24995+ * This program, aufs is free software; you can redistribute it and/or modify
24996+ * it under the terms of the GNU General Public License as published by
24997+ * the Free Software Foundation; either version 2 of the License, or
24998+ * (at your option) any later version.
dece6358
AM
24999+ *
25000+ * This program is distributed in the hope that it will be useful,
25001+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
25002+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
25003+ * GNU General Public License for more details.
25004+ *
25005+ * You should have received a copy of the GNU General Public License
25006+ * along with this program; if not, write to the Free Software
25007+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 25008+ */
25009+
25010+/*
25011+ * virtual or vertical directory
25012+ */
25013+
25014+#include "aufs.h"
25015+
dece6358 25016+static unsigned int calc_size(int nlen)
1facf9fc 25017+{
dece6358 25018+ return ALIGN(sizeof(struct au_vdir_de) + nlen, sizeof(ino_t));
1facf9fc 25019+}
25020+
25021+static int set_deblk_end(union au_vdir_deblk_p *p,
25022+ union au_vdir_deblk_p *deblk_end)
25023+{
25024+ if (calc_size(0) <= deblk_end->deblk - p->deblk) {
25025+ p->de->de_str.len = 0;
25026+ /* smp_mb(); */
25027+ return 0;
25028+ }
25029+ return -1; /* error */
25030+}
25031+
25032+/* returns true or false */
25033+static int is_deblk_end(union au_vdir_deblk_p *p,
25034+ union au_vdir_deblk_p *deblk_end)
25035+{
25036+ if (calc_size(0) <= deblk_end->deblk - p->deblk)
25037+ return !p->de->de_str.len;
25038+ return 1;
25039+}
25040+
25041+static unsigned char *last_deblk(struct au_vdir *vdir)
25042+{
25043+ return vdir->vd_deblk[vdir->vd_nblk - 1];
25044+}
25045+
25046+/* ---------------------------------------------------------------------- */
25047+
1308ab2a 25048+/* estimate the apropriate size for name hash table */
25049+unsigned int au_rdhash_est(loff_t sz)
25050+{
25051+ unsigned int n;
25052+
25053+ n = UINT_MAX;
25054+ sz >>= 10;
25055+ if (sz < n)
25056+ n = sz;
25057+ if (sz < AUFS_RDHASH_DEF)
25058+ n = AUFS_RDHASH_DEF;
4a4d8108 25059+ /* pr_info("n %u\n", n); */
1308ab2a 25060+ return n;
25061+}
25062+
1facf9fc 25063+/*
25064+ * the allocated memory has to be freed by
dece6358 25065+ * au_nhash_wh_free() or au_nhash_de_free().
1facf9fc 25066+ */
dece6358 25067+int au_nhash_alloc(struct au_nhash *nhash, unsigned int num_hash, gfp_t gfp)
1facf9fc 25068+{
1facf9fc 25069+ struct hlist_head *head;
dece6358 25070+ unsigned int u;
1facf9fc 25071+
dece6358
AM
25072+ head = kmalloc(sizeof(*nhash->nh_head) * num_hash, gfp);
25073+ if (head) {
25074+ nhash->nh_num = num_hash;
25075+ nhash->nh_head = head;
25076+ for (u = 0; u < num_hash; u++)
1facf9fc 25077+ INIT_HLIST_HEAD(head++);
dece6358 25078+ return 0; /* success */
1facf9fc 25079+ }
1facf9fc 25080+
dece6358 25081+ return -ENOMEM;
1facf9fc 25082+}
25083+
dece6358
AM
25084+static void nhash_count(struct hlist_head *head)
25085+{
25086+#if 0
25087+ unsigned long n;
25088+ struct hlist_node *pos;
25089+
25090+ n = 0;
25091+ hlist_for_each(pos, head)
25092+ n++;
4a4d8108 25093+ pr_info("%lu\n", n);
dece6358
AM
25094+#endif
25095+}
25096+
25097+static void au_nhash_wh_do_free(struct hlist_head *head)
1facf9fc 25098+{
1facf9fc 25099+ struct au_vdir_wh *tpos;
25100+ struct hlist_node *pos, *node;
25101+
dece6358
AM
25102+ hlist_for_each_entry_safe(tpos, pos, node, head, wh_hash) {
25103+ /* hlist_del(pos); */
25104+ kfree(tpos);
1facf9fc 25105+ }
25106+}
25107+
dece6358 25108+static void au_nhash_de_do_free(struct hlist_head *head)
1facf9fc 25109+{
dece6358
AM
25110+ struct au_vdir_dehstr *tpos;
25111+ struct hlist_node *pos, *node;
1facf9fc 25112+
dece6358
AM
25113+ hlist_for_each_entry_safe(tpos, pos, node, head, hash) {
25114+ /* hlist_del(pos); */
4a4d8108 25115+ au_cache_free_vdir_dehstr(tpos);
1facf9fc 25116+ }
1facf9fc 25117+}
25118+
dece6358
AM
25119+static void au_nhash_do_free(struct au_nhash *nhash,
25120+ void (*free)(struct hlist_head *head))
1facf9fc 25121+{
1308ab2a 25122+ unsigned int n;
1facf9fc 25123+ struct hlist_head *head;
1facf9fc 25124+
dece6358 25125+ n = nhash->nh_num;
1308ab2a 25126+ if (!n)
25127+ return;
25128+
dece6358 25129+ head = nhash->nh_head;
1308ab2a 25130+ while (n-- > 0) {
dece6358
AM
25131+ nhash_count(head);
25132+ free(head++);
1facf9fc 25133+ }
dece6358 25134+ kfree(nhash->nh_head);
1facf9fc 25135+}
25136+
dece6358 25137+void au_nhash_wh_free(struct au_nhash *whlist)
1facf9fc 25138+{
dece6358
AM
25139+ au_nhash_do_free(whlist, au_nhash_wh_do_free);
25140+}
1facf9fc 25141+
dece6358
AM
25142+static void au_nhash_de_free(struct au_nhash *delist)
25143+{
25144+ au_nhash_do_free(delist, au_nhash_de_do_free);
1facf9fc 25145+}
25146+
25147+/* ---------------------------------------------------------------------- */
25148+
25149+int au_nhash_test_longer_wh(struct au_nhash *whlist, aufs_bindex_t btgt,
25150+ int limit)
25151+{
25152+ int num;
25153+ unsigned int u, n;
25154+ struct hlist_head *head;
25155+ struct au_vdir_wh *tpos;
25156+ struct hlist_node *pos;
25157+
25158+ num = 0;
25159+ n = whlist->nh_num;
25160+ head = whlist->nh_head;
1308ab2a 25161+ for (u = 0; u < n; u++, head++)
1facf9fc 25162+ hlist_for_each_entry(tpos, pos, head, wh_hash)
25163+ if (tpos->wh_bindex == btgt && ++num > limit)
25164+ return 1;
1facf9fc 25165+ return 0;
25166+}
25167+
25168+static struct hlist_head *au_name_hash(struct au_nhash *nhash,
dece6358 25169+ unsigned char *name,
1facf9fc 25170+ unsigned int len)
25171+{
dece6358
AM
25172+ unsigned int v;
25173+ /* const unsigned int magic_bit = 12; */
25174+
1308ab2a 25175+ AuDebugOn(!nhash->nh_num || !nhash->nh_head);
25176+
dece6358
AM
25177+ v = 0;
25178+ while (len--)
25179+ v += *name++;
25180+ /* v = hash_long(v, magic_bit); */
25181+ v %= nhash->nh_num;
25182+ return nhash->nh_head + v;
25183+}
25184+
25185+static int au_nhash_test_name(struct au_vdir_destr *str, const char *name,
25186+ int nlen)
25187+{
25188+ return str->len == nlen && !memcmp(str->name, name, nlen);
1facf9fc 25189+}
25190+
25191+/* returns found or not */
dece6358 25192+int au_nhash_test_known_wh(struct au_nhash *whlist, char *name, int nlen)
1facf9fc 25193+{
25194+ struct hlist_head *head;
25195+ struct au_vdir_wh *tpos;
25196+ struct hlist_node *pos;
25197+ struct au_vdir_destr *str;
25198+
dece6358 25199+ head = au_name_hash(whlist, name, nlen);
1facf9fc 25200+ hlist_for_each_entry(tpos, pos, head, wh_hash) {
25201+ str = &tpos->wh_str;
25202+ AuDbg("%.*s\n", str->len, str->name);
dece6358
AM
25203+ if (au_nhash_test_name(str, name, nlen))
25204+ return 1;
25205+ }
25206+ return 0;
25207+}
25208+
25209+/* returns found(true) or not */
25210+static int test_known(struct au_nhash *delist, char *name, int nlen)
25211+{
25212+ struct hlist_head *head;
25213+ struct au_vdir_dehstr *tpos;
25214+ struct hlist_node *pos;
25215+ struct au_vdir_destr *str;
25216+
25217+ head = au_name_hash(delist, name, nlen);
25218+ hlist_for_each_entry(tpos, pos, head, hash) {
25219+ str = tpos->str;
25220+ AuDbg("%.*s\n", str->len, str->name);
25221+ if (au_nhash_test_name(str, name, nlen))
1facf9fc 25222+ return 1;
25223+ }
25224+ return 0;
25225+}
25226+
dece6358
AM
25227+static void au_shwh_init_wh(struct au_vdir_wh *wh, ino_t ino,
25228+ unsigned char d_type)
25229+{
25230+#ifdef CONFIG_AUFS_SHWH
25231+ wh->wh_ino = ino;
25232+ wh->wh_type = d_type;
25233+#endif
25234+}
25235+
25236+/* ---------------------------------------------------------------------- */
25237+
25238+int au_nhash_append_wh(struct au_nhash *whlist, char *name, int nlen, ino_t ino,
25239+ unsigned int d_type, aufs_bindex_t bindex,
25240+ unsigned char shwh)
1facf9fc 25241+{
25242+ int err;
25243+ struct au_vdir_destr *str;
25244+ struct au_vdir_wh *wh;
25245+
dece6358 25246+ AuDbg("%.*s\n", nlen, name);
1308ab2a 25247+ AuDebugOn(!whlist->nh_num || !whlist->nh_head);
25248+
1facf9fc 25249+ err = -ENOMEM;
dece6358 25250+ wh = kmalloc(sizeof(*wh) + nlen, GFP_NOFS);
1facf9fc 25251+ if (unlikely(!wh))
25252+ goto out;
25253+
25254+ err = 0;
25255+ wh->wh_bindex = bindex;
dece6358
AM
25256+ if (shwh)
25257+ au_shwh_init_wh(wh, ino, d_type);
1facf9fc 25258+ str = &wh->wh_str;
dece6358
AM
25259+ str->len = nlen;
25260+ memcpy(str->name, name, nlen);
25261+ hlist_add_head(&wh->wh_hash, au_name_hash(whlist, name, nlen));
1facf9fc 25262+ /* smp_mb(); */
25263+
4f0767ce 25264+out:
1facf9fc 25265+ return err;
25266+}
25267+
1facf9fc 25268+static int append_deblk(struct au_vdir *vdir)
25269+{
25270+ int err;
dece6358 25271+ unsigned long ul;
1facf9fc 25272+ const unsigned int deblk_sz = vdir->vd_deblk_sz;
25273+ union au_vdir_deblk_p p, deblk_end;
25274+ unsigned char **o;
25275+
25276+ err = -ENOMEM;
dece6358
AM
25277+ o = krealloc(vdir->vd_deblk, sizeof(*o) * (vdir->vd_nblk + 1),
25278+ GFP_NOFS);
1facf9fc 25279+ if (unlikely(!o))
25280+ goto out;
25281+
25282+ vdir->vd_deblk = o;
25283+ p.deblk = kmalloc(deblk_sz, GFP_NOFS);
25284+ if (p.deblk) {
25285+ ul = vdir->vd_nblk++;
25286+ vdir->vd_deblk[ul] = p.deblk;
25287+ vdir->vd_last.ul = ul;
25288+ vdir->vd_last.p.deblk = p.deblk;
25289+ deblk_end.deblk = p.deblk + deblk_sz;
25290+ err = set_deblk_end(&p, &deblk_end);
25291+ }
25292+
4f0767ce 25293+out:
1facf9fc 25294+ return err;
25295+}
25296+
dece6358
AM
25297+static int append_de(struct au_vdir *vdir, char *name, int nlen, ino_t ino,
25298+ unsigned int d_type, struct au_nhash *delist)
25299+{
25300+ int err;
25301+ unsigned int sz;
25302+ const unsigned int deblk_sz = vdir->vd_deblk_sz;
25303+ union au_vdir_deblk_p p, *room, deblk_end;
25304+ struct au_vdir_dehstr *dehstr;
25305+
25306+ p.deblk = last_deblk(vdir);
25307+ deblk_end.deblk = p.deblk + deblk_sz;
25308+ room = &vdir->vd_last.p;
25309+ AuDebugOn(room->deblk < p.deblk || deblk_end.deblk <= room->deblk
25310+ || !is_deblk_end(room, &deblk_end));
25311+
25312+ sz = calc_size(nlen);
25313+ if (unlikely(sz > deblk_end.deblk - room->deblk)) {
25314+ err = append_deblk(vdir);
25315+ if (unlikely(err))
25316+ goto out;
25317+
25318+ p.deblk = last_deblk(vdir);
25319+ deblk_end.deblk = p.deblk + deblk_sz;
25320+ /* smp_mb(); */
25321+ AuDebugOn(room->deblk != p.deblk);
25322+ }
25323+
25324+ err = -ENOMEM;
4a4d8108 25325+ dehstr = au_cache_alloc_vdir_dehstr();
dece6358
AM
25326+ if (unlikely(!dehstr))
25327+ goto out;
25328+
25329+ dehstr->str = &room->de->de_str;
25330+ hlist_add_head(&dehstr->hash, au_name_hash(delist, name, nlen));
25331+ room->de->de_ino = ino;
25332+ room->de->de_type = d_type;
25333+ room->de->de_str.len = nlen;
25334+ memcpy(room->de->de_str.name, name, nlen);
25335+
25336+ err = 0;
25337+ room->deblk += sz;
25338+ if (unlikely(set_deblk_end(room, &deblk_end)))
25339+ err = append_deblk(vdir);
25340+ /* smp_mb(); */
25341+
4f0767ce 25342+out:
dece6358
AM
25343+ return err;
25344+}
25345+
25346+/* ---------------------------------------------------------------------- */
25347+
25348+void au_vdir_free(struct au_vdir *vdir)
25349+{
25350+ unsigned char **deblk;
25351+
25352+ deblk = vdir->vd_deblk;
25353+ while (vdir->vd_nblk--)
25354+ kfree(*deblk++);
25355+ kfree(vdir->vd_deblk);
25356+ au_cache_free_vdir(vdir);
25357+}
25358+
1308ab2a 25359+static struct au_vdir *alloc_vdir(struct file *file)
1facf9fc 25360+{
25361+ struct au_vdir *vdir;
1308ab2a 25362+ struct super_block *sb;
1facf9fc 25363+ int err;
25364+
1308ab2a 25365+ sb = file->f_dentry->d_sb;
dece6358
AM
25366+ SiMustAnyLock(sb);
25367+
1facf9fc 25368+ err = -ENOMEM;
25369+ vdir = au_cache_alloc_vdir();
25370+ if (unlikely(!vdir))
25371+ goto out;
25372+
25373+ vdir->vd_deblk = kzalloc(sizeof(*vdir->vd_deblk), GFP_NOFS);
25374+ if (unlikely(!vdir->vd_deblk))
25375+ goto out_free;
25376+
25377+ vdir->vd_deblk_sz = au_sbi(sb)->si_rdblk;
1308ab2a 25378+ if (!vdir->vd_deblk_sz) {
25379+ /* estimate the apropriate size for deblk */
25380+ vdir->vd_deblk_sz = au_dir_size(file, /*dentry*/NULL);
4a4d8108 25381+ /* pr_info("vd_deblk_sz %u\n", vdir->vd_deblk_sz); */
1308ab2a 25382+ }
1facf9fc 25383+ vdir->vd_nblk = 0;
25384+ vdir->vd_version = 0;
25385+ vdir->vd_jiffy = 0;
25386+ err = append_deblk(vdir);
25387+ if (!err)
25388+ return vdir; /* success */
25389+
25390+ kfree(vdir->vd_deblk);
25391+
4f0767ce 25392+out_free:
1facf9fc 25393+ au_cache_free_vdir(vdir);
4f0767ce 25394+out:
1facf9fc 25395+ vdir = ERR_PTR(err);
25396+ return vdir;
25397+}
25398+
25399+static int reinit_vdir(struct au_vdir *vdir)
25400+{
25401+ int err;
25402+ union au_vdir_deblk_p p, deblk_end;
25403+
25404+ while (vdir->vd_nblk > 1) {
25405+ kfree(vdir->vd_deblk[vdir->vd_nblk - 1]);
25406+ /* vdir->vd_deblk[vdir->vd_nblk - 1] = NULL; */
25407+ vdir->vd_nblk--;
25408+ }
25409+ p.deblk = vdir->vd_deblk[0];
25410+ deblk_end.deblk = p.deblk + vdir->vd_deblk_sz;
25411+ err = set_deblk_end(&p, &deblk_end);
25412+ /* keep vd_dblk_sz */
25413+ vdir->vd_last.ul = 0;
25414+ vdir->vd_last.p.deblk = vdir->vd_deblk[0];
25415+ vdir->vd_version = 0;
25416+ vdir->vd_jiffy = 0;
25417+ /* smp_mb(); */
25418+ return err;
25419+}
25420+
25421+/* ---------------------------------------------------------------------- */
25422+
1facf9fc 25423+#define AuFillVdir_CALLED 1
25424+#define AuFillVdir_WHABLE (1 << 1)
dece6358 25425+#define AuFillVdir_SHWH (1 << 2)
1facf9fc 25426+#define au_ftest_fillvdir(flags, name) ((flags) & AuFillVdir_##name)
7f207e10
AM
25427+#define au_fset_fillvdir(flags, name) \
25428+ do { (flags) |= AuFillVdir_##name; } while (0)
25429+#define au_fclr_fillvdir(flags, name) \
25430+ do { (flags) &= ~AuFillVdir_##name; } while (0)
1facf9fc 25431+
dece6358
AM
25432+#ifndef CONFIG_AUFS_SHWH
25433+#undef AuFillVdir_SHWH
25434+#define AuFillVdir_SHWH 0
25435+#endif
25436+
1facf9fc 25437+struct fillvdir_arg {
25438+ struct file *file;
25439+ struct au_vdir *vdir;
dece6358
AM
25440+ struct au_nhash delist;
25441+ struct au_nhash whlist;
1facf9fc 25442+ aufs_bindex_t bindex;
25443+ unsigned int flags;
25444+ int err;
25445+};
25446+
dece6358 25447+static int fillvdir(void *__arg, const char *__name, int nlen,
1facf9fc 25448+ loff_t offset __maybe_unused, u64 h_ino,
25449+ unsigned int d_type)
25450+{
25451+ struct fillvdir_arg *arg = __arg;
25452+ char *name = (void *)__name;
25453+ struct super_block *sb;
1facf9fc 25454+ ino_t ino;
dece6358 25455+ const unsigned char shwh = !!au_ftest_fillvdir(arg->flags, SHWH);
1facf9fc 25456+
1facf9fc 25457+ arg->err = 0;
dece6358 25458+ sb = arg->file->f_dentry->d_sb;
1facf9fc 25459+ au_fset_fillvdir(arg->flags, CALLED);
25460+ /* smp_mb(); */
dece6358 25461+ if (nlen <= AUFS_WH_PFX_LEN
1facf9fc 25462+ || memcmp(name, AUFS_WH_PFX, AUFS_WH_PFX_LEN)) {
dece6358
AM
25463+ if (test_known(&arg->delist, name, nlen)
25464+ || au_nhash_test_known_wh(&arg->whlist, name, nlen))
25465+ goto out; /* already exists or whiteouted */
1facf9fc 25466+
25467+ sb = arg->file->f_dentry->d_sb;
dece6358 25468+ arg->err = au_ino(sb, arg->bindex, h_ino, d_type, &ino);
4a4d8108
AM
25469+ if (!arg->err) {
25470+ if (unlikely(nlen > AUFS_MAX_NAMELEN))
25471+ d_type = DT_UNKNOWN;
dece6358
AM
25472+ arg->err = append_de(arg->vdir, name, nlen, ino,
25473+ d_type, &arg->delist);
4a4d8108 25474+ }
1facf9fc 25475+ } else if (au_ftest_fillvdir(arg->flags, WHABLE)) {
25476+ name += AUFS_WH_PFX_LEN;
dece6358
AM
25477+ nlen -= AUFS_WH_PFX_LEN;
25478+ if (au_nhash_test_known_wh(&arg->whlist, name, nlen))
25479+ goto out; /* already whiteouted */
1facf9fc 25480+
dece6358
AM
25481+ if (shwh)
25482+ arg->err = au_wh_ino(sb, arg->bindex, h_ino, d_type,
25483+ &ino);
4a4d8108
AM
25484+ if (!arg->err) {
25485+ if (nlen <= AUFS_MAX_NAMELEN + AUFS_WH_PFX_LEN)
25486+ d_type = DT_UNKNOWN;
1facf9fc 25487+ arg->err = au_nhash_append_wh
dece6358
AM
25488+ (&arg->whlist, name, nlen, ino, d_type,
25489+ arg->bindex, shwh);
4a4d8108 25490+ }
1facf9fc 25491+ }
25492+
4f0767ce 25493+out:
1facf9fc 25494+ if (!arg->err)
25495+ arg->vdir->vd_jiffy = jiffies;
25496+ /* smp_mb(); */
25497+ AuTraceErr(arg->err);
25498+ return arg->err;
25499+}
25500+
dece6358
AM
25501+static int au_handle_shwh(struct super_block *sb, struct au_vdir *vdir,
25502+ struct au_nhash *whlist, struct au_nhash *delist)
25503+{
25504+#ifdef CONFIG_AUFS_SHWH
25505+ int err;
25506+ unsigned int nh, u;
25507+ struct hlist_head *head;
25508+ struct au_vdir_wh *tpos;
25509+ struct hlist_node *pos, *n;
25510+ char *p, *o;
25511+ struct au_vdir_destr *destr;
25512+
25513+ AuDebugOn(!au_opt_test(au_mntflags(sb), SHWH));
25514+
25515+ err = -ENOMEM;
537831f9 25516+ o = p = (void *)__get_free_page(GFP_NOFS);
dece6358
AM
25517+ if (unlikely(!p))
25518+ goto out;
25519+
25520+ err = 0;
25521+ nh = whlist->nh_num;
25522+ memcpy(p, AUFS_WH_PFX, AUFS_WH_PFX_LEN);
25523+ p += AUFS_WH_PFX_LEN;
25524+ for (u = 0; u < nh; u++) {
25525+ head = whlist->nh_head + u;
25526+ hlist_for_each_entry_safe(tpos, pos, n, head, wh_hash) {
25527+ destr = &tpos->wh_str;
25528+ memcpy(p, destr->name, destr->len);
25529+ err = append_de(vdir, o, destr->len + AUFS_WH_PFX_LEN,
25530+ tpos->wh_ino, tpos->wh_type, delist);
25531+ if (unlikely(err))
25532+ break;
25533+ }
25534+ }
25535+
537831f9 25536+ free_page((unsigned long)o);
dece6358 25537+
4f0767ce 25538+out:
dece6358
AM
25539+ AuTraceErr(err);
25540+ return err;
25541+#else
25542+ return 0;
25543+#endif
25544+}
25545+
1facf9fc 25546+static int au_do_read_vdir(struct fillvdir_arg *arg)
25547+{
25548+ int err;
dece6358 25549+ unsigned int rdhash;
1facf9fc 25550+ loff_t offset;
dece6358
AM
25551+ aufs_bindex_t bend, bindex, bstart;
25552+ unsigned char shwh;
1facf9fc 25553+ struct file *hf, *file;
25554+ struct super_block *sb;
25555+
1facf9fc 25556+ file = arg->file;
25557+ sb = file->f_dentry->d_sb;
dece6358
AM
25558+ SiMustAnyLock(sb);
25559+
25560+ rdhash = au_sbi(sb)->si_rdhash;
1308ab2a 25561+ if (!rdhash)
25562+ rdhash = au_rdhash_est(au_dir_size(file, /*dentry*/NULL));
dece6358
AM
25563+ err = au_nhash_alloc(&arg->delist, rdhash, GFP_NOFS);
25564+ if (unlikely(err))
1facf9fc 25565+ goto out;
dece6358
AM
25566+ err = au_nhash_alloc(&arg->whlist, rdhash, GFP_NOFS);
25567+ if (unlikely(err))
1facf9fc 25568+ goto out_delist;
25569+
25570+ err = 0;
25571+ arg->flags = 0;
dece6358
AM
25572+ shwh = 0;
25573+ if (au_opt_test(au_mntflags(sb), SHWH)) {
25574+ shwh = 1;
25575+ au_fset_fillvdir(arg->flags, SHWH);
25576+ }
25577+ bstart = au_fbstart(file);
4a4d8108 25578+ bend = au_fbend_dir(file);
dece6358 25579+ for (bindex = bstart; !err && bindex <= bend; bindex++) {
4a4d8108 25580+ hf = au_hf_dir(file, bindex);
1facf9fc 25581+ if (!hf)
25582+ continue;
25583+
25584+ offset = vfsub_llseek(hf, 0, SEEK_SET);
25585+ err = offset;
25586+ if (unlikely(offset))
25587+ break;
25588+
25589+ arg->bindex = bindex;
25590+ au_fclr_fillvdir(arg->flags, WHABLE);
dece6358
AM
25591+ if (shwh
25592+ || (bindex != bend
25593+ && au_br_whable(au_sbr_perm(sb, bindex))))
1facf9fc 25594+ au_fset_fillvdir(arg->flags, WHABLE);
25595+ do {
25596+ arg->err = 0;
25597+ au_fclr_fillvdir(arg->flags, CALLED);
25598+ /* smp_mb(); */
25599+ err = vfsub_readdir(hf, fillvdir, arg);
25600+ if (err >= 0)
25601+ err = arg->err;
25602+ } while (!err && au_ftest_fillvdir(arg->flags, CALLED));
25603+ }
dece6358
AM
25604+
25605+ if (!err && shwh)
25606+ err = au_handle_shwh(sb, arg->vdir, &arg->whlist, &arg->delist);
25607+
25608+ au_nhash_wh_free(&arg->whlist);
1facf9fc 25609+
4f0767ce 25610+out_delist:
dece6358 25611+ au_nhash_de_free(&arg->delist);
4f0767ce 25612+out:
1facf9fc 25613+ return err;
25614+}
25615+
25616+static int read_vdir(struct file *file, int may_read)
25617+{
25618+ int err;
25619+ unsigned long expire;
25620+ unsigned char do_read;
25621+ struct fillvdir_arg arg;
25622+ struct inode *inode;
25623+ struct au_vdir *vdir, *allocated;
25624+
25625+ err = 0;
25626+ inode = file->f_dentry->d_inode;
25627+ IMustLock(inode);
dece6358
AM
25628+ SiMustAnyLock(inode->i_sb);
25629+
1facf9fc 25630+ allocated = NULL;
25631+ do_read = 0;
25632+ expire = au_sbi(inode->i_sb)->si_rdcache;
25633+ vdir = au_ivdir(inode);
25634+ if (!vdir) {
25635+ do_read = 1;
1308ab2a 25636+ vdir = alloc_vdir(file);
1facf9fc 25637+ err = PTR_ERR(vdir);
25638+ if (IS_ERR(vdir))
25639+ goto out;
25640+ err = 0;
25641+ allocated = vdir;
25642+ } else if (may_read
25643+ && (inode->i_version != vdir->vd_version
25644+ || time_after(jiffies, vdir->vd_jiffy + expire))) {
25645+ do_read = 1;
25646+ err = reinit_vdir(vdir);
25647+ if (unlikely(err))
25648+ goto out;
25649+ }
25650+
25651+ if (!do_read)
25652+ return 0; /* success */
25653+
25654+ arg.file = file;
25655+ arg.vdir = vdir;
25656+ err = au_do_read_vdir(&arg);
25657+ if (!err) {
25658+ /* file->f_pos = 0; */
25659+ vdir->vd_version = inode->i_version;
25660+ vdir->vd_last.ul = 0;
25661+ vdir->vd_last.p.deblk = vdir->vd_deblk[0];
25662+ if (allocated)
25663+ au_set_ivdir(inode, allocated);
25664+ } else if (allocated)
25665+ au_vdir_free(allocated);
25666+
4f0767ce 25667+out:
1facf9fc 25668+ return err;
25669+}
25670+
25671+static int copy_vdir(struct au_vdir *tgt, struct au_vdir *src)
25672+{
25673+ int err, rerr;
25674+ unsigned long ul, n;
25675+ const unsigned int deblk_sz = src->vd_deblk_sz;
25676+
25677+ AuDebugOn(tgt->vd_nblk != 1);
25678+
25679+ err = -ENOMEM;
25680+ if (tgt->vd_nblk < src->vd_nblk) {
25681+ unsigned char **p;
25682+
dece6358
AM
25683+ p = krealloc(tgt->vd_deblk, sizeof(*p) * src->vd_nblk,
25684+ GFP_NOFS);
1facf9fc 25685+ if (unlikely(!p))
25686+ goto out;
25687+ tgt->vd_deblk = p;
25688+ }
25689+
1308ab2a 25690+ if (tgt->vd_deblk_sz != deblk_sz) {
25691+ unsigned char *p;
25692+
25693+ tgt->vd_deblk_sz = deblk_sz;
25694+ p = krealloc(tgt->vd_deblk[0], deblk_sz, GFP_NOFS);
25695+ if (unlikely(!p))
25696+ goto out;
25697+ tgt->vd_deblk[0] = p;
25698+ }
1facf9fc 25699+ memcpy(tgt->vd_deblk[0], src->vd_deblk[0], deblk_sz);
1facf9fc 25700+ tgt->vd_version = src->vd_version;
25701+ tgt->vd_jiffy = src->vd_jiffy;
25702+
25703+ n = src->vd_nblk;
25704+ for (ul = 1; ul < n; ul++) {
dece6358
AM
25705+ tgt->vd_deblk[ul] = kmemdup(src->vd_deblk[ul], deblk_sz,
25706+ GFP_NOFS);
25707+ if (unlikely(!tgt->vd_deblk[ul]))
1facf9fc 25708+ goto out;
1308ab2a 25709+ tgt->vd_nblk++;
1facf9fc 25710+ }
1308ab2a 25711+ tgt->vd_nblk = n;
25712+ tgt->vd_last.ul = tgt->vd_last.ul;
25713+ tgt->vd_last.p.deblk = tgt->vd_deblk[tgt->vd_last.ul];
25714+ tgt->vd_last.p.deblk += src->vd_last.p.deblk
25715+ - src->vd_deblk[src->vd_last.ul];
1facf9fc 25716+ /* smp_mb(); */
25717+ return 0; /* success */
25718+
4f0767ce 25719+out:
1facf9fc 25720+ rerr = reinit_vdir(tgt);
25721+ BUG_ON(rerr);
25722+ return err;
25723+}
25724+
25725+int au_vdir_init(struct file *file)
25726+{
25727+ int err;
25728+ struct inode *inode;
25729+ struct au_vdir *vdir_cache, *allocated;
25730+
25731+ err = read_vdir(file, !file->f_pos);
25732+ if (unlikely(err))
25733+ goto out;
25734+
25735+ allocated = NULL;
25736+ vdir_cache = au_fvdir_cache(file);
25737+ if (!vdir_cache) {
1308ab2a 25738+ vdir_cache = alloc_vdir(file);
1facf9fc 25739+ err = PTR_ERR(vdir_cache);
25740+ if (IS_ERR(vdir_cache))
25741+ goto out;
25742+ allocated = vdir_cache;
25743+ } else if (!file->f_pos && vdir_cache->vd_version != file->f_version) {
25744+ err = reinit_vdir(vdir_cache);
25745+ if (unlikely(err))
25746+ goto out;
25747+ } else
25748+ return 0; /* success */
25749+
25750+ inode = file->f_dentry->d_inode;
25751+ err = copy_vdir(vdir_cache, au_ivdir(inode));
25752+ if (!err) {
25753+ file->f_version = inode->i_version;
25754+ if (allocated)
25755+ au_set_fvdir_cache(file, allocated);
25756+ } else if (allocated)
25757+ au_vdir_free(allocated);
25758+
4f0767ce 25759+out:
1facf9fc 25760+ return err;
25761+}
25762+
25763+static loff_t calc_offset(struct au_vdir *vdir)
25764+{
25765+ loff_t offset;
25766+ union au_vdir_deblk_p p;
25767+
25768+ p.deblk = vdir->vd_deblk[vdir->vd_last.ul];
25769+ offset = vdir->vd_last.p.deblk - p.deblk;
25770+ offset += vdir->vd_deblk_sz * vdir->vd_last.ul;
25771+ return offset;
25772+}
25773+
25774+/* returns true or false */
25775+static int seek_vdir(struct file *file)
25776+{
25777+ int valid;
25778+ unsigned int deblk_sz;
25779+ unsigned long ul, n;
25780+ loff_t offset;
25781+ union au_vdir_deblk_p p, deblk_end;
25782+ struct au_vdir *vdir_cache;
25783+
25784+ valid = 1;
25785+ vdir_cache = au_fvdir_cache(file);
25786+ offset = calc_offset(vdir_cache);
25787+ AuDbg("offset %lld\n", offset);
25788+ if (file->f_pos == offset)
25789+ goto out;
25790+
25791+ vdir_cache->vd_last.ul = 0;
25792+ vdir_cache->vd_last.p.deblk = vdir_cache->vd_deblk[0];
25793+ if (!file->f_pos)
25794+ goto out;
25795+
25796+ valid = 0;
25797+ deblk_sz = vdir_cache->vd_deblk_sz;
25798+ ul = div64_u64(file->f_pos, deblk_sz);
25799+ AuDbg("ul %lu\n", ul);
25800+ if (ul >= vdir_cache->vd_nblk)
25801+ goto out;
25802+
25803+ n = vdir_cache->vd_nblk;
25804+ for (; ul < n; ul++) {
25805+ p.deblk = vdir_cache->vd_deblk[ul];
25806+ deblk_end.deblk = p.deblk + deblk_sz;
25807+ offset = ul;
25808+ offset *= deblk_sz;
25809+ while (!is_deblk_end(&p, &deblk_end) && offset < file->f_pos) {
25810+ unsigned int l;
25811+
25812+ l = calc_size(p.de->de_str.len);
25813+ offset += l;
25814+ p.deblk += l;
25815+ }
25816+ if (!is_deblk_end(&p, &deblk_end)) {
25817+ valid = 1;
25818+ vdir_cache->vd_last.ul = ul;
25819+ vdir_cache->vd_last.p = p;
25820+ break;
25821+ }
25822+ }
25823+
4f0767ce 25824+out:
1facf9fc 25825+ /* smp_mb(); */
25826+ AuTraceErr(!valid);
25827+ return valid;
25828+}
25829+
25830+int au_vdir_fill_de(struct file *file, void *dirent, filldir_t filldir)
25831+{
25832+ int err;
25833+ unsigned int l, deblk_sz;
25834+ union au_vdir_deblk_p deblk_end;
25835+ struct au_vdir *vdir_cache;
25836+ struct au_vdir_de *de;
25837+
25838+ vdir_cache = au_fvdir_cache(file);
25839+ if (!seek_vdir(file))
25840+ return 0;
25841+
25842+ deblk_sz = vdir_cache->vd_deblk_sz;
25843+ while (1) {
25844+ deblk_end.deblk = vdir_cache->vd_deblk[vdir_cache->vd_last.ul];
25845+ deblk_end.deblk += deblk_sz;
25846+ while (!is_deblk_end(&vdir_cache->vd_last.p, &deblk_end)) {
25847+ de = vdir_cache->vd_last.p.de;
25848+ AuDbg("%.*s, off%lld, i%lu, dt%d\n",
25849+ de->de_str.len, de->de_str.name, file->f_pos,
25850+ (unsigned long)de->de_ino, de->de_type);
25851+ err = filldir(dirent, de->de_str.name, de->de_str.len,
25852+ file->f_pos, de->de_ino, de->de_type);
25853+ if (unlikely(err)) {
25854+ AuTraceErr(err);
25855+ /* todo: ignore the error caused by udba? */
25856+ /* return err; */
25857+ return 0;
25858+ }
25859+
25860+ l = calc_size(de->de_str.len);
25861+ vdir_cache->vd_last.p.deblk += l;
25862+ file->f_pos += l;
25863+ }
25864+ if (vdir_cache->vd_last.ul < vdir_cache->vd_nblk - 1) {
25865+ vdir_cache->vd_last.ul++;
25866+ vdir_cache->vd_last.p.deblk
25867+ = vdir_cache->vd_deblk[vdir_cache->vd_last.ul];
25868+ file->f_pos = deblk_sz * vdir_cache->vd_last.ul;
25869+ continue;
25870+ }
25871+ break;
25872+ }
25873+
25874+ /* smp_mb(); */
25875+ return 0;
25876+}
7f207e10
AM
25877diff -urN /usr/share/empty/fs/aufs/vfsub.c linux/fs/aufs/vfsub.c
25878--- /usr/share/empty/fs/aufs/vfsub.c 1970-01-01 01:00:00.000000000 +0100
537831f9 25879+++ linux/fs/aufs/vfsub.c 2012-12-13 20:41:10.434793588 +0100
b4510431 25880@@ -0,0 +1,777 @@
1facf9fc 25881+/*
f6c5ef8b 25882+ * Copyright (C) 2005-2012 Junjiro R. Okajima
1facf9fc 25883+ *
25884+ * This program, aufs is free software; you can redistribute it and/or modify
25885+ * it under the terms of the GNU General Public License as published by
25886+ * the Free Software Foundation; either version 2 of the License, or
25887+ * (at your option) any later version.
dece6358
AM
25888+ *
25889+ * This program is distributed in the hope that it will be useful,
25890+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
25891+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
25892+ * GNU General Public License for more details.
25893+ *
25894+ * You should have received a copy of the GNU General Public License
25895+ * along with this program; if not, write to the Free Software
25896+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 25897+ */
25898+
25899+/*
25900+ * sub-routines for VFS
25901+ */
25902+
1308ab2a 25903+#include <linux/ima.h>
dece6358
AM
25904+#include <linux/namei.h>
25905+#include <linux/security.h>
25906+#include <linux/splice.h>
1facf9fc 25907+#include "aufs.h"
25908+
25909+int vfsub_update_h_iattr(struct path *h_path, int *did)
25910+{
25911+ int err;
25912+ struct kstat st;
25913+ struct super_block *h_sb;
25914+
25915+ /* for remote fs, leave work for its getattr or d_revalidate */
25916+ /* for bad i_attr fs, handle them in aufs_getattr() */
25917+ /* still some fs may acquire i_mutex. we need to skip them */
25918+ err = 0;
25919+ if (!did)
25920+ did = &err;
25921+ h_sb = h_path->dentry->d_sb;
25922+ *did = (!au_test_fs_remote(h_sb) && au_test_fs_refresh_iattr(h_sb));
25923+ if (*did)
25924+ err = vfs_getattr(h_path->mnt, h_path->dentry, &st);
25925+
25926+ return err;
25927+}
25928+
25929+/* ---------------------------------------------------------------------- */
25930+
4a4d8108 25931+struct file *vfsub_dentry_open(struct path *path, int flags)
1308ab2a 25932+{
25933+ struct file *file;
25934+
b4510431 25935+ file = dentry_open(path, flags /* | __FMODE_NONOTIFY */,
7f207e10 25936+ current_cred());
2cbb1c4b
JR
25937+ if (!IS_ERR_OR_NULL(file)
25938+ && (file->f_mode & (FMODE_READ | FMODE_WRITE)) == FMODE_READ)
25939+ i_readcount_inc(path->dentry->d_inode);
4a4d8108 25940+
1308ab2a 25941+ return file;
25942+}
25943+
1facf9fc 25944+struct file *vfsub_filp_open(const char *path, int oflags, int mode)
25945+{
25946+ struct file *file;
25947+
2cbb1c4b 25948+ lockdep_off();
7f207e10 25949+ file = filp_open(path,
2cbb1c4b 25950+ oflags /* | __FMODE_NONOTIFY */,
7f207e10 25951+ mode);
2cbb1c4b 25952+ lockdep_on();
1facf9fc 25953+ if (IS_ERR(file))
25954+ goto out;
25955+ vfsub_update_h_iattr(&file->f_path, /*did*/NULL); /*ignore*/
25956+
4f0767ce 25957+out:
1facf9fc 25958+ return file;
25959+}
25960+
25961+int vfsub_kern_path(const char *name, unsigned int flags, struct path *path)
25962+{
25963+ int err;
25964+
1facf9fc 25965+ err = kern_path(name, flags, path);
1facf9fc 25966+ if (!err && path->dentry->d_inode)
25967+ vfsub_update_h_iattr(path, /*did*/NULL); /*ignore*/
25968+ return err;
25969+}
25970+
25971+struct dentry *vfsub_lookup_one_len(const char *name, struct dentry *parent,
25972+ int len)
25973+{
25974+ struct path path = {
25975+ .mnt = NULL
25976+ };
25977+
1308ab2a 25978+ /* VFS checks it too, but by WARN_ON_ONCE() */
1facf9fc 25979+ IMustLock(parent->d_inode);
25980+
25981+ path.dentry = lookup_one_len(name, parent, len);
25982+ if (IS_ERR(path.dentry))
25983+ goto out;
25984+ if (path.dentry->d_inode)
25985+ vfsub_update_h_iattr(&path, /*did*/NULL); /*ignore*/
25986+
4f0767ce 25987+out:
4a4d8108 25988+ AuTraceErrPtr(path.dentry);
1facf9fc 25989+ return path.dentry;
25990+}
25991+
b4510431 25992+void vfsub_call_lkup_one(void *args)
2cbb1c4b 25993+{
b4510431
AM
25994+ struct vfsub_lkup_one_args *a = args;
25995+ *a->errp = vfsub_lkup_one(a->name, a->parent);
2cbb1c4b
JR
25996+}
25997+
1facf9fc 25998+/* ---------------------------------------------------------------------- */
25999+
26000+struct dentry *vfsub_lock_rename(struct dentry *d1, struct au_hinode *hdir1,
26001+ struct dentry *d2, struct au_hinode *hdir2)
26002+{
26003+ struct dentry *d;
26004+
2cbb1c4b 26005+ lockdep_off();
1facf9fc 26006+ d = lock_rename(d1, d2);
2cbb1c4b 26007+ lockdep_on();
4a4d8108 26008+ au_hn_suspend(hdir1);
1facf9fc 26009+ if (hdir1 != hdir2)
4a4d8108 26010+ au_hn_suspend(hdir2);
1facf9fc 26011+
26012+ return d;
26013+}
26014+
26015+void vfsub_unlock_rename(struct dentry *d1, struct au_hinode *hdir1,
26016+ struct dentry *d2, struct au_hinode *hdir2)
26017+{
4a4d8108 26018+ au_hn_resume(hdir1);
1facf9fc 26019+ if (hdir1 != hdir2)
4a4d8108 26020+ au_hn_resume(hdir2);
2cbb1c4b 26021+ lockdep_off();
1facf9fc 26022+ unlock_rename(d1, d2);
2cbb1c4b 26023+ lockdep_on();
1facf9fc 26024+}
26025+
26026+/* ---------------------------------------------------------------------- */
26027+
b4510431 26028+int vfsub_create(struct inode *dir, struct path *path, int mode, bool want_excl)
1facf9fc 26029+{
26030+ int err;
26031+ struct dentry *d;
26032+
26033+ IMustLock(dir);
26034+
26035+ d = path->dentry;
26036+ path->dentry = d->d_parent;
b752ccd1 26037+ err = security_path_mknod(path, d, mode, 0);
1facf9fc 26038+ path->dentry = d;
26039+ if (unlikely(err))
26040+ goto out;
26041+
b4510431 26042+ err = vfs_create(dir, path->dentry, mode, want_excl);
1facf9fc 26043+ if (!err) {
26044+ struct path tmp = *path;
26045+ int did;
26046+
26047+ vfsub_update_h_iattr(&tmp, &did);
26048+ if (did) {
26049+ tmp.dentry = path->dentry->d_parent;
26050+ vfsub_update_h_iattr(&tmp, /*did*/NULL);
26051+ }
26052+ /*ignore*/
26053+ }
26054+
4f0767ce 26055+out:
1facf9fc 26056+ return err;
26057+}
26058+
26059+int vfsub_symlink(struct inode *dir, struct path *path, const char *symname)
26060+{
26061+ int err;
26062+ struct dentry *d;
26063+
26064+ IMustLock(dir);
26065+
26066+ d = path->dentry;
26067+ path->dentry = d->d_parent;
b752ccd1 26068+ err = security_path_symlink(path, d, symname);
1facf9fc 26069+ path->dentry = d;
26070+ if (unlikely(err))
26071+ goto out;
26072+
26073+ err = vfs_symlink(dir, path->dentry, symname);
26074+ if (!err) {
26075+ struct path tmp = *path;
26076+ int did;
26077+
26078+ vfsub_update_h_iattr(&tmp, &did);
26079+ if (did) {
26080+ tmp.dentry = path->dentry->d_parent;
26081+ vfsub_update_h_iattr(&tmp, /*did*/NULL);
26082+ }
26083+ /*ignore*/
26084+ }
26085+
4f0767ce 26086+out:
1facf9fc 26087+ return err;
26088+}
26089+
26090+int vfsub_mknod(struct inode *dir, struct path *path, int mode, dev_t dev)
26091+{
26092+ int err;
26093+ struct dentry *d;
26094+
26095+ IMustLock(dir);
26096+
26097+ d = path->dentry;
26098+ path->dentry = d->d_parent;
027c5e7a 26099+ err = security_path_mknod(path, d, mode, new_encode_dev(dev));
1facf9fc 26100+ path->dentry = d;
26101+ if (unlikely(err))
26102+ goto out;
26103+
26104+ err = vfs_mknod(dir, path->dentry, mode, dev);
26105+ if (!err) {
26106+ struct path tmp = *path;
26107+ int did;
26108+
26109+ vfsub_update_h_iattr(&tmp, &did);
26110+ if (did) {
26111+ tmp.dentry = path->dentry->d_parent;
26112+ vfsub_update_h_iattr(&tmp, /*did*/NULL);
26113+ }
26114+ /*ignore*/
26115+ }
26116+
4f0767ce 26117+out:
1facf9fc 26118+ return err;
26119+}
26120+
26121+static int au_test_nlink(struct inode *inode)
26122+{
26123+ const unsigned int link_max = UINT_MAX >> 1; /* rough margin */
26124+
26125+ if (!au_test_fs_no_limit_nlink(inode->i_sb)
26126+ || inode->i_nlink < link_max)
26127+ return 0;
26128+ return -EMLINK;
26129+}
26130+
26131+int vfsub_link(struct dentry *src_dentry, struct inode *dir, struct path *path)
26132+{
26133+ int err;
26134+ struct dentry *d;
26135+
26136+ IMustLock(dir);
26137+
26138+ err = au_test_nlink(src_dentry->d_inode);
26139+ if (unlikely(err))
26140+ return err;
26141+
b4510431 26142+ /* we don't call may_linkat() */
1facf9fc 26143+ d = path->dentry;
26144+ path->dentry = d->d_parent;
b752ccd1 26145+ err = security_path_link(src_dentry, path, d);
1facf9fc 26146+ path->dentry = d;
26147+ if (unlikely(err))
26148+ goto out;
26149+
2cbb1c4b 26150+ lockdep_off();
1facf9fc 26151+ err = vfs_link(src_dentry, dir, path->dentry);
2cbb1c4b 26152+ lockdep_on();
1facf9fc 26153+ if (!err) {
26154+ struct path tmp = *path;
26155+ int did;
26156+
26157+ /* fuse has different memory inode for the same inumber */
26158+ vfsub_update_h_iattr(&tmp, &did);
26159+ if (did) {
26160+ tmp.dentry = path->dentry->d_parent;
26161+ vfsub_update_h_iattr(&tmp, /*did*/NULL);
26162+ tmp.dentry = src_dentry;
26163+ vfsub_update_h_iattr(&tmp, /*did*/NULL);
26164+ }
26165+ /*ignore*/
26166+ }
26167+
4f0767ce 26168+out:
1facf9fc 26169+ return err;
26170+}
26171+
26172+int vfsub_rename(struct inode *src_dir, struct dentry *src_dentry,
26173+ struct inode *dir, struct path *path)
26174+{
26175+ int err;
26176+ struct path tmp = {
26177+ .mnt = path->mnt
26178+ };
26179+ struct dentry *d;
26180+
26181+ IMustLock(dir);
26182+ IMustLock(src_dir);
26183+
26184+ d = path->dentry;
26185+ path->dentry = d->d_parent;
26186+ tmp.dentry = src_dentry->d_parent;
b752ccd1 26187+ err = security_path_rename(&tmp, src_dentry, path, d);
1facf9fc 26188+ path->dentry = d;
26189+ if (unlikely(err))
26190+ goto out;
26191+
2cbb1c4b 26192+ lockdep_off();
1facf9fc 26193+ err = vfs_rename(src_dir, src_dentry, dir, path->dentry);
2cbb1c4b 26194+ lockdep_on();
1facf9fc 26195+ if (!err) {
26196+ int did;
26197+
26198+ tmp.dentry = d->d_parent;
26199+ vfsub_update_h_iattr(&tmp, &did);
26200+ if (did) {
26201+ tmp.dentry = src_dentry;
26202+ vfsub_update_h_iattr(&tmp, /*did*/NULL);
26203+ tmp.dentry = src_dentry->d_parent;
26204+ vfsub_update_h_iattr(&tmp, /*did*/NULL);
26205+ }
26206+ /*ignore*/
26207+ }
26208+
4f0767ce 26209+out:
1facf9fc 26210+ return err;
26211+}
26212+
26213+int vfsub_mkdir(struct inode *dir, struct path *path, int mode)
26214+{
26215+ int err;
26216+ struct dentry *d;
26217+
26218+ IMustLock(dir);
26219+
26220+ d = path->dentry;
26221+ path->dentry = d->d_parent;
b752ccd1 26222+ err = security_path_mkdir(path, d, mode);
1facf9fc 26223+ path->dentry = d;
26224+ if (unlikely(err))
26225+ goto out;
26226+
26227+ err = vfs_mkdir(dir, path->dentry, mode);
26228+ if (!err) {
26229+ struct path tmp = *path;
26230+ int did;
26231+
26232+ vfsub_update_h_iattr(&tmp, &did);
26233+ if (did) {
26234+ tmp.dentry = path->dentry->d_parent;
26235+ vfsub_update_h_iattr(&tmp, /*did*/NULL);
26236+ }
26237+ /*ignore*/
26238+ }
26239+
4f0767ce 26240+out:
1facf9fc 26241+ return err;
26242+}
26243+
26244+int vfsub_rmdir(struct inode *dir, struct path *path)
26245+{
26246+ int err;
26247+ struct dentry *d;
26248+
26249+ IMustLock(dir);
26250+
26251+ d = path->dentry;
26252+ path->dentry = d->d_parent;
b752ccd1 26253+ err = security_path_rmdir(path, d);
1facf9fc 26254+ path->dentry = d;
26255+ if (unlikely(err))
26256+ goto out;
26257+
2cbb1c4b 26258+ lockdep_off();
1facf9fc 26259+ err = vfs_rmdir(dir, path->dentry);
2cbb1c4b 26260+ lockdep_on();
1facf9fc 26261+ if (!err) {
26262+ struct path tmp = {
26263+ .dentry = path->dentry->d_parent,
26264+ .mnt = path->mnt
26265+ };
26266+
26267+ vfsub_update_h_iattr(&tmp, /*did*/NULL); /*ignore*/
26268+ }
26269+
4f0767ce 26270+out:
1facf9fc 26271+ return err;
26272+}
26273+
26274+/* ---------------------------------------------------------------------- */
26275+
9dbd164d 26276+/* todo: support mmap_sem? */
1facf9fc 26277+ssize_t vfsub_read_u(struct file *file, char __user *ubuf, size_t count,
26278+ loff_t *ppos)
26279+{
26280+ ssize_t err;
26281+
2cbb1c4b 26282+ lockdep_off();
1facf9fc 26283+ err = vfs_read(file, ubuf, count, ppos);
2cbb1c4b 26284+ lockdep_on();
1facf9fc 26285+ if (err >= 0)
26286+ vfsub_update_h_iattr(&file->f_path, /*did*/NULL); /*ignore*/
26287+ return err;
26288+}
26289+
26290+/* todo: kernel_read()? */
26291+ssize_t vfsub_read_k(struct file *file, void *kbuf, size_t count,
26292+ loff_t *ppos)
26293+{
26294+ ssize_t err;
26295+ mm_segment_t oldfs;
b752ccd1
AM
26296+ union {
26297+ void *k;
26298+ char __user *u;
26299+ } buf;
1facf9fc 26300+
b752ccd1 26301+ buf.k = kbuf;
1facf9fc 26302+ oldfs = get_fs();
26303+ set_fs(KERNEL_DS);
b752ccd1 26304+ err = vfsub_read_u(file, buf.u, count, ppos);
1facf9fc 26305+ set_fs(oldfs);
26306+ return err;
26307+}
26308+
26309+ssize_t vfsub_write_u(struct file *file, const char __user *ubuf, size_t count,
26310+ loff_t *ppos)
26311+{
26312+ ssize_t err;
26313+
2cbb1c4b 26314+ lockdep_off();
1facf9fc 26315+ err = vfs_write(file, ubuf, count, ppos);
2cbb1c4b 26316+ lockdep_on();
1facf9fc 26317+ if (err >= 0)
26318+ vfsub_update_h_iattr(&file->f_path, /*did*/NULL); /*ignore*/
26319+ return err;
26320+}
26321+
26322+ssize_t vfsub_write_k(struct file *file, void *kbuf, size_t count, loff_t *ppos)
26323+{
26324+ ssize_t err;
26325+ mm_segment_t oldfs;
b752ccd1
AM
26326+ union {
26327+ void *k;
26328+ const char __user *u;
26329+ } buf;
1facf9fc 26330+
b752ccd1 26331+ buf.k = kbuf;
1facf9fc 26332+ oldfs = get_fs();
26333+ set_fs(KERNEL_DS);
b752ccd1 26334+ err = vfsub_write_u(file, buf.u, count, ppos);
1facf9fc 26335+ set_fs(oldfs);
26336+ return err;
26337+}
26338+
4a4d8108
AM
26339+int vfsub_flush(struct file *file, fl_owner_t id)
26340+{
26341+ int err;
26342+
26343+ err = 0;
26344+ if (file->f_op && file->f_op->flush) {
2cbb1c4b
JR
26345+ if (!au_test_nfs(file->f_dentry->d_sb))
26346+ err = file->f_op->flush(file, id);
26347+ else {
26348+ lockdep_off();
26349+ err = file->f_op->flush(file, id);
26350+ lockdep_on();
26351+ }
4a4d8108
AM
26352+ if (!err)
26353+ vfsub_update_h_iattr(&file->f_path, /*did*/NULL);
26354+ /*ignore*/
26355+ }
26356+ return err;
26357+}
26358+
1facf9fc 26359+int vfsub_readdir(struct file *file, filldir_t filldir, void *arg)
26360+{
26361+ int err;
26362+
2cbb1c4b 26363+ lockdep_off();
1facf9fc 26364+ err = vfs_readdir(file, filldir, arg);
2cbb1c4b 26365+ lockdep_on();
1facf9fc 26366+ if (err >= 0)
26367+ vfsub_update_h_iattr(&file->f_path, /*did*/NULL); /*ignore*/
26368+ return err;
26369+}
26370+
26371+long vfsub_splice_to(struct file *in, loff_t *ppos,
26372+ struct pipe_inode_info *pipe, size_t len,
26373+ unsigned int flags)
26374+{
26375+ long err;
26376+
2cbb1c4b 26377+ lockdep_off();
0fc653ad 26378+ err = do_splice_to(in, ppos, pipe, len, flags);
2cbb1c4b 26379+ lockdep_on();
4a4d8108 26380+ file_accessed(in);
1facf9fc 26381+ if (err >= 0)
26382+ vfsub_update_h_iattr(&in->f_path, /*did*/NULL); /*ignore*/
26383+ return err;
26384+}
26385+
26386+long vfsub_splice_from(struct pipe_inode_info *pipe, struct file *out,
26387+ loff_t *ppos, size_t len, unsigned int flags)
26388+{
26389+ long err;
26390+
2cbb1c4b 26391+ lockdep_off();
0fc653ad 26392+ err = do_splice_from(pipe, out, ppos, len, flags);
2cbb1c4b 26393+ lockdep_on();
1facf9fc 26394+ if (err >= 0)
26395+ vfsub_update_h_iattr(&out->f_path, /*did*/NULL); /*ignore*/
26396+ return err;
26397+}
26398+
53392da6
AM
26399+int vfsub_fsync(struct file *file, struct path *path, int datasync)
26400+{
26401+ int err;
26402+
26403+ /* file can be NULL */
26404+ lockdep_off();
26405+ err = vfs_fsync(file, datasync);
26406+ lockdep_on();
26407+ if (!err) {
26408+ if (!path) {
26409+ AuDebugOn(!file);
26410+ path = &file->f_path;
26411+ }
26412+ vfsub_update_h_iattr(path, /*did*/NULL); /*ignore*/
26413+ }
26414+ return err;
26415+}
26416+
1facf9fc 26417+/* cf. open.c:do_sys_truncate() and do_sys_ftruncate() */
26418+int vfsub_trunc(struct path *h_path, loff_t length, unsigned int attr,
26419+ struct file *h_file)
26420+{
26421+ int err;
26422+ struct inode *h_inode;
26423+
26424+ h_inode = h_path->dentry->d_inode;
26425+ if (!h_file) {
b4510431 26426+ err = vfsub_mnt_want_write(h_path->mnt);
1facf9fc 26427+ if (err)
26428+ goto out;
26429+ err = inode_permission(h_inode, MAY_WRITE);
26430+ if (err)
26431+ goto out_mnt;
26432+ err = get_write_access(h_inode);
26433+ if (err)
26434+ goto out_mnt;
4a4d8108 26435+ err = break_lease(h_inode, O_WRONLY);
1facf9fc 26436+ if (err)
26437+ goto out_inode;
26438+ }
26439+
26440+ err = locks_verify_truncate(h_inode, h_file, length);
26441+ if (!err)
953406b4 26442+ err = security_path_truncate(h_path);
2cbb1c4b
JR
26443+ if (!err) {
26444+ lockdep_off();
1facf9fc 26445+ err = do_truncate(h_path->dentry, length, attr, h_file);
2cbb1c4b
JR
26446+ lockdep_on();
26447+ }
1facf9fc 26448+
4f0767ce 26449+out_inode:
1facf9fc 26450+ if (!h_file)
26451+ put_write_access(h_inode);
4f0767ce 26452+out_mnt:
1facf9fc 26453+ if (!h_file)
b4510431 26454+ vfsub_mnt_drop_write(h_path->mnt);
4f0767ce 26455+out:
1facf9fc 26456+ return err;
26457+}
26458+
26459+/* ---------------------------------------------------------------------- */
26460+
26461+struct au_vfsub_mkdir_args {
26462+ int *errp;
26463+ struct inode *dir;
26464+ struct path *path;
26465+ int mode;
26466+};
26467+
26468+static void au_call_vfsub_mkdir(void *args)
26469+{
26470+ struct au_vfsub_mkdir_args *a = args;
26471+ *a->errp = vfsub_mkdir(a->dir, a->path, a->mode);
26472+}
26473+
26474+int vfsub_sio_mkdir(struct inode *dir, struct path *path, int mode)
26475+{
26476+ int err, do_sio, wkq_err;
26477+
26478+ do_sio = au_test_h_perm_sio(dir, MAY_EXEC | MAY_WRITE);
26479+ if (!do_sio)
26480+ err = vfsub_mkdir(dir, path, mode);
26481+ else {
26482+ struct au_vfsub_mkdir_args args = {
26483+ .errp = &err,
26484+ .dir = dir,
26485+ .path = path,
26486+ .mode = mode
26487+ };
26488+ wkq_err = au_wkq_wait(au_call_vfsub_mkdir, &args);
26489+ if (unlikely(wkq_err))
26490+ err = wkq_err;
26491+ }
26492+
26493+ return err;
26494+}
26495+
26496+struct au_vfsub_rmdir_args {
26497+ int *errp;
26498+ struct inode *dir;
26499+ struct path *path;
26500+};
26501+
26502+static void au_call_vfsub_rmdir(void *args)
26503+{
26504+ struct au_vfsub_rmdir_args *a = args;
26505+ *a->errp = vfsub_rmdir(a->dir, a->path);
26506+}
26507+
26508+int vfsub_sio_rmdir(struct inode *dir, struct path *path)
26509+{
26510+ int err, do_sio, wkq_err;
26511+
26512+ do_sio = au_test_h_perm_sio(dir, MAY_EXEC | MAY_WRITE);
26513+ if (!do_sio)
26514+ err = vfsub_rmdir(dir, path);
26515+ else {
26516+ struct au_vfsub_rmdir_args args = {
26517+ .errp = &err,
26518+ .dir = dir,
26519+ .path = path
26520+ };
26521+ wkq_err = au_wkq_wait(au_call_vfsub_rmdir, &args);
26522+ if (unlikely(wkq_err))
26523+ err = wkq_err;
26524+ }
26525+
26526+ return err;
26527+}
26528+
26529+/* ---------------------------------------------------------------------- */
26530+
26531+struct notify_change_args {
26532+ int *errp;
26533+ struct path *path;
26534+ struct iattr *ia;
26535+};
26536+
26537+static void call_notify_change(void *args)
26538+{
26539+ struct notify_change_args *a = args;
26540+ struct inode *h_inode;
26541+
26542+ h_inode = a->path->dentry->d_inode;
26543+ IMustLock(h_inode);
26544+
26545+ *a->errp = -EPERM;
26546+ if (!IS_IMMUTABLE(h_inode) && !IS_APPEND(h_inode)) {
1facf9fc 26547+ *a->errp = notify_change(a->path->dentry, a->ia);
1facf9fc 26548+ if (!*a->errp)
26549+ vfsub_update_h_iattr(a->path, /*did*/NULL); /*ignore*/
26550+ }
26551+ AuTraceErr(*a->errp);
26552+}
26553+
26554+int vfsub_notify_change(struct path *path, struct iattr *ia)
26555+{
26556+ int err;
26557+ struct notify_change_args args = {
26558+ .errp = &err,
26559+ .path = path,
26560+ .ia = ia
26561+ };
26562+
26563+ call_notify_change(&args);
26564+
26565+ return err;
26566+}
26567+
26568+int vfsub_sio_notify_change(struct path *path, struct iattr *ia)
26569+{
26570+ int err, wkq_err;
26571+ struct notify_change_args args = {
26572+ .errp = &err,
26573+ .path = path,
26574+ .ia = ia
26575+ };
26576+
26577+ wkq_err = au_wkq_wait(call_notify_change, &args);
26578+ if (unlikely(wkq_err))
26579+ err = wkq_err;
26580+
26581+ return err;
26582+}
26583+
26584+/* ---------------------------------------------------------------------- */
26585+
26586+struct unlink_args {
26587+ int *errp;
26588+ struct inode *dir;
26589+ struct path *path;
26590+};
26591+
26592+static void call_unlink(void *args)
26593+{
26594+ struct unlink_args *a = args;
26595+ struct dentry *d = a->path->dentry;
26596+ struct inode *h_inode;
26597+ const int stop_sillyrename = (au_test_nfs(d->d_sb)
027c5e7a 26598+ && d->d_count == 1);
1facf9fc 26599+
26600+ IMustLock(a->dir);
26601+
26602+ a->path->dentry = d->d_parent;
26603+ *a->errp = security_path_unlink(a->path, d);
26604+ a->path->dentry = d;
26605+ if (unlikely(*a->errp))
26606+ return;
26607+
26608+ if (!stop_sillyrename)
26609+ dget(d);
26610+ h_inode = d->d_inode;
26611+ if (h_inode)
027c5e7a 26612+ ihold(h_inode);
1facf9fc 26613+
2cbb1c4b 26614+ lockdep_off();
1facf9fc 26615+ *a->errp = vfs_unlink(a->dir, d);
2cbb1c4b 26616+ lockdep_on();
1facf9fc 26617+ if (!*a->errp) {
26618+ struct path tmp = {
26619+ .dentry = d->d_parent,
26620+ .mnt = a->path->mnt
26621+ };
26622+ vfsub_update_h_iattr(&tmp, /*did*/NULL); /*ignore*/
26623+ }
26624+
26625+ if (!stop_sillyrename)
26626+ dput(d);
26627+ if (h_inode)
26628+ iput(h_inode);
26629+
26630+ AuTraceErr(*a->errp);
26631+}
26632+
26633+/*
26634+ * @dir: must be locked.
26635+ * @dentry: target dentry.
26636+ */
26637+int vfsub_unlink(struct inode *dir, struct path *path, int force)
26638+{
26639+ int err;
26640+ struct unlink_args args = {
26641+ .errp = &err,
26642+ .dir = dir,
26643+ .path = path
26644+ };
26645+
26646+ if (!force)
26647+ call_unlink(&args);
26648+ else {
26649+ int wkq_err;
26650+
26651+ wkq_err = au_wkq_wait(call_unlink, &args);
26652+ if (unlikely(wkq_err))
26653+ err = wkq_err;
26654+ }
26655+
26656+ return err;
26657+}
7f207e10
AM
26658diff -urN /usr/share/empty/fs/aufs/vfsub.h linux/fs/aufs/vfsub.h
26659--- /usr/share/empty/fs/aufs/vfsub.h 1970-01-01 01:00:00.000000000 +0100
537831f9
AM
26660+++ linux/fs/aufs/vfsub.h 2012-12-13 20:41:10.434793588 +0100
26661@@ -0,0 +1,284 @@
1facf9fc 26662+/*
f6c5ef8b 26663+ * Copyright (C) 2005-2012 Junjiro R. Okajima
1facf9fc 26664+ *
26665+ * This program, aufs is free software; you can redistribute it and/or modify
26666+ * it under the terms of the GNU General Public License as published by
26667+ * the Free Software Foundation; either version 2 of the License, or
26668+ * (at your option) any later version.
dece6358
AM
26669+ *
26670+ * This program is distributed in the hope that it will be useful,
26671+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
26672+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
26673+ * GNU General Public License for more details.
26674+ *
26675+ * You should have received a copy of the GNU General Public License
26676+ * along with this program; if not, write to the Free Software
26677+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 26678+ */
26679+
26680+/*
26681+ * sub-routines for VFS
26682+ */
26683+
26684+#ifndef __AUFS_VFSUB_H__
26685+#define __AUFS_VFSUB_H__
26686+
26687+#ifdef __KERNEL__
26688+
26689+#include <linux/fs.h>
0c5527e5 26690+#include <linux/lglock.h>
b4510431 26691+#include <linux/mount.h>
7f207e10 26692+#include "debug.h"
1facf9fc 26693+
7f207e10 26694+/* copied from linux/fs/internal.h */
2cbb1c4b 26695+/* todo: BAD approach!! */
0c3ec466 26696+extern struct lglock vfsmount_lock;
2cbb1c4b 26697+extern spinlock_t inode_sb_list_lock;
0c5527e5 26698+
7f207e10 26699+/* copied from linux/fs/file_table.c */
0c3ec466 26700+extern struct lglock files_lglock;
0c5527e5
AM
26701+#ifdef CONFIG_SMP
26702+/*
26703+ * These macros iterate all files on all CPUs for a given superblock.
26704+ * files_lglock must be held globally.
26705+ */
26706+#define do_file_list_for_each_entry(__sb, __file) \
26707+{ \
26708+ int i; \
26709+ for_each_possible_cpu(i) { \
26710+ struct list_head *list; \
26711+ list = per_cpu_ptr((__sb)->s_files, i); \
26712+ list_for_each_entry((__file), list, f_u.fu_list)
26713+
26714+#define while_file_list_for_each_entry \
26715+ } \
26716+}
26717+
26718+#else
26719+
26720+#define do_file_list_for_each_entry(__sb, __file) \
26721+{ \
26722+ struct list_head *list; \
26723+ list = &(sb)->s_files; \
26724+ list_for_each_entry((__file), list, f_u.fu_list)
26725+
26726+#define while_file_list_for_each_entry \
26727+}
7f207e10
AM
26728+#endif
26729+
26730+/* ---------------------------------------------------------------------- */
1facf9fc 26731+
26732+/* lock subclass for lower inode */
26733+/* default MAX_LOCKDEP_SUBCLASSES(8) is not enough */
26734+/* reduce? gave up. */
26735+enum {
26736+ AuLsc_I_Begin = I_MUTEX_QUOTA, /* 4 */
26737+ AuLsc_I_PARENT, /* lower inode, parent first */
26738+ AuLsc_I_PARENT2, /* copyup dirs */
dece6358 26739+ AuLsc_I_PARENT3, /* copyup wh */
1facf9fc 26740+ AuLsc_I_CHILD,
26741+ AuLsc_I_CHILD2,
26742+ AuLsc_I_End
26743+};
26744+
26745+/* to debug easier, do not make them inlined functions */
26746+#define MtxMustLock(mtx) AuDebugOn(!mutex_is_locked(mtx))
26747+#define IMustLock(i) MtxMustLock(&(i)->i_mutex)
26748+
26749+/* ---------------------------------------------------------------------- */
26750+
7f207e10
AM
26751+static inline void vfsub_drop_nlink(struct inode *inode)
26752+{
26753+ AuDebugOn(!inode->i_nlink);
26754+ drop_nlink(inode);
26755+}
26756+
027c5e7a
AM
26757+static inline void vfsub_dead_dir(struct inode *inode)
26758+{
26759+ AuDebugOn(!S_ISDIR(inode->i_mode));
26760+ inode->i_flags |= S_DEAD;
26761+ clear_nlink(inode);
26762+}
26763+
7f207e10
AM
26764+/* ---------------------------------------------------------------------- */
26765+
0c3ec466
AM
26766+/* cf. i_[ug]id_read() in linux/include/fs.h */
26767+static inline uid_t vfsub_ia_uid(struct iattr *ia)
26768+{
26769+ return from_kuid(&init_user_ns, ia->ia_uid);
26770+}
26771+
26772+static inline gid_t vfsub_ia_gid(struct iattr *ia)
26773+{
26774+ return from_kgid(&init_user_ns, ia->ia_gid);
26775+}
26776+
26777+/* ---------------------------------------------------------------------- */
26778+
7f207e10
AM
26779+int vfsub_update_h_iattr(struct path *h_path, int *did);
26780+struct file *vfsub_dentry_open(struct path *path, int flags);
26781+struct file *vfsub_filp_open(const char *path, int oflags, int mode);
1facf9fc 26782+int vfsub_kern_path(const char *name, unsigned int flags, struct path *path);
b4510431 26783+
1facf9fc 26784+struct dentry *vfsub_lookup_one_len(const char *name, struct dentry *parent,
26785+ int len);
b4510431
AM
26786+
26787+struct vfsub_lkup_one_args {
26788+ struct dentry **errp;
26789+ struct qstr *name;
26790+ struct dentry *parent;
26791+};
26792+
26793+static inline struct dentry *vfsub_lkup_one(struct qstr *name,
26794+ struct dentry *parent)
26795+{
26796+ return vfsub_lookup_one_len(name->name, parent, name->len);
26797+}
26798+
26799+void vfsub_call_lkup_one(void *args);
26800+
26801+/* ---------------------------------------------------------------------- */
26802+
26803+static inline int vfsub_mnt_want_write(struct vfsmount *mnt)
26804+{
26805+ int err;
26806+ lockdep_off();
26807+ err = mnt_want_write(mnt);
26808+ lockdep_on();
26809+ return err;
26810+}
26811+
26812+static inline void vfsub_mnt_drop_write(struct vfsmount *mnt)
26813+{
26814+ lockdep_off();
26815+ mnt_drop_write(mnt);
26816+ lockdep_on();
26817+}
1facf9fc 26818+
26819+/* ---------------------------------------------------------------------- */
26820+
26821+struct au_hinode;
26822+struct dentry *vfsub_lock_rename(struct dentry *d1, struct au_hinode *hdir1,
26823+ struct dentry *d2, struct au_hinode *hdir2);
26824+void vfsub_unlock_rename(struct dentry *d1, struct au_hinode *hdir1,
26825+ struct dentry *d2, struct au_hinode *hdir2);
26826+
537831f9
AM
26827+int vfsub_create(struct inode *dir, struct path *path, int mode,
26828+ bool want_excl);
1facf9fc 26829+int vfsub_symlink(struct inode *dir, struct path *path,
26830+ const char *symname);
26831+int vfsub_mknod(struct inode *dir, struct path *path, int mode, dev_t dev);
26832+int vfsub_link(struct dentry *src_dentry, struct inode *dir,
26833+ struct path *path);
26834+int vfsub_rename(struct inode *src_hdir, struct dentry *src_dentry,
26835+ struct inode *hdir, struct path *path);
26836+int vfsub_mkdir(struct inode *dir, struct path *path, int mode);
26837+int vfsub_rmdir(struct inode *dir, struct path *path);
26838+
26839+/* ---------------------------------------------------------------------- */
26840+
26841+ssize_t vfsub_read_u(struct file *file, char __user *ubuf, size_t count,
26842+ loff_t *ppos);
26843+ssize_t vfsub_read_k(struct file *file, void *kbuf, size_t count,
26844+ loff_t *ppos);
26845+ssize_t vfsub_write_u(struct file *file, const char __user *ubuf, size_t count,
26846+ loff_t *ppos);
26847+ssize_t vfsub_write_k(struct file *file, void *kbuf, size_t count,
26848+ loff_t *ppos);
4a4d8108 26849+int vfsub_flush(struct file *file, fl_owner_t id);
1facf9fc 26850+int vfsub_readdir(struct file *file, filldir_t filldir, void *arg);
26851+
4a4d8108
AM
26852+static inline unsigned int vfsub_file_flags(struct file *file)
26853+{
26854+ unsigned int flags;
26855+
26856+ spin_lock(&file->f_lock);
26857+ flags = file->f_flags;
26858+ spin_unlock(&file->f_lock);
26859+
26860+ return flags;
26861+}
1308ab2a 26862+
1facf9fc 26863+static inline void vfsub_file_accessed(struct file *h_file)
26864+{
26865+ file_accessed(h_file);
26866+ vfsub_update_h_iattr(&h_file->f_path, /*did*/NULL); /*ignore*/
26867+}
26868+
26869+static inline void vfsub_touch_atime(struct vfsmount *h_mnt,
26870+ struct dentry *h_dentry)
26871+{
26872+ struct path h_path = {
26873+ .dentry = h_dentry,
26874+ .mnt = h_mnt
26875+ };
92d182d2 26876+ touch_atime(&h_path);
1facf9fc 26877+ vfsub_update_h_iattr(&h_path, /*did*/NULL); /*ignore*/
26878+}
26879+
0c3ec466
AM
26880+static inline int vfsub_update_time(struct inode *h_inode, struct timespec *ts,
26881+ int flags)
26882+{
26883+ return update_time(h_inode, ts, flags);
26884+ /* no vfsub_update_h_iattr() since we don't have struct path */
26885+}
26886+
4a4d8108
AM
26887+long vfsub_splice_to(struct file *in, loff_t *ppos,
26888+ struct pipe_inode_info *pipe, size_t len,
26889+ unsigned int flags);
26890+long vfsub_splice_from(struct pipe_inode_info *pipe, struct file *out,
26891+ loff_t *ppos, size_t len, unsigned int flags);
26892+int vfsub_trunc(struct path *h_path, loff_t length, unsigned int attr,
26893+ struct file *h_file);
53392da6 26894+int vfsub_fsync(struct file *file, struct path *path, int datasync);
4a4d8108 26895+
1facf9fc 26896+/* ---------------------------------------------------------------------- */
26897+
26898+static inline loff_t vfsub_llseek(struct file *file, loff_t offset, int origin)
26899+{
26900+ loff_t err;
26901+
2cbb1c4b 26902+ lockdep_off();
1facf9fc 26903+ err = vfs_llseek(file, offset, origin);
2cbb1c4b 26904+ lockdep_on();
1facf9fc 26905+ return err;
26906+}
26907+
26908+/* ---------------------------------------------------------------------- */
26909+
26910+/* dirty workaround for strict type of fmode_t */
26911+union vfsub_fmu {
26912+ fmode_t fm;
26913+ unsigned int ui;
26914+};
26915+
26916+static inline unsigned int vfsub_fmode_to_uint(fmode_t fm)
26917+{
26918+ union vfsub_fmu u = {
26919+ .fm = fm
26920+ };
26921+
26922+ BUILD_BUG_ON(sizeof(u.fm) != sizeof(u.ui));
26923+
26924+ return u.ui;
26925+}
26926+
26927+static inline fmode_t vfsub_uint_to_fmode(unsigned int ui)
26928+{
26929+ union vfsub_fmu u = {
26930+ .ui = ui
26931+ };
26932+
26933+ return u.fm;
26934+}
26935+
4a4d8108
AM
26936+/* ---------------------------------------------------------------------- */
26937+
26938+int vfsub_sio_mkdir(struct inode *dir, struct path *path, int mode);
26939+int vfsub_sio_rmdir(struct inode *dir, struct path *path);
26940+int vfsub_sio_notify_change(struct path *path, struct iattr *ia);
26941+int vfsub_notify_change(struct path *path, struct iattr *ia);
26942+int vfsub_unlink(struct inode *dir, struct path *path, int force);
26943+
1facf9fc 26944+#endif /* __KERNEL__ */
26945+#endif /* __AUFS_VFSUB_H__ */
7f207e10
AM
26946diff -urN /usr/share/empty/fs/aufs/wbr_policy.c linux/fs/aufs/wbr_policy.c
26947--- /usr/share/empty/fs/aufs/wbr_policy.c 1970-01-01 01:00:00.000000000 +0100
537831f9 26948+++ linux/fs/aufs/wbr_policy.c 2012-12-13 20:41:10.434793588 +0100
027c5e7a 26949@@ -0,0 +1,700 @@
1facf9fc 26950+/*
f6c5ef8b 26951+ * Copyright (C) 2005-2012 Junjiro R. Okajima
1facf9fc 26952+ *
26953+ * This program, aufs is free software; you can redistribute it and/or modify
26954+ * it under the terms of the GNU General Public License as published by
26955+ * the Free Software Foundation; either version 2 of the License, or
26956+ * (at your option) any later version.
dece6358
AM
26957+ *
26958+ * This program is distributed in the hope that it will be useful,
26959+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
26960+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
26961+ * GNU General Public License for more details.
26962+ *
26963+ * You should have received a copy of the GNU General Public License
26964+ * along with this program; if not, write to the Free Software
26965+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 26966+ */
26967+
26968+/*
26969+ * policies for selecting one among multiple writable branches
26970+ */
26971+
26972+#include <linux/statfs.h>
26973+#include "aufs.h"
26974+
26975+/* subset of cpup_attr() */
26976+static noinline_for_stack
26977+int au_cpdown_attr(struct path *h_path, struct dentry *h_src)
26978+{
26979+ int err, sbits;
26980+ struct iattr ia;
26981+ struct inode *h_isrc;
26982+
26983+ h_isrc = h_src->d_inode;
26984+ ia.ia_valid = ATTR_FORCE | ATTR_MODE | ATTR_UID | ATTR_GID;
26985+ ia.ia_mode = h_isrc->i_mode;
26986+ ia.ia_uid = h_isrc->i_uid;
26987+ ia.ia_gid = h_isrc->i_gid;
26988+ sbits = !!(ia.ia_mode & (S_ISUID | S_ISGID));
26989+ au_cpup_attr_flags(h_path->dentry->d_inode, h_isrc);
26990+ err = vfsub_sio_notify_change(h_path, &ia);
26991+
26992+ /* is this nfs only? */
26993+ if (!err && sbits && au_test_nfs(h_path->dentry->d_sb)) {
26994+ ia.ia_valid = ATTR_FORCE | ATTR_MODE;
26995+ ia.ia_mode = h_isrc->i_mode;
26996+ err = vfsub_sio_notify_change(h_path, &ia);
26997+ }
26998+
26999+ return err;
27000+}
27001+
27002+#define AuCpdown_PARENT_OPQ 1
27003+#define AuCpdown_WHED (1 << 1)
27004+#define AuCpdown_MADE_DIR (1 << 2)
27005+#define AuCpdown_DIROPQ (1 << 3)
27006+#define au_ftest_cpdown(flags, name) ((flags) & AuCpdown_##name)
7f207e10
AM
27007+#define au_fset_cpdown(flags, name) \
27008+ do { (flags) |= AuCpdown_##name; } while (0)
27009+#define au_fclr_cpdown(flags, name) \
27010+ do { (flags) &= ~AuCpdown_##name; } while (0)
1facf9fc 27011+
27012+struct au_cpdown_dir_args {
27013+ struct dentry *parent;
27014+ unsigned int flags;
27015+};
27016+
27017+static int au_cpdown_dir_opq(struct dentry *dentry, aufs_bindex_t bdst,
27018+ struct au_cpdown_dir_args *a)
27019+{
27020+ int err;
27021+ struct dentry *opq_dentry;
27022+
27023+ opq_dentry = au_diropq_create(dentry, bdst);
27024+ err = PTR_ERR(opq_dentry);
27025+ if (IS_ERR(opq_dentry))
27026+ goto out;
27027+ dput(opq_dentry);
27028+ au_fset_cpdown(a->flags, DIROPQ);
27029+
4f0767ce 27030+out:
1facf9fc 27031+ return err;
27032+}
27033+
27034+static int au_cpdown_dir_wh(struct dentry *dentry, struct dentry *h_parent,
27035+ struct inode *dir, aufs_bindex_t bdst)
27036+{
27037+ int err;
27038+ struct path h_path;
27039+ struct au_branch *br;
27040+
27041+ br = au_sbr(dentry->d_sb, bdst);
27042+ h_path.dentry = au_wh_lkup(h_parent, &dentry->d_name, br);
27043+ err = PTR_ERR(h_path.dentry);
27044+ if (IS_ERR(h_path.dentry))
27045+ goto out;
27046+
27047+ err = 0;
27048+ if (h_path.dentry->d_inode) {
27049+ h_path.mnt = br->br_mnt;
27050+ err = au_wh_unlink_dentry(au_h_iptr(dir, bdst), &h_path,
27051+ dentry);
27052+ }
27053+ dput(h_path.dentry);
27054+
4f0767ce 27055+out:
1facf9fc 27056+ return err;
27057+}
27058+
27059+static int au_cpdown_dir(struct dentry *dentry, aufs_bindex_t bdst,
27060+ struct dentry *h_parent, void *arg)
27061+{
27062+ int err, rerr;
4a4d8108 27063+ aufs_bindex_t bopq, bstart;
1facf9fc 27064+ struct path h_path;
27065+ struct dentry *parent;
27066+ struct inode *h_dir, *h_inode, *inode, *dir;
27067+ struct au_cpdown_dir_args *args = arg;
27068+
27069+ bstart = au_dbstart(dentry);
27070+ /* dentry is di-locked */
27071+ parent = dget_parent(dentry);
27072+ dir = parent->d_inode;
27073+ h_dir = h_parent->d_inode;
27074+ AuDebugOn(h_dir != au_h_iptr(dir, bdst));
27075+ IMustLock(h_dir);
27076+
27077+ err = au_lkup_neg(dentry, bdst);
27078+ if (unlikely(err < 0))
27079+ goto out;
27080+ h_path.dentry = au_h_dptr(dentry, bdst);
27081+ h_path.mnt = au_sbr_mnt(dentry->d_sb, bdst);
27082+ err = vfsub_sio_mkdir(au_h_iptr(dir, bdst), &h_path,
27083+ S_IRWXU | S_IRUGO | S_IXUGO);
27084+ if (unlikely(err))
27085+ goto out_put;
27086+ au_fset_cpdown(args->flags, MADE_DIR);
27087+
1facf9fc 27088+ bopq = au_dbdiropq(dentry);
27089+ au_fclr_cpdown(args->flags, WHED);
27090+ au_fclr_cpdown(args->flags, DIROPQ);
27091+ if (au_dbwh(dentry) == bdst)
27092+ au_fset_cpdown(args->flags, WHED);
27093+ if (!au_ftest_cpdown(args->flags, PARENT_OPQ) && bopq <= bdst)
27094+ au_fset_cpdown(args->flags, PARENT_OPQ);
1facf9fc 27095+ h_inode = h_path.dentry->d_inode;
27096+ mutex_lock_nested(&h_inode->i_mutex, AuLsc_I_CHILD);
27097+ if (au_ftest_cpdown(args->flags, WHED)) {
27098+ err = au_cpdown_dir_opq(dentry, bdst, args);
27099+ if (unlikely(err)) {
27100+ mutex_unlock(&h_inode->i_mutex);
27101+ goto out_dir;
27102+ }
27103+ }
27104+
27105+ err = au_cpdown_attr(&h_path, au_h_dptr(dentry, bstart));
27106+ mutex_unlock(&h_inode->i_mutex);
27107+ if (unlikely(err))
27108+ goto out_opq;
27109+
27110+ if (au_ftest_cpdown(args->flags, WHED)) {
27111+ err = au_cpdown_dir_wh(dentry, h_parent, dir, bdst);
27112+ if (unlikely(err))
27113+ goto out_opq;
27114+ }
27115+
27116+ inode = dentry->d_inode;
27117+ if (au_ibend(inode) < bdst)
27118+ au_set_ibend(inode, bdst);
27119+ au_set_h_iptr(inode, bdst, au_igrab(h_inode),
27120+ au_hi_flags(inode, /*isdir*/1));
27121+ goto out; /* success */
27122+
27123+ /* revert */
4f0767ce 27124+out_opq:
1facf9fc 27125+ if (au_ftest_cpdown(args->flags, DIROPQ)) {
27126+ mutex_lock_nested(&h_inode->i_mutex, AuLsc_I_CHILD);
27127+ rerr = au_diropq_remove(dentry, bdst);
27128+ mutex_unlock(&h_inode->i_mutex);
27129+ if (unlikely(rerr)) {
27130+ AuIOErr("failed removing diropq for %.*s b%d (%d)\n",
27131+ AuDLNPair(dentry), bdst, rerr);
27132+ err = -EIO;
27133+ goto out;
27134+ }
27135+ }
4f0767ce 27136+out_dir:
1facf9fc 27137+ if (au_ftest_cpdown(args->flags, MADE_DIR)) {
27138+ rerr = vfsub_sio_rmdir(au_h_iptr(dir, bdst), &h_path);
27139+ if (unlikely(rerr)) {
27140+ AuIOErr("failed removing %.*s b%d (%d)\n",
27141+ AuDLNPair(dentry), bdst, rerr);
27142+ err = -EIO;
27143+ }
27144+ }
4f0767ce 27145+out_put:
1facf9fc 27146+ au_set_h_dptr(dentry, bdst, NULL);
27147+ if (au_dbend(dentry) == bdst)
27148+ au_update_dbend(dentry);
4f0767ce 27149+out:
1facf9fc 27150+ dput(parent);
27151+ return err;
27152+}
27153+
27154+int au_cpdown_dirs(struct dentry *dentry, aufs_bindex_t bdst)
27155+{
27156+ int err;
27157+ struct au_cpdown_dir_args args = {
27158+ .parent = dget_parent(dentry),
27159+ .flags = 0
27160+ };
27161+
27162+ err = au_cp_dirs(dentry, bdst, au_cpdown_dir, &args);
27163+ dput(args.parent);
27164+
27165+ return err;
27166+}
27167+
27168+/* ---------------------------------------------------------------------- */
27169+
27170+/* policies for create */
27171+
4a4d8108
AM
27172+static int au_wbr_nonopq(struct dentry *dentry, aufs_bindex_t bindex)
27173+{
27174+ int err, i, j, ndentry;
27175+ aufs_bindex_t bopq;
27176+ struct au_dcsub_pages dpages;
27177+ struct au_dpage *dpage;
27178+ struct dentry **dentries, *parent, *d;
27179+
27180+ err = au_dpages_init(&dpages, GFP_NOFS);
27181+ if (unlikely(err))
27182+ goto out;
27183+ parent = dget_parent(dentry);
027c5e7a 27184+ err = au_dcsub_pages_rev_aufs(&dpages, parent, /*do_include*/0);
4a4d8108
AM
27185+ if (unlikely(err))
27186+ goto out_free;
27187+
27188+ err = bindex;
27189+ for (i = 0; i < dpages.ndpage; i++) {
27190+ dpage = dpages.dpages + i;
27191+ dentries = dpage->dentries;
27192+ ndentry = dpage->ndentry;
27193+ for (j = 0; j < ndentry; j++) {
27194+ d = dentries[j];
27195+ di_read_lock_parent2(d, !AuLock_IR);
27196+ bopq = au_dbdiropq(d);
27197+ di_read_unlock(d, !AuLock_IR);
27198+ if (bopq >= 0 && bopq < err)
27199+ err = bopq;
27200+ }
27201+ }
27202+
27203+out_free:
27204+ dput(parent);
27205+ au_dpages_free(&dpages);
27206+out:
27207+ return err;
27208+}
27209+
1facf9fc 27210+static int au_wbr_bu(struct super_block *sb, aufs_bindex_t bindex)
27211+{
27212+ for (; bindex >= 0; bindex--)
27213+ if (!au_br_rdonly(au_sbr(sb, bindex)))
27214+ return bindex;
27215+ return -EROFS;
27216+}
27217+
27218+/* top down parent */
27219+static int au_wbr_create_tdp(struct dentry *dentry, int isdir __maybe_unused)
27220+{
27221+ int err;
27222+ aufs_bindex_t bstart, bindex;
27223+ struct super_block *sb;
27224+ struct dentry *parent, *h_parent;
27225+
27226+ sb = dentry->d_sb;
27227+ bstart = au_dbstart(dentry);
27228+ err = bstart;
27229+ if (!au_br_rdonly(au_sbr(sb, bstart)))
27230+ goto out;
27231+
27232+ err = -EROFS;
27233+ parent = dget_parent(dentry);
27234+ for (bindex = au_dbstart(parent); bindex < bstart; bindex++) {
27235+ h_parent = au_h_dptr(parent, bindex);
27236+ if (!h_parent || !h_parent->d_inode)
27237+ continue;
27238+
27239+ if (!au_br_rdonly(au_sbr(sb, bindex))) {
27240+ err = bindex;
27241+ break;
27242+ }
27243+ }
27244+ dput(parent);
27245+
27246+ /* bottom up here */
4a4d8108 27247+ if (unlikely(err < 0)) {
1facf9fc 27248+ err = au_wbr_bu(sb, bstart - 1);
4a4d8108
AM
27249+ if (err >= 0)
27250+ err = au_wbr_nonopq(dentry, err);
27251+ }
1facf9fc 27252+
4f0767ce 27253+out:
1facf9fc 27254+ AuDbg("b%d\n", err);
27255+ return err;
27256+}
27257+
27258+/* ---------------------------------------------------------------------- */
27259+
27260+/* an exception for the policy other than tdp */
27261+static int au_wbr_create_exp(struct dentry *dentry)
27262+{
27263+ int err;
27264+ aufs_bindex_t bwh, bdiropq;
27265+ struct dentry *parent;
27266+
27267+ err = -1;
27268+ bwh = au_dbwh(dentry);
27269+ parent = dget_parent(dentry);
27270+ bdiropq = au_dbdiropq(parent);
27271+ if (bwh >= 0) {
27272+ if (bdiropq >= 0)
27273+ err = min(bdiropq, bwh);
27274+ else
27275+ err = bwh;
27276+ AuDbg("%d\n", err);
27277+ } else if (bdiropq >= 0) {
27278+ err = bdiropq;
27279+ AuDbg("%d\n", err);
27280+ }
27281+ dput(parent);
27282+
4a4d8108
AM
27283+ if (err >= 0)
27284+ err = au_wbr_nonopq(dentry, err);
27285+
1facf9fc 27286+ if (err >= 0 && au_br_rdonly(au_sbr(dentry->d_sb, err)))
27287+ err = -1;
27288+
27289+ AuDbg("%d\n", err);
27290+ return err;
27291+}
27292+
27293+/* ---------------------------------------------------------------------- */
27294+
27295+/* round robin */
27296+static int au_wbr_create_init_rr(struct super_block *sb)
27297+{
27298+ int err;
27299+
27300+ err = au_wbr_bu(sb, au_sbend(sb));
27301+ atomic_set(&au_sbi(sb)->si_wbr_rr_next, -err); /* less important */
dece6358 27302+ /* smp_mb(); */
1facf9fc 27303+
27304+ AuDbg("b%d\n", err);
27305+ return err;
27306+}
27307+
27308+static int au_wbr_create_rr(struct dentry *dentry, int isdir)
27309+{
27310+ int err, nbr;
27311+ unsigned int u;
27312+ aufs_bindex_t bindex, bend;
27313+ struct super_block *sb;
27314+ atomic_t *next;
27315+
27316+ err = au_wbr_create_exp(dentry);
27317+ if (err >= 0)
27318+ goto out;
27319+
27320+ sb = dentry->d_sb;
27321+ next = &au_sbi(sb)->si_wbr_rr_next;
27322+ bend = au_sbend(sb);
27323+ nbr = bend + 1;
27324+ for (bindex = 0; bindex <= bend; bindex++) {
27325+ if (!isdir) {
27326+ err = atomic_dec_return(next) + 1;
27327+ /* modulo for 0 is meaningless */
27328+ if (unlikely(!err))
27329+ err = atomic_dec_return(next) + 1;
27330+ } else
27331+ err = atomic_read(next);
27332+ AuDbg("%d\n", err);
27333+ u = err;
27334+ err = u % nbr;
27335+ AuDbg("%d\n", err);
27336+ if (!au_br_rdonly(au_sbr(sb, err)))
27337+ break;
27338+ err = -EROFS;
27339+ }
27340+
4a4d8108
AM
27341+ if (err >= 0)
27342+ err = au_wbr_nonopq(dentry, err);
27343+
4f0767ce 27344+out:
1facf9fc 27345+ AuDbg("%d\n", err);
27346+ return err;
27347+}
27348+
27349+/* ---------------------------------------------------------------------- */
27350+
27351+/* most free space */
27352+static void au_mfs(struct dentry *dentry)
27353+{
27354+ struct super_block *sb;
27355+ struct au_branch *br;
27356+ struct au_wbr_mfs *mfs;
27357+ aufs_bindex_t bindex, bend;
27358+ int err;
27359+ unsigned long long b, bavail;
7f207e10 27360+ struct path h_path;
1facf9fc 27361+ /* reduce the stack usage */
27362+ struct kstatfs *st;
27363+
27364+ st = kmalloc(sizeof(*st), GFP_NOFS);
27365+ if (unlikely(!st)) {
27366+ AuWarn1("failed updating mfs(%d), ignored\n", -ENOMEM);
27367+ return;
27368+ }
27369+
27370+ bavail = 0;
27371+ sb = dentry->d_sb;
27372+ mfs = &au_sbi(sb)->si_wbr_mfs;
dece6358 27373+ MtxMustLock(&mfs->mfs_lock);
1facf9fc 27374+ mfs->mfs_bindex = -EROFS;
27375+ mfs->mfsrr_bytes = 0;
27376+ bend = au_sbend(sb);
27377+ for (bindex = 0; bindex <= bend; bindex++) {
27378+ br = au_sbr(sb, bindex);
27379+ if (au_br_rdonly(br))
27380+ continue;
27381+
27382+ /* sb->s_root for NFS is unreliable */
7f207e10
AM
27383+ h_path.mnt = br->br_mnt;
27384+ h_path.dentry = h_path.mnt->mnt_root;
27385+ err = vfs_statfs(&h_path, st);
1facf9fc 27386+ if (unlikely(err)) {
27387+ AuWarn1("failed statfs, b%d, %d\n", bindex, err);
27388+ continue;
27389+ }
27390+
27391+ /* when the available size is equal, select the lower one */
27392+ BUILD_BUG_ON(sizeof(b) < sizeof(st->f_bavail)
27393+ || sizeof(b) < sizeof(st->f_bsize));
27394+ b = st->f_bavail * st->f_bsize;
27395+ br->br_wbr->wbr_bytes = b;
27396+ if (b >= bavail) {
27397+ bavail = b;
27398+ mfs->mfs_bindex = bindex;
27399+ mfs->mfs_jiffy = jiffies;
27400+ }
27401+ }
27402+
27403+ mfs->mfsrr_bytes = bavail;
27404+ AuDbg("b%d\n", mfs->mfs_bindex);
27405+ kfree(st);
27406+}
27407+
27408+static int au_wbr_create_mfs(struct dentry *dentry, int isdir __maybe_unused)
27409+{
27410+ int err;
27411+ struct super_block *sb;
27412+ struct au_wbr_mfs *mfs;
27413+
27414+ err = au_wbr_create_exp(dentry);
27415+ if (err >= 0)
27416+ goto out;
27417+
27418+ sb = dentry->d_sb;
27419+ mfs = &au_sbi(sb)->si_wbr_mfs;
27420+ mutex_lock(&mfs->mfs_lock);
27421+ if (time_after(jiffies, mfs->mfs_jiffy + mfs->mfs_expire)
27422+ || mfs->mfs_bindex < 0
27423+ || au_br_rdonly(au_sbr(sb, mfs->mfs_bindex)))
27424+ au_mfs(dentry);
27425+ mutex_unlock(&mfs->mfs_lock);
27426+ err = mfs->mfs_bindex;
27427+
4a4d8108
AM
27428+ if (err >= 0)
27429+ err = au_wbr_nonopq(dentry, err);
27430+
4f0767ce 27431+out:
1facf9fc 27432+ AuDbg("b%d\n", err);
27433+ return err;
27434+}
27435+
27436+static int au_wbr_create_init_mfs(struct super_block *sb)
27437+{
27438+ struct au_wbr_mfs *mfs;
27439+
27440+ mfs = &au_sbi(sb)->si_wbr_mfs;
27441+ mutex_init(&mfs->mfs_lock);
27442+ mfs->mfs_jiffy = 0;
27443+ mfs->mfs_bindex = -EROFS;
27444+
27445+ return 0;
27446+}
27447+
27448+static int au_wbr_create_fin_mfs(struct super_block *sb __maybe_unused)
27449+{
27450+ mutex_destroy(&au_sbi(sb)->si_wbr_mfs.mfs_lock);
27451+ return 0;
27452+}
27453+
27454+/* ---------------------------------------------------------------------- */
27455+
27456+/* most free space and then round robin */
27457+static int au_wbr_create_mfsrr(struct dentry *dentry, int isdir)
27458+{
27459+ int err;
27460+ struct au_wbr_mfs *mfs;
27461+
27462+ err = au_wbr_create_mfs(dentry, isdir);
27463+ if (err >= 0) {
27464+ mfs = &au_sbi(dentry->d_sb)->si_wbr_mfs;
dece6358 27465+ mutex_lock(&mfs->mfs_lock);
1facf9fc 27466+ if (mfs->mfsrr_bytes < mfs->mfsrr_watermark)
27467+ err = au_wbr_create_rr(dentry, isdir);
dece6358 27468+ mutex_unlock(&mfs->mfs_lock);
1facf9fc 27469+ }
27470+
27471+ AuDbg("b%d\n", err);
27472+ return err;
27473+}
27474+
27475+static int au_wbr_create_init_mfsrr(struct super_block *sb)
27476+{
27477+ int err;
27478+
27479+ au_wbr_create_init_mfs(sb); /* ignore */
27480+ err = au_wbr_create_init_rr(sb);
27481+
27482+ return err;
27483+}
27484+
27485+/* ---------------------------------------------------------------------- */
27486+
27487+/* top down parent and most free space */
27488+static int au_wbr_create_pmfs(struct dentry *dentry, int isdir)
27489+{
27490+ int err, e2;
27491+ unsigned long long b;
27492+ aufs_bindex_t bindex, bstart, bend;
27493+ struct super_block *sb;
27494+ struct dentry *parent, *h_parent;
27495+ struct au_branch *br;
27496+
27497+ err = au_wbr_create_tdp(dentry, isdir);
27498+ if (unlikely(err < 0))
27499+ goto out;
27500+ parent = dget_parent(dentry);
27501+ bstart = au_dbstart(parent);
27502+ bend = au_dbtaildir(parent);
27503+ if (bstart == bend)
27504+ goto out_parent; /* success */
27505+
27506+ e2 = au_wbr_create_mfs(dentry, isdir);
27507+ if (e2 < 0)
27508+ goto out_parent; /* success */
27509+
27510+ /* when the available size is equal, select upper one */
27511+ sb = dentry->d_sb;
27512+ br = au_sbr(sb, err);
27513+ b = br->br_wbr->wbr_bytes;
27514+ AuDbg("b%d, %llu\n", err, b);
27515+
27516+ for (bindex = bstart; bindex <= bend; bindex++) {
27517+ h_parent = au_h_dptr(parent, bindex);
27518+ if (!h_parent || !h_parent->d_inode)
27519+ continue;
27520+
27521+ br = au_sbr(sb, bindex);
27522+ if (!au_br_rdonly(br) && br->br_wbr->wbr_bytes > b) {
27523+ b = br->br_wbr->wbr_bytes;
27524+ err = bindex;
27525+ AuDbg("b%d, %llu\n", err, b);
27526+ }
27527+ }
27528+
4a4d8108
AM
27529+ if (err >= 0)
27530+ err = au_wbr_nonopq(dentry, err);
27531+
4f0767ce 27532+out_parent:
1facf9fc 27533+ dput(parent);
4f0767ce 27534+out:
1facf9fc 27535+ AuDbg("b%d\n", err);
27536+ return err;
27537+}
27538+
27539+/* ---------------------------------------------------------------------- */
27540+
27541+/* policies for copyup */
27542+
27543+/* top down parent */
27544+static int au_wbr_copyup_tdp(struct dentry *dentry)
27545+{
27546+ return au_wbr_create_tdp(dentry, /*isdir, anything is ok*/0);
27547+}
27548+
27549+/* bottom up parent */
27550+static int au_wbr_copyup_bup(struct dentry *dentry)
27551+{
27552+ int err;
27553+ aufs_bindex_t bindex, bstart;
27554+ struct dentry *parent, *h_parent;
27555+ struct super_block *sb;
27556+
27557+ err = -EROFS;
27558+ sb = dentry->d_sb;
27559+ parent = dget_parent(dentry);
27560+ bstart = au_dbstart(parent);
27561+ for (bindex = au_dbstart(dentry); bindex >= bstart; bindex--) {
27562+ h_parent = au_h_dptr(parent, bindex);
27563+ if (!h_parent || !h_parent->d_inode)
27564+ continue;
27565+
27566+ if (!au_br_rdonly(au_sbr(sb, bindex))) {
27567+ err = bindex;
27568+ break;
27569+ }
27570+ }
27571+ dput(parent);
27572+
27573+ /* bottom up here */
27574+ if (unlikely(err < 0))
27575+ err = au_wbr_bu(sb, bstart - 1);
27576+
27577+ AuDbg("b%d\n", err);
27578+ return err;
27579+}
27580+
27581+/* bottom up */
27582+static int au_wbr_copyup_bu(struct dentry *dentry)
27583+{
27584+ int err;
4a4d8108 27585+ aufs_bindex_t bstart;
1facf9fc 27586+
4a4d8108
AM
27587+ bstart = au_dbstart(dentry);
27588+ err = au_wbr_bu(dentry->d_sb, bstart);
27589+ AuDbg("b%d\n", err);
27590+ if (err > bstart)
27591+ err = au_wbr_nonopq(dentry, err);
1facf9fc 27592+
27593+ AuDbg("b%d\n", err);
27594+ return err;
27595+}
27596+
27597+/* ---------------------------------------------------------------------- */
27598+
27599+struct au_wbr_copyup_operations au_wbr_copyup_ops[] = {
27600+ [AuWbrCopyup_TDP] = {
27601+ .copyup = au_wbr_copyup_tdp
27602+ },
27603+ [AuWbrCopyup_BUP] = {
27604+ .copyup = au_wbr_copyup_bup
27605+ },
27606+ [AuWbrCopyup_BU] = {
27607+ .copyup = au_wbr_copyup_bu
27608+ }
27609+};
27610+
27611+struct au_wbr_create_operations au_wbr_create_ops[] = {
27612+ [AuWbrCreate_TDP] = {
27613+ .create = au_wbr_create_tdp
27614+ },
27615+ [AuWbrCreate_RR] = {
27616+ .create = au_wbr_create_rr,
27617+ .init = au_wbr_create_init_rr
27618+ },
27619+ [AuWbrCreate_MFS] = {
27620+ .create = au_wbr_create_mfs,
27621+ .init = au_wbr_create_init_mfs,
27622+ .fin = au_wbr_create_fin_mfs
27623+ },
27624+ [AuWbrCreate_MFSV] = {
27625+ .create = au_wbr_create_mfs,
27626+ .init = au_wbr_create_init_mfs,
27627+ .fin = au_wbr_create_fin_mfs
27628+ },
27629+ [AuWbrCreate_MFSRR] = {
27630+ .create = au_wbr_create_mfsrr,
27631+ .init = au_wbr_create_init_mfsrr,
27632+ .fin = au_wbr_create_fin_mfs
27633+ },
27634+ [AuWbrCreate_MFSRRV] = {
27635+ .create = au_wbr_create_mfsrr,
27636+ .init = au_wbr_create_init_mfsrr,
27637+ .fin = au_wbr_create_fin_mfs
27638+ },
27639+ [AuWbrCreate_PMFS] = {
27640+ .create = au_wbr_create_pmfs,
27641+ .init = au_wbr_create_init_mfs,
27642+ .fin = au_wbr_create_fin_mfs
27643+ },
27644+ [AuWbrCreate_PMFSV] = {
27645+ .create = au_wbr_create_pmfs,
27646+ .init = au_wbr_create_init_mfs,
27647+ .fin = au_wbr_create_fin_mfs
27648+ }
27649+};
7f207e10
AM
27650diff -urN /usr/share/empty/fs/aufs/whout.c linux/fs/aufs/whout.c
27651--- /usr/share/empty/fs/aufs/whout.c 1970-01-01 01:00:00.000000000 +0100
537831f9 27652+++ linux/fs/aufs/whout.c 2012-12-13 20:41:10.434793588 +0100
b4510431 27653@@ -0,0 +1,1042 @@
1facf9fc 27654+/*
f6c5ef8b 27655+ * Copyright (C) 2005-2012 Junjiro R. Okajima
1facf9fc 27656+ *
27657+ * This program, aufs is free software; you can redistribute it and/or modify
27658+ * it under the terms of the GNU General Public License as published by
27659+ * the Free Software Foundation; either version 2 of the License, or
27660+ * (at your option) any later version.
dece6358
AM
27661+ *
27662+ * This program is distributed in the hope that it will be useful,
27663+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
27664+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
27665+ * GNU General Public License for more details.
27666+ *
27667+ * You should have received a copy of the GNU General Public License
27668+ * along with this program; if not, write to the Free Software
27669+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 27670+ */
27671+
27672+/*
27673+ * whiteout for logical deletion and opaque directory
27674+ */
27675+
1facf9fc 27676+#include "aufs.h"
27677+
27678+#define WH_MASK S_IRUGO
27679+
27680+/*
27681+ * If a directory contains this file, then it is opaque. We start with the
27682+ * .wh. flag so that it is blocked by lookup.
27683+ */
0c3ec466
AM
27684+static struct qstr diropq_name = QSTR_INIT(AUFS_WH_DIROPQ,
27685+ sizeof(AUFS_WH_DIROPQ) - 1);
1facf9fc 27686+
27687+/*
27688+ * generate whiteout name, which is NOT terminated by NULL.
27689+ * @name: original d_name.name
27690+ * @len: original d_name.len
27691+ * @wh: whiteout qstr
27692+ * returns zero when succeeds, otherwise error.
27693+ * succeeded value as wh->name should be freed by kfree().
27694+ */
27695+int au_wh_name_alloc(struct qstr *wh, const struct qstr *name)
27696+{
27697+ char *p;
27698+
27699+ if (unlikely(name->len > PATH_MAX - AUFS_WH_PFX_LEN))
27700+ return -ENAMETOOLONG;
27701+
27702+ wh->len = name->len + AUFS_WH_PFX_LEN;
27703+ p = kmalloc(wh->len, GFP_NOFS);
27704+ wh->name = p;
27705+ if (p) {
27706+ memcpy(p, AUFS_WH_PFX, AUFS_WH_PFX_LEN);
27707+ memcpy(p + AUFS_WH_PFX_LEN, name->name, name->len);
27708+ /* smp_mb(); */
27709+ return 0;
27710+ }
27711+ return -ENOMEM;
27712+}
27713+
27714+/* ---------------------------------------------------------------------- */
27715+
27716+/*
27717+ * test if the @wh_name exists under @h_parent.
27718+ * @try_sio specifies the necessary of super-io.
27719+ */
27720+int au_wh_test(struct dentry *h_parent, struct qstr *wh_name,
27721+ struct au_branch *br, int try_sio)
27722+{
27723+ int err;
27724+ struct dentry *wh_dentry;
1facf9fc 27725+
1facf9fc 27726+ if (!try_sio)
b4510431 27727+ wh_dentry = vfsub_lkup_one(wh_name, h_parent);
1facf9fc 27728+ else
27729+ wh_dentry = au_sio_lkup_one(wh_name, h_parent, br);
27730+ err = PTR_ERR(wh_dentry);
27731+ if (IS_ERR(wh_dentry))
27732+ goto out;
27733+
27734+ err = 0;
27735+ if (!wh_dentry->d_inode)
27736+ goto out_wh; /* success */
27737+
27738+ err = 1;
27739+ if (S_ISREG(wh_dentry->d_inode->i_mode))
27740+ goto out_wh; /* success */
27741+
27742+ err = -EIO;
27743+ AuIOErr("%.*s Invalid whiteout entry type 0%o.\n",
27744+ AuDLNPair(wh_dentry), wh_dentry->d_inode->i_mode);
27745+
4f0767ce 27746+out_wh:
1facf9fc 27747+ dput(wh_dentry);
4f0767ce 27748+out:
1facf9fc 27749+ return err;
27750+}
27751+
27752+/*
27753+ * test if the @h_dentry sets opaque or not.
27754+ */
27755+int au_diropq_test(struct dentry *h_dentry, struct au_branch *br)
27756+{
27757+ int err;
27758+ struct inode *h_dir;
27759+
27760+ h_dir = h_dentry->d_inode;
27761+ err = au_wh_test(h_dentry, &diropq_name, br,
27762+ au_test_h_perm_sio(h_dir, MAY_EXEC));
27763+ return err;
27764+}
27765+
27766+/*
27767+ * returns a negative dentry whose name is unique and temporary.
27768+ */
27769+struct dentry *au_whtmp_lkup(struct dentry *h_parent, struct au_branch *br,
27770+ struct qstr *prefix)
27771+{
1facf9fc 27772+ struct dentry *dentry;
27773+ int i;
027c5e7a 27774+ char defname[NAME_MAX - AUFS_MAX_NAMELEN + DNAME_INLINE_LEN + 1],
4a4d8108 27775+ *name, *p;
027c5e7a 27776+ /* strict atomic_t is unnecessary here */
1facf9fc 27777+ static unsigned short cnt;
27778+ struct qstr qs;
27779+
4a4d8108
AM
27780+ BUILD_BUG_ON(sizeof(cnt) * 2 > AUFS_WH_TMP_LEN);
27781+
1facf9fc 27782+ name = defname;
027c5e7a
AM
27783+ qs.len = sizeof(defname) - DNAME_INLINE_LEN + prefix->len - 1;
27784+ if (unlikely(prefix->len > DNAME_INLINE_LEN)) {
1facf9fc 27785+ dentry = ERR_PTR(-ENAMETOOLONG);
4a4d8108 27786+ if (unlikely(qs.len > NAME_MAX))
1facf9fc 27787+ goto out;
27788+ dentry = ERR_PTR(-ENOMEM);
27789+ name = kmalloc(qs.len + 1, GFP_NOFS);
27790+ if (unlikely(!name))
27791+ goto out;
27792+ }
27793+
27794+ /* doubly whiteout-ed */
27795+ memcpy(name, AUFS_WH_PFX AUFS_WH_PFX, AUFS_WH_PFX_LEN * 2);
27796+ p = name + AUFS_WH_PFX_LEN * 2;
27797+ memcpy(p, prefix->name, prefix->len);
27798+ p += prefix->len;
27799+ *p++ = '.';
4a4d8108 27800+ AuDebugOn(name + qs.len + 1 - p <= AUFS_WH_TMP_LEN);
1facf9fc 27801+
27802+ qs.name = name;
27803+ for (i = 0; i < 3; i++) {
b752ccd1 27804+ sprintf(p, "%.*x", AUFS_WH_TMP_LEN, cnt++);
1facf9fc 27805+ dentry = au_sio_lkup_one(&qs, h_parent, br);
27806+ if (IS_ERR(dentry) || !dentry->d_inode)
27807+ goto out_name;
27808+ dput(dentry);
27809+ }
0c3ec466 27810+ /* pr_warn("could not get random name\n"); */
1facf9fc 27811+ dentry = ERR_PTR(-EEXIST);
27812+ AuDbg("%.*s\n", AuLNPair(&qs));
27813+ BUG();
27814+
4f0767ce 27815+out_name:
1facf9fc 27816+ if (name != defname)
27817+ kfree(name);
4f0767ce 27818+out:
4a4d8108 27819+ AuTraceErrPtr(dentry);
1facf9fc 27820+ return dentry;
1facf9fc 27821+}
27822+
27823+/*
27824+ * rename the @h_dentry on @br to the whiteouted temporary name.
27825+ */
27826+int au_whtmp_ren(struct dentry *h_dentry, struct au_branch *br)
27827+{
27828+ int err;
27829+ struct path h_path = {
27830+ .mnt = br->br_mnt
27831+ };
27832+ struct inode *h_dir;
27833+ struct dentry *h_parent;
27834+
27835+ h_parent = h_dentry->d_parent; /* dir inode is locked */
27836+ h_dir = h_parent->d_inode;
27837+ IMustLock(h_dir);
27838+
27839+ h_path.dentry = au_whtmp_lkup(h_parent, br, &h_dentry->d_name);
27840+ err = PTR_ERR(h_path.dentry);
27841+ if (IS_ERR(h_path.dentry))
27842+ goto out;
27843+
27844+ /* under the same dir, no need to lock_rename() */
27845+ err = vfsub_rename(h_dir, h_dentry, h_dir, &h_path);
27846+ AuTraceErr(err);
27847+ dput(h_path.dentry);
27848+
4f0767ce 27849+out:
4a4d8108 27850+ AuTraceErr(err);
1facf9fc 27851+ return err;
27852+}
27853+
27854+/* ---------------------------------------------------------------------- */
27855+/*
27856+ * functions for removing a whiteout
27857+ */
27858+
27859+static int do_unlink_wh(struct inode *h_dir, struct path *h_path)
27860+{
27861+ int force;
27862+
27863+ /*
27864+ * forces superio when the dir has a sticky bit.
27865+ * this may be a violation of unix fs semantics.
27866+ */
27867+ force = (h_dir->i_mode & S_ISVTX)
0c3ec466 27868+ && !uid_eq(current_fsuid(), h_path->dentry->d_inode->i_uid);
1facf9fc 27869+ return vfsub_unlink(h_dir, h_path, force);
27870+}
27871+
27872+int au_wh_unlink_dentry(struct inode *h_dir, struct path *h_path,
27873+ struct dentry *dentry)
27874+{
27875+ int err;
27876+
27877+ err = do_unlink_wh(h_dir, h_path);
27878+ if (!err && dentry)
27879+ au_set_dbwh(dentry, -1);
27880+
27881+ return err;
27882+}
27883+
27884+static int unlink_wh_name(struct dentry *h_parent, struct qstr *wh,
27885+ struct au_branch *br)
27886+{
27887+ int err;
27888+ struct path h_path = {
27889+ .mnt = br->br_mnt
27890+ };
27891+
27892+ err = 0;
b4510431 27893+ h_path.dentry = vfsub_lkup_one(wh, h_parent);
1facf9fc 27894+ if (IS_ERR(h_path.dentry))
27895+ err = PTR_ERR(h_path.dentry);
27896+ else {
27897+ if (h_path.dentry->d_inode
27898+ && S_ISREG(h_path.dentry->d_inode->i_mode))
27899+ err = do_unlink_wh(h_parent->d_inode, &h_path);
27900+ dput(h_path.dentry);
27901+ }
27902+
27903+ return err;
27904+}
27905+
27906+/* ---------------------------------------------------------------------- */
27907+/*
27908+ * initialize/clean whiteout for a branch
27909+ */
27910+
27911+static void au_wh_clean(struct inode *h_dir, struct path *whpath,
27912+ const int isdir)
27913+{
27914+ int err;
27915+
27916+ if (!whpath->dentry->d_inode)
27917+ return;
27918+
b4510431 27919+ err = vfsub_mnt_want_write(whpath->mnt);
1facf9fc 27920+ if (!err) {
27921+ if (isdir)
27922+ err = vfsub_rmdir(h_dir, whpath);
27923+ else
27924+ err = vfsub_unlink(h_dir, whpath, /*force*/0);
b4510431 27925+ vfsub_mnt_drop_write(whpath->mnt);
1facf9fc 27926+ }
27927+ if (unlikely(err))
0c3ec466
AM
27928+ pr_warn("failed removing %.*s (%d), ignored.\n",
27929+ AuDLNPair(whpath->dentry), err);
1facf9fc 27930+}
27931+
27932+static int test_linkable(struct dentry *h_root)
27933+{
27934+ struct inode *h_dir = h_root->d_inode;
27935+
27936+ if (h_dir->i_op->link)
27937+ return 0;
27938+
4a4d8108
AM
27939+ pr_err("%.*s (%s) doesn't support link(2), use noplink and rw+nolwh\n",
27940+ AuDLNPair(h_root), au_sbtype(h_root->d_sb));
1facf9fc 27941+ return -ENOSYS;
27942+}
27943+
27944+/* todo: should this mkdir be done in /sbin/mount.aufs helper? */
27945+static int au_whdir(struct inode *h_dir, struct path *path)
27946+{
27947+ int err;
27948+
27949+ err = -EEXIST;
27950+ if (!path->dentry->d_inode) {
27951+ int mode = S_IRWXU;
27952+
27953+ if (au_test_nfs(path->dentry->d_sb))
27954+ mode |= S_IXUGO;
b4510431 27955+ err = vfsub_mnt_want_write(path->mnt);
1facf9fc 27956+ if (!err) {
27957+ err = vfsub_mkdir(h_dir, path, mode);
b4510431 27958+ vfsub_mnt_drop_write(path->mnt);
1facf9fc 27959+ }
27960+ } else if (S_ISDIR(path->dentry->d_inode->i_mode))
27961+ err = 0;
27962+ else
4a4d8108 27963+ pr_err("unknown %.*s exists\n", AuDLNPair(path->dentry));
1facf9fc 27964+
27965+ return err;
27966+}
27967+
27968+struct au_wh_base {
27969+ const struct qstr *name;
27970+ struct dentry *dentry;
27971+};
27972+
27973+static void au_wh_init_ro(struct inode *h_dir, struct au_wh_base base[],
27974+ struct path *h_path)
27975+{
27976+ h_path->dentry = base[AuBrWh_BASE].dentry;
27977+ au_wh_clean(h_dir, h_path, /*isdir*/0);
27978+ h_path->dentry = base[AuBrWh_PLINK].dentry;
27979+ au_wh_clean(h_dir, h_path, /*isdir*/1);
27980+ h_path->dentry = base[AuBrWh_ORPH].dentry;
27981+ au_wh_clean(h_dir, h_path, /*isdir*/1);
27982+}
27983+
27984+/*
27985+ * returns tri-state,
27986+ * minus: error, caller should print the mesage
27987+ * zero: succuess
27988+ * plus: error, caller should NOT print the mesage
27989+ */
27990+static int au_wh_init_rw_nolink(struct dentry *h_root, struct au_wbr *wbr,
27991+ int do_plink, struct au_wh_base base[],
27992+ struct path *h_path)
27993+{
27994+ int err;
27995+ struct inode *h_dir;
27996+
27997+ h_dir = h_root->d_inode;
27998+ h_path->dentry = base[AuBrWh_BASE].dentry;
27999+ au_wh_clean(h_dir, h_path, /*isdir*/0);
28000+ h_path->dentry = base[AuBrWh_PLINK].dentry;
28001+ if (do_plink) {
28002+ err = test_linkable(h_root);
28003+ if (unlikely(err)) {
28004+ err = 1;
28005+ goto out;
28006+ }
28007+
28008+ err = au_whdir(h_dir, h_path);
28009+ if (unlikely(err))
28010+ goto out;
28011+ wbr->wbr_plink = dget(base[AuBrWh_PLINK].dentry);
28012+ } else
28013+ au_wh_clean(h_dir, h_path, /*isdir*/1);
28014+ h_path->dentry = base[AuBrWh_ORPH].dentry;
28015+ err = au_whdir(h_dir, h_path);
28016+ if (unlikely(err))
28017+ goto out;
28018+ wbr->wbr_orph = dget(base[AuBrWh_ORPH].dentry);
28019+
4f0767ce 28020+out:
1facf9fc 28021+ return err;
28022+}
28023+
28024+/*
28025+ * for the moment, aufs supports the branch filesystem which does not support
28026+ * link(2). testing on FAT which does not support i_op->setattr() fully either,
28027+ * copyup failed. finally, such filesystem will not be used as the writable
28028+ * branch.
28029+ *
28030+ * returns tri-state, see above.
28031+ */
28032+static int au_wh_init_rw(struct dentry *h_root, struct au_wbr *wbr,
28033+ int do_plink, struct au_wh_base base[],
28034+ struct path *h_path)
28035+{
28036+ int err;
28037+ struct inode *h_dir;
28038+
1308ab2a 28039+ WbrWhMustWriteLock(wbr);
28040+
1facf9fc 28041+ err = test_linkable(h_root);
28042+ if (unlikely(err)) {
28043+ err = 1;
28044+ goto out;
28045+ }
28046+
28047+ /*
28048+ * todo: should this create be done in /sbin/mount.aufs helper?
28049+ */
28050+ err = -EEXIST;
28051+ h_dir = h_root->d_inode;
28052+ if (!base[AuBrWh_BASE].dentry->d_inode) {
b4510431 28053+ err = vfsub_mnt_want_write(h_path->mnt);
1facf9fc 28054+ if (!err) {
28055+ h_path->dentry = base[AuBrWh_BASE].dentry;
b4510431
AM
28056+ err = vfsub_create(h_dir, h_path, WH_MASK,
28057+ /*want_excl*/true);
28058+ vfsub_mnt_drop_write(h_path->mnt);
1facf9fc 28059+ }
28060+ } else if (S_ISREG(base[AuBrWh_BASE].dentry->d_inode->i_mode))
28061+ err = 0;
28062+ else
4a4d8108
AM
28063+ pr_err("unknown %.*s/%.*s exists\n",
28064+ AuDLNPair(h_root), AuDLNPair(base[AuBrWh_BASE].dentry));
1facf9fc 28065+ if (unlikely(err))
28066+ goto out;
28067+
28068+ h_path->dentry = base[AuBrWh_PLINK].dentry;
28069+ if (do_plink) {
28070+ err = au_whdir(h_dir, h_path);
28071+ if (unlikely(err))
28072+ goto out;
28073+ wbr->wbr_plink = dget(base[AuBrWh_PLINK].dentry);
28074+ } else
28075+ au_wh_clean(h_dir, h_path, /*isdir*/1);
28076+ wbr->wbr_whbase = dget(base[AuBrWh_BASE].dentry);
28077+
28078+ h_path->dentry = base[AuBrWh_ORPH].dentry;
28079+ err = au_whdir(h_dir, h_path);
28080+ if (unlikely(err))
28081+ goto out;
28082+ wbr->wbr_orph = dget(base[AuBrWh_ORPH].dentry);
28083+
4f0767ce 28084+out:
1facf9fc 28085+ return err;
28086+}
28087+
28088+/*
28089+ * initialize the whiteout base file/dir for @br.
28090+ */
28091+int au_wh_init(struct dentry *h_root, struct au_branch *br,
28092+ struct super_block *sb)
28093+{
28094+ int err, i;
28095+ const unsigned char do_plink
28096+ = !!au_opt_test(au_mntflags(sb), PLINK);
28097+ struct path path = {
28098+ .mnt = br->br_mnt
28099+ };
28100+ struct inode *h_dir;
28101+ struct au_wbr *wbr = br->br_wbr;
28102+ static const struct qstr base_name[] = {
0c3ec466
AM
28103+ [AuBrWh_BASE] = QSTR_INIT(AUFS_BASE_NAME,
28104+ sizeof(AUFS_BASE_NAME) - 1),
28105+ [AuBrWh_PLINK] = QSTR_INIT(AUFS_PLINKDIR_NAME,
28106+ sizeof(AUFS_PLINKDIR_NAME) - 1),
28107+ [AuBrWh_ORPH] = QSTR_INIT(AUFS_ORPHDIR_NAME,
28108+ sizeof(AUFS_ORPHDIR_NAME) - 1)
1facf9fc 28109+ };
28110+ struct au_wh_base base[] = {
28111+ [AuBrWh_BASE] = {
28112+ .name = base_name + AuBrWh_BASE,
28113+ .dentry = NULL
28114+ },
28115+ [AuBrWh_PLINK] = {
28116+ .name = base_name + AuBrWh_PLINK,
28117+ .dentry = NULL
28118+ },
28119+ [AuBrWh_ORPH] = {
28120+ .name = base_name + AuBrWh_ORPH,
28121+ .dentry = NULL
28122+ }
28123+ };
28124+
1308ab2a 28125+ if (wbr)
28126+ WbrWhMustWriteLock(wbr);
1facf9fc 28127+
1facf9fc 28128+ for (i = 0; i < AuBrWh_Last; i++) {
28129+ /* doubly whiteouted */
28130+ struct dentry *d;
28131+
28132+ d = au_wh_lkup(h_root, (void *)base[i].name, br);
28133+ err = PTR_ERR(d);
28134+ if (IS_ERR(d))
28135+ goto out;
28136+
28137+ base[i].dentry = d;
28138+ AuDebugOn(wbr
28139+ && wbr->wbr_wh[i]
28140+ && wbr->wbr_wh[i] != base[i].dentry);
28141+ }
28142+
28143+ if (wbr)
28144+ for (i = 0; i < AuBrWh_Last; i++) {
28145+ dput(wbr->wbr_wh[i]);
28146+ wbr->wbr_wh[i] = NULL;
28147+ }
28148+
28149+ err = 0;
1e00d052 28150+ if (!au_br_writable(br->br_perm)) {
4a4d8108 28151+ h_dir = h_root->d_inode;
1facf9fc 28152+ au_wh_init_ro(h_dir, base, &path);
1e00d052 28153+ } else if (!au_br_wh_linkable(br->br_perm)) {
1facf9fc 28154+ err = au_wh_init_rw_nolink(h_root, wbr, do_plink, base, &path);
28155+ if (err > 0)
28156+ goto out;
28157+ else if (err)
28158+ goto out_err;
1e00d052 28159+ } else {
1facf9fc 28160+ err = au_wh_init_rw(h_root, wbr, do_plink, base, &path);
28161+ if (err > 0)
28162+ goto out;
28163+ else if (err)
28164+ goto out_err;
1facf9fc 28165+ }
28166+ goto out; /* success */
28167+
4f0767ce 28168+out_err:
4a4d8108
AM
28169+ pr_err("an error(%d) on the writable branch %.*s(%s)\n",
28170+ err, AuDLNPair(h_root), au_sbtype(h_root->d_sb));
4f0767ce 28171+out:
1facf9fc 28172+ for (i = 0; i < AuBrWh_Last; i++)
28173+ dput(base[i].dentry);
28174+ return err;
28175+}
28176+
28177+/* ---------------------------------------------------------------------- */
28178+/*
28179+ * whiteouts are all hard-linked usually.
28180+ * when its link count reaches a ceiling, we create a new whiteout base
28181+ * asynchronously.
28182+ */
28183+
28184+struct reinit_br_wh {
28185+ struct super_block *sb;
28186+ struct au_branch *br;
28187+};
28188+
28189+static void reinit_br_wh(void *arg)
28190+{
28191+ int err;
28192+ aufs_bindex_t bindex;
28193+ struct path h_path;
28194+ struct reinit_br_wh *a = arg;
28195+ struct au_wbr *wbr;
28196+ struct inode *dir;
28197+ struct dentry *h_root;
28198+ struct au_hinode *hdir;
28199+
28200+ err = 0;
28201+ wbr = a->br->br_wbr;
28202+ /* big aufs lock */
28203+ si_noflush_write_lock(a->sb);
28204+ if (!au_br_writable(a->br->br_perm))
28205+ goto out;
28206+ bindex = au_br_index(a->sb, a->br->br_id);
28207+ if (unlikely(bindex < 0))
28208+ goto out;
28209+
1308ab2a 28210+ di_read_lock_parent(a->sb->s_root, AuLock_IR);
1facf9fc 28211+ dir = a->sb->s_root->d_inode;
1facf9fc 28212+ hdir = au_hi(dir, bindex);
28213+ h_root = au_h_dptr(a->sb->s_root, bindex);
28214+
4a4d8108 28215+ au_hn_imtx_lock_nested(hdir, AuLsc_I_PARENT);
1facf9fc 28216+ wbr_wh_write_lock(wbr);
28217+ err = au_h_verify(wbr->wbr_whbase, au_opt_udba(a->sb), hdir->hi_inode,
28218+ h_root, a->br);
28219+ if (!err) {
b4510431 28220+ err = vfsub_mnt_want_write(a->br->br_mnt);
1facf9fc 28221+ if (!err) {
28222+ h_path.dentry = wbr->wbr_whbase;
28223+ h_path.mnt = a->br->br_mnt;
28224+ err = vfsub_unlink(hdir->hi_inode, &h_path, /*force*/0);
b4510431 28225+ vfsub_mnt_drop_write(a->br->br_mnt);
1facf9fc 28226+ }
28227+ } else {
0c3ec466
AM
28228+ pr_warn("%.*s is moved, ignored\n",
28229+ AuDLNPair(wbr->wbr_whbase));
1facf9fc 28230+ err = 0;
28231+ }
28232+ dput(wbr->wbr_whbase);
28233+ wbr->wbr_whbase = NULL;
28234+ if (!err)
28235+ err = au_wh_init(h_root, a->br, a->sb);
28236+ wbr_wh_write_unlock(wbr);
4a4d8108 28237+ au_hn_imtx_unlock(hdir);
1308ab2a 28238+ di_read_unlock(a->sb->s_root, AuLock_IR);
1facf9fc 28239+
4f0767ce 28240+out:
1facf9fc 28241+ if (wbr)
28242+ atomic_dec(&wbr->wbr_wh_running);
28243+ atomic_dec(&a->br->br_count);
1facf9fc 28244+ si_write_unlock(a->sb);
027c5e7a 28245+ au_nwt_done(&au_sbi(a->sb)->si_nowait);
1facf9fc 28246+ kfree(arg);
28247+ if (unlikely(err))
28248+ AuIOErr("err %d\n", err);
28249+}
28250+
28251+static void kick_reinit_br_wh(struct super_block *sb, struct au_branch *br)
28252+{
28253+ int do_dec, wkq_err;
28254+ struct reinit_br_wh *arg;
28255+
28256+ do_dec = 1;
28257+ if (atomic_inc_return(&br->br_wbr->wbr_wh_running) != 1)
28258+ goto out;
28259+
28260+ /* ignore ENOMEM */
28261+ arg = kmalloc(sizeof(*arg), GFP_NOFS);
28262+ if (arg) {
28263+ /*
28264+ * dec(wh_running), kfree(arg) and dec(br_count)
28265+ * in reinit function
28266+ */
28267+ arg->sb = sb;
28268+ arg->br = br;
28269+ atomic_inc(&br->br_count);
53392da6 28270+ wkq_err = au_wkq_nowait(reinit_br_wh, arg, sb, /*flags*/0);
1facf9fc 28271+ if (unlikely(wkq_err)) {
28272+ atomic_dec(&br->br_wbr->wbr_wh_running);
28273+ atomic_dec(&br->br_count);
28274+ kfree(arg);
28275+ }
28276+ do_dec = 0;
28277+ }
28278+
4f0767ce 28279+out:
1facf9fc 28280+ if (do_dec)
28281+ atomic_dec(&br->br_wbr->wbr_wh_running);
28282+}
28283+
28284+/* ---------------------------------------------------------------------- */
28285+
28286+/*
28287+ * create the whiteout @wh.
28288+ */
28289+static int link_or_create_wh(struct super_block *sb, aufs_bindex_t bindex,
28290+ struct dentry *wh)
28291+{
28292+ int err;
28293+ struct path h_path = {
28294+ .dentry = wh
28295+ };
28296+ struct au_branch *br;
28297+ struct au_wbr *wbr;
28298+ struct dentry *h_parent;
28299+ struct inode *h_dir;
28300+
28301+ h_parent = wh->d_parent; /* dir inode is locked */
28302+ h_dir = h_parent->d_inode;
28303+ IMustLock(h_dir);
28304+
28305+ br = au_sbr(sb, bindex);
28306+ h_path.mnt = br->br_mnt;
28307+ wbr = br->br_wbr;
28308+ wbr_wh_read_lock(wbr);
28309+ if (wbr->wbr_whbase) {
28310+ err = vfsub_link(wbr->wbr_whbase, h_dir, &h_path);
28311+ if (!err || err != -EMLINK)
28312+ goto out;
28313+
28314+ /* link count full. re-initialize br_whbase. */
28315+ kick_reinit_br_wh(sb, br);
28316+ }
28317+
28318+ /* return this error in this context */
b4510431 28319+ err = vfsub_create(h_dir, &h_path, WH_MASK, /*want_excl*/true);
1facf9fc 28320+
4f0767ce 28321+out:
1facf9fc 28322+ wbr_wh_read_unlock(wbr);
28323+ return err;
28324+}
28325+
28326+/* ---------------------------------------------------------------------- */
28327+
28328+/*
28329+ * create or remove the diropq.
28330+ */
28331+static struct dentry *do_diropq(struct dentry *dentry, aufs_bindex_t bindex,
28332+ unsigned int flags)
28333+{
28334+ struct dentry *opq_dentry, *h_dentry;
28335+ struct super_block *sb;
28336+ struct au_branch *br;
28337+ int err;
28338+
28339+ sb = dentry->d_sb;
28340+ br = au_sbr(sb, bindex);
28341+ h_dentry = au_h_dptr(dentry, bindex);
b4510431 28342+ opq_dentry = vfsub_lkup_one(&diropq_name, h_dentry);
1facf9fc 28343+ if (IS_ERR(opq_dentry))
28344+ goto out;
28345+
28346+ if (au_ftest_diropq(flags, CREATE)) {
28347+ err = link_or_create_wh(sb, bindex, opq_dentry);
28348+ if (!err) {
28349+ au_set_dbdiropq(dentry, bindex);
28350+ goto out; /* success */
28351+ }
28352+ } else {
28353+ struct path tmp = {
28354+ .dentry = opq_dentry,
28355+ .mnt = br->br_mnt
28356+ };
28357+ err = do_unlink_wh(au_h_iptr(dentry->d_inode, bindex), &tmp);
28358+ if (!err)
28359+ au_set_dbdiropq(dentry, -1);
28360+ }
28361+ dput(opq_dentry);
28362+ opq_dentry = ERR_PTR(err);
28363+
4f0767ce 28364+out:
1facf9fc 28365+ return opq_dentry;
28366+}
28367+
28368+struct do_diropq_args {
28369+ struct dentry **errp;
28370+ struct dentry *dentry;
28371+ aufs_bindex_t bindex;
28372+ unsigned int flags;
28373+};
28374+
28375+static void call_do_diropq(void *args)
28376+{
28377+ struct do_diropq_args *a = args;
28378+ *a->errp = do_diropq(a->dentry, a->bindex, a->flags);
28379+}
28380+
28381+struct dentry *au_diropq_sio(struct dentry *dentry, aufs_bindex_t bindex,
28382+ unsigned int flags)
28383+{
28384+ struct dentry *diropq, *h_dentry;
28385+
28386+ h_dentry = au_h_dptr(dentry, bindex);
28387+ if (!au_test_h_perm_sio(h_dentry->d_inode, MAY_EXEC | MAY_WRITE))
28388+ diropq = do_diropq(dentry, bindex, flags);
28389+ else {
28390+ int wkq_err;
28391+ struct do_diropq_args args = {
28392+ .errp = &diropq,
28393+ .dentry = dentry,
28394+ .bindex = bindex,
28395+ .flags = flags
28396+ };
28397+
28398+ wkq_err = au_wkq_wait(call_do_diropq, &args);
28399+ if (unlikely(wkq_err))
28400+ diropq = ERR_PTR(wkq_err);
28401+ }
28402+
28403+ return diropq;
28404+}
28405+
28406+/* ---------------------------------------------------------------------- */
28407+
28408+/*
28409+ * lookup whiteout dentry.
28410+ * @h_parent: lower parent dentry which must exist and be locked
28411+ * @base_name: name of dentry which will be whiteouted
28412+ * returns dentry for whiteout.
28413+ */
28414+struct dentry *au_wh_lkup(struct dentry *h_parent, struct qstr *base_name,
28415+ struct au_branch *br)
28416+{
28417+ int err;
28418+ struct qstr wh_name;
28419+ struct dentry *wh_dentry;
28420+
28421+ err = au_wh_name_alloc(&wh_name, base_name);
28422+ wh_dentry = ERR_PTR(err);
28423+ if (!err) {
b4510431 28424+ wh_dentry = vfsub_lkup_one(&wh_name, h_parent);
1facf9fc 28425+ kfree(wh_name.name);
28426+ }
28427+ return wh_dentry;
28428+}
28429+
28430+/*
28431+ * link/create a whiteout for @dentry on @bindex.
28432+ */
28433+struct dentry *au_wh_create(struct dentry *dentry, aufs_bindex_t bindex,
28434+ struct dentry *h_parent)
28435+{
28436+ struct dentry *wh_dentry;
28437+ struct super_block *sb;
28438+ int err;
28439+
28440+ sb = dentry->d_sb;
28441+ wh_dentry = au_wh_lkup(h_parent, &dentry->d_name, au_sbr(sb, bindex));
28442+ if (!IS_ERR(wh_dentry) && !wh_dentry->d_inode) {
28443+ err = link_or_create_wh(sb, bindex, wh_dentry);
28444+ if (!err)
28445+ au_set_dbwh(dentry, bindex);
28446+ else {
28447+ dput(wh_dentry);
28448+ wh_dentry = ERR_PTR(err);
28449+ }
28450+ }
28451+
28452+ return wh_dentry;
28453+}
28454+
28455+/* ---------------------------------------------------------------------- */
28456+
28457+/* Delete all whiteouts in this directory on branch bindex. */
28458+static int del_wh_children(struct dentry *h_dentry, struct au_nhash *whlist,
28459+ aufs_bindex_t bindex, struct au_branch *br)
28460+{
28461+ int err;
28462+ unsigned long ul, n;
28463+ struct qstr wh_name;
28464+ char *p;
28465+ struct hlist_head *head;
28466+ struct au_vdir_wh *tpos;
28467+ struct hlist_node *pos;
28468+ struct au_vdir_destr *str;
28469+
28470+ err = -ENOMEM;
537831f9 28471+ p = (void *)__get_free_page(GFP_NOFS);
1facf9fc 28472+ wh_name.name = p;
28473+ if (unlikely(!wh_name.name))
28474+ goto out;
28475+
28476+ err = 0;
28477+ memcpy(p, AUFS_WH_PFX, AUFS_WH_PFX_LEN);
28478+ p += AUFS_WH_PFX_LEN;
28479+ n = whlist->nh_num;
28480+ head = whlist->nh_head;
28481+ for (ul = 0; !err && ul < n; ul++, head++) {
28482+ hlist_for_each_entry(tpos, pos, head, wh_hash) {
28483+ if (tpos->wh_bindex != bindex)
28484+ continue;
28485+
28486+ str = &tpos->wh_str;
28487+ if (str->len + AUFS_WH_PFX_LEN <= PATH_MAX) {
28488+ memcpy(p, str->name, str->len);
28489+ wh_name.len = AUFS_WH_PFX_LEN + str->len;
28490+ err = unlink_wh_name(h_dentry, &wh_name, br);
28491+ if (!err)
28492+ continue;
28493+ break;
28494+ }
28495+ AuIOErr("whiteout name too long %.*s\n",
28496+ str->len, str->name);
28497+ err = -EIO;
28498+ break;
28499+ }
28500+ }
537831f9 28501+ free_page((unsigned long)wh_name.name);
1facf9fc 28502+
4f0767ce 28503+out:
1facf9fc 28504+ return err;
28505+}
28506+
28507+struct del_wh_children_args {
28508+ int *errp;
28509+ struct dentry *h_dentry;
1308ab2a 28510+ struct au_nhash *whlist;
1facf9fc 28511+ aufs_bindex_t bindex;
28512+ struct au_branch *br;
28513+};
28514+
28515+static void call_del_wh_children(void *args)
28516+{
28517+ struct del_wh_children_args *a = args;
1308ab2a 28518+ *a->errp = del_wh_children(a->h_dentry, a->whlist, a->bindex, a->br);
1facf9fc 28519+}
28520+
28521+/* ---------------------------------------------------------------------- */
28522+
28523+struct au_whtmp_rmdir *au_whtmp_rmdir_alloc(struct super_block *sb, gfp_t gfp)
28524+{
28525+ struct au_whtmp_rmdir *whtmp;
dece6358 28526+ int err;
1308ab2a 28527+ unsigned int rdhash;
dece6358
AM
28528+
28529+ SiMustAnyLock(sb);
1facf9fc 28530+
28531+ whtmp = kmalloc(sizeof(*whtmp), gfp);
dece6358
AM
28532+ if (unlikely(!whtmp)) {
28533+ whtmp = ERR_PTR(-ENOMEM);
1facf9fc 28534+ goto out;
dece6358 28535+ }
1facf9fc 28536+
28537+ whtmp->dir = NULL;
027c5e7a 28538+ whtmp->br = NULL;
1facf9fc 28539+ whtmp->wh_dentry = NULL;
1308ab2a 28540+ /* no estimation for dir size */
28541+ rdhash = au_sbi(sb)->si_rdhash;
28542+ if (!rdhash)
28543+ rdhash = AUFS_RDHASH_DEF;
28544+ err = au_nhash_alloc(&whtmp->whlist, rdhash, gfp);
28545+ if (unlikely(err)) {
28546+ kfree(whtmp);
28547+ whtmp = ERR_PTR(err);
28548+ }
dece6358 28549+
4f0767ce 28550+out:
dece6358 28551+ return whtmp;
1facf9fc 28552+}
28553+
28554+void au_whtmp_rmdir_free(struct au_whtmp_rmdir *whtmp)
28555+{
027c5e7a
AM
28556+ if (whtmp->br)
28557+ atomic_dec(&whtmp->br->br_count);
1facf9fc 28558+ dput(whtmp->wh_dentry);
28559+ iput(whtmp->dir);
dece6358 28560+ au_nhash_wh_free(&whtmp->whlist);
1facf9fc 28561+ kfree(whtmp);
28562+}
28563+
28564+/*
28565+ * rmdir the whiteouted temporary named dir @h_dentry.
28566+ * @whlist: whiteouted children.
28567+ */
28568+int au_whtmp_rmdir(struct inode *dir, aufs_bindex_t bindex,
28569+ struct dentry *wh_dentry, struct au_nhash *whlist)
28570+{
28571+ int err;
28572+ struct path h_tmp;
28573+ struct inode *wh_inode, *h_dir;
28574+ struct au_branch *br;
28575+
28576+ h_dir = wh_dentry->d_parent->d_inode; /* dir inode is locked */
28577+ IMustLock(h_dir);
28578+
28579+ br = au_sbr(dir->i_sb, bindex);
28580+ wh_inode = wh_dentry->d_inode;
28581+ mutex_lock_nested(&wh_inode->i_mutex, AuLsc_I_CHILD);
28582+
28583+ /*
28584+ * someone else might change some whiteouts while we were sleeping.
28585+ * it means this whlist may have an obsoleted entry.
28586+ */
28587+ if (!au_test_h_perm_sio(wh_inode, MAY_EXEC | MAY_WRITE))
28588+ err = del_wh_children(wh_dentry, whlist, bindex, br);
28589+ else {
28590+ int wkq_err;
28591+ struct del_wh_children_args args = {
28592+ .errp = &err,
28593+ .h_dentry = wh_dentry,
1308ab2a 28594+ .whlist = whlist,
1facf9fc 28595+ .bindex = bindex,
28596+ .br = br
28597+ };
28598+
28599+ wkq_err = au_wkq_wait(call_del_wh_children, &args);
28600+ if (unlikely(wkq_err))
28601+ err = wkq_err;
28602+ }
28603+ mutex_unlock(&wh_inode->i_mutex);
28604+
28605+ if (!err) {
28606+ h_tmp.dentry = wh_dentry;
28607+ h_tmp.mnt = br->br_mnt;
28608+ err = vfsub_rmdir(h_dir, &h_tmp);
1facf9fc 28609+ }
28610+
28611+ if (!err) {
28612+ if (au_ibstart(dir) == bindex) {
7f207e10 28613+ /* todo: dir->i_mutex is necessary */
1facf9fc 28614+ au_cpup_attr_timesizes(dir);
7f207e10 28615+ vfsub_drop_nlink(dir);
1facf9fc 28616+ }
28617+ return 0; /* success */
28618+ }
28619+
0c3ec466
AM
28620+ pr_warn("failed removing %.*s(%d), ignored\n",
28621+ AuDLNPair(wh_dentry), err);
1facf9fc 28622+ return err;
28623+}
28624+
28625+static void call_rmdir_whtmp(void *args)
28626+{
28627+ int err;
e49829fe 28628+ aufs_bindex_t bindex;
1facf9fc 28629+ struct au_whtmp_rmdir *a = args;
28630+ struct super_block *sb;
28631+ struct dentry *h_parent;
28632+ struct inode *h_dir;
1facf9fc 28633+ struct au_hinode *hdir;
28634+
28635+ /* rmdir by nfsd may cause deadlock with this i_mutex */
28636+ /* mutex_lock(&a->dir->i_mutex); */
e49829fe 28637+ err = -EROFS;
1facf9fc 28638+ sb = a->dir->i_sb;
e49829fe
JR
28639+ si_read_lock(sb, !AuLock_FLUSH);
28640+ if (!au_br_writable(a->br->br_perm))
28641+ goto out;
28642+ bindex = au_br_index(sb, a->br->br_id);
28643+ if (unlikely(bindex < 0))
1facf9fc 28644+ goto out;
28645+
28646+ err = -EIO;
1facf9fc 28647+ ii_write_lock_parent(a->dir);
28648+ h_parent = dget_parent(a->wh_dentry);
28649+ h_dir = h_parent->d_inode;
e49829fe 28650+ hdir = au_hi(a->dir, bindex);
4a4d8108 28651+ au_hn_imtx_lock_nested(hdir, AuLsc_I_PARENT);
e49829fe
JR
28652+ err = au_h_verify(a->wh_dentry, au_opt_udba(sb), h_dir, h_parent,
28653+ a->br);
1facf9fc 28654+ if (!err) {
b4510431 28655+ err = vfsub_mnt_want_write(a->br->br_mnt);
1facf9fc 28656+ if (!err) {
e49829fe 28657+ err = au_whtmp_rmdir(a->dir, bindex, a->wh_dentry,
dece6358 28658+ &a->whlist);
b4510431 28659+ vfsub_mnt_drop_write(a->br->br_mnt);
1facf9fc 28660+ }
28661+ }
4a4d8108 28662+ au_hn_imtx_unlock(hdir);
1facf9fc 28663+ dput(h_parent);
28664+ ii_write_unlock(a->dir);
28665+
4f0767ce 28666+out:
1facf9fc 28667+ /* mutex_unlock(&a->dir->i_mutex); */
1facf9fc 28668+ au_whtmp_rmdir_free(a);
027c5e7a
AM
28669+ si_read_unlock(sb);
28670+ au_nwt_done(&au_sbi(sb)->si_nowait);
1facf9fc 28671+ if (unlikely(err))
28672+ AuIOErr("err %d\n", err);
28673+}
28674+
28675+void au_whtmp_kick_rmdir(struct inode *dir, aufs_bindex_t bindex,
28676+ struct dentry *wh_dentry, struct au_whtmp_rmdir *args)
28677+{
28678+ int wkq_err;
e49829fe 28679+ struct super_block *sb;
1facf9fc 28680+
28681+ IMustLock(dir);
28682+
28683+ /* all post-process will be done in do_rmdir_whtmp(). */
e49829fe 28684+ sb = dir->i_sb;
1facf9fc 28685+ args->dir = au_igrab(dir);
e49829fe
JR
28686+ args->br = au_sbr(sb, bindex);
28687+ atomic_inc(&args->br->br_count);
1facf9fc 28688+ args->wh_dentry = dget(wh_dentry);
53392da6 28689+ wkq_err = au_wkq_nowait(call_rmdir_whtmp, args, sb, /*flags*/0);
1facf9fc 28690+ if (unlikely(wkq_err)) {
0c3ec466
AM
28691+ pr_warn("rmdir error %.*s (%d), ignored\n",
28692+ AuDLNPair(wh_dentry), wkq_err);
1facf9fc 28693+ au_whtmp_rmdir_free(args);
28694+ }
28695+}
7f207e10
AM
28696diff -urN /usr/share/empty/fs/aufs/whout.h linux/fs/aufs/whout.h
28697--- /usr/share/empty/fs/aufs/whout.h 1970-01-01 01:00:00.000000000 +0100
537831f9 28698+++ linux/fs/aufs/whout.h 2012-12-13 20:41:10.434793588 +0100
f6c5ef8b 28699@@ -0,0 +1,88 @@
1facf9fc 28700+/*
f6c5ef8b 28701+ * Copyright (C) 2005-2012 Junjiro R. Okajima
1facf9fc 28702+ *
28703+ * This program, aufs is free software; you can redistribute it and/or modify
28704+ * it under the terms of the GNU General Public License as published by
28705+ * the Free Software Foundation; either version 2 of the License, or
28706+ * (at your option) any later version.
dece6358
AM
28707+ *
28708+ * This program is distributed in the hope that it will be useful,
28709+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
28710+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
28711+ * GNU General Public License for more details.
28712+ *
28713+ * You should have received a copy of the GNU General Public License
28714+ * along with this program; if not, write to the Free Software
28715+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 28716+ */
28717+
28718+/*
28719+ * whiteout for logical deletion and opaque directory
28720+ */
28721+
28722+#ifndef __AUFS_WHOUT_H__
28723+#define __AUFS_WHOUT_H__
28724+
28725+#ifdef __KERNEL__
28726+
1facf9fc 28727+#include "dir.h"
28728+
28729+/* whout.c */
28730+int au_wh_name_alloc(struct qstr *wh, const struct qstr *name);
28731+struct au_branch;
28732+int au_wh_test(struct dentry *h_parent, struct qstr *wh_name,
28733+ struct au_branch *br, int try_sio);
28734+int au_diropq_test(struct dentry *h_dentry, struct au_branch *br);
28735+struct dentry *au_whtmp_lkup(struct dentry *h_parent, struct au_branch *br,
28736+ struct qstr *prefix);
28737+int au_whtmp_ren(struct dentry *h_dentry, struct au_branch *br);
28738+int au_wh_unlink_dentry(struct inode *h_dir, struct path *h_path,
28739+ struct dentry *dentry);
28740+int au_wh_init(struct dentry *h_parent, struct au_branch *br,
28741+ struct super_block *sb);
28742+
28743+/* diropq flags */
28744+#define AuDiropq_CREATE 1
28745+#define au_ftest_diropq(flags, name) ((flags) & AuDiropq_##name)
7f207e10
AM
28746+#define au_fset_diropq(flags, name) \
28747+ do { (flags) |= AuDiropq_##name; } while (0)
28748+#define au_fclr_diropq(flags, name) \
28749+ do { (flags) &= ~AuDiropq_##name; } while (0)
1facf9fc 28750+
28751+struct dentry *au_diropq_sio(struct dentry *dentry, aufs_bindex_t bindex,
28752+ unsigned int flags);
28753+struct dentry *au_wh_lkup(struct dentry *h_parent, struct qstr *base_name,
28754+ struct au_branch *br);
28755+struct dentry *au_wh_create(struct dentry *dentry, aufs_bindex_t bindex,
28756+ struct dentry *h_parent);
28757+
28758+/* real rmdir for the whiteout-ed dir */
28759+struct au_whtmp_rmdir {
28760+ struct inode *dir;
e49829fe 28761+ struct au_branch *br;
1facf9fc 28762+ struct dentry *wh_dentry;
dece6358 28763+ struct au_nhash whlist;
1facf9fc 28764+};
28765+
28766+struct au_whtmp_rmdir *au_whtmp_rmdir_alloc(struct super_block *sb, gfp_t gfp);
28767+void au_whtmp_rmdir_free(struct au_whtmp_rmdir *whtmp);
28768+int au_whtmp_rmdir(struct inode *dir, aufs_bindex_t bindex,
28769+ struct dentry *wh_dentry, struct au_nhash *whlist);
28770+void au_whtmp_kick_rmdir(struct inode *dir, aufs_bindex_t bindex,
28771+ struct dentry *wh_dentry, struct au_whtmp_rmdir *args);
28772+
28773+/* ---------------------------------------------------------------------- */
28774+
28775+static inline struct dentry *au_diropq_create(struct dentry *dentry,
28776+ aufs_bindex_t bindex)
28777+{
28778+ return au_diropq_sio(dentry, bindex, AuDiropq_CREATE);
28779+}
28780+
28781+static inline int au_diropq_remove(struct dentry *dentry, aufs_bindex_t bindex)
28782+{
28783+ return PTR_ERR(au_diropq_sio(dentry, bindex, !AuDiropq_CREATE));
28784+}
28785+
28786+#endif /* __KERNEL__ */
28787+#endif /* __AUFS_WHOUT_H__ */
7f207e10
AM
28788diff -urN /usr/share/empty/fs/aufs/wkq.c linux/fs/aufs/wkq.c
28789--- /usr/share/empty/fs/aufs/wkq.c 1970-01-01 01:00:00.000000000 +0100
537831f9 28790+++ linux/fs/aufs/wkq.c 2012-12-13 20:41:10.434793588 +0100
9dbd164d 28791@@ -0,0 +1,214 @@
1facf9fc 28792+/*
f6c5ef8b 28793+ * Copyright (C) 2005-2012 Junjiro R. Okajima
1facf9fc 28794+ *
28795+ * This program, aufs is free software; you can redistribute it and/or modify
28796+ * it under the terms of the GNU General Public License as published by
28797+ * the Free Software Foundation; either version 2 of the License, or
28798+ * (at your option) any later version.
dece6358
AM
28799+ *
28800+ * This program is distributed in the hope that it will be useful,
28801+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
28802+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
28803+ * GNU General Public License for more details.
28804+ *
28805+ * You should have received a copy of the GNU General Public License
28806+ * along with this program; if not, write to the Free Software
28807+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 28808+ */
28809+
28810+/*
28811+ * workqueue for asynchronous/super-io operations
28812+ * todo: try new dredential scheme
28813+ */
28814+
dece6358 28815+#include <linux/module.h>
1facf9fc 28816+#include "aufs.h"
28817+
9dbd164d 28818+/* internal workqueue named AUFS_WKQ_NAME */
b752ccd1 28819+
9dbd164d 28820+static struct workqueue_struct *au_wkq;
1facf9fc 28821+
28822+struct au_wkinfo {
28823+ struct work_struct wk;
7f207e10 28824+ struct kobject *kobj;
1facf9fc 28825+
28826+ unsigned int flags; /* see wkq.h */
28827+
28828+ au_wkq_func_t func;
28829+ void *args;
28830+
1facf9fc 28831+ struct completion *comp;
28832+};
28833+
28834+/* ---------------------------------------------------------------------- */
28835+
1facf9fc 28836+static void wkq_func(struct work_struct *wk)
28837+{
28838+ struct au_wkinfo *wkinfo = container_of(wk, struct au_wkinfo, wk);
28839+
2dfbb274 28840+ AuDebugOn(!uid_eq(current_fsuid(), GLOBAL_ROOT_UID));
7f207e10
AM
28841+ AuDebugOn(rlimit(RLIMIT_FSIZE) != RLIM_INFINITY);
28842+
1facf9fc 28843+ wkinfo->func(wkinfo->args);
1facf9fc 28844+ if (au_ftest_wkq(wkinfo->flags, WAIT))
28845+ complete(wkinfo->comp);
28846+ else {
7f207e10 28847+ kobject_put(wkinfo->kobj);
9dbd164d 28848+ module_put(THIS_MODULE); /* todo: ?? */
1facf9fc 28849+ kfree(wkinfo);
28850+ }
28851+}
28852+
28853+/*
28854+ * Since struct completion is large, try allocating it dynamically.
28855+ */
28856+#if defined(CONFIG_4KSTACKS) || defined(AuTest4KSTACKS)
28857+#define AuWkqCompDeclare(name) struct completion *comp = NULL
28858+
28859+static int au_wkq_comp_alloc(struct au_wkinfo *wkinfo, struct completion **comp)
28860+{
28861+ *comp = kmalloc(sizeof(**comp), GFP_NOFS);
28862+ if (*comp) {
28863+ init_completion(*comp);
28864+ wkinfo->comp = *comp;
28865+ return 0;
28866+ }
28867+ return -ENOMEM;
28868+}
28869+
28870+static void au_wkq_comp_free(struct completion *comp)
28871+{
28872+ kfree(comp);
28873+}
28874+
28875+#else
28876+
28877+/* no braces */
28878+#define AuWkqCompDeclare(name) \
28879+ DECLARE_COMPLETION_ONSTACK(_ ## name); \
28880+ struct completion *comp = &_ ## name
28881+
28882+static int au_wkq_comp_alloc(struct au_wkinfo *wkinfo, struct completion **comp)
28883+{
28884+ wkinfo->comp = *comp;
28885+ return 0;
28886+}
28887+
28888+static void au_wkq_comp_free(struct completion *comp __maybe_unused)
28889+{
28890+ /* empty */
28891+}
28892+#endif /* 4KSTACKS */
28893+
53392da6 28894+static void au_wkq_run(struct au_wkinfo *wkinfo)
1facf9fc 28895+{
53392da6
AM
28896+ if (au_ftest_wkq(wkinfo->flags, NEST)) {
28897+ if (au_wkq_test()) {
28898+ AuWarn1("wkq from wkq, due to a dead dir by UDBA?\n");
28899+ AuDebugOn(au_ftest_wkq(wkinfo->flags, WAIT));
28900+ }
28901+ } else
28902+ au_dbg_verify_kthread();
28903+
28904+ if (au_ftest_wkq(wkinfo->flags, WAIT)) {
a1f66529 28905+ INIT_WORK_ONSTACK(&wkinfo->wk, wkq_func);
9dbd164d 28906+ queue_work(au_wkq, &wkinfo->wk);
4a4d8108
AM
28907+ } else {
28908+ INIT_WORK(&wkinfo->wk, wkq_func);
28909+ schedule_work(&wkinfo->wk);
28910+ }
1facf9fc 28911+}
28912+
7f207e10
AM
28913+/*
28914+ * Be careful. It is easy to make deadlock happen.
28915+ * processA: lock, wkq and wait
28916+ * processB: wkq and wait, lock in wkq
28917+ * --> deadlock
28918+ */
b752ccd1 28919+int au_wkq_do_wait(unsigned int flags, au_wkq_func_t func, void *args)
1facf9fc 28920+{
28921+ int err;
28922+ AuWkqCompDeclare(comp);
28923+ struct au_wkinfo wkinfo = {
b752ccd1 28924+ .flags = flags,
1facf9fc 28925+ .func = func,
28926+ .args = args
28927+ };
28928+
28929+ err = au_wkq_comp_alloc(&wkinfo, &comp);
28930+ if (!err) {
53392da6 28931+ au_wkq_run(&wkinfo);
1facf9fc 28932+ /* no timeout, no interrupt */
28933+ wait_for_completion(wkinfo.comp);
28934+ au_wkq_comp_free(comp);
4a4d8108 28935+ destroy_work_on_stack(&wkinfo.wk);
1facf9fc 28936+ }
28937+
28938+ return err;
28939+
28940+}
28941+
027c5e7a
AM
28942+/*
28943+ * Note: dget/dput() in func for aufs dentries are not supported. It will be a
28944+ * problem in a concurrent umounting.
28945+ */
53392da6
AM
28946+int au_wkq_nowait(au_wkq_func_t func, void *args, struct super_block *sb,
28947+ unsigned int flags)
1facf9fc 28948+{
28949+ int err;
28950+ struct au_wkinfo *wkinfo;
28951+
28952+ atomic_inc(&au_sbi(sb)->si_nowait.nw_len);
28953+
28954+ /*
28955+ * wkq_func() must free this wkinfo.
28956+ * it highly depends upon the implementation of workqueue.
28957+ */
28958+ err = 0;
28959+ wkinfo = kmalloc(sizeof(*wkinfo), GFP_NOFS);
28960+ if (wkinfo) {
7f207e10 28961+ wkinfo->kobj = &au_sbi(sb)->si_kobj;
53392da6 28962+ wkinfo->flags = flags & ~AuWkq_WAIT;
1facf9fc 28963+ wkinfo->func = func;
28964+ wkinfo->args = args;
28965+ wkinfo->comp = NULL;
7f207e10 28966+ kobject_get(wkinfo->kobj);
9dbd164d 28967+ __module_get(THIS_MODULE); /* todo: ?? */
1facf9fc 28968+
53392da6 28969+ au_wkq_run(wkinfo);
1facf9fc 28970+ } else {
28971+ err = -ENOMEM;
e49829fe 28972+ au_nwt_done(&au_sbi(sb)->si_nowait);
1facf9fc 28973+ }
28974+
28975+ return err;
28976+}
28977+
28978+/* ---------------------------------------------------------------------- */
28979+
28980+void au_nwt_init(struct au_nowait_tasks *nwt)
28981+{
28982+ atomic_set(&nwt->nw_len, 0);
4a4d8108 28983+ /* smp_mb(); */ /* atomic_set */
1facf9fc 28984+ init_waitqueue_head(&nwt->nw_wq);
28985+}
28986+
28987+void au_wkq_fin(void)
28988+{
9dbd164d 28989+ destroy_workqueue(au_wkq);
1facf9fc 28990+}
28991+
28992+int __init au_wkq_init(void)
28993+{
9dbd164d 28994+ int err;
b752ccd1
AM
28995+
28996+ err = 0;
9dbd164d
AM
28997+ BUILD_BUG_ON(!WQ_RESCUER);
28998+ au_wkq = alloc_workqueue(AUFS_WKQ_NAME, !WQ_RESCUER, WQ_DFL_ACTIVE);
28999+ if (IS_ERR(au_wkq))
29000+ err = PTR_ERR(au_wkq);
29001+ else if (!au_wkq)
29002+ err = -ENOMEM;
b752ccd1
AM
29003+
29004+ return err;
1facf9fc 29005+}
7f207e10
AM
29006diff -urN /usr/share/empty/fs/aufs/wkq.h linux/fs/aufs/wkq.h
29007--- /usr/share/empty/fs/aufs/wkq.h 1970-01-01 01:00:00.000000000 +0100
537831f9 29008+++ linux/fs/aufs/wkq.h 2012-12-13 20:41:10.434793588 +0100
f6c5ef8b 29009@@ -0,0 +1,92 @@
1facf9fc 29010+/*
f6c5ef8b 29011+ * Copyright (C) 2005-2012 Junjiro R. Okajima
1facf9fc 29012+ *
29013+ * This program, aufs is free software; you can redistribute it and/or modify
29014+ * it under the terms of the GNU General Public License as published by
29015+ * the Free Software Foundation; either version 2 of the License, or
29016+ * (at your option) any later version.
dece6358
AM
29017+ *
29018+ * This program is distributed in the hope that it will be useful,
29019+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
29020+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
29021+ * GNU General Public License for more details.
29022+ *
29023+ * You should have received a copy of the GNU General Public License
29024+ * along with this program; if not, write to the Free Software
29025+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 29026+ */
29027+
29028+/*
29029+ * workqueue for asynchronous/super-io operations
29030+ * todo: try new credentials management scheme
29031+ */
29032+
29033+#ifndef __AUFS_WKQ_H__
29034+#define __AUFS_WKQ_H__
29035+
29036+#ifdef __KERNEL__
29037+
dece6358
AM
29038+struct super_block;
29039+
1facf9fc 29040+/* ---------------------------------------------------------------------- */
29041+
29042+/*
29043+ * in the next operation, wait for the 'nowait' tasks in system-wide workqueue
29044+ */
29045+struct au_nowait_tasks {
29046+ atomic_t nw_len;
29047+ wait_queue_head_t nw_wq;
29048+};
29049+
29050+/* ---------------------------------------------------------------------- */
29051+
29052+typedef void (*au_wkq_func_t)(void *args);
29053+
29054+/* wkq flags */
29055+#define AuWkq_WAIT 1
9dbd164d 29056+#define AuWkq_NEST (1 << 1)
1facf9fc 29057+#define au_ftest_wkq(flags, name) ((flags) & AuWkq_##name)
7f207e10
AM
29058+#define au_fset_wkq(flags, name) \
29059+ do { (flags) |= AuWkq_##name; } while (0)
29060+#define au_fclr_wkq(flags, name) \
29061+ do { (flags) &= ~AuWkq_##name; } while (0)
1facf9fc 29062+
9dbd164d
AM
29063+#ifndef CONFIG_AUFS_HNOTIFY
29064+#undef AuWkq_NEST
29065+#define AuWkq_NEST 0
29066+#endif
29067+
1facf9fc 29068+/* wkq.c */
b752ccd1 29069+int au_wkq_do_wait(unsigned int flags, au_wkq_func_t func, void *args);
53392da6
AM
29070+int au_wkq_nowait(au_wkq_func_t func, void *args, struct super_block *sb,
29071+ unsigned int flags);
1facf9fc 29072+void au_nwt_init(struct au_nowait_tasks *nwt);
29073+int __init au_wkq_init(void);
29074+void au_wkq_fin(void);
29075+
29076+/* ---------------------------------------------------------------------- */
29077+
53392da6
AM
29078+static inline int au_wkq_test(void)
29079+{
29080+ return current->flags & PF_WQ_WORKER;
29081+}
29082+
b752ccd1 29083+static inline int au_wkq_wait(au_wkq_func_t func, void *args)
1facf9fc 29084+{
b752ccd1 29085+ return au_wkq_do_wait(AuWkq_WAIT, func, args);
1facf9fc 29086+}
29087+
29088+static inline void au_nwt_done(struct au_nowait_tasks *nwt)
29089+{
e49829fe 29090+ if (atomic_dec_and_test(&nwt->nw_len))
1facf9fc 29091+ wake_up_all(&nwt->nw_wq);
29092+}
29093+
29094+static inline int au_nwt_flush(struct au_nowait_tasks *nwt)
29095+{
29096+ wait_event(nwt->nw_wq, !atomic_read(&nwt->nw_len));
29097+ return 0;
29098+}
29099+
29100+#endif /* __KERNEL__ */
29101+#endif /* __AUFS_WKQ_H__ */
7f207e10
AM
29102diff -urN /usr/share/empty/fs/aufs/xino.c linux/fs/aufs/xino.c
29103--- /usr/share/empty/fs/aufs/xino.c 1970-01-01 01:00:00.000000000 +0100
537831f9 29104+++ linux/fs/aufs/xino.c 2012-12-13 20:41:10.434793588 +0100
f6c5ef8b 29105@@ -0,0 +1,1264 @@
1facf9fc 29106+/*
f6c5ef8b 29107+ * Copyright (C) 2005-2012 Junjiro R. Okajima
1facf9fc 29108+ *
29109+ * This program, aufs is free software; you can redistribute it and/or modify
29110+ * it under the terms of the GNU General Public License as published by
29111+ * the Free Software Foundation; either version 2 of the License, or
29112+ * (at your option) any later version.
dece6358
AM
29113+ *
29114+ * This program is distributed in the hope that it will be useful,
29115+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
29116+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
29117+ * GNU General Public License for more details.
29118+ *
29119+ * You should have received a copy of the GNU General Public License
29120+ * along with this program; if not, write to the Free Software
29121+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 29122+ */
29123+
29124+/*
29125+ * external inode number translation table and bitmap
29126+ */
29127+
29128+#include <linux/seq_file.h>
1facf9fc 29129+#include "aufs.h"
29130+
9dbd164d 29131+/* todo: unnecessary to support mmap_sem since kernel-space? */
b752ccd1 29132+ssize_t xino_fread(au_readf_t func, struct file *file, void *kbuf, size_t size,
1facf9fc 29133+ loff_t *pos)
29134+{
29135+ ssize_t err;
29136+ mm_segment_t oldfs;
b752ccd1
AM
29137+ union {
29138+ void *k;
29139+ char __user *u;
29140+ } buf;
1facf9fc 29141+
b752ccd1 29142+ buf.k = kbuf;
1facf9fc 29143+ oldfs = get_fs();
29144+ set_fs(KERNEL_DS);
29145+ do {
29146+ /* todo: signal_pending? */
b752ccd1 29147+ err = func(file, buf.u, size, pos);
1facf9fc 29148+ } while (err == -EAGAIN || err == -EINTR);
29149+ set_fs(oldfs);
29150+
29151+#if 0 /* reserved for future use */
29152+ if (err > 0)
29153+ fsnotify_access(file->f_dentry);
29154+#endif
29155+
29156+ return err;
29157+}
29158+
29159+/* ---------------------------------------------------------------------- */
29160+
b752ccd1 29161+static ssize_t do_xino_fwrite(au_writef_t func, struct file *file, void *kbuf,
1facf9fc 29162+ size_t size, loff_t *pos)
29163+{
29164+ ssize_t err;
29165+ mm_segment_t oldfs;
b752ccd1
AM
29166+ union {
29167+ void *k;
29168+ const char __user *u;
29169+ } buf;
1facf9fc 29170+
b752ccd1 29171+ buf.k = kbuf;
1facf9fc 29172+ oldfs = get_fs();
29173+ set_fs(KERNEL_DS);
1facf9fc 29174+ do {
29175+ /* todo: signal_pending? */
b752ccd1 29176+ err = func(file, buf.u, size, pos);
1facf9fc 29177+ } while (err == -EAGAIN || err == -EINTR);
1facf9fc 29178+ set_fs(oldfs);
29179+
29180+#if 0 /* reserved for future use */
29181+ if (err > 0)
29182+ fsnotify_modify(file->f_dentry);
29183+#endif
29184+
29185+ return err;
29186+}
29187+
29188+struct do_xino_fwrite_args {
29189+ ssize_t *errp;
29190+ au_writef_t func;
29191+ struct file *file;
29192+ void *buf;
29193+ size_t size;
29194+ loff_t *pos;
29195+};
29196+
29197+static void call_do_xino_fwrite(void *args)
29198+{
29199+ struct do_xino_fwrite_args *a = args;
29200+ *a->errp = do_xino_fwrite(a->func, a->file, a->buf, a->size, a->pos);
29201+}
29202+
29203+ssize_t xino_fwrite(au_writef_t func, struct file *file, void *buf, size_t size,
29204+ loff_t *pos)
29205+{
29206+ ssize_t err;
29207+
29208+ /* todo: signal block and no wkq? */
b752ccd1
AM
29209+ if (rlimit(RLIMIT_FSIZE) == RLIM_INFINITY) {
29210+ lockdep_off();
29211+ err = do_xino_fwrite(func, file, buf, size, pos);
29212+ lockdep_on();
29213+ } else {
29214+ /*
29215+ * it breaks RLIMIT_FSIZE and normal user's limit,
29216+ * users should care about quota and real 'filesystem full.'
29217+ */
1facf9fc 29218+ int wkq_err;
29219+ struct do_xino_fwrite_args args = {
29220+ .errp = &err,
29221+ .func = func,
29222+ .file = file,
29223+ .buf = buf,
29224+ .size = size,
29225+ .pos = pos
29226+ };
29227+
29228+ wkq_err = au_wkq_wait(call_do_xino_fwrite, &args);
29229+ if (unlikely(wkq_err))
29230+ err = wkq_err;
b752ccd1 29231+ }
1facf9fc 29232+
29233+ return err;
29234+}
29235+
29236+/* ---------------------------------------------------------------------- */
29237+
29238+/*
29239+ * create a new xinofile at the same place/path as @base_file.
29240+ */
29241+struct file *au_xino_create2(struct file *base_file, struct file *copy_src)
29242+{
29243+ struct file *file;
4a4d8108 29244+ struct dentry *base, *parent;
1facf9fc 29245+ struct inode *dir;
29246+ struct qstr *name;
1308ab2a 29247+ struct path path;
4a4d8108 29248+ int err;
1facf9fc 29249+
29250+ base = base_file->f_dentry;
29251+ parent = base->d_parent; /* dir inode is locked */
29252+ dir = parent->d_inode;
29253+ IMustLock(dir);
29254+
29255+ file = ERR_PTR(-EINVAL);
29256+ name = &base->d_name;
4a4d8108
AM
29257+ path.dentry = vfsub_lookup_one_len(name->name, parent, name->len);
29258+ if (IS_ERR(path.dentry)) {
29259+ file = (void *)path.dentry;
29260+ pr_err("%.*s lookup err %ld\n",
29261+ AuLNPair(name), PTR_ERR(path.dentry));
1facf9fc 29262+ goto out;
29263+ }
29264+
29265+ /* no need to mnt_want_write() since we call dentry_open() later */
4a4d8108 29266+ err = vfs_create(dir, path.dentry, S_IRUGO | S_IWUGO, NULL);
1facf9fc 29267+ if (unlikely(err)) {
29268+ file = ERR_PTR(err);
4a4d8108 29269+ pr_err("%.*s create err %d\n", AuLNPair(name), err);
1facf9fc 29270+ goto out_dput;
29271+ }
29272+
1308ab2a 29273+ path.mnt = base_file->f_vfsmnt;
4a4d8108 29274+ file = vfsub_dentry_open(&path,
7f207e10 29275+ O_RDWR | O_CREAT | O_EXCL | O_LARGEFILE
2cbb1c4b 29276+ /* | __FMODE_NONOTIFY */);
1facf9fc 29277+ if (IS_ERR(file)) {
4a4d8108 29278+ pr_err("%.*s open err %ld\n", AuLNPair(name), PTR_ERR(file));
1facf9fc 29279+ goto out_dput;
29280+ }
29281+
29282+ err = vfsub_unlink(dir, &file->f_path, /*force*/0);
29283+ if (unlikely(err)) {
4a4d8108 29284+ pr_err("%.*s unlink err %d\n", AuLNPair(name), err);
1facf9fc 29285+ goto out_fput;
29286+ }
29287+
29288+ if (copy_src) {
29289+ /* no one can touch copy_src xino */
29290+ err = au_copy_file(file, copy_src,
29291+ i_size_read(copy_src->f_dentry->d_inode));
29292+ if (unlikely(err)) {
4a4d8108 29293+ pr_err("%.*s copy err %d\n", AuLNPair(name), err);
1facf9fc 29294+ goto out_fput;
29295+ }
29296+ }
29297+ goto out_dput; /* success */
29298+
4f0767ce 29299+out_fput:
1facf9fc 29300+ fput(file);
29301+ file = ERR_PTR(err);
4f0767ce 29302+out_dput:
4a4d8108 29303+ dput(path.dentry);
4f0767ce 29304+out:
1facf9fc 29305+ return file;
29306+}
29307+
29308+struct au_xino_lock_dir {
29309+ struct au_hinode *hdir;
29310+ struct dentry *parent;
29311+ struct mutex *mtx;
29312+};
29313+
29314+static void au_xino_lock_dir(struct super_block *sb, struct file *xino,
29315+ struct au_xino_lock_dir *ldir)
29316+{
29317+ aufs_bindex_t brid, bindex;
29318+
29319+ ldir->hdir = NULL;
29320+ bindex = -1;
29321+ brid = au_xino_brid(sb);
29322+ if (brid >= 0)
29323+ bindex = au_br_index(sb, brid);
29324+ if (bindex >= 0) {
29325+ ldir->hdir = au_hi(sb->s_root->d_inode, bindex);
4a4d8108 29326+ au_hn_imtx_lock_nested(ldir->hdir, AuLsc_I_PARENT);
1facf9fc 29327+ } else {
29328+ ldir->parent = dget_parent(xino->f_dentry);
29329+ ldir->mtx = &ldir->parent->d_inode->i_mutex;
29330+ mutex_lock_nested(ldir->mtx, AuLsc_I_PARENT);
29331+ }
29332+}
29333+
29334+static void au_xino_unlock_dir(struct au_xino_lock_dir *ldir)
29335+{
29336+ if (ldir->hdir)
4a4d8108 29337+ au_hn_imtx_unlock(ldir->hdir);
1facf9fc 29338+ else {
29339+ mutex_unlock(ldir->mtx);
29340+ dput(ldir->parent);
29341+ }
29342+}
29343+
29344+/* ---------------------------------------------------------------------- */
29345+
29346+/* trucate xino files asynchronously */
29347+
29348+int au_xino_trunc(struct super_block *sb, aufs_bindex_t bindex)
29349+{
29350+ int err;
29351+ aufs_bindex_t bi, bend;
29352+ struct au_branch *br;
29353+ struct file *new_xino, *file;
29354+ struct super_block *h_sb;
29355+ struct au_xino_lock_dir ldir;
29356+
29357+ err = -EINVAL;
29358+ bend = au_sbend(sb);
29359+ if (unlikely(bindex < 0 || bend < bindex))
29360+ goto out;
29361+ br = au_sbr(sb, bindex);
29362+ file = br->br_xino.xi_file;
29363+ if (!file)
29364+ goto out;
29365+
29366+ au_xino_lock_dir(sb, file, &ldir);
29367+ /* mnt_want_write() is unnecessary here */
29368+ new_xino = au_xino_create2(file, file);
29369+ au_xino_unlock_dir(&ldir);
29370+ err = PTR_ERR(new_xino);
29371+ if (IS_ERR(new_xino))
29372+ goto out;
29373+ err = 0;
29374+ fput(file);
29375+ br->br_xino.xi_file = new_xino;
29376+
29377+ h_sb = br->br_mnt->mnt_sb;
29378+ for (bi = 0; bi <= bend; bi++) {
29379+ if (unlikely(bi == bindex))
29380+ continue;
29381+ br = au_sbr(sb, bi);
29382+ if (br->br_mnt->mnt_sb != h_sb)
29383+ continue;
29384+
29385+ fput(br->br_xino.xi_file);
29386+ br->br_xino.xi_file = new_xino;
29387+ get_file(new_xino);
29388+ }
29389+
4f0767ce 29390+out:
1facf9fc 29391+ return err;
29392+}
29393+
29394+struct xino_do_trunc_args {
29395+ struct super_block *sb;
29396+ struct au_branch *br;
29397+};
29398+
29399+static void xino_do_trunc(void *_args)
29400+{
29401+ struct xino_do_trunc_args *args = _args;
29402+ struct super_block *sb;
29403+ struct au_branch *br;
29404+ struct inode *dir;
29405+ int err;
29406+ aufs_bindex_t bindex;
29407+
29408+ err = 0;
29409+ sb = args->sb;
29410+ dir = sb->s_root->d_inode;
29411+ br = args->br;
29412+
29413+ si_noflush_write_lock(sb);
29414+ ii_read_lock_parent(dir);
29415+ bindex = au_br_index(sb, br->br_id);
29416+ err = au_xino_trunc(sb, bindex);
dece6358
AM
29417+ if (!err
29418+ && br->br_xino.xi_file->f_dentry->d_inode->i_blocks
1facf9fc 29419+ >= br->br_xino_upper)
29420+ br->br_xino_upper += AUFS_XINO_TRUNC_STEP;
29421+
1facf9fc 29422+ ii_read_unlock(dir);
29423+ if (unlikely(err))
0c3ec466 29424+ pr_warn("err b%d, (%d)\n", bindex, err);
1facf9fc 29425+ atomic_dec(&br->br_xino_running);
29426+ atomic_dec(&br->br_count);
1facf9fc 29427+ si_write_unlock(sb);
027c5e7a 29428+ au_nwt_done(&au_sbi(sb)->si_nowait);
1facf9fc 29429+ kfree(args);
29430+}
29431+
29432+static void xino_try_trunc(struct super_block *sb, struct au_branch *br)
29433+{
29434+ struct xino_do_trunc_args *args;
29435+ int wkq_err;
29436+
29437+ if (br->br_xino.xi_file->f_dentry->d_inode->i_blocks
29438+ < br->br_xino_upper)
29439+ return;
29440+
29441+ if (atomic_inc_return(&br->br_xino_running) > 1)
29442+ goto out;
29443+
29444+ /* lock and kfree() will be called in trunc_xino() */
29445+ args = kmalloc(sizeof(*args), GFP_NOFS);
29446+ if (unlikely(!args)) {
29447+ AuErr1("no memory\n");
29448+ goto out_args;
29449+ }
29450+
e49829fe 29451+ atomic_inc(&br->br_count);
1facf9fc 29452+ args->sb = sb;
29453+ args->br = br;
53392da6 29454+ wkq_err = au_wkq_nowait(xino_do_trunc, args, sb, /*flags*/0);
1facf9fc 29455+ if (!wkq_err)
29456+ return; /* success */
29457+
4a4d8108 29458+ pr_err("wkq %d\n", wkq_err);
e49829fe 29459+ atomic_dec(&br->br_count);
1facf9fc 29460+
4f0767ce 29461+out_args:
1facf9fc 29462+ kfree(args);
4f0767ce 29463+out:
e49829fe 29464+ atomic_dec(&br->br_xino_running);
1facf9fc 29465+}
29466+
29467+/* ---------------------------------------------------------------------- */
29468+
29469+static int au_xino_do_write(au_writef_t write, struct file *file,
29470+ ino_t h_ino, ino_t ino)
29471+{
29472+ loff_t pos;
29473+ ssize_t sz;
29474+
29475+ pos = h_ino;
29476+ if (unlikely(au_loff_max / sizeof(ino) - 1 < pos)) {
29477+ AuIOErr1("too large hi%lu\n", (unsigned long)h_ino);
29478+ return -EFBIG;
29479+ }
29480+ pos *= sizeof(ino);
29481+ sz = xino_fwrite(write, file, &ino, sizeof(ino), &pos);
29482+ if (sz == sizeof(ino))
29483+ return 0; /* success */
29484+
29485+ AuIOErr("write failed (%zd)\n", sz);
29486+ return -EIO;
29487+}
29488+
29489+/*
29490+ * write @ino to the xinofile for the specified branch{@sb, @bindex}
29491+ * at the position of @h_ino.
29492+ * even if @ino is zero, it is written to the xinofile and means no entry.
29493+ * if the size of the xino file on a specific filesystem exceeds the watermark,
29494+ * try truncating it.
29495+ */
29496+int au_xino_write(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino,
29497+ ino_t ino)
29498+{
29499+ int err;
29500+ unsigned int mnt_flags;
29501+ struct au_branch *br;
29502+
29503+ BUILD_BUG_ON(sizeof(long long) != sizeof(au_loff_max)
29504+ || ((loff_t)-1) > 0);
dece6358 29505+ SiMustAnyLock(sb);
1facf9fc 29506+
29507+ mnt_flags = au_mntflags(sb);
29508+ if (!au_opt_test(mnt_flags, XINO))
29509+ return 0;
29510+
29511+ br = au_sbr(sb, bindex);
29512+ err = au_xino_do_write(au_sbi(sb)->si_xwrite, br->br_xino.xi_file,
29513+ h_ino, ino);
29514+ if (!err) {
29515+ if (au_opt_test(mnt_flags, TRUNC_XINO)
29516+ && au_test_fs_trunc_xino(br->br_mnt->mnt_sb))
29517+ xino_try_trunc(sb, br);
29518+ return 0; /* success */
29519+ }
29520+
29521+ AuIOErr("write failed (%d)\n", err);
29522+ return -EIO;
29523+}
29524+
29525+/* ---------------------------------------------------------------------- */
29526+
29527+/* aufs inode number bitmap */
29528+
29529+static const int page_bits = (int)PAGE_SIZE * BITS_PER_BYTE;
29530+static ino_t xib_calc_ino(unsigned long pindex, int bit)
29531+{
29532+ ino_t ino;
29533+
29534+ AuDebugOn(bit < 0 || page_bits <= bit);
29535+ ino = AUFS_FIRST_INO + pindex * page_bits + bit;
29536+ return ino;
29537+}
29538+
29539+static void xib_calc_bit(ino_t ino, unsigned long *pindex, int *bit)
29540+{
29541+ AuDebugOn(ino < AUFS_FIRST_INO);
29542+ ino -= AUFS_FIRST_INO;
29543+ *pindex = ino / page_bits;
29544+ *bit = ino % page_bits;
29545+}
29546+
29547+static int xib_pindex(struct super_block *sb, unsigned long pindex)
29548+{
29549+ int err;
29550+ loff_t pos;
29551+ ssize_t sz;
29552+ struct au_sbinfo *sbinfo;
29553+ struct file *xib;
29554+ unsigned long *p;
29555+
29556+ sbinfo = au_sbi(sb);
29557+ MtxMustLock(&sbinfo->si_xib_mtx);
29558+ AuDebugOn(pindex > ULONG_MAX / PAGE_SIZE
29559+ || !au_opt_test(sbinfo->si_mntflags, XINO));
29560+
29561+ if (pindex == sbinfo->si_xib_last_pindex)
29562+ return 0;
29563+
29564+ xib = sbinfo->si_xib;
29565+ p = sbinfo->si_xib_buf;
29566+ pos = sbinfo->si_xib_last_pindex;
29567+ pos *= PAGE_SIZE;
29568+ sz = xino_fwrite(sbinfo->si_xwrite, xib, p, PAGE_SIZE, &pos);
29569+ if (unlikely(sz != PAGE_SIZE))
29570+ goto out;
29571+
29572+ pos = pindex;
29573+ pos *= PAGE_SIZE;
29574+ if (i_size_read(xib->f_dentry->d_inode) >= pos + PAGE_SIZE)
29575+ sz = xino_fread(sbinfo->si_xread, xib, p, PAGE_SIZE, &pos);
29576+ else {
29577+ memset(p, 0, PAGE_SIZE);
29578+ sz = xino_fwrite(sbinfo->si_xwrite, xib, p, PAGE_SIZE, &pos);
29579+ }
29580+ if (sz == PAGE_SIZE) {
29581+ sbinfo->si_xib_last_pindex = pindex;
29582+ return 0; /* success */
29583+ }
29584+
4f0767ce 29585+out:
b752ccd1
AM
29586+ AuIOErr1("write failed (%zd)\n", sz);
29587+ err = sz;
29588+ if (sz >= 0)
29589+ err = -EIO;
29590+ return err;
29591+}
29592+
29593+/* ---------------------------------------------------------------------- */
29594+
29595+static void au_xib_clear_bit(struct inode *inode)
29596+{
29597+ int err, bit;
29598+ unsigned long pindex;
29599+ struct super_block *sb;
29600+ struct au_sbinfo *sbinfo;
29601+
29602+ AuDebugOn(inode->i_nlink);
29603+
29604+ sb = inode->i_sb;
29605+ xib_calc_bit(inode->i_ino, &pindex, &bit);
29606+ AuDebugOn(page_bits <= bit);
29607+ sbinfo = au_sbi(sb);
29608+ mutex_lock(&sbinfo->si_xib_mtx);
29609+ err = xib_pindex(sb, pindex);
29610+ if (!err) {
29611+ clear_bit(bit, sbinfo->si_xib_buf);
29612+ sbinfo->si_xib_next_bit = bit;
29613+ }
29614+ mutex_unlock(&sbinfo->si_xib_mtx);
29615+}
29616+
29617+/* for s_op->delete_inode() */
29618+void au_xino_delete_inode(struct inode *inode, const int unlinked)
29619+{
29620+ int err;
29621+ unsigned int mnt_flags;
29622+ aufs_bindex_t bindex, bend, bi;
29623+ unsigned char try_trunc;
29624+ struct au_iinfo *iinfo;
29625+ struct super_block *sb;
29626+ struct au_hinode *hi;
29627+ struct inode *h_inode;
29628+ struct au_branch *br;
29629+ au_writef_t xwrite;
29630+
29631+ sb = inode->i_sb;
29632+ mnt_flags = au_mntflags(sb);
29633+ if (!au_opt_test(mnt_flags, XINO)
29634+ || inode->i_ino == AUFS_ROOT_INO)
29635+ return;
29636+
29637+ if (unlinked) {
29638+ au_xigen_inc(inode);
29639+ au_xib_clear_bit(inode);
29640+ }
29641+
29642+ iinfo = au_ii(inode);
29643+ if (!iinfo)
29644+ return;
1facf9fc 29645+
b752ccd1
AM
29646+ bindex = iinfo->ii_bstart;
29647+ if (bindex < 0)
29648+ return;
1facf9fc 29649+
b752ccd1
AM
29650+ xwrite = au_sbi(sb)->si_xwrite;
29651+ try_trunc = !!au_opt_test(mnt_flags, TRUNC_XINO);
29652+ hi = iinfo->ii_hinode + bindex;
29653+ bend = iinfo->ii_bend;
29654+ for (; bindex <= bend; bindex++, hi++) {
29655+ h_inode = hi->hi_inode;
29656+ if (!h_inode
29657+ || (!unlinked && h_inode->i_nlink))
29658+ continue;
1facf9fc 29659+
b752ccd1
AM
29660+ /* inode may not be revalidated */
29661+ bi = au_br_index(sb, hi->hi_id);
29662+ if (bi < 0)
29663+ continue;
1facf9fc 29664+
b752ccd1
AM
29665+ br = au_sbr(sb, bi);
29666+ err = au_xino_do_write(xwrite, br->br_xino.xi_file,
29667+ h_inode->i_ino, /*ino*/0);
29668+ if (!err && try_trunc
29669+ && au_test_fs_trunc_xino(br->br_mnt->mnt_sb))
29670+ xino_try_trunc(sb, br);
1facf9fc 29671+ }
1facf9fc 29672+}
29673+
29674+/* get an unused inode number from bitmap */
29675+ino_t au_xino_new_ino(struct super_block *sb)
29676+{
29677+ ino_t ino;
29678+ unsigned long *p, pindex, ul, pend;
29679+ struct au_sbinfo *sbinfo;
29680+ struct file *file;
29681+ int free_bit, err;
29682+
29683+ if (!au_opt_test(au_mntflags(sb), XINO))
29684+ return iunique(sb, AUFS_FIRST_INO);
29685+
29686+ sbinfo = au_sbi(sb);
29687+ mutex_lock(&sbinfo->si_xib_mtx);
29688+ p = sbinfo->si_xib_buf;
29689+ free_bit = sbinfo->si_xib_next_bit;
29690+ if (free_bit < page_bits && !test_bit(free_bit, p))
29691+ goto out; /* success */
29692+ free_bit = find_first_zero_bit(p, page_bits);
29693+ if (free_bit < page_bits)
29694+ goto out; /* success */
29695+
29696+ pindex = sbinfo->si_xib_last_pindex;
29697+ for (ul = pindex - 1; ul < ULONG_MAX; ul--) {
29698+ err = xib_pindex(sb, ul);
29699+ if (unlikely(err))
29700+ goto out_err;
29701+ free_bit = find_first_zero_bit(p, page_bits);
29702+ if (free_bit < page_bits)
29703+ goto out; /* success */
29704+ }
29705+
29706+ file = sbinfo->si_xib;
29707+ pend = i_size_read(file->f_dentry->d_inode) / PAGE_SIZE;
29708+ for (ul = pindex + 1; ul <= pend; ul++) {
29709+ err = xib_pindex(sb, ul);
29710+ if (unlikely(err))
29711+ goto out_err;
29712+ free_bit = find_first_zero_bit(p, page_bits);
29713+ if (free_bit < page_bits)
29714+ goto out; /* success */
29715+ }
29716+ BUG();
29717+
4f0767ce 29718+out:
1facf9fc 29719+ set_bit(free_bit, p);
7f207e10 29720+ sbinfo->si_xib_next_bit = free_bit + 1;
1facf9fc 29721+ pindex = sbinfo->si_xib_last_pindex;
29722+ mutex_unlock(&sbinfo->si_xib_mtx);
29723+ ino = xib_calc_ino(pindex, free_bit);
29724+ AuDbg("i%lu\n", (unsigned long)ino);
29725+ return ino;
4f0767ce 29726+out_err:
1facf9fc 29727+ mutex_unlock(&sbinfo->si_xib_mtx);
29728+ AuDbg("i0\n");
29729+ return 0;
29730+}
29731+
29732+/*
29733+ * read @ino from xinofile for the specified branch{@sb, @bindex}
29734+ * at the position of @h_ino.
29735+ * if @ino does not exist and @do_new is true, get new one.
29736+ */
29737+int au_xino_read(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino,
29738+ ino_t *ino)
29739+{
29740+ int err;
29741+ ssize_t sz;
29742+ loff_t pos;
29743+ struct file *file;
29744+ struct au_sbinfo *sbinfo;
29745+
29746+ *ino = 0;
29747+ if (!au_opt_test(au_mntflags(sb), XINO))
29748+ return 0; /* no xino */
29749+
29750+ err = 0;
29751+ sbinfo = au_sbi(sb);
29752+ pos = h_ino;
29753+ if (unlikely(au_loff_max / sizeof(*ino) - 1 < pos)) {
29754+ AuIOErr1("too large hi%lu\n", (unsigned long)h_ino);
29755+ return -EFBIG;
29756+ }
29757+ pos *= sizeof(*ino);
29758+
29759+ file = au_sbr(sb, bindex)->br_xino.xi_file;
29760+ if (i_size_read(file->f_dentry->d_inode) < pos + sizeof(*ino))
29761+ return 0; /* no ino */
29762+
29763+ sz = xino_fread(sbinfo->si_xread, file, ino, sizeof(*ino), &pos);
29764+ if (sz == sizeof(*ino))
29765+ return 0; /* success */
29766+
29767+ err = sz;
29768+ if (unlikely(sz >= 0)) {
29769+ err = -EIO;
29770+ AuIOErr("xino read error (%zd)\n", sz);
29771+ }
29772+
29773+ return err;
29774+}
29775+
29776+/* ---------------------------------------------------------------------- */
29777+
29778+/* create and set a new xino file */
29779+
29780+struct file *au_xino_create(struct super_block *sb, char *fname, int silent)
29781+{
29782+ struct file *file;
29783+ struct dentry *h_parent, *d;
29784+ struct inode *h_dir;
29785+ int err;
29786+
29787+ /*
29788+ * at mount-time, and the xino file is the default path,
4a4d8108 29789+ * hnotify is disabled so we have no notify events to ignore.
1facf9fc 29790+ * when a user specified the xino, we cannot get au_hdir to be ignored.
29791+ */
7f207e10 29792+ file = vfsub_filp_open(fname, O_RDWR | O_CREAT | O_EXCL | O_LARGEFILE
2cbb1c4b 29793+ /* | __FMODE_NONOTIFY */,
1facf9fc 29794+ S_IRUGO | S_IWUGO);
29795+ if (IS_ERR(file)) {
29796+ if (!silent)
4a4d8108 29797+ pr_err("open %s(%ld)\n", fname, PTR_ERR(file));
1facf9fc 29798+ return file;
29799+ }
29800+
29801+ /* keep file count */
29802+ h_parent = dget_parent(file->f_dentry);
29803+ h_dir = h_parent->d_inode;
29804+ mutex_lock_nested(&h_dir->i_mutex, AuLsc_I_PARENT);
29805+ /* mnt_want_write() is unnecessary here */
29806+ err = vfsub_unlink(h_dir, &file->f_path, /*force*/0);
29807+ mutex_unlock(&h_dir->i_mutex);
29808+ dput(h_parent);
29809+ if (unlikely(err)) {
29810+ if (!silent)
4a4d8108 29811+ pr_err("unlink %s(%d)\n", fname, err);
1facf9fc 29812+ goto out;
29813+ }
29814+
29815+ err = -EINVAL;
29816+ d = file->f_dentry;
29817+ if (unlikely(sb == d->d_sb)) {
29818+ if (!silent)
4a4d8108 29819+ pr_err("%s must be outside\n", fname);
1facf9fc 29820+ goto out;
29821+ }
29822+ if (unlikely(au_test_fs_bad_xino(d->d_sb))) {
29823+ if (!silent)
4a4d8108
AM
29824+ pr_err("xino doesn't support %s(%s)\n",
29825+ fname, au_sbtype(d->d_sb));
1facf9fc 29826+ goto out;
29827+ }
29828+ return file; /* success */
29829+
4f0767ce 29830+out:
1facf9fc 29831+ fput(file);
29832+ file = ERR_PTR(err);
29833+ return file;
29834+}
29835+
29836+/*
29837+ * find another branch who is on the same filesystem of the specified
29838+ * branch{@btgt}. search until @bend.
29839+ */
29840+static int is_sb_shared(struct super_block *sb, aufs_bindex_t btgt,
29841+ aufs_bindex_t bend)
29842+{
29843+ aufs_bindex_t bindex;
29844+ struct super_block *tgt_sb = au_sbr_sb(sb, btgt);
29845+
29846+ for (bindex = 0; bindex < btgt; bindex++)
29847+ if (unlikely(tgt_sb == au_sbr_sb(sb, bindex)))
29848+ return bindex;
29849+ for (bindex++; bindex <= bend; bindex++)
29850+ if (unlikely(tgt_sb == au_sbr_sb(sb, bindex)))
29851+ return bindex;
29852+ return -1;
29853+}
29854+
29855+/* ---------------------------------------------------------------------- */
29856+
29857+/*
29858+ * initialize the xinofile for the specified branch @br
29859+ * at the place/path where @base_file indicates.
29860+ * test whether another branch is on the same filesystem or not,
29861+ * if @do_test is true.
29862+ */
29863+int au_xino_br(struct super_block *sb, struct au_branch *br, ino_t h_ino,
29864+ struct file *base_file, int do_test)
29865+{
29866+ int err;
29867+ ino_t ino;
29868+ aufs_bindex_t bend, bindex;
29869+ struct au_branch *shared_br, *b;
29870+ struct file *file;
29871+ struct super_block *tgt_sb;
29872+
29873+ shared_br = NULL;
29874+ bend = au_sbend(sb);
29875+ if (do_test) {
29876+ tgt_sb = br->br_mnt->mnt_sb;
29877+ for (bindex = 0; bindex <= bend; bindex++) {
29878+ b = au_sbr(sb, bindex);
29879+ if (tgt_sb == b->br_mnt->mnt_sb) {
29880+ shared_br = b;
29881+ break;
29882+ }
29883+ }
29884+ }
29885+
29886+ if (!shared_br || !shared_br->br_xino.xi_file) {
29887+ struct au_xino_lock_dir ldir;
29888+
29889+ au_xino_lock_dir(sb, base_file, &ldir);
29890+ /* mnt_want_write() is unnecessary here */
29891+ file = au_xino_create2(base_file, NULL);
29892+ au_xino_unlock_dir(&ldir);
29893+ err = PTR_ERR(file);
29894+ if (IS_ERR(file))
29895+ goto out;
29896+ br->br_xino.xi_file = file;
29897+ } else {
29898+ br->br_xino.xi_file = shared_br->br_xino.xi_file;
29899+ get_file(br->br_xino.xi_file);
29900+ }
29901+
29902+ ino = AUFS_ROOT_INO;
29903+ err = au_xino_do_write(au_sbi(sb)->si_xwrite, br->br_xino.xi_file,
29904+ h_ino, ino);
b752ccd1
AM
29905+ if (unlikely(err)) {
29906+ fput(br->br_xino.xi_file);
29907+ br->br_xino.xi_file = NULL;
29908+ }
1facf9fc 29909+
4f0767ce 29910+out:
1facf9fc 29911+ return err;
29912+}
29913+
29914+/* ---------------------------------------------------------------------- */
29915+
29916+/* trucate a xino bitmap file */
29917+
29918+/* todo: slow */
29919+static int do_xib_restore(struct super_block *sb, struct file *file, void *page)
29920+{
29921+ int err, bit;
29922+ ssize_t sz;
29923+ unsigned long pindex;
29924+ loff_t pos, pend;
29925+ struct au_sbinfo *sbinfo;
29926+ au_readf_t func;
29927+ ino_t *ino;
29928+ unsigned long *p;
29929+
29930+ err = 0;
29931+ sbinfo = au_sbi(sb);
dece6358 29932+ MtxMustLock(&sbinfo->si_xib_mtx);
1facf9fc 29933+ p = sbinfo->si_xib_buf;
29934+ func = sbinfo->si_xread;
29935+ pend = i_size_read(file->f_dentry->d_inode);
29936+ pos = 0;
29937+ while (pos < pend) {
29938+ sz = xino_fread(func, file, page, PAGE_SIZE, &pos);
29939+ err = sz;
29940+ if (unlikely(sz <= 0))
29941+ goto out;
29942+
29943+ err = 0;
29944+ for (ino = page; sz > 0; ino++, sz -= sizeof(ino)) {
29945+ if (unlikely(*ino < AUFS_FIRST_INO))
29946+ continue;
29947+
29948+ xib_calc_bit(*ino, &pindex, &bit);
29949+ AuDebugOn(page_bits <= bit);
29950+ err = xib_pindex(sb, pindex);
29951+ if (!err)
29952+ set_bit(bit, p);
29953+ else
29954+ goto out;
29955+ }
29956+ }
29957+
4f0767ce 29958+out:
1facf9fc 29959+ return err;
29960+}
29961+
29962+static int xib_restore(struct super_block *sb)
29963+{
29964+ int err;
29965+ aufs_bindex_t bindex, bend;
29966+ void *page;
29967+
29968+ err = -ENOMEM;
29969+ page = (void *)__get_free_page(GFP_NOFS);
29970+ if (unlikely(!page))
29971+ goto out;
29972+
29973+ err = 0;
29974+ bend = au_sbend(sb);
29975+ for (bindex = 0; !err && bindex <= bend; bindex++)
29976+ if (!bindex || is_sb_shared(sb, bindex, bindex - 1) < 0)
29977+ err = do_xib_restore
29978+ (sb, au_sbr(sb, bindex)->br_xino.xi_file, page);
29979+ else
29980+ AuDbg("b%d\n", bindex);
29981+ free_page((unsigned long)page);
29982+
4f0767ce 29983+out:
1facf9fc 29984+ return err;
29985+}
29986+
29987+int au_xib_trunc(struct super_block *sb)
29988+{
29989+ int err;
29990+ ssize_t sz;
29991+ loff_t pos;
29992+ struct au_xino_lock_dir ldir;
29993+ struct au_sbinfo *sbinfo;
29994+ unsigned long *p;
29995+ struct file *file;
29996+
dece6358
AM
29997+ SiMustWriteLock(sb);
29998+
1facf9fc 29999+ err = 0;
30000+ sbinfo = au_sbi(sb);
30001+ if (!au_opt_test(sbinfo->si_mntflags, XINO))
30002+ goto out;
30003+
30004+ file = sbinfo->si_xib;
30005+ if (i_size_read(file->f_dentry->d_inode) <= PAGE_SIZE)
30006+ goto out;
30007+
30008+ au_xino_lock_dir(sb, file, &ldir);
30009+ /* mnt_want_write() is unnecessary here */
30010+ file = au_xino_create2(sbinfo->si_xib, NULL);
30011+ au_xino_unlock_dir(&ldir);
30012+ err = PTR_ERR(file);
30013+ if (IS_ERR(file))
30014+ goto out;
30015+ fput(sbinfo->si_xib);
30016+ sbinfo->si_xib = file;
30017+
30018+ p = sbinfo->si_xib_buf;
30019+ memset(p, 0, PAGE_SIZE);
30020+ pos = 0;
30021+ sz = xino_fwrite(sbinfo->si_xwrite, sbinfo->si_xib, p, PAGE_SIZE, &pos);
30022+ if (unlikely(sz != PAGE_SIZE)) {
30023+ err = sz;
30024+ AuIOErr("err %d\n", err);
30025+ if (sz >= 0)
30026+ err = -EIO;
30027+ goto out;
30028+ }
30029+
30030+ mutex_lock(&sbinfo->si_xib_mtx);
30031+ /* mnt_want_write() is unnecessary here */
30032+ err = xib_restore(sb);
30033+ mutex_unlock(&sbinfo->si_xib_mtx);
30034+
30035+out:
30036+ return err;
30037+}
30038+
30039+/* ---------------------------------------------------------------------- */
30040+
30041+/*
30042+ * xino mount option handlers
30043+ */
30044+static au_readf_t find_readf(struct file *h_file)
30045+{
30046+ const struct file_operations *fop = h_file->f_op;
30047+
30048+ if (fop) {
30049+ if (fop->read)
30050+ return fop->read;
30051+ if (fop->aio_read)
30052+ return do_sync_read;
30053+ }
30054+ return ERR_PTR(-ENOSYS);
30055+}
30056+
30057+static au_writef_t find_writef(struct file *h_file)
30058+{
30059+ const struct file_operations *fop = h_file->f_op;
30060+
30061+ if (fop) {
30062+ if (fop->write)
30063+ return fop->write;
30064+ if (fop->aio_write)
30065+ return do_sync_write;
30066+ }
30067+ return ERR_PTR(-ENOSYS);
30068+}
30069+
30070+/* xino bitmap */
30071+static void xino_clear_xib(struct super_block *sb)
30072+{
30073+ struct au_sbinfo *sbinfo;
30074+
dece6358
AM
30075+ SiMustWriteLock(sb);
30076+
1facf9fc 30077+ sbinfo = au_sbi(sb);
30078+ sbinfo->si_xread = NULL;
30079+ sbinfo->si_xwrite = NULL;
30080+ if (sbinfo->si_xib)
30081+ fput(sbinfo->si_xib);
30082+ sbinfo->si_xib = NULL;
30083+ free_page((unsigned long)sbinfo->si_xib_buf);
30084+ sbinfo->si_xib_buf = NULL;
30085+}
30086+
30087+static int au_xino_set_xib(struct super_block *sb, struct file *base)
30088+{
30089+ int err;
30090+ loff_t pos;
30091+ struct au_sbinfo *sbinfo;
30092+ struct file *file;
30093+
dece6358
AM
30094+ SiMustWriteLock(sb);
30095+
1facf9fc 30096+ sbinfo = au_sbi(sb);
30097+ file = au_xino_create2(base, sbinfo->si_xib);
30098+ err = PTR_ERR(file);
30099+ if (IS_ERR(file))
30100+ goto out;
30101+ if (sbinfo->si_xib)
30102+ fput(sbinfo->si_xib);
30103+ sbinfo->si_xib = file;
30104+ sbinfo->si_xread = find_readf(file);
30105+ sbinfo->si_xwrite = find_writef(file);
30106+
30107+ err = -ENOMEM;
30108+ if (!sbinfo->si_xib_buf)
30109+ sbinfo->si_xib_buf = (void *)get_zeroed_page(GFP_NOFS);
30110+ if (unlikely(!sbinfo->si_xib_buf))
30111+ goto out_unset;
30112+
30113+ sbinfo->si_xib_last_pindex = 0;
30114+ sbinfo->si_xib_next_bit = 0;
30115+ if (i_size_read(file->f_dentry->d_inode) < PAGE_SIZE) {
30116+ pos = 0;
30117+ err = xino_fwrite(sbinfo->si_xwrite, file, sbinfo->si_xib_buf,
30118+ PAGE_SIZE, &pos);
30119+ if (unlikely(err != PAGE_SIZE))
30120+ goto out_free;
30121+ }
30122+ err = 0;
30123+ goto out; /* success */
30124+
4f0767ce 30125+out_free:
1facf9fc 30126+ free_page((unsigned long)sbinfo->si_xib_buf);
b752ccd1
AM
30127+ sbinfo->si_xib_buf = NULL;
30128+ if (err >= 0)
30129+ err = -EIO;
4f0767ce 30130+out_unset:
b752ccd1
AM
30131+ fput(sbinfo->si_xib);
30132+ sbinfo->si_xib = NULL;
30133+ sbinfo->si_xread = NULL;
30134+ sbinfo->si_xwrite = NULL;
4f0767ce 30135+out:
b752ccd1 30136+ return err;
1facf9fc 30137+}
30138+
b752ccd1
AM
30139+/* xino for each branch */
30140+static void xino_clear_br(struct super_block *sb)
30141+{
30142+ aufs_bindex_t bindex, bend;
30143+ struct au_branch *br;
1facf9fc 30144+
b752ccd1
AM
30145+ bend = au_sbend(sb);
30146+ for (bindex = 0; bindex <= bend; bindex++) {
30147+ br = au_sbr(sb, bindex);
30148+ if (!br || !br->br_xino.xi_file)
30149+ continue;
30150+
30151+ fput(br->br_xino.xi_file);
30152+ br->br_xino.xi_file = NULL;
30153+ }
30154+}
30155+
30156+static int au_xino_set_br(struct super_block *sb, struct file *base)
1facf9fc 30157+{
30158+ int err;
b752ccd1
AM
30159+ ino_t ino;
30160+ aufs_bindex_t bindex, bend, bshared;
30161+ struct {
30162+ struct file *old, *new;
30163+ } *fpair, *p;
30164+ struct au_branch *br;
30165+ struct inode *inode;
30166+ au_writef_t writef;
1facf9fc 30167+
b752ccd1
AM
30168+ SiMustWriteLock(sb);
30169+
30170+ err = -ENOMEM;
30171+ bend = au_sbend(sb);
30172+ fpair = kcalloc(bend + 1, sizeof(*fpair), GFP_NOFS);
30173+ if (unlikely(!fpair))
1facf9fc 30174+ goto out;
30175+
b752ccd1
AM
30176+ inode = sb->s_root->d_inode;
30177+ ino = AUFS_ROOT_INO;
30178+ writef = au_sbi(sb)->si_xwrite;
30179+ for (bindex = 0, p = fpair; bindex <= bend; bindex++, p++) {
30180+ br = au_sbr(sb, bindex);
30181+ bshared = is_sb_shared(sb, bindex, bindex - 1);
30182+ if (bshared >= 0) {
30183+ /* shared xino */
30184+ *p = fpair[bshared];
30185+ get_file(p->new);
30186+ }
30187+
30188+ if (!p->new) {
30189+ /* new xino */
30190+ p->old = br->br_xino.xi_file;
30191+ p->new = au_xino_create2(base, br->br_xino.xi_file);
30192+ err = PTR_ERR(p->new);
30193+ if (IS_ERR(p->new)) {
30194+ p->new = NULL;
30195+ goto out_pair;
30196+ }
30197+ }
30198+
30199+ err = au_xino_do_write(writef, p->new,
30200+ au_h_iptr(inode, bindex)->i_ino, ino);
30201+ if (unlikely(err))
30202+ goto out_pair;
30203+ }
30204+
30205+ for (bindex = 0, p = fpair; bindex <= bend; bindex++, p++) {
30206+ br = au_sbr(sb, bindex);
30207+ if (br->br_xino.xi_file)
30208+ fput(br->br_xino.xi_file);
30209+ get_file(p->new);
30210+ br->br_xino.xi_file = p->new;
30211+ }
1facf9fc 30212+
4f0767ce 30213+out_pair:
b752ccd1
AM
30214+ for (bindex = 0, p = fpair; bindex <= bend; bindex++, p++)
30215+ if (p->new)
30216+ fput(p->new);
30217+ else
30218+ break;
30219+ kfree(fpair);
4f0767ce 30220+out:
1facf9fc 30221+ return err;
30222+}
b752ccd1
AM
30223+
30224+void au_xino_clr(struct super_block *sb)
30225+{
30226+ struct au_sbinfo *sbinfo;
30227+
30228+ au_xigen_clr(sb);
30229+ xino_clear_xib(sb);
30230+ xino_clear_br(sb);
30231+ sbinfo = au_sbi(sb);
30232+ /* lvalue, do not call au_mntflags() */
30233+ au_opt_clr(sbinfo->si_mntflags, XINO);
30234+}
30235+
30236+int au_xino_set(struct super_block *sb, struct au_opt_xino *xino, int remount)
30237+{
30238+ int err, skip;
30239+ struct dentry *parent, *cur_parent;
30240+ struct qstr *dname, *cur_name;
30241+ struct file *cur_xino;
30242+ struct inode *dir;
30243+ struct au_sbinfo *sbinfo;
30244+
30245+ SiMustWriteLock(sb);
30246+
30247+ err = 0;
30248+ sbinfo = au_sbi(sb);
30249+ parent = dget_parent(xino->file->f_dentry);
30250+ if (remount) {
30251+ skip = 0;
30252+ dname = &xino->file->f_dentry->d_name;
30253+ cur_xino = sbinfo->si_xib;
30254+ if (cur_xino) {
30255+ cur_parent = dget_parent(cur_xino->f_dentry);
30256+ cur_name = &cur_xino->f_dentry->d_name;
30257+ skip = (cur_parent == parent
30258+ && dname->len == cur_name->len
30259+ && !memcmp(dname->name, cur_name->name,
30260+ dname->len));
30261+ dput(cur_parent);
30262+ }
30263+ if (skip)
30264+ goto out;
30265+ }
30266+
30267+ au_opt_set(sbinfo->si_mntflags, XINO);
30268+ dir = parent->d_inode;
30269+ mutex_lock_nested(&dir->i_mutex, AuLsc_I_PARENT);
30270+ /* mnt_want_write() is unnecessary here */
30271+ err = au_xino_set_xib(sb, xino->file);
30272+ if (!err)
30273+ err = au_xigen_set(sb, xino->file);
30274+ if (!err)
30275+ err = au_xino_set_br(sb, xino->file);
30276+ mutex_unlock(&dir->i_mutex);
30277+ if (!err)
30278+ goto out; /* success */
30279+
30280+ /* reset all */
30281+ AuIOErr("failed creating xino(%d).\n", err);
30282+
4f0767ce 30283+out:
b752ccd1
AM
30284+ dput(parent);
30285+ return err;
30286+}
30287+
30288+/* ---------------------------------------------------------------------- */
30289+
30290+/*
30291+ * create a xinofile at the default place/path.
30292+ */
30293+struct file *au_xino_def(struct super_block *sb)
30294+{
30295+ struct file *file;
30296+ char *page, *p;
30297+ struct au_branch *br;
30298+ struct super_block *h_sb;
30299+ struct path path;
30300+ aufs_bindex_t bend, bindex, bwr;
30301+
30302+ br = NULL;
30303+ bend = au_sbend(sb);
30304+ bwr = -1;
30305+ for (bindex = 0; bindex <= bend; bindex++) {
30306+ br = au_sbr(sb, bindex);
30307+ if (au_br_writable(br->br_perm)
30308+ && !au_test_fs_bad_xino(br->br_mnt->mnt_sb)) {
30309+ bwr = bindex;
30310+ break;
30311+ }
30312+ }
30313+
7f207e10
AM
30314+ if (bwr >= 0) {
30315+ file = ERR_PTR(-ENOMEM);
537831f9 30316+ page = (void *)__get_free_page(GFP_NOFS);
7f207e10
AM
30317+ if (unlikely(!page))
30318+ goto out;
30319+ path.mnt = br->br_mnt;
30320+ path.dentry = au_h_dptr(sb->s_root, bwr);
30321+ p = d_path(&path, page, PATH_MAX - sizeof(AUFS_XINO_FNAME));
30322+ file = (void *)p;
30323+ if (!IS_ERR(p)) {
30324+ strcat(p, "/" AUFS_XINO_FNAME);
30325+ AuDbg("%s\n", p);
30326+ file = au_xino_create(sb, p, /*silent*/0);
30327+ if (!IS_ERR(file))
30328+ au_xino_brid_set(sb, br->br_id);
30329+ }
537831f9 30330+ free_page((unsigned long)page);
7f207e10
AM
30331+ } else {
30332+ file = au_xino_create(sb, AUFS_XINO_DEFPATH, /*silent*/0);
30333+ if (IS_ERR(file))
30334+ goto out;
30335+ h_sb = file->f_dentry->d_sb;
30336+ if (unlikely(au_test_fs_bad_xino(h_sb))) {
30337+ pr_err("xino doesn't support %s(%s)\n",
30338+ AUFS_XINO_DEFPATH, au_sbtype(h_sb));
30339+ fput(file);
30340+ file = ERR_PTR(-EINVAL);
30341+ }
30342+ if (!IS_ERR(file))
30343+ au_xino_brid_set(sb, -1);
30344+ }
0c5527e5 30345+
7f207e10
AM
30346+out:
30347+ return file;
30348+}
30349+
30350+/* ---------------------------------------------------------------------- */
30351+
30352+int au_xino_path(struct seq_file *seq, struct file *file)
30353+{
30354+ int err;
30355+
30356+ err = au_seq_path(seq, &file->f_path);
30357+ if (unlikely(err < 0))
30358+ goto out;
30359+
30360+ err = 0;
30361+#define Deleted "\\040(deleted)"
30362+ seq->count -= sizeof(Deleted) - 1;
30363+ AuDebugOn(memcmp(seq->buf + seq->count, Deleted,
30364+ sizeof(Deleted) - 1));
30365+#undef Deleted
30366+
30367+out:
30368+ return err;
30369+}
30370diff -urN /usr/share/empty/include/linux/aufs_type.h linux/include/linux/aufs_type.h
30371--- /usr/share/empty/include/linux/aufs_type.h 1970-01-01 01:00:00.000000000 +0100
537831f9
AM
30372+++ linux/include/linux/aufs_type.h 2012-12-13 20:41:10.434793588 +0100
30373@@ -0,0 +1,19 @@
30374+/*
30375+ * Copyright (C) 2012 Junjiro R. Okajima
30376+ *
30377+ * This program, aufs is free software; you can redistribute it and/or modify
30378+ * it under the terms of the GNU General Public License as published by
30379+ * the Free Software Foundation; either version 2 of the License, or
30380+ * (at your option) any later version.
30381+ *
30382+ * This program is distributed in the hope that it will be useful,
30383+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
30384+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
30385+ * GNU General Public License for more details.
30386+ *
30387+ * You should have received a copy of the GNU General Public License
30388+ * along with this program; if not, write to the Free Software
30389+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
30390+ */
30391+
30392+#include <uapi/linux/aufs_type.h>
30393diff -urN /usr/share/empty/include/uapi/linux/aufs_type.h linux/include/uapi/linux/aufs_type.h
30394--- /usr/share/empty/include/uapi/linux/aufs_type.h 1970-01-01 01:00:00.000000000 +0100
30395+++ linux/include/uapi/linux/aufs_type.h 2012-12-13 20:41:10.434793588 +0100
f6c5ef8b 30396@@ -0,0 +1,233 @@
7f207e10 30397+/*
f6c5ef8b 30398+ * Copyright (C) 2005-2012 Junjiro R. Okajima
7f207e10
AM
30399+ *
30400+ * This program, aufs is free software; you can redistribute it and/or modify
30401+ * it under the terms of the GNU General Public License as published by
30402+ * the Free Software Foundation; either version 2 of the License, or
30403+ * (at your option) any later version.
30404+ *
30405+ * This program is distributed in the hope that it will be useful,
30406+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
30407+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
30408+ * GNU General Public License for more details.
30409+ *
30410+ * You should have received a copy of the GNU General Public License
30411+ * along with this program; if not, write to the Free Software
30412+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
30413+ */
30414+
30415+#ifndef __AUFS_TYPE_H__
30416+#define __AUFS_TYPE_H__
30417+
f6c5ef8b
AM
30418+#define AUFS_NAME "aufs"
30419+
9dbd164d 30420+#ifdef __KERNEL__
f6c5ef8b
AM
30421+/*
30422+ * define it before including all other headers.
30423+ * sched.h may use pr_* macros before defining "current", so define the
30424+ * no-current version first, and re-define later.
30425+ */
30426+#define pr_fmt(fmt) AUFS_NAME " %s:%d: " fmt, __func__, __LINE__
30427+#include <linux/sched.h>
30428+#undef pr_fmt
30429+#define pr_fmt(fmt) AUFS_NAME " %s:%d:%s[%d]: " fmt, \
30430+ __func__, __LINE__, current->comm, current->pid
9dbd164d
AM
30431+#else
30432+#include <stdint.h>
30433+#include <sys/types.h>
f6c5ef8b 30434+#endif /* __KERNEL__ */
7f207e10 30435+
f6c5ef8b
AM
30436+#include <linux/limits.h>
30437+
537831f9 30438+#define AUFS_VERSION "3.x-rcN-20121210"
7f207e10
AM
30439+
30440+/* todo? move this to linux-2.6.19/include/magic.h */
30441+#define AUFS_SUPER_MAGIC ('a' << 24 | 'u' << 16 | 'f' << 8 | 's')
30442+
30443+/* ---------------------------------------------------------------------- */
30444+
30445+#ifdef CONFIG_AUFS_BRANCH_MAX_127
9dbd164d 30446+typedef int8_t aufs_bindex_t;
7f207e10
AM
30447+#define AUFS_BRANCH_MAX 127
30448+#else
9dbd164d 30449+typedef int16_t aufs_bindex_t;
7f207e10
AM
30450+#ifdef CONFIG_AUFS_BRANCH_MAX_511
30451+#define AUFS_BRANCH_MAX 511
30452+#elif defined(CONFIG_AUFS_BRANCH_MAX_1023)
30453+#define AUFS_BRANCH_MAX 1023
30454+#elif defined(CONFIG_AUFS_BRANCH_MAX_32767)
30455+#define AUFS_BRANCH_MAX 32767
30456+#endif
30457+#endif
30458+
30459+#ifdef __KERNEL__
30460+#ifndef AUFS_BRANCH_MAX
30461+#error unknown CONFIG_AUFS_BRANCH_MAX value
30462+#endif
30463+#endif /* __KERNEL__ */
30464+
30465+/* ---------------------------------------------------------------------- */
30466+
7f207e10
AM
30467+#define AUFS_FSTYPE AUFS_NAME
30468+
30469+#define AUFS_ROOT_INO 2
30470+#define AUFS_FIRST_INO 11
30471+
30472+#define AUFS_WH_PFX ".wh."
30473+#define AUFS_WH_PFX_LEN ((int)sizeof(AUFS_WH_PFX) - 1)
30474+#define AUFS_WH_TMP_LEN 4
30475+/* a limit for rmdir/rename a dir */
30476+#define AUFS_MAX_NAMELEN (NAME_MAX \
30477+ - AUFS_WH_PFX_LEN * 2 /* doubly whiteouted */\
30478+ - 1 /* dot */\
30479+ - AUFS_WH_TMP_LEN) /* hex */
30480+#define AUFS_XINO_FNAME "." AUFS_NAME ".xino"
30481+#define AUFS_XINO_DEFPATH "/tmp/" AUFS_XINO_FNAME
30482+#define AUFS_XINO_TRUNC_INIT 64 /* blocks */
30483+#define AUFS_XINO_TRUNC_STEP 4 /* blocks */
30484+#define AUFS_DIRWH_DEF 3
30485+#define AUFS_RDCACHE_DEF 10 /* seconds */
027c5e7a 30486+#define AUFS_RDCACHE_MAX 3600 /* seconds */
7f207e10
AM
30487+#define AUFS_RDBLK_DEF 512 /* bytes */
30488+#define AUFS_RDHASH_DEF 32
30489+#define AUFS_WKQ_NAME AUFS_NAME "d"
027c5e7a
AM
30490+#define AUFS_MFS_DEF_SEC 30 /* seconds */
30491+#define AUFS_MFS_MAX_SEC 3600 /* seconds */
7f207e10
AM
30492+#define AUFS_PLINK_WARN 100 /* number of plinks */
30493+
30494+/* pseudo-link maintenace under /proc */
30495+#define AUFS_PLINK_MAINT_NAME "plink_maint"
30496+#define AUFS_PLINK_MAINT_DIR "fs/" AUFS_NAME
30497+#define AUFS_PLINK_MAINT_PATH AUFS_PLINK_MAINT_DIR "/" AUFS_PLINK_MAINT_NAME
30498+
30499+#define AUFS_DIROPQ_NAME AUFS_WH_PFX ".opq" /* whiteouted doubly */
30500+#define AUFS_WH_DIROPQ AUFS_WH_PFX AUFS_DIROPQ_NAME
30501+
30502+#define AUFS_BASE_NAME AUFS_WH_PFX AUFS_NAME
30503+#define AUFS_PLINKDIR_NAME AUFS_WH_PFX "plnk"
30504+#define AUFS_ORPHDIR_NAME AUFS_WH_PFX "orph"
30505+
30506+/* doubly whiteouted */
30507+#define AUFS_WH_BASE AUFS_WH_PFX AUFS_BASE_NAME
30508+#define AUFS_WH_PLINKDIR AUFS_WH_PFX AUFS_PLINKDIR_NAME
30509+#define AUFS_WH_ORPHDIR AUFS_WH_PFX AUFS_ORPHDIR_NAME
30510+
1e00d052 30511+/* branch permissions and attributes */
7f207e10
AM
30512+#define AUFS_BRPERM_RW "rw"
30513+#define AUFS_BRPERM_RO "ro"
30514+#define AUFS_BRPERM_RR "rr"
1e00d052
AM
30515+#define AUFS_BRRATTR_WH "wh"
30516+#define AUFS_BRWATTR_NLWH "nolwh"
7f207e10
AM
30517+
30518+/* ---------------------------------------------------------------------- */
30519+
30520+/* ioctl */
30521+enum {
30522+ /* readdir in userspace */
30523+ AuCtl_RDU,
30524+ AuCtl_RDU_INO,
30525+
30526+ /* pathconf wrapper */
027c5e7a
AM
30527+ AuCtl_WBR_FD,
30528+
30529+ /* busy inode */
30530+ AuCtl_IBUSY
7f207e10
AM
30531+};
30532+
30533+/* borrowed from linux/include/linux/kernel.h */
30534+#ifndef ALIGN
30535+#define ALIGN(x, a) __ALIGN_MASK(x, (typeof(x))(a)-1)
30536+#define __ALIGN_MASK(x, mask) (((x)+(mask))&~(mask))
30537+#endif
30538+
30539+/* borrowed from linux/include/linux/compiler-gcc3.h */
30540+#ifndef __aligned
30541+#define __aligned(x) __attribute__((aligned(x)))
53392da6
AM
30542+#endif
30543+
30544+#ifdef __KERNEL__
30545+#ifndef __packed
7f207e10
AM
30546+#define __packed __attribute__((packed))
30547+#endif
53392da6 30548+#endif
7f207e10
AM
30549+
30550+struct au_rdu_cookie {
9dbd164d
AM
30551+ uint64_t h_pos;
30552+ int16_t bindex;
30553+ uint8_t flags;
30554+ uint8_t pad;
30555+ uint32_t generation;
7f207e10
AM
30556+} __aligned(8);
30557+
30558+struct au_rdu_ent {
9dbd164d
AM
30559+ uint64_t ino;
30560+ int16_t bindex;
30561+ uint8_t type;
30562+ uint8_t nlen;
30563+ uint8_t wh;
7f207e10
AM
30564+ char name[0];
30565+} __aligned(8);
30566+
30567+static inline int au_rdu_len(int nlen)
30568+{
30569+ /* include the terminating NULL */
30570+ return ALIGN(sizeof(struct au_rdu_ent) + nlen + 1,
9dbd164d 30571+ sizeof(uint64_t));
7f207e10
AM
30572+}
30573+
30574+union au_rdu_ent_ul {
30575+ struct au_rdu_ent __user *e;
9dbd164d 30576+ uint64_t ul;
7f207e10
AM
30577+};
30578+
30579+enum {
30580+ AufsCtlRduV_SZ,
30581+ AufsCtlRduV_End
30582+};
30583+
30584+struct aufs_rdu {
30585+ /* input */
30586+ union {
9dbd164d
AM
30587+ uint64_t sz; /* AuCtl_RDU */
30588+ uint64_t nent; /* AuCtl_RDU_INO */
7f207e10
AM
30589+ };
30590+ union au_rdu_ent_ul ent;
9dbd164d 30591+ uint16_t verify[AufsCtlRduV_End];
7f207e10
AM
30592+
30593+ /* input/output */
9dbd164d 30594+ uint32_t blk;
7f207e10
AM
30595+
30596+ /* output */
30597+ union au_rdu_ent_ul tail;
30598+ /* number of entries which were added in a single call */
9dbd164d
AM
30599+ uint64_t rent;
30600+ uint8_t full;
30601+ uint8_t shwh;
7f207e10
AM
30602+
30603+ struct au_rdu_cookie cookie;
30604+} __aligned(8);
30605+
1e00d052
AM
30606+/* ---------------------------------------------------------------------- */
30607+
30608+struct aufs_wbr_fd {
9dbd164d
AM
30609+ uint32_t oflags;
30610+ int16_t brid;
1e00d052
AM
30611+} __aligned(8);
30612+
30613+/* ---------------------------------------------------------------------- */
30614+
027c5e7a 30615+struct aufs_ibusy {
9dbd164d
AM
30616+ uint64_t ino, h_ino;
30617+ int16_t bindex;
027c5e7a
AM
30618+} __aligned(8);
30619+
1e00d052
AM
30620+/* ---------------------------------------------------------------------- */
30621+
7f207e10
AM
30622+#define AuCtlType 'A'
30623+#define AUFS_CTL_RDU _IOWR(AuCtlType, AuCtl_RDU, struct aufs_rdu)
30624+#define AUFS_CTL_RDU_INO _IOWR(AuCtlType, AuCtl_RDU_INO, struct aufs_rdu)
1e00d052
AM
30625+#define AUFS_CTL_WBR_FD _IOW(AuCtlType, AuCtl_WBR_FD, \
30626+ struct aufs_wbr_fd)
027c5e7a 30627+#define AUFS_CTL_IBUSY _IOWR(AuCtlType, AuCtl_IBUSY, struct aufs_ibusy)
7f207e10
AM
30628+
30629+#endif /* __AUFS_TYPE_H__ */
This page took 4.596816 seconds and 4 git commands to generate.