]> git.pld-linux.org Git - packages/kernel.git/blame - kernel-aufs3.patch
- up to 3.5.2
[packages/kernel.git] / kernel-aufs3.patch
CommitLineData
0c3ec466 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
92d182d2 16index 2fb9779..abefac5 100644
7f207e10
AM
17--- a/fs/Makefile
18+++ b/fs/Makefile
92d182d2 19@@ -125,3 +125,4 @@ obj-$(CONFIG_GFS2_FS) += gfs2/
9dbd164d 20 obj-y += exofs/ # Multiple modules
7f207e10 21 obj-$(CONFIG_CEPH_FS) += ceph/
bf0370f2 22 obj-$(CONFIG_PSTORE) += pstore/
2cbb1c4b 23+obj-$(CONFIG_AUFS_FS) += aufs/
7f207e10 24diff --git a/include/linux/Kbuild b/include/linux/Kbuild
0c3ec466 25index 8760be3..a1b8446 100644
7f207e10
AM
26--- a/include/linux/Kbuild
27+++ b/include/linux/Kbuild
92d182d2 28@@ -66,6 +66,7 @@ header-y += atmppp.h
7f207e10
AM
29 header-y += atmsap.h
30 header-y += atmsvc.h
31 header-y += audit.h
32+header-y += aufs_type.h
33 header-y += auto_fs.h
34 header-y += auto_fs4.h
35 header-y += auxvec.h
0c3ec466 36aufs3.x-rcN base patch
7f207e10 37
0c3ec466
AM
38diff --git a/fs/inode.c b/fs/inode.c
39index c99163b..7f772fd 100644
40--- a/fs/inode.c
41+++ b/fs/inode.c
42@@ -1491,7 +1491,7 @@ static int relatime_need_update(struct vfsmount *mnt, struct inode *inode,
43 * This does the actual work of updating an inodes time or version. Must have
44 * had called mnt_want_write() before calling this.
45 */
46-static int update_time(struct inode *inode, struct timespec *time, int flags)
47+int update_time(struct inode *inode, struct timespec *time, int flags)
48 {
49 if (inode->i_op->update_time)
50 return inode->i_op->update_time(inode, time, flags);
7f207e10 51diff --git a/fs/namei.c b/fs/namei.c
0c3ec466 52index 7d69419..18c9782 100644
7f207e10
AM
53--- a/fs/namei.c
54+++ b/fs/namei.c
0c3ec466 55@@ -1864,7 +1864,7 @@ int vfs_path_lookup(struct dentry *dentry, struct vfsmount *mnt,
7f207e10
AM
56 * needs parent already locked. Doesn't follow mounts.
57 * SMP-safe.
58 */
59-static struct dentry *lookup_hash(struct nameidata *nd)
60+struct dentry *lookup_hash(struct nameidata *nd)
61 {
7f207e10
AM
62 return __lookup_hash(&nd->last, nd->path.dentry, nd);
63 }
7f207e10 64diff --git a/fs/splice.c b/fs/splice.c
0c3ec466 65index c9f1318..490239f 100644
7f207e10
AM
66--- a/fs/splice.c
67+++ b/fs/splice.c
0c3ec466 68@@ -1086,8 +1086,8 @@ EXPORT_SYMBOL(generic_splice_sendpage);
7f207e10
AM
69 /*
70 * Attempt to initiate a splice from pipe to file.
71 */
72-static long do_splice_from(struct pipe_inode_info *pipe, struct file *out,
73- loff_t *ppos, size_t len, unsigned int flags)
74+long do_splice_from(struct pipe_inode_info *pipe, struct file *out,
75+ loff_t *ppos, size_t len, unsigned int flags)
76 {
77 ssize_t (*splice_write)(struct pipe_inode_info *, struct file *,
78 loff_t *, size_t, unsigned int);
0c3ec466 79@@ -1114,9 +1114,9 @@ static long do_splice_from(struct pipe_inode_info *pipe, struct file *out,
7f207e10
AM
80 /*
81 * Attempt to initiate a splice from a file to a pipe.
82 */
83-static long do_splice_to(struct file *in, loff_t *ppos,
84- struct pipe_inode_info *pipe, size_t len,
85- unsigned int flags)
86+long do_splice_to(struct file *in, loff_t *ppos,
87+ struct pipe_inode_info *pipe, size_t len,
88+ unsigned int flags)
89 {
90 ssize_t (*splice_read)(struct file *, loff_t *,
91 struct pipe_inode_info *, size_t, unsigned int);
0c3ec466
AM
92diff --git a/include/linux/fs.h b/include/linux/fs.h
93index 17fd887..9c75a47 100644
94--- a/include/linux/fs.h
95+++ b/include/linux/fs.h
96@@ -2591,6 +2591,7 @@ extern int inode_change_ok(const struct inode *, struct iattr *);
97 extern int inode_newsize_ok(const struct inode *, loff_t offset);
98 extern void setattr_copy(struct inode *inode, const struct iattr *attr);
99
100+extern int update_time(struct inode *, struct timespec *, int);
101 extern int file_update_time(struct file *file);
102
103 extern int generic_show_options(struct seq_file *m, struct dentry *root);
7f207e10 104diff --git a/include/linux/namei.h b/include/linux/namei.h
9dbd164d 105index ffc0213..ef35a31 100644
7f207e10
AM
106--- a/include/linux/namei.h
107+++ b/include/linux/namei.h
9dbd164d 108@@ -85,6 +85,7 @@ extern int vfs_path_lookup(struct dentry *, struct vfsmount *,
7f207e10
AM
109 extern struct file *lookup_instantiate_filp(struct nameidata *nd, struct dentry *dentry,
110 int (*open)(struct inode *, struct file *));
111
112+extern struct dentry *lookup_hash(struct nameidata *nd);
7f207e10
AM
113 extern struct dentry *lookup_one_len(const char *, struct dentry *, int);
114
027c5e7a 115 extern int follow_down_one(struct path *);
1e00d052
AM
116diff --git a/include/linux/splice.h b/include/linux/splice.h
117index 26e5b61..3ffef2f 100644
118--- a/include/linux/splice.h
119+++ b/include/linux/splice.h
120@@ -91,4 +91,10 @@ extern void splice_shrink_spd(struct pipe_inode_info *,
4b3da204
AM
121 extern void spd_release_page(struct splice_pipe_desc *, unsigned int);
122
123 extern const struct pipe_buf_operations page_cache_pipe_buf_ops;
1e00d052
AM
124+
125+extern long do_splice_from(struct pipe_inode_info *pipe, struct file *out,
126+ loff_t *ppos, size_t len, unsigned int flags);
127+extern long do_splice_to(struct file *in, loff_t *ppos,
128+ struct pipe_inode_info *pipe, size_t len,
129+ unsigned int flags);
130 #endif
0c3ec466 131aufs3.x-rcN standalone patch
7f207e10
AM
132
133diff --git a/fs/file_table.c b/fs/file_table.c
0c3ec466 134index a305d9e..6a768be 100644
7f207e10
AM
135--- a/fs/file_table.c
136+++ b/fs/file_table.c
0c3ec466
AM
137@@ -35,6 +35,7 @@ struct files_stat_struct files_stat = {
138 };
139
140 DEFINE_LGLOCK(files_lglock);
141+EXPORT_SYMBOL(files_lglock);
142
143 /* SLAB cache for file structures */
144 static struct kmem_cache *filp_cachep __read_mostly;
145@@ -441,6 +442,8 @@ void file_sb_list_del(struct file *file)
7f207e10
AM
146 }
147 }
148
149+EXPORT_SYMBOL(file_sb_list_del);
1facf9fc 150+
7f207e10
AM
151 #ifdef CONFIG_SMP
152
153 /*
1e00d052 154diff --git a/fs/inode.c b/fs/inode.c
0c3ec466 155index 7f772fd..e789d2f 100644
1e00d052
AM
156--- a/fs/inode.c
157+++ b/fs/inode.c
92d182d2 158@@ -56,6 +56,7 @@ static struct hlist_head *inode_hashtable __read_mostly;
4b3da204 159 static __cacheline_aligned_in_smp DEFINE_SPINLOCK(inode_hash_lock);
2cbb1c4b
JR
160
161 __cacheline_aligned_in_smp DEFINE_SPINLOCK(inode_sb_list_lock);
2cbb1c4b 162+EXPORT_SYMBOL(inode_sb_list_lock);
7f207e10
AM
163
164 /*
4b3da204 165 * Empty aops. Can be used for the cases where the user does not
0c3ec466
AM
166@@ -1507,6 +1508,7 @@ int update_time(struct inode *inode, struct timespec *time, int flags)
167 mark_inode_dirty_sync(inode);
168 return 0;
169 }
170+EXPORT_SYMBOL(update_time);
171
172 /**
173 * touch_atime - update the access time
7f207e10 174diff --git a/fs/namei.c b/fs/namei.c
0c3ec466 175index 18c9782..f09edf3 100644
7f207e10
AM
176--- a/fs/namei.c
177+++ b/fs/namei.c
0c3ec466 178@@ -1868,6 +1868,7 @@ struct dentry *lookup_hash(struct nameidata *nd)
027c5e7a 179 {
7f207e10
AM
180 return __lookup_hash(&nd->last, nd->path.dentry, nd);
181 }
182+EXPORT_SYMBOL(lookup_hash);
183
7f207e10
AM
184 /**
185 * lookup_one_len - filesystem helper to lookup single pathname component
186diff --git a/fs/namespace.c b/fs/namespace.c
0c3ec466 187index 1e4a5fe..06aa768 100644
7f207e10
AM
188--- a/fs/namespace.c
189+++ b/fs/namespace.c
0c3ec466
AM
190@@ -50,6 +50,7 @@ EXPORT_SYMBOL_GPL(fs_kobj);
191 * tree or hash is modified or when a vfsmount structure is modified.
192 */
193 DEFINE_BRLOCK(vfsmount_lock);
194+EXPORT_SYMBOL(vfsmount_lock);
195
196 static inline unsigned long hash(struct vfsmount *mnt, struct dentry *dentry)
197 {
198@@ -1341,6 +1342,7 @@ int iterate_mounts(int (*f)(struct vfsmount *, void *), void *arg,
7f207e10
AM
199 }
200 return 0;
201 }
202+EXPORT_SYMBOL(iterate_mounts);
203
7eafdf33 204 static void cleanup_group_ids(struct mount *mnt, struct mount *end)
7f207e10
AM
205 {
206diff --git a/fs/notify/group.c b/fs/notify/group.c
1e00d052 207index 63fc294..6f4adca 100644
7f207e10
AM
208--- a/fs/notify/group.c
209+++ b/fs/notify/group.c
210@@ -22,6 +22,7 @@
211 #include <linux/srcu.h>
212 #include <linux/rculist.h>
213 #include <linux/wait.h>
214+#include <linux/module.h>
215
216 #include <linux/fsnotify_backend.h>
217 #include "fsnotify.h"
218@@ -70,6 +71,7 @@ void fsnotify_put_group(struct fsnotify_group *group)
219 if (atomic_dec_and_test(&group->refcnt))
220 fsnotify_destroy_group(group);
221 }
222+EXPORT_SYMBOL(fsnotify_put_group);
223
224 /*
225 * Create a new fsnotify_group and hold a reference for the group returned.
226@@ -102,3 +104,4 @@ struct fsnotify_group *fsnotify_alloc_group(const struct fsnotify_ops *ops)
227
228 return group;
229 }
230+EXPORT_SYMBOL(fsnotify_alloc_group);
231diff --git a/fs/notify/mark.c b/fs/notify/mark.c
7eafdf33 232index f104d56..54f36db 100644
7f207e10
AM
233--- a/fs/notify/mark.c
234+++ b/fs/notify/mark.c
2cbb1c4b 235@@ -112,6 +112,7 @@ void fsnotify_put_mark(struct fsnotify_mark *mark)
7f207e10
AM
236 if (atomic_dec_and_test(&mark->refcnt))
237 mark->free_mark(mark);
238 }
239+EXPORT_SYMBOL(fsnotify_put_mark);
240
241 /*
242 * Any time a mark is getting freed we end up here.
7eafdf33 243@@ -191,6 +192,7 @@ void fsnotify_destroy_mark(struct fsnotify_mark *mark)
7f207e10
AM
244 if (unlikely(atomic_dec_and_test(&group->num_marks)))
245 fsnotify_final_destroy_group(group);
246 }
247+EXPORT_SYMBOL(fsnotify_destroy_mark);
248
249 void fsnotify_set_mark_mask_locked(struct fsnotify_mark *mark, __u32 mask)
250 {
7eafdf33 251@@ -278,6 +280,7 @@ err:
7f207e10
AM
252
253 return ret;
254 }
255+EXPORT_SYMBOL(fsnotify_add_mark);
256
257 /*
258 * clear any marks in a group in which mark->flags & flags is true
7eafdf33 259@@ -333,6 +336,7 @@ void fsnotify_init_mark(struct fsnotify_mark *mark,
7f207e10
AM
260 atomic_set(&mark->refcnt, 1);
261 mark->free_mark = free_mark;
262 }
263+EXPORT_SYMBOL(fsnotify_init_mark);
264
265 static int fsnotify_mark_destroy(void *ignored)
266 {
267diff --git a/fs/open.c b/fs/open.c
0c3ec466 268index d6c79a0..9004a15 100644
7f207e10
AM
269--- a/fs/open.c
270+++ b/fs/open.c
271@@ -60,6 +60,7 @@ int do_truncate(struct dentry *dentry, loff_t length, unsigned int time_attrs,
272 mutex_unlock(&dentry->d_inode->i_mutex);
273 return ret;
274 }
275+EXPORT_SYMBOL(do_truncate);
276
277 static long do_sys_truncate(const char __user *pathname, loff_t length)
278 {
279diff --git a/fs/splice.c b/fs/splice.c
0c3ec466 280index 490239f..701d34a 100644
7f207e10
AM
281--- a/fs/splice.c
282+++ b/fs/splice.c
0c3ec466 283@@ -1110,6 +1110,7 @@ long do_splice_from(struct pipe_inode_info *pipe, struct file *out,
7f207e10
AM
284
285 return splice_write(pipe, out, ppos, len, flags);
286 }
287+EXPORT_SYMBOL(do_splice_from);
288
289 /*
290 * Attempt to initiate a splice from a file to a pipe.
0c3ec466 291@@ -1136,6 +1137,7 @@ long do_splice_to(struct file *in, loff_t *ppos,
7f207e10
AM
292
293 return splice_read(in, ppos, pipe, len, flags);
294 }
295+EXPORT_SYMBOL(do_splice_to);
296
297 /**
298 * splice_direct_to_actor - splices data directly between two non-pipes
299diff --git a/security/commoncap.c b/security/commoncap.c
0c3ec466 300index 6dbae46..9f4f29a 100644
7f207e10
AM
301--- a/security/commoncap.c
302+++ b/security/commoncap.c
0c3ec466 303@@ -979,9 +979,11 @@ int cap_mmap_addr(unsigned long addr)
94337f0d 304 }
7f207e10
AM
305 return ret;
306 }
0c3ec466
AM
307+EXPORT_SYMBOL(cap_mmap_addr);
308
309 int cap_mmap_file(struct file *file, unsigned long reqprot,
310 unsigned long prot, unsigned long flags)
311 {
312 return 0;
313 }
314+EXPORT_SYMBOL(cap_mmap_file);
7f207e10 315diff --git a/security/device_cgroup.c b/security/device_cgroup.c
0c3ec466 316index 442204c..e644a1c 100644
7f207e10
AM
317--- a/security/device_cgroup.c
318+++ b/security/device_cgroup.c
f6c5ef8b
AM
319@@ -7,6 +7,7 @@
320 #include <linux/device_cgroup.h>
321 #include <linux/cgroup.h>
322 #include <linux/ctype.h>
323+#include <linux/export.h>
324 #include <linux/list.h>
325 #include <linux/uaccess.h>
326 #include <linux/seq_file.h>
0c3ec466 327@@ -493,6 +494,7 @@ found:
7f207e10
AM
328
329 return -EPERM;
330 }
2cbb1c4b 331+EXPORT_SYMBOL(__devcgroup_inode_permission);
7f207e10
AM
332
333 int devcgroup_inode_mknod(int mode, dev_t dev)
334 {
335diff --git a/security/security.c b/security/security.c
0c3ec466 336index 3efc9b1..c7afd35 100644
7f207e10
AM
337--- a/security/security.c
338+++ b/security/security.c
0c3ec466 339@@ -383,6 +383,7 @@ int security_path_rmdir(struct path *dir, struct dentry *dentry)
7f207e10
AM
340 return 0;
341 return security_ops->path_rmdir(dir, dentry);
342 }
343+EXPORT_SYMBOL(security_path_rmdir);
344
345 int security_path_unlink(struct path *dir, struct dentry *dentry)
346 {
0c3ec466 347@@ -399,6 +400,7 @@ int security_path_symlink(struct path *dir, struct dentry *dentry,
7f207e10
AM
348 return 0;
349 return security_ops->path_symlink(dir, dentry, old_name);
350 }
351+EXPORT_SYMBOL(security_path_symlink);
352
353 int security_path_link(struct dentry *old_dentry, struct path *new_dir,
354 struct dentry *new_dentry)
0c3ec466 355@@ -407,6 +409,7 @@ int security_path_link(struct dentry *old_dentry, struct path *new_dir,
7f207e10
AM
356 return 0;
357 return security_ops->path_link(old_dentry, new_dir, new_dentry);
358 }
359+EXPORT_SYMBOL(security_path_link);
360
361 int security_path_rename(struct path *old_dir, struct dentry *old_dentry,
362 struct path *new_dir, struct dentry *new_dentry)
0c3ec466 363@@ -425,6 +428,7 @@ int security_path_truncate(struct path *path)
7f207e10
AM
364 return 0;
365 return security_ops->path_truncate(path);
366 }
367+EXPORT_SYMBOL(security_path_truncate);
368
7eafdf33
AM
369 int security_path_chmod(struct path *path, umode_t mode)
370 {
0c3ec466 371@@ -432,6 +436,7 @@ int security_path_chmod(struct path *path, umode_t mode)
7f207e10 372 return 0;
7eafdf33 373 return security_ops->path_chmod(path, mode);
7f207e10
AM
374 }
375+EXPORT_SYMBOL(security_path_chmod);
376
377 int security_path_chown(struct path *path, uid_t uid, gid_t gid)
378 {
0c3ec466 379@@ -439,6 +444,7 @@ int security_path_chown(struct path *path, uid_t uid, gid_t gid)
7f207e10
AM
380 return 0;
381 return security_ops->path_chown(path, uid, gid);
382 }
383+EXPORT_SYMBOL(security_path_chown);
384
385 int security_path_chroot(struct path *path)
386 {
0c3ec466 387@@ -515,6 +521,7 @@ int security_inode_readlink(struct dentry *dentry)
7f207e10
AM
388 return 0;
389 return security_ops->inode_readlink(dentry);
390 }
391+EXPORT_SYMBOL(security_inode_readlink);
392
393 int security_inode_follow_link(struct dentry *dentry, struct nameidata *nd)
394 {
0c3ec466 395@@ -529,6 +536,7 @@ int security_inode_permission(struct inode *inode, int mask)
7f207e10 396 return 0;
1e00d052 397 return security_ops->inode_permission(inode, mask);
7f207e10
AM
398 }
399+EXPORT_SYMBOL(security_inode_permission);
400
1e00d052 401 int security_inode_setattr(struct dentry *dentry, struct iattr *attr)
7f207e10 402 {
0c3ec466 403@@ -644,6 +652,7 @@ int security_file_permission(struct file *file, int mask)
7f207e10
AM
404
405 return fsnotify_perm(file, mask);
406 }
407+EXPORT_SYMBOL(security_file_permission);
408
409 int security_file_alloc(struct file *file)
410 {
0c3ec466 411@@ -704,6 +713,7 @@ int security_mmap_file(struct file *file, unsigned long prot,
7f207e10
AM
412 return ret;
413 return ima_file_mmap(file, prot);
414 }
0c3ec466 415+EXPORT_SYMBOL(security_mmap_file);
7f207e10 416
0c3ec466
AM
417 int security_mmap_addr(unsigned long addr)
418 {
7f207e10
AM
419diff -urN /usr/share/empty/Documentation/ABI/testing/debugfs-aufs linux/Documentation/ABI/testing/debugfs-aufs
420--- /usr/share/empty/Documentation/ABI/testing/debugfs-aufs 1970-01-01 01:00:00.000000000 +0100
0c3ec466 421+++ linux/Documentation/ABI/testing/debugfs-aufs 2012-07-22 19:57:03.161004529 +0200
7f207e10
AM
422@@ -0,0 +1,37 @@
423+What: /debug/aufs/si_<id>/
424+Date: March 2009
425+Contact: J. R. Okajima <hooanon05@yahoo.co.jp>
426+Description:
427+ Under /debug/aufs, a directory named si_<id> is created
428+ per aufs mount, where <id> is a unique id generated
429+ internally.
1facf9fc 430+
7f207e10
AM
431+What: /debug/aufs/si_<id>/xib
432+Date: March 2009
433+Contact: J. R. Okajima <hooanon05@yahoo.co.jp>
434+Description:
435+ It shows the consumed blocks by xib (External Inode Number
436+ Bitmap), its block size and file size.
437+ When the aufs mount option 'noxino' is specified, it
438+ will be empty. About XINO files, see the aufs manual.
439+
440+What: /debug/aufs/si_<id>/xino0, xino1 ... xinoN
441+Date: March 2009
442+Contact: J. R. Okajima <hooanon05@yahoo.co.jp>
443+Description:
444+ It shows the consumed blocks by xino (External Inode Number
445+ Translation Table), its link count, block size and file
446+ size.
447+ When the aufs mount option 'noxino' is specified, it
448+ will be empty. About XINO files, see the aufs manual.
449+
450+What: /debug/aufs/si_<id>/xigen
451+Date: March 2009
452+Contact: J. R. Okajima <hooanon05@yahoo.co.jp>
453+Description:
454+ It shows the consumed blocks by xigen (External Inode
455+ Generation Table), its block size and file size.
456+ If CONFIG_AUFS_EXPORT is disabled, this entry will not
457+ be created.
458+ When the aufs mount option 'noxino' is specified, it
459+ will be empty. About XINO files, see the aufs manual.
460diff -urN /usr/share/empty/Documentation/ABI/testing/sysfs-aufs linux/Documentation/ABI/testing/sysfs-aufs
461--- /usr/share/empty/Documentation/ABI/testing/sysfs-aufs 1970-01-01 01:00:00.000000000 +0100
0c3ec466 462+++ linux/Documentation/ABI/testing/sysfs-aufs 2012-07-22 19:57:03.161004529 +0200
7f207e10
AM
463@@ -0,0 +1,24 @@
464+What: /sys/fs/aufs/si_<id>/
465+Date: March 2009
466+Contact: J. R. Okajima <hooanon05@yahoo.co.jp>
467+Description:
468+ Under /sys/fs/aufs, a directory named si_<id> is created
469+ per aufs mount, where <id> is a unique id generated
470+ internally.
471+
472+What: /sys/fs/aufs/si_<id>/br0, br1 ... brN
473+Date: March 2009
474+Contact: J. R. Okajima <hooanon05@yahoo.co.jp>
475+Description:
476+ It shows the abolute path of a member directory (which
477+ is called branch) in aufs, and its permission.
478+
479+What: /sys/fs/aufs/si_<id>/xi_path
480+Date: March 2009
481+Contact: J. R. Okajima <hooanon05@yahoo.co.jp>
482+Description:
483+ It shows the abolute path of XINO (External Inode Number
484+ Bitmap, Translation Table and Generation Table) file
485+ even if it is the default path.
486+ When the aufs mount option 'noxino' is specified, it
487+ will be empty. About XINO files, see the aufs manual.
53392da6
AM
488diff -urN /usr/share/empty/Documentation/filesystems/aufs/design/01intro.txt linux/Documentation/filesystems/aufs/design/01intro.txt
489--- /usr/share/empty/Documentation/filesystems/aufs/design/01intro.txt 1970-01-01 01:00:00.000000000 +0100
0c3ec466 490+++ linux/Documentation/filesystems/aufs/design/01intro.txt 2012-07-22 19:57:03.161004531 +0200
53392da6
AM
491@@ -0,0 +1,162 @@
492+
493+# Copyright (C) 2005-2011 Junjiro R. Okajima
494+#
495+# This program is free software; you can redistribute it and/or modify
496+# it under the terms of the GNU General Public License as published by
497+# the Free Software Foundation; either version 2 of the License, or
498+# (at your option) any later version.
499+#
500+# This program is distributed in the hope that it will be useful,
501+# but WITHOUT ANY WARRANTY; without even the implied warranty of
502+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
503+# GNU General Public License for more details.
504+#
505+# You should have received a copy of the GNU General Public License
506+# along with this program; if not, write to the Free Software
507+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
508+
509+Introduction
510+----------------------------------------
511+
512+aufs [ei ju: ef es] | [a u f s]
513+1. abbrev. for "advanced multi-layered unification filesystem".
514+2. abbrev. for "another unionfs".
515+3. abbrev. for "auf das" in German which means "on the" in English.
516+ Ex. "Butter aufs Brot"(G) means "butter onto bread"(E).
517+ But "Filesystem aufs Filesystem" is hard to understand.
518+
519+AUFS is a filesystem with features:
520+- multi layered stackable unification filesystem, the member directory
521+ is called as a branch.
522+- branch permission and attribute, 'readonly', 'real-readonly',
523+ 'readwrite', 'whiteout-able', 'link-able whiteout' and their
524+ combination.
525+- internal "file copy-on-write".
526+- logical deletion, whiteout.
527+- dynamic branch manipulation, adding, deleting and changing permission.
528+- allow bypassing aufs, user's direct branch access.
529+- external inode number translation table and bitmap which maintains the
530+ persistent aufs inode number.
531+- seekable directory, including NFS readdir.
532+- file mapping, mmap and sharing pages.
533+- pseudo-link, hardlink over branches.
534+- loopback mounted filesystem as a branch.
535+- several policies to select one among multiple writable branches.
536+- revert a single systemcall when an error occurs in aufs.
537+- and more...
538+
539+
540+Multi Layered Stackable Unification Filesystem
541+----------------------------------------------------------------------
542+Most people already knows what it is.
543+It is a filesystem which unifies several directories and provides a
544+merged single directory. When users access a file, the access will be
545+passed/re-directed/converted (sorry, I am not sure which English word is
546+correct) to the real file on the member filesystem. The member
547+filesystem is called 'lower filesystem' or 'branch' and has a mode
548+'readonly' and 'readwrite.' And the deletion for a file on the lower
549+readonly branch is handled by creating 'whiteout' on the upper writable
550+branch.
551+
552+On LKML, there have been discussions about UnionMount (Jan Blunck,
553+Bharata B Rao and Valerie Aurora) and Unionfs (Erez Zadok). They took
554+different approaches to implement the merged-view.
555+The former tries putting it into VFS, and the latter implements as a
556+separate filesystem.
557+(If I misunderstand about these implementations, please let me know and
558+I shall correct it. Because it is a long time ago when I read their
559+source files last time).
560+
561+UnionMount's approach will be able to small, but may be hard to share
562+branches between several UnionMount since the whiteout in it is
563+implemented in the inode on branch filesystem and always
564+shared. According to Bharata's post, readdir does not seems to be
565+finished yet.
566+There are several missing features known in this implementations such as
567+- for users, the inode number may change silently. eg. copy-up.
568+- link(2) may break by copy-up.
569+- read(2) may get an obsoleted filedata (fstat(2) too).
570+- fcntl(F_SETLK) may be broken by copy-up.
571+- unnecessary copy-up may happen, for example mmap(MAP_PRIVATE) after
572+ open(O_RDWR).
573+
574+Unionfs has a longer history. When I started implementing a stacking filesystem
575+(Aug 2005), it already existed. It has virtual super_block, inode,
576+dentry and file objects and they have an array pointing lower same kind
577+objects. After contributing many patches for Unionfs, I re-started my
578+project AUFS (Jun 2006).
579+
580+In AUFS, the structure of filesystem resembles to Unionfs, but I
581+implemented my own ideas, approaches and enhancements and it became
582+totally different one.
583+
584+Comparing DM snapshot and fs based implementation
585+- the number of bytes to be copied between devices is much smaller.
586+- the type of filesystem must be one and only.
587+- the fs must be writable, no readonly fs, even for the lower original
588+ device. so the compression fs will not be usable. but if we use
589+ loopback mount, we may address this issue.
590+ for instance,
591+ mount /cdrom/squashfs.img /sq
592+ losetup /sq/ext2.img
593+ losetup /somewhere/cow
594+ dmsetup "snapshot /dev/loop0 /dev/loop1 ..."
595+- it will be difficult (or needs more operations) to extract the
596+ difference between the original device and COW.
597+- DM snapshot-merge may help a lot when users try merging. in the
598+ fs-layer union, users will use rsync(1).
599+
600+
601+Several characters/aspects of aufs
602+----------------------------------------------------------------------
603+
604+Aufs has several characters or aspects.
605+1. a filesystem, callee of VFS helper
606+2. sub-VFS, caller of VFS helper for branches
607+3. a virtual filesystem which maintains persistent inode number
608+4. reader/writer of files on branches such like an application
609+
610+1. Callee of VFS Helper
611+As an ordinary linux filesystem, aufs is a callee of VFS. For instance,
612+unlink(2) from an application reaches sys_unlink() kernel function and
613+then vfs_unlink() is called. vfs_unlink() is one of VFS helper and it
614+calls filesystem specific unlink operation. Actually aufs implements the
615+unlink operation but it behaves like a redirector.
616+
617+2. Caller of VFS Helper for Branches
618+aufs_unlink() passes the unlink request to the branch filesystem as if
619+it were called from VFS. So the called unlink operation of the branch
620+filesystem acts as usual. As a caller of VFS helper, aufs should handle
621+every necessary pre/post operation for the branch filesystem.
622+- acquire the lock for the parent dir on a branch
623+- lookup in a branch
624+- revalidate dentry on a branch
625+- mnt_want_write() for a branch
626+- vfs_unlink() for a branch
627+- mnt_drop_write() for a branch
628+- release the lock on a branch
629+
630+3. Persistent Inode Number
631+One of the most important issue for a filesystem is to maintain inode
632+numbers. This is particularly important to support exporting a
633+filesystem via NFS. Aufs is a virtual filesystem which doesn't have a
634+backend block device for its own. But some storage is necessary to
635+maintain inode number. It may be a large space and may not suit to keep
636+in memory. Aufs rents some space from its first writable branch
637+filesystem (by default) and creates file(s) on it. These files are
638+created by aufs internally and removed soon (currently) keeping opened.
639+Note: Because these files are removed, they are totally gone after
640+ unmounting aufs. It means the inode numbers are not persistent
641+ across unmount or reboot. I have a plan to make them really
642+ persistent which will be important for aufs on NFS server.
643+
644+4. Read/Write Files Internally (copy-on-write)
645+Because a branch can be readonly, when you write a file on it, aufs will
646+"copy-up" it to the upper writable branch internally. And then write the
647+originally requested thing to the file. Generally kernel doesn't
648+open/read/write file actively. In aufs, even a single write may cause a
649+internal "file copy". This behaviour is very similar to cp(1) command.
650+
651+Some people may think it is better to pass such work to user space
652+helper, instead of doing in kernel space. Actually I am still thinking
653+about it. But currently I have implemented it in kernel space.
654diff -urN /usr/share/empty/Documentation/filesystems/aufs/design/02struct.txt linux/Documentation/filesystems/aufs/design/02struct.txt
655--- /usr/share/empty/Documentation/filesystems/aufs/design/02struct.txt 1970-01-01 01:00:00.000000000 +0100
0c3ec466 656+++ linux/Documentation/filesystems/aufs/design/02struct.txt 2012-07-22 19:57:03.161004531 +0200
53392da6
AM
657@@ -0,0 +1,226 @@
658+
659+# Copyright (C) 2005-2011 Junjiro R. Okajima
660+#
661+# This program is free software; you can redistribute it and/or modify
662+# it under the terms of the GNU General Public License as published by
663+# the Free Software Foundation; either version 2 of the License, or
664+# (at your option) any later version.
665+#
666+# This program is distributed in the hope that it will be useful,
667+# but WITHOUT ANY WARRANTY; without even the implied warranty of
668+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
669+# GNU General Public License for more details.
670+#
671+# You should have received a copy of the GNU General Public License
672+# along with this program; if not, write to the Free Software
673+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
674+
675+Basic Aufs Internal Structure
676+
677+Superblock/Inode/Dentry/File Objects
678+----------------------------------------------------------------------
679+As like an ordinary filesystem, aufs has its own
680+superblock/inode/dentry/file objects. All these objects have a
681+dynamically allocated array and store the same kind of pointers to the
682+lower filesystem, branch.
683+For example, when you build a union with one readwrite branch and one
684+readonly, mounted /au, /rw and /ro respectively.
685+- /au = /rw + /ro
686+- /ro/fileA exists but /rw/fileA
687+
688+Aufs lookup operation finds /ro/fileA and gets dentry for that. These
689+pointers are stored in a aufs dentry. The array in aufs dentry will be,
690+- [0] = NULL
691+- [1] = /ro/fileA
692+
693+This style of an array is essentially same to the aufs
694+superblock/inode/dentry/file objects.
695+
696+Because aufs supports manipulating branches, ie. add/delete/change
697+dynamically, these objects has its own generation. When branches are
698+changed, the generation in aufs superblock is incremented. And a
699+generation in other object are compared when it is accessed.
700+When a generation in other objects are obsoleted, aufs refreshes the
701+internal array.
702+
703+
704+Superblock
705+----------------------------------------------------------------------
706+Additionally aufs superblock has some data for policies to select one
707+among multiple writable branches, XIB files, pseudo-links and kobject.
708+See below in detail.
709+About the policies which supports copy-down a directory, see policy.txt
710+too.
711+
712+
713+Branch and XINO(External Inode Number Translation Table)
714+----------------------------------------------------------------------
715+Every branch has its own xino (external inode number translation table)
716+file. The xino file is created and unlinked by aufs internally. When two
717+members of a union exist on the same filesystem, they share the single
718+xino file.
719+The struct of a xino file is simple, just a sequence of aufs inode
720+numbers which is indexed by the lower inode number.
721+In the above sample, assume the inode number of /ro/fileA is i111 and
722+aufs assigns the inode number i999 for fileA. Then aufs writes 999 as
723+4(8) bytes at 111 * 4(8) bytes offset in the xino file.
724+
725+When the inode numbers are not contiguous, the xino file will be sparse
726+which has a hole in it and doesn't consume as much disk space as it
727+might appear. If your branch filesystem consumes disk space for such
728+holes, then you should specify 'xino=' option at mounting aufs.
729+
730+Also a writable branch has three kinds of "whiteout bases". All these
731+are existed when the branch is joined to aufs and the names are
732+whiteout-ed doubly, so that users will never see their names in aufs
733+hierarchy.
734+1. a regular file which will be linked to all whiteouts.
735+2. a directory to store a pseudo-link.
736+3. a directory to store an "orphan-ed" file temporary.
737+
738+1. Whiteout Base
739+ When you remove a file on a readonly branch, aufs handles it as a
740+ logical deletion and creates a whiteout on the upper writable branch
741+ as a hardlink of this file in order not to consume inode on the
742+ writable branch.
743+2. Pseudo-link Dir
744+ See below, Pseudo-link.
745+3. Step-Parent Dir
746+ When "fileC" exists on the lower readonly branch only and it is
747+ opened and removed with its parent dir, and then user writes
748+ something into it, then aufs copies-up fileC to this
749+ directory. Because there is no other dir to store fileC. After
750+ creating a file under this dir, the file is unlinked.
751+
752+Because aufs supports manipulating branches, ie. add/delete/change
753+dynamically, a branch has its own id. When the branch order changes, aufs
754+finds the new index by searching the branch id.
755+
756+
757+Pseudo-link
758+----------------------------------------------------------------------
759+Assume "fileA" exists on the lower readonly branch only and it is
760+hardlinked to "fileB" on the branch. When you write something to fileA,
761+aufs copies-up it to the upper writable branch. Additionally aufs
762+creates a hardlink under the Pseudo-link Directory of the writable
763+branch. The inode of a pseudo-link is kept in aufs super_block as a
764+simple list. If fileB is read after unlinking fileA, aufs returns
765+filedata from the pseudo-link instead of the lower readonly
766+branch. Because the pseudo-link is based upon the inode, to keep the
767+inode number by xino (see above) is important.
768+
769+All the hardlinks under the Pseudo-link Directory of the writable branch
770+should be restored in a proper location later. Aufs provides a utility
771+to do this. The userspace helpers executed at remounting and unmounting
772+aufs by default.
773+During this utility is running, it puts aufs into the pseudo-link
774+maintenance mode. In this mode, only the process which began the
775+maintenance mode (and its child processes) is allowed to operate in
776+aufs. Some other processes which are not related to the pseudo-link will
777+be allowed to run too, but the rest have to return an error or wait
778+until the maintenance mode ends. If a process already acquires an inode
779+mutex (in VFS), it has to return an error.
780+
781+
782+XIB(external inode number bitmap)
783+----------------------------------------------------------------------
784+Addition to the xino file per a branch, aufs has an external inode number
785+bitmap in a superblock object. It is also a file such like a xino file.
786+It is a simple bitmap to mark whether the aufs inode number is in-use or
787+not.
788+To reduce the file I/O, aufs prepares a single memory page to cache xib.
789+
790+Aufs implements a feature to truncate/refresh both of xino and xib to
791+reduce the number of consumed disk blocks for these files.
792+
793+
794+Virtual or Vertical Dir, and Readdir in Userspace
795+----------------------------------------------------------------------
796+In order to support multiple layers (branches), aufs readdir operation
797+constructs a virtual dir block on memory. For readdir, aufs calls
798+vfs_readdir() internally for each dir on branches, merges their entries
799+with eliminating the whiteout-ed ones, and sets it to file (dir)
800+object. So the file object has its entry list until it is closed. The
801+entry list will be updated when the file position is zero and becomes
802+old. This decision is made in aufs automatically.
803+
804+The dynamically allocated memory block for the name of entries has a
805+unit of 512 bytes (by default) and stores the names contiguously (no
806+padding). Another block for each entry is handled by kmem_cache too.
807+During building dir blocks, aufs creates hash list and judging whether
808+the entry is whiteouted by its upper branch or already listed.
809+The merged result is cached in the corresponding inode object and
810+maintained by a customizable life-time option.
811+
812+Some people may call it can be a security hole or invite DoS attack
813+since the opened and once readdir-ed dir (file object) holds its entry
814+list and becomes a pressure for system memory. But I'd say it is similar
815+to files under /proc or /sys. The virtual files in them also holds a
816+memory page (generally) while they are opened. When an idea to reduce
817+memory for them is introduced, it will be applied to aufs too.
818+For those who really hate this situation, I've developed readdir(3)
819+library which operates this merging in userspace. You just need to set
820+LD_PRELOAD environment variable, and aufs will not consume no memory in
821+kernel space for readdir(3).
822+
823+
824+Workqueue
825+----------------------------------------------------------------------
826+Aufs sometimes requires privilege access to a branch. For instance,
827+in copy-up/down operation. When a user process is going to make changes
828+to a file which exists in the lower readonly branch only, and the mode
829+of one of ancestor directories may not be writable by a user
830+process. Here aufs copy-up the file with its ancestors and they may
831+require privilege to set its owner/group/mode/etc.
832+This is a typical case of a application character of aufs (see
833+Introduction).
834+
835+Aufs uses workqueue synchronously for this case. It creates its own
836+workqueue. The workqueue is a kernel thread and has privilege. Aufs
837+passes the request to call mkdir or write (for example), and wait for
838+its completion. This approach solves a problem of a signal handler
839+simply.
840+If aufs didn't adopt the workqueue and changed the privilege of the
841+process, and if the mkdir/write call arises SIGXFSZ or other signal,
842+then the user process might gain a privilege or the generated core file
843+was owned by a superuser.
844+
845+Also aufs uses the system global workqueue ("events" kernel thread) too
846+for asynchronous tasks, such like handling inotify/fsnotify, re-creating a
847+whiteout base and etc. This is unrelated to a privilege.
848+Most of aufs operation tries acquiring a rw_semaphore for aufs
849+superblock at the beginning, at the same time waits for the completion
850+of all queued asynchronous tasks.
851+
852+
853+Whiteout
854+----------------------------------------------------------------------
855+The whiteout in aufs is very similar to Unionfs's. That is represented
856+by its filename. UnionMount takes an approach of a file mode, but I am
857+afraid several utilities (find(1) or something) will have to support it.
858+
859+Basically the whiteout represents "logical deletion" which stops aufs to
860+lookup further, but also it represents "dir is opaque" which also stop
861+lookup.
862+
863+In aufs, rmdir(2) and rename(2) for dir uses whiteout alternatively.
864+In order to make several functions in a single systemcall to be
865+revertible, aufs adopts an approach to rename a directory to a temporary
866+unique whiteouted name.
867+For example, in rename(2) dir where the target dir already existed, aufs
868+renames the target dir to a temporary unique whiteouted name before the
869+actual rename on a branch and then handles other actions (make it opaque,
870+update the attributes, etc). If an error happens in these actions, aufs
871+simply renames the whiteouted name back and returns an error. If all are
872+succeeded, aufs registers a function to remove the whiteouted unique
873+temporary name completely and asynchronously to the system global
874+workqueue.
875+
876+
877+Copy-up
878+----------------------------------------------------------------------
879+It is a well-known feature or concept.
880+When user modifies a file on a readonly branch, aufs operate "copy-up"
881+internally and makes change to the new file on the upper writable branch.
882+When the trigger systemcall does not update the timestamps of the parent
883+dir, aufs reverts it after copy-up.
884diff -urN /usr/share/empty/Documentation/filesystems/aufs/design/03lookup.txt linux/Documentation/filesystems/aufs/design/03lookup.txt
885--- /usr/share/empty/Documentation/filesystems/aufs/design/03lookup.txt 1970-01-01 01:00:00.000000000 +0100
0c3ec466 886+++ linux/Documentation/filesystems/aufs/design/03lookup.txt 2012-07-22 19:57:03.161004531 +0200
53392da6
AM
887@@ -0,0 +1,106 @@
888+
889+# Copyright (C) 2005-2011 Junjiro R. Okajima
890+#
891+# This program is free software; you can redistribute it and/or modify
892+# it under the terms of the GNU General Public License as published by
893+# the Free Software Foundation; either version 2 of the License, or
894+# (at your option) any later version.
895+#
896+# This program is distributed in the hope that it will be useful,
897+# but WITHOUT ANY WARRANTY; without even the implied warranty of
898+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
899+# GNU General Public License for more details.
900+#
901+# You should have received a copy of the GNU General Public License
902+# along with this program; if not, write to the Free Software
903+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
904+
905+Lookup in a Branch
906+----------------------------------------------------------------------
907+Since aufs has a character of sub-VFS (see Introduction), it operates
908+lookup for branches as VFS does. It may be a heavy work. Generally
909+speaking struct nameidata is a bigger structure and includes many
910+information. But almost all lookup operation in aufs is the simplest
911+case, ie. lookup only an entry directly connected to its parent. Digging
912+down the directory hierarchy is unnecessary.
913+
914+VFS has a function lookup_one_len() for that use, but it is not usable
915+for a branch filesystem which requires struct nameidata. So aufs
916+implements a simple lookup wrapper function. When a branch filesystem
917+allows NULL as nameidata, it calls lookup_one_len(). Otherwise it builds
918+a simplest nameidata and calls lookup_hash().
919+Here aufs applies "a principle in NFSD", ie. if the filesystem supports
920+NFS-export, then it has to support NULL as a nameidata parameter for
921+->create(), ->lookup() and ->d_revalidate(). So the lookup wrapper in
922+aufs tests if ->s_export_op in the branch is NULL or not.
923+
924+When a branch is a remote filesystem, aufs basically trusts its
925+->d_revalidate(), also aufs forces the hardest revalidate tests for
926+them.
927+For d_revalidate, aufs implements three levels of revalidate tests. See
928+"Revalidate Dentry and UDBA" in detail.
929+
930+
931+Loopback Mount
932+----------------------------------------------------------------------
933+Basically aufs supports any type of filesystem and block device for a
934+branch (actually there are some exceptions). But it is prohibited to add
935+a loopback mounted one whose backend file exists in a filesystem which is
936+already added to aufs. The reason is to protect aufs from a recursive
937+lookup. If it was allowed, the aufs lookup operation might re-enter a
938+lookup for the loopback mounted branch in the same context, and will
939+cause a deadlock.
940+
941+
942+Revalidate Dentry and UDBA (User's Direct Branch Access)
943+----------------------------------------------------------------------
944+Generally VFS helpers re-validate a dentry as a part of lookup.
945+0. digging down the directory hierarchy.
946+1. lock the parent dir by its i_mutex.
947+2. lookup the final (child) entry.
948+3. revalidate it.
949+4. call the actual operation (create, unlink, etc.)
950+5. unlock the parent dir
951+
952+If the filesystem implements its ->d_revalidate() (step 3), then it is
953+called. Actually aufs implements it and checks the dentry on a branch is
954+still valid.
955+But it is not enough. Because aufs has to release the lock for the
956+parent dir on a branch at the end of ->lookup() (step 2) and
957+->d_revalidate() (step 3) while the i_mutex of the aufs dir is still
958+held by VFS.
959+If the file on a branch is changed directly, eg. bypassing aufs, after
960+aufs released the lock, then the subsequent operation may cause
961+something unpleasant result.
962+
963+This situation is a result of VFS architecture, ->lookup() and
964+->d_revalidate() is separated. But I never say it is wrong. It is a good
965+design from VFS's point of view. It is just not suitable for sub-VFS
966+character in aufs.
967+
968+Aufs supports such case by three level of revalidation which is
969+selectable by user.
970+1. Simple Revalidate
971+ Addition to the native flow in VFS's, confirm the child-parent
972+ relationship on the branch just after locking the parent dir on the
973+ branch in the "actual operation" (step 4). When this validation
974+ fails, aufs returns EBUSY. ->d_revalidate() (step 3) in aufs still
975+ checks the validation of the dentry on branches.
976+2. Monitor Changes Internally by Inotify/Fsnotify
977+ Addition to above, in the "actual operation" (step 4) aufs re-lookup
978+ the dentry on the branch, and returns EBUSY if it finds different
979+ dentry.
980+ Additionally, aufs sets the inotify/fsnotify watch for every dir on branches
981+ during it is in cache. When the event is notified, aufs registers a
982+ function to kernel 'events' thread by schedule_work(). And the
983+ function sets some special status to the cached aufs dentry and inode
984+ private data. If they are not cached, then aufs has nothing to
985+ do. When the same file is accessed through aufs (step 0-3) later,
986+ aufs will detect the status and refresh all necessary data.
987+ In this mode, aufs has to ignore the event which is fired by aufs
988+ itself.
989+3. No Extra Validation
990+ This is the simplest test and doesn't add any additional revalidation
991+ test, and skip therevalidatin in step 4. It is useful and improves
992+ aufs performance when system surely hide the aufs branches from user,
993+ by over-mounting something (or another method).
994diff -urN /usr/share/empty/Documentation/filesystems/aufs/design/04branch.txt linux/Documentation/filesystems/aufs/design/04branch.txt
995--- /usr/share/empty/Documentation/filesystems/aufs/design/04branch.txt 1970-01-01 01:00:00.000000000 +0100
0c3ec466 996+++ linux/Documentation/filesystems/aufs/design/04branch.txt 2012-07-22 19:57:03.161004531 +0200
53392da6
AM
997@@ -0,0 +1,76 @@
998+
999+# Copyright (C) 2005-2011 Junjiro R. Okajima
1000+#
1001+# This program is free software; you can redistribute it and/or modify
1002+# it under the terms of the GNU General Public License as published by
1003+# the Free Software Foundation; either version 2 of the License, or
1004+# (at your option) any later version.
1005+#
1006+# This program is distributed in the hope that it will be useful,
1007+# but WITHOUT ANY WARRANTY; without even the implied warranty of
1008+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1009+# GNU General Public License for more details.
1010+#
1011+# You should have received a copy of the GNU General Public License
1012+# along with this program; if not, write to the Free Software
1013+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1014+
1015+Branch Manipulation
1016+
1017+Since aufs supports dynamic branch manipulation, ie. add/remove a branch
1018+and changing its permission/attribute, there are a lot of works to do.
1019+
1020+
1021+Add a Branch
1022+----------------------------------------------------------------------
1023+o Confirm the adding dir exists outside of aufs, including loopback
1024+ mount.
1025+- and other various attributes...
1026+o Initialize the xino file and whiteout bases if necessary.
1027+ See struct.txt.
1028+
1029+o Check the owner/group/mode of the directory
1030+ When the owner/group/mode of the adding directory differs from the
1031+ existing branch, aufs issues a warning because it may impose a
1032+ security risk.
1033+ For example, when a upper writable branch has a world writable empty
1034+ top directory, a malicious user can create any files on the writable
1035+ branch directly, like copy-up and modify manually. If something like
1036+ /etc/{passwd,shadow} exists on the lower readonly branch but the upper
1037+ writable branch, and the writable branch is world-writable, then a
1038+ malicious guy may create /etc/passwd on the writable branch directly
1039+ and the infected file will be valid in aufs.
1040+ I am afraid it can be a security issue, but nothing to do except
1041+ producing a warning.
1042+
1043+
1044+Delete a Branch
1045+----------------------------------------------------------------------
1046+o Confirm the deleting branch is not busy
1047+ To be general, there is one merit to adopt "remount" interface to
1048+ manipulate branches. It is to discard caches. At deleting a branch,
1049+ aufs checks the still cached (and connected) dentries and inodes. If
1050+ there are any, then they are all in-use. An inode without its
1051+ corresponding dentry can be alive alone (for example, inotify/fsnotify case).
1052+
1053+ For the cached one, aufs checks whether the same named entry exists on
1054+ other branches.
1055+ If the cached one is a directory, because aufs provides a merged view
1056+ to users, as long as one dir is left on any branch aufs can show the
1057+ dir to users. In this case, the branch can be removed from aufs.
1058+ Otherwise aufs rejects deleting the branch.
1059+
1060+ If any file on the deleting branch is opened by aufs, then aufs
1061+ rejects deleting.
1062+
1063+
1064+Modify the Permission of a Branch
1065+----------------------------------------------------------------------
1066+o Re-initialize or remove the xino file and whiteout bases if necessary.
1067+ See struct.txt.
1068+
1069+o rw --> ro: Confirm the modifying branch is not busy
1070+ Aufs rejects the request if any of these conditions are true.
1071+ - a file on the branch is mmap-ed.
1072+ - a regular file on the branch is opened for write and there is no
1073+ same named entry on the upper branch.
1074diff -urN /usr/share/empty/Documentation/filesystems/aufs/design/05wbr_policy.txt linux/Documentation/filesystems/aufs/design/05wbr_policy.txt
1075--- /usr/share/empty/Documentation/filesystems/aufs/design/05wbr_policy.txt 1970-01-01 01:00:00.000000000 +0100
0c3ec466 1076+++ linux/Documentation/filesystems/aufs/design/05wbr_policy.txt 2012-07-22 19:57:03.161004531 +0200
53392da6
AM
1077@@ -0,0 +1,65 @@
1078+
1079+# Copyright (C) 2005-2011 Junjiro R. Okajima
1080+#
1081+# This program is free software; you can redistribute it and/or modify
1082+# it under the terms of the GNU General Public License as published by
1083+# the Free Software Foundation; either version 2 of the License, or
1084+# (at your option) any later version.
1085+#
1086+# This program is distributed in the hope that it will be useful,
1087+# but WITHOUT ANY WARRANTY; without even the implied warranty of
1088+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1089+# GNU General Public License for more details.
1090+#
1091+# You should have received a copy of the GNU General Public License
1092+# along with this program; if not, write to the Free Software
1093+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1094+
1095+Policies to Select One among Multiple Writable Branches
1096+----------------------------------------------------------------------
1097+When the number of writable branch is more than one, aufs has to decide
1098+the target branch for file creation or copy-up. By default, the highest
1099+writable branch which has the parent (or ancestor) dir of the target
1100+file is chosen (top-down-parent policy).
1101+By user's request, aufs implements some other policies to select the
1102+writable branch, for file creation two policies, round-robin and
1103+most-free-space policies. For copy-up three policies, top-down-parent,
1104+bottom-up-parent and bottom-up policies.
1105+
1106+As expected, the round-robin policy selects the branch in circular. When
1107+you have two writable branches and creates 10 new files, 5 files will be
1108+created for each branch. mkdir(2) systemcall is an exception. When you
1109+create 10 new directories, all will be created on the same branch.
1110+And the most-free-space policy selects the one which has most free
1111+space among the writable branches. The amount of free space will be
1112+checked by aufs internally, and users can specify its time interval.
1113+
1114+The policies for copy-up is more simple,
1115+top-down-parent is equivalent to the same named on in create policy,
1116+bottom-up-parent selects the writable branch where the parent dir
1117+exists and the nearest upper one from the copyup-source,
1118+bottom-up selects the nearest upper writable branch from the
1119+copyup-source, regardless the existence of the parent dir.
1120+
1121+There are some rules or exceptions to apply these policies.
1122+- If there is a readonly branch above the policy-selected branch and
1123+ the parent dir is marked as opaque (a variation of whiteout), or the
1124+ target (creating) file is whiteout-ed on the upper readonly branch,
1125+ then the result of the policy is ignored and the target file will be
1126+ created on the nearest upper writable branch than the readonly branch.
1127+- If there is a writable branch above the policy-selected branch and
1128+ the parent dir is marked as opaque or the target file is whiteouted
1129+ on the branch, then the result of the policy is ignored and the target
1130+ file will be created on the highest one among the upper writable
1131+ branches who has diropq or whiteout. In case of whiteout, aufs removes
1132+ it as usual.
1133+- link(2) and rename(2) systemcalls are exceptions in every policy.
1134+ They try selecting the branch where the source exists as possible
1135+ since copyup a large file will take long time. If it can't be,
1136+ ie. the branch where the source exists is readonly, then they will
1137+ follow the copyup policy.
1138+- There is an exception for rename(2) when the target exists.
1139+ If the rename target exists, aufs compares the index of the branches
1140+ where the source and the target exists and selects the higher
1141+ one. If the selected branch is readonly, then aufs follows the
1142+ copyup policy.
1143diff -urN /usr/share/empty/Documentation/filesystems/aufs/design/06mmap.txt linux/Documentation/filesystems/aufs/design/06mmap.txt
1144--- /usr/share/empty/Documentation/filesystems/aufs/design/06mmap.txt 1970-01-01 01:00:00.000000000 +0100
0c3ec466 1145+++ linux/Documentation/filesystems/aufs/design/06mmap.txt 2012-07-22 19:57:03.161004531 +0200
53392da6
AM
1146@@ -0,0 +1,47 @@
1147+
1148+# Copyright (C) 2005-2011 Junjiro R. Okajima
1149+#
1150+# This program is free software; you can redistribute it and/or modify
1151+# it under the terms of the GNU General Public License as published by
1152+# the Free Software Foundation; either version 2 of the License, or
1153+# (at your option) any later version.
1154+#
1155+# This program is distributed in the hope that it will be useful,
1156+# but WITHOUT ANY WARRANTY; without even the implied warranty of
1157+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1158+# GNU General Public License for more details.
1159+#
1160+# You should have received a copy of the GNU General Public License
1161+# along with this program; if not, write to the Free Software
1162+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1163+
1164+mmap(2) -- File Memory Mapping
1165+----------------------------------------------------------------------
1166+In aufs, the file-mapped pages are handled by a branch fs directly, no
1167+interaction with aufs. It means aufs_mmap() calls the branch fs's
1168+->mmap().
1169+This approach is simple and good, but there is one problem.
1170+Under /proc, several entries show the mmap-ped files by its path (with
1171+device and inode number), and the printed path will be the path on the
1172+branch fs's instead of virtual aufs's.
1173+This is not a problem in most cases, but some utilities lsof(1) (and its
1174+user) may expect the path on aufs.
1175+
1176+To address this issue, aufs adds a new member called vm_prfile in struct
1177+vm_area_struct (and struct vm_region). The original vm_file points to
1178+the file on the branch fs in order to handle everything correctly as
1179+usual. The new vm_prfile points to a virtual file in aufs, and the
1180+show-functions in procfs refers to vm_prfile if it is set.
1181+Also we need to maintain several other places where touching vm_file
1182+such like
1183+- fork()/clone() copies vma and the reference count of vm_file is
1184+ incremented.
1185+- merging vma maintains the ref count too.
1186+
1187+This is not a good approach. It just faking the printed path. But it
1188+leaves all behaviour around f_mapping unchanged. This is surely an
1189+advantage.
1190+Actually aufs had adopted another complicated approach which calls
1191+generic_file_mmap() and handles struct vm_operations_struct. In this
1192+approach, aufs met a hard problem and I could not solve it without
1193+switching the approach.
1194diff -urN /usr/share/empty/Documentation/filesystems/aufs/design/07export.txt linux/Documentation/filesystems/aufs/design/07export.txt
1195--- /usr/share/empty/Documentation/filesystems/aufs/design/07export.txt 1970-01-01 01:00:00.000000000 +0100
0c3ec466 1196+++ linux/Documentation/filesystems/aufs/design/07export.txt 2012-07-22 19:57:03.161004531 +0200
53392da6
AM
1197@@ -0,0 +1,59 @@
1198+
1199+# Copyright (C) 2005-2011 Junjiro R. Okajima
1200+#
1201+# This program is free software; you can redistribute it and/or modify
1202+# it under the terms of the GNU General Public License as published by
1203+# the Free Software Foundation; either version 2 of the License, or
1204+# (at your option) any later version.
1205+#
1206+# This program is distributed in the hope that it will be useful,
1207+# but WITHOUT ANY WARRANTY; without even the implied warranty of
1208+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1209+# GNU General Public License for more details.
1210+#
1211+# You should have received a copy of the GNU General Public License
1212+# along with this program; if not, write to the Free Software
1213+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1214+
1215+Export Aufs via NFS
1216+----------------------------------------------------------------------
1217+Here is an approach.
1218+- like xino/xib, add a new file 'xigen' which stores aufs inode
1219+ generation.
1220+- iget_locked(): initialize aufs inode generation for a new inode, and
1221+ store it in xigen file.
1222+- destroy_inode(): increment aufs inode generation and store it in xigen
1223+ file. it is necessary even if it is not unlinked, because any data of
1224+ inode may be changed by UDBA.
1225+- encode_fh(): for a root dir, simply return FILEID_ROOT. otherwise
1226+ build file handle by
1227+ + branch id (4 bytes)
1228+ + superblock generation (4 bytes)
1229+ + inode number (4 or 8 bytes)
1230+ + parent dir inode number (4 or 8 bytes)
1231+ + inode generation (4 bytes))
1232+ + return value of exportfs_encode_fh() for the parent on a branch (4
1233+ bytes)
1234+ + file handle for a branch (by exportfs_encode_fh())
1235+- fh_to_dentry():
1236+ + find the index of a branch from its id in handle, and check it is
1237+ still exist in aufs.
1238+ + 1st level: get the inode number from handle and search it in cache.
1239+ + 2nd level: if not found, get the parent inode number from handle and
1240+ search it in cache. and then open the parent dir, find the matching
1241+ inode number by vfs_readdir() and get its name, and call
1242+ lookup_one_len() for the target dentry.
1243+ + 3rd level: if the parent dir is not cached, call
1244+ exportfs_decode_fh() for a branch and get the parent on a branch,
1245+ build a pathname of it, convert it a pathname in aufs, call
1246+ path_lookup(). now aufs gets a parent dir dentry, then handle it as
1247+ the 2nd level.
1248+ + to open the dir, aufs needs struct vfsmount. aufs keeps vfsmount
1249+ for every branch, but not itself. to get this, (currently) aufs
1250+ searches in current->nsproxy->mnt_ns list. it may not be a good
1251+ idea, but I didn't get other approach.
1252+ + test the generation of the gotten inode.
1253+- every inode operation: they may get EBUSY due to UDBA. in this case,
1254+ convert it into ESTALE for NFSD.
1255+- readdir(): call lockdep_on/off() because filldir in NFSD calls
1256+ lookup_one_len(), vfs_getattr(), encode_fh() and others.
1257diff -urN /usr/share/empty/Documentation/filesystems/aufs/design/08shwh.txt linux/Documentation/filesystems/aufs/design/08shwh.txt
1258--- /usr/share/empty/Documentation/filesystems/aufs/design/08shwh.txt 1970-01-01 01:00:00.000000000 +0100
0c3ec466 1259+++ linux/Documentation/filesystems/aufs/design/08shwh.txt 2012-07-22 19:57:03.161004531 +0200
53392da6
AM
1260@@ -0,0 +1,53 @@
1261+
1262+# Copyright (C) 2005-2011 Junjiro R. Okajima
1263+#
1264+# This program is free software; you can redistribute it and/or modify
1265+# it under the terms of the GNU General Public License as published by
1266+# the Free Software Foundation; either version 2 of the License, or
1267+# (at your option) any later version.
1268+#
1269+# This program is distributed in the hope that it will be useful,
1270+# but WITHOUT ANY WARRANTY; without even the implied warranty of
1271+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1272+# GNU General Public License for more details.
1273+#
1274+# You should have received a copy of the GNU General Public License
1275+# along with this program; if not, write to the Free Software
1276+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1277+
1278+Show Whiteout Mode (shwh)
1279+----------------------------------------------------------------------
1280+Generally aufs hides the name of whiteouts. But in some cases, to show
1281+them is very useful for users. For instance, creating a new middle layer
1282+(branch) by merging existing layers.
1283+
1284+(borrowing aufs1 HOW-TO from a user, Michael Towers)
1285+When you have three branches,
1286+- Bottom: 'system', squashfs (underlying base system), read-only
1287+- Middle: 'mods', squashfs, read-only
1288+- Top: 'overlay', ram (tmpfs), read-write
1289+
1290+The top layer is loaded at boot time and saved at shutdown, to preserve
1291+the changes made to the system during the session.
1292+When larger changes have been made, or smaller changes have accumulated,
1293+the size of the saved top layer data grows. At this point, it would be
1294+nice to be able to merge the two overlay branches ('mods' and 'overlay')
1295+and rewrite the 'mods' squashfs, clearing the top layer and thus
1296+restoring save and load speed.
1297+
1298+This merging is simplified by the use of another aufs mount, of just the
1299+two overlay branches using the 'shwh' option.
1300+# mount -t aufs -o ro,shwh,br:/livesys/overlay=ro+wh:/livesys/mods=rr+wh \
1301+ aufs /livesys/merge_union
1302+
1303+A merged view of these two branches is then available at
1304+/livesys/merge_union, and the new feature is that the whiteouts are
1305+visible!
1306+Note that in 'shwh' mode the aufs mount must be 'ro', which will disable
1307+writing to all branches. Also the default mode for all branches is 'ro'.
1308+It is now possible to save the combined contents of the two overlay
1309+branches to a new squashfs, e.g.:
1310+# mksquashfs /livesys/merge_union /path/to/newmods.squash
1311+
1312+This new squashfs archive can be stored on the boot device and the
1313+initramfs will use it to replace the old one at the next boot.
1314diff -urN /usr/share/empty/Documentation/filesystems/aufs/design/10dynop.txt linux/Documentation/filesystems/aufs/design/10dynop.txt
1315--- /usr/share/empty/Documentation/filesystems/aufs/design/10dynop.txt 1970-01-01 01:00:00.000000000 +0100
0c3ec466 1316+++ linux/Documentation/filesystems/aufs/design/10dynop.txt 2012-07-22 19:57:03.161004531 +0200
53392da6
AM
1317@@ -0,0 +1,47 @@
1318+
1319+# Copyright (C) 2010-2011 Junjiro R. Okajima
1320+#
1321+# This program is free software; you can redistribute it and/or modify
1322+# it under the terms of the GNU General Public License as published by
1323+# the Free Software Foundation; either version 2 of the License, or
1324+# (at your option) any later version.
1325+#
1326+# This program is distributed in the hope that it will be useful,
1327+# but WITHOUT ANY WARRANTY; without even the implied warranty of
1328+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1329+# GNU General Public License for more details.
1330+#
1331+# You should have received a copy of the GNU General Public License
1332+# along with this program; if not, write to the Free Software
1333+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1334+
1335+Dynamically customizable FS operations
1336+----------------------------------------------------------------------
1337+Generally FS operations (struct inode_operations, struct
1338+address_space_operations, struct file_operations, etc.) are defined as
1339+"static const", but it never means that FS have only one set of
1340+operation. Some FS have multiple sets of them. For instance, ext2 has
1341+three sets, one for XIP, for NOBH, and for normal.
1342+Since aufs overrides and redirects these operations, sometimes aufs has
1343+to change its behaviour according to the branch FS type. More imporantly
1344+VFS acts differently if a function (member in the struct) is set or
1345+not. It means aufs should have several sets of operations and select one
1346+among them according to the branch FS definition.
1347+
1348+In order to solve this problem and not to affect the behavour of VFS,
1349+aufs defines these operations dynamically. For instance, aufs defines
1350+aio_read function for struct file_operations, but it may not be set to
1351+the file_operations. When the branch FS doesn't have it, aufs doesn't
1352+set it to its file_operations while the function definition itself is
1353+still alive. So the behaviour of io_submit(2) will not change, and it
1354+will return an error when aio_read is not defined.
1355+
1356+The lifetime of these dynamically generated operation object is
1357+maintained by aufs branch object. When the branch is removed from aufs,
1358+the reference counter of the object is decremented. When it reaches
1359+zero, the dynamically generated operation object will be freed.
1360+
1361+This approach is designed to support AIO (io_submit), Direcit I/O and
1362+XIP mainly.
1363+Currently this approach is applied to file_operations and
1364+vm_operations_struct for regular files only.
1365diff -urN /usr/share/empty/Documentation/filesystems/aufs/design/99plan.txt linux/Documentation/filesystems/aufs/design/99plan.txt
1366--- /usr/share/empty/Documentation/filesystems/aufs/design/99plan.txt 1970-01-01 01:00:00.000000000 +0100
0c3ec466 1367+++ linux/Documentation/filesystems/aufs/design/99plan.txt 2012-07-22 19:57:03.161004531 +0200
53392da6
AM
1368@@ -0,0 +1,96 @@
1369+
1370+# Copyright (C) 2005-2011 Junjiro R. Okajima
1371+#
1372+# This program is free software; you can redistribute it and/or modify
1373+# it under the terms of the GNU General Public License as published by
1374+# the Free Software Foundation; either version 2 of the License, or
1375+# (at your option) any later version.
1376+#
1377+# This program is distributed in the hope that it will be useful,
1378+# but WITHOUT ANY WARRANTY; without even the implied warranty of
1379+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1380+# GNU General Public License for more details.
1381+#
1382+# You should have received a copy of the GNU General Public License
1383+# along with this program; if not, write to the Free Software
1384+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1385+
1386+Plan
1387+
1388+Restoring some features which was implemented in aufs1.
1389+They were dropped in aufs2 in order to make source files simpler and
1390+easier to be reviewed.
1391+
1392+
1393+Test Only the Highest One for the Directory Permission (dirperm1 option)
1394+----------------------------------------------------------------------
1395+Let's try case study.
1396+- aufs has two branches, upper readwrite and lower readonly.
1397+ /au = /rw + /ro
1398+- "dirA" exists under /ro, but /rw. and its mode is 0700.
1399+- user invoked "chmod a+rx /au/dirA"
1400+- then "dirA" becomes world readable?
1401+
1402+In this case, /ro/dirA is still 0700 since it exists in readonly branch,
1403+or it may be a natively readonly filesystem. If aufs respects the lower
1404+branch, it should not respond readdir request from other users. But user
1405+allowed it by chmod. Should really aufs rejects showing the entries
1406+under /ro/dirA?
1407+
1408+To be honest, I don't have a best solution for this case. So I
1409+implemented 'dirperm1' and 'nodirperm1' option in aufs1, and leave it to
1410+users.
1411+When dirperm1 is specified, aufs checks only the highest one for the
1412+directory permission, and shows the entries. Otherwise, as usual, checks
1413+every dir existing on all branches and rejects the request.
1414+
1415+As a side effect, dirperm1 option improves the performance of aufs
1416+because the number of permission check is reduced.
1417+
1418+
1419+Being Another Aufs's Readonly Branch (robr)
1420+----------------------------------------------------------------------
1421+Aufs1 allows aufs to be another aufs's readonly branch.
1422+This feature was developed by a user's request. But it may not be used
1423+currecnly.
1424+
1425+
1426+Copy-up on Open (coo=)
1427+----------------------------------------------------------------------
1428+By default the internal copy-up is executed when it is really necessary.
1429+It is not done when a file is opened for writing, but when write(2) is
1430+done. Users who have many (over 100) branches want to know and analyse
1431+when and what file is copied-up. To insert a new upper branch which
1432+contains such files only may improve the performance of aufs.
1433+
1434+Aufs1 implemented "coo=none | leaf | all" option.
1435+
1436+
1437+Refresh the Opened File (refrof)
1438+----------------------------------------------------------------------
1439+This option is implemented in aufs1 but incomplete.
1440+
1441+When user reads from a file, he expects to get its latest filedata
1442+generally. If the file is removed and a new same named file is created,
1443+the content he gets is unchanged, ie. the unlinked filedata.
1444+
1445+Let's try case study again.
1446+- aufs has two branches.
1447+ /au = /rw + /ro
1448+- "fileA" exists under /ro, but /rw.
1449+- user opened "/au/fileA".
1450+- he or someone else inserts a branch (/new) between /rw and /ro.
1451+ /au = /rw + /new + /ro
1452+- the new branch has "fileA".
1453+- user reads from the opened "fileA"
1454+- which filedata should aufs return, from /ro or /new?
1455+
1456+Some people says it has to be "from /ro" and it is a semantics of Unix.
1457+The others say it should be "from /new" because the file is not removed
1458+and it is equivalent to the case of someone else modifies the file.
1459+
1460+Here again I don't have a best and final answer. I got an idea to
1461+implement 'refrof' and 'norefrof' option. When 'refrof' (REFResh the
1462+Opened File) is specified (by default), aufs returns the filedata from
1463+/new.
1464+Otherwise from /new.
1465diff -urN /usr/share/empty/Documentation/filesystems/aufs/README linux/Documentation/filesystems/aufs/README
1466--- /usr/share/empty/Documentation/filesystems/aufs/README 1970-01-01 01:00:00.000000000 +0100
0c3ec466 1467+++ linux/Documentation/filesystems/aufs/README 2012-07-22 19:57:03.161004529 +0200
7eafdf33 1468@@ -0,0 +1,330 @@
53392da6
AM
1469+
1470+Aufs3 -- advanced multi layered unification filesystem version 3.x
1471+http://aufs.sf.net
1472+Junjiro R. Okajima
1473+
1474+
1475+0. Introduction
1476+----------------------------------------
1477+In the early days, aufs was entirely re-designed and re-implemented
1478+Unionfs Version 1.x series. After many original ideas, approaches,
1479+improvements and implementations, it becomes totally different from
1480+Unionfs while keeping the basic features.
1481+Recently, Unionfs Version 2.x series begin taking some of the same
1482+approaches to aufs1's.
1483+Unionfs is being developed by Professor Erez Zadok at Stony Brook
1484+University and his team.
1485+
1486+Aufs3 supports linux-3.0 and later.
1487+If you want older kernel version support, try aufs2-2.6.git or
1488+aufs2-standalone.git repository, aufs1 from CVS on SourceForge.
1489+
1490+Note: it becomes clear that "Aufs was rejected. Let's give it up."
1491+According to Christoph Hellwig, linux rejects all union-type filesystems
1492+but UnionMount.
1493+<http://marc.info/?l=linux-kernel&m=123938533724484&w=2>
1494+
1495+
1496+1. Features
1497+----------------------------------------
1498+- unite several directories into a single virtual filesystem. The member
1499+ directory is called as a branch.
1500+- you can specify the permission flags to the branch, which are 'readonly',
1501+ 'readwrite' and 'whiteout-able.'
1502+- by upper writable branch, internal copyup and whiteout, files/dirs on
1503+ readonly branch are modifiable logically.
1504+- dynamic branch manipulation, add, del.
1505+- etc...
1506+
1507+Also there are many enhancements in aufs1, such as:
1508+- readdir(3) in userspace.
1509+- keep inode number by external inode number table
1510+- keep the timestamps of file/dir in internal copyup operation
1511+- seekable directory, supporting NFS readdir.
1512+- whiteout is hardlinked in order to reduce the consumption of inodes
1513+ on branch
1514+- do not copyup, nor create a whiteout when it is unnecessary
1515+- revert a single systemcall when an error occurs in aufs
1516+- remount interface instead of ioctl
1517+- maintain /etc/mtab by an external command, /sbin/mount.aufs.
1518+- loopback mounted filesystem as a branch
1519+- kernel thread for removing the dir who has a plenty of whiteouts
1520+- support copyup sparse file (a file which has a 'hole' in it)
1521+- default permission flags for branches
1522+- selectable permission flags for ro branch, whether whiteout can
1523+ exist or not
1524+- export via NFS.
1525+- support <sysfs>/fs/aufs and <debugfs>/aufs.
1526+- support multiple writable branches, some policies to select one
1527+ among multiple writable branches.
1528+- a new semantics for link(2) and rename(2) to support multiple
1529+ writable branches.
1530+- no glibc changes are required.
1531+- pseudo hardlink (hardlink over branches)
1532+- allow a direct access manually to a file on branch, e.g. bypassing aufs.
1533+ including NFS or remote filesystem branch.
1534+- userspace wrapper for pathconf(3)/fpathconf(3) with _PC_LINK_MAX.
1535+- and more...
1536+
1537+Currently these features are dropped temporary from aufs3.
1538+See design/08plan.txt in detail.
1539+- test only the highest one for the directory permission (dirperm1)
1540+- copyup on open (coo=)
1541+- nested mount, i.e. aufs as readonly no-whiteout branch of another aufs
1542+ (robr)
1543+- statistics of aufs thread (/sys/fs/aufs/stat)
1544+- delegation mode (dlgt)
1545+ a delegation of the internal branch access to support task I/O
1546+ accounting, which also supports Linux Security Modules (LSM) mainly
1547+ for Suse AppArmor.
1548+- intent.open/create (file open in a single lookup)
1549+
1550+Features or just an idea in the future (see also design/*.txt),
1551+- reorder the branch index without del/re-add.
1552+- permanent xino files for NFSD
1553+- an option for refreshing the opened files after add/del branches
1554+- 'move' policy for copy-up between two writable branches, after
1555+ checking free space.
1556+- light version, without branch manipulation. (unnecessary?)
1557+- copyup in userspace
1558+- inotify in userspace
1559+- readv/writev
1560+- xattr, acl
1561+
1562+
1563+2. Download
1564+----------------------------------------
1e00d052
AM
1565+There were three GIT trees for aufs3, aufs3-linux.git,
1566+aufs3-standalone.git, and aufs-util.git. Note that there is no "3" in
1567+"aufs-util.git."
1568+While the aufs-util is always necessary, you need either of aufs3-linux
1569+or aufs3-standalone.
1570+
1571+The aufs3-linux tree includes the whole linux mainline GIT tree,
1572+git://git.kernel.org/.../torvalds/linux.git.
1573+And you cannot select CONFIG_AUFS_FS=m for this version, eg. you cannot
1574+build aufs3 as an externel kernel module.
1575+
1576+On the other hand, the aufs3-standalone tree has only aufs source files
53392da6
AM
1577+and necessary patches, and you can select CONFIG_AUFS_FS=m.
1578+
1579+You will find GIT branches whose name is in form of "aufs3.x" where "x"
1580+represents the linux kernel version, "linux-3.x". For instance,
1e00d052
AM
1581+"aufs3.0" is for linux-3.0. For latest "linux-3.x-rcN", use
1582+"aufs3.x-rcN" branch.
1583+
1584+o aufs3-linux tree
1585+$ git clone --reference /your/linux/git/tree \
1586+ git://aufs.git.sourceforge.net/gitroot/aufs/aufs3-linux.git \
1587+ aufs3-linux.git
1588+- if you don't have linux GIT tree, then remove "--reference ..."
1589+$ cd aufs3-linux.git
1590+$ git checkout origin/aufs3.0
53392da6
AM
1591+
1592+o aufs3-standalone tree
1593+$ git clone git://aufs.git.sourceforge.net/gitroot/aufs/aufs3-standalone.git \
1594+ aufs3-standalone.git
1595+$ cd aufs3-standalone.git
1596+$ git checkout origin/aufs3.0
1597+
1598+o aufs-util tree
1599+$ git clone git://aufs.git.sourceforge.net/gitroot/aufs/aufs-util.git \
1600+ aufs-util.git
1601+$ cd aufs-util.git
1602+$ git checkout origin/aufs3.0
1603+
9dbd164d
AM
1604+Note: The 3.x-rcN branch is to be used with `rc' kernel versions ONLY.
1605+The minor version number, 'x' in '3.x', of aufs may not always
1606+follow the minor version number of the kernel.
1607+Because changes in the kernel that cause the use of a new
1608+minor version number do not always require changes to aufs-util.
1609+
1610+Since aufs-util has its own minor version number, you may not be
1611+able to find a GIT branch in aufs-util for your kernel's
1612+exact minor version number.
1613+In this case, you should git-checkout the branch for the
53392da6 1614+nearest lower number.
9dbd164d
AM
1615+
1616+For (an unreleased) example:
1617+If you are using "linux-3.10" and the "aufs3.10" branch
7eafdf33 1618+does not exist in aufs-util repository, then "aufs3.9", "aufs3.8"
9dbd164d
AM
1619+or something numerically smaller is the branch for your kernel.
1620+
53392da6
AM
1621+Also you can view all branches by
1622+ $ git branch -a
1623+
1624+
1625+3. Configuration and Compilation
1626+----------------------------------------
1627+Make sure you have git-checkout'ed the correct branch.
1628+
1e00d052
AM
1629+For aufs3-linux tree,
1630+- enable CONFIG_EXPERIMENTAL and CONFIG_AUFS_FS.
1631+- set other aufs configurations if necessary.
1632+
53392da6
AM
1633+For aufs3-standalone tree,
1634+There are several ways to build.
1635+
1636+1.
1637+- apply ./aufs3-kbuild.patch to your kernel source files.
1638+- apply ./aufs3-base.patch too.
1639+- apply ./aufs3-proc_map.patch too, if you want to make /proc/PID/maps (and
1640+ others including lsof(1)) show the file path on aufs instead of the
1641+ path on the branch fs.
1642+- apply ./aufs3-standalone.patch too, if you have a plan to set
1643+ CONFIG_AUFS_FS=m. otherwise you don't need ./aufs3-standalone.patch.
1644+- copy ./{Documentation,fs,include/linux/aufs_type.h} files to your
1645+ kernel source tree. Never copy ./include/linux/Kbuild.
1646+- enable CONFIG_EXPERIMENTAL and CONFIG_AUFS_FS, you can select either
1647+ =m or =y.
1648+- and build your kernel as usual.
1649+- install the built kernel.
7eafdf33
AM
1650+- install the header files too by "make headers_install" to the
1651+ directory where you specify. By default, it is $PWD/usr.
53392da6
AM
1652+- and reboot your system.
1653+
1654+2.
1655+- module only (CONFIG_AUFS_FS=m).
1656+- apply ./aufs3-base.patch to your kernel source files.
1657+- apply ./aufs3-proc_map.patch too to your kernel source files,
1658+ if you want to make /proc/PID/maps (and others including lsof(1)) show
1659+ the file path on aufs instead of the path on the branch fs.
1660+- apply ./aufs3-standalone.patch too.
1661+- build your kernel, don't forget "make headers_install", and reboot.
1662+- edit ./config.mk and set other aufs configurations if necessary.
1663+ Note: You should read ./fs/aufs/Kconfig carefully which describes
1664+ every aufs configurations.
1665+- build the module by simple "make".
1666+- you can specify ${KDIR} make variable which points to your kernel
1667+ source tree.
1668+- install the files
1669+ + run "make install" to install the aufs module, or copy the built
1670+ ./aufs.ko to /lib/modules/... and run depmod -a (or reboot simply).
1671+ + run "make headers_install" to install the aufs header file (you can
1672+ specify DESTDIR), or copty ./usr/include/linux/aufs_type.h to
7eafdf33
AM
1673+ /usr/include/linux or wherever you like. By default, the target
1674+ directory is $PWD/usr.
53392da6
AM
1675+- no need to apply aufs3-kbuild.patch, nor copying source files to your
1676+ kernel source tree.
1677+
1678+Note: The haeder file aufs_type.h is necessary to build aufs-util
1679+ as well as "make headers_install" in the kernel source tree.
1680+ headers_install is subject to be forgotten, but it is essentially
1681+ necessary, not only for building aufs-util.
1682+ You may not meet problems without headers_install in some older
1683+ version though.
1684+
1685+And then,
1686+- read README in aufs-util, build and install it
9dbd164d
AM
1687+- note that your distribution may contain an obsoleted version of
1688+ aufs_type.h in /usr/include/linux or something. When you build aufs
1689+ utilities, make sure that your compiler refers the correct aufs header
1690+ file which is built by "make headers_install."
53392da6
AM
1691+- if you want to use readdir(3) in userspace or pathconf(3) wrapper,
1692+ then run "make install_ulib" too. And refer to the aufs manual in
1693+ detail.
1694+
1695+
1696+4. Usage
1697+----------------------------------------
1698+At first, make sure aufs-util are installed, and please read the aufs
1699+manual, aufs.5 in aufs-util.git tree.
1700+$ man -l aufs.5
1701+
1702+And then,
1703+$ mkdir /tmp/rw /tmp/aufs
1704+# mount -t aufs -o br=/tmp/rw:${HOME} none /tmp/aufs
1705+
1706+Here is another example. The result is equivalent.
1707+# mount -t aufs -o br=/tmp/rw=rw:${HOME}=ro none /tmp/aufs
1708+ Or
1709+# mount -t aufs -o br:/tmp/rw none /tmp/aufs
1710+# mount -o remount,append:${HOME} /tmp/aufs
1711+
1712+Then, you can see whole tree of your home dir through /tmp/aufs. If
1713+you modify a file under /tmp/aufs, the one on your home directory is
1714+not affected, instead the same named file will be newly created under
1715+/tmp/rw. And all of your modification to a file will be applied to
1716+the one under /tmp/rw. This is called the file based Copy on Write
1717+(COW) method.
1718+Aufs mount options are described in aufs.5.
1719+If you run chroot or something and make your aufs as a root directory,
1720+then you need to customize the shutdown script. See the aufs manual in
1721+detail.
1722+
1723+Additionally, there are some sample usages of aufs which are a
1724+diskless system with network booting, and LiveCD over NFS.
1725+See sample dir in CVS tree on SourceForge.
1726+
1727+
1728+5. Contact
1729+----------------------------------------
1730+When you have any problems or strange behaviour in aufs, please let me
1731+know with:
1732+- /proc/mounts (instead of the output of mount(8))
1733+- /sys/module/aufs/*
1734+- /sys/fs/aufs/* (if you have them)
1735+- /debug/aufs/* (if you have them)
1736+- linux kernel version
1737+ if your kernel is not plain, for example modified by distributor,
1738+ the url where i can download its source is necessary too.
1739+- aufs version which was printed at loading the module or booting the
1740+ system, instead of the date you downloaded.
1741+- configuration (define/undefine CONFIG_AUFS_xxx)
1742+- kernel configuration or /proc/config.gz (if you have it)
1743+- behaviour which you think to be incorrect
1744+- actual operation, reproducible one is better
1745+- mailto: aufs-users at lists.sourceforge.net
1746+
1747+Usually, I don't watch the Public Areas(Bugs, Support Requests, Patches,
1748+and Feature Requests) on SourceForge. Please join and write to
1749+aufs-users ML.
1750+
1751+
1752+6. Acknowledgements
1753+----------------------------------------
1754+Thanks to everyone who have tried and are using aufs, whoever
1755+have reported a bug or any feedback.
1756+
1757+Especially donators:
1758+Tomas Matejicek(slax.org) made a donation (much more than once).
1759+ Since Apr 2010, Tomas M (the author of Slax and Linux Live
1760+ scripts) is making "doubling" donations.
1761+ Unfortunately I cannot list all of the donators, but I really
1762+ appriciate.
1763+ It ends Aug 2010, but the ordinary donation URL is still available.
1764+ <http://sourceforge.net/donate/index.php?group_id=167503>
1765+Dai Itasaka made a donation (2007/8).
1766+Chuck Smith made a donation (2008/4, 10 and 12).
1767+Henk Schoneveld made a donation (2008/9).
1768+Chih-Wei Huang, ASUS, CTC donated Eee PC 4G (2008/10).
1769+Francois Dupoux made a donation (2008/11).
1770+Bruno Cesar Ribas and Luis Carlos Erpen de Bona, C3SL serves public
1771+ aufs2 GIT tree (2009/2).
1772+William Grant made a donation (2009/3).
1773+Patrick Lane made a donation (2009/4).
1774+The Mail Archive (mail-archive.com) made donations (2009/5).
1775+Nippy Networks (Ed Wildgoose) made a donation (2009/7).
1776+New Dream Network, LLC (www.dreamhost.com) made a donation (2009/11).
1777+Pavel Pronskiy made a donation (2011/2).
1778+Iridium and Inmarsat satellite phone retailer (www.mailasail.com), Nippy
1779+ Networks (Ed Wildgoose) made a donation for hardware (2011/3).
92d182d2 1780+Max Lekomcev (DOM-TV project) made a donation (2011/7, 12 and 2012/3).
1e00d052 1781+Sam Liddicott made a donation (2011/9).
53392da6
AM
1782+
1783+Thank you very much.
1784+Donations are always, including future donations, very important and
1785+helpful for me to keep on developing aufs.
1786+
1787+
1788+7.
1789+----------------------------------------
1790+If you are an experienced user, no explanation is needed. Aufs is
1791+just a linux filesystem.
1792+
1793+
1794+Enjoy!
1795+
1796+# Local variables: ;
1797+# mode: text;
1798+# End: ;
7f207e10
AM
1799diff -urN /usr/share/empty/fs/aufs/aufs.h linux/fs/aufs/aufs.h
1800--- /usr/share/empty/fs/aufs/aufs.h 1970-01-01 01:00:00.000000000 +0100
0c3ec466 1801+++ linux/fs/aufs/aufs.h 2012-07-22 19:57:03.161004531 +0200
2cbb1c4b 1802@@ -0,0 +1,60 @@
7f207e10 1803+/*
f6c5ef8b 1804+ * Copyright (C) 2005-2012 Junjiro R. Okajima
7f207e10
AM
1805+ *
1806+ * This program, aufs is free software; you can redistribute it and/or modify
1807+ * it under the terms of the GNU General Public License as published by
1808+ * the Free Software Foundation; either version 2 of the License, or
1809+ * (at your option) any later version.
1810+ *
1811+ * This program is distributed in the hope that it will be useful,
1812+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1813+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1814+ * GNU General Public License for more details.
1815+ *
1816+ * You should have received a copy of the GNU General Public License
1817+ * along with this program; if not, write to the Free Software
1818+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1819+ */
1820+
1821+/*
1822+ * all header files
1823+ */
1824+
1825+#ifndef __AUFS_H__
1826+#define __AUFS_H__
1827+
1828+#ifdef __KERNEL__
1829+
1830+#define AuStub(type, name, body, ...) \
1831+ static inline type name(__VA_ARGS__) { body; }
1832+
1833+#define AuStubVoid(name, ...) \
1834+ AuStub(void, name, , __VA_ARGS__)
1835+#define AuStubInt0(name, ...) \
1836+ AuStub(int, name, return 0, __VA_ARGS__)
1837+
1838+#include "debug.h"
1839+
1840+#include "branch.h"
1841+#include "cpup.h"
1842+#include "dcsub.h"
1843+#include "dbgaufs.h"
1844+#include "dentry.h"
1845+#include "dir.h"
1846+#include "dynop.h"
1847+#include "file.h"
1848+#include "fstype.h"
1849+#include "inode.h"
1850+#include "loop.h"
1851+#include "module.h"
7f207e10
AM
1852+#include "opts.h"
1853+#include "rwsem.h"
1854+#include "spl.h"
1855+#include "super.h"
1856+#include "sysaufs.h"
1857+#include "vfsub.h"
1858+#include "whout.h"
1859+#include "wkq.h"
1860+
1861+#endif /* __KERNEL__ */
1862+#endif /* __AUFS_H__ */
1863diff -urN /usr/share/empty/fs/aufs/branch.c linux/fs/aufs/branch.c
1864--- /usr/share/empty/fs/aufs/branch.c 1970-01-01 01:00:00.000000000 +0100
0c3ec466 1865+++ linux/fs/aufs/branch.c 2012-07-22 19:57:03.161004531 +0200
f6c5ef8b 1866@@ -0,0 +1,1169 @@
7f207e10 1867+/*
f6c5ef8b 1868+ * Copyright (C) 2005-2012 Junjiro R. Okajima
7f207e10
AM
1869+ *
1870+ * This program, aufs is free software; you can redistribute it and/or modify
1871+ * it under the terms of the GNU General Public License as published by
1872+ * the Free Software Foundation; either version 2 of the License, or
1873+ * (at your option) any later version.
1874+ *
1875+ * This program is distributed in the hope that it will be useful,
1876+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1877+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1878+ * GNU General Public License for more details.
1879+ *
1880+ * You should have received a copy of the GNU General Public License
1881+ * along with this program; if not, write to the Free Software
1882+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1883+ */
1884+
1885+/*
1886+ * branch management
1887+ */
1888+
027c5e7a 1889+#include <linux/compat.h>
7f207e10
AM
1890+#include <linux/statfs.h>
1891+#include "aufs.h"
1892+
1893+/*
1894+ * free a single branch
1facf9fc 1895+ */
1896+static void au_br_do_free(struct au_branch *br)
1897+{
1898+ int i;
1899+ struct au_wbr *wbr;
4a4d8108 1900+ struct au_dykey **key;
1facf9fc 1901+
027c5e7a
AM
1902+ au_hnotify_fin_br(br);
1903+
1facf9fc 1904+ if (br->br_xino.xi_file)
1905+ fput(br->br_xino.xi_file);
1906+ mutex_destroy(&br->br_xino.xi_nondir_mtx);
1907+
1908+ AuDebugOn(atomic_read(&br->br_count));
1909+
1910+ wbr = br->br_wbr;
1911+ if (wbr) {
1912+ for (i = 0; i < AuBrWh_Last; i++)
1913+ dput(wbr->wbr_wh[i]);
1914+ AuDebugOn(atomic_read(&wbr->wbr_wh_running));
dece6358 1915+ AuRwDestroy(&wbr->wbr_wh_rwsem);
1facf9fc 1916+ }
1917+
4a4d8108
AM
1918+ key = br->br_dykey;
1919+ for (i = 0; i < AuBrDynOp; i++, key++)
1920+ if (*key)
1921+ au_dy_put(*key);
1922+ else
1923+ break;
1924+
1facf9fc 1925+ mntput(br->br_mnt);
1facf9fc 1926+ kfree(wbr);
1927+ kfree(br);
1928+}
1929+
1930+/*
1931+ * frees all branches
1932+ */
1933+void au_br_free(struct au_sbinfo *sbinfo)
1934+{
1935+ aufs_bindex_t bmax;
1936+ struct au_branch **br;
1937+
dece6358
AM
1938+ AuRwMustWriteLock(&sbinfo->si_rwsem);
1939+
1facf9fc 1940+ bmax = sbinfo->si_bend + 1;
1941+ br = sbinfo->si_branch;
1942+ while (bmax--)
1943+ au_br_do_free(*br++);
1944+}
1945+
1946+/*
1947+ * find the index of a branch which is specified by @br_id.
1948+ */
1949+int au_br_index(struct super_block *sb, aufs_bindex_t br_id)
1950+{
1951+ aufs_bindex_t bindex, bend;
1952+
1953+ bend = au_sbend(sb);
1954+ for (bindex = 0; bindex <= bend; bindex++)
1955+ if (au_sbr_id(sb, bindex) == br_id)
1956+ return bindex;
1957+ return -1;
1958+}
1959+
1960+/* ---------------------------------------------------------------------- */
1961+
1962+/*
1963+ * add a branch
1964+ */
1965+
b752ccd1
AM
1966+static int test_overlap(struct super_block *sb, struct dentry *h_adding,
1967+ struct dentry *h_root)
1facf9fc 1968+{
b752ccd1
AM
1969+ if (unlikely(h_adding == h_root
1970+ || au_test_loopback_overlap(sb, h_adding)))
1facf9fc 1971+ return 1;
b752ccd1
AM
1972+ if (h_adding->d_sb != h_root->d_sb)
1973+ return 0;
1974+ return au_test_subdir(h_adding, h_root)
1975+ || au_test_subdir(h_root, h_adding);
1facf9fc 1976+}
1977+
1978+/*
1979+ * returns a newly allocated branch. @new_nbranch is a number of branches
1980+ * after adding a branch.
1981+ */
1982+static struct au_branch *au_br_alloc(struct super_block *sb, int new_nbranch,
1983+ int perm)
1984+{
1985+ struct au_branch *add_branch;
1986+ struct dentry *root;
4a4d8108 1987+ int err;
1facf9fc 1988+
4a4d8108 1989+ err = -ENOMEM;
1facf9fc 1990+ root = sb->s_root;
1991+ add_branch = kmalloc(sizeof(*add_branch), GFP_NOFS);
1992+ if (unlikely(!add_branch))
1993+ goto out;
1994+
027c5e7a
AM
1995+ err = au_hnotify_init_br(add_branch, perm);
1996+ if (unlikely(err))
1997+ goto out_br;
1998+
1facf9fc 1999+ add_branch->br_wbr = NULL;
2000+ if (au_br_writable(perm)) {
2001+ /* may be freed separately at changing the branch permission */
2002+ add_branch->br_wbr = kmalloc(sizeof(*add_branch->br_wbr),
2003+ GFP_NOFS);
2004+ if (unlikely(!add_branch->br_wbr))
027c5e7a 2005+ goto out_hnotify;
1facf9fc 2006+ }
2007+
4a4d8108
AM
2008+ err = au_sbr_realloc(au_sbi(sb), new_nbranch);
2009+ if (!err)
2010+ err = au_di_realloc(au_di(root), new_nbranch);
2011+ if (!err)
2012+ err = au_ii_realloc(au_ii(root->d_inode), new_nbranch);
2013+ if (!err)
2014+ return add_branch; /* success */
1facf9fc 2015+
1facf9fc 2016+ kfree(add_branch->br_wbr);
4a4d8108 2017+
027c5e7a
AM
2018+out_hnotify:
2019+ au_hnotify_fin_br(add_branch);
4f0767ce 2020+out_br:
1facf9fc 2021+ kfree(add_branch);
4f0767ce 2022+out:
4a4d8108 2023+ return ERR_PTR(err);
1facf9fc 2024+}
2025+
2026+/*
2027+ * test if the branch permission is legal or not.
2028+ */
2029+static int test_br(struct inode *inode, int brperm, char *path)
2030+{
2031+ int err;
2032+
4a4d8108
AM
2033+ err = (au_br_writable(brperm) && IS_RDONLY(inode));
2034+ if (!err)
2035+ goto out;
1facf9fc 2036+
4a4d8108
AM
2037+ err = -EINVAL;
2038+ pr_err("write permission for readonly mount or inode, %s\n", path);
2039+
4f0767ce 2040+out:
1facf9fc 2041+ return err;
2042+}
2043+
2044+/*
2045+ * returns:
2046+ * 0: success, the caller will add it
2047+ * plus: success, it is already unified, the caller should ignore it
2048+ * minus: error
2049+ */
2050+static int test_add(struct super_block *sb, struct au_opt_add *add, int remount)
2051+{
2052+ int err;
2053+ aufs_bindex_t bend, bindex;
2054+ struct dentry *root;
2055+ struct inode *inode, *h_inode;
2056+
2057+ root = sb->s_root;
2058+ bend = au_sbend(sb);
2059+ if (unlikely(bend >= 0
2060+ && au_find_dbindex(root, add->path.dentry) >= 0)) {
2061+ err = 1;
2062+ if (!remount) {
2063+ err = -EINVAL;
4a4d8108 2064+ pr_err("%s duplicated\n", add->pathname);
1facf9fc 2065+ }
2066+ goto out;
2067+ }
2068+
2069+ err = -ENOSPC; /* -E2BIG; */
2070+ if (unlikely(AUFS_BRANCH_MAX <= add->bindex
2071+ || AUFS_BRANCH_MAX - 1 <= bend)) {
4a4d8108 2072+ pr_err("number of branches exceeded %s\n", add->pathname);
1facf9fc 2073+ goto out;
2074+ }
2075+
2076+ err = -EDOM;
2077+ if (unlikely(add->bindex < 0 || bend + 1 < add->bindex)) {
4a4d8108 2078+ pr_err("bad index %d\n", add->bindex);
1facf9fc 2079+ goto out;
2080+ }
2081+
2082+ inode = add->path.dentry->d_inode;
2083+ err = -ENOENT;
2084+ if (unlikely(!inode->i_nlink)) {
4a4d8108 2085+ pr_err("no existence %s\n", add->pathname);
1facf9fc 2086+ goto out;
2087+ }
2088+
2089+ err = -EINVAL;
2090+ if (unlikely(inode->i_sb == sb)) {
4a4d8108 2091+ pr_err("%s must be outside\n", add->pathname);
1facf9fc 2092+ goto out;
2093+ }
2094+
2095+ if (unlikely(au_test_fs_unsuppoted(inode->i_sb))) {
4a4d8108
AM
2096+ pr_err("unsupported filesystem, %s (%s)\n",
2097+ add->pathname, au_sbtype(inode->i_sb));
1facf9fc 2098+ goto out;
2099+ }
2100+
2101+ err = test_br(add->path.dentry->d_inode, add->perm, add->pathname);
2102+ if (unlikely(err))
2103+ goto out;
2104+
2105+ if (bend < 0)
2106+ return 0; /* success */
2107+
2108+ err = -EINVAL;
2109+ for (bindex = 0; bindex <= bend; bindex++)
2110+ if (unlikely(test_overlap(sb, add->path.dentry,
2111+ au_h_dptr(root, bindex)))) {
4a4d8108 2112+ pr_err("%s is overlapped\n", add->pathname);
1facf9fc 2113+ goto out;
2114+ }
2115+
2116+ err = 0;
2117+ if (au_opt_test(au_mntflags(sb), WARN_PERM)) {
2118+ h_inode = au_h_dptr(root, 0)->d_inode;
2119+ if ((h_inode->i_mode & S_IALLUGO) != (inode->i_mode & S_IALLUGO)
0c3ec466
AM
2120+ || !uid_eq(h_inode->i_uid, inode->i_uid)
2121+ || !gid_eq(h_inode->i_gid, inode->i_gid))
2122+ pr_warn("uid/gid/perm %s %u/%u/0%o, %u/%u/0%o\n",
2123+ add->pathname,
2124+ i_uid_read(inode), i_gid_read(inode),
2125+ (inode->i_mode & S_IALLUGO),
2126+ i_uid_read(h_inode), i_gid_read(h_inode),
2127+ (h_inode->i_mode & S_IALLUGO));
1facf9fc 2128+ }
2129+
4f0767ce 2130+out:
1facf9fc 2131+ return err;
2132+}
2133+
2134+/*
2135+ * initialize or clean the whiteouts for an adding branch
2136+ */
2137+static int au_br_init_wh(struct super_block *sb, struct au_branch *br,
2138+ int new_perm, struct dentry *h_root)
2139+{
2140+ int err, old_perm;
2141+ aufs_bindex_t bindex;
2142+ struct mutex *h_mtx;
2143+ struct au_wbr *wbr;
2144+ struct au_hinode *hdir;
2145+
2146+ wbr = br->br_wbr;
2147+ old_perm = br->br_perm;
2148+ br->br_perm = new_perm;
2149+ hdir = NULL;
2150+ h_mtx = NULL;
2151+ bindex = au_br_index(sb, br->br_id);
2152+ if (0 <= bindex) {
2153+ hdir = au_hi(sb->s_root->d_inode, bindex);
4a4d8108 2154+ au_hn_imtx_lock_nested(hdir, AuLsc_I_PARENT);
1facf9fc 2155+ } else {
2156+ h_mtx = &h_root->d_inode->i_mutex;
2157+ mutex_lock_nested(h_mtx, AuLsc_I_PARENT);
2158+ }
2159+ if (!wbr)
2160+ err = au_wh_init(h_root, br, sb);
2161+ else {
2162+ wbr_wh_write_lock(wbr);
2163+ err = au_wh_init(h_root, br, sb);
2164+ wbr_wh_write_unlock(wbr);
2165+ }
2166+ if (hdir)
4a4d8108 2167+ au_hn_imtx_unlock(hdir);
1facf9fc 2168+ else
2169+ mutex_unlock(h_mtx);
2170+ br->br_perm = old_perm;
2171+
2172+ if (!err && wbr && !au_br_writable(new_perm)) {
2173+ kfree(wbr);
2174+ br->br_wbr = NULL;
2175+ }
2176+
2177+ return err;
2178+}
2179+
2180+static int au_wbr_init(struct au_branch *br, struct super_block *sb,
2181+ int perm, struct path *path)
2182+{
2183+ int err;
4a4d8108 2184+ struct kstatfs kst;
1facf9fc 2185+ struct au_wbr *wbr;
4a4d8108 2186+ struct dentry *h_dentry;
1facf9fc 2187+
2188+ wbr = br->br_wbr;
dece6358 2189+ au_rw_init(&wbr->wbr_wh_rwsem);
1facf9fc 2190+ memset(wbr->wbr_wh, 0, sizeof(wbr->wbr_wh));
2191+ atomic_set(&wbr->wbr_wh_running, 0);
2192+ wbr->wbr_bytes = 0;
2193+
4a4d8108
AM
2194+ /*
2195+ * a limit for rmdir/rename a dir
2196+ * cf. AUFS_MAX_NAMELEN in include/linux/aufs_type.h
2197+ */
7f207e10 2198+ err = vfs_statfs(path, &kst);
4a4d8108
AM
2199+ if (unlikely(err))
2200+ goto out;
2201+ err = -EINVAL;
7f207e10 2202+ h_dentry = path->dentry;
4a4d8108
AM
2203+ if (kst.f_namelen >= NAME_MAX)
2204+ err = au_br_init_wh(sb, br, perm, h_dentry);
2205+ else
2206+ pr_err("%.*s(%s), unsupported namelen %ld\n",
2207+ AuDLNPair(h_dentry), au_sbtype(h_dentry->d_sb),
2208+ kst.f_namelen);
1facf9fc 2209+
4f0767ce 2210+out:
1facf9fc 2211+ return err;
2212+}
2213+
2214+/* intialize a new branch */
2215+static int au_br_init(struct au_branch *br, struct super_block *sb,
2216+ struct au_opt_add *add)
2217+{
2218+ int err;
2219+
2220+ err = 0;
2221+ memset(&br->br_xino, 0, sizeof(br->br_xino));
2222+ mutex_init(&br->br_xino.xi_nondir_mtx);
2223+ br->br_perm = add->perm;
2224+ br->br_mnt = add->path.mnt; /* set first, mntget() later */
4a4d8108
AM
2225+ spin_lock_init(&br->br_dykey_lock);
2226+ memset(br->br_dykey, 0, sizeof(br->br_dykey));
1facf9fc 2227+ atomic_set(&br->br_count, 0);
2228+ br->br_xino_upper = AUFS_XINO_TRUNC_INIT;
2229+ atomic_set(&br->br_xino_running, 0);
2230+ br->br_id = au_new_br_id(sb);
7f207e10 2231+ AuDebugOn(br->br_id < 0);
1facf9fc 2232+
2233+ if (au_br_writable(add->perm)) {
2234+ err = au_wbr_init(br, sb, add->perm, &add->path);
2235+ if (unlikely(err))
b752ccd1 2236+ goto out_err;
1facf9fc 2237+ }
2238+
2239+ if (au_opt_test(au_mntflags(sb), XINO)) {
2240+ err = au_xino_br(sb, br, add->path.dentry->d_inode->i_ino,
2241+ au_sbr(sb, 0)->br_xino.xi_file, /*do_test*/1);
2242+ if (unlikely(err)) {
2243+ AuDebugOn(br->br_xino.xi_file);
b752ccd1 2244+ goto out_err;
1facf9fc 2245+ }
2246+ }
2247+
2248+ sysaufs_br_init(br);
2249+ mntget(add->path.mnt);
b752ccd1 2250+ goto out; /* success */
1facf9fc 2251+
4f0767ce 2252+out_err:
b752ccd1 2253+ br->br_mnt = NULL;
4f0767ce 2254+out:
1facf9fc 2255+ return err;
2256+}
2257+
2258+static void au_br_do_add_brp(struct au_sbinfo *sbinfo, aufs_bindex_t bindex,
2259+ struct au_branch *br, aufs_bindex_t bend,
2260+ aufs_bindex_t amount)
2261+{
2262+ struct au_branch **brp;
2263+
dece6358
AM
2264+ AuRwMustWriteLock(&sbinfo->si_rwsem);
2265+
1facf9fc 2266+ brp = sbinfo->si_branch + bindex;
2267+ memmove(brp + 1, brp, sizeof(*brp) * amount);
2268+ *brp = br;
2269+ sbinfo->si_bend++;
2270+ if (unlikely(bend < 0))
2271+ sbinfo->si_bend = 0;
2272+}
2273+
2274+static void au_br_do_add_hdp(struct au_dinfo *dinfo, aufs_bindex_t bindex,
2275+ aufs_bindex_t bend, aufs_bindex_t amount)
2276+{
2277+ struct au_hdentry *hdp;
2278+
1308ab2a 2279+ AuRwMustWriteLock(&dinfo->di_rwsem);
2280+
1facf9fc 2281+ hdp = dinfo->di_hdentry + bindex;
2282+ memmove(hdp + 1, hdp, sizeof(*hdp) * amount);
2283+ au_h_dentry_init(hdp);
2284+ dinfo->di_bend++;
2285+ if (unlikely(bend < 0))
2286+ dinfo->di_bstart = 0;
2287+}
2288+
2289+static void au_br_do_add_hip(struct au_iinfo *iinfo, aufs_bindex_t bindex,
2290+ aufs_bindex_t bend, aufs_bindex_t amount)
2291+{
2292+ struct au_hinode *hip;
2293+
1308ab2a 2294+ AuRwMustWriteLock(&iinfo->ii_rwsem);
2295+
1facf9fc 2296+ hip = iinfo->ii_hinode + bindex;
2297+ memmove(hip + 1, hip, sizeof(*hip) * amount);
2298+ hip->hi_inode = NULL;
4a4d8108 2299+ au_hn_init(hip);
1facf9fc 2300+ iinfo->ii_bend++;
2301+ if (unlikely(bend < 0))
2302+ iinfo->ii_bstart = 0;
2303+}
2304+
2305+static void au_br_do_add(struct super_block *sb, struct dentry *h_dentry,
2306+ struct au_branch *br, aufs_bindex_t bindex)
2307+{
2308+ struct dentry *root;
2309+ struct inode *root_inode;
2310+ aufs_bindex_t bend, amount;
2311+
2312+ root = sb->s_root;
2313+ root_inode = root->d_inode;
1facf9fc 2314+ bend = au_sbend(sb);
2315+ amount = bend + 1 - bindex;
53392da6 2316+ au_sbilist_lock();
1facf9fc 2317+ au_br_do_add_brp(au_sbi(sb), bindex, br, bend, amount);
2318+ au_br_do_add_hdp(au_di(root), bindex, bend, amount);
2319+ au_br_do_add_hip(au_ii(root_inode), bindex, bend, amount);
2320+ au_set_h_dptr(root, bindex, dget(h_dentry));
2321+ au_set_h_iptr(root_inode, bindex, au_igrab(h_dentry->d_inode),
2322+ /*flags*/0);
53392da6 2323+ au_sbilist_unlock();
1facf9fc 2324+}
2325+
2326+int au_br_add(struct super_block *sb, struct au_opt_add *add, int remount)
2327+{
2328+ int err;
1facf9fc 2329+ aufs_bindex_t bend, add_bindex;
2330+ struct dentry *root, *h_dentry;
2331+ struct inode *root_inode;
2332+ struct au_branch *add_branch;
2333+
2334+ root = sb->s_root;
2335+ root_inode = root->d_inode;
2336+ IMustLock(root_inode);
2337+ err = test_add(sb, add, remount);
2338+ if (unlikely(err < 0))
2339+ goto out;
2340+ if (err) {
2341+ err = 0;
2342+ goto out; /* success */
2343+ }
2344+
2345+ bend = au_sbend(sb);
2346+ add_branch = au_br_alloc(sb, bend + 2, add->perm);
2347+ err = PTR_ERR(add_branch);
2348+ if (IS_ERR(add_branch))
2349+ goto out;
2350+
2351+ err = au_br_init(add_branch, sb, add);
2352+ if (unlikely(err)) {
2353+ au_br_do_free(add_branch);
2354+ goto out;
2355+ }
2356+
2357+ add_bindex = add->bindex;
2358+ h_dentry = add->path.dentry;
2359+ if (!remount)
2360+ au_br_do_add(sb, h_dentry, add_branch, add_bindex);
2361+ else {
2362+ sysaufs_brs_del(sb, add_bindex);
2363+ au_br_do_add(sb, h_dentry, add_branch, add_bindex);
2364+ sysaufs_brs_add(sb, add_bindex);
2365+ }
2366+
1308ab2a 2367+ if (!add_bindex) {
1facf9fc 2368+ au_cpup_attr_all(root_inode, /*force*/1);
1308ab2a 2369+ sb->s_maxbytes = h_dentry->d_sb->s_maxbytes;
2370+ } else
1facf9fc 2371+ au_add_nlink(root_inode, h_dentry->d_inode);
1facf9fc 2372+
2373+ /*
4a4d8108 2374+ * this test/set prevents aufs from handling unnecesary notify events
027c5e7a 2375+ * of xino files, in case of re-adding a writable branch which was
1facf9fc 2376+ * once detached from aufs.
2377+ */
2378+ if (au_xino_brid(sb) < 0
2379+ && au_br_writable(add_branch->br_perm)
2380+ && !au_test_fs_bad_xino(h_dentry->d_sb)
2381+ && add_branch->br_xino.xi_file
2382+ && add_branch->br_xino.xi_file->f_dentry->d_parent == h_dentry)
2383+ au_xino_brid_set(sb, add_branch->br_id);
2384+
4f0767ce 2385+out:
1facf9fc 2386+ return err;
2387+}
2388+
2389+/* ---------------------------------------------------------------------- */
2390+
2391+/*
2392+ * delete a branch
2393+ */
2394+
2395+/* to show the line number, do not make it inlined function */
4a4d8108 2396+#define AuVerbose(do_info, fmt, ...) do { \
1facf9fc 2397+ if (do_info) \
4a4d8108 2398+ pr_info(fmt, ##__VA_ARGS__); \
1facf9fc 2399+} while (0)
2400+
027c5e7a
AM
2401+static int au_test_ibusy(struct inode *inode, aufs_bindex_t bstart,
2402+ aufs_bindex_t bend)
2403+{
2404+ return (inode && !S_ISDIR(inode->i_mode)) || bstart == bend;
2405+}
2406+
2407+static int au_test_dbusy(struct dentry *dentry, aufs_bindex_t bstart,
2408+ aufs_bindex_t bend)
2409+{
2410+ return au_test_ibusy(dentry->d_inode, bstart, bend);
2411+}
2412+
1facf9fc 2413+/*
2414+ * test if the branch is deletable or not.
2415+ */
2416+static int test_dentry_busy(struct dentry *root, aufs_bindex_t bindex,
b752ccd1 2417+ unsigned int sigen, const unsigned int verbose)
1facf9fc 2418+{
2419+ int err, i, j, ndentry;
2420+ aufs_bindex_t bstart, bend;
1facf9fc 2421+ struct au_dcsub_pages dpages;
2422+ struct au_dpage *dpage;
2423+ struct dentry *d;
1facf9fc 2424+
2425+ err = au_dpages_init(&dpages, GFP_NOFS);
2426+ if (unlikely(err))
2427+ goto out;
2428+ err = au_dcsub_pages(&dpages, root, NULL, NULL);
2429+ if (unlikely(err))
2430+ goto out_dpages;
2431+
1facf9fc 2432+ for (i = 0; !err && i < dpages.ndpage; i++) {
2433+ dpage = dpages.dpages + i;
2434+ ndentry = dpage->ndentry;
2435+ for (j = 0; !err && j < ndentry; j++) {
2436+ d = dpage->dentries[j];
027c5e7a
AM
2437+ AuDebugOn(!d->d_count);
2438+ if (!au_digen_test(d, sigen)) {
1facf9fc 2439+ di_read_lock_child(d, AuLock_IR);
027c5e7a
AM
2440+ if (unlikely(au_dbrange_test(d))) {
2441+ di_read_unlock(d, AuLock_IR);
2442+ continue;
2443+ }
2444+ } else {
1facf9fc 2445+ di_write_lock_child(d);
027c5e7a
AM
2446+ if (unlikely(au_dbrange_test(d))) {
2447+ di_write_unlock(d);
2448+ continue;
2449+ }
1facf9fc 2450+ err = au_reval_dpath(d, sigen);
2451+ if (!err)
2452+ di_downgrade_lock(d, AuLock_IR);
2453+ else {
2454+ di_write_unlock(d);
2455+ break;
2456+ }
2457+ }
2458+
027c5e7a 2459+ /* AuDbgDentry(d); */
1facf9fc 2460+ bstart = au_dbstart(d);
2461+ bend = au_dbend(d);
2462+ if (bstart <= bindex
2463+ && bindex <= bend
2464+ && au_h_dptr(d, bindex)
027c5e7a 2465+ && au_test_dbusy(d, bstart, bend)) {
1facf9fc 2466+ err = -EBUSY;
2467+ AuVerbose(verbose, "busy %.*s\n", AuDLNPair(d));
027c5e7a 2468+ AuDbgDentry(d);
1facf9fc 2469+ }
2470+ di_read_unlock(d, AuLock_IR);
2471+ }
2472+ }
2473+
4f0767ce 2474+out_dpages:
1facf9fc 2475+ au_dpages_free(&dpages);
4f0767ce 2476+out:
1facf9fc 2477+ return err;
2478+}
2479+
2480+static int test_inode_busy(struct super_block *sb, aufs_bindex_t bindex,
b752ccd1 2481+ unsigned int sigen, const unsigned int verbose)
1facf9fc 2482+{
2483+ int err;
7f207e10
AM
2484+ unsigned long long max, ull;
2485+ struct inode *i, **array;
1facf9fc 2486+ aufs_bindex_t bstart, bend;
1facf9fc 2487+
7f207e10
AM
2488+ array = au_iarray_alloc(sb, &max);
2489+ err = PTR_ERR(array);
2490+ if (IS_ERR(array))
2491+ goto out;
2492+
1facf9fc 2493+ err = 0;
7f207e10
AM
2494+ AuDbg("b%d\n", bindex);
2495+ for (ull = 0; !err && ull < max; ull++) {
2496+ i = array[ull];
2497+ if (i->i_ino == AUFS_ROOT_INO)
1facf9fc 2498+ continue;
2499+
7f207e10 2500+ /* AuDbgInode(i); */
1facf9fc 2501+ if (au_iigen(i) == sigen)
2502+ ii_read_lock_child(i);
2503+ else {
2504+ ii_write_lock_child(i);
027c5e7a
AM
2505+ err = au_refresh_hinode_self(i);
2506+ au_iigen_dec(i);
1facf9fc 2507+ if (!err)
2508+ ii_downgrade_lock(i);
2509+ else {
2510+ ii_write_unlock(i);
2511+ break;
2512+ }
2513+ }
2514+
2515+ bstart = au_ibstart(i);
2516+ bend = au_ibend(i);
2517+ if (bstart <= bindex
2518+ && bindex <= bend
2519+ && au_h_iptr(i, bindex)
027c5e7a 2520+ && au_test_ibusy(i, bstart, bend)) {
1facf9fc 2521+ err = -EBUSY;
2522+ AuVerbose(verbose, "busy i%lu\n", i->i_ino);
7f207e10 2523+ AuDbgInode(i);
1facf9fc 2524+ }
2525+ ii_read_unlock(i);
2526+ }
7f207e10 2527+ au_iarray_free(array, max);
1facf9fc 2528+
7f207e10 2529+out:
1facf9fc 2530+ return err;
2531+}
2532+
b752ccd1
AM
2533+static int test_children_busy(struct dentry *root, aufs_bindex_t bindex,
2534+ const unsigned int verbose)
1facf9fc 2535+{
2536+ int err;
2537+ unsigned int sigen;
2538+
2539+ sigen = au_sigen(root->d_sb);
2540+ DiMustNoWaiters(root);
2541+ IiMustNoWaiters(root->d_inode);
2542+ di_write_unlock(root);
b752ccd1 2543+ err = test_dentry_busy(root, bindex, sigen, verbose);
1facf9fc 2544+ if (!err)
b752ccd1 2545+ err = test_inode_busy(root->d_sb, bindex, sigen, verbose);
1facf9fc 2546+ di_write_lock_child(root); /* aufs_write_lock() calls ..._child() */
2547+
2548+ return err;
2549+}
2550+
2551+static void au_br_do_del_brp(struct au_sbinfo *sbinfo,
2552+ const aufs_bindex_t bindex,
2553+ const aufs_bindex_t bend)
2554+{
2555+ struct au_branch **brp, **p;
2556+
dece6358
AM
2557+ AuRwMustWriteLock(&sbinfo->si_rwsem);
2558+
1facf9fc 2559+ brp = sbinfo->si_branch + bindex;
2560+ if (bindex < bend)
2561+ memmove(brp, brp + 1, sizeof(*brp) * (bend - bindex));
2562+ sbinfo->si_branch[0 + bend] = NULL;
2563+ sbinfo->si_bend--;
2564+
53392da6 2565+ p = krealloc(sbinfo->si_branch, sizeof(*p) * bend, AuGFP_SBILIST);
1facf9fc 2566+ if (p)
2567+ sbinfo->si_branch = p;
4a4d8108 2568+ /* harmless error */
1facf9fc 2569+}
2570+
2571+static void au_br_do_del_hdp(struct au_dinfo *dinfo, const aufs_bindex_t bindex,
2572+ const aufs_bindex_t bend)
2573+{
2574+ struct au_hdentry *hdp, *p;
2575+
1308ab2a 2576+ AuRwMustWriteLock(&dinfo->di_rwsem);
2577+
4a4d8108 2578+ hdp = dinfo->di_hdentry;
1facf9fc 2579+ if (bindex < bend)
4a4d8108
AM
2580+ memmove(hdp + bindex, hdp + bindex + 1,
2581+ sizeof(*hdp) * (bend - bindex));
2582+ hdp[0 + bend].hd_dentry = NULL;
1facf9fc 2583+ dinfo->di_bend--;
2584+
53392da6 2585+ p = krealloc(hdp, sizeof(*p) * bend, AuGFP_SBILIST);
1facf9fc 2586+ if (p)
2587+ dinfo->di_hdentry = p;
4a4d8108 2588+ /* harmless error */
1facf9fc 2589+}
2590+
2591+static void au_br_do_del_hip(struct au_iinfo *iinfo, const aufs_bindex_t bindex,
2592+ const aufs_bindex_t bend)
2593+{
2594+ struct au_hinode *hip, *p;
2595+
1308ab2a 2596+ AuRwMustWriteLock(&iinfo->ii_rwsem);
2597+
1facf9fc 2598+ hip = iinfo->ii_hinode + bindex;
2599+ if (bindex < bend)
2600+ memmove(hip, hip + 1, sizeof(*hip) * (bend - bindex));
2601+ iinfo->ii_hinode[0 + bend].hi_inode = NULL;
4a4d8108 2602+ au_hn_init(iinfo->ii_hinode + bend);
1facf9fc 2603+ iinfo->ii_bend--;
2604+
53392da6 2605+ p = krealloc(iinfo->ii_hinode, sizeof(*p) * bend, AuGFP_SBILIST);
1facf9fc 2606+ if (p)
2607+ iinfo->ii_hinode = p;
4a4d8108 2608+ /* harmless error */
1facf9fc 2609+}
2610+
2611+static void au_br_do_del(struct super_block *sb, aufs_bindex_t bindex,
2612+ struct au_branch *br)
2613+{
2614+ aufs_bindex_t bend;
2615+ struct au_sbinfo *sbinfo;
53392da6
AM
2616+ struct dentry *root, *h_root;
2617+ struct inode *inode, *h_inode;
2618+ struct au_hinode *hinode;
1facf9fc 2619+
dece6358
AM
2620+ SiMustWriteLock(sb);
2621+
1facf9fc 2622+ root = sb->s_root;
2623+ inode = root->d_inode;
1facf9fc 2624+ sbinfo = au_sbi(sb);
2625+ bend = sbinfo->si_bend;
2626+
53392da6
AM
2627+ h_root = au_h_dptr(root, bindex);
2628+ hinode = au_hi(inode, bindex);
2629+ h_inode = au_igrab(hinode->hi_inode);
2630+ au_hiput(hinode);
1facf9fc 2631+
53392da6 2632+ au_sbilist_lock();
1facf9fc 2633+ au_br_do_del_brp(sbinfo, bindex, bend);
2634+ au_br_do_del_hdp(au_di(root), bindex, bend);
2635+ au_br_do_del_hip(au_ii(inode), bindex, bend);
53392da6
AM
2636+ au_sbilist_unlock();
2637+
2638+ dput(h_root);
2639+ iput(h_inode);
2640+ au_br_do_free(br);
1facf9fc 2641+}
2642+
2643+int au_br_del(struct super_block *sb, struct au_opt_del *del, int remount)
2644+{
2645+ int err, rerr, i;
2646+ unsigned int mnt_flags;
2647+ aufs_bindex_t bindex, bend, br_id;
2648+ unsigned char do_wh, verbose;
2649+ struct au_branch *br;
2650+ struct au_wbr *wbr;
2651+
2652+ err = 0;
2653+ bindex = au_find_dbindex(sb->s_root, del->h_path.dentry);
2654+ if (bindex < 0) {
2655+ if (remount)
2656+ goto out; /* success */
2657+ err = -ENOENT;
4a4d8108 2658+ pr_err("%s no such branch\n", del->pathname);
1facf9fc 2659+ goto out;
2660+ }
2661+ AuDbg("bindex b%d\n", bindex);
2662+
2663+ err = -EBUSY;
2664+ mnt_flags = au_mntflags(sb);
2665+ verbose = !!au_opt_test(mnt_flags, VERBOSE);
2666+ bend = au_sbend(sb);
2667+ if (unlikely(!bend)) {
2668+ AuVerbose(verbose, "no more branches left\n");
2669+ goto out;
2670+ }
2671+ br = au_sbr(sb, bindex);
2672+ i = atomic_read(&br->br_count);
2673+ if (unlikely(i)) {
2674+ AuVerbose(verbose, "%d file(s) opened\n", i);
e49829fe 2675+ goto out;
1facf9fc 2676+ }
2677+
2678+ wbr = br->br_wbr;
2679+ do_wh = wbr && (wbr->wbr_whbase || wbr->wbr_plink || wbr->wbr_orph);
2680+ if (do_wh) {
1308ab2a 2681+ /* instead of WbrWhMustWriteLock(wbr) */
2682+ SiMustWriteLock(sb);
1facf9fc 2683+ for (i = 0; i < AuBrWh_Last; i++) {
2684+ dput(wbr->wbr_wh[i]);
2685+ wbr->wbr_wh[i] = NULL;
2686+ }
2687+ }
2688+
b752ccd1 2689+ err = test_children_busy(sb->s_root, bindex, verbose);
1facf9fc 2690+ if (unlikely(err)) {
2691+ if (do_wh)
2692+ goto out_wh;
2693+ goto out;
2694+ }
2695+
2696+ err = 0;
2697+ br_id = br->br_id;
2698+ if (!remount)
2699+ au_br_do_del(sb, bindex, br);
2700+ else {
2701+ sysaufs_brs_del(sb, bindex);
2702+ au_br_do_del(sb, bindex, br);
2703+ sysaufs_brs_add(sb, bindex);
2704+ }
2705+
1308ab2a 2706+ if (!bindex) {
1facf9fc 2707+ au_cpup_attr_all(sb->s_root->d_inode, /*force*/1);
1308ab2a 2708+ sb->s_maxbytes = au_sbr_sb(sb, 0)->s_maxbytes;
2709+ } else
1facf9fc 2710+ au_sub_nlink(sb->s_root->d_inode, del->h_path.dentry->d_inode);
2711+ if (au_opt_test(mnt_flags, PLINK))
2712+ au_plink_half_refresh(sb, br_id);
2713+
b752ccd1 2714+ if (au_xino_brid(sb) == br_id)
1facf9fc 2715+ au_xino_brid_set(sb, -1);
2716+ goto out; /* success */
2717+
4f0767ce 2718+out_wh:
1facf9fc 2719+ /* revert */
2720+ rerr = au_br_init_wh(sb, br, br->br_perm, del->h_path.dentry);
2721+ if (rerr)
0c3ec466
AM
2722+ pr_warn("failed re-creating base whiteout, %s. (%d)\n",
2723+ del->pathname, rerr);
4f0767ce 2724+out:
1facf9fc 2725+ return err;
2726+}
2727+
2728+/* ---------------------------------------------------------------------- */
2729+
027c5e7a
AM
2730+static int au_ibusy(struct super_block *sb, struct aufs_ibusy __user *arg)
2731+{
2732+ int err;
2733+ aufs_bindex_t bstart, bend;
2734+ struct aufs_ibusy ibusy;
2735+ struct inode *inode, *h_inode;
2736+
2737+ err = -EPERM;
2738+ if (unlikely(!capable(CAP_SYS_ADMIN)))
2739+ goto out;
2740+
2741+ err = copy_from_user(&ibusy, arg, sizeof(ibusy));
2742+ if (!err)
2743+ err = !access_ok(VERIFY_WRITE, &arg->h_ino, sizeof(arg->h_ino));
2744+ if (unlikely(err)) {
2745+ err = -EFAULT;
2746+ AuTraceErr(err);
2747+ goto out;
2748+ }
2749+
2750+ err = -EINVAL;
2751+ si_read_lock(sb, AuLock_FLUSH);
2752+ if (unlikely(ibusy.bindex < 0 || ibusy.bindex > au_sbend(sb)))
2753+ goto out_unlock;
2754+
2755+ err = 0;
2756+ ibusy.h_ino = 0; /* invalid */
2757+ inode = ilookup(sb, ibusy.ino);
2758+ if (!inode
2759+ || inode->i_ino == AUFS_ROOT_INO
2760+ || is_bad_inode(inode))
2761+ goto out_unlock;
2762+
2763+ ii_read_lock_child(inode);
2764+ bstart = au_ibstart(inode);
2765+ bend = au_ibend(inode);
2766+ if (bstart <= ibusy.bindex && ibusy.bindex <= bend) {
2767+ h_inode = au_h_iptr(inode, ibusy.bindex);
2768+ if (h_inode && au_test_ibusy(inode, bstart, bend))
2769+ ibusy.h_ino = h_inode->i_ino;
2770+ }
2771+ ii_read_unlock(inode);
2772+ iput(inode);
2773+
2774+out_unlock:
2775+ si_read_unlock(sb);
2776+ if (!err) {
2777+ err = __put_user(ibusy.h_ino, &arg->h_ino);
2778+ if (unlikely(err)) {
2779+ err = -EFAULT;
2780+ AuTraceErr(err);
2781+ }
2782+ }
2783+out:
2784+ return err;
2785+}
2786+
2787+long au_ibusy_ioctl(struct file *file, unsigned long arg)
2788+{
2789+ return au_ibusy(file->f_dentry->d_sb, (void __user *)arg);
2790+}
2791+
2792+#ifdef CONFIG_COMPAT
2793+long au_ibusy_compat_ioctl(struct file *file, unsigned long arg)
2794+{
2795+ return au_ibusy(file->f_dentry->d_sb, compat_ptr(arg));
2796+}
2797+#endif
2798+
2799+/* ---------------------------------------------------------------------- */
2800+
1facf9fc 2801+/*
2802+ * change a branch permission
2803+ */
2804+
dece6358
AM
2805+static void au_warn_ima(void)
2806+{
2807+#ifdef CONFIG_IMA
1308ab2a 2808+ /* since it doesn't support mark_files_ro() */
027c5e7a 2809+ AuWarn1("RW -> RO makes IMA to produce wrong message\n");
dece6358
AM
2810+#endif
2811+}
2812+
1facf9fc 2813+static int do_need_sigen_inc(int a, int b)
2814+{
2815+ return au_br_whable(a) && !au_br_whable(b);
2816+}
2817+
2818+static int need_sigen_inc(int old, int new)
2819+{
2820+ return do_need_sigen_inc(old, new)
2821+ || do_need_sigen_inc(new, old);
2822+}
2823+
7f207e10
AM
2824+static unsigned long long au_farray_cb(void *a,
2825+ unsigned long long max __maybe_unused,
2826+ void *arg)
2827+{
2828+ unsigned long long n;
2829+ struct file **p, *f;
2830+ struct super_block *sb = arg;
2831+
2832+ n = 0;
2833+ p = a;
0c3ec466 2834+ lg_global_lock(&files_lglock);
7f207e10
AM
2835+ do_file_list_for_each_entry(sb, f) {
2836+ if (au_fi(f)
027c5e7a 2837+ && file_count(f)
7f207e10
AM
2838+ && !special_file(f->f_dentry->d_inode->i_mode)) {
2839+ get_file(f);
2840+ *p++ = f;
2841+ n++;
2842+ AuDebugOn(n > max);
2843+ }
2844+ } while_file_list_for_each_entry;
0c3ec466 2845+ lg_global_unlock(&files_lglock);
7f207e10
AM
2846+
2847+ return n;
2848+}
2849+
2850+static struct file **au_farray_alloc(struct super_block *sb,
2851+ unsigned long long *max)
2852+{
2853+ *max = atomic_long_read(&au_sbi(sb)->si_nfiles);
2854+ return au_array_alloc(max, au_farray_cb, sb);
2855+}
2856+
2857+static void au_farray_free(struct file **a, unsigned long long max)
2858+{
2859+ unsigned long long ull;
2860+
2861+ for (ull = 0; ull < max; ull++)
2862+ if (a[ull])
2863+ fput(a[ull]);
2864+ au_array_free(a);
2865+}
2866+
1facf9fc 2867+static int au_br_mod_files_ro(struct super_block *sb, aufs_bindex_t bindex)
2868+{
7f207e10 2869+ int err, do_warn;
027c5e7a 2870+ unsigned int mnt_flags;
7f207e10 2871+ unsigned long long ull, max;
e49829fe 2872+ aufs_bindex_t br_id;
027c5e7a 2873+ unsigned char verbose;
7f207e10 2874+ struct file *file, *hf, **array;
e49829fe
JR
2875+ struct inode *inode;
2876+ struct au_hfile *hfile;
1facf9fc 2877+
027c5e7a
AM
2878+ mnt_flags = au_mntflags(sb);
2879+ verbose = !!au_opt_test(mnt_flags, VERBOSE);
2880+
7f207e10
AM
2881+ array = au_farray_alloc(sb, &max);
2882+ err = PTR_ERR(array);
2883+ if (IS_ERR(array))
1facf9fc 2884+ goto out;
2885+
7f207e10 2886+ do_warn = 0;
e49829fe 2887+ br_id = au_sbr_id(sb, bindex);
7f207e10
AM
2888+ for (ull = 0; ull < max; ull++) {
2889+ file = array[ull];
1facf9fc 2890+
7f207e10 2891+ /* AuDbg("%.*s\n", AuDLNPair(file->f_dentry)); */
1facf9fc 2892+ fi_read_lock(file);
2893+ if (unlikely(au_test_mmapped(file))) {
2894+ err = -EBUSY;
027c5e7a
AM
2895+ AuVerbose(verbose, "mmapped %.*s\n",
2896+ AuDLNPair(file->f_dentry));
7f207e10 2897+ AuDbgFile(file);
1facf9fc 2898+ FiMustNoWaiters(file);
2899+ fi_read_unlock(file);
7f207e10 2900+ goto out_array;
1facf9fc 2901+ }
2902+
027c5e7a 2903+ inode = file->f_dentry->d_inode;
e49829fe
JR
2904+ hfile = &au_fi(file)->fi_htop;
2905+ hf = hfile->hf_file;
2906+ if (!S_ISREG(inode->i_mode)
1facf9fc 2907+ || !(file->f_mode & FMODE_WRITE)
e49829fe 2908+ || hfile->hf_br->br_id != br_id
7f207e10
AM
2909+ || !(hf->f_mode & FMODE_WRITE))
2910+ array[ull] = NULL;
2911+ else {
2912+ do_warn = 1;
2913+ get_file(file);
1facf9fc 2914+ }
2915+
1facf9fc 2916+ FiMustNoWaiters(file);
2917+ fi_read_unlock(file);
7f207e10
AM
2918+ fput(file);
2919+ }
1facf9fc 2920+
2921+ err = 0;
7f207e10 2922+ if (do_warn)
dece6358 2923+ au_warn_ima();
7f207e10
AM
2924+
2925+ for (ull = 0; ull < max; ull++) {
2926+ file = array[ull];
2927+ if (!file)
2928+ continue;
2929+
1facf9fc 2930+ /* todo: already flushed? */
2931+ /* cf. fs/super.c:mark_files_ro() */
7f207e10
AM
2932+ /* fi_read_lock(file); */
2933+ hfile = &au_fi(file)->fi_htop;
2934+ hf = hfile->hf_file;
2935+ /* fi_read_unlock(file); */
027c5e7a 2936+ spin_lock(&hf->f_lock);
1facf9fc 2937+ hf->f_mode &= ~FMODE_WRITE;
027c5e7a 2938+ spin_unlock(&hf->f_lock);
1facf9fc 2939+ if (!file_check_writeable(hf)) {
2940+ file_release_write(hf);
2941+ mnt_drop_write(hf->f_vfsmnt);
2942+ }
2943+ }
2944+
7f207e10
AM
2945+out_array:
2946+ au_farray_free(array, max);
4f0767ce 2947+out:
7f207e10 2948+ AuTraceErr(err);
1facf9fc 2949+ return err;
2950+}
2951+
2952+int au_br_mod(struct super_block *sb, struct au_opt_mod *mod, int remount,
7f207e10 2953+ int *do_refresh)
1facf9fc 2954+{
2955+ int err, rerr;
2956+ aufs_bindex_t bindex;
1308ab2a 2957+ struct path path;
1facf9fc 2958+ struct dentry *root;
2959+ struct au_branch *br;
2960+
2961+ root = sb->s_root;
1facf9fc 2962+ bindex = au_find_dbindex(root, mod->h_root);
2963+ if (bindex < 0) {
2964+ if (remount)
2965+ return 0; /* success */
2966+ err = -ENOENT;
4a4d8108 2967+ pr_err("%s no such branch\n", mod->path);
1facf9fc 2968+ goto out;
2969+ }
2970+ AuDbg("bindex b%d\n", bindex);
2971+
2972+ err = test_br(mod->h_root->d_inode, mod->perm, mod->path);
2973+ if (unlikely(err))
2974+ goto out;
2975+
2976+ br = au_sbr(sb, bindex);
2977+ if (br->br_perm == mod->perm)
2978+ return 0; /* success */
2979+
2980+ if (au_br_writable(br->br_perm)) {
2981+ /* remove whiteout base */
2982+ err = au_br_init_wh(sb, br, mod->perm, mod->h_root);
2983+ if (unlikely(err))
2984+ goto out;
2985+
2986+ if (!au_br_writable(mod->perm)) {
2987+ /* rw --> ro, file might be mmapped */
2988+ DiMustNoWaiters(root);
2989+ IiMustNoWaiters(root->d_inode);
2990+ di_write_unlock(root);
2991+ err = au_br_mod_files_ro(sb, bindex);
2992+ /* aufs_write_lock() calls ..._child() */
2993+ di_write_lock_child(root);
2994+
2995+ if (unlikely(err)) {
2996+ rerr = -ENOMEM;
2997+ br->br_wbr = kmalloc(sizeof(*br->br_wbr),
2998+ GFP_NOFS);
1308ab2a 2999+ if (br->br_wbr) {
3000+ path.mnt = br->br_mnt;
3001+ path.dentry = mod->h_root;
3002+ rerr = au_wbr_init(br, sb, br->br_perm,
3003+ &path);
3004+ }
1facf9fc 3005+ if (unlikely(rerr)) {
3006+ AuIOErr("nested error %d (%d)\n",
3007+ rerr, err);
3008+ br->br_perm = mod->perm;
3009+ }
3010+ }
3011+ }
3012+ } else if (au_br_writable(mod->perm)) {
3013+ /* ro --> rw */
3014+ err = -ENOMEM;
3015+ br->br_wbr = kmalloc(sizeof(*br->br_wbr), GFP_NOFS);
3016+ if (br->br_wbr) {
1308ab2a 3017+ path.mnt = br->br_mnt;
3018+ path.dentry = mod->h_root;
1facf9fc 3019+ err = au_wbr_init(br, sb, mod->perm, &path);
3020+ if (unlikely(err)) {
3021+ kfree(br->br_wbr);
3022+ br->br_wbr = NULL;
3023+ }
3024+ }
3025+ }
3026+
3027+ if (!err) {
7f207e10 3028+ *do_refresh |= need_sigen_inc(br->br_perm, mod->perm);
1facf9fc 3029+ br->br_perm = mod->perm;
3030+ }
3031+
4f0767ce 3032+out:
7f207e10 3033+ AuTraceErr(err);
1facf9fc 3034+ return err;
3035+}
7f207e10
AM
3036diff -urN /usr/share/empty/fs/aufs/branch.h linux/fs/aufs/branch.h
3037--- /usr/share/empty/fs/aufs/branch.h 1970-01-01 01:00:00.000000000 +0100
0c3ec466 3038+++ linux/fs/aufs/branch.h 2012-07-22 19:57:03.161004531 +0200
f6c5ef8b 3039@@ -0,0 +1,230 @@
1facf9fc 3040+/*
f6c5ef8b 3041+ * Copyright (C) 2005-2012 Junjiro R. Okajima
1facf9fc 3042+ *
3043+ * This program, aufs is free software; you can redistribute it and/or modify
3044+ * it under the terms of the GNU General Public License as published by
3045+ * the Free Software Foundation; either version 2 of the License, or
3046+ * (at your option) any later version.
dece6358
AM
3047+ *
3048+ * This program is distributed in the hope that it will be useful,
3049+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
3050+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
3051+ * GNU General Public License for more details.
3052+ *
3053+ * You should have received a copy of the GNU General Public License
3054+ * along with this program; if not, write to the Free Software
3055+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 3056+ */
3057+
3058+/*
3059+ * branch filesystems and xino for them
3060+ */
3061+
3062+#ifndef __AUFS_BRANCH_H__
3063+#define __AUFS_BRANCH_H__
3064+
3065+#ifdef __KERNEL__
3066+
1facf9fc 3067+#include <linux/mount.h>
4a4d8108 3068+#include "dynop.h"
1facf9fc 3069+#include "rwsem.h"
3070+#include "super.h"
3071+
3072+/* ---------------------------------------------------------------------- */
3073+
3074+/* a xino file */
3075+struct au_xino_file {
3076+ struct file *xi_file;
3077+ struct mutex xi_nondir_mtx;
3078+
3079+ /* todo: make xino files an array to support huge inode number */
3080+
3081+#ifdef CONFIG_DEBUG_FS
3082+ struct dentry *xi_dbgaufs;
3083+#endif
3084+};
3085+
3086+/* members for writable branch only */
3087+enum {AuBrWh_BASE, AuBrWh_PLINK, AuBrWh_ORPH, AuBrWh_Last};
3088+struct au_wbr {
dece6358 3089+ struct au_rwsem wbr_wh_rwsem;
1facf9fc 3090+ struct dentry *wbr_wh[AuBrWh_Last];
4a4d8108 3091+ atomic_t wbr_wh_running;
1facf9fc 3092+#define wbr_whbase wbr_wh[AuBrWh_BASE] /* whiteout base */
3093+#define wbr_plink wbr_wh[AuBrWh_PLINK] /* pseudo-link dir */
3094+#define wbr_orph wbr_wh[AuBrWh_ORPH] /* dir for orphans */
3095+
3096+ /* mfs mode */
3097+ unsigned long long wbr_bytes;
3098+};
3099+
4a4d8108
AM
3100+/* ext2 has 3 types of operations at least, ext3 has 4 */
3101+#define AuBrDynOp (AuDyLast * 4)
3102+
1facf9fc 3103+/* protected by superblock rwsem */
3104+struct au_branch {
3105+ struct au_xino_file br_xino;
3106+
3107+ aufs_bindex_t br_id;
3108+
3109+ int br_perm;
3110+ struct vfsmount *br_mnt;
4a4d8108
AM
3111+ spinlock_t br_dykey_lock;
3112+ struct au_dykey *br_dykey[AuBrDynOp];
1facf9fc 3113+ atomic_t br_count;
3114+
3115+ struct au_wbr *br_wbr;
3116+
3117+ /* xino truncation */
3118+ blkcnt_t br_xino_upper; /* watermark in blocks */
3119+ atomic_t br_xino_running;
3120+
027c5e7a
AM
3121+#ifdef CONFIG_AUFS_HFSNOTIFY
3122+ struct fsnotify_group *br_hfsn_group;
3123+ struct fsnotify_ops br_hfsn_ops;
3124+#endif
3125+
1facf9fc 3126+#ifdef CONFIG_SYSFS
3127+ /* an entry under sysfs per mount-point */
3128+ char br_name[8];
3129+ struct attribute br_attr;
3130+#endif
3131+};
3132+
3133+/* ---------------------------------------------------------------------- */
3134+
1e00d052
AM
3135+/* branch permissions and attributes */
3136+#define AuBrPerm_RW 1 /* writable, hardlinkable wh */
3137+#define AuBrPerm_RO (1 << 1) /* readonly */
3138+#define AuBrPerm_RR (1 << 2) /* natively readonly */
3139+#define AuBrPerm_Mask (AuBrPerm_RW | AuBrPerm_RO | AuBrPerm_RR)
1facf9fc 3140+
1e00d052 3141+#define AuBrRAttr_WH (1 << 3) /* whiteout-able */
1facf9fc 3142+
1e00d052 3143+#define AuBrWAttr_NoLinkWH (1 << 4) /* un-hardlinkable whiteouts */
1facf9fc 3144+
3145+static inline int au_br_writable(int brperm)
3146+{
1e00d052 3147+ return brperm & AuBrPerm_RW;
1facf9fc 3148+}
3149+
3150+static inline int au_br_whable(int brperm)
3151+{
1e00d052
AM
3152+ return brperm & (AuBrPerm_RW | AuBrRAttr_WH);
3153+}
3154+
3155+static inline int au_br_wh_linkable(int brperm)
3156+{
3157+ return !(brperm & AuBrWAttr_NoLinkWH);
1facf9fc 3158+}
3159+
3160+static inline int au_br_rdonly(struct au_branch *br)
3161+{
3162+ return ((br->br_mnt->mnt_sb->s_flags & MS_RDONLY)
3163+ || !au_br_writable(br->br_perm))
3164+ ? -EROFS : 0;
3165+}
3166+
4a4d8108 3167+static inline int au_br_hnotifyable(int brperm __maybe_unused)
1facf9fc 3168+{
4a4d8108 3169+#ifdef CONFIG_AUFS_HNOTIFY
1e00d052 3170+ return !(brperm & AuBrPerm_RR);
1facf9fc 3171+#else
3172+ return 0;
3173+#endif
3174+}
3175+
3176+/* ---------------------------------------------------------------------- */
3177+
3178+/* branch.c */
3179+struct au_sbinfo;
3180+void au_br_free(struct au_sbinfo *sinfo);
3181+int au_br_index(struct super_block *sb, aufs_bindex_t br_id);
3182+struct au_opt_add;
3183+int au_br_add(struct super_block *sb, struct au_opt_add *add, int remount);
3184+struct au_opt_del;
3185+int au_br_del(struct super_block *sb, struct au_opt_del *del, int remount);
027c5e7a
AM
3186+long au_ibusy_ioctl(struct file *file, unsigned long arg);
3187+#ifdef CONFIG_COMPAT
3188+long au_ibusy_compat_ioctl(struct file *file, unsigned long arg);
3189+#endif
1facf9fc 3190+struct au_opt_mod;
3191+int au_br_mod(struct super_block *sb, struct au_opt_mod *mod, int remount,
7f207e10 3192+ int *do_refresh);
1facf9fc 3193+
3194+/* xino.c */
3195+static const loff_t au_loff_max = LLONG_MAX;
3196+
3197+int au_xib_trunc(struct super_block *sb);
3198+ssize_t xino_fread(au_readf_t func, struct file *file, void *buf, size_t size,
3199+ loff_t *pos);
3200+ssize_t xino_fwrite(au_writef_t func, struct file *file, void *buf, size_t size,
3201+ loff_t *pos);
3202+struct file *au_xino_create2(struct file *base_file, struct file *copy_src);
3203+struct file *au_xino_create(struct super_block *sb, char *fname, int silent);
3204+ino_t au_xino_new_ino(struct super_block *sb);
b752ccd1 3205+void au_xino_delete_inode(struct inode *inode, const int unlinked);
1facf9fc 3206+int au_xino_write(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino,
3207+ ino_t ino);
3208+int au_xino_read(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino,
3209+ ino_t *ino);
3210+int au_xino_br(struct super_block *sb, struct au_branch *br, ino_t hino,
3211+ struct file *base_file, int do_test);
3212+int au_xino_trunc(struct super_block *sb, aufs_bindex_t bindex);
3213+
3214+struct au_opt_xino;
3215+int au_xino_set(struct super_block *sb, struct au_opt_xino *xino, int remount);
3216+void au_xino_clr(struct super_block *sb);
3217+struct file *au_xino_def(struct super_block *sb);
3218+int au_xino_path(struct seq_file *seq, struct file *file);
3219+
3220+/* ---------------------------------------------------------------------- */
3221+
3222+/* Superblock to branch */
3223+static inline
3224+aufs_bindex_t au_sbr_id(struct super_block *sb, aufs_bindex_t bindex)
3225+{
3226+ return au_sbr(sb, bindex)->br_id;
3227+}
3228+
3229+static inline
3230+struct vfsmount *au_sbr_mnt(struct super_block *sb, aufs_bindex_t bindex)
3231+{
3232+ return au_sbr(sb, bindex)->br_mnt;
3233+}
3234+
3235+static inline
3236+struct super_block *au_sbr_sb(struct super_block *sb, aufs_bindex_t bindex)
3237+{
3238+ return au_sbr_mnt(sb, bindex)->mnt_sb;
3239+}
3240+
3241+static inline void au_sbr_put(struct super_block *sb, aufs_bindex_t bindex)
3242+{
e49829fe 3243+ atomic_dec(&au_sbr(sb, bindex)->br_count);
1facf9fc 3244+}
3245+
3246+static inline int au_sbr_perm(struct super_block *sb, aufs_bindex_t bindex)
3247+{
3248+ return au_sbr(sb, bindex)->br_perm;
3249+}
3250+
3251+static inline int au_sbr_whable(struct super_block *sb, aufs_bindex_t bindex)
3252+{
3253+ return au_br_whable(au_sbr_perm(sb, bindex));
3254+}
3255+
3256+/* ---------------------------------------------------------------------- */
3257+
3258+/*
3259+ * wbr_wh_read_lock, wbr_wh_write_lock
3260+ * wbr_wh_read_unlock, wbr_wh_write_unlock, wbr_wh_downgrade_lock
3261+ */
3262+AuSimpleRwsemFuncs(wbr_wh, struct au_wbr *wbr, &wbr->wbr_wh_rwsem);
3263+
dece6358
AM
3264+#define WbrWhMustNoWaiters(wbr) AuRwMustNoWaiters(&wbr->wbr_wh_rwsem)
3265+#define WbrWhMustAnyLock(wbr) AuRwMustAnyLock(&wbr->wbr_wh_rwsem)
3266+#define WbrWhMustWriteLock(wbr) AuRwMustWriteLock(&wbr->wbr_wh_rwsem)
3267+
1facf9fc 3268+#endif /* __KERNEL__ */
3269+#endif /* __AUFS_BRANCH_H__ */
7f207e10
AM
3270diff -urN /usr/share/empty/fs/aufs/conf.mk linux/fs/aufs/conf.mk
3271--- /usr/share/empty/fs/aufs/conf.mk 1970-01-01 01:00:00.000000000 +0100
0c3ec466 3272+++ linux/fs/aufs/conf.mk 2012-07-22 19:57:03.161004531 +0200
2cbb1c4b 3273@@ -0,0 +1,38 @@
4a4d8108
AM
3274+
3275+AuConfStr = CONFIG_AUFS_FS=${CONFIG_AUFS_FS}
3276+
3277+define AuConf
3278+ifdef ${1}
3279+AuConfStr += ${1}=${${1}}
3280+endif
3281+endef
3282+
b752ccd1 3283+AuConfAll = BRANCH_MAX_127 BRANCH_MAX_511 BRANCH_MAX_1023 BRANCH_MAX_32767 \
e49829fe 3284+ SBILIST \
7f207e10 3285+ HNOTIFY HFSNOTIFY \
4a4d8108
AM
3286+ EXPORT INO_T_64 \
3287+ RDU \
2cbb1c4b 3288+ PROC_MAP \
4a4d8108
AM
3289+ SP_IATTR \
3290+ SHWH \
3291+ BR_RAMFS \
3292+ BR_FUSE POLL \
3293+ BR_HFSPLUS \
3294+ BDEV_LOOP \
b752ccd1
AM
3295+ DEBUG MAGIC_SYSRQ
3296+$(foreach i, ${AuConfAll}, \
4a4d8108
AM
3297+ $(eval $(call AuConf,CONFIG_AUFS_${i})))
3298+
3299+AuConfName = ${obj}/conf.str
3300+${AuConfName}.tmp: FORCE
3301+ @echo ${AuConfStr} | tr ' ' '\n' | sed -e 's/^/"/' -e 's/$$/\\n"/' > $@
3302+${AuConfName}: ${AuConfName}.tmp
3303+ @diff -q $< $@ > /dev/null 2>&1 || { \
3304+ echo ' GEN ' $@; \
3305+ cp -p $< $@; \
3306+ }
3307+FORCE:
3308+clean-files += ${AuConfName} ${AuConfName}.tmp
3309+${obj}/sysfs.o: ${AuConfName}
b752ccd1
AM
3310+
3311+-include ${srctree}/${src}/conf_priv.mk
7f207e10
AM
3312diff -urN /usr/share/empty/fs/aufs/cpup.c linux/fs/aufs/cpup.c
3313--- /usr/share/empty/fs/aufs/cpup.c 1970-01-01 01:00:00.000000000 +0100
0c3ec466 3314+++ linux/fs/aufs/cpup.c 2012-07-22 19:57:03.161004531 +0200
7eafdf33 3315@@ -0,0 +1,1084 @@
1facf9fc 3316+/*
f6c5ef8b 3317+ * Copyright (C) 2005-2012 Junjiro R. Okajima
1facf9fc 3318+ *
3319+ * This program, aufs is free software; you can redistribute it and/or modify
3320+ * it under the terms of the GNU General Public License as published by
3321+ * the Free Software Foundation; either version 2 of the License, or
3322+ * (at your option) any later version.
dece6358
AM
3323+ *
3324+ * This program is distributed in the hope that it will be useful,
3325+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
3326+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
3327+ * GNU General Public License for more details.
3328+ *
3329+ * You should have received a copy of the GNU General Public License
3330+ * along with this program; if not, write to the Free Software
3331+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 3332+ */
3333+
3334+/*
3335+ * copy-up functions, see wbr_policy.c for copy-down
3336+ */
3337+
3338+#include <linux/fs_stack.h>
dece6358 3339+#include <linux/mm.h>
1facf9fc 3340+#include "aufs.h"
3341+
3342+void au_cpup_attr_flags(struct inode *dst, struct inode *src)
3343+{
3344+ const unsigned int mask = S_DEAD | S_SWAPFILE | S_PRIVATE
3345+ | S_NOATIME | S_NOCMTIME;
3346+
3347+ dst->i_flags |= src->i_flags & ~mask;
3348+ if (au_test_fs_notime(dst->i_sb))
3349+ dst->i_flags |= S_NOATIME | S_NOCMTIME;
3350+}
3351+
3352+void au_cpup_attr_timesizes(struct inode *inode)
3353+{
3354+ struct inode *h_inode;
3355+
3356+ h_inode = au_h_iptr(inode, au_ibstart(inode));
3357+ fsstack_copy_attr_times(inode, h_inode);
4a4d8108 3358+ fsstack_copy_inode_size(inode, h_inode);
1facf9fc 3359+}
3360+
3361+void au_cpup_attr_nlink(struct inode *inode, int force)
3362+{
3363+ struct inode *h_inode;
3364+ struct super_block *sb;
3365+ aufs_bindex_t bindex, bend;
3366+
3367+ sb = inode->i_sb;
3368+ bindex = au_ibstart(inode);
3369+ h_inode = au_h_iptr(inode, bindex);
3370+ if (!force
3371+ && !S_ISDIR(h_inode->i_mode)
3372+ && au_opt_test(au_mntflags(sb), PLINK)
3373+ && au_plink_test(inode))
3374+ return;
3375+
7eafdf33
AM
3376+ /*
3377+ * 0 can happen in revalidating.
3378+ * h_inode->i_mutex is not held, but it is harmless since once i_nlink
3379+ * reaches 0, it will never become positive.
3380+ */
92d182d2 3381+ set_nlink(inode, h_inode->i_nlink);
1facf9fc 3382+
3383+ /*
3384+ * fewer nlink makes find(1) noisy, but larger nlink doesn't.
3385+ * it may includes whplink directory.
3386+ */
3387+ if (S_ISDIR(h_inode->i_mode)) {
3388+ bend = au_ibend(inode);
3389+ for (bindex++; bindex <= bend; bindex++) {
3390+ h_inode = au_h_iptr(inode, bindex);
3391+ if (h_inode)
3392+ au_add_nlink(inode, h_inode);
3393+ }
3394+ }
3395+}
3396+
3397+void au_cpup_attr_changeable(struct inode *inode)
3398+{
3399+ struct inode *h_inode;
3400+
3401+ h_inode = au_h_iptr(inode, au_ibstart(inode));
3402+ inode->i_mode = h_inode->i_mode;
3403+ inode->i_uid = h_inode->i_uid;
3404+ inode->i_gid = h_inode->i_gid;
3405+ au_cpup_attr_timesizes(inode);
3406+ au_cpup_attr_flags(inode, h_inode);
3407+}
3408+
3409+void au_cpup_igen(struct inode *inode, struct inode *h_inode)
3410+{
3411+ struct au_iinfo *iinfo = au_ii(inode);
3412+
1308ab2a 3413+ IiMustWriteLock(inode);
3414+
1facf9fc 3415+ iinfo->ii_higen = h_inode->i_generation;
3416+ iinfo->ii_hsb1 = h_inode->i_sb;
3417+}
3418+
3419+void au_cpup_attr_all(struct inode *inode, int force)
3420+{
3421+ struct inode *h_inode;
3422+
3423+ h_inode = au_h_iptr(inode, au_ibstart(inode));
3424+ au_cpup_attr_changeable(inode);
3425+ if (inode->i_nlink > 0)
3426+ au_cpup_attr_nlink(inode, force);
3427+ inode->i_rdev = h_inode->i_rdev;
3428+ inode->i_blkbits = h_inode->i_blkbits;
3429+ au_cpup_igen(inode, h_inode);
3430+}
3431+
3432+/* ---------------------------------------------------------------------- */
3433+
3434+/* Note: dt_dentry and dt_h_dentry are not dget/dput-ed */
3435+
3436+/* keep the timestamps of the parent dir when cpup */
3437+void au_dtime_store(struct au_dtime *dt, struct dentry *dentry,
3438+ struct path *h_path)
3439+{
3440+ struct inode *h_inode;
3441+
3442+ dt->dt_dentry = dentry;
3443+ dt->dt_h_path = *h_path;
3444+ h_inode = h_path->dentry->d_inode;
3445+ dt->dt_atime = h_inode->i_atime;
3446+ dt->dt_mtime = h_inode->i_mtime;
3447+ /* smp_mb(); */
3448+}
3449+
3450+void au_dtime_revert(struct au_dtime *dt)
3451+{
3452+ struct iattr attr;
3453+ int err;
3454+
3455+ attr.ia_atime = dt->dt_atime;
3456+ attr.ia_mtime = dt->dt_mtime;
3457+ attr.ia_valid = ATTR_FORCE | ATTR_MTIME | ATTR_MTIME_SET
3458+ | ATTR_ATIME | ATTR_ATIME_SET;
3459+
3460+ err = vfsub_notify_change(&dt->dt_h_path, &attr);
3461+ if (unlikely(err))
0c3ec466 3462+ pr_warn("restoring timestamps failed(%d). ignored\n", err);
1facf9fc 3463+}
3464+
3465+/* ---------------------------------------------------------------------- */
3466+
3467+static noinline_for_stack
3468+int cpup_iattr(struct dentry *dst, aufs_bindex_t bindex, struct dentry *h_src)
3469+{
3470+ int err, sbits;
3471+ struct iattr ia;
3472+ struct path h_path;
1308ab2a 3473+ struct inode *h_isrc, *h_idst;
1facf9fc 3474+
3475+ h_path.dentry = au_h_dptr(dst, bindex);
1308ab2a 3476+ h_idst = h_path.dentry->d_inode;
1facf9fc 3477+ h_path.mnt = au_sbr_mnt(dst->d_sb, bindex);
3478+ h_isrc = h_src->d_inode;
1308ab2a 3479+ ia.ia_valid = ATTR_FORCE | ATTR_UID | ATTR_GID
1facf9fc 3480+ | ATTR_ATIME | ATTR_MTIME
3481+ | ATTR_ATIME_SET | ATTR_MTIME_SET;
1facf9fc 3482+ ia.ia_uid = h_isrc->i_uid;
3483+ ia.ia_gid = h_isrc->i_gid;
3484+ ia.ia_atime = h_isrc->i_atime;
3485+ ia.ia_mtime = h_isrc->i_mtime;
1308ab2a 3486+ if (h_idst->i_mode != h_isrc->i_mode
3487+ && !S_ISLNK(h_idst->i_mode)) {
3488+ ia.ia_valid |= ATTR_MODE;
3489+ ia.ia_mode = h_isrc->i_mode;
3490+ }
3491+ sbits = !!(h_isrc->i_mode & (S_ISUID | S_ISGID));
3492+ au_cpup_attr_flags(h_idst, h_isrc);
1facf9fc 3493+ err = vfsub_notify_change(&h_path, &ia);
3494+
3495+ /* is this nfs only? */
3496+ if (!err && sbits && au_test_nfs(h_path.dentry->d_sb)) {
3497+ ia.ia_valid = ATTR_FORCE | ATTR_MODE;
3498+ ia.ia_mode = h_isrc->i_mode;
3499+ err = vfsub_notify_change(&h_path, &ia);
3500+ }
3501+
3502+ return err;
3503+}
3504+
3505+/* ---------------------------------------------------------------------- */
3506+
3507+static int au_do_copy_file(struct file *dst, struct file *src, loff_t len,
3508+ char *buf, unsigned long blksize)
3509+{
3510+ int err;
3511+ size_t sz, rbytes, wbytes;
3512+ unsigned char all_zero;
3513+ char *p, *zp;
3514+ struct mutex *h_mtx;
3515+ /* reduce stack usage */
3516+ struct iattr *ia;
3517+
3518+ zp = page_address(ZERO_PAGE(0));
3519+ if (unlikely(!zp))
3520+ return -ENOMEM; /* possible? */
3521+
3522+ err = 0;
3523+ all_zero = 0;
3524+ while (len) {
3525+ AuDbg("len %lld\n", len);
3526+ sz = blksize;
3527+ if (len < blksize)
3528+ sz = len;
3529+
3530+ rbytes = 0;
3531+ /* todo: signal_pending? */
3532+ while (!rbytes || err == -EAGAIN || err == -EINTR) {
3533+ rbytes = vfsub_read_k(src, buf, sz, &src->f_pos);
3534+ err = rbytes;
3535+ }
3536+ if (unlikely(err < 0))
3537+ break;
3538+
3539+ all_zero = 0;
3540+ if (len >= rbytes && rbytes == blksize)
3541+ all_zero = !memcmp(buf, zp, rbytes);
3542+ if (!all_zero) {
3543+ wbytes = rbytes;
3544+ p = buf;
3545+ while (wbytes) {
3546+ size_t b;
3547+
3548+ b = vfsub_write_k(dst, p, wbytes, &dst->f_pos);
3549+ err = b;
3550+ /* todo: signal_pending? */
3551+ if (unlikely(err == -EAGAIN || err == -EINTR))
3552+ continue;
3553+ if (unlikely(err < 0))
3554+ break;
3555+ wbytes -= b;
3556+ p += b;
3557+ }
3558+ } else {
3559+ loff_t res;
3560+
3561+ AuLabel(hole);
3562+ res = vfsub_llseek(dst, rbytes, SEEK_CUR);
3563+ err = res;
3564+ if (unlikely(res < 0))
3565+ break;
3566+ }
3567+ len -= rbytes;
3568+ err = 0;
3569+ }
3570+
3571+ /* the last block may be a hole */
3572+ if (!err && all_zero) {
3573+ AuLabel(last hole);
3574+
3575+ err = 1;
3576+ if (au_test_nfs(dst->f_dentry->d_sb)) {
3577+ /* nfs requires this step to make last hole */
3578+ /* is this only nfs? */
3579+ do {
3580+ /* todo: signal_pending? */
3581+ err = vfsub_write_k(dst, "\0", 1, &dst->f_pos);
3582+ } while (err == -EAGAIN || err == -EINTR);
3583+ if (err == 1)
3584+ dst->f_pos--;
3585+ }
3586+
3587+ if (err == 1) {
3588+ ia = (void *)buf;
3589+ ia->ia_size = dst->f_pos;
3590+ ia->ia_valid = ATTR_SIZE | ATTR_FILE;
3591+ ia->ia_file = dst;
3592+ h_mtx = &dst->f_dentry->d_inode->i_mutex;
3593+ mutex_lock_nested(h_mtx, AuLsc_I_CHILD2);
3594+ err = vfsub_notify_change(&dst->f_path, ia);
3595+ mutex_unlock(h_mtx);
3596+ }
3597+ }
3598+
3599+ return err;
3600+}
3601+
3602+int au_copy_file(struct file *dst, struct file *src, loff_t len)
3603+{
3604+ int err;
3605+ unsigned long blksize;
3606+ unsigned char do_kfree;
3607+ char *buf;
3608+
3609+ err = -ENOMEM;
3610+ blksize = dst->f_dentry->d_sb->s_blocksize;
3611+ if (!blksize || PAGE_SIZE < blksize)
3612+ blksize = PAGE_SIZE;
3613+ AuDbg("blksize %lu\n", blksize);
3614+ do_kfree = (blksize != PAGE_SIZE && blksize >= sizeof(struct iattr *));
3615+ if (do_kfree)
3616+ buf = kmalloc(blksize, GFP_NOFS);
3617+ else
3618+ buf = (void *)__get_free_page(GFP_NOFS);
3619+ if (unlikely(!buf))
3620+ goto out;
3621+
3622+ if (len > (1 << 22))
3623+ AuDbg("copying a large file %lld\n", (long long)len);
3624+
3625+ src->f_pos = 0;
3626+ dst->f_pos = 0;
3627+ err = au_do_copy_file(dst, src, len, buf, blksize);
3628+ if (do_kfree)
3629+ kfree(buf);
3630+ else
3631+ free_page((unsigned long)buf);
3632+
4f0767ce 3633+out:
1facf9fc 3634+ return err;
3635+}
3636+
3637+/*
3638+ * to support a sparse file which is opened with O_APPEND,
3639+ * we need to close the file.
3640+ */
3641+static int au_cp_regular(struct dentry *dentry, aufs_bindex_t bdst,
4a4d8108 3642+ aufs_bindex_t bsrc, loff_t len)
1facf9fc 3643+{
3644+ int err, i;
3645+ enum { SRC, DST };
3646+ struct {
3647+ aufs_bindex_t bindex;
3648+ unsigned int flags;
3649+ struct dentry *dentry;
3650+ struct file *file;
3651+ void *label, *label_file;
3652+ } *f, file[] = {
3653+ {
3654+ .bindex = bsrc,
3655+ .flags = O_RDONLY | O_NOATIME | O_LARGEFILE,
3656+ .file = NULL,
3657+ .label = &&out,
3658+ .label_file = &&out_src
3659+ },
3660+ {
3661+ .bindex = bdst,
3662+ .flags = O_WRONLY | O_NOATIME | O_LARGEFILE,
3663+ .file = NULL,
3664+ .label = &&out_src,
3665+ .label_file = &&out_dst
3666+ }
3667+ };
3668+ struct super_block *sb;
3669+
3670+ /* bsrc branch can be ro/rw. */
3671+ sb = dentry->d_sb;
3672+ f = file;
3673+ for (i = 0; i < 2; i++, f++) {
3674+ f->dentry = au_h_dptr(dentry, f->bindex);
3675+ f->file = au_h_open(dentry, f->bindex, f->flags, /*file*/NULL);
3676+ err = PTR_ERR(f->file);
3677+ if (IS_ERR(f->file))
3678+ goto *f->label;
3679+ err = -EINVAL;
3680+ if (unlikely(!f->file->f_op))
3681+ goto *f->label_file;
3682+ }
3683+
3684+ /* try stopping to update while we copyup */
3685+ IMustLock(file[SRC].dentry->d_inode);
3686+ err = au_copy_file(file[DST].file, file[SRC].file, len);
3687+
4f0767ce 3688+out_dst:
1facf9fc 3689+ fput(file[DST].file);
3690+ au_sbr_put(sb, file[DST].bindex);
4f0767ce 3691+out_src:
1facf9fc 3692+ fput(file[SRC].file);
3693+ au_sbr_put(sb, file[SRC].bindex);
4f0767ce 3694+out:
1facf9fc 3695+ return err;
3696+}
3697+
3698+static int au_do_cpup_regular(struct dentry *dentry, aufs_bindex_t bdst,
3699+ aufs_bindex_t bsrc, loff_t len,
3700+ struct inode *h_dir, struct path *h_path)
3701+{
3702+ int err, rerr;
3703+ loff_t l;
3704+
3705+ err = 0;
3706+ l = i_size_read(au_h_iptr(dentry->d_inode, bsrc));
3707+ if (len == -1 || l < len)
3708+ len = l;
3709+ if (len)
3710+ err = au_cp_regular(dentry, bdst, bsrc, len);
3711+ if (!err)
3712+ goto out; /* success */
3713+
3714+ rerr = vfsub_unlink(h_dir, h_path, /*force*/0);
3715+ if (rerr) {
3716+ AuIOErr("failed unlinking cpup-ed %.*s(%d, %d)\n",
3717+ AuDLNPair(h_path->dentry), err, rerr);
3718+ err = -EIO;
3719+ }
3720+
4f0767ce 3721+out:
1facf9fc 3722+ return err;
3723+}
3724+
3725+static int au_do_cpup_symlink(struct path *h_path, struct dentry *h_src,
3726+ struct inode *h_dir)
3727+{
3728+ int err, symlen;
3729+ mm_segment_t old_fs;
b752ccd1
AM
3730+ union {
3731+ char *k;
3732+ char __user *u;
3733+ } sym;
1facf9fc 3734+
3735+ err = -ENOSYS;
3736+ if (unlikely(!h_src->d_inode->i_op->readlink))
3737+ goto out;
3738+
3739+ err = -ENOMEM;
b752ccd1
AM
3740+ sym.k = __getname_gfp(GFP_NOFS);
3741+ if (unlikely(!sym.k))
1facf9fc 3742+ goto out;
3743+
9dbd164d 3744+ /* unnecessary to support mmap_sem since symlink is not mmap-able */
1facf9fc 3745+ old_fs = get_fs();
3746+ set_fs(KERNEL_DS);
b752ccd1 3747+ symlen = h_src->d_inode->i_op->readlink(h_src, sym.u, PATH_MAX);
1facf9fc 3748+ err = symlen;
3749+ set_fs(old_fs);
3750+
3751+ if (symlen > 0) {
b752ccd1
AM
3752+ sym.k[symlen] = 0;
3753+ err = vfsub_symlink(h_dir, h_path, sym.k);
1facf9fc 3754+ }
b752ccd1 3755+ __putname(sym.k);
1facf9fc 3756+
4f0767ce 3757+out:
1facf9fc 3758+ return err;
3759+}
3760+
3761+/* return with the lower dst inode is locked */
3762+static noinline_for_stack
3763+int cpup_entry(struct dentry *dentry, aufs_bindex_t bdst,
3764+ aufs_bindex_t bsrc, loff_t len, unsigned int flags,
3765+ struct dentry *dst_parent)
3766+{
3767+ int err;
3768+ umode_t mode;
3769+ unsigned int mnt_flags;
3770+ unsigned char isdir;
3771+ const unsigned char do_dt = !!au_ftest_cpup(flags, DTIME);
3772+ struct au_dtime dt;
3773+ struct path h_path;
3774+ struct dentry *h_src, *h_dst, *h_parent;
3775+ struct inode *h_inode, *h_dir;
3776+ struct super_block *sb;
3777+
3778+ /* bsrc branch can be ro/rw. */
3779+ h_src = au_h_dptr(dentry, bsrc);
3780+ h_inode = h_src->d_inode;
3781+ AuDebugOn(h_inode != au_h_iptr(dentry->d_inode, bsrc));
3782+
3783+ /* try stopping to be referenced while we are creating */
3784+ h_dst = au_h_dptr(dentry, bdst);
3785+ h_parent = h_dst->d_parent; /* dir inode is locked */
3786+ h_dir = h_parent->d_inode;
3787+ IMustLock(h_dir);
3788+ AuDebugOn(h_parent != h_dst->d_parent);
3789+
3790+ sb = dentry->d_sb;
3791+ h_path.mnt = au_sbr_mnt(sb, bdst);
3792+ if (do_dt) {
3793+ h_path.dentry = h_parent;
3794+ au_dtime_store(&dt, dst_parent, &h_path);
3795+ }
3796+ h_path.dentry = h_dst;
3797+
3798+ isdir = 0;
3799+ mode = h_inode->i_mode;
3800+ switch (mode & S_IFMT) {
3801+ case S_IFREG:
3802+ /* try stopping to update while we are referencing */
3803+ IMustLock(h_inode);
3804+ err = vfsub_create(h_dir, &h_path, mode | S_IWUSR);
3805+ if (!err)
3806+ err = au_do_cpup_regular
3807+ (dentry, bdst, bsrc, len,
3808+ au_h_iptr(dst_parent->d_inode, bdst), &h_path);
3809+ break;
3810+ case S_IFDIR:
3811+ isdir = 1;
3812+ err = vfsub_mkdir(h_dir, &h_path, mode);
3813+ if (!err) {
3814+ /*
3815+ * strange behaviour from the users view,
3816+ * particularry setattr case
3817+ */
3818+ if (au_ibstart(dst_parent->d_inode) == bdst)
3819+ au_cpup_attr_nlink(dst_parent->d_inode,
3820+ /*force*/1);
3821+ au_cpup_attr_nlink(dentry->d_inode, /*force*/1);
3822+ }
3823+ break;
3824+ case S_IFLNK:
3825+ err = au_do_cpup_symlink(&h_path, h_src, h_dir);
3826+ break;
3827+ case S_IFCHR:
3828+ case S_IFBLK:
3829+ AuDebugOn(!capable(CAP_MKNOD));
3830+ /*FALLTHROUGH*/
3831+ case S_IFIFO:
3832+ case S_IFSOCK:
3833+ err = vfsub_mknod(h_dir, &h_path, mode, h_inode->i_rdev);
3834+ break;
3835+ default:
3836+ AuIOErr("Unknown inode type 0%o\n", mode);
3837+ err = -EIO;
3838+ }
3839+
3840+ mnt_flags = au_mntflags(sb);
3841+ if (!au_opt_test(mnt_flags, UDBA_NONE)
3842+ && !isdir
3843+ && au_opt_test(mnt_flags, XINO)
3844+ && h_inode->i_nlink == 1
3845+ /* todo: unnecessary? */
3846+ /* && dentry->d_inode->i_nlink == 1 */
3847+ && bdst < bsrc
3848+ && !au_ftest_cpup(flags, KEEPLINO))
1308ab2a 3849+ au_xino_write(sb, bsrc, h_inode->i_ino, /*ino*/0);
1facf9fc 3850+ /* ignore this error */
3851+
3852+ if (do_dt)
3853+ au_dtime_revert(&dt);
3854+ return err;
3855+}
3856+
3857+/*
3858+ * copyup the @dentry from @bsrc to @bdst.
3859+ * the caller must set the both of lower dentries.
3860+ * @len is for truncating when it is -1 copyup the entire file.
3861+ * in link/rename cases, @dst_parent may be different from the real one.
3862+ */
3863+static int au_cpup_single(struct dentry *dentry, aufs_bindex_t bdst,
3864+ aufs_bindex_t bsrc, loff_t len, unsigned int flags,
3865+ struct dentry *dst_parent)
3866+{
3867+ int err, rerr;
3868+ aufs_bindex_t old_ibstart;
3869+ unsigned char isdir, plink;
3870+ struct au_dtime dt;
3871+ struct path h_path;
3872+ struct dentry *h_src, *h_dst, *h_parent;
3873+ struct inode *dst_inode, *h_dir, *inode;
3874+ struct super_block *sb;
3875+
3876+ AuDebugOn(bsrc <= bdst);
3877+
3878+ sb = dentry->d_sb;
3879+ h_path.mnt = au_sbr_mnt(sb, bdst);
3880+ h_dst = au_h_dptr(dentry, bdst);
3881+ h_parent = h_dst->d_parent; /* dir inode is locked */
3882+ h_dir = h_parent->d_inode;
3883+ IMustLock(h_dir);
3884+
3885+ h_src = au_h_dptr(dentry, bsrc);
3886+ inode = dentry->d_inode;
3887+
3888+ if (!dst_parent)
3889+ dst_parent = dget_parent(dentry);
3890+ else
3891+ dget(dst_parent);
3892+
3893+ plink = !!au_opt_test(au_mntflags(sb), PLINK);
3894+ dst_inode = au_h_iptr(inode, bdst);
3895+ if (dst_inode) {
3896+ if (unlikely(!plink)) {
3897+ err = -EIO;
027c5e7a
AM
3898+ AuIOErr("hi%lu(i%lu) exists on b%d "
3899+ "but plink is disabled\n",
3900+ dst_inode->i_ino, inode->i_ino, bdst);
1facf9fc 3901+ goto out;
3902+ }
3903+
3904+ if (dst_inode->i_nlink) {
3905+ const int do_dt = au_ftest_cpup(flags, DTIME);
3906+
3907+ h_src = au_plink_lkup(inode, bdst);
3908+ err = PTR_ERR(h_src);
3909+ if (IS_ERR(h_src))
3910+ goto out;
3911+ if (unlikely(!h_src->d_inode)) {
3912+ err = -EIO;
3913+ AuIOErr("i%lu exists on a upper branch "
027c5e7a
AM
3914+ "but not pseudo-linked\n",
3915+ inode->i_ino);
1facf9fc 3916+ dput(h_src);
3917+ goto out;
3918+ }
3919+
3920+ if (do_dt) {
3921+ h_path.dentry = h_parent;
3922+ au_dtime_store(&dt, dst_parent, &h_path);
3923+ }
3924+ h_path.dentry = h_dst;
3925+ err = vfsub_link(h_src, h_dir, &h_path);
3926+ if (do_dt)
3927+ au_dtime_revert(&dt);
3928+ dput(h_src);
3929+ goto out;
3930+ } else
3931+ /* todo: cpup_wh_file? */
3932+ /* udba work */
4a4d8108 3933+ au_update_ibrange(inode, /*do_put_zero*/1);
1facf9fc 3934+ }
3935+
3936+ old_ibstart = au_ibstart(inode);
3937+ err = cpup_entry(dentry, bdst, bsrc, len, flags, dst_parent);
3938+ if (unlikely(err))
3939+ goto out;
3940+ dst_inode = h_dst->d_inode;
3941+ mutex_lock_nested(&dst_inode->i_mutex, AuLsc_I_CHILD2);
3942+
3943+ err = cpup_iattr(dentry, bdst, h_src);
3944+ isdir = S_ISDIR(dst_inode->i_mode);
3945+ if (!err) {
4a4d8108
AM
3946+ if (bdst < old_ibstart) {
3947+ if (S_ISREG(inode->i_mode)) {
3948+ err = au_dy_iaop(inode, bdst, dst_inode);
3949+ if (unlikely(err))
3950+ goto out_rev;
3951+ }
1facf9fc 3952+ au_set_ibstart(inode, bdst);
4a4d8108 3953+ }
1facf9fc 3954+ au_set_h_iptr(inode, bdst, au_igrab(dst_inode),
3955+ au_hi_flags(inode, isdir));
3956+ mutex_unlock(&dst_inode->i_mutex);
3957+ if (!isdir
3958+ && h_src->d_inode->i_nlink > 1
3959+ && plink)
3960+ au_plink_append(inode, bdst, h_dst);
3961+ goto out; /* success */
3962+ }
3963+
3964+ /* revert */
4a4d8108 3965+out_rev:
1facf9fc 3966+ h_path.dentry = h_parent;
3967+ mutex_unlock(&dst_inode->i_mutex);
3968+ au_dtime_store(&dt, dst_parent, &h_path);
3969+ h_path.dentry = h_dst;
3970+ if (!isdir)
3971+ rerr = vfsub_unlink(h_dir, &h_path, /*force*/0);
3972+ else
3973+ rerr = vfsub_rmdir(h_dir, &h_path);
3974+ au_dtime_revert(&dt);
3975+ if (rerr) {
3976+ AuIOErr("failed removing broken entry(%d, %d)\n", err, rerr);
3977+ err = -EIO;
3978+ }
3979+
4f0767ce 3980+out:
1facf9fc 3981+ dput(dst_parent);
3982+ return err;
3983+}
3984+
3985+struct au_cpup_single_args {
3986+ int *errp;
3987+ struct dentry *dentry;
3988+ aufs_bindex_t bdst, bsrc;
3989+ loff_t len;
3990+ unsigned int flags;
3991+ struct dentry *dst_parent;
3992+};
3993+
3994+static void au_call_cpup_single(void *args)
3995+{
3996+ struct au_cpup_single_args *a = args;
3997+ *a->errp = au_cpup_single(a->dentry, a->bdst, a->bsrc, a->len,
3998+ a->flags, a->dst_parent);
3999+}
4000+
53392da6
AM
4001+/*
4002+ * prevent SIGXFSZ in copy-up.
4003+ * testing CAP_MKNOD is for generic fs,
4004+ * but CAP_FSETID is for xfs only, currently.
4005+ */
4006+static int au_cpup_sio_test(struct super_block *sb, umode_t mode)
4007+{
4008+ int do_sio;
4009+
4010+ do_sio = 0;
4011+ if (!au_wkq_test()
4012+ && (!au_sbi(sb)->si_plink_maint_pid
4013+ || au_plink_maint(sb, AuLock_NOPLM))) {
4014+ switch (mode & S_IFMT) {
4015+ case S_IFREG:
4016+ /* no condition about RLIMIT_FSIZE and the file size */
4017+ do_sio = 1;
4018+ break;
4019+ case S_IFCHR:
4020+ case S_IFBLK:
4021+ do_sio = !capable(CAP_MKNOD);
4022+ break;
4023+ }
4024+ if (!do_sio)
4025+ do_sio = ((mode & (S_ISUID | S_ISGID))
4026+ && !capable(CAP_FSETID));
4027+ }
4028+
4029+ return do_sio;
4030+}
4031+
1facf9fc 4032+int au_sio_cpup_single(struct dentry *dentry, aufs_bindex_t bdst,
4033+ aufs_bindex_t bsrc, loff_t len, unsigned int flags,
4034+ struct dentry *dst_parent)
4035+{
4036+ int err, wkq_err;
1facf9fc 4037+ struct dentry *h_dentry;
4038+
4039+ h_dentry = au_h_dptr(dentry, bsrc);
53392da6 4040+ if (!au_cpup_sio_test(dentry->d_sb, h_dentry->d_inode->i_mode))
1facf9fc 4041+ err = au_cpup_single(dentry, bdst, bsrc, len, flags,
4042+ dst_parent);
4043+ else {
4044+ struct au_cpup_single_args args = {
4045+ .errp = &err,
4046+ .dentry = dentry,
4047+ .bdst = bdst,
4048+ .bsrc = bsrc,
4049+ .len = len,
4050+ .flags = flags,
4051+ .dst_parent = dst_parent
4052+ };
4053+ wkq_err = au_wkq_wait(au_call_cpup_single, &args);
4054+ if (unlikely(wkq_err))
4055+ err = wkq_err;
4056+ }
4057+
4058+ return err;
4059+}
4060+
4061+/*
4062+ * copyup the @dentry from the first active lower branch to @bdst,
4063+ * using au_cpup_single().
4064+ */
4065+static int au_cpup_simple(struct dentry *dentry, aufs_bindex_t bdst, loff_t len,
4066+ unsigned int flags)
4067+{
4068+ int err;
4069+ aufs_bindex_t bsrc, bend;
4070+
4071+ bend = au_dbend(dentry);
4072+ for (bsrc = bdst + 1; bsrc <= bend; bsrc++)
4073+ if (au_h_dptr(dentry, bsrc))
4074+ break;
4075+
4076+ err = au_lkup_neg(dentry, bdst);
4077+ if (!err) {
4078+ err = au_cpup_single(dentry, bdst, bsrc, len, flags, NULL);
4079+ if (!err)
4080+ return 0; /* success */
4081+
4082+ /* revert */
4083+ au_set_h_dptr(dentry, bdst, NULL);
4084+ au_set_dbstart(dentry, bsrc);
4085+ }
4086+
4087+ return err;
4088+}
4089+
4090+struct au_cpup_simple_args {
4091+ int *errp;
4092+ struct dentry *dentry;
4093+ aufs_bindex_t bdst;
4094+ loff_t len;
4095+ unsigned int flags;
4096+};
4097+
4098+static void au_call_cpup_simple(void *args)
4099+{
4100+ struct au_cpup_simple_args *a = args;
4101+ *a->errp = au_cpup_simple(a->dentry, a->bdst, a->len, a->flags);
4102+}
4103+
4104+int au_sio_cpup_simple(struct dentry *dentry, aufs_bindex_t bdst, loff_t len,
4105+ unsigned int flags)
4106+{
4107+ int err, wkq_err;
1facf9fc 4108+ struct dentry *parent;
4109+ struct inode *h_dir;
4110+
4111+ parent = dget_parent(dentry);
4112+ h_dir = au_h_iptr(parent->d_inode, bdst);
53392da6
AM
4113+ if (!au_test_h_perm_sio(h_dir, MAY_EXEC | MAY_WRITE)
4114+ && !au_cpup_sio_test(dentry->d_sb, dentry->d_inode->i_mode))
1facf9fc 4115+ err = au_cpup_simple(dentry, bdst, len, flags);
4116+ else {
4117+ struct au_cpup_simple_args args = {
4118+ .errp = &err,
4119+ .dentry = dentry,
4120+ .bdst = bdst,
4121+ .len = len,
4122+ .flags = flags
4123+ };
4124+ wkq_err = au_wkq_wait(au_call_cpup_simple, &args);
4125+ if (unlikely(wkq_err))
4126+ err = wkq_err;
4127+ }
4128+
4129+ dput(parent);
4130+ return err;
4131+}
4132+
4133+/* ---------------------------------------------------------------------- */
4134+
4135+/*
4136+ * copyup the deleted file for writing.
4137+ */
4138+static int au_do_cpup_wh(struct dentry *dentry, aufs_bindex_t bdst,
4139+ struct dentry *wh_dentry, struct file *file,
4140+ loff_t len)
4141+{
4142+ int err;
4143+ aufs_bindex_t bstart;
4144+ struct au_dinfo *dinfo;
4145+ struct dentry *h_d_dst, *h_d_start;
4a4d8108 4146+ struct au_hdentry *hdp;
1facf9fc 4147+
4148+ dinfo = au_di(dentry);
1308ab2a 4149+ AuRwMustWriteLock(&dinfo->di_rwsem);
4150+
1facf9fc 4151+ bstart = dinfo->di_bstart;
4a4d8108
AM
4152+ hdp = dinfo->di_hdentry;
4153+ h_d_dst = hdp[0 + bdst].hd_dentry;
1facf9fc 4154+ dinfo->di_bstart = bdst;
4a4d8108 4155+ hdp[0 + bdst].hd_dentry = wh_dentry;
027c5e7a
AM
4156+ if (file) {
4157+ h_d_start = hdp[0 + bstart].hd_dentry;
4a4d8108 4158+ hdp[0 + bstart].hd_dentry = au_hf_top(file)->f_dentry;
027c5e7a 4159+ }
1facf9fc 4160+ err = au_cpup_single(dentry, bdst, bstart, len, !AuCpup_DTIME,
4161+ /*h_parent*/NULL);
027c5e7a
AM
4162+ if (file) {
4163+ if (!err)
4164+ err = au_reopen_nondir(file);
4a4d8108 4165+ hdp[0 + bstart].hd_dentry = h_d_start;
1facf9fc 4166+ }
4a4d8108 4167+ hdp[0 + bdst].hd_dentry = h_d_dst;
1facf9fc 4168+ dinfo->di_bstart = bstart;
4169+
4170+ return err;
4171+}
4172+
4173+static int au_cpup_wh(struct dentry *dentry, aufs_bindex_t bdst, loff_t len,
4174+ struct file *file)
4175+{
4176+ int err;
4177+ struct au_dtime dt;
4178+ struct dentry *parent, *h_parent, *wh_dentry;
4179+ struct au_branch *br;
4180+ struct path h_path;
4181+
4182+ br = au_sbr(dentry->d_sb, bdst);
4183+ parent = dget_parent(dentry);
4184+ h_parent = au_h_dptr(parent, bdst);
4185+ wh_dentry = au_whtmp_lkup(h_parent, br, &dentry->d_name);
4186+ err = PTR_ERR(wh_dentry);
4187+ if (IS_ERR(wh_dentry))
4188+ goto out;
4189+
4190+ h_path.dentry = h_parent;
4191+ h_path.mnt = br->br_mnt;
4192+ au_dtime_store(&dt, parent, &h_path);
4193+ err = au_do_cpup_wh(dentry, bdst, wh_dentry, file, len);
4194+ if (unlikely(err))
4195+ goto out_wh;
4196+
4197+ dget(wh_dentry);
4198+ h_path.dentry = wh_dentry;
4a4d8108
AM
4199+ if (!S_ISDIR(wh_dentry->d_inode->i_mode))
4200+ err = vfsub_unlink(h_parent->d_inode, &h_path, /*force*/0);
4201+ else
4202+ err = vfsub_rmdir(h_parent->d_inode, &h_path);
1facf9fc 4203+ if (unlikely(err)) {
4204+ AuIOErr("failed remove copied-up tmp file %.*s(%d)\n",
4205+ AuDLNPair(wh_dentry), err);
4206+ err = -EIO;
4207+ }
4208+ au_dtime_revert(&dt);
4209+ au_set_hi_wh(dentry->d_inode, bdst, wh_dentry);
4210+
4f0767ce 4211+out_wh:
1facf9fc 4212+ dput(wh_dentry);
4f0767ce 4213+out:
1facf9fc 4214+ dput(parent);
4215+ return err;
4216+}
4217+
4218+struct au_cpup_wh_args {
4219+ int *errp;
4220+ struct dentry *dentry;
4221+ aufs_bindex_t bdst;
4222+ loff_t len;
4223+ struct file *file;
4224+};
4225+
4226+static void au_call_cpup_wh(void *args)
4227+{
4228+ struct au_cpup_wh_args *a = args;
4229+ *a->errp = au_cpup_wh(a->dentry, a->bdst, a->len, a->file);
4230+}
4231+
4232+int au_sio_cpup_wh(struct dentry *dentry, aufs_bindex_t bdst, loff_t len,
4233+ struct file *file)
4234+{
4235+ int err, wkq_err;
4236+ struct dentry *parent, *h_orph, *h_parent, *h_dentry;
4237+ struct inode *dir, *h_dir, *h_tmpdir, *h_inode;
4238+ struct au_wbr *wbr;
4239+
4240+ parent = dget_parent(dentry);
4241+ dir = parent->d_inode;
4242+ h_orph = NULL;
4243+ h_parent = NULL;
4244+ h_dir = au_igrab(au_h_iptr(dir, bdst));
4245+ h_tmpdir = h_dir;
4246+ if (!h_dir->i_nlink) {
4247+ wbr = au_sbr(dentry->d_sb, bdst)->br_wbr;
4248+ h_orph = wbr->wbr_orph;
4249+
4250+ h_parent = dget(au_h_dptr(parent, bdst));
1facf9fc 4251+ au_set_h_dptr(parent, bdst, dget(h_orph));
4252+ h_tmpdir = h_orph->d_inode;
1facf9fc 4253+ au_set_h_iptr(dir, bdst, au_igrab(h_tmpdir), /*flags*/0);
4254+
4255+ /* this temporary unlock is safe */
4256+ if (file)
4a4d8108 4257+ h_dentry = au_hf_top(file)->f_dentry;
1facf9fc 4258+ else
4259+ h_dentry = au_h_dptr(dentry, au_dbstart(dentry));
4260+ h_inode = h_dentry->d_inode;
4261+ IMustLock(h_inode);
4262+ mutex_unlock(&h_inode->i_mutex);
dece6358 4263+ mutex_lock_nested(&h_tmpdir->i_mutex, AuLsc_I_PARENT3);
1facf9fc 4264+ mutex_lock_nested(&h_inode->i_mutex, AuLsc_I_CHILD);
4a4d8108 4265+ /* todo: au_h_open_pre()? */
1facf9fc 4266+ }
4267+
53392da6
AM
4268+ if (!au_test_h_perm_sio(h_tmpdir, MAY_EXEC | MAY_WRITE)
4269+ && !au_cpup_sio_test(dentry->d_sb, dentry->d_inode->i_mode))
1facf9fc 4270+ err = au_cpup_wh(dentry, bdst, len, file);
4271+ else {
4272+ struct au_cpup_wh_args args = {
4273+ .errp = &err,
4274+ .dentry = dentry,
4275+ .bdst = bdst,
4276+ .len = len,
4277+ .file = file
4278+ };
4279+ wkq_err = au_wkq_wait(au_call_cpup_wh, &args);
4280+ if (unlikely(wkq_err))
4281+ err = wkq_err;
4282+ }
4283+
4284+ if (h_orph) {
4285+ mutex_unlock(&h_tmpdir->i_mutex);
4a4d8108 4286+ /* todo: au_h_open_post()? */
1facf9fc 4287+ au_set_h_iptr(dir, bdst, au_igrab(h_dir), /*flags*/0);
1facf9fc 4288+ au_set_h_dptr(parent, bdst, h_parent);
4289+ }
4290+ iput(h_dir);
4291+ dput(parent);
4292+
4293+ return err;
4294+}
4295+
4296+/* ---------------------------------------------------------------------- */
4297+
4298+/*
4299+ * generic routine for both of copy-up and copy-down.
4300+ */
4301+/* cf. revalidate function in file.c */
4302+int au_cp_dirs(struct dentry *dentry, aufs_bindex_t bdst,
4303+ int (*cp)(struct dentry *dentry, aufs_bindex_t bdst,
4304+ struct dentry *h_parent, void *arg),
4305+ void *arg)
4306+{
4307+ int err;
4308+ struct au_pin pin;
4309+ struct dentry *d, *parent, *h_parent, *real_parent;
4310+
4311+ err = 0;
4312+ parent = dget_parent(dentry);
4313+ if (IS_ROOT(parent))
4314+ goto out;
4315+
4316+ au_pin_init(&pin, dentry, bdst, AuLsc_DI_PARENT2, AuLsc_I_PARENT2,
4317+ au_opt_udba(dentry->d_sb), AuPin_MNT_WRITE);
4318+
4319+ /* do not use au_dpage */
4320+ real_parent = parent;
4321+ while (1) {
4322+ dput(parent);
4323+ parent = dget_parent(dentry);
4324+ h_parent = au_h_dptr(parent, bdst);
4325+ if (h_parent)
4326+ goto out; /* success */
4327+
4328+ /* find top dir which is necessary to cpup */
4329+ do {
4330+ d = parent;
4331+ dput(parent);
4332+ parent = dget_parent(d);
4333+ di_read_lock_parent3(parent, !AuLock_IR);
4334+ h_parent = au_h_dptr(parent, bdst);
4335+ di_read_unlock(parent, !AuLock_IR);
4336+ } while (!h_parent);
4337+
4338+ if (d != real_parent)
4339+ di_write_lock_child3(d);
4340+
4341+ /* somebody else might create while we were sleeping */
4342+ if (!au_h_dptr(d, bdst) || !au_h_dptr(d, bdst)->d_inode) {
4343+ if (au_h_dptr(d, bdst))
4344+ au_update_dbstart(d);
4345+
4346+ au_pin_set_dentry(&pin, d);
4347+ err = au_do_pin(&pin);
4348+ if (!err) {
4349+ err = cp(d, bdst, h_parent, arg);
4350+ au_unpin(&pin);
4351+ }
4352+ }
4353+
4354+ if (d != real_parent)
4355+ di_write_unlock(d);
4356+ if (unlikely(err))
4357+ break;
4358+ }
4359+
4f0767ce 4360+out:
1facf9fc 4361+ dput(parent);
4362+ return err;
4363+}
4364+
4365+static int au_cpup_dir(struct dentry *dentry, aufs_bindex_t bdst,
4366+ struct dentry *h_parent __maybe_unused ,
4367+ void *arg __maybe_unused)
4368+{
4369+ return au_sio_cpup_simple(dentry, bdst, -1, AuCpup_DTIME);
4370+}
4371+
4372+int au_cpup_dirs(struct dentry *dentry, aufs_bindex_t bdst)
4373+{
4374+ return au_cp_dirs(dentry, bdst, au_cpup_dir, NULL);
4375+}
4376+
4377+int au_test_and_cpup_dirs(struct dentry *dentry, aufs_bindex_t bdst)
4378+{
4379+ int err;
4380+ struct dentry *parent;
4381+ struct inode *dir;
4382+
4383+ parent = dget_parent(dentry);
4384+ dir = parent->d_inode;
4385+ err = 0;
4386+ if (au_h_iptr(dir, bdst))
4387+ goto out;
4388+
4389+ di_read_unlock(parent, AuLock_IR);
4390+ di_write_lock_parent(parent);
4391+ /* someone else might change our inode while we were sleeping */
4392+ if (!au_h_iptr(dir, bdst))
4393+ err = au_cpup_dirs(dentry, bdst);
4394+ di_downgrade_lock(parent, AuLock_IR);
4395+
4f0767ce 4396+out:
1facf9fc 4397+ dput(parent);
4398+ return err;
4399+}
7f207e10
AM
4400diff -urN /usr/share/empty/fs/aufs/cpup.h linux/fs/aufs/cpup.h
4401--- /usr/share/empty/fs/aufs/cpup.h 1970-01-01 01:00:00.000000000 +0100
0c3ec466 4402+++ linux/fs/aufs/cpup.h 2012-07-22 19:57:03.161004531 +0200
f6c5ef8b 4403@@ -0,0 +1,81 @@
1facf9fc 4404+/*
f6c5ef8b 4405+ * Copyright (C) 2005-2012 Junjiro R. Okajima
1facf9fc 4406+ *
4407+ * This program, aufs is free software; you can redistribute it and/or modify
4408+ * it under the terms of the GNU General Public License as published by
4409+ * the Free Software Foundation; either version 2 of the License, or
4410+ * (at your option) any later version.
dece6358
AM
4411+ *
4412+ * This program is distributed in the hope that it will be useful,
4413+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
4414+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
4415+ * GNU General Public License for more details.
4416+ *
4417+ * You should have received a copy of the GNU General Public License
4418+ * along with this program; if not, write to the Free Software
4419+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 4420+ */
4421+
4422+/*
4423+ * copy-up/down functions
4424+ */
4425+
4426+#ifndef __AUFS_CPUP_H__
4427+#define __AUFS_CPUP_H__
4428+
4429+#ifdef __KERNEL__
4430+
dece6358 4431+#include <linux/path.h>
1facf9fc 4432+
dece6358
AM
4433+struct inode;
4434+struct file;
4435+
1facf9fc 4436+void au_cpup_attr_flags(struct inode *dst, struct inode *src);
4437+void au_cpup_attr_timesizes(struct inode *inode);
4438+void au_cpup_attr_nlink(struct inode *inode, int force);
4439+void au_cpup_attr_changeable(struct inode *inode);
4440+void au_cpup_igen(struct inode *inode, struct inode *h_inode);
4441+void au_cpup_attr_all(struct inode *inode, int force);
4442+
4443+/* ---------------------------------------------------------------------- */
4444+
4445+/* cpup flags */
4446+#define AuCpup_DTIME 1 /* do dtime_store/revert */
4447+#define AuCpup_KEEPLINO (1 << 1) /* do not clear the lower xino,
4448+ for link(2) */
4449+#define au_ftest_cpup(flags, name) ((flags) & AuCpup_##name)
7f207e10
AM
4450+#define au_fset_cpup(flags, name) \
4451+ do { (flags) |= AuCpup_##name; } while (0)
4452+#define au_fclr_cpup(flags, name) \
4453+ do { (flags) &= ~AuCpup_##name; } while (0)
1facf9fc 4454+
4455+int au_copy_file(struct file *dst, struct file *src, loff_t len);
4456+int au_sio_cpup_single(struct dentry *dentry, aufs_bindex_t bdst,
4457+ aufs_bindex_t bsrc, loff_t len, unsigned int flags,
4458+ struct dentry *dst_parent);
4459+int au_sio_cpup_simple(struct dentry *dentry, aufs_bindex_t bdst, loff_t len,
4460+ unsigned int flags);
4461+int au_sio_cpup_wh(struct dentry *dentry, aufs_bindex_t bdst, loff_t len,
4462+ struct file *file);
4463+
4464+int au_cp_dirs(struct dentry *dentry, aufs_bindex_t bdst,
4465+ int (*cp)(struct dentry *dentry, aufs_bindex_t bdst,
4466+ struct dentry *h_parent, void *arg),
4467+ void *arg);
4468+int au_cpup_dirs(struct dentry *dentry, aufs_bindex_t bdst);
4469+int au_test_and_cpup_dirs(struct dentry *dentry, aufs_bindex_t bdst);
4470+
4471+/* ---------------------------------------------------------------------- */
4472+
4473+/* keep timestamps when copyup */
4474+struct au_dtime {
4475+ struct dentry *dt_dentry;
4476+ struct path dt_h_path;
4477+ struct timespec dt_atime, dt_mtime;
4478+};
4479+void au_dtime_store(struct au_dtime *dt, struct dentry *dentry,
4480+ struct path *h_path);
4481+void au_dtime_revert(struct au_dtime *dt);
4482+
4483+#endif /* __KERNEL__ */
4484+#endif /* __AUFS_CPUP_H__ */
7f207e10
AM
4485diff -urN /usr/share/empty/fs/aufs/dbgaufs.c linux/fs/aufs/dbgaufs.c
4486--- /usr/share/empty/fs/aufs/dbgaufs.c 1970-01-01 01:00:00.000000000 +0100
0c3ec466 4487+++ linux/fs/aufs/dbgaufs.c 2012-07-22 19:57:03.161004531 +0200
4a4d8108 4488@@ -0,0 +1,334 @@
1facf9fc 4489+/*
f6c5ef8b 4490+ * Copyright (C) 2005-2012 Junjiro R. Okajima
1facf9fc 4491+ *
4492+ * This program, aufs is free software; you can redistribute it and/or modify
4493+ * it under the terms of the GNU General Public License as published by
4494+ * the Free Software Foundation; either version 2 of the License, or
4495+ * (at your option) any later version.
dece6358
AM
4496+ *
4497+ * This program is distributed in the hope that it will be useful,
4498+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
4499+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
4500+ * GNU General Public License for more details.
4501+ *
4502+ * You should have received a copy of the GNU General Public License
4503+ * along with this program; if not, write to the Free Software
4504+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 4505+ */
4506+
4507+/*
4508+ * debugfs interface
4509+ */
4510+
4511+#include <linux/debugfs.h>
4512+#include "aufs.h"
4513+
4514+#ifndef CONFIG_SYSFS
4515+#error DEBUG_FS depends upon SYSFS
4516+#endif
4517+
4518+static struct dentry *dbgaufs;
4519+static const mode_t dbgaufs_mode = S_IRUSR | S_IRGRP | S_IROTH;
4520+
4521+/* 20 is max digits length of ulong 64 */
4522+struct dbgaufs_arg {
4523+ int n;
4524+ char a[20 * 4];
4525+};
4526+
4527+/*
4528+ * common function for all XINO files
4529+ */
4530+static int dbgaufs_xi_release(struct inode *inode __maybe_unused,
4531+ struct file *file)
4532+{
4533+ kfree(file->private_data);
4534+ return 0;
4535+}
4536+
4537+static int dbgaufs_xi_open(struct file *xf, struct file *file, int do_fcnt)
4538+{
4539+ int err;
4540+ struct kstat st;
4541+ struct dbgaufs_arg *p;
4542+
4543+ err = -ENOMEM;
4544+ p = kmalloc(sizeof(*p), GFP_NOFS);
4545+ if (unlikely(!p))
4546+ goto out;
4547+
4548+ err = 0;
4549+ p->n = 0;
4550+ file->private_data = p;
4551+ if (!xf)
4552+ goto out;
4553+
4554+ err = vfs_getattr(xf->f_vfsmnt, xf->f_dentry, &st);
4555+ if (!err) {
4556+ if (do_fcnt)
4557+ p->n = snprintf
4558+ (p->a, sizeof(p->a), "%ld, %llux%lu %lld\n",
4559+ (long)file_count(xf), st.blocks, st.blksize,
4560+ (long long)st.size);
4561+ else
4562+ p->n = snprintf(p->a, sizeof(p->a), "%llux%lu %lld\n",
4563+ st.blocks, st.blksize,
4564+ (long long)st.size);
4565+ AuDebugOn(p->n >= sizeof(p->a));
4566+ } else {
4567+ p->n = snprintf(p->a, sizeof(p->a), "err %d\n", err);
4568+ err = 0;
4569+ }
4570+
4f0767ce 4571+out:
1facf9fc 4572+ return err;
4573+
4574+}
4575+
4576+static ssize_t dbgaufs_xi_read(struct file *file, char __user *buf,
4577+ size_t count, loff_t *ppos)
4578+{
4579+ struct dbgaufs_arg *p;
4580+
4581+ p = file->private_data;
4582+ return simple_read_from_buffer(buf, count, ppos, p->a, p->n);
4583+}
4584+
4585+/* ---------------------------------------------------------------------- */
4586+
4587+static int dbgaufs_xib_open(struct inode *inode, struct file *file)
4588+{
4589+ int err;
4590+ struct au_sbinfo *sbinfo;
4591+ struct super_block *sb;
4592+
4593+ sbinfo = inode->i_private;
4594+ sb = sbinfo->si_sb;
4595+ si_noflush_read_lock(sb);
4596+ err = dbgaufs_xi_open(sbinfo->si_xib, file, /*do_fcnt*/0);
4597+ si_read_unlock(sb);
4598+ return err;
4599+}
4600+
4601+static const struct file_operations dbgaufs_xib_fop = {
4a4d8108 4602+ .owner = THIS_MODULE,
1facf9fc 4603+ .open = dbgaufs_xib_open,
4604+ .release = dbgaufs_xi_release,
4605+ .read = dbgaufs_xi_read
4606+};
4607+
4608+/* ---------------------------------------------------------------------- */
4609+
4610+#define DbgaufsXi_PREFIX "xi"
4611+
4612+static int dbgaufs_xino_open(struct inode *inode, struct file *file)
4613+{
4614+ int err;
4615+ long l;
4616+ struct au_sbinfo *sbinfo;
4617+ struct super_block *sb;
4618+ struct file *xf;
4619+ struct qstr *name;
4620+
4621+ err = -ENOENT;
4622+ xf = NULL;
4623+ name = &file->f_dentry->d_name;
4624+ if (unlikely(name->len < sizeof(DbgaufsXi_PREFIX)
4625+ || memcmp(name->name, DbgaufsXi_PREFIX,
4626+ sizeof(DbgaufsXi_PREFIX) - 1)))
4627+ goto out;
9dbd164d 4628+ err = kstrtol(name->name + sizeof(DbgaufsXi_PREFIX) - 1, 10, &l);
1facf9fc 4629+ if (unlikely(err))
4630+ goto out;
4631+
4632+ sbinfo = inode->i_private;
4633+ sb = sbinfo->si_sb;
4634+ si_noflush_read_lock(sb);
4635+ if (l <= au_sbend(sb)) {
4636+ xf = au_sbr(sb, (aufs_bindex_t)l)->br_xino.xi_file;
4637+ err = dbgaufs_xi_open(xf, file, /*do_fcnt*/1);
4638+ } else
4639+ err = -ENOENT;
4640+ si_read_unlock(sb);
4641+
4f0767ce 4642+out:
1facf9fc 4643+ return err;
4644+}
4645+
4646+static const struct file_operations dbgaufs_xino_fop = {
4a4d8108 4647+ .owner = THIS_MODULE,
1facf9fc 4648+ .open = dbgaufs_xino_open,
4649+ .release = dbgaufs_xi_release,
4650+ .read = dbgaufs_xi_read
4651+};
4652+
4653+void dbgaufs_brs_del(struct super_block *sb, aufs_bindex_t bindex)
4654+{
4655+ aufs_bindex_t bend;
4656+ struct au_branch *br;
4657+ struct au_xino_file *xi;
4658+
4659+ if (!au_sbi(sb)->si_dbgaufs)
4660+ return;
4661+
4662+ bend = au_sbend(sb);
4663+ for (; bindex <= bend; bindex++) {
4664+ br = au_sbr(sb, bindex);
4665+ xi = &br->br_xino;
4666+ if (xi->xi_dbgaufs) {
4667+ debugfs_remove(xi->xi_dbgaufs);
4668+ xi->xi_dbgaufs = NULL;
4669+ }
4670+ }
4671+}
4672+
4673+void dbgaufs_brs_add(struct super_block *sb, aufs_bindex_t bindex)
4674+{
4675+ struct au_sbinfo *sbinfo;
4676+ struct dentry *parent;
4677+ struct au_branch *br;
4678+ struct au_xino_file *xi;
4679+ aufs_bindex_t bend;
4680+ char name[sizeof(DbgaufsXi_PREFIX) + 5]; /* "xi" bindex NULL */
4681+
4682+ sbinfo = au_sbi(sb);
4683+ parent = sbinfo->si_dbgaufs;
4684+ if (!parent)
4685+ return;
4686+
4687+ bend = au_sbend(sb);
4688+ for (; bindex <= bend; bindex++) {
4689+ snprintf(name, sizeof(name), DbgaufsXi_PREFIX "%d", bindex);
4690+ br = au_sbr(sb, bindex);
4691+ xi = &br->br_xino;
4692+ AuDebugOn(xi->xi_dbgaufs);
4693+ xi->xi_dbgaufs = debugfs_create_file(name, dbgaufs_mode, parent,
4694+ sbinfo, &dbgaufs_xino_fop);
4695+ /* ignore an error */
4696+ if (unlikely(!xi->xi_dbgaufs))
4697+ AuWarn1("failed %s under debugfs\n", name);
4698+ }
4699+}
4700+
4701+/* ---------------------------------------------------------------------- */
4702+
4703+#ifdef CONFIG_AUFS_EXPORT
4704+static int dbgaufs_xigen_open(struct inode *inode, struct file *file)
4705+{
4706+ int err;
4707+ struct au_sbinfo *sbinfo;
4708+ struct super_block *sb;
4709+
4710+ sbinfo = inode->i_private;
4711+ sb = sbinfo->si_sb;
4712+ si_noflush_read_lock(sb);
4713+ err = dbgaufs_xi_open(sbinfo->si_xigen, file, /*do_fcnt*/0);
4714+ si_read_unlock(sb);
4715+ return err;
4716+}
4717+
4718+static const struct file_operations dbgaufs_xigen_fop = {
4a4d8108 4719+ .owner = THIS_MODULE,
1facf9fc 4720+ .open = dbgaufs_xigen_open,
4721+ .release = dbgaufs_xi_release,
4722+ .read = dbgaufs_xi_read
4723+};
4724+
4725+static int dbgaufs_xigen_init(struct au_sbinfo *sbinfo)
4726+{
4727+ int err;
4728+
dece6358
AM
4729+ /*
4730+ * This function is a dynamic '__init' fucntion actually,
4731+ * so the tiny check for si_rwsem is unnecessary.
4732+ */
4733+ /* AuRwMustWriteLock(&sbinfo->si_rwsem); */
4734+
1facf9fc 4735+ err = -EIO;
4736+ sbinfo->si_dbgaufs_xigen = debugfs_create_file
4737+ ("xigen", dbgaufs_mode, sbinfo->si_dbgaufs, sbinfo,
4738+ &dbgaufs_xigen_fop);
4739+ if (sbinfo->si_dbgaufs_xigen)
4740+ err = 0;
4741+
4742+ return err;
4743+}
4744+#else
4745+static int dbgaufs_xigen_init(struct au_sbinfo *sbinfo)
4746+{
4747+ return 0;
4748+}
4749+#endif /* CONFIG_AUFS_EXPORT */
4750+
4751+/* ---------------------------------------------------------------------- */
4752+
4753+void dbgaufs_si_fin(struct au_sbinfo *sbinfo)
4754+{
dece6358
AM
4755+ /*
4756+ * This function is a dynamic '__init' fucntion actually,
4757+ * so the tiny check for si_rwsem is unnecessary.
4758+ */
4759+ /* AuRwMustWriteLock(&sbinfo->si_rwsem); */
4760+
1facf9fc 4761+ debugfs_remove_recursive(sbinfo->si_dbgaufs);
4762+ sbinfo->si_dbgaufs = NULL;
4763+ kobject_put(&sbinfo->si_kobj);
4764+}
4765+
4766+int dbgaufs_si_init(struct au_sbinfo *sbinfo)
4767+{
4768+ int err;
4769+ char name[SysaufsSiNameLen];
4770+
dece6358
AM
4771+ /*
4772+ * This function is a dynamic '__init' fucntion actually,
4773+ * so the tiny check for si_rwsem is unnecessary.
4774+ */
4775+ /* AuRwMustWriteLock(&sbinfo->si_rwsem); */
4776+
1facf9fc 4777+ err = -ENOENT;
4778+ if (!dbgaufs) {
4779+ AuErr1("/debug/aufs is uninitialized\n");
4780+ goto out;
4781+ }
4782+
4783+ err = -EIO;
4784+ sysaufs_name(sbinfo, name);
4785+ sbinfo->si_dbgaufs = debugfs_create_dir(name, dbgaufs);
4786+ if (unlikely(!sbinfo->si_dbgaufs))
4787+ goto out;
4788+ kobject_get(&sbinfo->si_kobj);
4789+
4790+ sbinfo->si_dbgaufs_xib = debugfs_create_file
4791+ ("xib", dbgaufs_mode, sbinfo->si_dbgaufs, sbinfo,
4792+ &dbgaufs_xib_fop);
4793+ if (unlikely(!sbinfo->si_dbgaufs_xib))
4794+ goto out_dir;
4795+
4796+ err = dbgaufs_xigen_init(sbinfo);
4797+ if (!err)
4798+ goto out; /* success */
4799+
4f0767ce 4800+out_dir:
1facf9fc 4801+ dbgaufs_si_fin(sbinfo);
4f0767ce 4802+out:
1facf9fc 4803+ return err;
4804+}
4805+
4806+/* ---------------------------------------------------------------------- */
4807+
4808+void dbgaufs_fin(void)
4809+{
4810+ debugfs_remove(dbgaufs);
4811+}
4812+
4813+int __init dbgaufs_init(void)
4814+{
4815+ int err;
4816+
4817+ err = -EIO;
4818+ dbgaufs = debugfs_create_dir(AUFS_NAME, NULL);
4819+ if (dbgaufs)
4820+ err = 0;
4821+ return err;
4822+}
7f207e10
AM
4823diff -urN /usr/share/empty/fs/aufs/dbgaufs.h linux/fs/aufs/dbgaufs.h
4824--- /usr/share/empty/fs/aufs/dbgaufs.h 1970-01-01 01:00:00.000000000 +0100
0c3ec466 4825+++ linux/fs/aufs/dbgaufs.h 2012-07-22 19:57:03.161004531 +0200
f6c5ef8b 4826@@ -0,0 +1,49 @@
1facf9fc 4827+/*
f6c5ef8b 4828+ * Copyright (C) 2005-2012 Junjiro R. Okajima
1facf9fc 4829+ *
4830+ * This program, aufs is free software; you can redistribute it and/or modify
4831+ * it under the terms of the GNU General Public License as published by
4832+ * the Free Software Foundation; either version 2 of the License, or
4833+ * (at your option) any later version.
dece6358
AM
4834+ *
4835+ * This program is distributed in the hope that it will be useful,
4836+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
4837+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
4838+ * GNU General Public License for more details.
4839+ *
4840+ * You should have received a copy of the GNU General Public License
4841+ * along with this program; if not, write to the Free Software
4842+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 4843+ */
4844+
4845+/*
4846+ * debugfs interface
4847+ */
4848+
4849+#ifndef __DBGAUFS_H__
4850+#define __DBGAUFS_H__
4851+
4852+#ifdef __KERNEL__
4853+
dece6358 4854+struct super_block;
1facf9fc 4855+struct au_sbinfo;
dece6358 4856+
1facf9fc 4857+#ifdef CONFIG_DEBUG_FS
4858+/* dbgaufs.c */
4859+void dbgaufs_brs_del(struct super_block *sb, aufs_bindex_t bindex);
4860+void dbgaufs_brs_add(struct super_block *sb, aufs_bindex_t bindex);
4861+void dbgaufs_si_fin(struct au_sbinfo *sbinfo);
4862+int dbgaufs_si_init(struct au_sbinfo *sbinfo);
4863+void dbgaufs_fin(void);
4864+int __init dbgaufs_init(void);
1facf9fc 4865+#else
4a4d8108
AM
4866+AuStubVoid(dbgaufs_brs_del, struct super_block *sb, aufs_bindex_t bindex)
4867+AuStubVoid(dbgaufs_brs_add, struct super_block *sb, aufs_bindex_t bindex)
4868+AuStubVoid(dbgaufs_si_fin, struct au_sbinfo *sbinfo)
4869+AuStubInt0(dbgaufs_si_init, struct au_sbinfo *sbinfo)
4870+AuStubVoid(dbgaufs_fin, void)
4871+AuStubInt0(__init dbgaufs_init, void)
1facf9fc 4872+#endif /* CONFIG_DEBUG_FS */
4873+
4874+#endif /* __KERNEL__ */
4875+#endif /* __DBGAUFS_H__ */
7f207e10
AM
4876diff -urN /usr/share/empty/fs/aufs/dcsub.c linux/fs/aufs/dcsub.c
4877--- /usr/share/empty/fs/aufs/dcsub.c 1970-01-01 01:00:00.000000000 +0100
0c3ec466 4878+++ linux/fs/aufs/dcsub.c 2012-07-22 19:57:03.161004531 +0200
027c5e7a 4879@@ -0,0 +1,243 @@
1facf9fc 4880+/*
f6c5ef8b 4881+ * Copyright (C) 2005-2012 Junjiro R. Okajima
1facf9fc 4882+ *
4883+ * This program, aufs is free software; you can redistribute it and/or modify
4884+ * it under the terms of the GNU General Public License as published by
4885+ * the Free Software Foundation; either version 2 of the License, or
4886+ * (at your option) any later version.
dece6358
AM
4887+ *
4888+ * This program is distributed in the hope that it will be useful,
4889+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
4890+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
4891+ * GNU General Public License for more details.
4892+ *
4893+ * You should have received a copy of the GNU General Public License
4894+ * along with this program; if not, write to the Free Software
4895+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 4896+ */
4897+
4898+/*
4899+ * sub-routines for dentry cache
4900+ */
4901+
4902+#include "aufs.h"
4903+
4904+static void au_dpage_free(struct au_dpage *dpage)
4905+{
4906+ int i;
4907+ struct dentry **p;
4908+
4909+ p = dpage->dentries;
4910+ for (i = 0; i < dpage->ndentry; i++)
4911+ dput(*p++);
4912+ free_page((unsigned long)dpage->dentries);
4913+}
4914+
4915+int au_dpages_init(struct au_dcsub_pages *dpages, gfp_t gfp)
4916+{
4917+ int err;
4918+ void *p;
4919+
4920+ err = -ENOMEM;
4921+ dpages->dpages = kmalloc(sizeof(*dpages->dpages), gfp);
4922+ if (unlikely(!dpages->dpages))
4923+ goto out;
4924+
4925+ p = (void *)__get_free_page(gfp);
4926+ if (unlikely(!p))
4927+ goto out_dpages;
4928+
4929+ dpages->dpages[0].ndentry = 0;
4930+ dpages->dpages[0].dentries = p;
4931+ dpages->ndpage = 1;
4932+ return 0; /* success */
4933+
4f0767ce 4934+out_dpages:
1facf9fc 4935+ kfree(dpages->dpages);
4f0767ce 4936+out:
1facf9fc 4937+ return err;
4938+}
4939+
4940+void au_dpages_free(struct au_dcsub_pages *dpages)
4941+{
4942+ int i;
4943+ struct au_dpage *p;
4944+
4945+ p = dpages->dpages;
4946+ for (i = 0; i < dpages->ndpage; i++)
4947+ au_dpage_free(p++);
4948+ kfree(dpages->dpages);
4949+}
4950+
4951+static int au_dpages_append(struct au_dcsub_pages *dpages,
4952+ struct dentry *dentry, gfp_t gfp)
4953+{
4954+ int err, sz;
4955+ struct au_dpage *dpage;
4956+ void *p;
4957+
4958+ dpage = dpages->dpages + dpages->ndpage - 1;
4959+ sz = PAGE_SIZE / sizeof(dentry);
4960+ if (unlikely(dpage->ndentry >= sz)) {
4961+ AuLabel(new dpage);
4962+ err = -ENOMEM;
4963+ sz = dpages->ndpage * sizeof(*dpages->dpages);
4964+ p = au_kzrealloc(dpages->dpages, sz,
4965+ sz + sizeof(*dpages->dpages), gfp);
4966+ if (unlikely(!p))
4967+ goto out;
4968+
4969+ dpages->dpages = p;
4970+ dpage = dpages->dpages + dpages->ndpage;
4971+ p = (void *)__get_free_page(gfp);
4972+ if (unlikely(!p))
4973+ goto out;
4974+
4975+ dpage->ndentry = 0;
4976+ dpage->dentries = p;
4977+ dpages->ndpage++;
4978+ }
4979+
027c5e7a
AM
4980+ AuDebugOn(!dentry->d_count);
4981+ dpage->dentries[dpage->ndentry++] = dget_dlock(dentry);
1facf9fc 4982+ return 0; /* success */
4983+
4f0767ce 4984+out:
1facf9fc 4985+ return err;
4986+}
4987+
4988+int au_dcsub_pages(struct au_dcsub_pages *dpages, struct dentry *root,
4989+ au_dpages_test test, void *arg)
4990+{
4991+ int err;
027c5e7a 4992+ struct dentry *this_parent;
1facf9fc 4993+ struct list_head *next;
4994+ struct super_block *sb = root->d_sb;
4995+
4996+ err = 0;
027c5e7a
AM
4997+ write_seqlock(&rename_lock);
4998+ this_parent = root;
4999+ spin_lock(&this_parent->d_lock);
4f0767ce 5000+repeat:
1facf9fc 5001+ next = this_parent->d_subdirs.next;
4f0767ce 5002+resume:
1facf9fc 5003+ if (this_parent->d_sb == sb
5004+ && !IS_ROOT(this_parent)
027c5e7a
AM
5005+ && au_di(this_parent)
5006+ && this_parent->d_count
1facf9fc 5007+ && (!test || test(this_parent, arg))) {
5008+ err = au_dpages_append(dpages, this_parent, GFP_ATOMIC);
5009+ if (unlikely(err))
5010+ goto out;
5011+ }
5012+
5013+ while (next != &this_parent->d_subdirs) {
5014+ struct list_head *tmp = next;
5015+ struct dentry *dentry = list_entry(tmp, struct dentry,
5016+ d_u.d_child);
027c5e7a 5017+
1facf9fc 5018+ next = tmp->next;
027c5e7a
AM
5019+ spin_lock_nested(&dentry->d_lock, DENTRY_D_LOCK_NESTED);
5020+ if (dentry->d_count) {
5021+ if (!list_empty(&dentry->d_subdirs)) {
5022+ spin_unlock(&this_parent->d_lock);
5023+ spin_release(&dentry->d_lock.dep_map, 1,
5024+ _RET_IP_);
5025+ this_parent = dentry;
5026+ spin_acquire(&this_parent->d_lock.dep_map, 0, 1,
5027+ _RET_IP_);
5028+ goto repeat;
5029+ }
5030+ if (dentry->d_sb == sb
5031+ && au_di(dentry)
5032+ && (!test || test(dentry, arg)))
5033+ err = au_dpages_append(dpages, dentry,
5034+ GFP_ATOMIC);
1facf9fc 5035+ }
027c5e7a
AM
5036+ spin_unlock(&dentry->d_lock);
5037+ if (unlikely(err))
5038+ goto out;
1facf9fc 5039+ }
5040+
5041+ if (this_parent != root) {
027c5e7a
AM
5042+ struct dentry *tmp;
5043+ struct dentry *child;
5044+
5045+ tmp = this_parent->d_parent;
5046+ rcu_read_lock();
5047+ spin_unlock(&this_parent->d_lock);
5048+ child = this_parent;
5049+ this_parent = tmp;
5050+ spin_lock(&this_parent->d_lock);
5051+ rcu_read_unlock();
5052+ next = child->d_u.d_child.next;
1facf9fc 5053+ goto resume;
5054+ }
027c5e7a 5055+
4f0767ce 5056+out:
027c5e7a
AM
5057+ spin_unlock(&this_parent->d_lock);
5058+ write_sequnlock(&rename_lock);
1facf9fc 5059+ return err;
5060+}
5061+
5062+int au_dcsub_pages_rev(struct au_dcsub_pages *dpages, struct dentry *dentry,
5063+ int do_include, au_dpages_test test, void *arg)
5064+{
5065+ int err;
5066+
5067+ err = 0;
027c5e7a
AM
5068+ write_seqlock(&rename_lock);
5069+ spin_lock(&dentry->d_lock);
5070+ if (do_include
5071+ && dentry->d_count
5072+ && (!test || test(dentry, arg)))
1facf9fc 5073+ err = au_dpages_append(dpages, dentry, GFP_ATOMIC);
027c5e7a
AM
5074+ spin_unlock(&dentry->d_lock);
5075+ if (unlikely(err))
5076+ goto out;
5077+
5078+ /*
5079+ * vfsmount_lock is unnecessary since this is a traverse in a single
5080+ * mount
5081+ */
1facf9fc 5082+ while (!IS_ROOT(dentry)) {
027c5e7a
AM
5083+ dentry = dentry->d_parent; /* rename_lock is locked */
5084+ spin_lock(&dentry->d_lock);
5085+ if (dentry->d_count
5086+ && (!test || test(dentry, arg)))
1facf9fc 5087+ err = au_dpages_append(dpages, dentry, GFP_ATOMIC);
027c5e7a
AM
5088+ spin_unlock(&dentry->d_lock);
5089+ if (unlikely(err))
5090+ break;
1facf9fc 5091+ }
5092+
4f0767ce 5093+out:
027c5e7a 5094+ write_sequnlock(&rename_lock);
1facf9fc 5095+ return err;
5096+}
5097+
027c5e7a
AM
5098+static inline int au_dcsub_dpages_aufs(struct dentry *dentry, void *arg)
5099+{
5100+ return au_di(dentry) && dentry->d_sb == arg;
5101+}
5102+
5103+int au_dcsub_pages_rev_aufs(struct au_dcsub_pages *dpages,
5104+ struct dentry *dentry, int do_include)
5105+{
5106+ return au_dcsub_pages_rev(dpages, dentry, do_include,
5107+ au_dcsub_dpages_aufs, dentry->d_sb);
5108+}
5109+
4a4d8108 5110+int au_test_subdir(struct dentry *d1, struct dentry *d2)
1facf9fc 5111+{
4a4d8108
AM
5112+ struct path path[2] = {
5113+ {
5114+ .dentry = d1
5115+ },
5116+ {
5117+ .dentry = d2
5118+ }
5119+ };
1facf9fc 5120+
4a4d8108 5121+ return path_is_under(path + 0, path + 1);
1facf9fc 5122+}
7f207e10
AM
5123diff -urN /usr/share/empty/fs/aufs/dcsub.h linux/fs/aufs/dcsub.h
5124--- /usr/share/empty/fs/aufs/dcsub.h 1970-01-01 01:00:00.000000000 +0100
0c3ec466 5125+++ linux/fs/aufs/dcsub.h 2012-07-22 19:57:03.161004531 +0200
f6c5ef8b 5126@@ -0,0 +1,94 @@
1facf9fc 5127+/*
f6c5ef8b 5128+ * Copyright (C) 2005-2012 Junjiro R. Okajima
1facf9fc 5129+ *
5130+ * This program, aufs is free software; you can redistribute it and/or modify
5131+ * it under the terms of the GNU General Public License as published by
5132+ * the Free Software Foundation; either version 2 of the License, or
5133+ * (at your option) any later version.
dece6358
AM
5134+ *
5135+ * This program is distributed in the hope that it will be useful,
5136+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
5137+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
5138+ * GNU General Public License for more details.
5139+ *
5140+ * You should have received a copy of the GNU General Public License
5141+ * along with this program; if not, write to the Free Software
5142+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 5143+ */
5144+
5145+/*
5146+ * sub-routines for dentry cache
5147+ */
5148+
5149+#ifndef __AUFS_DCSUB_H__
5150+#define __AUFS_DCSUB_H__
5151+
5152+#ifdef __KERNEL__
5153+
7f207e10 5154+#include <linux/dcache.h>
027c5e7a 5155+#include <linux/fs.h>
dece6358
AM
5156+
5157+struct dentry;
1facf9fc 5158+
5159+struct au_dpage {
5160+ int ndentry;
5161+ struct dentry **dentries;
5162+};
5163+
5164+struct au_dcsub_pages {
5165+ int ndpage;
5166+ struct au_dpage *dpages;
5167+};
5168+
5169+/* ---------------------------------------------------------------------- */
5170+
7f207e10 5171+/* dcsub.c */
1facf9fc 5172+int au_dpages_init(struct au_dcsub_pages *dpages, gfp_t gfp);
5173+void au_dpages_free(struct au_dcsub_pages *dpages);
5174+typedef int (*au_dpages_test)(struct dentry *dentry, void *arg);
5175+int au_dcsub_pages(struct au_dcsub_pages *dpages, struct dentry *root,
5176+ au_dpages_test test, void *arg);
5177+int au_dcsub_pages_rev(struct au_dcsub_pages *dpages, struct dentry *dentry,
5178+ int do_include, au_dpages_test test, void *arg);
027c5e7a
AM
5179+int au_dcsub_pages_rev_aufs(struct au_dcsub_pages *dpages,
5180+ struct dentry *dentry, int do_include);
4a4d8108 5181+int au_test_subdir(struct dentry *d1, struct dentry *d2);
1facf9fc 5182+
7f207e10
AM
5183+/* ---------------------------------------------------------------------- */
5184+
027c5e7a
AM
5185+static inline int au_d_hashed_positive(struct dentry *d)
5186+{
5187+ int err;
5188+ struct inode *inode = d->d_inode;
5189+ err = 0;
5190+ if (unlikely(d_unhashed(d) || !inode || !inode->i_nlink))
5191+ err = -ENOENT;
5192+ return err;
5193+}
5194+
5195+static inline int au_d_alive(struct dentry *d)
5196+{
5197+ int err;
5198+ struct inode *inode;
5199+ err = 0;
5200+ if (!IS_ROOT(d))
5201+ err = au_d_hashed_positive(d);
5202+ else {
5203+ inode = d->d_inode;
5204+ if (unlikely(d_unlinked(d) || !inode || !inode->i_nlink))
5205+ err = -ENOENT;
5206+ }
5207+ return err;
5208+}
5209+
5210+static inline int au_alive_dir(struct dentry *d)
7f207e10 5211+{
027c5e7a
AM
5212+ int err;
5213+ err = au_d_alive(d);
5214+ if (unlikely(err || IS_DEADDIR(d->d_inode)))
5215+ err = -ENOENT;
5216+ return err;
7f207e10
AM
5217+}
5218+
1facf9fc 5219+#endif /* __KERNEL__ */
5220+#endif /* __AUFS_DCSUB_H__ */
7f207e10
AM
5221diff -urN /usr/share/empty/fs/aufs/debug.c linux/fs/aufs/debug.c
5222--- /usr/share/empty/fs/aufs/debug.c 1970-01-01 01:00:00.000000000 +0100
0c3ec466 5223+++ linux/fs/aufs/debug.c 2012-07-22 19:57:03.161004531 +0200
f6c5ef8b 5224@@ -0,0 +1,489 @@
1facf9fc 5225+/*
f6c5ef8b 5226+ * Copyright (C) 2005-2012 Junjiro R. Okajima
1facf9fc 5227+ *
5228+ * This program, aufs is free software; you can redistribute it and/or modify
5229+ * it under the terms of the GNU General Public License as published by
5230+ * the Free Software Foundation; either version 2 of the License, or
5231+ * (at your option) any later version.
dece6358
AM
5232+ *
5233+ * This program is distributed in the hope that it will be useful,
5234+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
5235+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
5236+ * GNU General Public License for more details.
5237+ *
5238+ * You should have received a copy of the GNU General Public License
5239+ * along with this program; if not, write to the Free Software
5240+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 5241+ */
5242+
5243+/*
5244+ * debug print functions
5245+ */
5246+
7f207e10 5247+#include <linux/vt_kern.h>
1facf9fc 5248+#include "aufs.h"
5249+
5250+int aufs_debug;
5251+MODULE_PARM_DESC(debug, "debug print");
5252+module_param_named(debug, aufs_debug, int, S_IRUGO | S_IWUSR | S_IWGRP);
5253+
5254+char *au_plevel = KERN_DEBUG;
e49829fe
JR
5255+#define dpri(fmt, ...) do { \
5256+ if ((au_plevel \
5257+ && strcmp(au_plevel, KERN_DEBUG)) \
5258+ || au_debug_test()) \
5259+ printk("%s" fmt, au_plevel, ##__VA_ARGS__); \
1facf9fc 5260+} while (0)
5261+
5262+/* ---------------------------------------------------------------------- */
5263+
5264+void au_dpri_whlist(struct au_nhash *whlist)
5265+{
5266+ unsigned long ul, n;
5267+ struct hlist_head *head;
5268+ struct au_vdir_wh *tpos;
5269+ struct hlist_node *pos;
5270+
5271+ n = whlist->nh_num;
5272+ head = whlist->nh_head;
5273+ for (ul = 0; ul < n; ul++) {
5274+ hlist_for_each_entry(tpos, pos, head, wh_hash)
5275+ dpri("b%d, %.*s, %d\n",
5276+ tpos->wh_bindex,
5277+ tpos->wh_str.len, tpos->wh_str.name,
5278+ tpos->wh_str.len);
5279+ head++;
5280+ }
5281+}
5282+
5283+void au_dpri_vdir(struct au_vdir *vdir)
5284+{
5285+ unsigned long ul;
5286+ union au_vdir_deblk_p p;
5287+ unsigned char *o;
5288+
5289+ if (!vdir || IS_ERR(vdir)) {
5290+ dpri("err %ld\n", PTR_ERR(vdir));
5291+ return;
5292+ }
5293+
5294+ dpri("deblk %u, nblk %lu, deblk %p, last{%lu, %p}, ver %lu\n",
5295+ vdir->vd_deblk_sz, vdir->vd_nblk, vdir->vd_deblk,
5296+ vdir->vd_last.ul, vdir->vd_last.p.deblk, vdir->vd_version);
5297+ for (ul = 0; ul < vdir->vd_nblk; ul++) {
5298+ p.deblk = vdir->vd_deblk[ul];
5299+ o = p.deblk;
5300+ dpri("[%lu]: %p\n", ul, o);
5301+ }
5302+}
5303+
53392da6 5304+static int do_pri_inode(aufs_bindex_t bindex, struct inode *inode, int hn,
1facf9fc 5305+ struct dentry *wh)
5306+{
5307+ char *n = NULL;
5308+ int l = 0;
5309+
5310+ if (!inode || IS_ERR(inode)) {
5311+ dpri("i%d: err %ld\n", bindex, PTR_ERR(inode));
5312+ return -1;
5313+ }
5314+
5315+ /* the type of i_blocks depends upon CONFIG_LSF */
5316+ BUILD_BUG_ON(sizeof(inode->i_blocks) != sizeof(unsigned long)
5317+ && sizeof(inode->i_blocks) != sizeof(u64));
5318+ if (wh) {
5319+ n = (void *)wh->d_name.name;
5320+ l = wh->d_name.len;
5321+ }
5322+
53392da6
AM
5323+ dpri("i%d: %p, i%lu, %s, cnt %d, nl %u, 0%o, sz %llu, blk %llu,"
5324+ " hn %d, ct %lld, np %lu, st 0x%lx, f 0x%x, v %llu, g %x%s%.*s\n",
5325+ bindex, inode,
1facf9fc 5326+ inode->i_ino, inode->i_sb ? au_sbtype(inode->i_sb) : "??",
5327+ atomic_read(&inode->i_count), inode->i_nlink, inode->i_mode,
5328+ i_size_read(inode), (unsigned long long)inode->i_blocks,
53392da6 5329+ hn, (long long)timespec_to_ns(&inode->i_ctime) & 0x0ffff,
1facf9fc 5330+ inode->i_mapping ? inode->i_mapping->nrpages : 0,
b752ccd1
AM
5331+ inode->i_state, inode->i_flags, inode->i_version,
5332+ inode->i_generation,
1facf9fc 5333+ l ? ", wh " : "", l, n);
5334+ return 0;
5335+}
5336+
5337+void au_dpri_inode(struct inode *inode)
5338+{
5339+ struct au_iinfo *iinfo;
5340+ aufs_bindex_t bindex;
53392da6 5341+ int err, hn;
1facf9fc 5342+
53392da6 5343+ err = do_pri_inode(-1, inode, -1, NULL);
1facf9fc 5344+ if (err || !au_test_aufs(inode->i_sb))
5345+ return;
5346+
5347+ iinfo = au_ii(inode);
5348+ if (!iinfo)
5349+ return;
5350+ dpri("i-1: bstart %d, bend %d, gen %d\n",
5351+ iinfo->ii_bstart, iinfo->ii_bend, au_iigen(inode));
5352+ if (iinfo->ii_bstart < 0)
5353+ return;
53392da6
AM
5354+ hn = 0;
5355+ for (bindex = iinfo->ii_bstart; bindex <= iinfo->ii_bend; bindex++) {
5356+ hn = !!au_hn(iinfo->ii_hinode + bindex);
5357+ do_pri_inode(bindex, iinfo->ii_hinode[0 + bindex].hi_inode, hn,
1facf9fc 5358+ iinfo->ii_hinode[0 + bindex].hi_whdentry);
53392da6 5359+ }
1facf9fc 5360+}
5361+
2cbb1c4b
JR
5362+void au_dpri_dalias(struct inode *inode)
5363+{
5364+ struct dentry *d;
5365+
5366+ spin_lock(&inode->i_lock);
5367+ list_for_each_entry(d, &inode->i_dentry, d_alias)
5368+ au_dpri_dentry(d);
5369+ spin_unlock(&inode->i_lock);
5370+}
5371+
1facf9fc 5372+static int do_pri_dentry(aufs_bindex_t bindex, struct dentry *dentry)
5373+{
5374+ struct dentry *wh = NULL;
53392da6 5375+ int hn;
1facf9fc 5376+
5377+ if (!dentry || IS_ERR(dentry)) {
5378+ dpri("d%d: err %ld\n", bindex, PTR_ERR(dentry));
5379+ return -1;
5380+ }
5381+ /* do not call dget_parent() here */
027c5e7a 5382+ /* note: access d_xxx without d_lock */
1facf9fc 5383+ dpri("d%d: %.*s?/%.*s, %s, cnt %d, flags 0x%x\n",
5384+ bindex,
5385+ AuDLNPair(dentry->d_parent), AuDLNPair(dentry),
5386+ dentry->d_sb ? au_sbtype(dentry->d_sb) : "??",
027c5e7a 5387+ dentry->d_count, dentry->d_flags);
53392da6 5388+ hn = -1;
1facf9fc 5389+ if (bindex >= 0 && dentry->d_inode && au_test_aufs(dentry->d_sb)) {
5390+ struct au_iinfo *iinfo = au_ii(dentry->d_inode);
53392da6
AM
5391+ if (iinfo) {
5392+ hn = !!au_hn(iinfo->ii_hinode + bindex);
1facf9fc 5393+ wh = iinfo->ii_hinode[0 + bindex].hi_whdentry;
53392da6 5394+ }
1facf9fc 5395+ }
53392da6 5396+ do_pri_inode(bindex, dentry->d_inode, hn, wh);
1facf9fc 5397+ return 0;
5398+}
5399+
5400+void au_dpri_dentry(struct dentry *dentry)
5401+{
5402+ struct au_dinfo *dinfo;
5403+ aufs_bindex_t bindex;
5404+ int err;
4a4d8108 5405+ struct au_hdentry *hdp;
1facf9fc 5406+
5407+ err = do_pri_dentry(-1, dentry);
5408+ if (err || !au_test_aufs(dentry->d_sb))
5409+ return;
5410+
5411+ dinfo = au_di(dentry);
5412+ if (!dinfo)
5413+ return;
5414+ dpri("d-1: bstart %d, bend %d, bwh %d, bdiropq %d, gen %d\n",
5415+ dinfo->di_bstart, dinfo->di_bend,
5416+ dinfo->di_bwh, dinfo->di_bdiropq, au_digen(dentry));
5417+ if (dinfo->di_bstart < 0)
5418+ return;
4a4d8108 5419+ hdp = dinfo->di_hdentry;
1facf9fc 5420+ for (bindex = dinfo->di_bstart; bindex <= dinfo->di_bend; bindex++)
4a4d8108 5421+ do_pri_dentry(bindex, hdp[0 + bindex].hd_dentry);
1facf9fc 5422+}
5423+
5424+static int do_pri_file(aufs_bindex_t bindex, struct file *file)
5425+{
5426+ char a[32];
5427+
5428+ if (!file || IS_ERR(file)) {
5429+ dpri("f%d: err %ld\n", bindex, PTR_ERR(file));
5430+ return -1;
5431+ }
5432+ a[0] = 0;
5433+ if (bindex < 0
5434+ && file->f_dentry
5435+ && au_test_aufs(file->f_dentry->d_sb)
5436+ && au_fi(file))
e49829fe 5437+ snprintf(a, sizeof(a), ", gen %d, mmapped %d",
2cbb1c4b 5438+ au_figen(file), atomic_read(&au_fi(file)->fi_mmapped));
b752ccd1 5439+ dpri("f%d: mode 0x%x, flags 0%o, cnt %ld, v %llu, pos %llu%s\n",
1facf9fc 5440+ bindex, file->f_mode, file->f_flags, (long)file_count(file),
b752ccd1 5441+ file->f_version, file->f_pos, a);
1facf9fc 5442+ if (file->f_dentry)
5443+ do_pri_dentry(bindex, file->f_dentry);
5444+ return 0;
5445+}
5446+
5447+void au_dpri_file(struct file *file)
5448+{
5449+ struct au_finfo *finfo;
4a4d8108
AM
5450+ struct au_fidir *fidir;
5451+ struct au_hfile *hfile;
1facf9fc 5452+ aufs_bindex_t bindex;
5453+ int err;
5454+
5455+ err = do_pri_file(-1, file);
5456+ if (err || !file->f_dentry || !au_test_aufs(file->f_dentry->d_sb))
5457+ return;
5458+
5459+ finfo = au_fi(file);
5460+ if (!finfo)
5461+ return;
4a4d8108 5462+ if (finfo->fi_btop < 0)
1facf9fc 5463+ return;
4a4d8108
AM
5464+ fidir = finfo->fi_hdir;
5465+ if (!fidir)
5466+ do_pri_file(finfo->fi_btop, finfo->fi_htop.hf_file);
5467+ else
e49829fe
JR
5468+ for (bindex = finfo->fi_btop;
5469+ bindex >= 0 && bindex <= fidir->fd_bbot;
4a4d8108
AM
5470+ bindex++) {
5471+ hfile = fidir->fd_hfile + bindex;
5472+ do_pri_file(bindex, hfile ? hfile->hf_file : NULL);
5473+ }
1facf9fc 5474+}
5475+
5476+static int do_pri_br(aufs_bindex_t bindex, struct au_branch *br)
5477+{
5478+ struct vfsmount *mnt;
5479+ struct super_block *sb;
5480+
5481+ if (!br || IS_ERR(br))
5482+ goto out;
5483+ mnt = br->br_mnt;
5484+ if (!mnt || IS_ERR(mnt))
5485+ goto out;
5486+ sb = mnt->mnt_sb;
5487+ if (!sb || IS_ERR(sb))
5488+ goto out;
5489+
1e00d052 5490+ dpri("s%d: {perm 0x%x, id %d, cnt %d, wbr %p}, "
b752ccd1 5491+ "%s, dev 0x%02x%02x, flags 0x%lx, cnt %d, active %d, "
1facf9fc 5492+ "xino %d\n",
1e00d052
AM
5493+ bindex, br->br_perm, br->br_id, atomic_read(&br->br_count),
5494+ br->br_wbr, au_sbtype(sb), MAJOR(sb->s_dev), MINOR(sb->s_dev),
b752ccd1 5495+ sb->s_flags, sb->s_count,
1facf9fc 5496+ atomic_read(&sb->s_active), !!br->br_xino.xi_file);
5497+ return 0;
5498+
4f0767ce 5499+out:
1facf9fc 5500+ dpri("s%d: err %ld\n", bindex, PTR_ERR(br));
5501+ return -1;
5502+}
5503+
5504+void au_dpri_sb(struct super_block *sb)
5505+{
5506+ struct au_sbinfo *sbinfo;
5507+ aufs_bindex_t bindex;
5508+ int err;
5509+ /* to reuduce stack size */
5510+ struct {
5511+ struct vfsmount mnt;
5512+ struct au_branch fake;
5513+ } *a;
5514+
5515+ /* this function can be called from magic sysrq */
5516+ a = kzalloc(sizeof(*a), GFP_ATOMIC);
5517+ if (unlikely(!a)) {
5518+ dpri("no memory\n");
5519+ return;
5520+ }
5521+
5522+ a->mnt.mnt_sb = sb;
5523+ a->fake.br_perm = 0;
5524+ a->fake.br_mnt = &a->mnt;
5525+ a->fake.br_xino.xi_file = NULL;
5526+ atomic_set(&a->fake.br_count, 0);
5527+ smp_mb(); /* atomic_set */
5528+ err = do_pri_br(-1, &a->fake);
5529+ kfree(a);
5530+ dpri("dev 0x%x\n", sb->s_dev);
5531+ if (err || !au_test_aufs(sb))
5532+ return;
5533+
5534+ sbinfo = au_sbi(sb);
5535+ if (!sbinfo)
5536+ return;
5537+ dpri("nw %d, gen %u, kobj %d\n",
5538+ atomic_read(&sbinfo->si_nowait.nw_len), sbinfo->si_generation,
5539+ atomic_read(&sbinfo->si_kobj.kref.refcount));
5540+ for (bindex = 0; bindex <= sbinfo->si_bend; bindex++)
5541+ do_pri_br(bindex, sbinfo->si_branch[0 + bindex]);
5542+}
5543+
5544+/* ---------------------------------------------------------------------- */
5545+
5546+void au_dbg_sleep_jiffy(int jiffy)
5547+{
5548+ while (jiffy)
5549+ jiffy = schedule_timeout_uninterruptible(jiffy);
5550+}
5551+
5552+void au_dbg_iattr(struct iattr *ia)
5553+{
5554+#define AuBit(name) if (ia->ia_valid & ATTR_ ## name) \
5555+ dpri(#name "\n")
5556+ AuBit(MODE);
5557+ AuBit(UID);
5558+ AuBit(GID);
5559+ AuBit(SIZE);
5560+ AuBit(ATIME);
5561+ AuBit(MTIME);
5562+ AuBit(CTIME);
5563+ AuBit(ATIME_SET);
5564+ AuBit(MTIME_SET);
5565+ AuBit(FORCE);
5566+ AuBit(ATTR_FLAG);
5567+ AuBit(KILL_SUID);
5568+ AuBit(KILL_SGID);
5569+ AuBit(FILE);
5570+ AuBit(KILL_PRIV);
5571+ AuBit(OPEN);
5572+ AuBit(TIMES_SET);
5573+#undef AuBit
5574+ dpri("ia_file %p\n", ia->ia_file);
5575+}
5576+
5577+/* ---------------------------------------------------------------------- */
5578+
027c5e7a
AM
5579+void __au_dbg_verify_dinode(struct dentry *dentry, const char *func, int line)
5580+{
5581+ struct inode *h_inode, *inode = dentry->d_inode;
5582+ struct dentry *h_dentry;
5583+ aufs_bindex_t bindex, bend, bi;
5584+
5585+ if (!inode /* || au_di(dentry)->di_lsc == AuLsc_DI_TMP */)
5586+ return;
5587+
5588+ bend = au_dbend(dentry);
5589+ bi = au_ibend(inode);
5590+ if (bi < bend)
5591+ bend = bi;
5592+ bindex = au_dbstart(dentry);
5593+ bi = au_ibstart(inode);
5594+ if (bi > bindex)
5595+ bindex = bi;
5596+
5597+ for (; bindex <= bend; bindex++) {
5598+ h_dentry = au_h_dptr(dentry, bindex);
5599+ if (!h_dentry)
5600+ continue;
5601+ h_inode = au_h_iptr(inode, bindex);
5602+ if (unlikely(h_inode != h_dentry->d_inode)) {
5603+ int old = au_debug_test();
5604+ if (!old)
5605+ au_debug(1);
5606+ AuDbg("b%d, %s:%d\n", bindex, func, line);
5607+ AuDbgDentry(dentry);
5608+ AuDbgInode(inode);
5609+ if (!old)
5610+ au_debug(0);
5611+ BUG();
5612+ }
5613+ }
5614+}
5615+
1facf9fc 5616+void au_dbg_verify_dir_parent(struct dentry *dentry, unsigned int sigen)
5617+{
5618+ struct dentry *parent;
5619+
5620+ parent = dget_parent(dentry);
027c5e7a
AM
5621+ AuDebugOn(!S_ISDIR(dentry->d_inode->i_mode));
5622+ AuDebugOn(IS_ROOT(dentry));
5623+ AuDebugOn(au_digen_test(parent, sigen));
1facf9fc 5624+ dput(parent);
5625+}
5626+
5627+void au_dbg_verify_nondir_parent(struct dentry *dentry, unsigned int sigen)
5628+{
5629+ struct dentry *parent;
027c5e7a 5630+ struct inode *inode;
1facf9fc 5631+
5632+ parent = dget_parent(dentry);
027c5e7a
AM
5633+ inode = dentry->d_inode;
5634+ AuDebugOn(inode && S_ISDIR(dentry->d_inode->i_mode));
5635+ AuDebugOn(au_digen_test(parent, sigen));
1facf9fc 5636+ dput(parent);
5637+}
5638+
5639+void au_dbg_verify_gen(struct dentry *parent, unsigned int sigen)
5640+{
5641+ int err, i, j;
5642+ struct au_dcsub_pages dpages;
5643+ struct au_dpage *dpage;
5644+ struct dentry **dentries;
5645+
5646+ err = au_dpages_init(&dpages, GFP_NOFS);
5647+ AuDebugOn(err);
027c5e7a 5648+ err = au_dcsub_pages_rev_aufs(&dpages, parent, /*do_include*/1);
1facf9fc 5649+ AuDebugOn(err);
5650+ for (i = dpages.ndpage - 1; !err && i >= 0; i--) {
5651+ dpage = dpages.dpages + i;
5652+ dentries = dpage->dentries;
5653+ for (j = dpage->ndentry - 1; !err && j >= 0; j--)
027c5e7a 5654+ AuDebugOn(au_digen_test(dentries[j], sigen));
1facf9fc 5655+ }
5656+ au_dpages_free(&dpages);
5657+}
5658+
1facf9fc 5659+void au_dbg_verify_kthread(void)
5660+{
53392da6 5661+ if (au_wkq_test()) {
1facf9fc 5662+ au_dbg_blocked();
1e00d052
AM
5663+ /*
5664+ * It may be recursive, but udba=notify between two aufs mounts,
5665+ * where a single ro branch is shared, is not a problem.
5666+ */
5667+ /* WARN_ON(1); */
1facf9fc 5668+ }
5669+}
5670+
5671+/* ---------------------------------------------------------------------- */
5672+
5673+void au_debug_sbinfo_init(struct au_sbinfo *sbinfo __maybe_unused)
5674+{
5675+#ifdef AuForceNoPlink
5676+ au_opt_clr(sbinfo->si_mntflags, PLINK);
5677+#endif
5678+#ifdef AuForceNoXino
5679+ au_opt_clr(sbinfo->si_mntflags, XINO);
5680+#endif
5681+#ifdef AuForceNoRefrof
5682+ au_opt_clr(sbinfo->si_mntflags, REFROF);
5683+#endif
4a4d8108
AM
5684+#ifdef AuForceHnotify
5685+ au_opt_set_udba(sbinfo->si_mntflags, UDBA_HNOTIFY);
1facf9fc 5686+#endif
1308ab2a 5687+#ifdef AuForceRd0
5688+ sbinfo->si_rdblk = 0;
5689+ sbinfo->si_rdhash = 0;
5690+#endif
1facf9fc 5691+}
5692+
5693+int __init au_debug_init(void)
5694+{
5695+ aufs_bindex_t bindex;
5696+ struct au_vdir_destr destr;
5697+
5698+ bindex = -1;
5699+ AuDebugOn(bindex >= 0);
5700+
5701+ destr.len = -1;
5702+ AuDebugOn(destr.len < NAME_MAX);
5703+
5704+#ifdef CONFIG_4KSTACKS
0c3ec466 5705+ pr_warn("CONFIG_4KSTACKS is defined.\n");
1facf9fc 5706+#endif
5707+
5708+#ifdef AuForceNoBrs
5709+ sysaufs_brs = 0;
5710+#endif
5711+
5712+ return 0;
5713+}
7f207e10
AM
5714diff -urN /usr/share/empty/fs/aufs/debug.h linux/fs/aufs/debug.h
5715--- /usr/share/empty/fs/aufs/debug.h 1970-01-01 01:00:00.000000000 +0100
0c3ec466 5716+++ linux/fs/aufs/debug.h 2012-07-22 19:57:03.161004531 +0200
92d182d2 5717@@ -0,0 +1,242 @@
1facf9fc 5718+/*
f6c5ef8b 5719+ * Copyright (C) 2005-2012 Junjiro R. Okajima
1facf9fc 5720+ *
5721+ * This program, aufs is free software; you can redistribute it and/or modify
5722+ * it under the terms of the GNU General Public License as published by
5723+ * the Free Software Foundation; either version 2 of the License, or
5724+ * (at your option) any later version.
dece6358
AM
5725+ *
5726+ * This program is distributed in the hope that it will be useful,
5727+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
5728+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
5729+ * GNU General Public License for more details.
5730+ *
5731+ * You should have received a copy of the GNU General Public License
5732+ * along with this program; if not, write to the Free Software
5733+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 5734+ */
5735+
5736+/*
5737+ * debug print functions
5738+ */
5739+
5740+#ifndef __AUFS_DEBUG_H__
5741+#define __AUFS_DEBUG_H__
5742+
5743+#ifdef __KERNEL__
5744+
4a4d8108
AM
5745+#include <linux/module.h>
5746+#include <linux/kallsyms.h>
1facf9fc 5747+#include <linux/sysrq.h>
4a4d8108 5748+
1facf9fc 5749+#ifdef CONFIG_AUFS_DEBUG
5750+#define AuDebugOn(a) BUG_ON(a)
5751+
5752+/* module parameter */
5753+extern int aufs_debug;
5754+static inline void au_debug(int n)
5755+{
5756+ aufs_debug = n;
5757+ smp_mb();
5758+}
5759+
5760+static inline int au_debug_test(void)
5761+{
5762+ return aufs_debug;
5763+}
5764+#else
5765+#define AuDebugOn(a) do {} while (0)
4a4d8108
AM
5766+AuStubVoid(au_debug, int n)
5767+AuStubInt0(au_debug_test, void)
1facf9fc 5768+#endif /* CONFIG_AUFS_DEBUG */
5769+
5770+/* ---------------------------------------------------------------------- */
5771+
5772+/* debug print */
5773+
4a4d8108 5774+#define AuDbg(fmt, ...) do { \
1facf9fc 5775+ if (au_debug_test()) \
4a4d8108 5776+ pr_debug("DEBUG: " fmt, ##__VA_ARGS__); \
1facf9fc 5777+} while (0)
4a4d8108
AM
5778+#define AuLabel(l) AuDbg(#l "\n")
5779+#define AuIOErr(fmt, ...) pr_err("I/O Error, " fmt, ##__VA_ARGS__)
5780+#define AuWarn1(fmt, ...) do { \
1facf9fc 5781+ static unsigned char _c; \
5782+ if (!_c++) \
0c3ec466 5783+ pr_warn(fmt, ##__VA_ARGS__); \
1facf9fc 5784+} while (0)
5785+
4a4d8108 5786+#define AuErr1(fmt, ...) do { \
1facf9fc 5787+ static unsigned char _c; \
5788+ if (!_c++) \
4a4d8108 5789+ pr_err(fmt, ##__VA_ARGS__); \
1facf9fc 5790+} while (0)
5791+
4a4d8108 5792+#define AuIOErr1(fmt, ...) do { \
1facf9fc 5793+ static unsigned char _c; \
5794+ if (!_c++) \
4a4d8108 5795+ AuIOErr(fmt, ##__VA_ARGS__); \
1facf9fc 5796+} while (0)
5797+
5798+#define AuUnsupportMsg "This operation is not supported." \
5799+ " Please report this application to aufs-users ML."
4a4d8108
AM
5800+#define AuUnsupport(fmt, ...) do { \
5801+ pr_err(AuUnsupportMsg "\n" fmt, ##__VA_ARGS__); \
1facf9fc 5802+ dump_stack(); \
5803+} while (0)
5804+
5805+#define AuTraceErr(e) do { \
5806+ if (unlikely((e) < 0)) \
5807+ AuDbg("err %d\n", (int)(e)); \
5808+} while (0)
5809+
5810+#define AuTraceErrPtr(p) do { \
5811+ if (IS_ERR(p)) \
5812+ AuDbg("err %ld\n", PTR_ERR(p)); \
5813+} while (0)
5814+
5815+/* dirty macros for debug print, use with "%.*s" and caution */
5816+#define AuLNPair(qstr) (qstr)->len, (qstr)->name
5817+#define AuDLNPair(d) AuLNPair(&(d)->d_name)
5818+
5819+/* ---------------------------------------------------------------------- */
5820+
5821+struct au_sbinfo;
5822+struct au_finfo;
dece6358 5823+struct dentry;
1facf9fc 5824+#ifdef CONFIG_AUFS_DEBUG
5825+extern char *au_plevel;
5826+struct au_nhash;
5827+void au_dpri_whlist(struct au_nhash *whlist);
5828+struct au_vdir;
5829+void au_dpri_vdir(struct au_vdir *vdir);
dece6358 5830+struct inode;
1facf9fc 5831+void au_dpri_inode(struct inode *inode);
2cbb1c4b 5832+void au_dpri_dalias(struct inode *inode);
1facf9fc 5833+void au_dpri_dentry(struct dentry *dentry);
dece6358 5834+struct file;
1facf9fc 5835+void au_dpri_file(struct file *filp);
dece6358 5836+struct super_block;
1facf9fc 5837+void au_dpri_sb(struct super_block *sb);
5838+
5839+void au_dbg_sleep_jiffy(int jiffy);
dece6358 5840+struct iattr;
1facf9fc 5841+void au_dbg_iattr(struct iattr *ia);
5842+
027c5e7a
AM
5843+#define au_dbg_verify_dinode(d) __au_dbg_verify_dinode(d, __func__, __LINE__)
5844+void __au_dbg_verify_dinode(struct dentry *dentry, const char *func, int line);
1facf9fc 5845+void au_dbg_verify_dir_parent(struct dentry *dentry, unsigned int sigen);
5846+void au_dbg_verify_nondir_parent(struct dentry *dentry, unsigned int sigen);
5847+void au_dbg_verify_gen(struct dentry *parent, unsigned int sigen);
1facf9fc 5848+void au_dbg_verify_kthread(void);
5849+
5850+int __init au_debug_init(void);
5851+void au_debug_sbinfo_init(struct au_sbinfo *sbinfo);
5852+#define AuDbgWhlist(w) do { \
5853+ AuDbg(#w "\n"); \
5854+ au_dpri_whlist(w); \
5855+} while (0)
5856+
5857+#define AuDbgVdir(v) do { \
5858+ AuDbg(#v "\n"); \
5859+ au_dpri_vdir(v); \
5860+} while (0)
5861+
5862+#define AuDbgInode(i) do { \
5863+ AuDbg(#i "\n"); \
5864+ au_dpri_inode(i); \
5865+} while (0)
5866+
2cbb1c4b
JR
5867+#define AuDbgDAlias(i) do { \
5868+ AuDbg(#i "\n"); \
5869+ au_dpri_dalias(i); \
5870+} while (0)
5871+
1facf9fc 5872+#define AuDbgDentry(d) do { \
5873+ AuDbg(#d "\n"); \
5874+ au_dpri_dentry(d); \
5875+} while (0)
5876+
5877+#define AuDbgFile(f) do { \
5878+ AuDbg(#f "\n"); \
5879+ au_dpri_file(f); \
5880+} while (0)
5881+
5882+#define AuDbgSb(sb) do { \
5883+ AuDbg(#sb "\n"); \
5884+ au_dpri_sb(sb); \
5885+} while (0)
5886+
5887+#define AuDbgSleep(sec) do { \
5888+ AuDbg("sleep %d sec\n", sec); \
5889+ ssleep(sec); \
5890+} while (0)
5891+
5892+#define AuDbgSleepJiffy(jiffy) do { \
5893+ AuDbg("sleep %d jiffies\n", jiffy); \
5894+ au_dbg_sleep_jiffy(jiffy); \
5895+} while (0)
5896+
5897+#define AuDbgIAttr(ia) do { \
5898+ AuDbg("ia_valid 0x%x\n", (ia)->ia_valid); \
5899+ au_dbg_iattr(ia); \
5900+} while (0)
4a4d8108
AM
5901+
5902+#define AuDbgSym(addr) do { \
5903+ char sym[KSYM_SYMBOL_LEN]; \
5904+ sprint_symbol(sym, (unsigned long)addr); \
5905+ AuDbg("%s\n", sym); \
5906+} while (0)
5907+
5908+#define AuInfoSym(addr) do { \
5909+ char sym[KSYM_SYMBOL_LEN]; \
5910+ sprint_symbol(sym, (unsigned long)addr); \
5911+ AuInfo("%s\n", sym); \
5912+} while (0)
1facf9fc 5913+#else
027c5e7a 5914+AuStubVoid(au_dbg_verify_dinode, struct dentry *dentry)
4a4d8108
AM
5915+AuStubVoid(au_dbg_verify_dir_parent, struct dentry *dentry, unsigned int sigen)
5916+AuStubVoid(au_dbg_verify_nondir_parent, struct dentry *dentry,
5917+ unsigned int sigen)
5918+AuStubVoid(au_dbg_verify_gen, struct dentry *parent, unsigned int sigen)
5919+AuStubVoid(au_dbg_verify_kthread, void)
5920+AuStubInt0(__init au_debug_init, void)
5921+AuStubVoid(au_debug_sbinfo_init, struct au_sbinfo *sbinfo)
1facf9fc 5922+
1facf9fc 5923+#define AuDbgWhlist(w) do {} while (0)
5924+#define AuDbgVdir(v) do {} while (0)
5925+#define AuDbgInode(i) do {} while (0)
2cbb1c4b 5926+#define AuDbgDAlias(i) do {} while (0)
1facf9fc 5927+#define AuDbgDentry(d) do {} while (0)
5928+#define AuDbgFile(f) do {} while (0)
5929+#define AuDbgSb(sb) do {} while (0)
5930+#define AuDbgSleep(sec) do {} while (0)
5931+#define AuDbgSleepJiffy(jiffy) do {} while (0)
5932+#define AuDbgIAttr(ia) do {} while (0)
4a4d8108
AM
5933+#define AuDbgSym(addr) do {} while (0)
5934+#define AuInfoSym(addr) do {} while (0)
1facf9fc 5935+#endif /* CONFIG_AUFS_DEBUG */
5936+
5937+/* ---------------------------------------------------------------------- */
5938+
5939+#ifdef CONFIG_AUFS_MAGIC_SYSRQ
5940+int __init au_sysrq_init(void);
5941+void au_sysrq_fin(void);
5942+
5943+#ifdef CONFIG_HW_CONSOLE
5944+#define au_dbg_blocked() do { \
5945+ WARN_ON(1); \
0c5527e5 5946+ handle_sysrq('w'); \
1facf9fc 5947+} while (0)
5948+#else
4a4d8108 5949+AuStubVoid(au_dbg_blocked, void)
1facf9fc 5950+#endif
5951+
5952+#else
4a4d8108
AM
5953+AuStubInt0(__init au_sysrq_init, void)
5954+AuStubVoid(au_sysrq_fin, void)
5955+AuStubVoid(au_dbg_blocked, void)
1facf9fc 5956+#endif /* CONFIG_AUFS_MAGIC_SYSRQ */
5957+
5958+#endif /* __KERNEL__ */
5959+#endif /* __AUFS_DEBUG_H__ */
7f207e10
AM
5960diff -urN /usr/share/empty/fs/aufs/dentry.c linux/fs/aufs/dentry.c
5961--- /usr/share/empty/fs/aufs/dentry.c 1970-01-01 01:00:00.000000000 +0100
0c3ec466 5962+++ linux/fs/aufs/dentry.c 2012-07-22 19:57:03.161004531 +0200
027c5e7a 5963@@ -0,0 +1,1140 @@
1facf9fc 5964+/*
f6c5ef8b 5965+ * Copyright (C) 2005-2012 Junjiro R. Okajima
1facf9fc 5966+ *
5967+ * This program, aufs is free software; you can redistribute it and/or modify
5968+ * it under the terms of the GNU General Public License as published by
5969+ * the Free Software Foundation; either version 2 of the License, or
5970+ * (at your option) any later version.
dece6358
AM
5971+ *
5972+ * This program is distributed in the hope that it will be useful,
5973+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
5974+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
5975+ * GNU General Public License for more details.
5976+ *
5977+ * You should have received a copy of the GNU General Public License
5978+ * along with this program; if not, write to the Free Software
5979+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 5980+ */
5981+
5982+/*
5983+ * lookup and dentry operations
5984+ */
5985+
dece6358 5986+#include <linux/namei.h>
1facf9fc 5987+#include "aufs.h"
5988+
5989+static void au_h_nd(struct nameidata *h_nd, struct nameidata *nd)
5990+{
5991+ if (nd) {
5992+ *h_nd = *nd;
5993+
5994+ /*
5995+ * gave up supporting LOOKUP_CREATE/OPEN for lower fs,
5996+ * due to whiteout and branch permission.
5997+ */
5998+ h_nd->flags &= ~(/*LOOKUP_PARENT |*/ LOOKUP_OPEN | LOOKUP_CREATE
b752ccd1 5999+ | LOOKUP_FOLLOW | LOOKUP_EXCL);
1facf9fc 6000+ /* unnecessary? */
6001+ h_nd->intent.open.file = NULL;
6002+ } else
6003+ memset(h_nd, 0, sizeof(*h_nd));
6004+}
6005+
6006+struct au_lkup_one_args {
6007+ struct dentry **errp;
6008+ struct qstr *name;
6009+ struct dentry *h_parent;
6010+ struct au_branch *br;
6011+ struct nameidata *nd;
6012+};
6013+
6014+struct dentry *au_lkup_one(struct qstr *name, struct dentry *h_parent,
6015+ struct au_branch *br, struct nameidata *nd)
6016+{
6017+ struct dentry *h_dentry;
6018+ int err;
6019+ struct nameidata h_nd;
6020+
6021+ if (au_test_fs_null_nd(h_parent->d_sb))
6022+ return vfsub_lookup_one_len(name->name, h_parent, name->len);
6023+
6024+ au_h_nd(&h_nd, nd);
6025+ h_nd.path.dentry = h_parent;
6026+ h_nd.path.mnt = br->br_mnt;
6027+
2cbb1c4b 6028+ err = vfsub_name_hash(name->name, &h_nd.last, name->len);
1facf9fc 6029+ h_dentry = ERR_PTR(err);
6030+ if (!err) {
6031+ path_get(&h_nd.path);
6032+ h_dentry = vfsub_lookup_hash(&h_nd);
6033+ path_put(&h_nd.path);
6034+ }
6035+
4a4d8108 6036+ AuTraceErrPtr(h_dentry);
1facf9fc 6037+ return h_dentry;
6038+}
6039+
6040+static void au_call_lkup_one(void *args)
6041+{
6042+ struct au_lkup_one_args *a = args;
6043+ *a->errp = au_lkup_one(a->name, a->h_parent, a->br, a->nd);
6044+}
6045+
6046+#define AuLkup_ALLOW_NEG 1
6047+#define au_ftest_lkup(flags, name) ((flags) & AuLkup_##name)
7f207e10
AM
6048+#define au_fset_lkup(flags, name) \
6049+ do { (flags) |= AuLkup_##name; } while (0)
6050+#define au_fclr_lkup(flags, name) \
6051+ do { (flags) &= ~AuLkup_##name; } while (0)
1facf9fc 6052+
6053+struct au_do_lookup_args {
6054+ unsigned int flags;
6055+ mode_t type;
6056+ struct nameidata *nd;
6057+};
6058+
6059+/*
6060+ * returns positive/negative dentry, NULL or an error.
6061+ * NULL means whiteout-ed or not-found.
6062+ */
6063+static struct dentry*
6064+au_do_lookup(struct dentry *h_parent, struct dentry *dentry,
6065+ aufs_bindex_t bindex, struct qstr *wh_name,
6066+ struct au_do_lookup_args *args)
6067+{
6068+ struct dentry *h_dentry;
6069+ struct inode *h_inode, *inode;
1facf9fc 6070+ struct au_branch *br;
6071+ int wh_found, opq;
6072+ unsigned char wh_able;
6073+ const unsigned char allow_neg = !!au_ftest_lkup(args->flags, ALLOW_NEG);
6074+
1facf9fc 6075+ wh_found = 0;
6076+ br = au_sbr(dentry->d_sb, bindex);
6077+ wh_able = !!au_br_whable(br->br_perm);
6078+ if (wh_able)
6079+ wh_found = au_wh_test(h_parent, wh_name, br, /*try_sio*/0);
6080+ h_dentry = ERR_PTR(wh_found);
6081+ if (!wh_found)
6082+ goto real_lookup;
6083+ if (unlikely(wh_found < 0))
6084+ goto out;
6085+
6086+ /* We found a whiteout */
6087+ /* au_set_dbend(dentry, bindex); */
6088+ au_set_dbwh(dentry, bindex);
6089+ if (!allow_neg)
6090+ return NULL; /* success */
6091+
4f0767ce 6092+real_lookup:
4a4d8108 6093+ h_dentry = au_lkup_one(&dentry->d_name, h_parent, br, args->nd);
1facf9fc 6094+ if (IS_ERR(h_dentry))
6095+ goto out;
6096+
6097+ h_inode = h_dentry->d_inode;
6098+ if (!h_inode) {
6099+ if (!allow_neg)
6100+ goto out_neg;
6101+ } else if (wh_found
6102+ || (args->type && args->type != (h_inode->i_mode & S_IFMT)))
6103+ goto out_neg;
6104+
6105+ if (au_dbend(dentry) <= bindex)
6106+ au_set_dbend(dentry, bindex);
6107+ if (au_dbstart(dentry) < 0 || bindex < au_dbstart(dentry))
6108+ au_set_dbstart(dentry, bindex);
6109+ au_set_h_dptr(dentry, bindex, h_dentry);
6110+
6111+ inode = dentry->d_inode;
6112+ if (!h_inode || !S_ISDIR(h_inode->i_mode) || !wh_able
6113+ || (inode && !S_ISDIR(inode->i_mode)))
6114+ goto out; /* success */
6115+
6116+ mutex_lock_nested(&h_inode->i_mutex, AuLsc_I_CHILD);
6117+ opq = au_diropq_test(h_dentry, br);
6118+ mutex_unlock(&h_inode->i_mutex);
6119+ if (opq > 0)
6120+ au_set_dbdiropq(dentry, bindex);
6121+ else if (unlikely(opq < 0)) {
6122+ au_set_h_dptr(dentry, bindex, NULL);
6123+ h_dentry = ERR_PTR(opq);
6124+ }
6125+ goto out;
6126+
4f0767ce 6127+out_neg:
1facf9fc 6128+ dput(h_dentry);
6129+ h_dentry = NULL;
4f0767ce 6130+out:
1facf9fc 6131+ return h_dentry;
6132+}
6133+
dece6358
AM
6134+static int au_test_shwh(struct super_block *sb, const struct qstr *name)
6135+{
6136+ if (unlikely(!au_opt_test(au_mntflags(sb), SHWH)
6137+ && !strncmp(name->name, AUFS_WH_PFX, AUFS_WH_PFX_LEN)))
6138+ return -EPERM;
6139+ return 0;
6140+}
6141+
1facf9fc 6142+/*
6143+ * returns the number of lower positive dentries,
6144+ * otherwise an error.
6145+ * can be called at unlinking with @type is zero.
6146+ */
6147+int au_lkup_dentry(struct dentry *dentry, aufs_bindex_t bstart, mode_t type,
6148+ struct nameidata *nd)
6149+{
6150+ int npositive, err;
6151+ aufs_bindex_t bindex, btail, bdiropq;
6152+ unsigned char isdir;
6153+ struct qstr whname;
6154+ struct au_do_lookup_args args = {
6155+ .flags = 0,
6156+ .type = type,
6157+ .nd = nd
6158+ };
6159+ const struct qstr *name = &dentry->d_name;
6160+ struct dentry *parent;
6161+ struct inode *inode;
6162+
dece6358
AM
6163+ err = au_test_shwh(dentry->d_sb, name);
6164+ if (unlikely(err))
1facf9fc 6165+ goto out;
6166+
6167+ err = au_wh_name_alloc(&whname, name);
6168+ if (unlikely(err))
6169+ goto out;
6170+
6171+ inode = dentry->d_inode;
6172+ isdir = !!(inode && S_ISDIR(inode->i_mode));
6173+ if (!type)
6174+ au_fset_lkup(args.flags, ALLOW_NEG);
6175+
6176+ npositive = 0;
4a4d8108 6177+ parent = dget_parent(dentry);
1facf9fc 6178+ btail = au_dbtaildir(parent);
6179+ for (bindex = bstart; bindex <= btail; bindex++) {
6180+ struct dentry *h_parent, *h_dentry;
6181+ struct inode *h_inode, *h_dir;
6182+
6183+ h_dentry = au_h_dptr(dentry, bindex);
6184+ if (h_dentry) {
6185+ if (h_dentry->d_inode)
6186+ npositive++;
6187+ if (type != S_IFDIR)
6188+ break;
6189+ continue;
6190+ }
6191+ h_parent = au_h_dptr(parent, bindex);
6192+ if (!h_parent)
6193+ continue;
6194+ h_dir = h_parent->d_inode;
6195+ if (!h_dir || !S_ISDIR(h_dir->i_mode))
6196+ continue;
6197+
6198+ mutex_lock_nested(&h_dir->i_mutex, AuLsc_I_PARENT);
6199+ h_dentry = au_do_lookup(h_parent, dentry, bindex, &whname,
6200+ &args);
6201+ mutex_unlock(&h_dir->i_mutex);
6202+ err = PTR_ERR(h_dentry);
6203+ if (IS_ERR(h_dentry))
4a4d8108 6204+ goto out_parent;
1facf9fc 6205+ au_fclr_lkup(args.flags, ALLOW_NEG);
6206+
6207+ if (au_dbwh(dentry) >= 0)
6208+ break;
6209+ if (!h_dentry)
6210+ continue;
6211+ h_inode = h_dentry->d_inode;
6212+ if (!h_inode)
6213+ continue;
6214+ npositive++;
6215+ if (!args.type)
6216+ args.type = h_inode->i_mode & S_IFMT;
6217+ if (args.type != S_IFDIR)
6218+ break;
6219+ else if (isdir) {
6220+ /* the type of lower may be different */
6221+ bdiropq = au_dbdiropq(dentry);
6222+ if (bdiropq >= 0 && bdiropq <= bindex)
6223+ break;
6224+ }
6225+ }
6226+
6227+ if (npositive) {
6228+ AuLabel(positive);
6229+ au_update_dbstart(dentry);
6230+ }
6231+ err = npositive;
6232+ if (unlikely(!au_opt_test(au_mntflags(dentry->d_sb), UDBA_NONE)
027c5e7a 6233+ && au_dbstart(dentry) < 0)) {
1facf9fc 6234+ err = -EIO;
027c5e7a
AM
6235+ AuIOErr("both of real entry and whiteout found, %.*s, err %d\n",
6236+ AuDLNPair(dentry), err);
6237+ }
1facf9fc 6238+
4f0767ce 6239+out_parent:
4a4d8108 6240+ dput(parent);
1facf9fc 6241+ kfree(whname.name);
4f0767ce 6242+out:
1facf9fc 6243+ return err;
6244+}
6245+
6246+struct dentry *au_sio_lkup_one(struct qstr *name, struct dentry *parent,
6247+ struct au_branch *br)
6248+{
6249+ struct dentry *dentry;
6250+ int wkq_err;
6251+
6252+ if (!au_test_h_perm_sio(parent->d_inode, MAY_EXEC))
6253+ dentry = au_lkup_one(name, parent, br, /*nd*/NULL);
6254+ else {
6255+ struct au_lkup_one_args args = {
6256+ .errp = &dentry,
6257+ .name = name,
6258+ .h_parent = parent,
6259+ .br = br,
6260+ .nd = NULL
6261+ };
6262+
6263+ wkq_err = au_wkq_wait(au_call_lkup_one, &args);
6264+ if (unlikely(wkq_err))
6265+ dentry = ERR_PTR(wkq_err);
6266+ }
6267+
6268+ return dentry;
6269+}
6270+
6271+/*
6272+ * lookup @dentry on @bindex which should be negative.
6273+ */
6274+int au_lkup_neg(struct dentry *dentry, aufs_bindex_t bindex)
6275+{
6276+ int err;
6277+ struct dentry *parent, *h_parent, *h_dentry;
1facf9fc 6278+
1facf9fc 6279+ parent = dget_parent(dentry);
6280+ h_parent = au_h_dptr(parent, bindex);
4a4d8108 6281+ h_dentry = au_sio_lkup_one(&dentry->d_name, h_parent,
1facf9fc 6282+ au_sbr(dentry->d_sb, bindex));
6283+ err = PTR_ERR(h_dentry);
6284+ if (IS_ERR(h_dentry))
6285+ goto out;
6286+ if (unlikely(h_dentry->d_inode)) {
6287+ err = -EIO;
027c5e7a
AM
6288+ AuIOErr("%.*s should be negative on b%d.\n",
6289+ AuDLNPair(h_dentry), bindex);
1facf9fc 6290+ dput(h_dentry);
6291+ goto out;
6292+ }
6293+
4a4d8108 6294+ err = 0;
1facf9fc 6295+ if (bindex < au_dbstart(dentry))
6296+ au_set_dbstart(dentry, bindex);
6297+ if (au_dbend(dentry) < bindex)
6298+ au_set_dbend(dentry, bindex);
6299+ au_set_h_dptr(dentry, bindex, h_dentry);
1facf9fc 6300+
4f0767ce 6301+out:
1facf9fc 6302+ dput(parent);
6303+ return err;
6304+}
6305+
6306+/* ---------------------------------------------------------------------- */
6307+
6308+/* subset of struct inode */
6309+struct au_iattr {
6310+ unsigned long i_ino;
6311+ /* unsigned int i_nlink; */
0c3ec466
AM
6312+ kuid_t i_uid;
6313+ kgid_t i_gid;
1facf9fc 6314+ u64 i_version;
6315+/*
6316+ loff_t i_size;
6317+ blkcnt_t i_blocks;
6318+*/
6319+ umode_t i_mode;
6320+};
6321+
6322+static void au_iattr_save(struct au_iattr *ia, struct inode *h_inode)
6323+{
6324+ ia->i_ino = h_inode->i_ino;
6325+ /* ia->i_nlink = h_inode->i_nlink; */
6326+ ia->i_uid = h_inode->i_uid;
6327+ ia->i_gid = h_inode->i_gid;
6328+ ia->i_version = h_inode->i_version;
6329+/*
6330+ ia->i_size = h_inode->i_size;
6331+ ia->i_blocks = h_inode->i_blocks;
6332+*/
6333+ ia->i_mode = (h_inode->i_mode & S_IFMT);
6334+}
6335+
6336+static int au_iattr_test(struct au_iattr *ia, struct inode *h_inode)
6337+{
6338+ return ia->i_ino != h_inode->i_ino
6339+ /* || ia->i_nlink != h_inode->i_nlink */
0c3ec466
AM
6340+ || !uid_eq(ia->i_uid, h_inode->i_uid)
6341+ || !uid_eq(ia->i_gid, h_inode->i_gid)
1facf9fc 6342+ || ia->i_version != h_inode->i_version
6343+/*
6344+ || ia->i_size != h_inode->i_size
6345+ || ia->i_blocks != h_inode->i_blocks
6346+*/
6347+ || ia->i_mode != (h_inode->i_mode & S_IFMT);
6348+}
6349+
6350+static int au_h_verify_dentry(struct dentry *h_dentry, struct dentry *h_parent,
6351+ struct au_branch *br)
6352+{
6353+ int err;
6354+ struct au_iattr ia;
6355+ struct inode *h_inode;
6356+ struct dentry *h_d;
6357+ struct super_block *h_sb;
6358+
6359+ err = 0;
6360+ memset(&ia, -1, sizeof(ia));
6361+ h_sb = h_dentry->d_sb;
6362+ h_inode = h_dentry->d_inode;
6363+ if (h_inode)
6364+ au_iattr_save(&ia, h_inode);
6365+ else if (au_test_nfs(h_sb) || au_test_fuse(h_sb))
6366+ /* nfs d_revalidate may return 0 for negative dentry */
6367+ /* fuse d_revalidate always return 0 for negative dentry */
6368+ goto out;
6369+
6370+ /* main purpose is namei.c:cached_lookup() and d_revalidate */
6371+ h_d = au_lkup_one(&h_dentry->d_name, h_parent, br, /*nd*/NULL);
6372+ err = PTR_ERR(h_d);
6373+ if (IS_ERR(h_d))
6374+ goto out;
6375+
6376+ err = 0;
6377+ if (unlikely(h_d != h_dentry
6378+ || h_d->d_inode != h_inode
6379+ || (h_inode && au_iattr_test(&ia, h_inode))))
6380+ err = au_busy_or_stale();
6381+ dput(h_d);
6382+
4f0767ce 6383+out:
1facf9fc 6384+ AuTraceErr(err);
6385+ return err;
6386+}
6387+
6388+int au_h_verify(struct dentry *h_dentry, unsigned int udba, struct inode *h_dir,
6389+ struct dentry *h_parent, struct au_branch *br)
6390+{
6391+ int err;
6392+
6393+ err = 0;
027c5e7a
AM
6394+ if (udba == AuOpt_UDBA_REVAL
6395+ && !au_test_fs_remote(h_dentry->d_sb)) {
1facf9fc 6396+ IMustLock(h_dir);
6397+ err = (h_dentry->d_parent->d_inode != h_dir);
027c5e7a 6398+ } else if (udba != AuOpt_UDBA_NONE)
1facf9fc 6399+ err = au_h_verify_dentry(h_dentry, h_parent, br);
6400+
6401+ return err;
6402+}
6403+
6404+/* ---------------------------------------------------------------------- */
6405+
027c5e7a 6406+static int au_do_refresh_hdentry(struct dentry *dentry, struct dentry *parent)
1facf9fc 6407+{
027c5e7a 6408+ int err;
1facf9fc 6409+ aufs_bindex_t new_bindex, bindex, bend, bwh, bdiropq;
027c5e7a
AM
6410+ struct au_hdentry tmp, *p, *q;
6411+ struct au_dinfo *dinfo;
6412+ struct super_block *sb;
1facf9fc 6413+
027c5e7a 6414+ DiMustWriteLock(dentry);
1308ab2a 6415+
027c5e7a
AM
6416+ sb = dentry->d_sb;
6417+ dinfo = au_di(dentry);
1facf9fc 6418+ bend = dinfo->di_bend;
6419+ bwh = dinfo->di_bwh;
6420+ bdiropq = dinfo->di_bdiropq;
027c5e7a 6421+ p = dinfo->di_hdentry + dinfo->di_bstart;
1facf9fc 6422+ for (bindex = dinfo->di_bstart; bindex <= bend; bindex++, p++) {
027c5e7a 6423+ if (!p->hd_dentry)
1facf9fc 6424+ continue;
6425+
027c5e7a
AM
6426+ new_bindex = au_br_index(sb, p->hd_id);
6427+ if (new_bindex == bindex)
1facf9fc 6428+ continue;
1facf9fc 6429+
1facf9fc 6430+ if (dinfo->di_bwh == bindex)
6431+ bwh = new_bindex;
6432+ if (dinfo->di_bdiropq == bindex)
6433+ bdiropq = new_bindex;
6434+ if (new_bindex < 0) {
6435+ au_hdput(p);
6436+ p->hd_dentry = NULL;
6437+ continue;
6438+ }
6439+
6440+ /* swap two lower dentries, and loop again */
6441+ q = dinfo->di_hdentry + new_bindex;
6442+ tmp = *q;
6443+ *q = *p;
6444+ *p = tmp;
6445+ if (tmp.hd_dentry) {
6446+ bindex--;
6447+ p--;
6448+ }
6449+ }
6450+
1facf9fc 6451+ dinfo->di_bwh = -1;
6452+ if (bwh >= 0 && bwh <= au_sbend(sb) && au_sbr_whable(sb, bwh))
6453+ dinfo->di_bwh = bwh;
6454+
6455+ dinfo->di_bdiropq = -1;
6456+ if (bdiropq >= 0
6457+ && bdiropq <= au_sbend(sb)
6458+ && au_sbr_whable(sb, bdiropq))
6459+ dinfo->di_bdiropq = bdiropq;
6460+
027c5e7a
AM
6461+ err = -EIO;
6462+ dinfo->di_bstart = -1;
6463+ dinfo->di_bend = -1;
1facf9fc 6464+ bend = au_dbend(parent);
6465+ p = dinfo->di_hdentry;
6466+ for (bindex = 0; bindex <= bend; bindex++, p++)
6467+ if (p->hd_dentry) {
6468+ dinfo->di_bstart = bindex;
6469+ break;
6470+ }
6471+
027c5e7a
AM
6472+ if (dinfo->di_bstart >= 0) {
6473+ p = dinfo->di_hdentry + bend;
6474+ for (bindex = bend; bindex >= 0; bindex--, p--)
6475+ if (p->hd_dentry) {
6476+ dinfo->di_bend = bindex;
6477+ err = 0;
6478+ break;
6479+ }
6480+ }
6481+
6482+ return err;
1facf9fc 6483+}
6484+
027c5e7a 6485+static void au_do_hide(struct dentry *dentry)
1facf9fc 6486+{
027c5e7a 6487+ struct inode *inode;
1facf9fc 6488+
027c5e7a
AM
6489+ inode = dentry->d_inode;
6490+ if (inode) {
6491+ if (!S_ISDIR(inode->i_mode)) {
6492+ if (inode->i_nlink && !d_unhashed(dentry))
6493+ drop_nlink(inode);
6494+ } else {
6495+ clear_nlink(inode);
6496+ /* stop next lookup */
6497+ inode->i_flags |= S_DEAD;
6498+ }
6499+ smp_mb(); /* necessary? */
6500+ }
6501+ d_drop(dentry);
6502+}
1308ab2a 6503+
027c5e7a
AM
6504+static int au_hide_children(struct dentry *parent)
6505+{
6506+ int err, i, j, ndentry;
6507+ struct au_dcsub_pages dpages;
6508+ struct au_dpage *dpage;
6509+ struct dentry *dentry;
1facf9fc 6510+
027c5e7a 6511+ err = au_dpages_init(&dpages, GFP_NOFS);
1facf9fc 6512+ if (unlikely(err))
6513+ goto out;
027c5e7a
AM
6514+ err = au_dcsub_pages(&dpages, parent, NULL, NULL);
6515+ if (unlikely(err))
6516+ goto out_dpages;
1facf9fc 6517+
027c5e7a
AM
6518+ /* in reverse order */
6519+ for (i = dpages.ndpage - 1; i >= 0; i--) {
6520+ dpage = dpages.dpages + i;
6521+ ndentry = dpage->ndentry;
6522+ for (j = ndentry - 1; j >= 0; j--) {
6523+ dentry = dpage->dentries[j];
6524+ if (dentry != parent)
6525+ au_do_hide(dentry);
6526+ }
6527+ }
1facf9fc 6528+
027c5e7a
AM
6529+out_dpages:
6530+ au_dpages_free(&dpages);
4f0767ce 6531+out:
027c5e7a 6532+ return err;
1facf9fc 6533+}
6534+
027c5e7a 6535+static void au_hide(struct dentry *dentry)
1facf9fc 6536+{
027c5e7a
AM
6537+ int err;
6538+ struct inode *inode;
1facf9fc 6539+
027c5e7a
AM
6540+ AuDbgDentry(dentry);
6541+ inode = dentry->d_inode;
6542+ if (inode && S_ISDIR(inode->i_mode)) {
6543+ /* shrink_dcache_parent(dentry); */
6544+ err = au_hide_children(dentry);
6545+ if (unlikely(err))
6546+ AuIOErr("%.*s, failed hiding children, ignored %d\n",
6547+ AuDLNPair(dentry), err);
6548+ }
6549+ au_do_hide(dentry);
6550+}
1facf9fc 6551+
027c5e7a
AM
6552+/*
6553+ * By adding a dirty branch, a cached dentry may be affected in various ways.
6554+ *
6555+ * a dirty branch is added
6556+ * - on the top of layers
6557+ * - in the middle of layers
6558+ * - to the bottom of layers
6559+ *
6560+ * on the added branch there exists
6561+ * - a whiteout
6562+ * - a diropq
6563+ * - a same named entry
6564+ * + exist
6565+ * * negative --> positive
6566+ * * positive --> positive
6567+ * - type is unchanged
6568+ * - type is changed
6569+ * + doesn't exist
6570+ * * negative --> negative
6571+ * * positive --> negative (rejected by au_br_del() for non-dir case)
6572+ * - none
6573+ */
6574+static int au_refresh_by_dinfo(struct dentry *dentry, struct au_dinfo *dinfo,
6575+ struct au_dinfo *tmp)
6576+{
6577+ int err;
6578+ aufs_bindex_t bindex, bend;
6579+ struct {
6580+ struct dentry *dentry;
6581+ struct inode *inode;
6582+ mode_t mode;
6583+ } orig_h, tmp_h;
6584+ struct au_hdentry *hd;
6585+ struct inode *inode, *h_inode;
6586+ struct dentry *h_dentry;
6587+
6588+ err = 0;
6589+ AuDebugOn(dinfo->di_bstart < 0);
6590+ orig_h.dentry = dinfo->di_hdentry[dinfo->di_bstart].hd_dentry;
6591+ orig_h.inode = orig_h.dentry->d_inode;
6592+ orig_h.mode = 0;
6593+ if (orig_h.inode)
6594+ orig_h.mode = orig_h.inode->i_mode & S_IFMT;
6595+ memset(&tmp_h, 0, sizeof(tmp_h));
6596+ if (tmp->di_bstart >= 0) {
6597+ tmp_h.dentry = tmp->di_hdentry[tmp->di_bstart].hd_dentry;
6598+ tmp_h.inode = tmp_h.dentry->d_inode;
6599+ if (tmp_h.inode)
6600+ tmp_h.mode = tmp_h.inode->i_mode & S_IFMT;
6601+ }
6602+
6603+ inode = dentry->d_inode;
6604+ if (!orig_h.inode) {
6605+ AuDbg("nagative originally\n");
6606+ if (inode) {
6607+ au_hide(dentry);
6608+ goto out;
6609+ }
6610+ AuDebugOn(inode);
6611+ AuDebugOn(dinfo->di_bstart != dinfo->di_bend);
6612+ AuDebugOn(dinfo->di_bdiropq != -1);
6613+
6614+ if (!tmp_h.inode) {
6615+ AuDbg("negative --> negative\n");
6616+ /* should have only one negative lower */
6617+ if (tmp->di_bstart >= 0
6618+ && tmp->di_bstart < dinfo->di_bstart) {
6619+ AuDebugOn(tmp->di_bstart != tmp->di_bend);
6620+ AuDebugOn(dinfo->di_bstart != dinfo->di_bend);
6621+ au_set_h_dptr(dentry, dinfo->di_bstart, NULL);
6622+ au_di_cp(dinfo, tmp);
6623+ hd = tmp->di_hdentry + tmp->di_bstart;
6624+ au_set_h_dptr(dentry, tmp->di_bstart,
6625+ dget(hd->hd_dentry));
6626+ }
6627+ au_dbg_verify_dinode(dentry);
6628+ } else {
6629+ AuDbg("negative --> positive\n");
6630+ /*
6631+ * similar to the behaviour of creating with bypassing
6632+ * aufs.
6633+ * unhash it in order to force an error in the
6634+ * succeeding create operation.
6635+ * we should not set S_DEAD here.
6636+ */
6637+ d_drop(dentry);
6638+ /* au_di_swap(tmp, dinfo); */
6639+ au_dbg_verify_dinode(dentry);
6640+ }
6641+ } else {
6642+ AuDbg("positive originally\n");
6643+ /* inode may be NULL */
6644+ AuDebugOn(inode && (inode->i_mode & S_IFMT) != orig_h.mode);
6645+ if (!tmp_h.inode) {
6646+ AuDbg("positive --> negative\n");
6647+ /* or bypassing aufs */
6648+ au_hide(dentry);
6649+ if (tmp->di_bwh >= 0 && tmp->di_bwh <= dinfo->di_bstart)
6650+ dinfo->di_bwh = tmp->di_bwh;
6651+ if (inode)
6652+ err = au_refresh_hinode_self(inode);
6653+ au_dbg_verify_dinode(dentry);
6654+ } else if (orig_h.mode == tmp_h.mode) {
6655+ AuDbg("positive --> positive, same type\n");
6656+ if (!S_ISDIR(orig_h.mode)
6657+ && dinfo->di_bstart > tmp->di_bstart) {
6658+ /*
6659+ * similar to the behaviour of removing and
6660+ * creating.
6661+ */
6662+ au_hide(dentry);
6663+ if (inode)
6664+ err = au_refresh_hinode_self(inode);
6665+ au_dbg_verify_dinode(dentry);
6666+ } else {
6667+ /* fill empty slots */
6668+ if (dinfo->di_bstart > tmp->di_bstart)
6669+ dinfo->di_bstart = tmp->di_bstart;
6670+ if (dinfo->di_bend < tmp->di_bend)
6671+ dinfo->di_bend = tmp->di_bend;
6672+ dinfo->di_bwh = tmp->di_bwh;
6673+ dinfo->di_bdiropq = tmp->di_bdiropq;
6674+ hd = tmp->di_hdentry;
6675+ bend = dinfo->di_bend;
6676+ for (bindex = tmp->di_bstart; bindex <= bend;
6677+ bindex++) {
6678+ if (au_h_dptr(dentry, bindex))
6679+ continue;
6680+ h_dentry = hd[bindex].hd_dentry;
6681+ if (!h_dentry)
6682+ continue;
6683+ h_inode = h_dentry->d_inode;
6684+ AuDebugOn(!h_inode);
6685+ AuDebugOn(orig_h.mode
6686+ != (h_inode->i_mode
6687+ & S_IFMT));
6688+ au_set_h_dptr(dentry, bindex,
6689+ dget(h_dentry));
6690+ }
6691+ err = au_refresh_hinode(inode, dentry);
6692+ au_dbg_verify_dinode(dentry);
6693+ }
6694+ } else {
6695+ AuDbg("positive --> positive, different type\n");
6696+ /* similar to the behaviour of removing and creating */
6697+ au_hide(dentry);
6698+ if (inode)
6699+ err = au_refresh_hinode_self(inode);
6700+ au_dbg_verify_dinode(dentry);
6701+ }
6702+ }
6703+
6704+out:
6705+ return err;
6706+}
6707+
6708+int au_refresh_dentry(struct dentry *dentry, struct dentry *parent)
6709+{
6710+ int err, ebrange;
6711+ unsigned int sigen;
6712+ struct au_dinfo *dinfo, *tmp;
6713+ struct super_block *sb;
6714+ struct inode *inode;
6715+
6716+ DiMustWriteLock(dentry);
6717+ AuDebugOn(IS_ROOT(dentry));
6718+ AuDebugOn(!parent->d_inode);
6719+
6720+ sb = dentry->d_sb;
6721+ inode = dentry->d_inode;
6722+ sigen = au_sigen(sb);
6723+ err = au_digen_test(parent, sigen);
6724+ if (unlikely(err))
6725+ goto out;
6726+
6727+ dinfo = au_di(dentry);
6728+ err = au_di_realloc(dinfo, au_sbend(sb) + 1);
6729+ if (unlikely(err))
6730+ goto out;
6731+ ebrange = au_dbrange_test(dentry);
6732+ if (!ebrange)
6733+ ebrange = au_do_refresh_hdentry(dentry, parent);
6734+
6735+ if (d_unhashed(dentry) || ebrange) {
6736+ AuDebugOn(au_dbstart(dentry) < 0 && au_dbend(dentry) >= 0);
6737+ if (inode)
6738+ err = au_refresh_hinode_self(inode);
6739+ au_dbg_verify_dinode(dentry);
6740+ if (!err)
6741+ goto out_dgen; /* success */
6742+ goto out;
6743+ }
6744+
6745+ /* temporary dinfo */
6746+ AuDbgDentry(dentry);
6747+ err = -ENOMEM;
6748+ tmp = au_di_alloc(sb, AuLsc_DI_TMP);
6749+ if (unlikely(!tmp))
6750+ goto out;
6751+ au_di_swap(tmp, dinfo);
6752+ /* returns the number of positive dentries */
6753+ /*
6754+ * if current working dir is removed, it returns an error.
6755+ * but the dentry is legal.
6756+ */
6757+ err = au_lkup_dentry(dentry, /*bstart*/0, /*type*/0, /*nd*/NULL);
6758+ AuDbgDentry(dentry);
6759+ au_di_swap(tmp, dinfo);
6760+ if (err == -ENOENT)
6761+ err = 0;
6762+ if (err >= 0) {
6763+ /* compare/refresh by dinfo */
6764+ AuDbgDentry(dentry);
6765+ err = au_refresh_by_dinfo(dentry, dinfo, tmp);
6766+ au_dbg_verify_dinode(dentry);
6767+ AuTraceErr(err);
6768+ }
6769+ au_rw_write_unlock(&tmp->di_rwsem);
6770+ au_di_free(tmp);
6771+ if (unlikely(err))
6772+ goto out;
6773+
6774+out_dgen:
6775+ au_update_digen(dentry);
6776+out:
6777+ if (unlikely(err && !(dentry->d_flags & DCACHE_NFSFS_RENAMED))) {
6778+ AuIOErr("failed refreshing %.*s, %d\n",
6779+ AuDLNPair(dentry), err);
6780+ AuDbgDentry(dentry);
6781+ }
6782+ AuTraceErr(err);
6783+ return err;
6784+}
6785+
6786+static noinline_for_stack
6787+int au_do_h_d_reval(struct dentry *h_dentry, struct nameidata *nd,
6788+ struct dentry *dentry, aufs_bindex_t bindex)
6789+{
6790+ int err, valid;
6791+ int (*reval)(struct dentry *, struct nameidata *);
6792+
6793+ err = 0;
6794+ if (!(h_dentry->d_flags & DCACHE_OP_REVALIDATE))
6795+ goto out;
6796+ reval = h_dentry->d_op->d_revalidate;
6797+
6798+ AuDbg("b%d\n", bindex);
6799+ if (au_test_fs_null_nd(h_dentry->d_sb))
6800+ /* it may return tri-state */
6801+ valid = reval(h_dentry, NULL);
6802+ else {
6803+ struct nameidata h_nd;
6804+ int locked;
1facf9fc 6805+ struct dentry *parent;
6806+
6807+ au_h_nd(&h_nd, nd);
6808+ parent = nd->path.dentry;
6809+ locked = (nd && nd->path.dentry != dentry);
6810+ if (locked)
6811+ di_read_lock_parent(parent, AuLock_IR);
6812+ BUG_ON(bindex > au_dbend(parent));
6813+ h_nd.path.dentry = au_h_dptr(parent, bindex);
6814+ BUG_ON(!h_nd.path.dentry);
6815+ h_nd.path.mnt = au_sbr(parent->d_sb, bindex)->br_mnt;
6816+ path_get(&h_nd.path);
6817+ valid = reval(h_dentry, &h_nd);
6818+ path_put(&h_nd.path);
6819+ if (locked)
6820+ di_read_unlock(parent, AuLock_IR);
6821+ }
6822+
6823+ if (unlikely(valid < 0))
6824+ err = valid;
6825+ else if (!valid)
6826+ err = -EINVAL;
6827+
4f0767ce 6828+out:
1facf9fc 6829+ AuTraceErr(err);
6830+ return err;
6831+}
6832+
6833+/* todo: remove this */
6834+static int h_d_revalidate(struct dentry *dentry, struct inode *inode,
6835+ struct nameidata *nd, int do_udba)
6836+{
6837+ int err;
6838+ umode_t mode, h_mode;
6839+ aufs_bindex_t bindex, btail, bstart, ibs, ibe;
6840+ unsigned char plus, unhashed, is_root, h_plus;
4a4d8108 6841+ struct inode *h_inode, *h_cached_inode;
1facf9fc 6842+ struct dentry *h_dentry;
6843+ struct qstr *name, *h_name;
6844+
6845+ err = 0;
6846+ plus = 0;
6847+ mode = 0;
1facf9fc 6848+ ibs = -1;
6849+ ibe = -1;
6850+ unhashed = !!d_unhashed(dentry);
6851+ is_root = !!IS_ROOT(dentry);
6852+ name = &dentry->d_name;
6853+
6854+ /*
7f207e10
AM
6855+ * Theoretically, REVAL test should be unnecessary in case of
6856+ * {FS,I}NOTIFY.
6857+ * But {fs,i}notify doesn't fire some necessary events,
1facf9fc 6858+ * IN_ATTRIB for atime/nlink/pageio
6859+ * IN_DELETE for NFS dentry
6860+ * Let's do REVAL test too.
6861+ */
6862+ if (do_udba && inode) {
6863+ mode = (inode->i_mode & S_IFMT);
6864+ plus = (inode->i_nlink > 0);
1facf9fc 6865+ ibs = au_ibstart(inode);
6866+ ibe = au_ibend(inode);
6867+ }
6868+
6869+ bstart = au_dbstart(dentry);
6870+ btail = bstart;
6871+ if (inode && S_ISDIR(inode->i_mode))
6872+ btail = au_dbtaildir(dentry);
6873+ for (bindex = bstart; bindex <= btail; bindex++) {
6874+ h_dentry = au_h_dptr(dentry, bindex);
6875+ if (!h_dentry)
6876+ continue;
6877+
6878+ AuDbg("b%d, %.*s\n", bindex, AuDLNPair(h_dentry));
027c5e7a 6879+ spin_lock(&h_dentry->d_lock);
1facf9fc 6880+ h_name = &h_dentry->d_name;
6881+ if (unlikely(do_udba
6882+ && !is_root
6883+ && (unhashed != !!d_unhashed(h_dentry)
6884+ || name->len != h_name->len
6885+ || memcmp(name->name, h_name->name, name->len))
6886+ )) {
6887+ AuDbg("unhash 0x%x 0x%x, %.*s %.*s\n",
6888+ unhashed, d_unhashed(h_dentry),
6889+ AuDLNPair(dentry), AuDLNPair(h_dentry));
027c5e7a 6890+ spin_unlock(&h_dentry->d_lock);
1facf9fc 6891+ goto err;
6892+ }
027c5e7a 6893+ spin_unlock(&h_dentry->d_lock);
1facf9fc 6894+
6895+ err = au_do_h_d_reval(h_dentry, nd, dentry, bindex);
6896+ if (unlikely(err))
6897+ /* do not goto err, to keep the errno */
6898+ break;
6899+
6900+ /* todo: plink too? */
6901+ if (!do_udba)
6902+ continue;
6903+
6904+ /* UDBA tests */
6905+ h_inode = h_dentry->d_inode;
6906+ if (unlikely(!!inode != !!h_inode))
6907+ goto err;
6908+
6909+ h_plus = plus;
6910+ h_mode = mode;
6911+ h_cached_inode = h_inode;
6912+ if (h_inode) {
6913+ h_mode = (h_inode->i_mode & S_IFMT);
6914+ h_plus = (h_inode->i_nlink > 0);
6915+ }
6916+ if (inode && ibs <= bindex && bindex <= ibe)
6917+ h_cached_inode = au_h_iptr(inode, bindex);
6918+
6919+ if (unlikely(plus != h_plus
6920+ || mode != h_mode
6921+ || h_cached_inode != h_inode))
6922+ goto err;
6923+ continue;
6924+
6925+ err:
6926+ err = -EINVAL;
6927+ break;
6928+ }
6929+
6930+ return err;
6931+}
6932+
027c5e7a 6933+/* todo: consolidate with do_refresh() and au_reval_for_attr() */
1facf9fc 6934+static int simple_reval_dpath(struct dentry *dentry, unsigned int sigen)
6935+{
6936+ int err;
6937+ struct dentry *parent;
1facf9fc 6938+
027c5e7a 6939+ if (!au_digen_test(dentry, sigen))
1facf9fc 6940+ return 0;
6941+
6942+ parent = dget_parent(dentry);
6943+ di_read_lock_parent(parent, AuLock_IR);
027c5e7a 6944+ AuDebugOn(au_digen_test(parent, sigen));
1facf9fc 6945+ au_dbg_verify_gen(parent, sigen);
027c5e7a 6946+ err = au_refresh_dentry(dentry, parent);
1facf9fc 6947+ di_read_unlock(parent, AuLock_IR);
6948+ dput(parent);
027c5e7a 6949+ AuTraceErr(err);
1facf9fc 6950+ return err;
6951+}
6952+
6953+int au_reval_dpath(struct dentry *dentry, unsigned int sigen)
6954+{
6955+ int err;
6956+ struct dentry *d, *parent;
6957+ struct inode *inode;
6958+
027c5e7a 6959+ if (!au_ftest_si(au_sbi(dentry->d_sb), FAILED_REFRESH_DIR))
1facf9fc 6960+ return simple_reval_dpath(dentry, sigen);
6961+
6962+ /* slow loop, keep it simple and stupid */
6963+ /* cf: au_cpup_dirs() */
6964+ err = 0;
6965+ parent = NULL;
027c5e7a 6966+ while (au_digen_test(dentry, sigen)) {
1facf9fc 6967+ d = dentry;
6968+ while (1) {
6969+ dput(parent);
6970+ parent = dget_parent(d);
027c5e7a 6971+ if (!au_digen_test(parent, sigen))
1facf9fc 6972+ break;
6973+ d = parent;
6974+ }
6975+
6976+ inode = d->d_inode;
6977+ if (d != dentry)
027c5e7a 6978+ di_write_lock_child2(d);
1facf9fc 6979+
6980+ /* someone might update our dentry while we were sleeping */
027c5e7a
AM
6981+ if (au_digen_test(d, sigen)) {
6982+ /*
6983+ * todo: consolidate with simple_reval_dpath(),
6984+ * do_refresh() and au_reval_for_attr().
6985+ */
1facf9fc 6986+ di_read_lock_parent(parent, AuLock_IR);
027c5e7a 6987+ err = au_refresh_dentry(d, parent);
1facf9fc 6988+ di_read_unlock(parent, AuLock_IR);
6989+ }
6990+
6991+ if (d != dentry)
6992+ di_write_unlock(d);
6993+ dput(parent);
6994+ if (unlikely(err))
6995+ break;
6996+ }
6997+
6998+ return err;
6999+}
7000+
7001+/*
7002+ * if valid returns 1, otherwise 0.
7003+ */
7004+static int aufs_d_revalidate(struct dentry *dentry, struct nameidata *nd)
7005+{
7006+ int valid, err;
7007+ unsigned int sigen;
7008+ unsigned char do_udba;
7009+ struct super_block *sb;
7010+ struct inode *inode;
7011+
027c5e7a
AM
7012+ /* todo: support rcu-walk? */
7013+ if (nd && (nd->flags & LOOKUP_RCU))
7014+ return -ECHILD;
7015+
7016+ valid = 0;
7017+ if (unlikely(!au_di(dentry)))
7018+ goto out;
7019+
7020+ inode = dentry->d_inode;
7021+ if (inode && is_bad_inode(inode))
7022+ goto out;
7023+
e49829fe 7024+ valid = 1;
1facf9fc 7025+ sb = dentry->d_sb;
e49829fe
JR
7026+ /*
7027+ * todo: very ugly
7028+ * i_mutex of parent dir may be held,
7029+ * but we should not return 'invalid' due to busy.
7030+ */
7031+ err = aufs_read_lock(dentry, AuLock_FLUSH | AuLock_DW | AuLock_NOPLM);
7032+ if (unlikely(err)) {
7033+ valid = err;
027c5e7a 7034+ AuTraceErr(err);
e49829fe
JR
7035+ goto out;
7036+ }
027c5e7a
AM
7037+ if (unlikely(au_dbrange_test(dentry))) {
7038+ err = -EINVAL;
7039+ AuTraceErr(err);
7040+ goto out_dgrade;
1facf9fc 7041+ }
027c5e7a
AM
7042+
7043+ sigen = au_sigen(sb);
7044+ if (au_digen_test(dentry, sigen)) {
1facf9fc 7045+ AuDebugOn(IS_ROOT(dentry));
027c5e7a
AM
7046+ err = au_reval_dpath(dentry, sigen);
7047+ if (unlikely(err)) {
7048+ AuTraceErr(err);
1facf9fc 7049+ goto out_dgrade;
027c5e7a 7050+ }
1facf9fc 7051+ }
7052+ di_downgrade_lock(dentry, AuLock_IR);
7053+
1facf9fc 7054+ err = -EINVAL;
027c5e7a
AM
7055+ if (inode && (IS_DEADDIR(inode) || !inode->i_nlink))
7056+ goto out_inval;
7057+
1facf9fc 7058+ do_udba = !au_opt_test(au_mntflags(sb), UDBA_NONE);
7059+ if (do_udba && inode) {
7060+ aufs_bindex_t bstart = au_ibstart(inode);
027c5e7a 7061+ struct inode *h_inode;
1facf9fc 7062+
027c5e7a
AM
7063+ if (bstart >= 0) {
7064+ h_inode = au_h_iptr(inode, bstart);
7065+ if (h_inode && au_test_higen(inode, h_inode))
7066+ goto out_inval;
7067+ }
1facf9fc 7068+ }
7069+
7070+ err = h_d_revalidate(dentry, inode, nd, do_udba);
027c5e7a 7071+ if (unlikely(!err && do_udba && au_dbstart(dentry) < 0)) {
1facf9fc 7072+ err = -EIO;
027c5e7a
AM
7073+ AuDbg("both of real entry and whiteout found, %.*s, err %d\n",
7074+ AuDLNPair(dentry), err);
7075+ }
e49829fe 7076+ goto out_inval;
1facf9fc 7077+
4f0767ce 7078+out_dgrade:
1facf9fc 7079+ di_downgrade_lock(dentry, AuLock_IR);
e49829fe 7080+out_inval:
1facf9fc 7081+ aufs_read_unlock(dentry, AuLock_IR);
7082+ AuTraceErr(err);
7083+ valid = !err;
e49829fe 7084+out:
027c5e7a 7085+ if (!valid) {
e49829fe 7086+ AuDbg("%.*s invalid, %d\n", AuDLNPair(dentry), valid);
027c5e7a
AM
7087+ d_drop(dentry);
7088+ }
1facf9fc 7089+ return valid;
7090+}
7091+
7092+static void aufs_d_release(struct dentry *dentry)
7093+{
027c5e7a 7094+ if (au_di(dentry)) {
4a4d8108
AM
7095+ au_di_fin(dentry);
7096+ au_hn_di_reinit(dentry);
1facf9fc 7097+ }
1facf9fc 7098+}
7099+
4a4d8108 7100+const struct dentry_operations aufs_dop = {
1facf9fc 7101+ .d_revalidate = aufs_d_revalidate,
7102+ .d_release = aufs_d_release
7103+};
7f207e10
AM
7104diff -urN /usr/share/empty/fs/aufs/dentry.h linux/fs/aufs/dentry.h
7105--- /usr/share/empty/fs/aufs/dentry.h 1970-01-01 01:00:00.000000000 +0100
0c3ec466 7106+++ linux/fs/aufs/dentry.h 2012-07-22 19:57:03.161004531 +0200
f6c5ef8b 7107@@ -0,0 +1,237 @@
1facf9fc 7108+/*
f6c5ef8b 7109+ * Copyright (C) 2005-2012 Junjiro R. Okajima
1facf9fc 7110+ *
7111+ * This program, aufs is free software; you can redistribute it and/or modify
7112+ * it under the terms of the GNU General Public License as published by
7113+ * the Free Software Foundation; either version 2 of the License, or
7114+ * (at your option) any later version.
dece6358
AM
7115+ *
7116+ * This program is distributed in the hope that it will be useful,
7117+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
7118+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
7119+ * GNU General Public License for more details.
7120+ *
7121+ * You should have received a copy of the GNU General Public License
7122+ * along with this program; if not, write to the Free Software
7123+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 7124+ */
7125+
7126+/*
7127+ * lookup and dentry operations
7128+ */
7129+
7130+#ifndef __AUFS_DENTRY_H__
7131+#define __AUFS_DENTRY_H__
7132+
7133+#ifdef __KERNEL__
7134+
dece6358 7135+#include <linux/dcache.h>
1facf9fc 7136+#include "rwsem.h"
7137+
1facf9fc 7138+struct au_hdentry {
7139+ struct dentry *hd_dentry;
027c5e7a 7140+ aufs_bindex_t hd_id;
1facf9fc 7141+};
7142+
7143+struct au_dinfo {
7144+ atomic_t di_generation;
7145+
dece6358 7146+ struct au_rwsem di_rwsem;
1facf9fc 7147+ aufs_bindex_t di_bstart, di_bend, di_bwh, di_bdiropq;
7148+ struct au_hdentry *di_hdentry;
4a4d8108 7149+} ____cacheline_aligned_in_smp;
1facf9fc 7150+
7151+/* ---------------------------------------------------------------------- */
7152+
7153+/* dentry.c */
4a4d8108 7154+extern const struct dentry_operations aufs_dop;
1facf9fc 7155+struct au_branch;
7156+struct dentry *au_lkup_one(struct qstr *name, struct dentry *h_parent,
7157+ struct au_branch *br, struct nameidata *nd);
7158+struct dentry *au_sio_lkup_one(struct qstr *name, struct dentry *parent,
7159+ struct au_branch *br);
7160+int au_h_verify(struct dentry *h_dentry, unsigned int udba, struct inode *h_dir,
7161+ struct dentry *h_parent, struct au_branch *br);
7162+
7163+int au_lkup_dentry(struct dentry *dentry, aufs_bindex_t bstart, mode_t type,
7164+ struct nameidata *nd);
7165+int au_lkup_neg(struct dentry *dentry, aufs_bindex_t bindex);
027c5e7a 7166+int au_refresh_dentry(struct dentry *dentry, struct dentry *parent);
1facf9fc 7167+int au_reval_dpath(struct dentry *dentry, unsigned int sigen);
7168+
7169+/* dinfo.c */
4a4d8108 7170+void au_di_init_once(void *_di);
027c5e7a
AM
7171+struct au_dinfo *au_di_alloc(struct super_block *sb, unsigned int lsc);
7172+void au_di_free(struct au_dinfo *dinfo);
7173+void au_di_swap(struct au_dinfo *a, struct au_dinfo *b);
7174+void au_di_cp(struct au_dinfo *dst, struct au_dinfo *src);
4a4d8108
AM
7175+int au_di_init(struct dentry *dentry);
7176+void au_di_fin(struct dentry *dentry);
1facf9fc 7177+int au_di_realloc(struct au_dinfo *dinfo, int nbr);
7178+
7179+void di_read_lock(struct dentry *d, int flags, unsigned int lsc);
7180+void di_read_unlock(struct dentry *d, int flags);
7181+void di_downgrade_lock(struct dentry *d, int flags);
7182+void di_write_lock(struct dentry *d, unsigned int lsc);
7183+void di_write_unlock(struct dentry *d);
7184+void di_write_lock2_child(struct dentry *d1, struct dentry *d2, int isdir);
7185+void di_write_lock2_parent(struct dentry *d1, struct dentry *d2, int isdir);
7186+void di_write_unlock2(struct dentry *d1, struct dentry *d2);
7187+
7188+struct dentry *au_h_dptr(struct dentry *dentry, aufs_bindex_t bindex);
2cbb1c4b 7189+struct dentry *au_h_d_alias(struct dentry *dentry, aufs_bindex_t bindex);
1facf9fc 7190+aufs_bindex_t au_dbtail(struct dentry *dentry);
7191+aufs_bindex_t au_dbtaildir(struct dentry *dentry);
7192+
7193+void au_set_h_dptr(struct dentry *dentry, aufs_bindex_t bindex,
7194+ struct dentry *h_dentry);
027c5e7a
AM
7195+int au_digen_test(struct dentry *dentry, unsigned int sigen);
7196+int au_dbrange_test(struct dentry *dentry);
1facf9fc 7197+void au_update_digen(struct dentry *dentry);
7198+void au_update_dbrange(struct dentry *dentry, int do_put_zero);
7199+void au_update_dbstart(struct dentry *dentry);
7200+void au_update_dbend(struct dentry *dentry);
7201+int au_find_dbindex(struct dentry *dentry, struct dentry *h_dentry);
7202+
7203+/* ---------------------------------------------------------------------- */
7204+
7205+static inline struct au_dinfo *au_di(struct dentry *dentry)
7206+{
7207+ return dentry->d_fsdata;
7208+}
7209+
7210+/* ---------------------------------------------------------------------- */
7211+
7212+/* lock subclass for dinfo */
7213+enum {
7214+ AuLsc_DI_CHILD, /* child first */
4a4d8108 7215+ AuLsc_DI_CHILD2, /* rename(2), link(2), and cpup at hnotify */
1facf9fc 7216+ AuLsc_DI_CHILD3, /* copyup dirs */
7217+ AuLsc_DI_PARENT,
7218+ AuLsc_DI_PARENT2,
027c5e7a
AM
7219+ AuLsc_DI_PARENT3,
7220+ AuLsc_DI_TMP /* temp for replacing dinfo */
1facf9fc 7221+};
7222+
7223+/*
7224+ * di_read_lock_child, di_write_lock_child,
7225+ * di_read_lock_child2, di_write_lock_child2,
7226+ * di_read_lock_child3, di_write_lock_child3,
7227+ * di_read_lock_parent, di_write_lock_parent,
7228+ * di_read_lock_parent2, di_write_lock_parent2,
7229+ * di_read_lock_parent3, di_write_lock_parent3,
7230+ */
7231+#define AuReadLockFunc(name, lsc) \
7232+static inline void di_read_lock_##name(struct dentry *d, int flags) \
7233+{ di_read_lock(d, flags, AuLsc_DI_##lsc); }
7234+
7235+#define AuWriteLockFunc(name, lsc) \
7236+static inline void di_write_lock_##name(struct dentry *d) \
7237+{ di_write_lock(d, AuLsc_DI_##lsc); }
7238+
7239+#define AuRWLockFuncs(name, lsc) \
7240+ AuReadLockFunc(name, lsc) \
7241+ AuWriteLockFunc(name, lsc)
7242+
7243+AuRWLockFuncs(child, CHILD);
7244+AuRWLockFuncs(child2, CHILD2);
7245+AuRWLockFuncs(child3, CHILD3);
7246+AuRWLockFuncs(parent, PARENT);
7247+AuRWLockFuncs(parent2, PARENT2);
7248+AuRWLockFuncs(parent3, PARENT3);
7249+
7250+#undef AuReadLockFunc
7251+#undef AuWriteLockFunc
7252+#undef AuRWLockFuncs
7253+
7254+#define DiMustNoWaiters(d) AuRwMustNoWaiters(&au_di(d)->di_rwsem)
dece6358
AM
7255+#define DiMustAnyLock(d) AuRwMustAnyLock(&au_di(d)->di_rwsem)
7256+#define DiMustWriteLock(d) AuRwMustWriteLock(&au_di(d)->di_rwsem)
1facf9fc 7257+
7258+/* ---------------------------------------------------------------------- */
7259+
7260+/* todo: memory barrier? */
7261+static inline unsigned int au_digen(struct dentry *d)
7262+{
7263+ return atomic_read(&au_di(d)->di_generation);
7264+}
7265+
7266+static inline void au_h_dentry_init(struct au_hdentry *hdentry)
7267+{
7268+ hdentry->hd_dentry = NULL;
7269+}
7270+
7271+static inline void au_hdput(struct au_hdentry *hd)
7272+{
4a4d8108
AM
7273+ if (hd)
7274+ dput(hd->hd_dentry);
1facf9fc 7275+}
7276+
7277+static inline aufs_bindex_t au_dbstart(struct dentry *dentry)
7278+{
1308ab2a 7279+ DiMustAnyLock(dentry);
1facf9fc 7280+ return au_di(dentry)->di_bstart;
7281+}
7282+
7283+static inline aufs_bindex_t au_dbend(struct dentry *dentry)
7284+{
1308ab2a 7285+ DiMustAnyLock(dentry);
1facf9fc 7286+ return au_di(dentry)->di_bend;
7287+}
7288+
7289+static inline aufs_bindex_t au_dbwh(struct dentry *dentry)
7290+{
1308ab2a 7291+ DiMustAnyLock(dentry);
1facf9fc 7292+ return au_di(dentry)->di_bwh;
7293+}
7294+
7295+static inline aufs_bindex_t au_dbdiropq(struct dentry *dentry)
7296+{
1308ab2a 7297+ DiMustAnyLock(dentry);
1facf9fc 7298+ return au_di(dentry)->di_bdiropq;
7299+}
7300+
7301+/* todo: hard/soft set? */
7302+static inline void au_set_dbstart(struct dentry *dentry, aufs_bindex_t bindex)
7303+{
1308ab2a 7304+ DiMustWriteLock(dentry);
1facf9fc 7305+ au_di(dentry)->di_bstart = bindex;
7306+}
7307+
7308+static inline void au_set_dbend(struct dentry *dentry, aufs_bindex_t bindex)
7309+{
1308ab2a 7310+ DiMustWriteLock(dentry);
1facf9fc 7311+ au_di(dentry)->di_bend = bindex;
7312+}
7313+
7314+static inline void au_set_dbwh(struct dentry *dentry, aufs_bindex_t bindex)
7315+{
1308ab2a 7316+ DiMustWriteLock(dentry);
1facf9fc 7317+ /* dbwh can be outside of bstart - bend range */
7318+ au_di(dentry)->di_bwh = bindex;
7319+}
7320+
7321+static inline void au_set_dbdiropq(struct dentry *dentry, aufs_bindex_t bindex)
7322+{
1308ab2a 7323+ DiMustWriteLock(dentry);
1facf9fc 7324+ au_di(dentry)->di_bdiropq = bindex;
7325+}
7326+
7327+/* ---------------------------------------------------------------------- */
7328+
4a4d8108 7329+#ifdef CONFIG_AUFS_HNOTIFY
1facf9fc 7330+static inline void au_digen_dec(struct dentry *d)
7331+{
e49829fe 7332+ atomic_dec(&au_di(d)->di_generation);
1facf9fc 7333+}
7334+
4a4d8108 7335+static inline void au_hn_di_reinit(struct dentry *dentry)
1facf9fc 7336+{
7337+ dentry->d_fsdata = NULL;
7338+}
7339+#else
4a4d8108
AM
7340+AuStubVoid(au_hn_di_reinit, struct dentry *dentry __maybe_unused)
7341+#endif /* CONFIG_AUFS_HNOTIFY */
1facf9fc 7342+
7343+#endif /* __KERNEL__ */
7344+#endif /* __AUFS_DENTRY_H__ */
7f207e10
AM
7345diff -urN /usr/share/empty/fs/aufs/dinfo.c linux/fs/aufs/dinfo.c
7346--- /usr/share/empty/fs/aufs/dinfo.c 1970-01-01 01:00:00.000000000 +0100
0c3ec466 7347+++ linux/fs/aufs/dinfo.c 2012-07-22 19:57:03.161004531 +0200
2cbb1c4b 7348@@ -0,0 +1,543 @@
1facf9fc 7349+/*
f6c5ef8b 7350+ * Copyright (C) 2005-2012 Junjiro R. Okajima
1facf9fc 7351+ *
7352+ * This program, aufs is free software; you can redistribute it and/or modify
7353+ * it under the terms of the GNU General Public License as published by
7354+ * the Free Software Foundation; either version 2 of the License, or
7355+ * (at your option) any later version.
dece6358
AM
7356+ *
7357+ * This program is distributed in the hope that it will be useful,
7358+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
7359+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
7360+ * GNU General Public License for more details.
7361+ *
7362+ * You should have received a copy of the GNU General Public License
7363+ * along with this program; if not, write to the Free Software
7364+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 7365+ */
7366+
7367+/*
7368+ * dentry private data
7369+ */
7370+
7371+#include "aufs.h"
7372+
e49829fe 7373+void au_di_init_once(void *_dinfo)
4a4d8108 7374+{
e49829fe
JR
7375+ struct au_dinfo *dinfo = _dinfo;
7376+ static struct lock_class_key aufs_di;
4a4d8108 7377+
e49829fe
JR
7378+ au_rw_init(&dinfo->di_rwsem);
7379+ au_rw_class(&dinfo->di_rwsem, &aufs_di);
4a4d8108
AM
7380+}
7381+
027c5e7a 7382+struct au_dinfo *au_di_alloc(struct super_block *sb, unsigned int lsc)
1facf9fc 7383+{
7384+ struct au_dinfo *dinfo;
027c5e7a 7385+ int nbr, i;
1facf9fc 7386+
7387+ dinfo = au_cache_alloc_dinfo();
7388+ if (unlikely(!dinfo))
7389+ goto out;
7390+
1facf9fc 7391+ nbr = au_sbend(sb) + 1;
7392+ if (nbr <= 0)
7393+ nbr = 1;
7394+ dinfo->di_hdentry = kcalloc(nbr, sizeof(*dinfo->di_hdentry), GFP_NOFS);
027c5e7a
AM
7395+ if (dinfo->di_hdentry) {
7396+ au_rw_write_lock_nested(&dinfo->di_rwsem, lsc);
7397+ dinfo->di_bstart = -1;
7398+ dinfo->di_bend = -1;
7399+ dinfo->di_bwh = -1;
7400+ dinfo->di_bdiropq = -1;
7401+ for (i = 0; i < nbr; i++)
7402+ dinfo->di_hdentry[i].hd_id = -1;
7403+ goto out;
7404+ }
1facf9fc 7405+
1facf9fc 7406+ au_cache_free_dinfo(dinfo);
027c5e7a
AM
7407+ dinfo = NULL;
7408+
4f0767ce 7409+out:
027c5e7a 7410+ return dinfo;
1facf9fc 7411+}
7412+
027c5e7a 7413+void au_di_free(struct au_dinfo *dinfo)
4a4d8108 7414+{
4a4d8108
AM
7415+ struct au_hdentry *p;
7416+ aufs_bindex_t bend, bindex;
7417+
7418+ /* dentry may not be revalidated */
027c5e7a 7419+ bindex = dinfo->di_bstart;
4a4d8108 7420+ if (bindex >= 0) {
027c5e7a
AM
7421+ bend = dinfo->di_bend;
7422+ p = dinfo->di_hdentry + bindex;
4a4d8108
AM
7423+ while (bindex++ <= bend)
7424+ au_hdput(p++);
7425+ }
027c5e7a
AM
7426+ kfree(dinfo->di_hdentry);
7427+ au_cache_free_dinfo(dinfo);
7428+}
7429+
7430+void au_di_swap(struct au_dinfo *a, struct au_dinfo *b)
7431+{
7432+ struct au_hdentry *p;
7433+ aufs_bindex_t bi;
7434+
7435+ AuRwMustWriteLock(&a->di_rwsem);
7436+ AuRwMustWriteLock(&b->di_rwsem);
7437+
7438+#define DiSwap(v, name) \
7439+ do { \
7440+ v = a->di_##name; \
7441+ a->di_##name = b->di_##name; \
7442+ b->di_##name = v; \
7443+ } while (0)
7444+
7445+ DiSwap(p, hdentry);
7446+ DiSwap(bi, bstart);
7447+ DiSwap(bi, bend);
7448+ DiSwap(bi, bwh);
7449+ DiSwap(bi, bdiropq);
7450+ /* smp_mb(); */
7451+
7452+#undef DiSwap
7453+}
7454+
7455+void au_di_cp(struct au_dinfo *dst, struct au_dinfo *src)
7456+{
7457+ AuRwMustWriteLock(&dst->di_rwsem);
7458+ AuRwMustWriteLock(&src->di_rwsem);
7459+
7460+ dst->di_bstart = src->di_bstart;
7461+ dst->di_bend = src->di_bend;
7462+ dst->di_bwh = src->di_bwh;
7463+ dst->di_bdiropq = src->di_bdiropq;
7464+ /* smp_mb(); */
7465+}
7466+
7467+int au_di_init(struct dentry *dentry)
7468+{
7469+ int err;
7470+ struct super_block *sb;
7471+ struct au_dinfo *dinfo;
7472+
7473+ err = 0;
7474+ sb = dentry->d_sb;
7475+ dinfo = au_di_alloc(sb, AuLsc_DI_CHILD);
7476+ if (dinfo) {
7477+ atomic_set(&dinfo->di_generation, au_sigen(sb));
7478+ /* smp_mb(); */ /* atomic_set */
7479+ dentry->d_fsdata = dinfo;
7480+ } else
7481+ err = -ENOMEM;
7482+
7483+ return err;
7484+}
7485+
7486+void au_di_fin(struct dentry *dentry)
7487+{
7488+ struct au_dinfo *dinfo;
7489+
7490+ dinfo = au_di(dentry);
7491+ AuRwDestroy(&dinfo->di_rwsem);
7492+ au_di_free(dinfo);
4a4d8108
AM
7493+}
7494+
1facf9fc 7495+int au_di_realloc(struct au_dinfo *dinfo, int nbr)
7496+{
7497+ int err, sz;
7498+ struct au_hdentry *hdp;
7499+
1308ab2a 7500+ AuRwMustWriteLock(&dinfo->di_rwsem);
7501+
1facf9fc 7502+ err = -ENOMEM;
7503+ sz = sizeof(*hdp) * (dinfo->di_bend + 1);
7504+ if (!sz)
7505+ sz = sizeof(*hdp);
7506+ hdp = au_kzrealloc(dinfo->di_hdentry, sz, sizeof(*hdp) * nbr, GFP_NOFS);
7507+ if (hdp) {
7508+ dinfo->di_hdentry = hdp;
7509+ err = 0;
7510+ }
7511+
7512+ return err;
7513+}
7514+
7515+/* ---------------------------------------------------------------------- */
7516+
7517+static void do_ii_write_lock(struct inode *inode, unsigned int lsc)
7518+{
7519+ switch (lsc) {
7520+ case AuLsc_DI_CHILD:
7521+ ii_write_lock_child(inode);
7522+ break;
7523+ case AuLsc_DI_CHILD2:
7524+ ii_write_lock_child2(inode);
7525+ break;
7526+ case AuLsc_DI_CHILD3:
7527+ ii_write_lock_child3(inode);
7528+ break;
7529+ case AuLsc_DI_PARENT:
7530+ ii_write_lock_parent(inode);
7531+ break;
7532+ case AuLsc_DI_PARENT2:
7533+ ii_write_lock_parent2(inode);
7534+ break;
7535+ case AuLsc_DI_PARENT3:
7536+ ii_write_lock_parent3(inode);
7537+ break;
7538+ default:
7539+ BUG();
7540+ }
7541+}
7542+
7543+static void do_ii_read_lock(struct inode *inode, unsigned int lsc)
7544+{
7545+ switch (lsc) {
7546+ case AuLsc_DI_CHILD:
7547+ ii_read_lock_child(inode);
7548+ break;
7549+ case AuLsc_DI_CHILD2:
7550+ ii_read_lock_child2(inode);
7551+ break;
7552+ case AuLsc_DI_CHILD3:
7553+ ii_read_lock_child3(inode);
7554+ break;
7555+ case AuLsc_DI_PARENT:
7556+ ii_read_lock_parent(inode);
7557+ break;
7558+ case AuLsc_DI_PARENT2:
7559+ ii_read_lock_parent2(inode);
7560+ break;
7561+ case AuLsc_DI_PARENT3:
7562+ ii_read_lock_parent3(inode);
7563+ break;
7564+ default:
7565+ BUG();
7566+ }
7567+}
7568+
7569+void di_read_lock(struct dentry *d, int flags, unsigned int lsc)
7570+{
dece6358 7571+ au_rw_read_lock_nested(&au_di(d)->di_rwsem, lsc);
1facf9fc 7572+ if (d->d_inode) {
7573+ if (au_ftest_lock(flags, IW))
7574+ do_ii_write_lock(d->d_inode, lsc);
7575+ else if (au_ftest_lock(flags, IR))
7576+ do_ii_read_lock(d->d_inode, lsc);
7577+ }
7578+}
7579+
7580+void di_read_unlock(struct dentry *d, int flags)
7581+{
7582+ if (d->d_inode) {
027c5e7a
AM
7583+ if (au_ftest_lock(flags, IW)) {
7584+ au_dbg_verify_dinode(d);
1facf9fc 7585+ ii_write_unlock(d->d_inode);
027c5e7a
AM
7586+ } else if (au_ftest_lock(flags, IR)) {
7587+ au_dbg_verify_dinode(d);
1facf9fc 7588+ ii_read_unlock(d->d_inode);
027c5e7a 7589+ }
1facf9fc 7590+ }
dece6358 7591+ au_rw_read_unlock(&au_di(d)->di_rwsem);
1facf9fc 7592+}
7593+
7594+void di_downgrade_lock(struct dentry *d, int flags)
7595+{
1facf9fc 7596+ if (d->d_inode && au_ftest_lock(flags, IR))
7597+ ii_downgrade_lock(d->d_inode);
dece6358 7598+ au_rw_dgrade_lock(&au_di(d)->di_rwsem);
1facf9fc 7599+}
7600+
7601+void di_write_lock(struct dentry *d, unsigned int lsc)
7602+{
dece6358 7603+ au_rw_write_lock_nested(&au_di(d)->di_rwsem, lsc);
1facf9fc 7604+ if (d->d_inode)
7605+ do_ii_write_lock(d->d_inode, lsc);
7606+}
7607+
7608+void di_write_unlock(struct dentry *d)
7609+{
027c5e7a 7610+ au_dbg_verify_dinode(d);
1facf9fc 7611+ if (d->d_inode)
7612+ ii_write_unlock(d->d_inode);
dece6358 7613+ au_rw_write_unlock(&au_di(d)->di_rwsem);
1facf9fc 7614+}
7615+
7616+void di_write_lock2_child(struct dentry *d1, struct dentry *d2, int isdir)
7617+{
7618+ AuDebugOn(d1 == d2
7619+ || d1->d_inode == d2->d_inode
7620+ || d1->d_sb != d2->d_sb);
7621+
7622+ if (isdir && au_test_subdir(d1, d2)) {
7623+ di_write_lock_child(d1);
7624+ di_write_lock_child2(d2);
7625+ } else {
7626+ /* there should be no races */
7627+ di_write_lock_child(d2);
7628+ di_write_lock_child2(d1);
7629+ }
7630+}
7631+
7632+void di_write_lock2_parent(struct dentry *d1, struct dentry *d2, int isdir)
7633+{
7634+ AuDebugOn(d1 == d2
7635+ || d1->d_inode == d2->d_inode
7636+ || d1->d_sb != d2->d_sb);
7637+
7638+ if (isdir && au_test_subdir(d1, d2)) {
7639+ di_write_lock_parent(d1);
7640+ di_write_lock_parent2(d2);
7641+ } else {
7642+ /* there should be no races */
7643+ di_write_lock_parent(d2);
7644+ di_write_lock_parent2(d1);
7645+ }
7646+}
7647+
7648+void di_write_unlock2(struct dentry *d1, struct dentry *d2)
7649+{
7650+ di_write_unlock(d1);
7651+ if (d1->d_inode == d2->d_inode)
dece6358 7652+ au_rw_write_unlock(&au_di(d2)->di_rwsem);
1facf9fc 7653+ else
7654+ di_write_unlock(d2);
7655+}
7656+
7657+/* ---------------------------------------------------------------------- */
7658+
7659+struct dentry *au_h_dptr(struct dentry *dentry, aufs_bindex_t bindex)
7660+{
7661+ struct dentry *d;
7662+
1308ab2a 7663+ DiMustAnyLock(dentry);
7664+
1facf9fc 7665+ if (au_dbstart(dentry) < 0 || bindex < au_dbstart(dentry))
7666+ return NULL;
7667+ AuDebugOn(bindex < 0);
7668+ d = au_di(dentry)->di_hdentry[0 + bindex].hd_dentry;
027c5e7a 7669+ AuDebugOn(d && d->d_count <= 0);
1facf9fc 7670+ return d;
7671+}
7672+
2cbb1c4b
JR
7673+/*
7674+ * extended version of au_h_dptr().
7675+ * returns a hashed and positive h_dentry in bindex, NULL, or error.
7676+ */
7677+struct dentry *au_h_d_alias(struct dentry *dentry, aufs_bindex_t bindex)
7678+{
7679+ struct dentry *h_dentry;
7680+ struct inode *inode, *h_inode;
7681+
7682+ inode = dentry->d_inode;
7683+ AuDebugOn(!inode);
7684+
7685+ h_dentry = NULL;
7686+ if (au_dbstart(dentry) <= bindex
7687+ && bindex <= au_dbend(dentry))
7688+ h_dentry = au_h_dptr(dentry, bindex);
7689+ if (h_dentry && !au_d_hashed_positive(h_dentry)) {
7690+ dget(h_dentry);
7691+ goto out; /* success */
7692+ }
7693+
7694+ AuDebugOn(bindex < au_ibstart(inode));
7695+ AuDebugOn(au_ibend(inode) < bindex);
7696+ h_inode = au_h_iptr(inode, bindex);
7697+ h_dentry = d_find_alias(h_inode);
7698+ if (h_dentry) {
7699+ if (!IS_ERR(h_dentry)) {
7700+ if (!au_d_hashed_positive(h_dentry))
7701+ goto out; /* success */
7702+ dput(h_dentry);
7703+ } else
7704+ goto out;
7705+ }
7706+
7707+ if (au_opt_test(au_mntflags(dentry->d_sb), PLINK)) {
7708+ h_dentry = au_plink_lkup(inode, bindex);
7709+ AuDebugOn(!h_dentry);
7710+ if (!IS_ERR(h_dentry)) {
7711+ if (!au_d_hashed_positive(h_dentry))
7712+ goto out; /* success */
7713+ dput(h_dentry);
7714+ h_dentry = NULL;
7715+ }
7716+ }
7717+
7718+out:
7719+ AuDbgDentry(h_dentry);
7720+ return h_dentry;
7721+}
7722+
1facf9fc 7723+aufs_bindex_t au_dbtail(struct dentry *dentry)
7724+{
7725+ aufs_bindex_t bend, bwh;
7726+
7727+ bend = au_dbend(dentry);
7728+ if (0 <= bend) {
7729+ bwh = au_dbwh(dentry);
7730+ if (!bwh)
7731+ return bwh;
7732+ if (0 < bwh && bwh < bend)
7733+ return bwh - 1;
7734+ }
7735+ return bend;
7736+}
7737+
7738+aufs_bindex_t au_dbtaildir(struct dentry *dentry)
7739+{
7740+ aufs_bindex_t bend, bopq;
7741+
7742+ bend = au_dbtail(dentry);
7743+ if (0 <= bend) {
7744+ bopq = au_dbdiropq(dentry);
7745+ if (0 <= bopq && bopq < bend)
7746+ bend = bopq;
7747+ }
7748+ return bend;
7749+}
7750+
7751+/* ---------------------------------------------------------------------- */
7752+
7753+void au_set_h_dptr(struct dentry *dentry, aufs_bindex_t bindex,
7754+ struct dentry *h_dentry)
7755+{
7756+ struct au_hdentry *hd = au_di(dentry)->di_hdentry + bindex;
027c5e7a 7757+ struct au_branch *br;
1facf9fc 7758+
1308ab2a 7759+ DiMustWriteLock(dentry);
7760+
4a4d8108 7761+ au_hdput(hd);
1facf9fc 7762+ hd->hd_dentry = h_dentry;
027c5e7a
AM
7763+ if (h_dentry) {
7764+ br = au_sbr(dentry->d_sb, bindex);
7765+ hd->hd_id = br->br_id;
7766+ }
7767+}
7768+
7769+int au_dbrange_test(struct dentry *dentry)
7770+{
7771+ int err;
7772+ aufs_bindex_t bstart, bend;
7773+
7774+ err = 0;
7775+ bstart = au_dbstart(dentry);
7776+ bend = au_dbend(dentry);
7777+ if (bstart >= 0)
7778+ AuDebugOn(bend < 0 && bstart > bend);
7779+ else {
7780+ err = -EIO;
7781+ AuDebugOn(bend >= 0);
7782+ }
7783+
7784+ return err;
7785+}
7786+
7787+int au_digen_test(struct dentry *dentry, unsigned int sigen)
7788+{
7789+ int err;
7790+
7791+ err = 0;
7792+ if (unlikely(au_digen(dentry) != sigen
7793+ || au_iigen_test(dentry->d_inode, sigen)))
7794+ err = -EIO;
7795+
7796+ return err;
1facf9fc 7797+}
7798+
7799+void au_update_digen(struct dentry *dentry)
7800+{
7801+ atomic_set(&au_di(dentry)->di_generation, au_sigen(dentry->d_sb));
7802+ /* smp_mb(); */ /* atomic_set */
7803+}
7804+
7805+void au_update_dbrange(struct dentry *dentry, int do_put_zero)
7806+{
7807+ struct au_dinfo *dinfo;
7808+ struct dentry *h_d;
4a4d8108 7809+ struct au_hdentry *hdp;
1facf9fc 7810+
1308ab2a 7811+ DiMustWriteLock(dentry);
7812+
1facf9fc 7813+ dinfo = au_di(dentry);
7814+ if (!dinfo || dinfo->di_bstart < 0)
7815+ return;
7816+
4a4d8108 7817+ hdp = dinfo->di_hdentry;
1facf9fc 7818+ if (do_put_zero) {
7819+ aufs_bindex_t bindex, bend;
7820+
7821+ bend = dinfo->di_bend;
7822+ for (bindex = dinfo->di_bstart; bindex <= bend; bindex++) {
4a4d8108 7823+ h_d = hdp[0 + bindex].hd_dentry;
1facf9fc 7824+ if (h_d && !h_d->d_inode)
7825+ au_set_h_dptr(dentry, bindex, NULL);
7826+ }
7827+ }
7828+
7829+ dinfo->di_bstart = -1;
7830+ while (++dinfo->di_bstart <= dinfo->di_bend)
4a4d8108 7831+ if (hdp[0 + dinfo->di_bstart].hd_dentry)
1facf9fc 7832+ break;
7833+ if (dinfo->di_bstart > dinfo->di_bend) {
7834+ dinfo->di_bstart = -1;
7835+ dinfo->di_bend = -1;
7836+ return;
7837+ }
7838+
7839+ dinfo->di_bend++;
7840+ while (0 <= --dinfo->di_bend)
4a4d8108 7841+ if (hdp[0 + dinfo->di_bend].hd_dentry)
1facf9fc 7842+ break;
7843+ AuDebugOn(dinfo->di_bstart > dinfo->di_bend || dinfo->di_bend < 0);
7844+}
7845+
7846+void au_update_dbstart(struct dentry *dentry)
7847+{
7848+ aufs_bindex_t bindex, bend;
7849+ struct dentry *h_dentry;
7850+
7851+ bend = au_dbend(dentry);
7852+ for (bindex = au_dbstart(dentry); bindex <= bend; bindex++) {
7853+ h_dentry = au_h_dptr(dentry, bindex);
7854+ if (!h_dentry)
7855+ continue;
7856+ if (h_dentry->d_inode) {
7857+ au_set_dbstart(dentry, bindex);
7858+ return;
7859+ }
7860+ au_set_h_dptr(dentry, bindex, NULL);
7861+ }
7862+}
7863+
7864+void au_update_dbend(struct dentry *dentry)
7865+{
7866+ aufs_bindex_t bindex, bstart;
7867+ struct dentry *h_dentry;
7868+
7869+ bstart = au_dbstart(dentry);
7f207e10 7870+ for (bindex = au_dbend(dentry); bindex >= bstart; bindex--) {
1facf9fc 7871+ h_dentry = au_h_dptr(dentry, bindex);
7872+ if (!h_dentry)
7873+ continue;
7874+ if (h_dentry->d_inode) {
7875+ au_set_dbend(dentry, bindex);
7876+ return;
7877+ }
7878+ au_set_h_dptr(dentry, bindex, NULL);
7879+ }
7880+}
7881+
7882+int au_find_dbindex(struct dentry *dentry, struct dentry *h_dentry)
7883+{
7884+ aufs_bindex_t bindex, bend;
7885+
7886+ bend = au_dbend(dentry);
7887+ for (bindex = au_dbstart(dentry); bindex <= bend; bindex++)
7888+ if (au_h_dptr(dentry, bindex) == h_dentry)
7889+ return bindex;
7890+ return -1;
7891+}
7f207e10
AM
7892diff -urN /usr/share/empty/fs/aufs/dir.c linux/fs/aufs/dir.c
7893--- /usr/share/empty/fs/aufs/dir.c 1970-01-01 01:00:00.000000000 +0100
0c3ec466 7894+++ linux/fs/aufs/dir.c 2012-07-22 19:57:03.161004531 +0200
7eafdf33 7895@@ -0,0 +1,636 @@
1facf9fc 7896+/*
f6c5ef8b 7897+ * Copyright (C) 2005-2012 Junjiro R. Okajima
1facf9fc 7898+ *
7899+ * This program, aufs is free software; you can redistribute it and/or modify
7900+ * it under the terms of the GNU General Public License as published by
7901+ * the Free Software Foundation; either version 2 of the License, or
7902+ * (at your option) any later version.
dece6358
AM
7903+ *
7904+ * This program is distributed in the hope that it will be useful,
7905+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
7906+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
7907+ * GNU General Public License for more details.
7908+ *
7909+ * You should have received a copy of the GNU General Public License
7910+ * along with this program; if not, write to the Free Software
7911+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 7912+ */
7913+
7914+/*
7915+ * directory operations
7916+ */
7917+
7918+#include <linux/fs_stack.h>
7919+#include "aufs.h"
7920+
7921+void au_add_nlink(struct inode *dir, struct inode *h_dir)
7922+{
9dbd164d
AM
7923+ unsigned int nlink;
7924+
1facf9fc 7925+ AuDebugOn(!S_ISDIR(dir->i_mode) || !S_ISDIR(h_dir->i_mode));
7926+
9dbd164d
AM
7927+ nlink = dir->i_nlink;
7928+ nlink += h_dir->i_nlink - 2;
1facf9fc 7929+ if (h_dir->i_nlink < 2)
9dbd164d 7930+ nlink += 2;
7eafdf33 7931+ /* 0 can happen in revaliding */
92d182d2 7932+ set_nlink(dir, nlink);
1facf9fc 7933+}
7934+
7935+void au_sub_nlink(struct inode *dir, struct inode *h_dir)
7936+{
9dbd164d
AM
7937+ unsigned int nlink;
7938+
1facf9fc 7939+ AuDebugOn(!S_ISDIR(dir->i_mode) || !S_ISDIR(h_dir->i_mode));
7940+
9dbd164d
AM
7941+ nlink = dir->i_nlink;
7942+ nlink -= h_dir->i_nlink - 2;
1facf9fc 7943+ if (h_dir->i_nlink < 2)
9dbd164d 7944+ nlink -= 2;
92d182d2 7945+ /* nlink == 0 means the branch-fs is broken */
9dbd164d 7946+ set_nlink(dir, nlink);
1facf9fc 7947+}
7948+
1308ab2a 7949+loff_t au_dir_size(struct file *file, struct dentry *dentry)
7950+{
7951+ loff_t sz;
7952+ aufs_bindex_t bindex, bend;
7953+ struct file *h_file;
7954+ struct dentry *h_dentry;
7955+
7956+ sz = 0;
7957+ if (file) {
7958+ AuDebugOn(!file->f_dentry);
7959+ AuDebugOn(!file->f_dentry->d_inode);
7960+ AuDebugOn(!S_ISDIR(file->f_dentry->d_inode->i_mode));
7961+
4a4d8108 7962+ bend = au_fbend_dir(file);
1308ab2a 7963+ for (bindex = au_fbstart(file);
7964+ bindex <= bend && sz < KMALLOC_MAX_SIZE;
7965+ bindex++) {
4a4d8108 7966+ h_file = au_hf_dir(file, bindex);
1308ab2a 7967+ if (h_file
7968+ && h_file->f_dentry
7969+ && h_file->f_dentry->d_inode)
7970+ sz += i_size_read(h_file->f_dentry->d_inode);
7971+ }
7972+ } else {
7973+ AuDebugOn(!dentry);
7974+ AuDebugOn(!dentry->d_inode);
7975+ AuDebugOn(!S_ISDIR(dentry->d_inode->i_mode));
7976+
7977+ bend = au_dbtaildir(dentry);
7978+ for (bindex = au_dbstart(dentry);
7979+ bindex <= bend && sz < KMALLOC_MAX_SIZE;
7980+ bindex++) {
7981+ h_dentry = au_h_dptr(dentry, bindex);
7982+ if (h_dentry && h_dentry->d_inode)
7983+ sz += i_size_read(h_dentry->d_inode);
7984+ }
7985+ }
7986+ if (sz < KMALLOC_MAX_SIZE)
7987+ sz = roundup_pow_of_two(sz);
7988+ if (sz > KMALLOC_MAX_SIZE)
7989+ sz = KMALLOC_MAX_SIZE;
7990+ else if (sz < NAME_MAX) {
7991+ BUILD_BUG_ON(AUFS_RDBLK_DEF < NAME_MAX);
7992+ sz = AUFS_RDBLK_DEF;
7993+ }
7994+ return sz;
7995+}
7996+
1facf9fc 7997+/* ---------------------------------------------------------------------- */
7998+
7999+static int reopen_dir(struct file *file)
8000+{
8001+ int err;
8002+ unsigned int flags;
8003+ aufs_bindex_t bindex, btail, bstart;
8004+ struct dentry *dentry, *h_dentry;
8005+ struct file *h_file;
8006+
8007+ /* open all lower dirs */
8008+ dentry = file->f_dentry;
8009+ bstart = au_dbstart(dentry);
8010+ for (bindex = au_fbstart(file); bindex < bstart; bindex++)
8011+ au_set_h_fptr(file, bindex, NULL);
8012+ au_set_fbstart(file, bstart);
8013+
8014+ btail = au_dbtaildir(dentry);
4a4d8108 8015+ for (bindex = au_fbend_dir(file); btail < bindex; bindex--)
1facf9fc 8016+ au_set_h_fptr(file, bindex, NULL);
4a4d8108 8017+ au_set_fbend_dir(file, btail);
1facf9fc 8018+
4a4d8108 8019+ flags = vfsub_file_flags(file);
1facf9fc 8020+ for (bindex = bstart; bindex <= btail; bindex++) {
8021+ h_dentry = au_h_dptr(dentry, bindex);
8022+ if (!h_dentry)
8023+ continue;
4a4d8108 8024+ h_file = au_hf_dir(file, bindex);
1facf9fc 8025+ if (h_file)
8026+ continue;
8027+
8028+ h_file = au_h_open(dentry, bindex, flags, file);
8029+ err = PTR_ERR(h_file);
8030+ if (IS_ERR(h_file))
8031+ goto out; /* close all? */
8032+ au_set_h_fptr(file, bindex, h_file);
8033+ }
8034+ au_update_figen(file);
8035+ /* todo: necessary? */
8036+ /* file->f_ra = h_file->f_ra; */
8037+ err = 0;
8038+
4f0767ce 8039+out:
1facf9fc 8040+ return err;
8041+}
8042+
8043+static int do_open_dir(struct file *file, int flags)
8044+{
8045+ int err;
8046+ aufs_bindex_t bindex, btail;
8047+ struct dentry *dentry, *h_dentry;
8048+ struct file *h_file;
8049+
1308ab2a 8050+ FiMustWriteLock(file);
8051+
1facf9fc 8052+ dentry = file->f_dentry;
027c5e7a
AM
8053+ err = au_alive_dir(dentry);
8054+ if (unlikely(err))
8055+ goto out;
8056+
1facf9fc 8057+ file->f_version = dentry->d_inode->i_version;
8058+ bindex = au_dbstart(dentry);
8059+ au_set_fbstart(file, bindex);
8060+ btail = au_dbtaildir(dentry);
4a4d8108 8061+ au_set_fbend_dir(file, btail);
1facf9fc 8062+ for (; !err && bindex <= btail; bindex++) {
8063+ h_dentry = au_h_dptr(dentry, bindex);
8064+ if (!h_dentry)
8065+ continue;
8066+
8067+ h_file = au_h_open(dentry, bindex, flags, file);
8068+ if (IS_ERR(h_file)) {
8069+ err = PTR_ERR(h_file);
8070+ break;
8071+ }
8072+ au_set_h_fptr(file, bindex, h_file);
8073+ }
8074+ au_update_figen(file);
8075+ /* todo: necessary? */
8076+ /* file->f_ra = h_file->f_ra; */
8077+ if (!err)
8078+ return 0; /* success */
8079+
8080+ /* close all */
8081+ for (bindex = au_fbstart(file); bindex <= btail; bindex++)
8082+ au_set_h_fptr(file, bindex, NULL);
8083+ au_set_fbstart(file, -1);
4a4d8108
AM
8084+ au_set_fbend_dir(file, -1);
8085+
027c5e7a 8086+out:
1facf9fc 8087+ return err;
8088+}
8089+
8090+static int aufs_open_dir(struct inode *inode __maybe_unused,
8091+ struct file *file)
8092+{
4a4d8108
AM
8093+ int err;
8094+ struct super_block *sb;
8095+ struct au_fidir *fidir;
8096+
8097+ err = -ENOMEM;
8098+ sb = file->f_dentry->d_sb;
8099+ si_read_lock(sb, AuLock_FLUSH);
e49829fe 8100+ fidir = au_fidir_alloc(sb);
4a4d8108
AM
8101+ if (fidir) {
8102+ err = au_do_open(file, do_open_dir, fidir);
8103+ if (unlikely(err))
8104+ kfree(fidir);
8105+ }
8106+ si_read_unlock(sb);
8107+ return err;
1facf9fc 8108+}
8109+
8110+static int aufs_release_dir(struct inode *inode __maybe_unused,
8111+ struct file *file)
8112+{
8113+ struct au_vdir *vdir_cache;
4a4d8108
AM
8114+ struct au_finfo *finfo;
8115+ struct au_fidir *fidir;
8116+ aufs_bindex_t bindex, bend;
1facf9fc 8117+
4a4d8108
AM
8118+ finfo = au_fi(file);
8119+ fidir = finfo->fi_hdir;
8120+ if (fidir) {
0c5527e5
AM
8121+ /* remove me from sb->s_files */
8122+ file_sb_list_del(file);
8123+
4a4d8108
AM
8124+ vdir_cache = fidir->fd_vdir_cache; /* lock-free */
8125+ if (vdir_cache)
8126+ au_vdir_free(vdir_cache);
8127+
8128+ bindex = finfo->fi_btop;
8129+ if (bindex >= 0) {
8130+ /*
8131+ * calls fput() instead of filp_close(),
8132+ * since no dnotify or lock for the lower file.
8133+ */
8134+ bend = fidir->fd_bbot;
8135+ for (; bindex <= bend; bindex++)
8136+ au_set_h_fptr(file, bindex, NULL);
8137+ }
8138+ kfree(fidir);
8139+ finfo->fi_hdir = NULL;
1facf9fc 8140+ }
1facf9fc 8141+ au_finfo_fin(file);
1facf9fc 8142+ return 0;
8143+}
8144+
8145+/* ---------------------------------------------------------------------- */
8146+
4a4d8108
AM
8147+static int au_do_flush_dir(struct file *file, fl_owner_t id)
8148+{
8149+ int err;
8150+ aufs_bindex_t bindex, bend;
8151+ struct file *h_file;
8152+
8153+ err = 0;
8154+ bend = au_fbend_dir(file);
8155+ for (bindex = au_fbstart(file); !err && bindex <= bend; bindex++) {
8156+ h_file = au_hf_dir(file, bindex);
8157+ if (h_file)
8158+ err = vfsub_flush(h_file, id);
8159+ }
8160+ return err;
8161+}
8162+
8163+static int aufs_flush_dir(struct file *file, fl_owner_t id)
8164+{
8165+ return au_do_flush(file, id, au_do_flush_dir);
8166+}
8167+
8168+/* ---------------------------------------------------------------------- */
8169+
1facf9fc 8170+static int au_do_fsync_dir_no_file(struct dentry *dentry, int datasync)
8171+{
8172+ int err;
8173+ aufs_bindex_t bend, bindex;
8174+ struct inode *inode;
8175+ struct super_block *sb;
8176+
8177+ err = 0;
8178+ sb = dentry->d_sb;
8179+ inode = dentry->d_inode;
8180+ IMustLock(inode);
8181+ bend = au_dbend(dentry);
8182+ for (bindex = au_dbstart(dentry); !err && bindex <= bend; bindex++) {
8183+ struct path h_path;
1facf9fc 8184+
8185+ if (au_test_ro(sb, bindex, inode))
8186+ continue;
8187+ h_path.dentry = au_h_dptr(dentry, bindex);
8188+ if (!h_path.dentry)
8189+ continue;
1facf9fc 8190+
1facf9fc 8191+ h_path.mnt = au_sbr_mnt(sb, bindex);
53392da6 8192+ err = vfsub_fsync(NULL, &h_path, datasync);
1facf9fc 8193+ }
8194+
8195+ return err;
8196+}
8197+
8198+static int au_do_fsync_dir(struct file *file, int datasync)
8199+{
8200+ int err;
8201+ aufs_bindex_t bend, bindex;
8202+ struct file *h_file;
8203+ struct super_block *sb;
8204+ struct inode *inode;
1facf9fc 8205+
8206+ err = au_reval_and_lock_fdi(file, reopen_dir, /*wlock*/1);
8207+ if (unlikely(err))
8208+ goto out;
8209+
8210+ sb = file->f_dentry->d_sb;
8211+ inode = file->f_dentry->d_inode;
4a4d8108 8212+ bend = au_fbend_dir(file);
1facf9fc 8213+ for (bindex = au_fbstart(file); !err && bindex <= bend; bindex++) {
4a4d8108 8214+ h_file = au_hf_dir(file, bindex);
1facf9fc 8215+ if (!h_file || au_test_ro(sb, bindex, inode))
8216+ continue;
8217+
53392da6 8218+ err = vfsub_fsync(h_file, &h_file->f_path, datasync);
1facf9fc 8219+ }
8220+
4f0767ce 8221+out:
1facf9fc 8222+ return err;
8223+}
8224+
8225+/*
8226+ * @file may be NULL
8227+ */
1e00d052
AM
8228+static int aufs_fsync_dir(struct file *file, loff_t start, loff_t end,
8229+ int datasync)
1facf9fc 8230+{
8231+ int err;
b752ccd1 8232+ struct dentry *dentry;
1facf9fc 8233+ struct super_block *sb;
1e00d052 8234+ struct mutex *mtx;
1facf9fc 8235+
8236+ err = 0;
1e00d052
AM
8237+ dentry = file->f_dentry;
8238+ mtx = &dentry->d_inode->i_mutex;
8239+ mutex_lock(mtx);
1facf9fc 8240+ sb = dentry->d_sb;
8241+ si_noflush_read_lock(sb);
8242+ if (file)
8243+ err = au_do_fsync_dir(file, datasync);
8244+ else {
8245+ di_write_lock_child(dentry);
8246+ err = au_do_fsync_dir_no_file(dentry, datasync);
8247+ }
8248+ au_cpup_attr_timesizes(dentry->d_inode);
8249+ di_write_unlock(dentry);
8250+ if (file)
8251+ fi_write_unlock(file);
8252+
8253+ si_read_unlock(sb);
1e00d052 8254+ mutex_unlock(mtx);
1facf9fc 8255+ return err;
8256+}
8257+
8258+/* ---------------------------------------------------------------------- */
8259+
8260+static int aufs_readdir(struct file *file, void *dirent, filldir_t filldir)
8261+{
8262+ int err;
8263+ struct dentry *dentry;
9dbd164d 8264+ struct inode *inode, *h_inode;
1facf9fc 8265+ struct super_block *sb;
8266+
8267+ dentry = file->f_dentry;
8268+ inode = dentry->d_inode;
8269+ IMustLock(inode);
8270+
8271+ sb = dentry->d_sb;
8272+ si_read_lock(sb, AuLock_FLUSH);
8273+ err = au_reval_and_lock_fdi(file, reopen_dir, /*wlock*/1);
8274+ if (unlikely(err))
8275+ goto out;
027c5e7a
AM
8276+ err = au_alive_dir(dentry);
8277+ if (!err)
8278+ err = au_vdir_init(file);
1facf9fc 8279+ di_downgrade_lock(dentry, AuLock_IR);
8280+ if (unlikely(err))
8281+ goto out_unlock;
8282+
9dbd164d 8283+ h_inode = au_h_iptr(inode, au_ibstart(inode));
b752ccd1 8284+ if (!au_test_nfsd()) {
1facf9fc 8285+ err = au_vdir_fill_de(file, dirent, filldir);
9dbd164d 8286+ fsstack_copy_attr_atime(inode, h_inode);
1facf9fc 8287+ } else {
8288+ /*
8289+ * nfsd filldir may call lookup_one_len(), vfs_getattr(),
8290+ * encode_fh() and others.
8291+ */
9dbd164d 8292+ atomic_inc(&h_inode->i_count);
1facf9fc 8293+ di_read_unlock(dentry, AuLock_IR);
8294+ si_read_unlock(sb);
1facf9fc 8295+ err = au_vdir_fill_de(file, dirent, filldir);
1facf9fc 8296+ fsstack_copy_attr_atime(inode, h_inode);
8297+ fi_write_unlock(file);
9dbd164d 8298+ iput(h_inode);
1facf9fc 8299+
8300+ AuTraceErr(err);
8301+ return err;
8302+ }
8303+
4f0767ce 8304+out_unlock:
1facf9fc 8305+ di_read_unlock(dentry, AuLock_IR);
8306+ fi_write_unlock(file);
4f0767ce 8307+out:
1facf9fc 8308+ si_read_unlock(sb);
8309+ return err;
8310+}
8311+
8312+/* ---------------------------------------------------------------------- */
8313+
8314+#define AuTestEmpty_WHONLY 1
dece6358
AM
8315+#define AuTestEmpty_CALLED (1 << 1)
8316+#define AuTestEmpty_SHWH (1 << 2)
1facf9fc 8317+#define au_ftest_testempty(flags, name) ((flags) & AuTestEmpty_##name)
7f207e10
AM
8318+#define au_fset_testempty(flags, name) \
8319+ do { (flags) |= AuTestEmpty_##name; } while (0)
8320+#define au_fclr_testempty(flags, name) \
8321+ do { (flags) &= ~AuTestEmpty_##name; } while (0)
1facf9fc 8322+
dece6358
AM
8323+#ifndef CONFIG_AUFS_SHWH
8324+#undef AuTestEmpty_SHWH
8325+#define AuTestEmpty_SHWH 0
8326+#endif
8327+
1facf9fc 8328+struct test_empty_arg {
1308ab2a 8329+ struct au_nhash *whlist;
1facf9fc 8330+ unsigned int flags;
8331+ int err;
8332+ aufs_bindex_t bindex;
8333+};
8334+
8335+static int test_empty_cb(void *__arg, const char *__name, int namelen,
dece6358
AM
8336+ loff_t offset __maybe_unused, u64 ino,
8337+ unsigned int d_type)
1facf9fc 8338+{
8339+ struct test_empty_arg *arg = __arg;
8340+ char *name = (void *)__name;
8341+
8342+ arg->err = 0;
8343+ au_fset_testempty(arg->flags, CALLED);
8344+ /* smp_mb(); */
8345+ if (name[0] == '.'
8346+ && (namelen == 1 || (name[1] == '.' && namelen == 2)))
8347+ goto out; /* success */
8348+
8349+ if (namelen <= AUFS_WH_PFX_LEN
8350+ || memcmp(name, AUFS_WH_PFX, AUFS_WH_PFX_LEN)) {
8351+ if (au_ftest_testempty(arg->flags, WHONLY)
1308ab2a 8352+ && !au_nhash_test_known_wh(arg->whlist, name, namelen))
1facf9fc 8353+ arg->err = -ENOTEMPTY;
8354+ goto out;
8355+ }
8356+
8357+ name += AUFS_WH_PFX_LEN;
8358+ namelen -= AUFS_WH_PFX_LEN;
1308ab2a 8359+ if (!au_nhash_test_known_wh(arg->whlist, name, namelen))
1facf9fc 8360+ arg->err = au_nhash_append_wh
1308ab2a 8361+ (arg->whlist, name, namelen, ino, d_type, arg->bindex,
dece6358 8362+ au_ftest_testempty(arg->flags, SHWH));
1facf9fc 8363+
4f0767ce 8364+out:
1facf9fc 8365+ /* smp_mb(); */
8366+ AuTraceErr(arg->err);
8367+ return arg->err;
8368+}
8369+
8370+static int do_test_empty(struct dentry *dentry, struct test_empty_arg *arg)
8371+{
8372+ int err;
8373+ struct file *h_file;
8374+
8375+ h_file = au_h_open(dentry, arg->bindex,
8376+ O_RDONLY | O_NONBLOCK | O_DIRECTORY | O_LARGEFILE,
8377+ /*file*/NULL);
8378+ err = PTR_ERR(h_file);
8379+ if (IS_ERR(h_file))
8380+ goto out;
8381+
8382+ err = 0;
8383+ if (!au_opt_test(au_mntflags(dentry->d_sb), UDBA_NONE)
8384+ && !h_file->f_dentry->d_inode->i_nlink)
8385+ goto out_put;
8386+
8387+ do {
8388+ arg->err = 0;
8389+ au_fclr_testempty(arg->flags, CALLED);
8390+ /* smp_mb(); */
8391+ err = vfsub_readdir(h_file, test_empty_cb, arg);
8392+ if (err >= 0)
8393+ err = arg->err;
8394+ } while (!err && au_ftest_testempty(arg->flags, CALLED));
8395+
4f0767ce 8396+out_put:
1facf9fc 8397+ fput(h_file);
8398+ au_sbr_put(dentry->d_sb, arg->bindex);
4f0767ce 8399+out:
1facf9fc 8400+ return err;
8401+}
8402+
8403+struct do_test_empty_args {
8404+ int *errp;
8405+ struct dentry *dentry;
8406+ struct test_empty_arg *arg;
8407+};
8408+
8409+static void call_do_test_empty(void *args)
8410+{
8411+ struct do_test_empty_args *a = args;
8412+ *a->errp = do_test_empty(a->dentry, a->arg);
8413+}
8414+
8415+static int sio_test_empty(struct dentry *dentry, struct test_empty_arg *arg)
8416+{
8417+ int err, wkq_err;
8418+ struct dentry *h_dentry;
8419+ struct inode *h_inode;
8420+
8421+ h_dentry = au_h_dptr(dentry, arg->bindex);
8422+ h_inode = h_dentry->d_inode;
53392da6 8423+ /* todo: i_mode changes anytime? */
1facf9fc 8424+ mutex_lock_nested(&h_inode->i_mutex, AuLsc_I_CHILD);
8425+ err = au_test_h_perm_sio(h_inode, MAY_EXEC | MAY_READ);
8426+ mutex_unlock(&h_inode->i_mutex);
8427+ if (!err)
8428+ err = do_test_empty(dentry, arg);
8429+ else {
8430+ struct do_test_empty_args args = {
8431+ .errp = &err,
8432+ .dentry = dentry,
8433+ .arg = arg
8434+ };
8435+ unsigned int flags = arg->flags;
8436+
8437+ wkq_err = au_wkq_wait(call_do_test_empty, &args);
8438+ if (unlikely(wkq_err))
8439+ err = wkq_err;
8440+ arg->flags = flags;
8441+ }
8442+
8443+ return err;
8444+}
8445+
8446+int au_test_empty_lower(struct dentry *dentry)
8447+{
8448+ int err;
1308ab2a 8449+ unsigned int rdhash;
1facf9fc 8450+ aufs_bindex_t bindex, bstart, btail;
1308ab2a 8451+ struct au_nhash whlist;
1facf9fc 8452+ struct test_empty_arg arg;
1facf9fc 8453+
dece6358
AM
8454+ SiMustAnyLock(dentry->d_sb);
8455+
1308ab2a 8456+ rdhash = au_sbi(dentry->d_sb)->si_rdhash;
8457+ if (!rdhash)
8458+ rdhash = au_rdhash_est(au_dir_size(/*file*/NULL, dentry));
8459+ err = au_nhash_alloc(&whlist, rdhash, GFP_NOFS);
dece6358 8460+ if (unlikely(err))
1facf9fc 8461+ goto out;
8462+
1facf9fc 8463+ arg.flags = 0;
1308ab2a 8464+ arg.whlist = &whlist;
8465+ bstart = au_dbstart(dentry);
dece6358
AM
8466+ if (au_opt_test(au_mntflags(dentry->d_sb), SHWH))
8467+ au_fset_testempty(arg.flags, SHWH);
1facf9fc 8468+ arg.bindex = bstart;
8469+ err = do_test_empty(dentry, &arg);
8470+ if (unlikely(err))
8471+ goto out_whlist;
8472+
8473+ au_fset_testempty(arg.flags, WHONLY);
8474+ btail = au_dbtaildir(dentry);
8475+ for (bindex = bstart + 1; !err && bindex <= btail; bindex++) {
8476+ struct dentry *h_dentry;
8477+
8478+ h_dentry = au_h_dptr(dentry, bindex);
8479+ if (h_dentry && h_dentry->d_inode) {
8480+ arg.bindex = bindex;
8481+ err = do_test_empty(dentry, &arg);
8482+ }
8483+ }
8484+
4f0767ce 8485+out_whlist:
1308ab2a 8486+ au_nhash_wh_free(&whlist);
4f0767ce 8487+out:
1facf9fc 8488+ return err;
8489+}
8490+
8491+int au_test_empty(struct dentry *dentry, struct au_nhash *whlist)
8492+{
8493+ int err;
8494+ struct test_empty_arg arg;
8495+ aufs_bindex_t bindex, btail;
8496+
8497+ err = 0;
1308ab2a 8498+ arg.whlist = whlist;
1facf9fc 8499+ arg.flags = AuTestEmpty_WHONLY;
dece6358
AM
8500+ if (au_opt_test(au_mntflags(dentry->d_sb), SHWH))
8501+ au_fset_testempty(arg.flags, SHWH);
1facf9fc 8502+ btail = au_dbtaildir(dentry);
8503+ for (bindex = au_dbstart(dentry); !err && bindex <= btail; bindex++) {
8504+ struct dentry *h_dentry;
8505+
8506+ h_dentry = au_h_dptr(dentry, bindex);
8507+ if (h_dentry && h_dentry->d_inode) {
8508+ arg.bindex = bindex;
8509+ err = sio_test_empty(dentry, &arg);
8510+ }
8511+ }
8512+
8513+ return err;
8514+}
8515+
8516+/* ---------------------------------------------------------------------- */
8517+
8518+const struct file_operations aufs_dir_fop = {
4a4d8108 8519+ .owner = THIS_MODULE,
027c5e7a 8520+ .llseek = default_llseek,
1facf9fc 8521+ .read = generic_read_dir,
8522+ .readdir = aufs_readdir,
8523+ .unlocked_ioctl = aufs_ioctl_dir,
b752ccd1
AM
8524+#ifdef CONFIG_COMPAT
8525+ .compat_ioctl = aufs_compat_ioctl_dir,
8526+#endif
1facf9fc 8527+ .open = aufs_open_dir,
8528+ .release = aufs_release_dir,
4a4d8108 8529+ .flush = aufs_flush_dir,
1facf9fc 8530+ .fsync = aufs_fsync_dir
8531+};
7f207e10
AM
8532diff -urN /usr/share/empty/fs/aufs/dir.h linux/fs/aufs/dir.h
8533--- /usr/share/empty/fs/aufs/dir.h 1970-01-01 01:00:00.000000000 +0100
0c3ec466 8534+++ linux/fs/aufs/dir.h 2012-07-22 19:57:03.161004531 +0200
f6c5ef8b 8535@@ -0,0 +1,137 @@
1facf9fc 8536+/*
f6c5ef8b 8537+ * Copyright (C) 2005-2012 Junjiro R. Okajima
1facf9fc 8538+ *
8539+ * This program, aufs is free software; you can redistribute it and/or modify
8540+ * it under the terms of the GNU General Public License as published by
8541+ * the Free Software Foundation; either version 2 of the License, or
8542+ * (at your option) any later version.
dece6358
AM
8543+ *
8544+ * This program is distributed in the hope that it will be useful,
8545+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
8546+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
8547+ * GNU General Public License for more details.
8548+ *
8549+ * You should have received a copy of the GNU General Public License
8550+ * along with this program; if not, write to the Free Software
8551+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 8552+ */
8553+
8554+/*
8555+ * directory operations
8556+ */
8557+
8558+#ifndef __AUFS_DIR_H__
8559+#define __AUFS_DIR_H__
8560+
8561+#ifdef __KERNEL__
8562+
8563+#include <linux/fs.h>
1facf9fc 8564+
8565+/* ---------------------------------------------------------------------- */
8566+
8567+/* need to be faster and smaller */
8568+
8569+struct au_nhash {
dece6358
AM
8570+ unsigned int nh_num;
8571+ struct hlist_head *nh_head;
1facf9fc 8572+};
8573+
8574+struct au_vdir_destr {
8575+ unsigned char len;
8576+ unsigned char name[0];
8577+} __packed;
8578+
8579+struct au_vdir_dehstr {
8580+ struct hlist_node hash;
8581+ struct au_vdir_destr *str;
4a4d8108 8582+} ____cacheline_aligned_in_smp;
1facf9fc 8583+
8584+struct au_vdir_de {
8585+ ino_t de_ino;
8586+ unsigned char de_type;
8587+ /* caution: packed */
8588+ struct au_vdir_destr de_str;
8589+} __packed;
8590+
8591+struct au_vdir_wh {
8592+ struct hlist_node wh_hash;
dece6358
AM
8593+#ifdef CONFIG_AUFS_SHWH
8594+ ino_t wh_ino;
1facf9fc 8595+ aufs_bindex_t wh_bindex;
dece6358
AM
8596+ unsigned char wh_type;
8597+#else
8598+ aufs_bindex_t wh_bindex;
8599+#endif
8600+ /* caution: packed */
1facf9fc 8601+ struct au_vdir_destr wh_str;
8602+} __packed;
8603+
8604+union au_vdir_deblk_p {
8605+ unsigned char *deblk;
8606+ struct au_vdir_de *de;
8607+};
8608+
8609+struct au_vdir {
8610+ unsigned char **vd_deblk;
8611+ unsigned long vd_nblk;
1facf9fc 8612+ struct {
8613+ unsigned long ul;
8614+ union au_vdir_deblk_p p;
8615+ } vd_last;
8616+
8617+ unsigned long vd_version;
dece6358 8618+ unsigned int vd_deblk_sz;
1facf9fc 8619+ unsigned long vd_jiffy;
4a4d8108 8620+} ____cacheline_aligned_in_smp;
1facf9fc 8621+
8622+/* ---------------------------------------------------------------------- */
8623+
8624+/* dir.c */
8625+extern const struct file_operations aufs_dir_fop;
8626+void au_add_nlink(struct inode *dir, struct inode *h_dir);
8627+void au_sub_nlink(struct inode *dir, struct inode *h_dir);
1308ab2a 8628+loff_t au_dir_size(struct file *file, struct dentry *dentry);
1facf9fc 8629+int au_test_empty_lower(struct dentry *dentry);
8630+int au_test_empty(struct dentry *dentry, struct au_nhash *whlist);
8631+
8632+/* vdir.c */
1308ab2a 8633+unsigned int au_rdhash_est(loff_t sz);
dece6358
AM
8634+int au_nhash_alloc(struct au_nhash *nhash, unsigned int num_hash, gfp_t gfp);
8635+void au_nhash_wh_free(struct au_nhash *whlist);
1facf9fc 8636+int au_nhash_test_longer_wh(struct au_nhash *whlist, aufs_bindex_t btgt,
8637+ int limit);
dece6358
AM
8638+int au_nhash_test_known_wh(struct au_nhash *whlist, char *name, int nlen);
8639+int au_nhash_append_wh(struct au_nhash *whlist, char *name, int nlen, ino_t ino,
8640+ unsigned int d_type, aufs_bindex_t bindex,
8641+ unsigned char shwh);
1facf9fc 8642+void au_vdir_free(struct au_vdir *vdir);
8643+int au_vdir_init(struct file *file);
8644+int au_vdir_fill_de(struct file *file, void *dirent, filldir_t filldir);
8645+
8646+/* ioctl.c */
8647+long aufs_ioctl_dir(struct file *file, unsigned int cmd, unsigned long arg);
8648+
1308ab2a 8649+#ifdef CONFIG_AUFS_RDU
8650+/* rdu.c */
8651+long au_rdu_ioctl(struct file *file, unsigned int cmd, unsigned long arg);
b752ccd1
AM
8652+#ifdef CONFIG_COMPAT
8653+long au_rdu_compat_ioctl(struct file *file, unsigned int cmd,
8654+ unsigned long arg);
8655+#endif
1308ab2a 8656+#else
8657+static inline long au_rdu_ioctl(struct file *file, unsigned int cmd,
8658+ unsigned long arg)
8659+{
8660+ return -EINVAL;
8661+}
b752ccd1
AM
8662+#ifdef CONFIG_COMPAT
8663+static inline long au_rdu_compat_ioctl(struct file *file, unsigned int cmd,
8664+ unsigned long arg)
8665+{
8666+ return -EINVAL;
8667+}
8668+#endif
1308ab2a 8669+#endif
8670+
1facf9fc 8671+#endif /* __KERNEL__ */
8672+#endif /* __AUFS_DIR_H__ */
7f207e10
AM
8673diff -urN /usr/share/empty/fs/aufs/dynop.c linux/fs/aufs/dynop.c
8674--- /usr/share/empty/fs/aufs/dynop.c 1970-01-01 01:00:00.000000000 +0100
0c3ec466 8675+++ linux/fs/aufs/dynop.c 2012-07-22 19:57:03.161004531 +0200
2cbb1c4b 8676@@ -0,0 +1,377 @@
1facf9fc 8677+/*
f6c5ef8b 8678+ * Copyright (C) 2010-2012 Junjiro R. Okajima
1facf9fc 8679+ *
8680+ * This program, aufs is free software; you can redistribute it and/or modify
8681+ * it under the terms of the GNU General Public License as published by
8682+ * the Free Software Foundation; either version 2 of the License, or
8683+ * (at your option) any later version.
dece6358
AM
8684+ *
8685+ * This program is distributed in the hope that it will be useful,
8686+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
8687+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
8688+ * GNU General Public License for more details.
8689+ *
8690+ * You should have received a copy of the GNU General Public License
8691+ * along with this program; if not, write to the Free Software
8692+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 8693+ */
8694+
8695+/*
4a4d8108 8696+ * dynamically customizable operations for regular files
1facf9fc 8697+ */
8698+
1facf9fc 8699+#include "aufs.h"
8700+
4a4d8108 8701+#define DyPrSym(key) AuDbgSym(key->dk_op.dy_hop)
1facf9fc 8702+
4a4d8108
AM
8703+/*
8704+ * How large will these lists be?
8705+ * Usually just a few elements, 20-30 at most for each, I guess.
8706+ */
8707+static struct au_splhead dynop[AuDyLast];
8708+
8709+static struct au_dykey *dy_gfind_get(struct au_splhead *spl, const void *h_op)
1facf9fc 8710+{
4a4d8108
AM
8711+ struct au_dykey *key, *tmp;
8712+ struct list_head *head;
1facf9fc 8713+
4a4d8108
AM
8714+ key = NULL;
8715+ head = &spl->head;
8716+ rcu_read_lock();
8717+ list_for_each_entry_rcu(tmp, head, dk_list)
8718+ if (tmp->dk_op.dy_hop == h_op) {
8719+ key = tmp;
8720+ kref_get(&key->dk_kref);
8721+ break;
8722+ }
8723+ rcu_read_unlock();
8724+
8725+ return key;
1facf9fc 8726+}
8727+
4a4d8108 8728+static struct au_dykey *dy_bradd(struct au_branch *br, struct au_dykey *key)
1facf9fc 8729+{
4a4d8108
AM
8730+ struct au_dykey **k, *found;
8731+ const void *h_op = key->dk_op.dy_hop;
8732+ int i;
1facf9fc 8733+
4a4d8108
AM
8734+ found = NULL;
8735+ k = br->br_dykey;
8736+ for (i = 0; i < AuBrDynOp; i++)
8737+ if (k[i]) {
8738+ if (k[i]->dk_op.dy_hop == h_op) {
8739+ found = k[i];
8740+ break;
8741+ }
8742+ } else
8743+ break;
8744+ if (!found) {
8745+ spin_lock(&br->br_dykey_lock);
8746+ for (; i < AuBrDynOp; i++)
8747+ if (k[i]) {
8748+ if (k[i]->dk_op.dy_hop == h_op) {
8749+ found = k[i];
8750+ break;
8751+ }
8752+ } else {
8753+ k[i] = key;
8754+ break;
8755+ }
8756+ spin_unlock(&br->br_dykey_lock);
8757+ BUG_ON(i == AuBrDynOp); /* expand the array */
8758+ }
8759+
8760+ return found;
1facf9fc 8761+}
8762+
4a4d8108
AM
8763+/* kref_get() if @key is already added */
8764+static struct au_dykey *dy_gadd(struct au_splhead *spl, struct au_dykey *key)
8765+{
8766+ struct au_dykey *tmp, *found;
8767+ struct list_head *head;
8768+ const void *h_op = key->dk_op.dy_hop;
1facf9fc 8769+
4a4d8108
AM
8770+ found = NULL;
8771+ head = &spl->head;
8772+ spin_lock(&spl->spin);
8773+ list_for_each_entry(tmp, head, dk_list)
8774+ if (tmp->dk_op.dy_hop == h_op) {
8775+ kref_get(&tmp->dk_kref);
8776+ found = tmp;
8777+ break;
8778+ }
8779+ if (!found)
8780+ list_add_rcu(&key->dk_list, head);
8781+ spin_unlock(&spl->spin);
1facf9fc 8782+
4a4d8108
AM
8783+ if (!found)
8784+ DyPrSym(key);
8785+ return found;
8786+}
8787+
8788+static void dy_free_rcu(struct rcu_head *rcu)
1facf9fc 8789+{
4a4d8108
AM
8790+ struct au_dykey *key;
8791+
8792+ key = container_of(rcu, struct au_dykey, dk_rcu);
8793+ DyPrSym(key);
8794+ kfree(key);
1facf9fc 8795+}
8796+
4a4d8108
AM
8797+static void dy_free(struct kref *kref)
8798+{
8799+ struct au_dykey *key;
8800+ struct au_splhead *spl;
1facf9fc 8801+
4a4d8108
AM
8802+ key = container_of(kref, struct au_dykey, dk_kref);
8803+ spl = dynop + key->dk_op.dy_type;
8804+ au_spl_del_rcu(&key->dk_list, spl);
8805+ call_rcu(&key->dk_rcu, dy_free_rcu);
8806+}
8807+
8808+void au_dy_put(struct au_dykey *key)
1facf9fc 8809+{
4a4d8108
AM
8810+ kref_put(&key->dk_kref, dy_free);
8811+}
1facf9fc 8812+
4a4d8108
AM
8813+/* ---------------------------------------------------------------------- */
8814+
8815+#define DyDbgSize(cnt, op) AuDebugOn(cnt != sizeof(op)/sizeof(void *))
8816+
8817+#ifdef CONFIG_AUFS_DEBUG
8818+#define DyDbgDeclare(cnt) unsigned int cnt = 0
4f0767ce 8819+#define DyDbgInc(cnt) do { cnt++; } while (0)
4a4d8108
AM
8820+#else
8821+#define DyDbgDeclare(cnt) do {} while (0)
8822+#define DyDbgInc(cnt) do {} while (0)
8823+#endif
8824+
8825+#define DySet(func, dst, src, h_op, h_sb) do { \
8826+ DyDbgInc(cnt); \
8827+ if (h_op->func) { \
8828+ if (src.func) \
8829+ dst.func = src.func; \
8830+ else \
8831+ AuDbg("%s %s\n", au_sbtype(h_sb), #func); \
8832+ } \
8833+} while (0)
8834+
8835+#define DySetForce(func, dst, src) do { \
8836+ AuDebugOn(!src.func); \
8837+ DyDbgInc(cnt); \
8838+ dst.func = src.func; \
8839+} while (0)
8840+
8841+#define DySetAop(func) \
8842+ DySet(func, dyaop->da_op, aufs_aop, h_aop, h_sb)
8843+#define DySetAopForce(func) \
8844+ DySetForce(func, dyaop->da_op, aufs_aop)
8845+
8846+static void dy_aop(struct au_dykey *key, const void *h_op,
8847+ struct super_block *h_sb __maybe_unused)
8848+{
8849+ struct au_dyaop *dyaop = (void *)key;
8850+ const struct address_space_operations *h_aop = h_op;
8851+ DyDbgDeclare(cnt);
8852+
8853+ AuDbg("%s\n", au_sbtype(h_sb));
8854+
8855+ DySetAop(writepage);
8856+ DySetAopForce(readpage); /* force */
4a4d8108
AM
8857+ DySetAop(writepages);
8858+ DySetAop(set_page_dirty);
8859+ DySetAop(readpages);
8860+ DySetAop(write_begin);
8861+ DySetAop(write_end);
8862+ DySetAop(bmap);
8863+ DySetAop(invalidatepage);
8864+ DySetAop(releasepage);
027c5e7a 8865+ DySetAop(freepage);
4a4d8108
AM
8866+ /* these two will be changed according to an aufs mount option */
8867+ DySetAop(direct_IO);
8868+ DySetAop(get_xip_mem);
8869+ DySetAop(migratepage);
8870+ DySetAop(launder_page);
8871+ DySetAop(is_partially_uptodate);
8872+ DySetAop(error_remove_page);
8873+
8874+ DyDbgSize(cnt, *h_aop);
8875+ dyaop->da_get_xip_mem = h_aop->get_xip_mem;
8876+}
8877+
4a4d8108
AM
8878+/* ---------------------------------------------------------------------- */
8879+
8880+static void dy_bug(struct kref *kref)
8881+{
8882+ BUG();
8883+}
8884+
8885+static struct au_dykey *dy_get(struct au_dynop *op, struct au_branch *br)
8886+{
8887+ struct au_dykey *key, *old;
8888+ struct au_splhead *spl;
b752ccd1 8889+ struct op {
4a4d8108 8890+ unsigned int sz;
b752ccd1
AM
8891+ void (*set)(struct au_dykey *key, const void *h_op,
8892+ struct super_block *h_sb __maybe_unused);
8893+ };
8894+ static const struct op a[] = {
4a4d8108
AM
8895+ [AuDy_AOP] = {
8896+ .sz = sizeof(struct au_dyaop),
b752ccd1 8897+ .set = dy_aop
4a4d8108 8898+ }
b752ccd1
AM
8899+ };
8900+ const struct op *p;
4a4d8108
AM
8901+
8902+ spl = dynop + op->dy_type;
8903+ key = dy_gfind_get(spl, op->dy_hop);
8904+ if (key)
8905+ goto out_add; /* success */
8906+
8907+ p = a + op->dy_type;
8908+ key = kzalloc(p->sz, GFP_NOFS);
8909+ if (unlikely(!key)) {
8910+ key = ERR_PTR(-ENOMEM);
8911+ goto out;
8912+ }
8913+
8914+ key->dk_op.dy_hop = op->dy_hop;
8915+ kref_init(&key->dk_kref);
b752ccd1 8916+ p->set(key, op->dy_hop, br->br_mnt->mnt_sb);
4a4d8108
AM
8917+ old = dy_gadd(spl, key);
8918+ if (old) {
8919+ kfree(key);
8920+ key = old;
8921+ }
8922+
8923+out_add:
8924+ old = dy_bradd(br, key);
8925+ if (old)
8926+ /* its ref-count should never be zero here */
8927+ kref_put(&key->dk_kref, dy_bug);
8928+out:
8929+ return key;
8930+}
8931+
8932+/* ---------------------------------------------------------------------- */
8933+/*
8934+ * Aufs prohibits O_DIRECT by defaut even if the branch supports it.
8935+ * This behaviour is neccessary to return an error from open(O_DIRECT) instead
8936+ * of the succeeding I/O. The dio mount option enables O_DIRECT and makes
8937+ * open(O_DIRECT) always succeed, but the succeeding I/O may return an error.
8938+ * See the aufs manual in detail.
8939+ *
8940+ * To keep this behaviour, aufs has to set NULL to ->get_xip_mem too, and the
8941+ * performance of fadvise() and madvise() may be affected.
8942+ */
8943+static void dy_adx(struct au_dyaop *dyaop, int do_dx)
8944+{
8945+ if (!do_dx) {
8946+ dyaop->da_op.direct_IO = NULL;
8947+ dyaop->da_op.get_xip_mem = NULL;
8948+ } else {
8949+ dyaop->da_op.direct_IO = aufs_aop.direct_IO;
8950+ dyaop->da_op.get_xip_mem = aufs_aop.get_xip_mem;
8951+ if (!dyaop->da_get_xip_mem)
8952+ dyaop->da_op.get_xip_mem = NULL;
8953+ }
8954+}
8955+
8956+static struct au_dyaop *dy_aget(struct au_branch *br,
8957+ const struct address_space_operations *h_aop,
8958+ int do_dx)
8959+{
8960+ struct au_dyaop *dyaop;
8961+ struct au_dynop op;
8962+
8963+ op.dy_type = AuDy_AOP;
8964+ op.dy_haop = h_aop;
8965+ dyaop = (void *)dy_get(&op, br);
8966+ if (IS_ERR(dyaop))
8967+ goto out;
8968+ dy_adx(dyaop, do_dx);
8969+
8970+out:
8971+ return dyaop;
8972+}
8973+
8974+int au_dy_iaop(struct inode *inode, aufs_bindex_t bindex,
8975+ struct inode *h_inode)
8976+{
8977+ int err, do_dx;
8978+ struct super_block *sb;
8979+ struct au_branch *br;
8980+ struct au_dyaop *dyaop;
8981+
8982+ AuDebugOn(!S_ISREG(h_inode->i_mode));
8983+ IiMustWriteLock(inode);
8984+
8985+ sb = inode->i_sb;
8986+ br = au_sbr(sb, bindex);
8987+ do_dx = !!au_opt_test(au_mntflags(sb), DIO);
8988+ dyaop = dy_aget(br, h_inode->i_mapping->a_ops, do_dx);
8989+ err = PTR_ERR(dyaop);
8990+ if (IS_ERR(dyaop))
8991+ /* unnecessary to call dy_fput() */
8992+ goto out;
8993+
8994+ err = 0;
8995+ inode->i_mapping->a_ops = &dyaop->da_op;
8996+
8997+out:
8998+ return err;
8999+}
9000+
b752ccd1
AM
9001+/*
9002+ * Is it safe to replace a_ops during the inode/file is in operation?
9003+ * Yes, I hope so.
9004+ */
9005+int au_dy_irefresh(struct inode *inode)
9006+{
9007+ int err;
9008+ aufs_bindex_t bstart;
9009+ struct inode *h_inode;
9010+
9011+ err = 0;
9012+ if (S_ISREG(inode->i_mode)) {
9013+ bstart = au_ibstart(inode);
9014+ h_inode = au_h_iptr(inode, bstart);
9015+ err = au_dy_iaop(inode, bstart, h_inode);
9016+ }
9017+ return err;
9018+}
9019+
4a4d8108
AM
9020+void au_dy_arefresh(int do_dx)
9021+{
9022+ struct au_splhead *spl;
9023+ struct list_head *head;
9024+ struct au_dykey *key;
9025+
9026+ spl = dynop + AuDy_AOP;
9027+ head = &spl->head;
9028+ spin_lock(&spl->spin);
9029+ list_for_each_entry(key, head, dk_list)
9030+ dy_adx((void *)key, do_dx);
9031+ spin_unlock(&spl->spin);
9032+}
9033+
4a4d8108
AM
9034+/* ---------------------------------------------------------------------- */
9035+
9036+void __init au_dy_init(void)
9037+{
9038+ int i;
9039+
9040+ /* make sure that 'struct au_dykey *' can be any type */
9041+ BUILD_BUG_ON(offsetof(struct au_dyaop, da_key));
4a4d8108
AM
9042+
9043+ for (i = 0; i < AuDyLast; i++)
9044+ au_spl_init(dynop + i);
9045+}
9046+
9047+void au_dy_fin(void)
9048+{
9049+ int i;
9050+
9051+ for (i = 0; i < AuDyLast; i++)
9052+ WARN_ON(!list_empty(&dynop[i].head));
9053+}
7f207e10
AM
9054diff -urN /usr/share/empty/fs/aufs/dynop.h linux/fs/aufs/dynop.h
9055--- /usr/share/empty/fs/aufs/dynop.h 1970-01-01 01:00:00.000000000 +0100
0c3ec466 9056+++ linux/fs/aufs/dynop.h 2012-07-22 19:57:03.161004531 +0200
f6c5ef8b 9057@@ -0,0 +1,76 @@
4a4d8108 9058+/*
f6c5ef8b 9059+ * Copyright (C) 2010-2012 Junjiro R. Okajima
4a4d8108
AM
9060+ *
9061+ * This program, aufs is free software; you can redistribute it and/or modify
9062+ * it under the terms of the GNU General Public License as published by
9063+ * the Free Software Foundation; either version 2 of the License, or
9064+ * (at your option) any later version.
9065+ *
9066+ * This program is distributed in the hope that it will be useful,
9067+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
9068+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
9069+ * GNU General Public License for more details.
9070+ *
9071+ * You should have received a copy of the GNU General Public License
9072+ * along with this program; if not, write to the Free Software
9073+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
9074+ */
9075+
9076+/*
9077+ * dynamically customizable operations (for regular files only)
9078+ */
9079+
9080+#ifndef __AUFS_DYNOP_H__
9081+#define __AUFS_DYNOP_H__
9082+
9083+#ifdef __KERNEL__
9084+
4a4d8108
AM
9085+#include "inode.h"
9086+
2cbb1c4b 9087+enum {AuDy_AOP, AuDyLast};
4a4d8108
AM
9088+
9089+struct au_dynop {
9090+ int dy_type;
9091+ union {
9092+ const void *dy_hop;
9093+ const struct address_space_operations *dy_haop;
4a4d8108
AM
9094+ };
9095+};
9096+
9097+struct au_dykey {
9098+ union {
9099+ struct list_head dk_list;
9100+ struct rcu_head dk_rcu;
9101+ };
9102+ struct au_dynop dk_op;
9103+
9104+ /*
9105+ * during I am in the branch local array, kref is gotten. when the
9106+ * branch is removed, kref is put.
9107+ */
9108+ struct kref dk_kref;
9109+};
9110+
9111+/* stop unioning since their sizes are very different from each other */
9112+struct au_dyaop {
9113+ struct au_dykey da_key;
9114+ struct address_space_operations da_op; /* not const */
9115+ int (*da_get_xip_mem)(struct address_space *, pgoff_t, int,
9116+ void **, unsigned long *);
9117+};
9118+
4a4d8108
AM
9119+/* ---------------------------------------------------------------------- */
9120+
9121+/* dynop.c */
9122+struct au_branch;
9123+void au_dy_put(struct au_dykey *key);
9124+int au_dy_iaop(struct inode *inode, aufs_bindex_t bindex,
9125+ struct inode *h_inode);
b752ccd1 9126+int au_dy_irefresh(struct inode *inode);
4a4d8108 9127+void au_dy_arefresh(int do_dio);
4a4d8108
AM
9128+
9129+void __init au_dy_init(void);
9130+void au_dy_fin(void);
9131+
4a4d8108
AM
9132+#endif /* __KERNEL__ */
9133+#endif /* __AUFS_DYNOP_H__ */
7f207e10
AM
9134diff -urN /usr/share/empty/fs/aufs/export.c linux/fs/aufs/export.c
9135--- /usr/share/empty/fs/aufs/export.c 1970-01-01 01:00:00.000000000 +0100
0c3ec466
AM
9136+++ linux/fs/aufs/export.c 2012-07-22 19:57:03.164337936 +0200
9137@@ -0,0 +1,810 @@
4a4d8108 9138+/*
f6c5ef8b 9139+ * Copyright (C) 2005-2012 Junjiro R. Okajima
4a4d8108
AM
9140+ *
9141+ * This program, aufs is free software; you can redistribute it and/or modify
9142+ * it under the terms of the GNU General Public License as published by
9143+ * the Free Software Foundation; either version 2 of the License, or
9144+ * (at your option) any later version.
9145+ *
9146+ * This program is distributed in the hope that it will be useful,
9147+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
9148+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
9149+ * GNU General Public License for more details.
9150+ *
9151+ * You should have received a copy of the GNU General Public License
9152+ * along with this program; if not, write to the Free Software
9153+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
9154+ */
9155+
9156+/*
9157+ * export via nfs
9158+ */
9159+
9160+#include <linux/exportfs.h>
7eafdf33 9161+#include <linux/fs_struct.h>
4a4d8108
AM
9162+#include <linux/namei.h>
9163+#include <linux/nsproxy.h>
9164+#include <linux/random.h>
9165+#include <linux/writeback.h>
7eafdf33 9166+#include "../fs/mount.h"
4a4d8108
AM
9167+#include "aufs.h"
9168+
9169+union conv {
9170+#ifdef CONFIG_AUFS_INO_T_64
9171+ __u32 a[2];
9172+#else
9173+ __u32 a[1];
9174+#endif
9175+ ino_t ino;
9176+};
9177+
9178+static ino_t decode_ino(__u32 *a)
9179+{
9180+ union conv u;
9181+
9182+ BUILD_BUG_ON(sizeof(u.ino) != sizeof(u.a));
9183+ u.a[0] = a[0];
9184+#ifdef CONFIG_AUFS_INO_T_64
9185+ u.a[1] = a[1];
9186+#endif
9187+ return u.ino;
9188+}
9189+
9190+static void encode_ino(__u32 *a, ino_t ino)
9191+{
9192+ union conv u;
9193+
9194+ u.ino = ino;
9195+ a[0] = u.a[0];
9196+#ifdef CONFIG_AUFS_INO_T_64
9197+ a[1] = u.a[1];
9198+#endif
9199+}
9200+
9201+/* NFS file handle */
9202+enum {
9203+ Fh_br_id,
9204+ Fh_sigen,
9205+#ifdef CONFIG_AUFS_INO_T_64
9206+ /* support 64bit inode number */
9207+ Fh_ino1,
9208+ Fh_ino2,
9209+ Fh_dir_ino1,
9210+ Fh_dir_ino2,
9211+#else
9212+ Fh_ino1,
9213+ Fh_dir_ino1,
9214+#endif
9215+ Fh_igen,
9216+ Fh_h_type,
9217+ Fh_tail,
9218+
9219+ Fh_ino = Fh_ino1,
9220+ Fh_dir_ino = Fh_dir_ino1
9221+};
9222+
9223+static int au_test_anon(struct dentry *dentry)
9224+{
027c5e7a 9225+ /* note: read d_flags without d_lock */
4a4d8108
AM
9226+ return !!(dentry->d_flags & DCACHE_DISCONNECTED);
9227+}
9228+
9229+/* ---------------------------------------------------------------------- */
9230+/* inode generation external table */
9231+
b752ccd1 9232+void au_xigen_inc(struct inode *inode)
4a4d8108 9233+{
4a4d8108
AM
9234+ loff_t pos;
9235+ ssize_t sz;
9236+ __u32 igen;
9237+ struct super_block *sb;
9238+ struct au_sbinfo *sbinfo;
9239+
4a4d8108 9240+ sb = inode->i_sb;
b752ccd1 9241+ AuDebugOn(!au_opt_test(au_mntflags(sb), XINO));
1facf9fc 9242+
b752ccd1 9243+ sbinfo = au_sbi(sb);
1facf9fc 9244+ pos = inode->i_ino;
9245+ pos *= sizeof(igen);
9246+ igen = inode->i_generation + 1;
1facf9fc 9247+ sz = xino_fwrite(sbinfo->si_xwrite, sbinfo->si_xigen, &igen,
9248+ sizeof(igen), &pos);
9249+ if (sz == sizeof(igen))
b752ccd1 9250+ return; /* success */
1facf9fc 9251+
b752ccd1 9252+ if (unlikely(sz >= 0))
1facf9fc 9253+ AuIOErr("xigen error (%zd)\n", sz);
1facf9fc 9254+}
9255+
9256+int au_xigen_new(struct inode *inode)
9257+{
9258+ int err;
9259+ loff_t pos;
9260+ ssize_t sz;
9261+ struct super_block *sb;
9262+ struct au_sbinfo *sbinfo;
9263+ struct file *file;
9264+
9265+ err = 0;
9266+ /* todo: dirty, at mount time */
9267+ if (inode->i_ino == AUFS_ROOT_INO)
9268+ goto out;
9269+ sb = inode->i_sb;
dece6358 9270+ SiMustAnyLock(sb);
1facf9fc 9271+ if (unlikely(!au_opt_test(au_mntflags(sb), XINO)))
9272+ goto out;
9273+
9274+ err = -EFBIG;
9275+ pos = inode->i_ino;
9276+ if (unlikely(au_loff_max / sizeof(inode->i_generation) - 1 < pos)) {
9277+ AuIOErr1("too large i%lld\n", pos);
9278+ goto out;
9279+ }
9280+ pos *= sizeof(inode->i_generation);
9281+
9282+ err = 0;
9283+ sbinfo = au_sbi(sb);
9284+ file = sbinfo->si_xigen;
9285+ BUG_ON(!file);
9286+
9287+ if (i_size_read(file->f_dentry->d_inode)
9288+ < pos + sizeof(inode->i_generation)) {
9289+ inode->i_generation = atomic_inc_return(&sbinfo->si_xigen_next);
9290+ sz = xino_fwrite(sbinfo->si_xwrite, file, &inode->i_generation,
9291+ sizeof(inode->i_generation), &pos);
9292+ } else
9293+ sz = xino_fread(sbinfo->si_xread, file, &inode->i_generation,
9294+ sizeof(inode->i_generation), &pos);
9295+ if (sz == sizeof(inode->i_generation))
9296+ goto out; /* success */
9297+
9298+ err = sz;
9299+ if (unlikely(sz >= 0)) {
9300+ err = -EIO;
9301+ AuIOErr("xigen error (%zd)\n", sz);
9302+ }
9303+
4f0767ce 9304+out:
1facf9fc 9305+ return err;
9306+}
9307+
9308+int au_xigen_set(struct super_block *sb, struct file *base)
9309+{
9310+ int err;
9311+ struct au_sbinfo *sbinfo;
9312+ struct file *file;
9313+
dece6358
AM
9314+ SiMustWriteLock(sb);
9315+
1facf9fc 9316+ sbinfo = au_sbi(sb);
9317+ file = au_xino_create2(base, sbinfo->si_xigen);
9318+ err = PTR_ERR(file);
9319+ if (IS_ERR(file))
9320+ goto out;
9321+ err = 0;
9322+ if (sbinfo->si_xigen)
9323+ fput(sbinfo->si_xigen);
9324+ sbinfo->si_xigen = file;
9325+
4f0767ce 9326+out:
1facf9fc 9327+ return err;
9328+}
9329+
9330+void au_xigen_clr(struct super_block *sb)
9331+{
9332+ struct au_sbinfo *sbinfo;
9333+
dece6358
AM
9334+ SiMustWriteLock(sb);
9335+
1facf9fc 9336+ sbinfo = au_sbi(sb);
9337+ if (sbinfo->si_xigen) {
9338+ fput(sbinfo->si_xigen);
9339+ sbinfo->si_xigen = NULL;
9340+ }
9341+}
9342+
9343+/* ---------------------------------------------------------------------- */
9344+
9345+static struct dentry *decode_by_ino(struct super_block *sb, ino_t ino,
9346+ ino_t dir_ino)
9347+{
9348+ struct dentry *dentry, *d;
9349+ struct inode *inode;
9350+ unsigned int sigen;
9351+
9352+ dentry = NULL;
9353+ inode = ilookup(sb, ino);
9354+ if (!inode)
9355+ goto out;
9356+
9357+ dentry = ERR_PTR(-ESTALE);
9358+ sigen = au_sigen(sb);
9359+ if (unlikely(is_bad_inode(inode)
9360+ || IS_DEADDIR(inode)
9361+ || sigen != au_iigen(inode)))
9362+ goto out_iput;
9363+
9364+ dentry = NULL;
9365+ if (!dir_ino || S_ISDIR(inode->i_mode))
9366+ dentry = d_find_alias(inode);
9367+ else {
027c5e7a
AM
9368+ spin_lock(&inode->i_lock);
9369+ list_for_each_entry(d, &inode->i_dentry, d_alias) {
9370+ spin_lock(&d->d_lock);
1facf9fc 9371+ if (!au_test_anon(d)
9372+ && d->d_parent->d_inode->i_ino == dir_ino) {
027c5e7a
AM
9373+ dentry = dget_dlock(d);
9374+ spin_unlock(&d->d_lock);
1facf9fc 9375+ break;
9376+ }
027c5e7a
AM
9377+ spin_unlock(&d->d_lock);
9378+ }
9379+ spin_unlock(&inode->i_lock);
1facf9fc 9380+ }
027c5e7a 9381+ if (unlikely(dentry && au_digen_test(dentry, sigen))) {
2cbb1c4b 9382+ /* need to refresh */
1facf9fc 9383+ dput(dentry);
2cbb1c4b 9384+ dentry = NULL;
1facf9fc 9385+ }
9386+
4f0767ce 9387+out_iput:
1facf9fc 9388+ iput(inode);
4f0767ce 9389+out:
2cbb1c4b 9390+ AuTraceErrPtr(dentry);
1facf9fc 9391+ return dentry;
9392+}
9393+
9394+/* ---------------------------------------------------------------------- */
9395+
9396+/* todo: dirty? */
9397+/* if exportfs_decode_fh() passed vfsmount*, we could be happy */
4a4d8108
AM
9398+
9399+struct au_compare_mnt_args {
9400+ /* input */
9401+ struct super_block *sb;
9402+
9403+ /* output */
9404+ struct vfsmount *mnt;
9405+};
9406+
9407+static int au_compare_mnt(struct vfsmount *mnt, void *arg)
9408+{
9409+ struct au_compare_mnt_args *a = arg;
9410+
9411+ if (mnt->mnt_sb != a->sb)
9412+ return 0;
9413+ a->mnt = mntget(mnt);
9414+ return 1;
9415+}
9416+
1facf9fc 9417+static struct vfsmount *au_mnt_get(struct super_block *sb)
9418+{
4a4d8108 9419+ int err;
7eafdf33 9420+ struct path root;
4a4d8108
AM
9421+ struct au_compare_mnt_args args = {
9422+ .sb = sb
9423+ };
1facf9fc 9424+
7eafdf33 9425+ get_fs_root(current->fs, &root);
0c3ec466 9426+ br_read_lock(&vfsmount_lock);
7eafdf33 9427+ err = iterate_mounts(au_compare_mnt, &args, root.mnt);
0c3ec466 9428+ br_read_unlock(&vfsmount_lock);
7eafdf33 9429+ path_put(&root);
4a4d8108
AM
9430+ AuDebugOn(!err);
9431+ AuDebugOn(!args.mnt);
9432+ return args.mnt;
1facf9fc 9433+}
9434+
9435+struct au_nfsd_si_lock {
4a4d8108 9436+ unsigned int sigen;
027c5e7a 9437+ aufs_bindex_t bindex, br_id;
1facf9fc 9438+ unsigned char force_lock;
9439+};
9440+
027c5e7a
AM
9441+static int si_nfsd_read_lock(struct super_block *sb,
9442+ struct au_nfsd_si_lock *nsi_lock)
1facf9fc 9443+{
027c5e7a 9444+ int err;
1facf9fc 9445+ aufs_bindex_t bindex;
9446+
9447+ si_read_lock(sb, AuLock_FLUSH);
9448+
9449+ /* branch id may be wrapped around */
027c5e7a 9450+ err = 0;
1facf9fc 9451+ bindex = au_br_index(sb, nsi_lock->br_id);
9452+ if (bindex >= 0 && nsi_lock->sigen + AUFS_BRANCH_MAX > au_sigen(sb))
9453+ goto out; /* success */
9454+
027c5e7a
AM
9455+ err = -ESTALE;
9456+ bindex = -1;
1facf9fc 9457+ if (!nsi_lock->force_lock)
9458+ si_read_unlock(sb);
1facf9fc 9459+
4f0767ce 9460+out:
027c5e7a
AM
9461+ nsi_lock->bindex = bindex;
9462+ return err;
1facf9fc 9463+}
9464+
9465+struct find_name_by_ino {
9466+ int called, found;
9467+ ino_t ino;
9468+ char *name;
9469+ int namelen;
9470+};
9471+
9472+static int
9473+find_name_by_ino(void *arg, const char *name, int namelen, loff_t offset,
9474+ u64 ino, unsigned int d_type)
9475+{
9476+ struct find_name_by_ino *a = arg;
9477+
9478+ a->called++;
9479+ if (a->ino != ino)
9480+ return 0;
9481+
9482+ memcpy(a->name, name, namelen);
9483+ a->namelen = namelen;
9484+ a->found = 1;
9485+ return 1;
9486+}
9487+
9488+static struct dentry *au_lkup_by_ino(struct path *path, ino_t ino,
9489+ struct au_nfsd_si_lock *nsi_lock)
9490+{
9491+ struct dentry *dentry, *parent;
9492+ struct file *file;
9493+ struct inode *dir;
9494+ struct find_name_by_ino arg;
9495+ int err;
9496+
9497+ parent = path->dentry;
9498+ if (nsi_lock)
9499+ si_read_unlock(parent->d_sb);
4a4d8108 9500+ file = vfsub_dentry_open(path, au_dir_roflags);
1facf9fc 9501+ dentry = (void *)file;
9502+ if (IS_ERR(file))
9503+ goto out;
9504+
9505+ dentry = ERR_PTR(-ENOMEM);
4a4d8108 9506+ arg.name = __getname_gfp(GFP_NOFS);
1facf9fc 9507+ if (unlikely(!arg.name))
9508+ goto out_file;
9509+ arg.ino = ino;
9510+ arg.found = 0;
9511+ do {
9512+ arg.called = 0;
9513+ /* smp_mb(); */
9514+ err = vfsub_readdir(file, find_name_by_ino, &arg);
9515+ } while (!err && !arg.found && arg.called);
9516+ dentry = ERR_PTR(err);
9517+ if (unlikely(err))
9518+ goto out_name;
9519+ dentry = ERR_PTR(-ENOENT);
9520+ if (!arg.found)
9521+ goto out_name;
9522+
9523+ /* do not call au_lkup_one() */
9524+ dir = parent->d_inode;
9525+ mutex_lock(&dir->i_mutex);
9526+ dentry = vfsub_lookup_one_len(arg.name, parent, arg.namelen);
9527+ mutex_unlock(&dir->i_mutex);
9528+ AuTraceErrPtr(dentry);
9529+ if (IS_ERR(dentry))
9530+ goto out_name;
9531+ AuDebugOn(au_test_anon(dentry));
9532+ if (unlikely(!dentry->d_inode)) {
9533+ dput(dentry);
9534+ dentry = ERR_PTR(-ENOENT);
9535+ }
9536+
4f0767ce 9537+out_name:
1facf9fc 9538+ __putname(arg.name);
4f0767ce 9539+out_file:
1facf9fc 9540+ fput(file);
4f0767ce 9541+out:
1facf9fc 9542+ if (unlikely(nsi_lock
9543+ && si_nfsd_read_lock(parent->d_sb, nsi_lock) < 0))
9544+ if (!IS_ERR(dentry)) {
9545+ dput(dentry);
9546+ dentry = ERR_PTR(-ESTALE);
9547+ }
9548+ AuTraceErrPtr(dentry);
9549+ return dentry;
9550+}
9551+
9552+static struct dentry *decode_by_dir_ino(struct super_block *sb, ino_t ino,
9553+ ino_t dir_ino,
9554+ struct au_nfsd_si_lock *nsi_lock)
9555+{
9556+ struct dentry *dentry;
9557+ struct path path;
9558+
9559+ if (dir_ino != AUFS_ROOT_INO) {
9560+ path.dentry = decode_by_ino(sb, dir_ino, 0);
9561+ dentry = path.dentry;
9562+ if (!path.dentry || IS_ERR(path.dentry))
9563+ goto out;
9564+ AuDebugOn(au_test_anon(path.dentry));
9565+ } else
9566+ path.dentry = dget(sb->s_root);
9567+
9568+ path.mnt = au_mnt_get(sb);
9569+ dentry = au_lkup_by_ino(&path, ino, nsi_lock);
9570+ path_put(&path);
9571+
4f0767ce 9572+out:
1facf9fc 9573+ AuTraceErrPtr(dentry);
9574+ return dentry;
9575+}
9576+
9577+/* ---------------------------------------------------------------------- */
9578+
9579+static int h_acceptable(void *expv, struct dentry *dentry)
9580+{
9581+ return 1;
9582+}
9583+
9584+static char *au_build_path(struct dentry *h_parent, struct path *h_rootpath,
9585+ char *buf, int len, struct super_block *sb)
9586+{
9587+ char *p;
9588+ int n;
9589+ struct path path;
9590+
9591+ p = d_path(h_rootpath, buf, len);
9592+ if (IS_ERR(p))
9593+ goto out;
9594+ n = strlen(p);
9595+
9596+ path.mnt = h_rootpath->mnt;
9597+ path.dentry = h_parent;
9598+ p = d_path(&path, buf, len);
9599+ if (IS_ERR(p))
9600+ goto out;
9601+ if (n != 1)
9602+ p += n;
9603+
9604+ path.mnt = au_mnt_get(sb);
9605+ path.dentry = sb->s_root;
9606+ p = d_path(&path, buf, len - strlen(p));
9607+ mntput(path.mnt);
9608+ if (IS_ERR(p))
9609+ goto out;
9610+ if (n != 1)
9611+ p[strlen(p)] = '/';
9612+
4f0767ce 9613+out:
1facf9fc 9614+ AuTraceErrPtr(p);
9615+ return p;
9616+}
9617+
9618+static
027c5e7a
AM
9619+struct dentry *decode_by_path(struct super_block *sb, ino_t ino, __u32 *fh,
9620+ int fh_len, struct au_nfsd_si_lock *nsi_lock)
1facf9fc 9621+{
9622+ struct dentry *dentry, *h_parent, *root;
9623+ struct super_block *h_sb;
9624+ char *pathname, *p;
9625+ struct vfsmount *h_mnt;
9626+ struct au_branch *br;
9627+ int err;
9628+ struct path path;
9629+
027c5e7a 9630+ br = au_sbr(sb, nsi_lock->bindex);
1facf9fc 9631+ h_mnt = br->br_mnt;
9632+ h_sb = h_mnt->mnt_sb;
9633+ /* todo: call lower fh_to_dentry()? fh_to_parent()? */
9634+ h_parent = exportfs_decode_fh(h_mnt, (void *)(fh + Fh_tail),
9635+ fh_len - Fh_tail, fh[Fh_h_type],
9636+ h_acceptable, /*context*/NULL);
9637+ dentry = h_parent;
9638+ if (unlikely(!h_parent || IS_ERR(h_parent))) {
9639+ AuWarn1("%s decode_fh failed, %ld\n",
9640+ au_sbtype(h_sb), PTR_ERR(h_parent));
9641+ goto out;
9642+ }
9643+ dentry = NULL;
9644+ if (unlikely(au_test_anon(h_parent))) {
9645+ AuWarn1("%s decode_fh returned a disconnected dentry\n",
9646+ au_sbtype(h_sb));
9647+ goto out_h_parent;
9648+ }
9649+
9650+ dentry = ERR_PTR(-ENOMEM);
9651+ pathname = (void *)__get_free_page(GFP_NOFS);
9652+ if (unlikely(!pathname))
9653+ goto out_h_parent;
9654+
9655+ root = sb->s_root;
9656+ path.mnt = h_mnt;
9657+ di_read_lock_parent(root, !AuLock_IR);
027c5e7a 9658+ path.dentry = au_h_dptr(root, nsi_lock->bindex);
1facf9fc 9659+ di_read_unlock(root, !AuLock_IR);
9660+ p = au_build_path(h_parent, &path, pathname, PAGE_SIZE, sb);
9661+ dentry = (void *)p;
9662+ if (IS_ERR(p))
9663+ goto out_pathname;
9664+
9665+ si_read_unlock(sb);
9666+ err = vfsub_kern_path(p, LOOKUP_FOLLOW | LOOKUP_DIRECTORY, &path);
9667+ dentry = ERR_PTR(err);
9668+ if (unlikely(err))
9669+ goto out_relock;
9670+
9671+ dentry = ERR_PTR(-ENOENT);
9672+ AuDebugOn(au_test_anon(path.dentry));
9673+ if (unlikely(!path.dentry->d_inode))
9674+ goto out_path;
9675+
9676+ if (ino != path.dentry->d_inode->i_ino)
9677+ dentry = au_lkup_by_ino(&path, ino, /*nsi_lock*/NULL);
9678+ else
9679+ dentry = dget(path.dentry);
9680+
4f0767ce 9681+out_path:
1facf9fc 9682+ path_put(&path);
4f0767ce 9683+out_relock:
1facf9fc 9684+ if (unlikely(si_nfsd_read_lock(sb, nsi_lock) < 0))
9685+ if (!IS_ERR(dentry)) {
9686+ dput(dentry);
9687+ dentry = ERR_PTR(-ESTALE);
9688+ }
4f0767ce 9689+out_pathname:
1facf9fc 9690+ free_page((unsigned long)pathname);
4f0767ce 9691+out_h_parent:
1facf9fc 9692+ dput(h_parent);
4f0767ce 9693+out:
1facf9fc 9694+ AuTraceErrPtr(dentry);
9695+ return dentry;
9696+}
9697+
9698+/* ---------------------------------------------------------------------- */
9699+
9700+static struct dentry *
9701+aufs_fh_to_dentry(struct super_block *sb, struct fid *fid, int fh_len,
9702+ int fh_type)
9703+{
9704+ struct dentry *dentry;
9705+ __u32 *fh = fid->raw;
027c5e7a 9706+ struct au_branch *br;
1facf9fc 9707+ ino_t ino, dir_ino;
1facf9fc 9708+ struct au_nfsd_si_lock nsi_lock = {
1facf9fc 9709+ .force_lock = 0
9710+ };
9711+
1facf9fc 9712+ dentry = ERR_PTR(-ESTALE);
4a4d8108
AM
9713+ /* it should never happen, but the file handle is unreliable */
9714+ if (unlikely(fh_len < Fh_tail))
9715+ goto out;
9716+ nsi_lock.sigen = fh[Fh_sigen];
9717+ nsi_lock.br_id = fh[Fh_br_id];
9718+
1facf9fc 9719+ /* branch id may be wrapped around */
027c5e7a
AM
9720+ br = NULL;
9721+ if (unlikely(si_nfsd_read_lock(sb, &nsi_lock)))
1facf9fc 9722+ goto out;
9723+ nsi_lock.force_lock = 1;
9724+
9725+ /* is this inode still cached? */
9726+ ino = decode_ino(fh + Fh_ino);
4a4d8108
AM
9727+ /* it should never happen */
9728+ if (unlikely(ino == AUFS_ROOT_INO))
9729+ goto out;
9730+
1facf9fc 9731+ dir_ino = decode_ino(fh + Fh_dir_ino);
9732+ dentry = decode_by_ino(sb, ino, dir_ino);
9733+ if (IS_ERR(dentry))
9734+ goto out_unlock;
9735+ if (dentry)
9736+ goto accept;
9737+
9738+ /* is the parent dir cached? */
027c5e7a
AM
9739+ br = au_sbr(sb, nsi_lock.bindex);
9740+ atomic_inc(&br->br_count);
1facf9fc 9741+ dentry = decode_by_dir_ino(sb, ino, dir_ino, &nsi_lock);
9742+ if (IS_ERR(dentry))
9743+ goto out_unlock;
9744+ if (dentry)
9745+ goto accept;
9746+
9747+ /* lookup path */
027c5e7a 9748+ dentry = decode_by_path(sb, ino, fh, fh_len, &nsi_lock);
1facf9fc 9749+ if (IS_ERR(dentry))
9750+ goto out_unlock;
9751+ if (unlikely(!dentry))
9752+ /* todo?: make it ESTALE */
9753+ goto out_unlock;
9754+
4f0767ce 9755+accept:
027c5e7a
AM
9756+ if (!au_digen_test(dentry, au_sigen(sb))
9757+ && dentry->d_inode->i_generation == fh[Fh_igen])
1facf9fc 9758+ goto out_unlock; /* success */
9759+
9760+ dput(dentry);
9761+ dentry = ERR_PTR(-ESTALE);
4f0767ce 9762+out_unlock:
027c5e7a
AM
9763+ if (br)
9764+ atomic_dec(&br->br_count);
1facf9fc 9765+ si_read_unlock(sb);
4f0767ce 9766+out:
1facf9fc 9767+ AuTraceErrPtr(dentry);
9768+ return dentry;
9769+}
9770+
9771+#if 0 /* reserved for future use */
9772+/* support subtreecheck option */
9773+static struct dentry *aufs_fh_to_parent(struct super_block *sb, struct fid *fid,
9774+ int fh_len, int fh_type)
9775+{
9776+ struct dentry *parent;
9777+ __u32 *fh = fid->raw;
9778+ ino_t dir_ino;
9779+
9780+ dir_ino = decode_ino(fh + Fh_dir_ino);
9781+ parent = decode_by_ino(sb, dir_ino, 0);
9782+ if (IS_ERR(parent))
9783+ goto out;
9784+ if (!parent)
9785+ parent = decode_by_path(sb, au_br_index(sb, fh[Fh_br_id]),
9786+ dir_ino, fh, fh_len);
9787+
4f0767ce 9788+out:
1facf9fc 9789+ AuTraceErrPtr(parent);
9790+ return parent;
9791+}
9792+#endif
9793+
9794+/* ---------------------------------------------------------------------- */
9795+
0c3ec466
AM
9796+static int aufs_encode_fh(struct inode *inode, __u32 *fh, int *max_len,
9797+ struct inode *dir)
1facf9fc 9798+{
9799+ int err;
0c3ec466 9800+ aufs_bindex_t bindex;
1facf9fc 9801+ struct super_block *sb, *h_sb;
0c3ec466
AM
9802+ struct dentry *dentry, *parent, *h_parent;
9803+ struct inode *h_dir;
1facf9fc 9804+ struct au_branch *br;
9805+
1facf9fc 9806+ err = -ENOSPC;
9807+ if (unlikely(*max_len <= Fh_tail)) {
9808+ AuWarn1("NFSv2 client (max_len %d)?\n", *max_len);
9809+ goto out;
9810+ }
9811+
9812+ err = FILEID_ROOT;
0c3ec466
AM
9813+ if (inode->i_ino == AUFS_ROOT_INO) {
9814+ AuDebugOn(inode->i_ino != AUFS_ROOT_INO);
1facf9fc 9815+ goto out;
9816+ }
9817+
1facf9fc 9818+ h_parent = NULL;
0c3ec466
AM
9819+ sb = inode->i_sb;
9820+ err = si_read_lock(sb, AuLock_FLUSH);
027c5e7a
AM
9821+ if (unlikely(err))
9822+ goto out;
9823+
1facf9fc 9824+#ifdef CONFIG_AUFS_DEBUG
9825+ if (unlikely(!au_opt_test(au_mntflags(sb), XINO)))
9826+ AuWarn1("NFS-exporting requires xino\n");
9827+#endif
027c5e7a 9828+ err = -EIO;
0c3ec466
AM
9829+ parent = NULL;
9830+ ii_read_lock_child(inode);
9831+ bindex = au_ibstart(inode);
9832+ if (!dir) {
9833+ dentry = d_find_alias(inode);
9834+ if (unlikely(!dentry))
9835+ goto out_unlock;
9836+ AuDebugOn(au_test_anon(dentry));
9837+ parent = dget_parent(dentry);
9838+ dput(dentry);
9839+ if (unlikely(!parent))
9840+ goto out_unlock;
9841+ dir = parent->d_inode;
1facf9fc 9842+ }
0c3ec466
AM
9843+
9844+ ii_read_lock_parent(dir);
9845+ h_dir = au_h_iptr(dir, bindex);
9846+ ii_read_unlock(dir);
9847+ if (unlikely(!h_dir))
9848+ goto out_parent;
9849+ h_parent = d_find_alias(h_dir);
1facf9fc 9850+ if (unlikely(!h_parent))
0c3ec466 9851+ goto out_hparent;
1facf9fc 9852+
9853+ err = -EPERM;
9854+ br = au_sbr(sb, bindex);
9855+ h_sb = br->br_mnt->mnt_sb;
9856+ if (unlikely(!h_sb->s_export_op)) {
9857+ AuErr1("%s branch is not exportable\n", au_sbtype(h_sb));
0c3ec466 9858+ goto out_hparent;
1facf9fc 9859+ }
9860+
9861+ fh[Fh_br_id] = br->br_id;
9862+ fh[Fh_sigen] = au_sigen(sb);
9863+ encode_ino(fh + Fh_ino, inode->i_ino);
0c3ec466 9864+ encode_ino(fh + Fh_dir_ino, dir->i_ino);
1facf9fc 9865+ fh[Fh_igen] = inode->i_generation;
9866+
9867+ *max_len -= Fh_tail;
9868+ fh[Fh_h_type] = exportfs_encode_fh(h_parent, (void *)(fh + Fh_tail),
9869+ max_len,
9870+ /*connectable or subtreecheck*/0);
9871+ err = fh[Fh_h_type];
9872+ *max_len += Fh_tail;
9873+ /* todo: macros? */
9874+ if (err != 255)
9875+ err = 99;
9876+ else
9877+ AuWarn1("%s encode_fh failed\n", au_sbtype(h_sb));
9878+
0c3ec466 9879+out_hparent:
1facf9fc 9880+ dput(h_parent);
0c3ec466 9881+out_parent:
1facf9fc 9882+ dput(parent);
0c3ec466
AM
9883+out_unlock:
9884+ ii_read_unlock(inode);
9885+ si_read_unlock(sb);
4f0767ce 9886+out:
1facf9fc 9887+ if (unlikely(err < 0))
9888+ err = 255;
9889+ return err;
9890+}
9891+
9892+/* ---------------------------------------------------------------------- */
9893+
4a4d8108
AM
9894+static int aufs_commit_metadata(struct inode *inode)
9895+{
9896+ int err;
9897+ aufs_bindex_t bindex;
9898+ struct super_block *sb;
9899+ struct inode *h_inode;
9900+ int (*f)(struct inode *inode);
9901+
9902+ sb = inode->i_sb;
e49829fe 9903+ si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLMW);
4a4d8108
AM
9904+ ii_write_lock_child(inode);
9905+ bindex = au_ibstart(inode);
9906+ AuDebugOn(bindex < 0);
9907+ h_inode = au_h_iptr(inode, bindex);
9908+
9909+ f = h_inode->i_sb->s_export_op->commit_metadata;
9910+ if (f)
9911+ err = f(h_inode);
9912+ else {
9913+ struct writeback_control wbc = {
9914+ .sync_mode = WB_SYNC_ALL,
9915+ .nr_to_write = 0 /* metadata only */
9916+ };
9917+
9918+ err = sync_inode(h_inode, &wbc);
9919+ }
9920+
9921+ au_cpup_attr_timesizes(inode);
9922+ ii_write_unlock(inode);
9923+ si_read_unlock(sb);
9924+ return err;
9925+}
9926+
9927+/* ---------------------------------------------------------------------- */
9928+
1facf9fc 9929+static struct export_operations aufs_export_op = {
4a4d8108 9930+ .fh_to_dentry = aufs_fh_to_dentry,
1facf9fc 9931+ /* .fh_to_parent = aufs_fh_to_parent, */
4a4d8108
AM
9932+ .encode_fh = aufs_encode_fh,
9933+ .commit_metadata = aufs_commit_metadata
1facf9fc 9934+};
9935+
9936+void au_export_init(struct super_block *sb)
9937+{
9938+ struct au_sbinfo *sbinfo;
9939+ __u32 u;
9940+
9941+ sb->s_export_op = &aufs_export_op;
9942+ sbinfo = au_sbi(sb);
9943+ sbinfo->si_xigen = NULL;
9944+ get_random_bytes(&u, sizeof(u));
9945+ BUILD_BUG_ON(sizeof(u) != sizeof(int));
9946+ atomic_set(&sbinfo->si_xigen_next, u);
9947+}
7f207e10
AM
9948diff -urN /usr/share/empty/fs/aufs/file.c linux/fs/aufs/file.c
9949--- /usr/share/empty/fs/aufs/file.c 1970-01-01 01:00:00.000000000 +0100
0c3ec466 9950+++ linux/fs/aufs/file.c 2012-07-22 19:57:03.164337936 +0200
7eafdf33 9951@@ -0,0 +1,676 @@
1facf9fc 9952+/*
f6c5ef8b 9953+ * Copyright (C) 2005-2012 Junjiro R. Okajima
1facf9fc 9954+ *
9955+ * This program, aufs is free software; you can redistribute it and/or modify
9956+ * it under the terms of the GNU General Public License as published by
9957+ * the Free Software Foundation; either version 2 of the License, or
9958+ * (at your option) any later version.
dece6358
AM
9959+ *
9960+ * This program is distributed in the hope that it will be useful,
9961+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
9962+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
9963+ * GNU General Public License for more details.
9964+ *
9965+ * You should have received a copy of the GNU General Public License
9966+ * along with this program; if not, write to the Free Software
9967+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 9968+ */
9969+
9970+/*
4a4d8108 9971+ * handling file/dir, and address_space operation
1facf9fc 9972+ */
9973+
7eafdf33
AM
9974+#ifdef CONFIG_AUFS_DEBUG
9975+#include <linux/migrate.h>
9976+#endif
4a4d8108 9977+#include <linux/pagemap.h>
1facf9fc 9978+#include "aufs.h"
9979+
4a4d8108
AM
9980+/* drop flags for writing */
9981+unsigned int au_file_roflags(unsigned int flags)
9982+{
9983+ flags &= ~(O_WRONLY | O_RDWR | O_APPEND | O_CREAT | O_TRUNC);
9984+ flags |= O_RDONLY | O_NOATIME;
9985+ return flags;
9986+}
9987+
9988+/* common functions to regular file and dir */
9989+struct file *au_h_open(struct dentry *dentry, aufs_bindex_t bindex, int flags,
9990+ struct file *file)
1facf9fc 9991+{
1308ab2a 9992+ struct file *h_file;
4a4d8108
AM
9993+ struct dentry *h_dentry;
9994+ struct inode *h_inode;
9995+ struct super_block *sb;
9996+ struct au_branch *br;
9997+ struct path h_path;
9998+ int err, exec_flag;
1facf9fc 9999+
4a4d8108
AM
10000+ /* a race condition can happen between open and unlink/rmdir */
10001+ h_file = ERR_PTR(-ENOENT);
10002+ h_dentry = au_h_dptr(dentry, bindex);
b752ccd1 10003+ if (au_test_nfsd() && !h_dentry)
4a4d8108
AM
10004+ goto out;
10005+ h_inode = h_dentry->d_inode;
b752ccd1 10006+ if (au_test_nfsd() && !h_inode)
4a4d8108 10007+ goto out;
027c5e7a
AM
10008+ spin_lock(&h_dentry->d_lock);
10009+ err = (!d_unhashed(dentry) && d_unlinked(h_dentry))
10010+ || !h_inode
10011+ /* || !dentry->d_inode->i_nlink */
10012+ ;
10013+ spin_unlock(&h_dentry->d_lock);
10014+ if (unlikely(err))
4a4d8108 10015+ goto out;
1facf9fc 10016+
4a4d8108
AM
10017+ sb = dentry->d_sb;
10018+ br = au_sbr(sb, bindex);
10019+ h_file = ERR_PTR(-EACCES);
2cbb1c4b 10020+ exec_flag = flags & __FMODE_EXEC;
4a4d8108 10021+ if (exec_flag && (br->br_mnt->mnt_flags & MNT_NOEXEC))
027c5e7a 10022+ goto out;
1facf9fc 10023+
4a4d8108
AM
10024+ /* drop flags for writing */
10025+ if (au_test_ro(sb, bindex, dentry->d_inode))
10026+ flags = au_file_roflags(flags);
10027+ flags &= ~O_CREAT;
10028+ atomic_inc(&br->br_count);
10029+ h_path.dentry = h_dentry;
10030+ h_path.mnt = br->br_mnt;
10031+ if (!au_special_file(h_inode->i_mode))
10032+ h_file = vfsub_dentry_open(&h_path, flags);
10033+ else {
10034+ /* this block depends upon the configuration */
10035+ di_read_unlock(dentry, AuLock_IR);
10036+ fi_write_unlock(file);
10037+ si_read_unlock(sb);
10038+ h_file = vfsub_dentry_open(&h_path, flags);
10039+ si_noflush_read_lock(sb);
10040+ fi_write_lock(file);
10041+ di_read_lock_child(dentry, AuLock_IR);
dece6358 10042+ }
4a4d8108
AM
10043+ if (IS_ERR(h_file))
10044+ goto out_br;
dece6358 10045+
4a4d8108
AM
10046+ if (exec_flag) {
10047+ err = deny_write_access(h_file);
10048+ if (unlikely(err)) {
10049+ fput(h_file);
10050+ h_file = ERR_PTR(err);
10051+ goto out_br;
10052+ }
10053+ }
953406b4 10054+ fsnotify_open(h_file);
4a4d8108 10055+ goto out; /* success */
1facf9fc 10056+
4f0767ce 10057+out_br:
4a4d8108 10058+ atomic_dec(&br->br_count);
4f0767ce 10059+out:
4a4d8108
AM
10060+ return h_file;
10061+}
1308ab2a 10062+
4a4d8108
AM
10063+int au_do_open(struct file *file, int (*open)(struct file *file, int flags),
10064+ struct au_fidir *fidir)
1facf9fc 10065+{
dece6358 10066+ int err;
1facf9fc 10067+ struct dentry *dentry;
1308ab2a 10068+
4a4d8108
AM
10069+ err = au_finfo_init(file, fidir);
10070+ if (unlikely(err))
10071+ goto out;
1facf9fc 10072+
10073+ dentry = file->f_dentry;
4a4d8108
AM
10074+ di_read_lock_child(dentry, AuLock_IR);
10075+ err = open(file, vfsub_file_flags(file));
10076+ di_read_unlock(dentry, AuLock_IR);
1facf9fc 10077+
4a4d8108
AM
10078+ fi_write_unlock(file);
10079+ if (unlikely(err)) {
10080+ au_fi(file)->fi_hdir = NULL;
10081+ au_finfo_fin(file);
1308ab2a 10082+ }
4a4d8108 10083+
4f0767ce 10084+out:
1308ab2a 10085+ return err;
10086+}
dece6358 10087+
4a4d8108 10088+int au_reopen_nondir(struct file *file)
1308ab2a 10089+{
4a4d8108
AM
10090+ int err;
10091+ aufs_bindex_t bstart;
10092+ struct dentry *dentry;
10093+ struct file *h_file, *h_file_tmp;
1308ab2a 10094+
4a4d8108
AM
10095+ dentry = file->f_dentry;
10096+ AuDebugOn(au_special_file(dentry->d_inode->i_mode));
10097+ bstart = au_dbstart(dentry);
10098+ h_file_tmp = NULL;
10099+ if (au_fbstart(file) == bstart) {
10100+ h_file = au_hf_top(file);
10101+ if (file->f_mode == h_file->f_mode)
10102+ return 0; /* success */
10103+ h_file_tmp = h_file;
10104+ get_file(h_file_tmp);
10105+ au_set_h_fptr(file, bstart, NULL);
10106+ }
10107+ AuDebugOn(au_fi(file)->fi_hdir);
10108+ AuDebugOn(au_fbstart(file) < bstart);
1308ab2a 10109+
4a4d8108
AM
10110+ h_file = au_h_open(dentry, bstart, vfsub_file_flags(file) & ~O_TRUNC,
10111+ file);
10112+ err = PTR_ERR(h_file);
10113+ if (IS_ERR(h_file))
10114+ goto out; /* todo: close all? */
10115+
10116+ err = 0;
10117+ au_set_fbstart(file, bstart);
10118+ au_set_h_fptr(file, bstart, h_file);
10119+ au_update_figen(file);
10120+ /* todo: necessary? */
10121+ /* file->f_ra = h_file->f_ra; */
10122+
4f0767ce 10123+out:
4a4d8108
AM
10124+ if (h_file_tmp)
10125+ fput(h_file_tmp);
10126+ return err;
1facf9fc 10127+}
10128+
1308ab2a 10129+/* ---------------------------------------------------------------------- */
10130+
4a4d8108
AM
10131+static int au_reopen_wh(struct file *file, aufs_bindex_t btgt,
10132+ struct dentry *hi_wh)
1facf9fc 10133+{
4a4d8108
AM
10134+ int err;
10135+ aufs_bindex_t bstart;
10136+ struct au_dinfo *dinfo;
10137+ struct dentry *h_dentry;
10138+ struct au_hdentry *hdp;
1facf9fc 10139+
4a4d8108
AM
10140+ dinfo = au_di(file->f_dentry);
10141+ AuRwMustWriteLock(&dinfo->di_rwsem);
dece6358 10142+
4a4d8108
AM
10143+ bstart = dinfo->di_bstart;
10144+ dinfo->di_bstart = btgt;
10145+ hdp = dinfo->di_hdentry;
10146+ h_dentry = hdp[0 + btgt].hd_dentry;
10147+ hdp[0 + btgt].hd_dentry = hi_wh;
10148+ err = au_reopen_nondir(file);
10149+ hdp[0 + btgt].hd_dentry = h_dentry;
10150+ dinfo->di_bstart = bstart;
1facf9fc 10151+
1facf9fc 10152+ return err;
10153+}
10154+
4a4d8108
AM
10155+static int au_ready_to_write_wh(struct file *file, loff_t len,
10156+ aufs_bindex_t bcpup)
1facf9fc 10157+{
4a4d8108 10158+ int err;
027c5e7a
AM
10159+ struct inode *inode, *h_inode;
10160+ struct dentry *dentry, *h_dentry, *hi_wh;
1facf9fc 10161+
dece6358 10162+ dentry = file->f_dentry;
4a4d8108 10163+ au_update_dbstart(dentry);
dece6358 10164+ inode = dentry->d_inode;
027c5e7a
AM
10165+ h_inode = NULL;
10166+ if (au_dbstart(dentry) <= bcpup && au_dbend(dentry) >= bcpup) {
10167+ h_dentry = au_h_dptr(dentry, bcpup);
10168+ if (h_dentry)
10169+ h_inode = h_dentry->d_inode;
10170+ }
4a4d8108 10171+ hi_wh = au_hi_wh(inode, bcpup);
027c5e7a 10172+ if (!hi_wh && !h_inode)
4a4d8108
AM
10173+ err = au_sio_cpup_wh(dentry, bcpup, len, file);
10174+ else
10175+ /* already copied-up after unlink */
10176+ err = au_reopen_wh(file, bcpup, hi_wh);
1facf9fc 10177+
4a4d8108
AM
10178+ if (!err
10179+ && inode->i_nlink > 1
10180+ && au_opt_test(au_mntflags(dentry->d_sb), PLINK))
10181+ au_plink_append(inode, bcpup, au_h_dptr(dentry, bcpup));
1308ab2a 10182+
dece6358 10183+ return err;
1facf9fc 10184+}
10185+
4a4d8108
AM
10186+/*
10187+ * prepare the @file for writing.
10188+ */
10189+int au_ready_to_write(struct file *file, loff_t len, struct au_pin *pin)
1facf9fc 10190+{
4a4d8108 10191+ int err;
027c5e7a 10192+ aufs_bindex_t bstart, bcpup, dbstart;
4a4d8108
AM
10193+ struct dentry *dentry, *parent, *h_dentry;
10194+ struct inode *h_inode, *inode;
1facf9fc 10195+ struct super_block *sb;
4a4d8108 10196+ struct file *h_file;
1facf9fc 10197+
10198+ dentry = file->f_dentry;
1facf9fc 10199+ sb = dentry->d_sb;
4a4d8108
AM
10200+ inode = dentry->d_inode;
10201+ AuDebugOn(au_special_file(inode->i_mode));
10202+ bstart = au_fbstart(file);
10203+ err = au_test_ro(sb, bstart, inode);
10204+ if (!err && (au_hf_top(file)->f_mode & FMODE_WRITE)) {
10205+ err = au_pin(pin, dentry, bstart, AuOpt_UDBA_NONE, /*flags*/0);
1facf9fc 10206+ goto out;
4a4d8108 10207+ }
1facf9fc 10208+
027c5e7a 10209+ /* need to cpup or reopen */
4a4d8108
AM
10210+ parent = dget_parent(dentry);
10211+ di_write_lock_parent(parent);
10212+ err = AuWbrCopyup(au_sbi(sb), dentry);
10213+ bcpup = err;
10214+ if (unlikely(err < 0))
10215+ goto out_dgrade;
10216+ err = 0;
10217+
027c5e7a 10218+ if (!d_unhashed(dentry) && !au_h_dptr(parent, bcpup)) {
4a4d8108 10219+ err = au_cpup_dirs(dentry, bcpup);
1facf9fc 10220+ if (unlikely(err))
4a4d8108
AM
10221+ goto out_dgrade;
10222+ }
10223+
10224+ err = au_pin(pin, dentry, bcpup, AuOpt_UDBA_NONE,
10225+ AuPin_DI_LOCKED | AuPin_MNT_WRITE);
10226+ if (unlikely(err))
10227+ goto out_dgrade;
10228+
10229+ h_dentry = au_hf_top(file)->f_dentry;
10230+ h_inode = h_dentry->d_inode;
027c5e7a
AM
10231+ dbstart = au_dbstart(dentry);
10232+ if (dbstart <= bcpup) {
10233+ h_dentry = au_h_dptr(dentry, bcpup);
10234+ AuDebugOn(!h_dentry);
10235+ h_inode = h_dentry->d_inode;
10236+ AuDebugOn(!h_inode);
10237+ bstart = bcpup;
10238+ }
10239+
10240+ if (dbstart <= bcpup /* just reopen */
10241+ || !d_unhashed(dentry) /* copyup and reopen */
10242+ ) {
10243+ mutex_lock_nested(&h_inode->i_mutex, AuLsc_I_CHILD);
10244+ h_file = au_h_open_pre(dentry, bstart);
10245+ if (IS_ERR(h_file)) {
10246+ err = PTR_ERR(h_file);
10247+ h_file = NULL;
10248+ } else {
10249+ di_downgrade_lock(parent, AuLock_IR);
10250+ if (dbstart > bcpup)
10251+ err = au_sio_cpup_simple(dentry, bcpup, len,
10252+ AuCpup_DTIME);
10253+ if (!err)
10254+ err = au_reopen_nondir(file);
10255+ }
10256+ mutex_unlock(&h_inode->i_mutex);
10257+ au_h_open_post(dentry, bstart, h_file);
10258+ } else { /* copyup as wh and reopen */
10259+ /*
10260+ * since writable hfsplus branch is not supported,
10261+ * h_open_pre/post() are unnecessary.
10262+ */
10263+ mutex_lock_nested(&h_inode->i_mutex, AuLsc_I_CHILD);
4a4d8108
AM
10264+ err = au_ready_to_write_wh(file, len, bcpup);
10265+ di_downgrade_lock(parent, AuLock_IR);
027c5e7a 10266+ mutex_unlock(&h_inode->i_mutex);
4a4d8108 10267+ }
4a4d8108
AM
10268+
10269+ if (!err) {
10270+ au_pin_set_parent_lflag(pin, /*lflag*/0);
10271+ goto out_dput; /* success */
10272+ }
10273+ au_unpin(pin);
10274+ goto out_unlock;
1facf9fc 10275+
4f0767ce 10276+out_dgrade:
4a4d8108 10277+ di_downgrade_lock(parent, AuLock_IR);
4f0767ce 10278+out_unlock:
4a4d8108 10279+ di_read_unlock(parent, AuLock_IR);
4f0767ce 10280+out_dput:
4a4d8108 10281+ dput(parent);
4f0767ce 10282+out:
1facf9fc 10283+ return err;
10284+}
10285+
4a4d8108
AM
10286+/* ---------------------------------------------------------------------- */
10287+
10288+int au_do_flush(struct file *file, fl_owner_t id,
10289+ int (*flush)(struct file *file, fl_owner_t id))
1facf9fc 10290+{
4a4d8108 10291+ int err;
1308ab2a 10292+ struct dentry *dentry;
1facf9fc 10293+ struct super_block *sb;
4a4d8108 10294+ struct inode *inode;
1facf9fc 10295+
1facf9fc 10296+ dentry = file->f_dentry;
10297+ sb = dentry->d_sb;
dece6358 10298+ inode = dentry->d_inode;
4a4d8108
AM
10299+ si_noflush_read_lock(sb);
10300+ fi_read_lock(file);
b752ccd1 10301+ ii_read_lock_child(inode);
1facf9fc 10302+
4a4d8108
AM
10303+ err = flush(file, id);
10304+ au_cpup_attr_timesizes(inode);
1facf9fc 10305+
b752ccd1 10306+ ii_read_unlock(inode);
4a4d8108 10307+ fi_read_unlock(file);
1308ab2a 10308+ si_read_unlock(sb);
dece6358 10309+ return err;
1facf9fc 10310+}
10311+
4a4d8108
AM
10312+/* ---------------------------------------------------------------------- */
10313+
10314+static int au_file_refresh_by_inode(struct file *file, int *need_reopen)
1facf9fc 10315+{
4a4d8108
AM
10316+ int err;
10317+ aufs_bindex_t bstart;
10318+ struct au_pin pin;
10319+ struct au_finfo *finfo;
10320+ struct dentry *dentry, *parent, *hi_wh;
10321+ struct inode *inode;
1facf9fc 10322+ struct super_block *sb;
10323+
4a4d8108
AM
10324+ FiMustWriteLock(file);
10325+
10326+ err = 0;
10327+ finfo = au_fi(file);
1308ab2a 10328+ dentry = file->f_dentry;
10329+ sb = dentry->d_sb;
4a4d8108
AM
10330+ inode = dentry->d_inode;
10331+ bstart = au_ibstart(inode);
027c5e7a 10332+ if (bstart == finfo->fi_btop || IS_ROOT(dentry))
1308ab2a 10333+ goto out;
dece6358 10334+
4a4d8108
AM
10335+ parent = dget_parent(dentry);
10336+ if (au_test_ro(sb, bstart, inode)) {
10337+ di_read_lock_parent(parent, !AuLock_IR);
10338+ err = AuWbrCopyup(au_sbi(sb), dentry);
10339+ bstart = err;
10340+ di_read_unlock(parent, !AuLock_IR);
10341+ if (unlikely(err < 0))
10342+ goto out_parent;
10343+ err = 0;
1facf9fc 10344+ }
1facf9fc 10345+
4a4d8108
AM
10346+ di_read_lock_parent(parent, AuLock_IR);
10347+ hi_wh = au_hi_wh(inode, bstart);
7f207e10
AM
10348+ if (!S_ISDIR(inode->i_mode)
10349+ && au_opt_test(au_mntflags(sb), PLINK)
4a4d8108
AM
10350+ && au_plink_test(inode)
10351+ && !d_unhashed(dentry)) {
10352+ err = au_test_and_cpup_dirs(dentry, bstart);
10353+ if (unlikely(err))
10354+ goto out_unlock;
10355+
10356+ /* always superio. */
10357+ err = au_pin(&pin, dentry, bstart, AuOpt_UDBA_NONE,
10358+ AuPin_DI_LOCKED | AuPin_MNT_WRITE);
10359+ if (!err)
10360+ err = au_sio_cpup_simple(dentry, bstart, -1,
10361+ AuCpup_DTIME);
10362+ au_unpin(&pin);
10363+ } else if (hi_wh) {
10364+ /* already copied-up after unlink */
10365+ err = au_reopen_wh(file, bstart, hi_wh);
10366+ *need_reopen = 0;
10367+ }
1facf9fc 10368+
4f0767ce 10369+out_unlock:
4a4d8108 10370+ di_read_unlock(parent, AuLock_IR);
4f0767ce 10371+out_parent:
4a4d8108 10372+ dput(parent);
4f0767ce 10373+out:
1308ab2a 10374+ return err;
dece6358 10375+}
1facf9fc 10376+
4a4d8108 10377+static void au_do_refresh_dir(struct file *file)
dece6358 10378+{
4a4d8108
AM
10379+ aufs_bindex_t bindex, bend, new_bindex, brid;
10380+ struct au_hfile *p, tmp, *q;
10381+ struct au_finfo *finfo;
1308ab2a 10382+ struct super_block *sb;
4a4d8108 10383+ struct au_fidir *fidir;
1facf9fc 10384+
4a4d8108 10385+ FiMustWriteLock(file);
1facf9fc 10386+
4a4d8108
AM
10387+ sb = file->f_dentry->d_sb;
10388+ finfo = au_fi(file);
10389+ fidir = finfo->fi_hdir;
10390+ AuDebugOn(!fidir);
10391+ p = fidir->fd_hfile + finfo->fi_btop;
10392+ brid = p->hf_br->br_id;
10393+ bend = fidir->fd_bbot;
10394+ for (bindex = finfo->fi_btop; bindex <= bend; bindex++, p++) {
10395+ if (!p->hf_file)
10396+ continue;
1308ab2a 10397+
4a4d8108
AM
10398+ new_bindex = au_br_index(sb, p->hf_br->br_id);
10399+ if (new_bindex == bindex)
10400+ continue;
10401+ if (new_bindex < 0) {
10402+ au_set_h_fptr(file, bindex, NULL);
10403+ continue;
10404+ }
1308ab2a 10405+
4a4d8108
AM
10406+ /* swap two lower inode, and loop again */
10407+ q = fidir->fd_hfile + new_bindex;
10408+ tmp = *q;
10409+ *q = *p;
10410+ *p = tmp;
10411+ if (tmp.hf_file) {
10412+ bindex--;
10413+ p--;
10414+ }
10415+ }
1308ab2a 10416+
4a4d8108 10417+ p = fidir->fd_hfile;
027c5e7a 10418+ if (!au_test_mmapped(file) && !d_unlinked(file->f_dentry)) {
4a4d8108
AM
10419+ bend = au_sbend(sb);
10420+ for (finfo->fi_btop = 0; finfo->fi_btop <= bend;
10421+ finfo->fi_btop++, p++)
10422+ if (p->hf_file) {
10423+ if (p->hf_file->f_dentry
10424+ && p->hf_file->f_dentry->d_inode)
10425+ break;
10426+ else
10427+ au_hfput(p, file);
10428+ }
10429+ } else {
10430+ bend = au_br_index(sb, brid);
10431+ for (finfo->fi_btop = 0; finfo->fi_btop < bend;
10432+ finfo->fi_btop++, p++)
10433+ if (p->hf_file)
10434+ au_hfput(p, file);
10435+ bend = au_sbend(sb);
10436+ }
1308ab2a 10437+
4a4d8108
AM
10438+ p = fidir->fd_hfile + bend;
10439+ for (fidir->fd_bbot = bend; fidir->fd_bbot >= finfo->fi_btop;
10440+ fidir->fd_bbot--, p--)
10441+ if (p->hf_file) {
10442+ if (p->hf_file->f_dentry
10443+ && p->hf_file->f_dentry->d_inode)
10444+ break;
10445+ else
10446+ au_hfput(p, file);
10447+ }
10448+ AuDebugOn(fidir->fd_bbot < finfo->fi_btop);
1308ab2a 10449+}
10450+
4a4d8108
AM
10451+/*
10452+ * after branch manipulating, refresh the file.
10453+ */
10454+static int refresh_file(struct file *file, int (*reopen)(struct file *file))
1facf9fc 10455+{
4a4d8108
AM
10456+ int err, need_reopen;
10457+ aufs_bindex_t bend, bindex;
10458+ struct dentry *dentry;
1308ab2a 10459+ struct au_finfo *finfo;
4a4d8108 10460+ struct au_hfile *hfile;
1facf9fc 10461+
4a4d8108 10462+ dentry = file->f_dentry;
1308ab2a 10463+ finfo = au_fi(file);
4a4d8108
AM
10464+ if (!finfo->fi_hdir) {
10465+ hfile = &finfo->fi_htop;
10466+ AuDebugOn(!hfile->hf_file);
10467+ bindex = au_br_index(dentry->d_sb, hfile->hf_br->br_id);
10468+ AuDebugOn(bindex < 0);
10469+ if (bindex != finfo->fi_btop)
10470+ au_set_fbstart(file, bindex);
10471+ } else {
10472+ err = au_fidir_realloc(finfo, au_sbend(dentry->d_sb) + 1);
10473+ if (unlikely(err))
10474+ goto out;
10475+ au_do_refresh_dir(file);
10476+ }
1facf9fc 10477+
4a4d8108
AM
10478+ err = 0;
10479+ need_reopen = 1;
10480+ if (!au_test_mmapped(file))
10481+ err = au_file_refresh_by_inode(file, &need_reopen);
027c5e7a 10482+ if (!err && need_reopen && !d_unlinked(dentry))
4a4d8108
AM
10483+ err = reopen(file);
10484+ if (!err) {
10485+ au_update_figen(file);
10486+ goto out; /* success */
10487+ }
10488+
10489+ /* error, close all lower files */
10490+ if (finfo->fi_hdir) {
10491+ bend = au_fbend_dir(file);
10492+ for (bindex = au_fbstart(file); bindex <= bend; bindex++)
10493+ au_set_h_fptr(file, bindex, NULL);
10494+ }
1facf9fc 10495+
4f0767ce 10496+out:
1facf9fc 10497+ return err;
10498+}
10499+
4a4d8108
AM
10500+/* common function to regular file and dir */
10501+int au_reval_and_lock_fdi(struct file *file, int (*reopen)(struct file *file),
10502+ int wlock)
dece6358 10503+{
1308ab2a 10504+ int err;
4a4d8108
AM
10505+ unsigned int sigen, figen;
10506+ aufs_bindex_t bstart;
10507+ unsigned char pseudo_link;
10508+ struct dentry *dentry;
10509+ struct inode *inode;
1facf9fc 10510+
4a4d8108
AM
10511+ err = 0;
10512+ dentry = file->f_dentry;
10513+ inode = dentry->d_inode;
10514+ AuDebugOn(au_special_file(inode->i_mode));
10515+ sigen = au_sigen(dentry->d_sb);
10516+ fi_write_lock(file);
10517+ figen = au_figen(file);
10518+ di_write_lock_child(dentry);
10519+ bstart = au_dbstart(dentry);
10520+ pseudo_link = (bstart != au_ibstart(inode));
10521+ if (sigen == figen && !pseudo_link && au_fbstart(file) == bstart) {
10522+ if (!wlock) {
10523+ di_downgrade_lock(dentry, AuLock_IR);
10524+ fi_downgrade_lock(file);
10525+ }
10526+ goto out; /* success */
10527+ }
dece6358 10528+
4a4d8108 10529+ AuDbg("sigen %d, figen %d\n", sigen, figen);
027c5e7a 10530+ if (au_digen_test(dentry, sigen)) {
4a4d8108 10531+ err = au_reval_dpath(dentry, sigen);
027c5e7a 10532+ AuDebugOn(!err && au_digen_test(dentry, sigen));
4a4d8108 10533+ }
dece6358 10534+
027c5e7a
AM
10535+ if (!err)
10536+ err = refresh_file(file, reopen);
4a4d8108
AM
10537+ if (!err) {
10538+ if (!wlock) {
10539+ di_downgrade_lock(dentry, AuLock_IR);
10540+ fi_downgrade_lock(file);
10541+ }
10542+ } else {
10543+ di_write_unlock(dentry);
10544+ fi_write_unlock(file);
10545+ }
1facf9fc 10546+
4f0767ce 10547+out:
1308ab2a 10548+ return err;
10549+}
1facf9fc 10550+
4a4d8108
AM
10551+/* ---------------------------------------------------------------------- */
10552+
10553+/* cf. aufs_nopage() */
10554+/* for madvise(2) */
10555+static int aufs_readpage(struct file *file __maybe_unused, struct page *page)
1308ab2a 10556+{
4a4d8108
AM
10557+ unlock_page(page);
10558+ return 0;
10559+}
1facf9fc 10560+
4a4d8108
AM
10561+/* it will never be called, but necessary to support O_DIRECT */
10562+static ssize_t aufs_direct_IO(int rw, struct kiocb *iocb,
10563+ const struct iovec *iov, loff_t offset,
10564+ unsigned long nr_segs)
10565+{ BUG(); return 0; }
1facf9fc 10566+
4a4d8108
AM
10567+/*
10568+ * it will never be called, but madvise and fadvise behaves differently
10569+ * when get_xip_mem is defined
10570+ */
10571+static int aufs_get_xip_mem(struct address_space *mapping, pgoff_t pgoff,
10572+ int create, void **kmem, unsigned long *pfn)
10573+{ BUG(); return 0; }
1facf9fc 10574+
4a4d8108
AM
10575+/* they will never be called. */
10576+#ifdef CONFIG_AUFS_DEBUG
10577+static int aufs_write_begin(struct file *file, struct address_space *mapping,
10578+ loff_t pos, unsigned len, unsigned flags,
10579+ struct page **pagep, void **fsdata)
10580+{ AuUnsupport(); return 0; }
10581+static int aufs_write_end(struct file *file, struct address_space *mapping,
10582+ loff_t pos, unsigned len, unsigned copied,
10583+ struct page *page, void *fsdata)
10584+{ AuUnsupport(); return 0; }
10585+static int aufs_writepage(struct page *page, struct writeback_control *wbc)
10586+{ AuUnsupport(); return 0; }
1308ab2a 10587+
4a4d8108
AM
10588+static int aufs_set_page_dirty(struct page *page)
10589+{ AuUnsupport(); return 0; }
10590+static void aufs_invalidatepage(struct page *page, unsigned long offset)
10591+{ AuUnsupport(); }
10592+static int aufs_releasepage(struct page *page, gfp_t gfp)
10593+{ AuUnsupport(); return 0; }
10594+static int aufs_migratepage(struct address_space *mapping, struct page *newpage,
7eafdf33 10595+ struct page *page, enum migrate_mode mode)
4a4d8108
AM
10596+{ AuUnsupport(); return 0; }
10597+static int aufs_launder_page(struct page *page)
10598+{ AuUnsupport(); return 0; }
10599+static int aufs_is_partially_uptodate(struct page *page,
10600+ read_descriptor_t *desc,
10601+ unsigned long from)
10602+{ AuUnsupport(); return 0; }
10603+static int aufs_error_remove_page(struct address_space *mapping,
10604+ struct page *page)
10605+{ AuUnsupport(); return 0; }
10606+#endif /* CONFIG_AUFS_DEBUG */
10607+
10608+const struct address_space_operations aufs_aop = {
10609+ .readpage = aufs_readpage,
10610+ .direct_IO = aufs_direct_IO,
10611+ .get_xip_mem = aufs_get_xip_mem,
10612+#ifdef CONFIG_AUFS_DEBUG
10613+ .writepage = aufs_writepage,
4a4d8108
AM
10614+ /* no writepages, because of writepage */
10615+ .set_page_dirty = aufs_set_page_dirty,
10616+ /* no readpages, because of readpage */
10617+ .write_begin = aufs_write_begin,
10618+ .write_end = aufs_write_end,
10619+ /* no bmap, no block device */
10620+ .invalidatepage = aufs_invalidatepage,
10621+ .releasepage = aufs_releasepage,
10622+ .migratepage = aufs_migratepage,
10623+ .launder_page = aufs_launder_page,
10624+ .is_partially_uptodate = aufs_is_partially_uptodate,
10625+ .error_remove_page = aufs_error_remove_page
10626+#endif /* CONFIG_AUFS_DEBUG */
dece6358 10627+};
7f207e10
AM
10628diff -urN /usr/share/empty/fs/aufs/file.h linux/fs/aufs/file.h
10629--- /usr/share/empty/fs/aufs/file.h 1970-01-01 01:00:00.000000000 +0100
0c3ec466
AM
10630+++ linux/fs/aufs/file.h 2012-07-22 19:57:03.164337936 +0200
10631@@ -0,0 +1,306 @@
4a4d8108 10632+/*
f6c5ef8b 10633+ * Copyright (C) 2005-2012 Junjiro R. Okajima
4a4d8108
AM
10634+ *
10635+ * This program, aufs is free software; you can redistribute it and/or modify
10636+ * it under the terms of the GNU General Public License as published by
10637+ * the Free Software Foundation; either version 2 of the License, or
10638+ * (at your option) any later version.
10639+ *
10640+ * This program is distributed in the hope that it will be useful,
10641+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
10642+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10643+ * GNU General Public License for more details.
10644+ *
10645+ * You should have received a copy of the GNU General Public License
10646+ * along with this program; if not, write to the Free Software
10647+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
10648+ */
1facf9fc 10649+
4a4d8108
AM
10650+/*
10651+ * file operations
10652+ */
1facf9fc 10653+
4a4d8108
AM
10654+#ifndef __AUFS_FILE_H__
10655+#define __AUFS_FILE_H__
1facf9fc 10656+
4a4d8108 10657+#ifdef __KERNEL__
1facf9fc 10658+
2cbb1c4b 10659+#include <linux/file.h>
4a4d8108
AM
10660+#include <linux/fs.h>
10661+#include <linux/poll.h>
4a4d8108 10662+#include "rwsem.h"
1facf9fc 10663+
4a4d8108
AM
10664+struct au_branch;
10665+struct au_hfile {
10666+ struct file *hf_file;
10667+ struct au_branch *hf_br;
10668+};
1facf9fc 10669+
4a4d8108
AM
10670+struct au_vdir;
10671+struct au_fidir {
10672+ aufs_bindex_t fd_bbot;
10673+ aufs_bindex_t fd_nent;
10674+ struct au_vdir *fd_vdir_cache;
10675+ struct au_hfile fd_hfile[];
10676+};
1facf9fc 10677+
4a4d8108 10678+static inline int au_fidir_sz(int nent)
dece6358 10679+{
4f0767ce
JR
10680+ AuDebugOn(nent < 0);
10681+ return sizeof(struct au_fidir) + sizeof(struct au_hfile) * nent;
4a4d8108 10682+}
1facf9fc 10683+
4a4d8108
AM
10684+struct au_finfo {
10685+ atomic_t fi_generation;
dece6358 10686+
4a4d8108
AM
10687+ struct au_rwsem fi_rwsem;
10688+ aufs_bindex_t fi_btop;
10689+
10690+ /* do not union them */
10691+ struct { /* for non-dir */
10692+ struct au_hfile fi_htop;
2cbb1c4b 10693+ atomic_t fi_mmapped;
4a4d8108
AM
10694+ };
10695+ struct au_fidir *fi_hdir; /* for dir only */
10696+} ____cacheline_aligned_in_smp;
1facf9fc 10697+
4a4d8108 10698+/* ---------------------------------------------------------------------- */
1facf9fc 10699+
4a4d8108
AM
10700+/* file.c */
10701+extern const struct address_space_operations aufs_aop;
10702+unsigned int au_file_roflags(unsigned int flags);
10703+struct file *au_h_open(struct dentry *dentry, aufs_bindex_t bindex, int flags,
10704+ struct file *file);
10705+int au_do_open(struct file *file, int (*open)(struct file *file, int flags),
10706+ struct au_fidir *fidir);
10707+int au_reopen_nondir(struct file *file);
10708+struct au_pin;
10709+int au_ready_to_write(struct file *file, loff_t len, struct au_pin *pin);
10710+int au_reval_and_lock_fdi(struct file *file, int (*reopen)(struct file *file),
10711+ int wlock);
10712+int au_do_flush(struct file *file, fl_owner_t id,
10713+ int (*flush)(struct file *file, fl_owner_t id));
1facf9fc 10714+
0c3ec466
AM
10715+#if defined(CONFIG_SECURITY) && defined(CONFIG_MMU)
10716+/* security.c */
10717+int au_security_mmap_file(struct file *h_file, struct vm_area_struct *vma);
10718+#else
10719+AuStubInt0(au_security_mmap_file, struct file *h_file,
10720+ struct vm_area_struct *vma);
10721+#endif
10722+
4a4d8108
AM
10723+/* poll.c */
10724+#ifdef CONFIG_AUFS_POLL
10725+unsigned int aufs_poll(struct file *file, poll_table *wait);
10726+#endif
1facf9fc 10727+
4a4d8108
AM
10728+#ifdef CONFIG_AUFS_BR_HFSPLUS
10729+/* hfsplus.c */
10730+struct file *au_h_open_pre(struct dentry *dentry, aufs_bindex_t bindex);
10731+void au_h_open_post(struct dentry *dentry, aufs_bindex_t bindex,
10732+ struct file *h_file);
10733+#else
10734+static inline
10735+struct file *au_h_open_pre(struct dentry *dentry, aufs_bindex_t bindex)
dece6358 10736+{
4a4d8108
AM
10737+ return NULL;
10738+}
1facf9fc 10739+
4a4d8108
AM
10740+AuStubVoid(au_h_open_post, struct dentry *dentry, aufs_bindex_t bindex,
10741+ struct file *h_file);
10742+#endif
1facf9fc 10743+
4a4d8108
AM
10744+/* f_op.c */
10745+extern const struct file_operations aufs_file_fop;
4a4d8108
AM
10746+int au_do_open_nondir(struct file *file, int flags);
10747+int aufs_release_nondir(struct inode *inode __maybe_unused, struct file *file);
10748+
10749+#ifdef CONFIG_AUFS_SP_IATTR
10750+/* f_op_sp.c */
10751+int au_special_file(umode_t mode);
10752+void au_init_special_fop(struct inode *inode, umode_t mode, dev_t rdev);
10753+#else
10754+AuStubInt0(au_special_file, umode_t mode)
10755+static inline void au_init_special_fop(struct inode *inode, umode_t mode,
10756+ dev_t rdev)
10757+{
10758+ init_special_inode(inode, mode, rdev);
10759+}
10760+#endif
1facf9fc 10761+
4a4d8108
AM
10762+/* finfo.c */
10763+void au_hfput(struct au_hfile *hf, struct file *file);
10764+void au_set_h_fptr(struct file *file, aufs_bindex_t bindex,
10765+ struct file *h_file);
1facf9fc 10766+
4a4d8108 10767+void au_update_figen(struct file *file);
4a4d8108
AM
10768+struct au_fidir *au_fidir_alloc(struct super_block *sb);
10769+int au_fidir_realloc(struct au_finfo *finfo, int nbr);
1facf9fc 10770+
4a4d8108
AM
10771+void au_fi_init_once(void *_fi);
10772+void au_finfo_fin(struct file *file);
10773+int au_finfo_init(struct file *file, struct au_fidir *fidir);
1facf9fc 10774+
4a4d8108
AM
10775+/* ioctl.c */
10776+long aufs_ioctl_nondir(struct file *file, unsigned int cmd, unsigned long arg);
b752ccd1
AM
10777+#ifdef CONFIG_COMPAT
10778+long aufs_compat_ioctl_dir(struct file *file, unsigned int cmd,
10779+ unsigned long arg);
10780+#endif
1facf9fc 10781+
4a4d8108 10782+/* ---------------------------------------------------------------------- */
1facf9fc 10783+
4a4d8108
AM
10784+static inline struct au_finfo *au_fi(struct file *file)
10785+{
10786+ return file->private_data;
10787+}
1facf9fc 10788+
4a4d8108 10789+/* ---------------------------------------------------------------------- */
1facf9fc 10790+
4a4d8108
AM
10791+/*
10792+ * fi_read_lock, fi_write_lock,
10793+ * fi_read_unlock, fi_write_unlock, fi_downgrade_lock
10794+ */
10795+AuSimpleRwsemFuncs(fi, struct file *f, &au_fi(f)->fi_rwsem);
1308ab2a 10796+
4a4d8108
AM
10797+#define FiMustNoWaiters(f) AuRwMustNoWaiters(&au_fi(f)->fi_rwsem)
10798+#define FiMustAnyLock(f) AuRwMustAnyLock(&au_fi(f)->fi_rwsem)
10799+#define FiMustWriteLock(f) AuRwMustWriteLock(&au_fi(f)->fi_rwsem)
1facf9fc 10800+
1308ab2a 10801+/* ---------------------------------------------------------------------- */
10802+
4a4d8108
AM
10803+/* todo: hard/soft set? */
10804+static inline aufs_bindex_t au_fbstart(struct file *file)
dece6358 10805+{
4a4d8108
AM
10806+ FiMustAnyLock(file);
10807+ return au_fi(file)->fi_btop;
10808+}
dece6358 10809+
4a4d8108
AM
10810+static inline aufs_bindex_t au_fbend_dir(struct file *file)
10811+{
10812+ FiMustAnyLock(file);
10813+ AuDebugOn(!au_fi(file)->fi_hdir);
10814+ return au_fi(file)->fi_hdir->fd_bbot;
10815+}
1facf9fc 10816+
4a4d8108
AM
10817+static inline struct au_vdir *au_fvdir_cache(struct file *file)
10818+{
10819+ FiMustAnyLock(file);
10820+ AuDebugOn(!au_fi(file)->fi_hdir);
10821+ return au_fi(file)->fi_hdir->fd_vdir_cache;
10822+}
1facf9fc 10823+
4a4d8108
AM
10824+static inline void au_set_fbstart(struct file *file, aufs_bindex_t bindex)
10825+{
10826+ FiMustWriteLock(file);
10827+ au_fi(file)->fi_btop = bindex;
10828+}
1facf9fc 10829+
4a4d8108
AM
10830+static inline void au_set_fbend_dir(struct file *file, aufs_bindex_t bindex)
10831+{
10832+ FiMustWriteLock(file);
10833+ AuDebugOn(!au_fi(file)->fi_hdir);
10834+ au_fi(file)->fi_hdir->fd_bbot = bindex;
10835+}
1308ab2a 10836+
4a4d8108
AM
10837+static inline void au_set_fvdir_cache(struct file *file,
10838+ struct au_vdir *vdir_cache)
10839+{
10840+ FiMustWriteLock(file);
10841+ AuDebugOn(!au_fi(file)->fi_hdir);
10842+ au_fi(file)->fi_hdir->fd_vdir_cache = vdir_cache;
10843+}
dece6358 10844+
4a4d8108
AM
10845+static inline struct file *au_hf_top(struct file *file)
10846+{
10847+ FiMustAnyLock(file);
10848+ AuDebugOn(au_fi(file)->fi_hdir);
10849+ return au_fi(file)->fi_htop.hf_file;
10850+}
1facf9fc 10851+
4a4d8108
AM
10852+static inline struct file *au_hf_dir(struct file *file, aufs_bindex_t bindex)
10853+{
10854+ FiMustAnyLock(file);
10855+ AuDebugOn(!au_fi(file)->fi_hdir);
10856+ return au_fi(file)->fi_hdir->fd_hfile[0 + bindex].hf_file;
dece6358
AM
10857+}
10858+
4a4d8108
AM
10859+/* todo: memory barrier? */
10860+static inline unsigned int au_figen(struct file *f)
dece6358 10861+{
4a4d8108
AM
10862+ return atomic_read(&au_fi(f)->fi_generation);
10863+}
dece6358 10864+
2cbb1c4b
JR
10865+static inline void au_set_mmapped(struct file *f)
10866+{
10867+ if (atomic_inc_return(&au_fi(f)->fi_mmapped))
10868+ return;
0c3ec466 10869+ pr_warn("fi_mmapped wrapped around\n");
2cbb1c4b
JR
10870+ while (!atomic_inc_return(&au_fi(f)->fi_mmapped))
10871+ ;
10872+}
10873+
10874+static inline void au_unset_mmapped(struct file *f)
10875+{
10876+ atomic_dec(&au_fi(f)->fi_mmapped);
10877+}
10878+
4a4d8108
AM
10879+static inline int au_test_mmapped(struct file *f)
10880+{
2cbb1c4b
JR
10881+ return atomic_read(&au_fi(f)->fi_mmapped);
10882+}
10883+
10884+/* customize vma->vm_file */
10885+
10886+static inline void au_do_vm_file_reset(struct vm_area_struct *vma,
10887+ struct file *file)
10888+{
53392da6
AM
10889+ struct file *f;
10890+
10891+ f = vma->vm_file;
2cbb1c4b
JR
10892+ get_file(file);
10893+ vma->vm_file = file;
53392da6 10894+ fput(f);
2cbb1c4b
JR
10895+}
10896+
10897+#ifdef CONFIG_MMU
10898+#define AuDbgVmRegion(file, vma) do {} while (0)
10899+
10900+static inline void au_vm_file_reset(struct vm_area_struct *vma,
10901+ struct file *file)
10902+{
10903+ au_do_vm_file_reset(vma, file);
10904+}
10905+#else
10906+#define AuDbgVmRegion(file, vma) \
10907+ AuDebugOn((vma)->vm_region && (vma)->vm_region->vm_file != (file))
10908+
10909+static inline void au_vm_file_reset(struct vm_area_struct *vma,
10910+ struct file *file)
10911+{
53392da6
AM
10912+ struct file *f;
10913+
2cbb1c4b 10914+ au_do_vm_file_reset(vma, file);
53392da6 10915+ f = vma->vm_region->vm_file;
2cbb1c4b
JR
10916+ get_file(file);
10917+ vma->vm_region->vm_file = file;
53392da6 10918+ fput(f);
2cbb1c4b
JR
10919+}
10920+#endif /* CONFIG_MMU */
10921+
10922+/* handle vma->vm_prfile */
10923+static inline void au_vm_prfile_set(struct vm_area_struct *vma,
10924+ struct file *file)
10925+{
10926+#ifdef CONFIG_AUFS_PROC_MAP
10927+ get_file(file);
10928+ vma->vm_prfile = file;
10929+#ifndef CONFIG_MMU
10930+ get_file(file);
10931+ vma->vm_region->vm_prfile = file;
10932+#endif
10933+#endif
4a4d8108 10934+}
1308ab2a 10935+
4a4d8108
AM
10936+#endif /* __KERNEL__ */
10937+#endif /* __AUFS_FILE_H__ */
7f207e10
AM
10938diff -urN /usr/share/empty/fs/aufs/finfo.c linux/fs/aufs/finfo.c
10939--- /usr/share/empty/fs/aufs/finfo.c 1970-01-01 01:00:00.000000000 +0100
0c3ec466 10940+++ linux/fs/aufs/finfo.c 2012-07-22 19:57:03.164337936 +0200
f6c5ef8b 10941@@ -0,0 +1,156 @@
4a4d8108 10942+/*
f6c5ef8b 10943+ * Copyright (C) 2005-2012 Junjiro R. Okajima
4a4d8108
AM
10944+ *
10945+ * This program, aufs is free software; you can redistribute it and/or modify
10946+ * it under the terms of the GNU General Public License as published by
10947+ * the Free Software Foundation; either version 2 of the License, or
10948+ * (at your option) any later version.
10949+ *
10950+ * This program is distributed in the hope that it will be useful,
10951+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
10952+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10953+ * GNU General Public License for more details.
10954+ *
10955+ * You should have received a copy of the GNU General Public License
10956+ * along with this program; if not, write to the Free Software
10957+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
10958+ */
1308ab2a 10959+
4a4d8108
AM
10960+/*
10961+ * file private data
10962+ */
1facf9fc 10963+
4a4d8108 10964+#include "aufs.h"
1facf9fc 10965+
4a4d8108
AM
10966+void au_hfput(struct au_hfile *hf, struct file *file)
10967+{
10968+ /* todo: direct access f_flags */
2cbb1c4b 10969+ if (vfsub_file_flags(file) & __FMODE_EXEC)
4a4d8108
AM
10970+ allow_write_access(hf->hf_file);
10971+ fput(hf->hf_file);
10972+ hf->hf_file = NULL;
e49829fe 10973+ atomic_dec(&hf->hf_br->br_count);
4a4d8108
AM
10974+ hf->hf_br = NULL;
10975+}
1facf9fc 10976+
4a4d8108
AM
10977+void au_set_h_fptr(struct file *file, aufs_bindex_t bindex, struct file *val)
10978+{
10979+ struct au_finfo *finfo = au_fi(file);
10980+ struct au_hfile *hf;
10981+ struct au_fidir *fidir;
10982+
10983+ fidir = finfo->fi_hdir;
10984+ if (!fidir) {
10985+ AuDebugOn(finfo->fi_btop != bindex);
10986+ hf = &finfo->fi_htop;
10987+ } else
10988+ hf = fidir->fd_hfile + bindex;
10989+
10990+ if (hf && hf->hf_file)
10991+ au_hfput(hf, file);
10992+ if (val) {
10993+ FiMustWriteLock(file);
10994+ hf->hf_file = val;
10995+ hf->hf_br = au_sbr(file->f_dentry->d_sb, bindex);
1308ab2a 10996+ }
4a4d8108 10997+}
1facf9fc 10998+
4a4d8108
AM
10999+void au_update_figen(struct file *file)
11000+{
11001+ atomic_set(&au_fi(file)->fi_generation, au_digen(file->f_dentry));
11002+ /* smp_mb(); */ /* atomic_set */
1facf9fc 11003+}
11004+
4a4d8108
AM
11005+/* ---------------------------------------------------------------------- */
11006+
4a4d8108
AM
11007+struct au_fidir *au_fidir_alloc(struct super_block *sb)
11008+{
11009+ struct au_fidir *fidir;
11010+ int nbr;
11011+
11012+ nbr = au_sbend(sb) + 1;
11013+ if (nbr < 2)
11014+ nbr = 2; /* initial allocate for 2 branches */
11015+ fidir = kzalloc(au_fidir_sz(nbr), GFP_NOFS);
11016+ if (fidir) {
11017+ fidir->fd_bbot = -1;
11018+ fidir->fd_nent = nbr;
11019+ fidir->fd_vdir_cache = NULL;
11020+ }
11021+
11022+ return fidir;
11023+}
11024+
11025+int au_fidir_realloc(struct au_finfo *finfo, int nbr)
11026+{
11027+ int err;
11028+ struct au_fidir *fidir, *p;
11029+
11030+ AuRwMustWriteLock(&finfo->fi_rwsem);
11031+ fidir = finfo->fi_hdir;
11032+ AuDebugOn(!fidir);
11033+
11034+ err = -ENOMEM;
11035+ p = au_kzrealloc(fidir, au_fidir_sz(fidir->fd_nent), au_fidir_sz(nbr),
11036+ GFP_NOFS);
11037+ if (p) {
11038+ p->fd_nent = nbr;
11039+ finfo->fi_hdir = p;
11040+ err = 0;
11041+ }
1facf9fc 11042+
dece6358 11043+ return err;
1facf9fc 11044+}
1308ab2a 11045+
11046+/* ---------------------------------------------------------------------- */
11047+
4a4d8108 11048+void au_finfo_fin(struct file *file)
1308ab2a 11049+{
4a4d8108
AM
11050+ struct au_finfo *finfo;
11051+
7f207e10
AM
11052+ au_nfiles_dec(file->f_dentry->d_sb);
11053+
4a4d8108
AM
11054+ finfo = au_fi(file);
11055+ AuDebugOn(finfo->fi_hdir);
11056+ AuRwDestroy(&finfo->fi_rwsem);
11057+ au_cache_free_finfo(finfo);
1308ab2a 11058+}
1308ab2a 11059+
e49829fe 11060+void au_fi_init_once(void *_finfo)
4a4d8108 11061+{
e49829fe 11062+ struct au_finfo *finfo = _finfo;
2cbb1c4b 11063+ static struct lock_class_key aufs_fi;
1308ab2a 11064+
e49829fe
JR
11065+ au_rw_init(&finfo->fi_rwsem);
11066+ au_rw_class(&finfo->fi_rwsem, &aufs_fi);
4a4d8108 11067+}
1308ab2a 11068+
4a4d8108
AM
11069+int au_finfo_init(struct file *file, struct au_fidir *fidir)
11070+{
9dbd164d 11071+ int err, lc_idx;
4a4d8108
AM
11072+ struct au_finfo *finfo;
11073+ struct dentry *dentry;
11074+
11075+ err = -ENOMEM;
11076+ dentry = file->f_dentry;
11077+ finfo = au_cache_alloc_finfo();
11078+ if (unlikely(!finfo))
11079+ goto out;
11080+
11081+ err = 0;
7f207e10 11082+ au_nfiles_inc(dentry->d_sb);
9dbd164d
AM
11083+ lc_idx = AuLcNonDir_FIINFO;
11084+ if (fidir)
11085+ lc_idx = AuLcDir_FIINFO;
11086+ au_rw_class(&finfo->fi_rwsem, au_lc_key + lc_idx);
4a4d8108
AM
11087+ au_rw_write_lock(&finfo->fi_rwsem);
11088+ finfo->fi_btop = -1;
11089+ finfo->fi_hdir = fidir;
11090+ atomic_set(&finfo->fi_generation, au_digen(dentry));
11091+ /* smp_mb(); */ /* atomic_set */
11092+
11093+ file->private_data = finfo;
11094+
11095+out:
11096+ return err;
11097+}
7f207e10
AM
11098diff -urN /usr/share/empty/fs/aufs/f_op.c linux/fs/aufs/f_op.c
11099--- /usr/share/empty/fs/aufs/f_op.c 1970-01-01 01:00:00.000000000 +0100
0c3ec466
AM
11100+++ linux/fs/aufs/f_op.c 2012-07-22 19:57:03.164337936 +0200
11101@@ -0,0 +1,692 @@
dece6358 11102+/*
f6c5ef8b 11103+ * Copyright (C) 2005-2012 Junjiro R. Okajima
dece6358
AM
11104+ *
11105+ * This program, aufs is free software; you can redistribute it and/or modify
11106+ * it under the terms of the GNU General Public License as published by
11107+ * the Free Software Foundation; either version 2 of the License, or
11108+ * (at your option) any later version.
11109+ *
11110+ * This program is distributed in the hope that it will be useful,
11111+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
11112+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11113+ * GNU General Public License for more details.
11114+ *
11115+ * You should have received a copy of the GNU General Public License
11116+ * along with this program; if not, write to the Free Software
11117+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
11118+ */
1facf9fc 11119+
11120+/*
4a4d8108 11121+ * file and vm operations
1facf9fc 11122+ */
dece6358 11123+
4a4d8108
AM
11124+#include <linux/fs_stack.h>
11125+#include <linux/mman.h>
4a4d8108 11126+#include <linux/security.h>
dece6358
AM
11127+#include "aufs.h"
11128+
4a4d8108 11129+int au_do_open_nondir(struct file *file, int flags)
1facf9fc 11130+{
4a4d8108
AM
11131+ int err;
11132+ aufs_bindex_t bindex;
11133+ struct file *h_file;
11134+ struct dentry *dentry;
11135+ struct au_finfo *finfo;
11136+
11137+ FiMustWriteLock(file);
11138+
4a4d8108 11139+ dentry = file->f_dentry;
027c5e7a
AM
11140+ err = au_d_alive(dentry);
11141+ if (unlikely(err))
11142+ goto out;
11143+
4a4d8108
AM
11144+ finfo = au_fi(file);
11145+ memset(&finfo->fi_htop, 0, sizeof(finfo->fi_htop));
2cbb1c4b 11146+ atomic_set(&finfo->fi_mmapped, 0);
4a4d8108
AM
11147+ bindex = au_dbstart(dentry);
11148+ h_file = au_h_open(dentry, bindex, flags, file);
11149+ if (IS_ERR(h_file))
11150+ err = PTR_ERR(h_file);
11151+ else {
11152+ au_set_fbstart(file, bindex);
11153+ au_set_h_fptr(file, bindex, h_file);
11154+ au_update_figen(file);
11155+ /* todo: necessary? */
11156+ /* file->f_ra = h_file->f_ra; */
11157+ }
027c5e7a
AM
11158+
11159+out:
4a4d8108 11160+ return err;
1facf9fc 11161+}
11162+
4a4d8108
AM
11163+static int aufs_open_nondir(struct inode *inode __maybe_unused,
11164+ struct file *file)
1facf9fc 11165+{
4a4d8108 11166+ int err;
1308ab2a 11167+ struct super_block *sb;
1facf9fc 11168+
2cbb1c4b 11169+ AuDbg("%.*s, f_flags 0x%x, f_mode 0x%x\n",
4a4d8108
AM
11170+ AuDLNPair(file->f_dentry), vfsub_file_flags(file),
11171+ file->f_mode);
1facf9fc 11172+
4a4d8108
AM
11173+ sb = file->f_dentry->d_sb;
11174+ si_read_lock(sb, AuLock_FLUSH);
11175+ err = au_do_open(file, au_do_open_nondir, /*fidir*/NULL);
11176+ si_read_unlock(sb);
11177+ return err;
11178+}
1facf9fc 11179+
4a4d8108
AM
11180+int aufs_release_nondir(struct inode *inode __maybe_unused, struct file *file)
11181+{
11182+ struct au_finfo *finfo;
11183+ aufs_bindex_t bindex;
1facf9fc 11184+
4a4d8108
AM
11185+ finfo = au_fi(file);
11186+ bindex = finfo->fi_btop;
0c5527e5
AM
11187+ if (bindex >= 0) {
11188+ /* remove me from sb->s_files */
11189+ file_sb_list_del(file);
4a4d8108 11190+ au_set_h_fptr(file, bindex, NULL);
0c5527e5 11191+ }
7f207e10 11192+
4a4d8108
AM
11193+ au_finfo_fin(file);
11194+ return 0;
1facf9fc 11195+}
11196+
4a4d8108
AM
11197+/* ---------------------------------------------------------------------- */
11198+
11199+static int au_do_flush_nondir(struct file *file, fl_owner_t id)
dece6358 11200+{
1308ab2a 11201+ int err;
4a4d8108
AM
11202+ struct file *h_file;
11203+
11204+ err = 0;
11205+ h_file = au_hf_top(file);
11206+ if (h_file)
11207+ err = vfsub_flush(h_file, id);
11208+ return err;
11209+}
11210+
11211+static int aufs_flush_nondir(struct file *file, fl_owner_t id)
11212+{
11213+ return au_do_flush(file, id, au_do_flush_nondir);
11214+}
11215+
11216+/* ---------------------------------------------------------------------- */
9dbd164d
AM
11217+/*
11218+ * read and write functions acquire [fdi]_rwsem once, but release before
11219+ * mmap_sem. This is because to stop a race condition between mmap(2).
11220+ * Releasing these aufs-rwsem should be safe, no branch-mamagement (by keeping
11221+ * si_rwsem), no harmful copy-up should happen. Actually copy-up may happen in
11222+ * read functions after [fdi]_rwsem are released, but it should be harmless.
11223+ */
4a4d8108
AM
11224+
11225+static ssize_t aufs_read(struct file *file, char __user *buf, size_t count,
11226+ loff_t *ppos)
11227+{
11228+ ssize_t err;
dece6358 11229+ struct dentry *dentry;
4a4d8108 11230+ struct file *h_file;
dece6358 11231+ struct super_block *sb;
1facf9fc 11232+
dece6358
AM
11233+ dentry = file->f_dentry;
11234+ sb = dentry->d_sb;
e49829fe 11235+ si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLMW);
4a4d8108 11236+ err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/0);
dece6358
AM
11237+ if (unlikely(err))
11238+ goto out;
1facf9fc 11239+
4a4d8108 11240+ h_file = au_hf_top(file);
9dbd164d
AM
11241+ get_file(h_file);
11242+ di_read_unlock(dentry, AuLock_IR);
11243+ fi_read_unlock(file);
11244+
11245+ /* filedata may be obsoleted by concurrent copyup, but no problem */
4a4d8108
AM
11246+ err = vfsub_read_u(h_file, buf, count, ppos);
11247+ /* todo: necessary? */
11248+ /* file->f_ra = h_file->f_ra; */
9dbd164d 11249+ /* update without lock, I don't think it a problem */
4a4d8108 11250+ fsstack_copy_attr_atime(dentry->d_inode, h_file->f_dentry->d_inode);
9dbd164d 11251+ fput(h_file);
1308ab2a 11252+
4f0767ce 11253+out:
dece6358
AM
11254+ si_read_unlock(sb);
11255+ return err;
11256+}
1facf9fc 11257+
e49829fe
JR
11258+/*
11259+ * todo: very ugly
11260+ * it locks both of i_mutex and si_rwsem for read in safe.
11261+ * if the plink maintenance mode continues forever (that is the problem),
11262+ * may loop forever.
11263+ */
11264+static void au_mtx_and_read_lock(struct inode *inode)
11265+{
11266+ int err;
11267+ struct super_block *sb = inode->i_sb;
11268+
11269+ while (1) {
11270+ mutex_lock(&inode->i_mutex);
11271+ err = si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLM);
11272+ if (!err)
11273+ break;
11274+ mutex_unlock(&inode->i_mutex);
11275+ si_read_lock(sb, AuLock_NOPLMW);
11276+ si_read_unlock(sb);
11277+ }
11278+}
11279+
4a4d8108
AM
11280+static ssize_t aufs_write(struct file *file, const char __user *ubuf,
11281+ size_t count, loff_t *ppos)
dece6358 11282+{
4a4d8108
AM
11283+ ssize_t err;
11284+ struct au_pin pin;
dece6358 11285+ struct dentry *dentry;
9dbd164d 11286+ struct super_block *sb;
4a4d8108 11287+ struct inode *inode;
4a4d8108
AM
11288+ struct file *h_file;
11289+ char __user *buf = (char __user *)ubuf;
1facf9fc 11290+
dece6358 11291+ dentry = file->f_dentry;
9dbd164d 11292+ sb = dentry->d_sb;
4a4d8108 11293+ inode = dentry->d_inode;
e49829fe 11294+ au_mtx_and_read_lock(inode);
1facf9fc 11295+
4a4d8108
AM
11296+ err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/1);
11297+ if (unlikely(err))
11298+ goto out;
1facf9fc 11299+
4a4d8108
AM
11300+ err = au_ready_to_write(file, -1, &pin);
11301+ di_downgrade_lock(dentry, AuLock_IR);
9dbd164d
AM
11302+ if (unlikely(err)) {
11303+ di_read_unlock(dentry, AuLock_IR);
11304+ fi_write_unlock(file);
11305+ goto out;
11306+ }
1facf9fc 11307+
4a4d8108 11308+ h_file = au_hf_top(file);
9dbd164d 11309+ get_file(h_file);
4a4d8108 11310+ au_unpin(&pin);
9dbd164d
AM
11311+ di_read_unlock(dentry, AuLock_IR);
11312+ fi_write_unlock(file);
11313+
4a4d8108 11314+ err = vfsub_write_u(h_file, buf, count, ppos);
9dbd164d 11315+ ii_write_lock_child(inode);
4a4d8108
AM
11316+ au_cpup_attr_timesizes(inode);
11317+ inode->i_mode = h_file->f_dentry->d_inode->i_mode;
9dbd164d
AM
11318+ ii_write_unlock(inode);
11319+ fput(h_file);
1facf9fc 11320+
4f0767ce 11321+out:
9dbd164d 11322+ si_read_unlock(sb);
4a4d8108 11323+ mutex_unlock(&inode->i_mutex);
dece6358
AM
11324+ return err;
11325+}
1facf9fc 11326+
4a4d8108
AM
11327+static ssize_t au_do_aio(struct file *h_file, int rw, struct kiocb *kio,
11328+ const struct iovec *iov, unsigned long nv, loff_t pos)
dece6358 11329+{
4a4d8108
AM
11330+ ssize_t err;
11331+ struct file *file;
11332+ ssize_t (*func)(struct kiocb *, const struct iovec *, unsigned long,
11333+ loff_t);
1facf9fc 11334+
4a4d8108
AM
11335+ err = security_file_permission(h_file, rw);
11336+ if (unlikely(err))
11337+ goto out;
1facf9fc 11338+
4a4d8108
AM
11339+ err = -ENOSYS;
11340+ func = NULL;
11341+ if (rw == MAY_READ)
11342+ func = h_file->f_op->aio_read;
11343+ else if (rw == MAY_WRITE)
11344+ func = h_file->f_op->aio_write;
11345+ if (func) {
11346+ file = kio->ki_filp;
11347+ kio->ki_filp = h_file;
2cbb1c4b 11348+ lockdep_off();
4a4d8108 11349+ err = func(kio, iov, nv, pos);
2cbb1c4b 11350+ lockdep_on();
4a4d8108
AM
11351+ kio->ki_filp = file;
11352+ } else
11353+ /* currently there is no such fs */
11354+ WARN_ON_ONCE(1);
1facf9fc 11355+
4f0767ce 11356+out:
dece6358
AM
11357+ return err;
11358+}
1facf9fc 11359+
4a4d8108
AM
11360+static ssize_t aufs_aio_read(struct kiocb *kio, const struct iovec *iov,
11361+ unsigned long nv, loff_t pos)
1facf9fc 11362+{
4a4d8108
AM
11363+ ssize_t err;
11364+ struct file *file, *h_file;
11365+ struct dentry *dentry;
dece6358 11366+ struct super_block *sb;
1facf9fc 11367+
4a4d8108 11368+ file = kio->ki_filp;
dece6358 11369+ dentry = file->f_dentry;
1308ab2a 11370+ sb = dentry->d_sb;
e49829fe 11371+ si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLMW);
4a4d8108
AM
11372+ err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/0);
11373+ if (unlikely(err))
11374+ goto out;
11375+
11376+ h_file = au_hf_top(file);
9dbd164d
AM
11377+ get_file(h_file);
11378+ di_read_unlock(dentry, AuLock_IR);
11379+ fi_read_unlock(file);
11380+
4a4d8108
AM
11381+ err = au_do_aio(h_file, MAY_READ, kio, iov, nv, pos);
11382+ /* todo: necessary? */
11383+ /* file->f_ra = h_file->f_ra; */
9dbd164d 11384+ /* update without lock, I don't think it a problem */
4a4d8108 11385+ fsstack_copy_attr_atime(dentry->d_inode, h_file->f_dentry->d_inode);
9dbd164d 11386+ fput(h_file);
1facf9fc 11387+
4f0767ce 11388+out:
4a4d8108 11389+ si_read_unlock(sb);
1308ab2a 11390+ return err;
11391+}
1facf9fc 11392+
4a4d8108
AM
11393+static ssize_t aufs_aio_write(struct kiocb *kio, const struct iovec *iov,
11394+ unsigned long nv, loff_t pos)
1308ab2a 11395+{
4a4d8108
AM
11396+ ssize_t err;
11397+ struct au_pin pin;
11398+ struct dentry *dentry;
11399+ struct inode *inode;
4a4d8108 11400+ struct file *file, *h_file;
9dbd164d 11401+ struct super_block *sb;
1308ab2a 11402+
4a4d8108 11403+ file = kio->ki_filp;
1308ab2a 11404+ dentry = file->f_dentry;
9dbd164d 11405+ sb = dentry->d_sb;
1308ab2a 11406+ inode = dentry->d_inode;
e49829fe
JR
11407+ au_mtx_and_read_lock(inode);
11408+
4a4d8108
AM
11409+ err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/1);
11410+ if (unlikely(err))
1308ab2a 11411+ goto out;
1facf9fc 11412+
4a4d8108
AM
11413+ err = au_ready_to_write(file, -1, &pin);
11414+ di_downgrade_lock(dentry, AuLock_IR);
9dbd164d
AM
11415+ if (unlikely(err)) {
11416+ di_read_unlock(dentry, AuLock_IR);
11417+ fi_write_unlock(file);
11418+ goto out;
11419+ }
1facf9fc 11420+
4a4d8108 11421+ h_file = au_hf_top(file);
9dbd164d
AM
11422+ get_file(h_file);
11423+ au_unpin(&pin);
11424+ di_read_unlock(dentry, AuLock_IR);
11425+ fi_write_unlock(file);
11426+
4a4d8108 11427+ err = au_do_aio(h_file, MAY_WRITE, kio, iov, nv, pos);
9dbd164d 11428+ ii_write_lock_child(inode);
4a4d8108
AM
11429+ au_cpup_attr_timesizes(inode);
11430+ inode->i_mode = h_file->f_dentry->d_inode->i_mode;
9dbd164d
AM
11431+ ii_write_unlock(inode);
11432+ fput(h_file);
1facf9fc 11433+
4f0767ce 11434+out:
9dbd164d 11435+ si_read_unlock(sb);
4a4d8108 11436+ mutex_unlock(&inode->i_mutex);
dece6358 11437+ return err;
1facf9fc 11438+}
11439+
4a4d8108
AM
11440+static ssize_t aufs_splice_read(struct file *file, loff_t *ppos,
11441+ struct pipe_inode_info *pipe, size_t len,
11442+ unsigned int flags)
1facf9fc 11443+{
4a4d8108
AM
11444+ ssize_t err;
11445+ struct file *h_file;
11446+ struct dentry *dentry;
dece6358 11447+ struct super_block *sb;
1facf9fc 11448+
dece6358 11449+ dentry = file->f_dentry;
dece6358 11450+ sb = dentry->d_sb;
e49829fe 11451+ si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLMW);
4a4d8108
AM
11452+ err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/0);
11453+ if (unlikely(err))
dece6358 11454+ goto out;
1facf9fc 11455+
4a4d8108
AM
11456+ err = -EINVAL;
11457+ h_file = au_hf_top(file);
9dbd164d 11458+ get_file(h_file);
4a4d8108 11459+ if (au_test_loopback_kthread()) {
87a755f4
AM
11460+ au_warn_loopback(h_file->f_dentry->d_sb);
11461+ if (file->f_mapping != h_file->f_mapping) {
11462+ file->f_mapping = h_file->f_mapping;
11463+ smp_mb(); /* unnecessary? */
11464+ }
1308ab2a 11465+ }
9dbd164d
AM
11466+ di_read_unlock(dentry, AuLock_IR);
11467+ fi_read_unlock(file);
11468+
4a4d8108
AM
11469+ err = vfsub_splice_to(h_file, ppos, pipe, len, flags);
11470+ /* todo: necessasry? */
11471+ /* file->f_ra = h_file->f_ra; */
9dbd164d 11472+ /* update without lock, I don't think it a problem */
4a4d8108 11473+ fsstack_copy_attr_atime(dentry->d_inode, h_file->f_dentry->d_inode);
9dbd164d 11474+ fput(h_file);
1facf9fc 11475+
4f0767ce 11476+out:
4a4d8108 11477+ si_read_unlock(sb);
dece6358 11478+ return err;
1facf9fc 11479+}
11480+
4a4d8108
AM
11481+static ssize_t
11482+aufs_splice_write(struct pipe_inode_info *pipe, struct file *file, loff_t *ppos,
11483+ size_t len, unsigned int flags)
1facf9fc 11484+{
4a4d8108
AM
11485+ ssize_t err;
11486+ struct au_pin pin;
11487+ struct dentry *dentry;
11488+ struct inode *inode;
4a4d8108 11489+ struct file *h_file;
9dbd164d 11490+ struct super_block *sb;
1facf9fc 11491+
4a4d8108 11492+ dentry = file->f_dentry;
9dbd164d 11493+ sb = dentry->d_sb;
4a4d8108 11494+ inode = dentry->d_inode;
e49829fe 11495+ au_mtx_and_read_lock(inode);
9dbd164d 11496+
4a4d8108
AM
11497+ err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/1);
11498+ if (unlikely(err))
11499+ goto out;
1facf9fc 11500+
4a4d8108
AM
11501+ err = au_ready_to_write(file, -1, &pin);
11502+ di_downgrade_lock(dentry, AuLock_IR);
9dbd164d
AM
11503+ if (unlikely(err)) {
11504+ di_read_unlock(dentry, AuLock_IR);
11505+ fi_write_unlock(file);
11506+ goto out;
11507+ }
1facf9fc 11508+
4a4d8108 11509+ h_file = au_hf_top(file);
9dbd164d 11510+ get_file(h_file);
4a4d8108 11511+ au_unpin(&pin);
9dbd164d
AM
11512+ di_read_unlock(dentry, AuLock_IR);
11513+ fi_write_unlock(file);
11514+
4a4d8108 11515+ err = vfsub_splice_from(pipe, h_file, ppos, len, flags);
9dbd164d 11516+ ii_write_lock_child(inode);
4a4d8108
AM
11517+ au_cpup_attr_timesizes(inode);
11518+ inode->i_mode = h_file->f_dentry->d_inode->i_mode;
9dbd164d
AM
11519+ ii_write_unlock(inode);
11520+ fput(h_file);
1facf9fc 11521+
4f0767ce 11522+out:
9dbd164d 11523+ si_read_unlock(sb);
4a4d8108
AM
11524+ mutex_unlock(&inode->i_mutex);
11525+ return err;
11526+}
1facf9fc 11527+
4a4d8108
AM
11528+/* ---------------------------------------------------------------------- */
11529+
9dbd164d
AM
11530+/*
11531+ * The locking order around current->mmap_sem.
11532+ * - in most and regular cases
11533+ * file I/O syscall -- aufs_read() or something
11534+ * -- si_rwsem for read -- mmap_sem
11535+ * (Note that [fdi]i_rwsem are released before mmap_sem).
11536+ * - in mmap case
11537+ * mmap(2) -- mmap_sem -- aufs_mmap() -- si_rwsem for read -- [fdi]i_rwsem
11538+ * This AB-BA order is definitly bad, but is not a problem since "si_rwsem for
11539+ * read" allows muliple processes to acquire it and [fdi]i_rwsem are not held in
11540+ * file I/O. Aufs needs to stop lockdep in aufs_mmap() though.
11541+ * It means that when aufs acquires si_rwsem for write, the process should never
11542+ * acquire mmap_sem.
11543+ *
11544+ * Actually aufs_readdir() holds [fdi]i_rwsem before mmap_sem, but this is not a
11545+ * problem either since any directory is not able to be mmap-ed.
11546+ * The similar scenario is applied to aufs_readlink() too.
11547+ */
11548+
9dbd164d 11549+static int aufs_mmap(struct file *file, struct vm_area_struct *vma)
dece6358 11550+{
4a4d8108
AM
11551+ int err;
11552+ aufs_bindex_t bstart;
11553+ const unsigned char wlock
9dbd164d 11554+ = (file->f_mode & FMODE_WRITE) && (vma->vm_flags & VM_SHARED);
4a4d8108
AM
11555+ struct dentry *dentry;
11556+ struct super_block *sb;
9dbd164d
AM
11557+ struct file *h_file;
11558+ struct au_branch *br;
11559+ struct au_pin pin;
11560+
11561+ AuDbgVmRegion(file, vma);
1308ab2a 11562+
4a4d8108
AM
11563+ dentry = file->f_dentry;
11564+ sb = dentry->d_sb;
9dbd164d 11565+ lockdep_off();
e49829fe 11566+ si_read_lock(sb, AuLock_NOPLMW);
4a4d8108
AM
11567+ err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/1);
11568+ if (unlikely(err))
11569+ goto out;
11570+
4a4d8108 11571+ if (wlock) {
4a4d8108
AM
11572+ err = au_ready_to_write(file, -1, &pin);
11573+ di_write_unlock(dentry);
9dbd164d
AM
11574+ if (unlikely(err)) {
11575+ fi_write_unlock(file);
11576+ goto out;
11577+ }
4a4d8108
AM
11578+ au_unpin(&pin);
11579+ } else
11580+ di_write_unlock(dentry);
9dbd164d 11581+
4a4d8108 11582+ bstart = au_fbstart(file);
9dbd164d
AM
11583+ br = au_sbr(sb, bstart);
11584+ h_file = au_hf_top(file);
11585+ get_file(h_file);
2cbb1c4b 11586+ au_set_mmapped(file);
4a4d8108 11587+ fi_write_unlock(file);
9dbd164d 11588+ lockdep_on();
1308ab2a 11589+
9dbd164d 11590+ au_vm_file_reset(vma, h_file);
0c3ec466
AM
11591+ /* todo: bad approach, I am not sure this is really necessary */
11592+ err = au_security_mmap_file(h_file, vma);
9dbd164d
AM
11593+ if (!err)
11594+ err = h_file->f_op->mmap(h_file, vma);
2cbb1c4b
JR
11595+ if (unlikely(err))
11596+ goto out_reset;
4a4d8108 11597+
2cbb1c4b 11598+ au_vm_prfile_set(vma, file);
4a4d8108 11599+ /* update without lock, I don't think it a problem */
2cbb1c4b 11600+ fsstack_copy_attr_atime(file->f_dentry->d_inode,
9dbd164d 11601+ h_file->f_dentry->d_inode);
2cbb1c4b 11602+ goto out_fput; /* success */
4a4d8108 11603+
2cbb1c4b
JR
11604+out_reset:
11605+ au_unset_mmapped(file);
11606+ au_vm_file_reset(vma, file);
11607+out_fput:
9dbd164d
AM
11608+ fput(h_file);
11609+ lockdep_off();
4f0767ce 11610+out:
9dbd164d
AM
11611+ si_read_unlock(sb);
11612+ lockdep_on();
11613+ AuTraceErr(err);
4a4d8108
AM
11614+ return err;
11615+}
11616+
11617+/* ---------------------------------------------------------------------- */
11618+
1e00d052
AM
11619+static int aufs_fsync_nondir(struct file *file, loff_t start, loff_t end,
11620+ int datasync)
4a4d8108
AM
11621+{
11622+ int err;
11623+ struct au_pin pin;
b752ccd1 11624+ struct dentry *dentry;
4a4d8108
AM
11625+ struct inode *inode;
11626+ struct file *h_file;
11627+ struct super_block *sb;
11628+
b752ccd1 11629+ dentry = file->f_dentry;
4a4d8108 11630+ inode = dentry->d_inode;
4a4d8108 11631+ sb = dentry->d_sb;
1e00d052 11632+ mutex_lock(&inode->i_mutex);
e49829fe
JR
11633+ err = si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLM);
11634+ if (unlikely(err))
11635+ goto out;
4a4d8108
AM
11636+
11637+ err = 0; /* -EBADF; */ /* posix? */
11638+ if (unlikely(!(file->f_mode & FMODE_WRITE)))
e49829fe 11639+ goto out_si;
4a4d8108
AM
11640+ err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/1);
11641+ if (unlikely(err))
e49829fe 11642+ goto out_si;
4a4d8108
AM
11643+
11644+ err = au_ready_to_write(file, -1, &pin);
11645+ di_downgrade_lock(dentry, AuLock_IR);
11646+ if (unlikely(err))
11647+ goto out_unlock;
11648+ au_unpin(&pin);
11649+
11650+ err = -EINVAL;
11651+ h_file = au_hf_top(file);
53392da6
AM
11652+ err = vfsub_fsync(h_file, &h_file->f_path, datasync);
11653+ au_cpup_attr_timesizes(inode);
4a4d8108 11654+
4f0767ce 11655+out_unlock:
4a4d8108 11656+ di_read_unlock(dentry, AuLock_IR);
1308ab2a 11657+ fi_write_unlock(file);
e49829fe 11658+out_si:
953406b4 11659+ si_read_unlock(sb);
e49829fe 11660+out:
1e00d052 11661+ mutex_unlock(&inode->i_mutex);
4a4d8108 11662+ return err;
dece6358
AM
11663+}
11664+
4a4d8108
AM
11665+/* no one supports this operation, currently */
11666+#if 0
11667+static int aufs_aio_fsync_nondir(struct kiocb *kio, int datasync)
dece6358 11668+{
4a4d8108
AM
11669+ int err;
11670+ struct au_pin pin;
1308ab2a 11671+ struct dentry *dentry;
4a4d8108
AM
11672+ struct inode *inode;
11673+ struct file *file, *h_file;
1308ab2a 11674+
4a4d8108 11675+ file = kio->ki_filp;
1308ab2a 11676+ dentry = file->f_dentry;
4a4d8108 11677+ inode = dentry->d_inode;
e49829fe 11678+ au_mtx_and_read_lock(inode);
4a4d8108
AM
11679+
11680+ err = 0; /* -EBADF; */ /* posix? */
11681+ if (unlikely(!(file->f_mode & FMODE_WRITE)))
11682+ goto out;
11683+ err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/1);
11684+ if (unlikely(err))
1308ab2a 11685+ goto out;
11686+
4a4d8108
AM
11687+ err = au_ready_to_write(file, -1, &pin);
11688+ di_downgrade_lock(dentry, AuLock_IR);
11689+ if (unlikely(err))
11690+ goto out_unlock;
11691+ au_unpin(&pin);
1308ab2a 11692+
4a4d8108
AM
11693+ err = -ENOSYS;
11694+ h_file = au_hf_top(file);
11695+ if (h_file->f_op && h_file->f_op->aio_fsync) {
11696+ struct dentry *h_d;
11697+ struct mutex *h_mtx;
1308ab2a 11698+
4a4d8108
AM
11699+ h_d = h_file->f_dentry;
11700+ h_mtx = &h_d->d_inode->i_mutex;
11701+ if (!is_sync_kiocb(kio)) {
11702+ get_file(h_file);
11703+ fput(file);
11704+ }
11705+ kio->ki_filp = h_file;
11706+ err = h_file->f_op->aio_fsync(kio, datasync);
11707+ mutex_lock_nested(h_mtx, AuLsc_I_CHILD);
11708+ if (!err)
11709+ vfsub_update_h_iattr(&h_file->f_path, /*did*/NULL);
11710+ /*ignore*/
11711+ au_cpup_attr_timesizes(inode);
11712+ mutex_unlock(h_mtx);
11713+ }
1308ab2a 11714+
4f0767ce 11715+out_unlock:
4a4d8108
AM
11716+ di_read_unlock(dentry, AuLock_IR);
11717+ fi_write_unlock(file);
4f0767ce 11718+out:
e49829fe 11719+ si_read_unlock(inode->sb);
4a4d8108
AM
11720+ mutex_unlock(&inode->i_mutex);
11721+ return err;
dece6358 11722+}
4a4d8108 11723+#endif
dece6358 11724+
4a4d8108 11725+static int aufs_fasync(int fd, struct file *file, int flag)
dece6358 11726+{
4a4d8108
AM
11727+ int err;
11728+ struct file *h_file;
11729+ struct dentry *dentry;
11730+ struct super_block *sb;
1308ab2a 11731+
4a4d8108
AM
11732+ dentry = file->f_dentry;
11733+ sb = dentry->d_sb;
e49829fe 11734+ si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLMW);
4a4d8108
AM
11735+ err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/0);
11736+ if (unlikely(err))
11737+ goto out;
11738+
11739+ h_file = au_hf_top(file);
11740+ if (h_file->f_op && h_file->f_op->fasync)
11741+ err = h_file->f_op->fasync(fd, h_file, flag);
11742+
11743+ di_read_unlock(dentry, AuLock_IR);
11744+ fi_read_unlock(file);
1308ab2a 11745+
4f0767ce 11746+out:
4a4d8108 11747+ si_read_unlock(sb);
1308ab2a 11748+ return err;
dece6358 11749+}
4a4d8108
AM
11750+
11751+/* ---------------------------------------------------------------------- */
11752+
11753+/* no one supports this operation, currently */
11754+#if 0
11755+static ssize_t aufs_sendpage(struct file *file, struct page *page, int offset,
11756+ size_t len, loff_t *pos , int more)
11757+{
11758+}
11759+#endif
11760+
11761+/* ---------------------------------------------------------------------- */
11762+
11763+const struct file_operations aufs_file_fop = {
11764+ .owner = THIS_MODULE,
2cbb1c4b 11765+
027c5e7a 11766+ .llseek = default_llseek,
4a4d8108
AM
11767+
11768+ .read = aufs_read,
11769+ .write = aufs_write,
11770+ .aio_read = aufs_aio_read,
11771+ .aio_write = aufs_aio_write,
11772+#ifdef CONFIG_AUFS_POLL
11773+ .poll = aufs_poll,
11774+#endif
11775+ .unlocked_ioctl = aufs_ioctl_nondir,
b752ccd1
AM
11776+#ifdef CONFIG_COMPAT
11777+ .compat_ioctl = aufs_ioctl_nondir, /* same */
11778+#endif
4a4d8108
AM
11779+ .mmap = aufs_mmap,
11780+ .open = aufs_open_nondir,
11781+ .flush = aufs_flush_nondir,
11782+ .release = aufs_release_nondir,
11783+ .fsync = aufs_fsync_nondir,
11784+ /* .aio_fsync = aufs_aio_fsync_nondir, */
11785+ .fasync = aufs_fasync,
11786+ /* .sendpage = aufs_sendpage, */
11787+ .splice_write = aufs_splice_write,
11788+ .splice_read = aufs_splice_read,
11789+#if 0
11790+ .aio_splice_write = aufs_aio_splice_write,
11791+ .aio_splice_read = aufs_aio_splice_read
11792+#endif
11793+};
7f207e10
AM
11794diff -urN /usr/share/empty/fs/aufs/f_op_sp.c linux/fs/aufs/f_op_sp.c
11795--- /usr/share/empty/fs/aufs/f_op_sp.c 1970-01-01 01:00:00.000000000 +0100
0c3ec466
AM
11796+++ linux/fs/aufs/f_op_sp.c 2012-07-22 19:57:03.164337936 +0200
11797@@ -0,0 +1,295 @@
1308ab2a 11798+/*
f6c5ef8b 11799+ * Copyright (C) 2005-2012 Junjiro R. Okajima
1308ab2a 11800+ *
11801+ * This program, aufs is free software; you can redistribute it and/or modify
11802+ * it under the terms of the GNU General Public License as published by
11803+ * the Free Software Foundation; either version 2 of the License, or
11804+ * (at your option) any later version.
11805+ *
11806+ * This program is distributed in the hope that it will be useful,
11807+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
11808+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11809+ * GNU General Public License for more details.
11810+ *
11811+ * You should have received a copy of the GNU General Public License
11812+ * along with this program; if not, write to the Free Software
11813+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
11814+ */
dece6358 11815+
1308ab2a 11816+/*
4a4d8108
AM
11817+ * file operations for special files.
11818+ * while they exist in aufs virtually,
11819+ * their file I/O is handled out of aufs.
1308ab2a 11820+ */
11821+
4a4d8108 11822+#include "aufs.h"
1308ab2a 11823+
4a4d8108
AM
11824+static ssize_t aufs_aio_read_sp(struct kiocb *kio, const struct iovec *iov,
11825+ unsigned long nv, loff_t pos)
dece6358 11826+{
4a4d8108
AM
11827+ ssize_t err;
11828+ aufs_bindex_t bstart;
11829+ unsigned char wbr;
11830+ struct file *file, *h_file;
11831+ struct super_block *sb;
1308ab2a 11832+
4a4d8108
AM
11833+ file = kio->ki_filp;
11834+ sb = file->f_dentry->d_sb;
11835+ si_read_lock(sb, AuLock_FLUSH);
11836+ fi_read_lock(file);
11837+ bstart = au_fbstart(file);
11838+ h_file = au_hf_top(file);
11839+ fi_read_unlock(file);
11840+ wbr = !!au_br_writable(au_sbr(sb, bstart)->br_perm);
11841+ si_read_unlock(sb);
11842+
11843+ /* do not change the file in kio */
11844+ AuDebugOn(!h_file->f_op || !h_file->f_op->aio_read);
11845+ err = h_file->f_op->aio_read(kio, iov, nv, pos);
11846+ if (err > 0 && wbr)
11847+ file_accessed(h_file);
11848+
11849+ return err;
11850+}
11851+
11852+static ssize_t aufs_aio_write_sp(struct kiocb *kio, const struct iovec *iov,
11853+ unsigned long nv, loff_t pos)
11854+{
11855+ ssize_t err;
11856+ aufs_bindex_t bstart;
11857+ unsigned char wbr;
11858+ struct super_block *sb;
11859+ struct file *file, *h_file;
11860+
11861+ file = kio->ki_filp;
11862+ sb = file->f_dentry->d_sb;
11863+ si_read_lock(sb, AuLock_FLUSH);
11864+ fi_read_lock(file);
11865+ bstart = au_fbstart(file);
11866+ h_file = au_hf_top(file);
11867+ fi_read_unlock(file);
11868+ wbr = !!au_br_writable(au_sbr(sb, bstart)->br_perm);
11869+ si_read_unlock(sb);
11870+
11871+ /* do not change the file in kio */
11872+ AuDebugOn(!h_file->f_op || !h_file->f_op->aio_write);
11873+ err = h_file->f_op->aio_write(kio, iov, nv, pos);
4a4d8108
AM
11874+ return err;
11875+}
11876+
11877+/* ---------------------------------------------------------------------- */
11878+
11879+static int aufs_release_sp(struct inode *inode, struct file *file)
11880+{
11881+ int err;
11882+ struct file *h_file;
11883+
11884+ fi_read_lock(file);
11885+ h_file = au_hf_top(file);
11886+ fi_read_unlock(file);
11887+ /* close this fifo in aufs */
11888+ err = h_file->f_op->release(inode, file); /* ignore */
11889+ aufs_release_nondir(inode, file); /* ignore */
11890+ return err;
11891+}
11892+
11893+/* ---------------------------------------------------------------------- */
11894+
11895+/* currently, support only FIFO */
4f0767ce
JR
11896+enum {
11897+ AuSp_FIFO, AuSp_FIFO_R, AuSp_FIFO_W, AuSp_FIFO_RW,
11898+ /* AuSp_SOCK, AuSp_CHR, AuSp_BLK, */
11899+ AuSp_Last
11900+};
4a4d8108
AM
11901+static int aufs_open_sp(struct inode *inode, struct file *file);
11902+static struct au_sp_fop {
11903+ int done;
11904+ struct file_operations fop; /* not 'const' */
11905+ spinlock_t spin;
11906+} au_sp_fop[AuSp_Last] = {
11907+ [AuSp_FIFO] = {
11908+ .fop = {
11909+ .owner = THIS_MODULE,
11910+ .open = aufs_open_sp
11911+ }
11912+ }
11913+};
11914+
11915+static void au_init_fop_sp(struct file *file)
11916+{
11917+ struct au_sp_fop *p;
11918+ int i;
11919+ struct file *h_file;
11920+
11921+ p = au_sp_fop;
11922+ if (unlikely(!p->done)) {
11923+ /* initialize first time only */
11924+ static DEFINE_SPINLOCK(spin);
11925+
11926+ spin_lock(&spin);
11927+ if (!p->done) {
11928+ BUILD_BUG_ON(sizeof(au_sp_fop)/sizeof(*au_sp_fop)
11929+ != AuSp_Last);
11930+ for (i = 0; i < AuSp_Last; i++)
11931+ spin_lock_init(&p[i].spin);
11932+ p->done = 1;
11933+ }
11934+ spin_unlock(&spin);
11935+ }
11936+
11937+ switch (file->f_mode & (FMODE_READ | FMODE_WRITE)) {
11938+ case FMODE_READ:
11939+ i = AuSp_FIFO_R;
11940+ break;
11941+ case FMODE_WRITE:
11942+ i = AuSp_FIFO_W;
11943+ break;
11944+ case FMODE_READ | FMODE_WRITE:
11945+ i = AuSp_FIFO_RW;
11946+ break;
11947+ default:
11948+ BUG();
11949+ }
11950+
11951+ p += i;
11952+ if (unlikely(!p->done)) {
11953+ /* initialize first time only */
11954+ h_file = au_hf_top(file);
11955+ spin_lock(&p->spin);
11956+ if (!p->done) {
11957+ p->fop = *h_file->f_op;
11958+ p->fop.owner = THIS_MODULE;
11959+ if (p->fop.aio_read)
11960+ p->fop.aio_read = aufs_aio_read_sp;
11961+ if (p->fop.aio_write)
11962+ p->fop.aio_write = aufs_aio_write_sp;
11963+ p->fop.release = aufs_release_sp;
11964+ p->done = 1;
11965+ }
11966+ spin_unlock(&p->spin);
11967+ }
11968+ file->f_op = &p->fop;
11969+}
11970+
11971+static int au_cpup_sp(struct dentry *dentry)
11972+{
11973+ int err;
11974+ aufs_bindex_t bcpup;
11975+ struct au_pin pin;
11976+ struct au_wr_dir_args wr_dir_args = {
11977+ .force_btgt = -1,
11978+ .flags = 0
11979+ };
11980+
11981+ AuDbg("%.*s\n", AuDLNPair(dentry));
11982+
11983+ di_read_unlock(dentry, AuLock_IR);
11984+ di_write_lock_child(dentry);
11985+ err = au_wr_dir(dentry, /*src_dentry*/NULL, &wr_dir_args);
11986+ if (unlikely(err < 0))
11987+ goto out;
11988+ bcpup = err;
11989+ err = 0;
11990+ if (bcpup == au_dbstart(dentry))
11991+ goto out; /* success */
11992+
11993+ err = au_pin(&pin, dentry, bcpup, au_opt_udba(dentry->d_sb),
11994+ AuPin_MNT_WRITE);
11995+ if (!err) {
11996+ err = au_sio_cpup_simple(dentry, bcpup, -1, AuCpup_DTIME);
11997+ au_unpin(&pin);
11998+ }
11999+
4f0767ce 12000+out:
4a4d8108
AM
12001+ di_downgrade_lock(dentry, AuLock_IR);
12002+ return err;
12003+}
12004+
12005+static int au_do_open_sp(struct file *file, int flags)
12006+{
12007+ int err;
12008+ struct dentry *dentry;
12009+ struct super_block *sb;
12010+ struct file *h_file;
12011+ struct inode *h_inode;
12012+
12013+ dentry = file->f_dentry;
12014+ AuDbg("%.*s\n", AuDLNPair(dentry));
12015+
12016+ /*
12017+ * try copying-up.
12018+ * operate on the ro branch is not an error.
12019+ */
12020+ au_cpup_sp(dentry); /* ignore */
12021+
12022+ /* prepare h_file */
12023+ err = au_do_open_nondir(file, vfsub_file_flags(file));
12024+ if (unlikely(err))
12025+ goto out;
12026+
12027+ sb = dentry->d_sb;
12028+ h_file = au_hf_top(file);
12029+ h_inode = h_file->f_dentry->d_inode;
12030+ di_read_unlock(dentry, AuLock_IR);
12031+ fi_write_unlock(file);
12032+ si_read_unlock(sb);
12033+ /* open this fifo in aufs */
12034+ err = h_inode->i_fop->open(file->f_dentry->d_inode, file);
12035+ si_noflush_read_lock(sb);
12036+ fi_write_lock(file);
12037+ di_read_lock_child(dentry, AuLock_IR);
12038+ if (!err)
12039+ au_init_fop_sp(file);
4a4d8108 12040+
4f0767ce 12041+out:
4a4d8108
AM
12042+ return err;
12043+}
12044+
12045+static int aufs_open_sp(struct inode *inode, struct file *file)
12046+{
12047+ int err;
12048+ struct super_block *sb;
12049+
12050+ sb = file->f_dentry->d_sb;
12051+ si_read_lock(sb, AuLock_FLUSH);
12052+ err = au_do_open(file, au_do_open_sp, /*fidir*/NULL);
12053+ si_read_unlock(sb);
12054+ return err;
12055+}
12056+
12057+/* ---------------------------------------------------------------------- */
12058+
12059+void au_init_special_fop(struct inode *inode, umode_t mode, dev_t rdev)
12060+{
12061+ init_special_inode(inode, mode, rdev);
12062+
12063+ switch (mode & S_IFMT) {
12064+ case S_IFIFO:
12065+ inode->i_fop = &au_sp_fop[AuSp_FIFO].fop;
12066+ /*FALLTHROUGH*/
12067+ case S_IFCHR:
12068+ case S_IFBLK:
12069+ case S_IFSOCK:
12070+ break;
12071+ default:
12072+ AuDebugOn(1);
12073+ }
12074+}
12075+
12076+int au_special_file(umode_t mode)
12077+{
12078+ int ret;
12079+
12080+ ret = 0;
12081+ switch (mode & S_IFMT) {
12082+ case S_IFIFO:
12083+#if 0
12084+ case S_IFCHR:
12085+ case S_IFBLK:
12086+ case S_IFSOCK:
12087+#endif
12088+ ret = 1;
12089+ }
12090+
12091+ return ret;
12092+}
7f207e10
AM
12093diff -urN /usr/share/empty/fs/aufs/fstype.h linux/fs/aufs/fstype.h
12094--- /usr/share/empty/fs/aufs/fstype.h 1970-01-01 01:00:00.000000000 +0100
0c3ec466 12095+++ linux/fs/aufs/fstype.h 2012-07-22 19:57:03.164337936 +0200
f6c5ef8b 12096@@ -0,0 +1,496 @@
4a4d8108 12097+/*
f6c5ef8b 12098+ * Copyright (C) 2005-2012 Junjiro R. Okajima
4a4d8108
AM
12099+ *
12100+ * This program, aufs is free software; you can redistribute it and/or modify
12101+ * it under the terms of the GNU General Public License as published by
12102+ * the Free Software Foundation; either version 2 of the License, or
12103+ * (at your option) any later version.
12104+ *
12105+ * This program is distributed in the hope that it will be useful,
12106+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
12107+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12108+ * GNU General Public License for more details.
12109+ *
12110+ * You should have received a copy of the GNU General Public License
12111+ * along with this program; if not, write to the Free Software
12112+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
12113+ */
12114+
12115+/*
12116+ * judging filesystem type
12117+ */
12118+
12119+#ifndef __AUFS_FSTYPE_H__
12120+#define __AUFS_FSTYPE_H__
12121+
12122+#ifdef __KERNEL__
12123+
12124+#include <linux/fs.h>
12125+#include <linux/magic.h>
12126+#include <linux/romfs_fs.h>
4a4d8108
AM
12127+
12128+static inline int au_test_aufs(struct super_block *sb)
12129+{
12130+ return sb->s_magic == AUFS_SUPER_MAGIC;
12131+}
12132+
12133+static inline const char *au_sbtype(struct super_block *sb)
12134+{
12135+ return sb->s_type->name;
12136+}
1308ab2a 12137+
12138+static inline int au_test_iso9660(struct super_block *sb __maybe_unused)
12139+{
12140+#if defined(CONFIG_ROMFS_FS) || defined(CONFIG_ROMFS_FS_MODULE)
12141+ return sb->s_magic == ROMFS_MAGIC;
dece6358
AM
12142+#else
12143+ return 0;
12144+#endif
12145+}
12146+
1308ab2a 12147+static inline int au_test_romfs(struct super_block *sb __maybe_unused)
dece6358 12148+{
1308ab2a 12149+#if defined(CONFIG_ISO9660_FS) || defined(CONFIG_ISO9660_FS_MODULE)
12150+ return sb->s_magic == ISOFS_SUPER_MAGIC;
dece6358
AM
12151+#else
12152+ return 0;
12153+#endif
12154+}
12155+
1308ab2a 12156+static inline int au_test_cramfs(struct super_block *sb __maybe_unused)
dece6358 12157+{
1308ab2a 12158+#if defined(CONFIG_CRAMFS) || defined(CONFIG_CRAMFS_MODULE)
12159+ return sb->s_magic == CRAMFS_MAGIC;
12160+#endif
12161+ return 0;
12162+}
12163+
12164+static inline int au_test_nfs(struct super_block *sb __maybe_unused)
12165+{
12166+#if defined(CONFIG_NFS_FS) || defined(CONFIG_NFS_FS_MODULE)
12167+ return sb->s_magic == NFS_SUPER_MAGIC;
dece6358
AM
12168+#else
12169+ return 0;
12170+#endif
12171+}
12172+
1308ab2a 12173+static inline int au_test_fuse(struct super_block *sb __maybe_unused)
dece6358 12174+{
1308ab2a 12175+#if defined(CONFIG_FUSE_FS) || defined(CONFIG_FUSE_FS_MODULE)
12176+ return sb->s_magic == FUSE_SUPER_MAGIC;
dece6358
AM
12177+#else
12178+ return 0;
12179+#endif
12180+}
12181+
1308ab2a 12182+static inline int au_test_xfs(struct super_block *sb __maybe_unused)
dece6358 12183+{
1308ab2a 12184+#if defined(CONFIG_XFS_FS) || defined(CONFIG_XFS_FS_MODULE)
12185+ return sb->s_magic == XFS_SB_MAGIC;
dece6358
AM
12186+#else
12187+ return 0;
12188+#endif
12189+}
12190+
1308ab2a 12191+static inline int au_test_tmpfs(struct super_block *sb __maybe_unused)
dece6358 12192+{
1308ab2a 12193+#ifdef CONFIG_TMPFS
12194+ return sb->s_magic == TMPFS_MAGIC;
12195+#else
12196+ return 0;
dece6358 12197+#endif
dece6358
AM
12198+}
12199+
1308ab2a 12200+static inline int au_test_ecryptfs(struct super_block *sb __maybe_unused)
1facf9fc 12201+{
1308ab2a 12202+#if defined(CONFIG_ECRYPT_FS) || defined(CONFIG_ECRYPT_FS_MODULE)
12203+ return !strcmp(au_sbtype(sb), "ecryptfs");
12204+#else
12205+ return 0;
12206+#endif
1facf9fc 12207+}
12208+
1308ab2a 12209+static inline int au_test_smbfs(struct super_block *sb __maybe_unused)
1facf9fc 12210+{
1308ab2a 12211+#if defined(CONFIG_SMB_FS) || defined(CONFIG_SMB_FS_MODULE)
12212+ return sb->s_magic == SMB_SUPER_MAGIC;
12213+#else
12214+ return 0;
1facf9fc 12215+#endif
1facf9fc 12216+}
12217+
1308ab2a 12218+static inline int au_test_ocfs2(struct super_block *sb __maybe_unused)
1facf9fc 12219+{
1308ab2a 12220+#if defined(CONFIG_OCFS2_FS) || defined(CONFIG_OCFS2_FS_MODULE)
12221+ return sb->s_magic == OCFS2_SUPER_MAGIC;
12222+#else
12223+ return 0;
12224+#endif
1facf9fc 12225+}
12226+
1308ab2a 12227+static inline int au_test_ocfs2_dlmfs(struct super_block *sb __maybe_unused)
1facf9fc 12228+{
1308ab2a 12229+#if defined(CONFIG_OCFS2_FS_O2CB) || defined(CONFIG_OCFS2_FS_O2CB_MODULE)
12230+ return sb->s_magic == DLMFS_MAGIC;
12231+#else
12232+ return 0;
12233+#endif
1facf9fc 12234+}
12235+
1308ab2a 12236+static inline int au_test_coda(struct super_block *sb __maybe_unused)
1facf9fc 12237+{
1308ab2a 12238+#if defined(CONFIG_CODA_FS) || defined(CONFIG_CODA_FS_MODULE)
12239+ return sb->s_magic == CODA_SUPER_MAGIC;
12240+#else
12241+ return 0;
12242+#endif
12243+}
12244+
12245+static inline int au_test_v9fs(struct super_block *sb __maybe_unused)
12246+{
12247+#if defined(CONFIG_9P_FS) || defined(CONFIG_9P_FS_MODULE)
12248+ return sb->s_magic == V9FS_MAGIC;
12249+#else
12250+ return 0;
12251+#endif
12252+}
12253+
12254+static inline int au_test_ext4(struct super_block *sb __maybe_unused)
12255+{
12256+#if defined(CONFIG_EXT4DEV_FS) || defined(CONFIG_EXT4DEV_FS_MODULE)
12257+ return sb->s_magic == EXT4_SUPER_MAGIC;
12258+#else
12259+ return 0;
12260+#endif
12261+}
12262+
12263+static inline int au_test_sysv(struct super_block *sb __maybe_unused)
12264+{
12265+#if defined(CONFIG_SYSV_FS) || defined(CONFIG_SYSV_FS_MODULE)
12266+ return !strcmp(au_sbtype(sb), "sysv");
12267+#else
12268+ return 0;
12269+#endif
12270+}
12271+
12272+static inline int au_test_ramfs(struct super_block *sb)
12273+{
12274+ return sb->s_magic == RAMFS_MAGIC;
12275+}
12276+
12277+static inline int au_test_ubifs(struct super_block *sb __maybe_unused)
12278+{
12279+#if defined(CONFIG_UBIFS_FS) || defined(CONFIG_UBIFS_FS_MODULE)
12280+ return sb->s_magic == UBIFS_SUPER_MAGIC;
12281+#else
12282+ return 0;
12283+#endif
12284+}
12285+
12286+static inline int au_test_procfs(struct super_block *sb __maybe_unused)
12287+{
12288+#ifdef CONFIG_PROC_FS
12289+ return sb->s_magic == PROC_SUPER_MAGIC;
12290+#else
12291+ return 0;
12292+#endif
12293+}
12294+
12295+static inline int au_test_sysfs(struct super_block *sb __maybe_unused)
12296+{
12297+#ifdef CONFIG_SYSFS
12298+ return sb->s_magic == SYSFS_MAGIC;
12299+#else
12300+ return 0;
12301+#endif
12302+}
12303+
12304+static inline int au_test_configfs(struct super_block *sb __maybe_unused)
12305+{
12306+#if defined(CONFIG_CONFIGFS_FS) || defined(CONFIG_CONFIGFS_FS_MODULE)
12307+ return sb->s_magic == CONFIGFS_MAGIC;
12308+#else
12309+ return 0;
12310+#endif
12311+}
12312+
12313+static inline int au_test_minix(struct super_block *sb __maybe_unused)
12314+{
12315+#if defined(CONFIG_MINIX_FS) || defined(CONFIG_MINIX_FS_MODULE)
12316+ return sb->s_magic == MINIX3_SUPER_MAGIC
12317+ || sb->s_magic == MINIX2_SUPER_MAGIC
12318+ || sb->s_magic == MINIX2_SUPER_MAGIC2
12319+ || sb->s_magic == MINIX_SUPER_MAGIC
12320+ || sb->s_magic == MINIX_SUPER_MAGIC2;
12321+#else
12322+ return 0;
12323+#endif
12324+}
12325+
12326+static inline int au_test_cifs(struct super_block *sb __maybe_unused)
12327+{
12328+#if defined(CONFIG_CIFS_FS) || defined(CONFIGCIFS_FS_MODULE)
12329+ return sb->s_magic == CIFS_MAGIC_NUMBER;
12330+#else
12331+ return 0;
12332+#endif
12333+}
12334+
12335+static inline int au_test_fat(struct super_block *sb __maybe_unused)
12336+{
12337+#if defined(CONFIG_FAT_FS) || defined(CONFIG_FAT_FS_MODULE)
12338+ return sb->s_magic == MSDOS_SUPER_MAGIC;
12339+#else
12340+ return 0;
12341+#endif
12342+}
12343+
12344+static inline int au_test_msdos(struct super_block *sb)
12345+{
12346+ return au_test_fat(sb);
12347+}
12348+
12349+static inline int au_test_vfat(struct super_block *sb)
12350+{
12351+ return au_test_fat(sb);
12352+}
12353+
12354+static inline int au_test_securityfs(struct super_block *sb __maybe_unused)
12355+{
12356+#ifdef CONFIG_SECURITYFS
12357+ return sb->s_magic == SECURITYFS_MAGIC;
12358+#else
12359+ return 0;
12360+#endif
12361+}
12362+
12363+static inline int au_test_squashfs(struct super_block *sb __maybe_unused)
12364+{
12365+#if defined(CONFIG_SQUASHFS) || defined(CONFIG_SQUASHFS_MODULE)
12366+ return sb->s_magic == SQUASHFS_MAGIC;
12367+#else
12368+ return 0;
12369+#endif
12370+}
12371+
12372+static inline int au_test_btrfs(struct super_block *sb __maybe_unused)
12373+{
12374+#if defined(CONFIG_BTRFS_FS) || defined(CONFIG_BTRFS_FS_MODULE)
12375+ return sb->s_magic == BTRFS_SUPER_MAGIC;
12376+#else
12377+ return 0;
12378+#endif
12379+}
12380+
12381+static inline int au_test_xenfs(struct super_block *sb __maybe_unused)
12382+{
12383+#if defined(CONFIG_XENFS) || defined(CONFIG_XENFS_MODULE)
12384+ return sb->s_magic == XENFS_SUPER_MAGIC;
12385+#else
12386+ return 0;
12387+#endif
12388+}
12389+
12390+static inline int au_test_debugfs(struct super_block *sb __maybe_unused)
12391+{
12392+#ifdef CONFIG_DEBUG_FS
12393+ return sb->s_magic == DEBUGFS_MAGIC;
12394+#else
12395+ return 0;
12396+#endif
12397+}
12398+
12399+static inline int au_test_nilfs(struct super_block *sb __maybe_unused)
12400+{
12401+#if defined(CONFIG_NILFS) || defined(CONFIG_NILFS_MODULE)
12402+ return sb->s_magic == NILFS_SUPER_MAGIC;
12403+#else
12404+ return 0;
12405+#endif
12406+}
12407+
4a4d8108
AM
12408+static inline int au_test_hfsplus(struct super_block *sb __maybe_unused)
12409+{
12410+#if defined(CONFIG_HFSPLUS_FS) || defined(CONFIG_HFSPLUS_FS_MODULE)
12411+ return sb->s_magic == HFSPLUS_SUPER_MAGIC;
12412+#else
12413+ return 0;
12414+#endif
12415+}
12416+
1308ab2a 12417+/* ---------------------------------------------------------------------- */
12418+/*
12419+ * they can't be an aufs branch.
12420+ */
12421+static inline int au_test_fs_unsuppoted(struct super_block *sb)
12422+{
12423+ return
12424+#ifndef CONFIG_AUFS_BR_RAMFS
12425+ au_test_ramfs(sb) ||
12426+#endif
12427+ au_test_procfs(sb)
12428+ || au_test_sysfs(sb)
12429+ || au_test_configfs(sb)
12430+ || au_test_debugfs(sb)
12431+ || au_test_securityfs(sb)
12432+ || au_test_xenfs(sb)
12433+ || au_test_ecryptfs(sb)
12434+ /* || !strcmp(au_sbtype(sb), "unionfs") */
12435+ || au_test_aufs(sb); /* will be supported in next version */
12436+}
12437+
12438+/*
12439+ * If the filesystem supports NFS-export, then it has to support NULL as
12440+ * a nameidata parameter for ->create(), ->lookup() and ->d_revalidate().
12441+ * We can apply this principle when we handle a lower filesystem.
12442+ */
12443+static inline int au_test_fs_null_nd(struct super_block *sb)
12444+{
12445+ return !!sb->s_export_op;
12446+}
12447+
12448+static inline int au_test_fs_remote(struct super_block *sb)
12449+{
12450+ return !au_test_tmpfs(sb)
12451+#ifdef CONFIG_AUFS_BR_RAMFS
12452+ && !au_test_ramfs(sb)
12453+#endif
12454+ && !(sb->s_type->fs_flags & FS_REQUIRES_DEV);
12455+}
12456+
12457+/* ---------------------------------------------------------------------- */
12458+
12459+/*
12460+ * Note: these functions (below) are created after reading ->getattr() in all
12461+ * filesystems under linux/fs. it means we have to do so in every update...
12462+ */
12463+
12464+/*
12465+ * some filesystems require getattr to refresh the inode attributes before
12466+ * referencing.
12467+ * in most cases, we can rely on the inode attribute in NFS (or every remote fs)
12468+ * and leave the work for d_revalidate()
12469+ */
12470+static inline int au_test_fs_refresh_iattr(struct super_block *sb)
12471+{
12472+ return au_test_nfs(sb)
12473+ || au_test_fuse(sb)
12474+ /* || au_test_smbfs(sb) */ /* untested */
12475+ /* || au_test_ocfs2(sb) */ /* untested */
12476+ /* || au_test_btrfs(sb) */ /* untested */
12477+ /* || au_test_coda(sb) */ /* untested */
12478+ /* || au_test_v9fs(sb) */ /* untested */
12479+ ;
12480+}
12481+
12482+/*
12483+ * filesystems which don't maintain i_size or i_blocks.
12484+ */
12485+static inline int au_test_fs_bad_iattr_size(struct super_block *sb)
12486+{
12487+ return au_test_xfs(sb)
4a4d8108
AM
12488+ || au_test_btrfs(sb)
12489+ || au_test_ubifs(sb)
12490+ || au_test_hfsplus(sb) /* maintained, but incorrect */
1308ab2a 12491+ /* || au_test_ext4(sb) */ /* untested */
12492+ /* || au_test_ocfs2(sb) */ /* untested */
12493+ /* || au_test_ocfs2_dlmfs(sb) */ /* untested */
12494+ /* || au_test_sysv(sb) */ /* untested */
1308ab2a 12495+ /* || au_test_minix(sb) */ /* untested */
12496+ ;
12497+}
12498+
12499+/*
12500+ * filesystems which don't store the correct value in some of their inode
12501+ * attributes.
12502+ */
12503+static inline int au_test_fs_bad_iattr(struct super_block *sb)
12504+{
12505+ return au_test_fs_bad_iattr_size(sb)
12506+ /* || au_test_cifs(sb) */ /* untested */
12507+ || au_test_fat(sb)
12508+ || au_test_msdos(sb)
12509+ || au_test_vfat(sb);
1facf9fc 12510+}
12511+
12512+/* they don't check i_nlink in link(2) */
12513+static inline int au_test_fs_no_limit_nlink(struct super_block *sb)
12514+{
12515+ return au_test_tmpfs(sb)
12516+#ifdef CONFIG_AUFS_BR_RAMFS
12517+ || au_test_ramfs(sb)
12518+#endif
4a4d8108
AM
12519+ || au_test_ubifs(sb)
12520+ || au_test_btrfs(sb)
12521+ || au_test_hfsplus(sb);
1facf9fc 12522+}
12523+
12524+/*
12525+ * filesystems which sets S_NOATIME and S_NOCMTIME.
12526+ */
12527+static inline int au_test_fs_notime(struct super_block *sb)
12528+{
12529+ return au_test_nfs(sb)
12530+ || au_test_fuse(sb)
dece6358 12531+ || au_test_ubifs(sb)
1facf9fc 12532+ /* || au_test_cifs(sb) */ /* untested */
1facf9fc 12533+ ;
12534+}
12535+
12536+/*
12537+ * filesystems which requires replacing i_mapping.
12538+ */
12539+static inline int au_test_fs_bad_mapping(struct super_block *sb)
12540+{
dece6358
AM
12541+ return au_test_fuse(sb)
12542+ || au_test_ubifs(sb);
1facf9fc 12543+}
12544+
12545+/* temporary support for i#1 in cramfs */
12546+static inline int au_test_fs_unique_ino(struct inode *inode)
12547+{
12548+ if (au_test_cramfs(inode->i_sb))
12549+ return inode->i_ino != 1;
12550+ return 1;
12551+}
12552+
12553+/* ---------------------------------------------------------------------- */
12554+
12555+/*
12556+ * the filesystem where the xino files placed must support i/o after unlink and
12557+ * maintain i_size and i_blocks.
12558+ */
12559+static inline int au_test_fs_bad_xino(struct super_block *sb)
12560+{
12561+ return au_test_fs_remote(sb)
12562+ || au_test_fs_bad_iattr_size(sb)
12563+#ifdef CONFIG_AUFS_BR_RAMFS
12564+ || !(au_test_ramfs(sb) || au_test_fs_null_nd(sb))
12565+#else
12566+ || !au_test_fs_null_nd(sb) /* to keep xino code simple */
12567+#endif
12568+ /* don't want unnecessary work for xino */
12569+ || au_test_aufs(sb)
1308ab2a 12570+ || au_test_ecryptfs(sb)
12571+ || au_test_nilfs(sb);
1facf9fc 12572+}
12573+
12574+static inline int au_test_fs_trunc_xino(struct super_block *sb)
12575+{
12576+ return au_test_tmpfs(sb)
12577+ || au_test_ramfs(sb);
12578+}
12579+
12580+/*
12581+ * test if the @sb is real-readonly.
12582+ */
12583+static inline int au_test_fs_rr(struct super_block *sb)
12584+{
12585+ return au_test_squashfs(sb)
12586+ || au_test_iso9660(sb)
12587+ || au_test_cramfs(sb)
12588+ || au_test_romfs(sb);
12589+}
12590+
12591+#endif /* __KERNEL__ */
12592+#endif /* __AUFS_FSTYPE_H__ */
7f207e10
AM
12593diff -urN /usr/share/empty/fs/aufs/hfsnotify.c linux/fs/aufs/hfsnotify.c
12594--- /usr/share/empty/fs/aufs/hfsnotify.c 1970-01-01 01:00:00.000000000 +0100
0c3ec466
AM
12595+++ linux/fs/aufs/hfsnotify.c 2012-07-22 19:57:03.164337936 +0200
12596@@ -0,0 +1,257 @@
1facf9fc 12597+/*
f6c5ef8b 12598+ * Copyright (C) 2005-2012 Junjiro R. Okajima
1facf9fc 12599+ *
12600+ * This program, aufs is free software; you can redistribute it and/or modify
12601+ * it under the terms of the GNU General Public License as published by
12602+ * the Free Software Foundation; either version 2 of the License, or
12603+ * (at your option) any later version.
dece6358
AM
12604+ *
12605+ * This program is distributed in the hope that it will be useful,
12606+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
12607+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12608+ * GNU General Public License for more details.
12609+ *
12610+ * You should have received a copy of the GNU General Public License
12611+ * along with this program; if not, write to the Free Software
12612+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 12613+ */
12614+
12615+/*
4a4d8108 12616+ * fsnotify for the lower directories
1facf9fc 12617+ */
12618+
12619+#include "aufs.h"
12620+
4a4d8108
AM
12621+/* FS_IN_IGNORED is unnecessary */
12622+static const __u32 AuHfsnMask = (FS_MOVED_TO | FS_MOVED_FROM | FS_DELETE
12623+ | FS_CREATE | FS_EVENT_ON_CHILD);
7f207e10 12624+static DECLARE_WAIT_QUEUE_HEAD(au_hfsn_wq);
7eafdf33 12625+static __cacheline_aligned_in_smp atomic64_t au_hfsn_ifree = ATOMIC64_INIT(0);
1facf9fc 12626+
0c5527e5 12627+static void au_hfsn_free_mark(struct fsnotify_mark *mark)
1facf9fc 12628+{
0c5527e5
AM
12629+ struct au_hnotify *hn = container_of(mark, struct au_hnotify,
12630+ hn_mark);
4a4d8108 12631+ AuDbg("here\n");
7eafdf33
AM
12632+ au_cache_free_hnotify(hn);
12633+ smp_mb__before_atomic_dec();
12634+ atomic64_dec(&au_hfsn_ifree);
12635+ wake_up(&au_hfsn_wq);
4a4d8108 12636+}
1facf9fc 12637+
027c5e7a 12638+static int au_hfsn_alloc(struct au_hinode *hinode)
4a4d8108 12639+{
027c5e7a
AM
12640+ struct au_hnotify *hn;
12641+ struct super_block *sb;
12642+ struct au_branch *br;
0c5527e5 12643+ struct fsnotify_mark *mark;
027c5e7a 12644+ aufs_bindex_t bindex;
1facf9fc 12645+
027c5e7a
AM
12646+ hn = hinode->hi_notify;
12647+ sb = hn->hn_aufs_inode->i_sb;
12648+ bindex = au_br_index(sb, hinode->hi_id);
12649+ br = au_sbr(sb, bindex);
0c5527e5
AM
12650+ mark = &hn->hn_mark;
12651+ fsnotify_init_mark(mark, au_hfsn_free_mark);
12652+ mark->mask = AuHfsnMask;
7f207e10
AM
12653+ /*
12654+ * by udba rename or rmdir, aufs assign a new inode to the known
12655+ * h_inode, so specify 1 to allow dups.
12656+ */
027c5e7a
AM
12657+ return fsnotify_add_mark(mark, br->br_hfsn_group, hinode->hi_inode,
12658+ /*mnt*/NULL, /*allow_dups*/1);
1facf9fc 12659+}
12660+
7eafdf33 12661+static int au_hfsn_free(struct au_hinode *hinode, struct au_hnotify *hn)
1facf9fc 12662+{
0c5527e5 12663+ struct fsnotify_mark *mark;
7eafdf33
AM
12664+ unsigned long long ull;
12665+
12666+ ull = atomic64_inc_return(&au_hfsn_ifree);
12667+ BUG_ON(!ull);
953406b4 12668+
0c5527e5
AM
12669+ mark = &hn->hn_mark;
12670+ fsnotify_destroy_mark(mark);
12671+ fsnotify_put_mark(mark);
7f207e10 12672+
7eafdf33
AM
12673+ /* free hn by myself */
12674+ return 0;
1facf9fc 12675+}
12676+
12677+/* ---------------------------------------------------------------------- */
12678+
4a4d8108 12679+static void au_hfsn_ctl(struct au_hinode *hinode, int do_set)
1facf9fc 12680+{
0c5527e5 12681+ struct fsnotify_mark *mark;
1facf9fc 12682+
0c5527e5
AM
12683+ mark = &hinode->hi_notify->hn_mark;
12684+ spin_lock(&mark->lock);
1facf9fc 12685+ if (do_set) {
0c5527e5
AM
12686+ AuDebugOn(mark->mask & AuHfsnMask);
12687+ mark->mask |= AuHfsnMask;
1facf9fc 12688+ } else {
0c5527e5
AM
12689+ AuDebugOn(!(mark->mask & AuHfsnMask));
12690+ mark->mask &= ~AuHfsnMask;
1facf9fc 12691+ }
0c5527e5 12692+ spin_unlock(&mark->lock);
4a4d8108 12693+ /* fsnotify_recalc_inode_mask(hinode->hi_inode); */
1facf9fc 12694+}
12695+
4a4d8108 12696+/* ---------------------------------------------------------------------- */
1facf9fc 12697+
4a4d8108
AM
12698+/* #define AuDbgHnotify */
12699+#ifdef AuDbgHnotify
12700+static char *au_hfsn_name(u32 mask)
12701+{
12702+#ifdef CONFIG_AUFS_DEBUG
12703+#define test_ret(flag) if (mask & flag) \
12704+ return #flag;
12705+ test_ret(FS_ACCESS);
12706+ test_ret(FS_MODIFY);
12707+ test_ret(FS_ATTRIB);
12708+ test_ret(FS_CLOSE_WRITE);
12709+ test_ret(FS_CLOSE_NOWRITE);
12710+ test_ret(FS_OPEN);
12711+ test_ret(FS_MOVED_FROM);
12712+ test_ret(FS_MOVED_TO);
12713+ test_ret(FS_CREATE);
12714+ test_ret(FS_DELETE);
12715+ test_ret(FS_DELETE_SELF);
12716+ test_ret(FS_MOVE_SELF);
12717+ test_ret(FS_UNMOUNT);
12718+ test_ret(FS_Q_OVERFLOW);
12719+ test_ret(FS_IN_IGNORED);
12720+ test_ret(FS_IN_ISDIR);
12721+ test_ret(FS_IN_ONESHOT);
12722+ test_ret(FS_EVENT_ON_CHILD);
12723+ return "";
12724+#undef test_ret
12725+#else
12726+ return "??";
12727+#endif
1facf9fc 12728+}
4a4d8108 12729+#endif
1facf9fc 12730+
12731+/* ---------------------------------------------------------------------- */
12732+
4a4d8108 12733+static int au_hfsn_handle_event(struct fsnotify_group *group,
0c5527e5
AM
12734+ struct fsnotify_mark *inode_mark,
12735+ struct fsnotify_mark *vfsmount_mark,
4a4d8108 12736+ struct fsnotify_event *event)
1facf9fc 12737+{
12738+ int err;
4a4d8108
AM
12739+ struct au_hnotify *hnotify;
12740+ struct inode *h_dir, *h_inode;
12741+ __u32 mask;
0c3ec466 12742+ struct qstr h_child_qstr = QSTR_INIT(event->file_name, event->name_len);
4a4d8108
AM
12743+
12744+ AuDebugOn(event->data_type != FSNOTIFY_EVENT_INODE);
1facf9fc 12745+
12746+ err = 0;
0c5527e5 12747+ /* if FS_UNMOUNT happens, there must be another bug */
4a4d8108
AM
12748+ mask = event->mask;
12749+ AuDebugOn(mask & FS_UNMOUNT);
0c5527e5 12750+ if (mask & (FS_IN_IGNORED | FS_UNMOUNT))
1facf9fc 12751+ goto out;
1facf9fc 12752+
4a4d8108
AM
12753+ h_dir = event->to_tell;
12754+ h_inode = event->inode;
12755+#ifdef AuDbgHnotify
12756+ au_debug(1);
12757+ if (1 || h_child_qstr.len != sizeof(AUFS_XINO_FNAME) - 1
12758+ || strncmp(h_child_qstr.name, AUFS_XINO_FNAME, h_child_qstr.len)) {
12759+ AuDbg("i%lu, mask 0x%x %s, hcname %.*s, hi%lu\n",
12760+ h_dir->i_ino, mask, au_hfsn_name(mask),
12761+ AuLNPair(&h_child_qstr), h_inode ? h_inode->i_ino : 0);
12762+ /* WARN_ON(1); */
1facf9fc 12763+ }
4a4d8108 12764+ au_debug(0);
1facf9fc 12765+#endif
4a4d8108 12766+
0c5527e5
AM
12767+ AuDebugOn(!inode_mark);
12768+ hnotify = container_of(inode_mark, struct au_hnotify, hn_mark);
12769+ err = au_hnotify(h_dir, hnotify, mask, &h_child_qstr, h_inode);
1facf9fc 12770+
4a4d8108
AM
12771+out:
12772+ return err;
12773+}
1facf9fc 12774+
027c5e7a 12775+/* isn't it waste to ask every registered 'group'? */
7f207e10 12776+/* copied from linux/fs/notify/inotify/inotify_fsnotiry.c */
4a4d8108 12777+/* it should be exported to modules */
7f207e10
AM
12778+static bool au_hfsn_should_send_event(struct fsnotify_group *group,
12779+ struct inode *h_inode,
0c5527e5
AM
12780+ struct fsnotify_mark *inode_mark,
12781+ struct fsnotify_mark *vfsmount_mark,
12782+ __u32 mask, void *data, int data_type)
4a4d8108 12783+{
4a4d8108 12784+ mask = (mask & ~FS_EVENT_ON_CHILD);
7f207e10 12785+ return inode_mark->mask & mask;
4a4d8108
AM
12786+}
12787+
12788+static struct fsnotify_ops au_hfsn_ops = {
12789+ .should_send_event = au_hfsn_should_send_event,
12790+ .handle_event = au_hfsn_handle_event
12791+};
12792+
12793+/* ---------------------------------------------------------------------- */
12794+
027c5e7a
AM
12795+static void au_hfsn_fin_br(struct au_branch *br)
12796+{
12797+ if (br->br_hfsn_group)
12798+ fsnotify_put_group(br->br_hfsn_group);
12799+}
12800+
12801+static int au_hfsn_init_br(struct au_branch *br, int perm)
12802+{
12803+ br->br_hfsn_group = NULL;
12804+ br->br_hfsn_ops = au_hfsn_ops;
12805+ return 0;
12806+}
12807+
12808+static int au_hfsn_reset_br(unsigned int udba, struct au_branch *br, int perm)
4a4d8108
AM
12809+{
12810+ int err;
1facf9fc 12811+
4a4d8108 12812+ err = 0;
027c5e7a
AM
12813+ if (udba != AuOpt_UDBA_HNOTIFY
12814+ || !au_br_hnotifyable(perm)) {
12815+ au_hfsn_fin_br(br);
12816+ br->br_hfsn_group = NULL;
12817+ goto out;
12818+ }
12819+
12820+ if (br->br_hfsn_group)
12821+ goto out;
12822+
12823+ br->br_hfsn_group = fsnotify_alloc_group(&br->br_hfsn_ops);
12824+ if (IS_ERR(br->br_hfsn_group)) {
12825+ err = PTR_ERR(br->br_hfsn_group);
0c5527e5 12826+ pr_err("fsnotify_alloc_group() failed, %d\n", err);
027c5e7a 12827+ br->br_hfsn_group = NULL;
4a4d8108 12828+ }
1facf9fc 12829+
027c5e7a 12830+out:
1facf9fc 12831+ AuTraceErr(err);
12832+ return err;
12833+}
12834+
7eafdf33
AM
12835+/* ---------------------------------------------------------------------- */
12836+
12837+static void au_hfsn_fin(void)
12838+{
12839+ AuDbg("au_hfsn_ifree %lld\n", (long long)atomic64_read(&au_hfsn_ifree));
12840+ wait_event(au_hfsn_wq, !atomic64_read(&au_hfsn_ifree));
12841+}
12842+
4a4d8108
AM
12843+const struct au_hnotify_op au_hnotify_op = {
12844+ .ctl = au_hfsn_ctl,
12845+ .alloc = au_hfsn_alloc,
12846+ .free = au_hfsn_free,
1facf9fc 12847+
7eafdf33
AM
12848+ .fin = au_hfsn_fin,
12849+
027c5e7a
AM
12850+ .reset_br = au_hfsn_reset_br,
12851+ .fin_br = au_hfsn_fin_br,
12852+ .init_br = au_hfsn_init_br
4a4d8108 12853+};
7f207e10
AM
12854diff -urN /usr/share/empty/fs/aufs/hfsplus.c linux/fs/aufs/hfsplus.c
12855--- /usr/share/empty/fs/aufs/hfsplus.c 1970-01-01 01:00:00.000000000 +0100
0c3ec466 12856+++ linux/fs/aufs/hfsplus.c 2012-07-22 19:57:03.164337936 +0200
f6c5ef8b 12857@@ -0,0 +1,57 @@
4a4d8108 12858+/*
f6c5ef8b 12859+ * Copyright (C) 2010-2012 Junjiro R. Okajima
4a4d8108
AM
12860+ *
12861+ * This program, aufs is free software; you can redistribute it and/or modify
12862+ * it under the terms of the GNU General Public License as published by
12863+ * the Free Software Foundation; either version 2 of the License, or
12864+ * (at your option) any later version.
12865+ *
12866+ * This program is distributed in the hope that it will be useful,
12867+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
12868+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12869+ * GNU General Public License for more details.
12870+ *
12871+ * You should have received a copy of the GNU General Public License
12872+ * along with this program; if not, write to the Free Software
12873+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
12874+ */
1facf9fc 12875+
4a4d8108
AM
12876+/*
12877+ * special support for filesystems which aqucires an inode mutex
12878+ * at final closing a file, eg, hfsplus.
12879+ *
12880+ * This trick is very simple and stupid, just to open the file before really
12881+ * neceeary open to tell hfsplus that this is not the final closing.
12882+ * The caller should call au_h_open_pre() after acquiring the inode mutex,
12883+ * and au_h_open_post() after releasing it.
12884+ */
1facf9fc 12885+
4a4d8108 12886+#include "aufs.h"
1facf9fc 12887+
4a4d8108
AM
12888+struct file *au_h_open_pre(struct dentry *dentry, aufs_bindex_t bindex)
12889+{
12890+ struct file *h_file;
12891+ struct dentry *h_dentry;
1facf9fc 12892+
4a4d8108
AM
12893+ h_dentry = au_h_dptr(dentry, bindex);
12894+ AuDebugOn(!h_dentry);
12895+ AuDebugOn(!h_dentry->d_inode);
12896+ IMustLock(h_dentry->d_inode);
12897+
12898+ h_file = NULL;
12899+ if (au_test_hfsplus(h_dentry->d_sb)
12900+ && S_ISREG(h_dentry->d_inode->i_mode))
12901+ h_file = au_h_open(dentry, bindex,
12902+ O_RDONLY | O_NOATIME | O_LARGEFILE,
12903+ /*file*/NULL);
12904+ return h_file;
1facf9fc 12905+}
12906+
4a4d8108
AM
12907+void au_h_open_post(struct dentry *dentry, aufs_bindex_t bindex,
12908+ struct file *h_file)
12909+{
12910+ if (h_file) {
12911+ fput(h_file);
12912+ au_sbr_put(dentry->d_sb, bindex);
12913+ }
12914+}
7f207e10
AM
12915diff -urN /usr/share/empty/fs/aufs/hnotify.c linux/fs/aufs/hnotify.c
12916--- /usr/share/empty/fs/aufs/hnotify.c 1970-01-01 01:00:00.000000000 +0100
0c3ec466 12917+++ linux/fs/aufs/hnotify.c 2012-07-22 19:57:03.164337936 +0200
53392da6 12918@@ -0,0 +1,712 @@
e49829fe 12919+/*
f6c5ef8b 12920+ * Copyright (C) 2005-2012 Junjiro R. Okajima
e49829fe
JR
12921+ *
12922+ * This program, aufs is free software; you can redistribute it and/or modify
12923+ * it under the terms of the GNU General Public License as published by
12924+ * the Free Software Foundation; either version 2 of the License, or
12925+ * (at your option) any later version.
12926+ *
12927+ * This program is distributed in the hope that it will be useful,
12928+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
12929+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12930+ * GNU General Public License for more details.
12931+ *
12932+ * You should have received a copy of the GNU General Public License
12933+ * along with this program; if not, write to the Free Software
12934+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
12935+ */
12936+
12937+/*
7f207e10 12938+ * abstraction to notify the direct changes on lower directories
e49829fe
JR
12939+ */
12940+
12941+#include "aufs.h"
12942+
027c5e7a 12943+int au_hn_alloc(struct au_hinode *hinode, struct inode *inode)
e49829fe
JR
12944+{
12945+ int err;
7f207e10 12946+ struct au_hnotify *hn;
1facf9fc 12947+
4a4d8108
AM
12948+ err = -ENOMEM;
12949+ hn = au_cache_alloc_hnotify();
12950+ if (hn) {
12951+ hn->hn_aufs_inode = inode;
027c5e7a
AM
12952+ hinode->hi_notify = hn;
12953+ err = au_hnotify_op.alloc(hinode);
12954+ AuTraceErr(err);
12955+ if (unlikely(err)) {
12956+ hinode->hi_notify = NULL;
4a4d8108
AM
12957+ au_cache_free_hnotify(hn);
12958+ /*
12959+ * The upper dir was removed by udba, but the same named
12960+ * dir left. In this case, aufs assignes a new inode
12961+ * number and set the monitor again.
12962+ * For the lower dir, the old monitnor is still left.
12963+ */
12964+ if (err == -EEXIST)
12965+ err = 0;
12966+ }
1308ab2a 12967+ }
1308ab2a 12968+
027c5e7a 12969+ AuTraceErr(err);
1308ab2a 12970+ return err;
dece6358 12971+}
1facf9fc 12972+
4a4d8108 12973+void au_hn_free(struct au_hinode *hinode)
dece6358 12974+{
4a4d8108 12975+ struct au_hnotify *hn;
1facf9fc 12976+
4a4d8108
AM
12977+ hn = hinode->hi_notify;
12978+ if (hn) {
4a4d8108 12979+ hinode->hi_notify = NULL;
7eafdf33
AM
12980+ if (au_hnotify_op.free(hinode, hn))
12981+ au_cache_free_hnotify(hn);
4a4d8108
AM
12982+ }
12983+}
dece6358 12984+
4a4d8108 12985+/* ---------------------------------------------------------------------- */
dece6358 12986+
4a4d8108
AM
12987+void au_hn_ctl(struct au_hinode *hinode, int do_set)
12988+{
12989+ if (hinode->hi_notify)
12990+ au_hnotify_op.ctl(hinode, do_set);
12991+}
12992+
12993+void au_hn_reset(struct inode *inode, unsigned int flags)
12994+{
12995+ aufs_bindex_t bindex, bend;
12996+ struct inode *hi;
12997+ struct dentry *iwhdentry;
1facf9fc 12998+
1308ab2a 12999+ bend = au_ibend(inode);
4a4d8108
AM
13000+ for (bindex = au_ibstart(inode); bindex <= bend; bindex++) {
13001+ hi = au_h_iptr(inode, bindex);
13002+ if (!hi)
13003+ continue;
1308ab2a 13004+
4a4d8108
AM
13005+ /* mutex_lock_nested(&hi->i_mutex, AuLsc_I_CHILD); */
13006+ iwhdentry = au_hi_wh(inode, bindex);
13007+ if (iwhdentry)
13008+ dget(iwhdentry);
13009+ au_igrab(hi);
13010+ au_set_h_iptr(inode, bindex, NULL, 0);
13011+ au_set_h_iptr(inode, bindex, au_igrab(hi),
13012+ flags & ~AuHi_XINO);
13013+ iput(hi);
13014+ dput(iwhdentry);
13015+ /* mutex_unlock(&hi->i_mutex); */
1facf9fc 13016+ }
1facf9fc 13017+}
13018+
1308ab2a 13019+/* ---------------------------------------------------------------------- */
1facf9fc 13020+
4a4d8108 13021+static int hn_xino(struct inode *inode, struct inode *h_inode)
1facf9fc 13022+{
4a4d8108
AM
13023+ int err;
13024+ aufs_bindex_t bindex, bend, bfound, bstart;
13025+ struct inode *h_i;
1facf9fc 13026+
4a4d8108
AM
13027+ err = 0;
13028+ if (unlikely(inode->i_ino == AUFS_ROOT_INO)) {
0c3ec466 13029+ pr_warn("branch root dir was changed\n");
4a4d8108
AM
13030+ goto out;
13031+ }
1facf9fc 13032+
4a4d8108
AM
13033+ bfound = -1;
13034+ bend = au_ibend(inode);
13035+ bstart = au_ibstart(inode);
13036+#if 0 /* reserved for future use */
13037+ if (bindex == bend) {
13038+ /* keep this ino in rename case */
13039+ goto out;
13040+ }
13041+#endif
13042+ for (bindex = bstart; bindex <= bend; bindex++)
13043+ if (au_h_iptr(inode, bindex) == h_inode) {
13044+ bfound = bindex;
13045+ break;
13046+ }
13047+ if (bfound < 0)
1308ab2a 13048+ goto out;
1facf9fc 13049+
4a4d8108
AM
13050+ for (bindex = bstart; bindex <= bend; bindex++) {
13051+ h_i = au_h_iptr(inode, bindex);
13052+ if (!h_i)
13053+ continue;
1facf9fc 13054+
4a4d8108
AM
13055+ err = au_xino_write(inode->i_sb, bindex, h_i->i_ino, /*ino*/0);
13056+ /* ignore this error */
13057+ /* bad action? */
1facf9fc 13058+ }
1facf9fc 13059+
4a4d8108 13060+ /* children inode number will be broken */
1facf9fc 13061+
4f0767ce 13062+out:
4a4d8108
AM
13063+ AuTraceErr(err);
13064+ return err;
1facf9fc 13065+}
13066+
4a4d8108 13067+static int hn_gen_tree(struct dentry *dentry)
1facf9fc 13068+{
4a4d8108
AM
13069+ int err, i, j, ndentry;
13070+ struct au_dcsub_pages dpages;
13071+ struct au_dpage *dpage;
13072+ struct dentry **dentries;
1facf9fc 13073+
4a4d8108
AM
13074+ err = au_dpages_init(&dpages, GFP_NOFS);
13075+ if (unlikely(err))
13076+ goto out;
13077+ err = au_dcsub_pages(&dpages, dentry, NULL, NULL);
13078+ if (unlikely(err))
13079+ goto out_dpages;
1facf9fc 13080+
4a4d8108
AM
13081+ for (i = 0; i < dpages.ndpage; i++) {
13082+ dpage = dpages.dpages + i;
13083+ dentries = dpage->dentries;
13084+ ndentry = dpage->ndentry;
13085+ for (j = 0; j < ndentry; j++) {
13086+ struct dentry *d;
13087+
13088+ d = dentries[j];
13089+ if (IS_ROOT(d))
13090+ continue;
13091+
4a4d8108
AM
13092+ au_digen_dec(d);
13093+ if (d->d_inode)
13094+ /* todo: reset children xino?
13095+ cached children only? */
13096+ au_iigen_dec(d->d_inode);
1308ab2a 13097+ }
dece6358 13098+ }
1facf9fc 13099+
4f0767ce 13100+out_dpages:
4a4d8108 13101+ au_dpages_free(&dpages);
dece6358 13102+
027c5e7a 13103+#if 0
4a4d8108
AM
13104+ /* discard children */
13105+ dentry_unhash(dentry);
13106+ dput(dentry);
027c5e7a 13107+#endif
4f0767ce 13108+out:
dece6358
AM
13109+ return err;
13110+}
13111+
1308ab2a 13112+/*
4a4d8108 13113+ * return 0 if processed.
1308ab2a 13114+ */
4a4d8108
AM
13115+static int hn_gen_by_inode(char *name, unsigned int nlen, struct inode *inode,
13116+ const unsigned int isdir)
dece6358 13117+{
1308ab2a 13118+ int err;
4a4d8108
AM
13119+ struct dentry *d;
13120+ struct qstr *dname;
1facf9fc 13121+
4a4d8108
AM
13122+ err = 1;
13123+ if (unlikely(inode->i_ino == AUFS_ROOT_INO)) {
0c3ec466 13124+ pr_warn("branch root dir was changed\n");
4a4d8108
AM
13125+ err = 0;
13126+ goto out;
13127+ }
dece6358 13128+
4a4d8108
AM
13129+ if (!isdir) {
13130+ AuDebugOn(!name);
13131+ au_iigen_dec(inode);
027c5e7a 13132+ spin_lock(&inode->i_lock);
4a4d8108 13133+ list_for_each_entry(d, &inode->i_dentry, d_alias) {
027c5e7a 13134+ spin_lock(&d->d_lock);
4a4d8108
AM
13135+ dname = &d->d_name;
13136+ if (dname->len != nlen
027c5e7a
AM
13137+ && memcmp(dname->name, name, nlen)) {
13138+ spin_unlock(&d->d_lock);
4a4d8108 13139+ continue;
027c5e7a 13140+ }
4a4d8108 13141+ err = 0;
4a4d8108
AM
13142+ au_digen_dec(d);
13143+ spin_unlock(&d->d_lock);
13144+ break;
1facf9fc 13145+ }
027c5e7a 13146+ spin_unlock(&inode->i_lock);
1308ab2a 13147+ } else {
027c5e7a 13148+ au_fset_si(au_sbi(inode->i_sb), FAILED_REFRESH_DIR);
4a4d8108
AM
13149+ d = d_find_alias(inode);
13150+ if (!d) {
13151+ au_iigen_dec(inode);
13152+ goto out;
13153+ }
1facf9fc 13154+
027c5e7a 13155+ spin_lock(&d->d_lock);
4a4d8108 13156+ dname = &d->d_name;
027c5e7a
AM
13157+ if (dname->len == nlen && !memcmp(dname->name, name, nlen)) {
13158+ spin_unlock(&d->d_lock);
4a4d8108 13159+ err = hn_gen_tree(d);
027c5e7a
AM
13160+ spin_lock(&d->d_lock);
13161+ }
13162+ spin_unlock(&d->d_lock);
4a4d8108
AM
13163+ dput(d);
13164+ }
1facf9fc 13165+
4f0767ce 13166+out:
4a4d8108 13167+ AuTraceErr(err);
1308ab2a 13168+ return err;
13169+}
dece6358 13170+
4a4d8108 13171+static int hn_gen_by_name(struct dentry *dentry, const unsigned int isdir)
1facf9fc 13172+{
4a4d8108
AM
13173+ int err;
13174+ struct inode *inode;
1facf9fc 13175+
4a4d8108
AM
13176+ inode = dentry->d_inode;
13177+ if (IS_ROOT(dentry)
13178+ /* || (inode && inode->i_ino == AUFS_ROOT_INO) */
13179+ ) {
0c3ec466 13180+ pr_warn("branch root dir was changed\n");
4a4d8108
AM
13181+ return 0;
13182+ }
1308ab2a 13183+
4a4d8108
AM
13184+ err = 0;
13185+ if (!isdir) {
4a4d8108
AM
13186+ au_digen_dec(dentry);
13187+ if (inode)
13188+ au_iigen_dec(inode);
13189+ } else {
027c5e7a 13190+ au_fset_si(au_sbi(dentry->d_sb), FAILED_REFRESH_DIR);
4a4d8108
AM
13191+ if (inode)
13192+ err = hn_gen_tree(dentry);
13193+ }
13194+
13195+ AuTraceErr(err);
13196+ return err;
1facf9fc 13197+}
13198+
4a4d8108 13199+/* ---------------------------------------------------------------------- */
1facf9fc 13200+
4a4d8108
AM
13201+/* hnotify job flags */
13202+#define AuHnJob_XINO0 1
13203+#define AuHnJob_GEN (1 << 1)
13204+#define AuHnJob_DIRENT (1 << 2)
13205+#define AuHnJob_ISDIR (1 << 3)
13206+#define AuHnJob_TRYXINO0 (1 << 4)
13207+#define AuHnJob_MNTPNT (1 << 5)
13208+#define au_ftest_hnjob(flags, name) ((flags) & AuHnJob_##name)
7f207e10
AM
13209+#define au_fset_hnjob(flags, name) \
13210+ do { (flags) |= AuHnJob_##name; } while (0)
13211+#define au_fclr_hnjob(flags, name) \
13212+ do { (flags) &= ~AuHnJob_##name; } while (0)
1facf9fc 13213+
4a4d8108
AM
13214+enum {
13215+ AuHn_CHILD,
13216+ AuHn_PARENT,
13217+ AuHnLast
13218+};
1facf9fc 13219+
4a4d8108
AM
13220+struct au_hnotify_args {
13221+ struct inode *h_dir, *dir, *h_child_inode;
13222+ u32 mask;
13223+ unsigned int flags[AuHnLast];
13224+ unsigned int h_child_nlen;
13225+ char h_child_name[];
13226+};
1facf9fc 13227+
4a4d8108
AM
13228+struct hn_job_args {
13229+ unsigned int flags;
13230+ struct inode *inode, *h_inode, *dir, *h_dir;
13231+ struct dentry *dentry;
13232+ char *h_name;
13233+ int h_nlen;
13234+};
1308ab2a 13235+
4a4d8108
AM
13236+static int hn_job(struct hn_job_args *a)
13237+{
13238+ const unsigned int isdir = au_ftest_hnjob(a->flags, ISDIR);
1308ab2a 13239+
4a4d8108
AM
13240+ /* reset xino */
13241+ if (au_ftest_hnjob(a->flags, XINO0) && a->inode)
13242+ hn_xino(a->inode, a->h_inode); /* ignore this error */
1308ab2a 13243+
4a4d8108
AM
13244+ if (au_ftest_hnjob(a->flags, TRYXINO0)
13245+ && a->inode
13246+ && a->h_inode) {
13247+ mutex_lock_nested(&a->h_inode->i_mutex, AuLsc_I_CHILD);
13248+ if (!a->h_inode->i_nlink)
13249+ hn_xino(a->inode, a->h_inode); /* ignore this error */
13250+ mutex_unlock(&a->h_inode->i_mutex);
1308ab2a 13251+ }
1facf9fc 13252+
4a4d8108
AM
13253+ /* make the generation obsolete */
13254+ if (au_ftest_hnjob(a->flags, GEN)) {
13255+ int err = -1;
13256+ if (a->inode)
13257+ err = hn_gen_by_inode(a->h_name, a->h_nlen, a->inode,
13258+ isdir);
13259+ if (err && a->dentry)
13260+ hn_gen_by_name(a->dentry, isdir);
13261+ /* ignore this error */
1facf9fc 13262+ }
1facf9fc 13263+
4a4d8108
AM
13264+ /* make dir entries obsolete */
13265+ if (au_ftest_hnjob(a->flags, DIRENT) && a->inode) {
13266+ struct au_vdir *vdir;
1facf9fc 13267+
4a4d8108
AM
13268+ vdir = au_ivdir(a->inode);
13269+ if (vdir)
13270+ vdir->vd_jiffy = 0;
13271+ /* IMustLock(a->inode); */
13272+ /* a->inode->i_version++; */
13273+ }
1facf9fc 13274+
4a4d8108
AM
13275+ /* can do nothing but warn */
13276+ if (au_ftest_hnjob(a->flags, MNTPNT)
13277+ && a->dentry
13278+ && d_mountpoint(a->dentry))
0c3ec466
AM
13279+ pr_warn("mount-point %.*s is removed or renamed\n",
13280+ AuDLNPair(a->dentry));
1facf9fc 13281+
4a4d8108 13282+ return 0;
1308ab2a 13283+}
1facf9fc 13284+
1308ab2a 13285+/* ---------------------------------------------------------------------- */
1facf9fc 13286+
4a4d8108
AM
13287+static struct dentry *lookup_wlock_by_name(char *name, unsigned int nlen,
13288+ struct inode *dir)
1308ab2a 13289+{
4a4d8108
AM
13290+ struct dentry *dentry, *d, *parent;
13291+ struct qstr *dname;
1308ab2a 13292+
4a4d8108
AM
13293+ parent = d_find_alias(dir);
13294+ if (!parent)
13295+ return NULL;
1308ab2a 13296+
4a4d8108 13297+ dentry = NULL;
027c5e7a 13298+ spin_lock(&parent->d_lock);
4a4d8108
AM
13299+ list_for_each_entry(d, &parent->d_subdirs, d_u.d_child) {
13300+ /* AuDbg("%.*s\n", AuDLNPair(d)); */
027c5e7a 13301+ spin_lock_nested(&d->d_lock, DENTRY_D_LOCK_NESTED);
4a4d8108
AM
13302+ dname = &d->d_name;
13303+ if (dname->len != nlen || memcmp(dname->name, name, nlen))
027c5e7a
AM
13304+ goto cont_unlock;
13305+ if (au_di(d))
13306+ au_digen_dec(d);
13307+ else
13308+ goto cont_unlock;
13309+ if (d->d_count) {
13310+ dentry = dget_dlock(d);
4a4d8108 13311+ spin_unlock(&d->d_lock);
027c5e7a 13312+ break;
dece6358 13313+ }
1facf9fc 13314+
027c5e7a
AM
13315+ cont_unlock:
13316+ spin_unlock(&d->d_lock);
1308ab2a 13317+ }
027c5e7a 13318+ spin_unlock(&parent->d_lock);
4a4d8108 13319+ dput(parent);
1facf9fc 13320+
4a4d8108
AM
13321+ if (dentry)
13322+ di_write_lock_child(dentry);
1308ab2a 13323+
4a4d8108
AM
13324+ return dentry;
13325+}
dece6358 13326+
4a4d8108
AM
13327+static struct inode *lookup_wlock_by_ino(struct super_block *sb,
13328+ aufs_bindex_t bindex, ino_t h_ino)
13329+{
13330+ struct inode *inode;
13331+ ino_t ino;
13332+ int err;
13333+
13334+ inode = NULL;
13335+ err = au_xino_read(sb, bindex, h_ino, &ino);
13336+ if (!err && ino)
13337+ inode = ilookup(sb, ino);
13338+ if (!inode)
13339+ goto out;
13340+
13341+ if (unlikely(inode->i_ino == AUFS_ROOT_INO)) {
0c3ec466 13342+ pr_warn("wrong root branch\n");
4a4d8108
AM
13343+ iput(inode);
13344+ inode = NULL;
13345+ goto out;
1308ab2a 13346+ }
13347+
4a4d8108 13348+ ii_write_lock_child(inode);
1308ab2a 13349+
4f0767ce 13350+out:
4a4d8108 13351+ return inode;
dece6358
AM
13352+}
13353+
4a4d8108 13354+static void au_hn_bh(void *_args)
1facf9fc 13355+{
4a4d8108
AM
13356+ struct au_hnotify_args *a = _args;
13357+ struct super_block *sb;
13358+ aufs_bindex_t bindex, bend, bfound;
13359+ unsigned char xino, try_iput;
1facf9fc 13360+ int err;
1308ab2a 13361+ struct inode *inode;
4a4d8108
AM
13362+ ino_t h_ino;
13363+ struct hn_job_args args;
13364+ struct dentry *dentry;
13365+ struct au_sbinfo *sbinfo;
1facf9fc 13366+
4a4d8108
AM
13367+ AuDebugOn(!_args);
13368+ AuDebugOn(!a->h_dir);
13369+ AuDebugOn(!a->dir);
13370+ AuDebugOn(!a->mask);
13371+ AuDbg("mask 0x%x, i%lu, hi%lu, hci%lu\n",
13372+ a->mask, a->dir->i_ino, a->h_dir->i_ino,
13373+ a->h_child_inode ? a->h_child_inode->i_ino : 0);
1facf9fc 13374+
4a4d8108
AM
13375+ inode = NULL;
13376+ dentry = NULL;
13377+ /*
13378+ * do not lock a->dir->i_mutex here
13379+ * because of d_revalidate() may cause a deadlock.
13380+ */
13381+ sb = a->dir->i_sb;
13382+ AuDebugOn(!sb);
13383+ sbinfo = au_sbi(sb);
13384+ AuDebugOn(!sbinfo);
7f207e10 13385+ si_write_lock(sb, AuLock_NOPLMW);
1facf9fc 13386+
4a4d8108
AM
13387+ ii_read_lock_parent(a->dir);
13388+ bfound = -1;
13389+ bend = au_ibend(a->dir);
13390+ for (bindex = au_ibstart(a->dir); bindex <= bend; bindex++)
13391+ if (au_h_iptr(a->dir, bindex) == a->h_dir) {
13392+ bfound = bindex;
13393+ break;
13394+ }
13395+ ii_read_unlock(a->dir);
13396+ if (unlikely(bfound < 0))
13397+ goto out;
1facf9fc 13398+
4a4d8108
AM
13399+ xino = !!au_opt_test(au_mntflags(sb), XINO);
13400+ h_ino = 0;
13401+ if (a->h_child_inode)
13402+ h_ino = a->h_child_inode->i_ino;
1facf9fc 13403+
4a4d8108
AM
13404+ if (a->h_child_nlen
13405+ && (au_ftest_hnjob(a->flags[AuHn_CHILD], GEN)
13406+ || au_ftest_hnjob(a->flags[AuHn_CHILD], MNTPNT)))
13407+ dentry = lookup_wlock_by_name(a->h_child_name, a->h_child_nlen,
13408+ a->dir);
13409+ try_iput = 0;
13410+ if (dentry)
13411+ inode = dentry->d_inode;
13412+ if (xino && !inode && h_ino
13413+ && (au_ftest_hnjob(a->flags[AuHn_CHILD], XINO0)
13414+ || au_ftest_hnjob(a->flags[AuHn_CHILD], TRYXINO0)
13415+ || au_ftest_hnjob(a->flags[AuHn_CHILD], GEN))) {
13416+ inode = lookup_wlock_by_ino(sb, bfound, h_ino);
13417+ try_iput = 1;
13418+ }
1facf9fc 13419+
4a4d8108
AM
13420+ args.flags = a->flags[AuHn_CHILD];
13421+ args.dentry = dentry;
13422+ args.inode = inode;
13423+ args.h_inode = a->h_child_inode;
13424+ args.dir = a->dir;
13425+ args.h_dir = a->h_dir;
13426+ args.h_name = a->h_child_name;
13427+ args.h_nlen = a->h_child_nlen;
13428+ err = hn_job(&args);
13429+ if (dentry) {
027c5e7a 13430+ if (au_di(dentry))
4a4d8108
AM
13431+ di_write_unlock(dentry);
13432+ dput(dentry);
13433+ }
13434+ if (inode && try_iput) {
13435+ ii_write_unlock(inode);
13436+ iput(inode);
13437+ }
1facf9fc 13438+
4a4d8108
AM
13439+ ii_write_lock_parent(a->dir);
13440+ args.flags = a->flags[AuHn_PARENT];
13441+ args.dentry = NULL;
13442+ args.inode = a->dir;
13443+ args.h_inode = a->h_dir;
13444+ args.dir = NULL;
13445+ args.h_dir = NULL;
13446+ args.h_name = NULL;
13447+ args.h_nlen = 0;
13448+ err = hn_job(&args);
13449+ ii_write_unlock(a->dir);
1facf9fc 13450+
4f0767ce 13451+out:
4a4d8108
AM
13452+ iput(a->h_child_inode);
13453+ iput(a->h_dir);
13454+ iput(a->dir);
027c5e7a
AM
13455+ si_write_unlock(sb);
13456+ au_nwt_done(&sbinfo->si_nowait);
1308ab2a 13457+ kfree(a);
dece6358 13458+}
1facf9fc 13459+
4a4d8108
AM
13460+/* ---------------------------------------------------------------------- */
13461+
13462+int au_hnotify(struct inode *h_dir, struct au_hnotify *hnotify, u32 mask,
13463+ struct qstr *h_child_qstr, struct inode *h_child_inode)
dece6358 13464+{
4a4d8108 13465+ int err, len;
53392da6 13466+ unsigned int flags[AuHnLast], f;
4a4d8108
AM
13467+ unsigned char isdir, isroot, wh;
13468+ struct inode *dir;
13469+ struct au_hnotify_args *args;
13470+ char *p, *h_child_name;
dece6358 13471+
1308ab2a 13472+ err = 0;
4a4d8108
AM
13473+ AuDebugOn(!hnotify || !hnotify->hn_aufs_inode);
13474+ dir = igrab(hnotify->hn_aufs_inode);
13475+ if (!dir)
13476+ goto out;
1facf9fc 13477+
4a4d8108
AM
13478+ isroot = (dir->i_ino == AUFS_ROOT_INO);
13479+ wh = 0;
13480+ h_child_name = (void *)h_child_qstr->name;
13481+ len = h_child_qstr->len;
13482+ if (h_child_name) {
13483+ if (len > AUFS_WH_PFX_LEN
13484+ && !memcmp(h_child_name, AUFS_WH_PFX, AUFS_WH_PFX_LEN)) {
13485+ h_child_name += AUFS_WH_PFX_LEN;
13486+ len -= AUFS_WH_PFX_LEN;
13487+ wh = 1;
13488+ }
1facf9fc 13489+ }
dece6358 13490+
4a4d8108
AM
13491+ isdir = 0;
13492+ if (h_child_inode)
13493+ isdir = !!S_ISDIR(h_child_inode->i_mode);
13494+ flags[AuHn_PARENT] = AuHnJob_ISDIR;
13495+ flags[AuHn_CHILD] = 0;
13496+ if (isdir)
13497+ flags[AuHn_CHILD] = AuHnJob_ISDIR;
13498+ au_fset_hnjob(flags[AuHn_PARENT], DIRENT);
13499+ au_fset_hnjob(flags[AuHn_CHILD], GEN);
13500+ switch (mask & FS_EVENTS_POSS_ON_CHILD) {
13501+ case FS_MOVED_FROM:
13502+ case FS_MOVED_TO:
13503+ au_fset_hnjob(flags[AuHn_CHILD], XINO0);
13504+ au_fset_hnjob(flags[AuHn_CHILD], MNTPNT);
13505+ /*FALLTHROUGH*/
13506+ case FS_CREATE:
13507+ AuDebugOn(!h_child_name || !h_child_inode);
13508+ break;
1facf9fc 13509+
4a4d8108
AM
13510+ case FS_DELETE:
13511+ /*
13512+ * aufs never be able to get this child inode.
13513+ * revalidation should be in d_revalidate()
13514+ * by checking i_nlink, i_generation or d_unhashed().
13515+ */
13516+ AuDebugOn(!h_child_name);
13517+ au_fset_hnjob(flags[AuHn_CHILD], TRYXINO0);
13518+ au_fset_hnjob(flags[AuHn_CHILD], MNTPNT);
13519+ break;
dece6358 13520+
4a4d8108
AM
13521+ default:
13522+ AuDebugOn(1);
13523+ }
1308ab2a 13524+
4a4d8108
AM
13525+ if (wh)
13526+ h_child_inode = NULL;
1308ab2a 13527+
4a4d8108
AM
13528+ err = -ENOMEM;
13529+ /* iput() and kfree() will be called in au_hnotify() */
4a4d8108 13530+ args = kmalloc(sizeof(*args) + len + 1, GFP_NOFS);
4a4d8108
AM
13531+ if (unlikely(!args)) {
13532+ AuErr1("no memory\n");
13533+ iput(dir);
13534+ goto out;
13535+ }
13536+ args->flags[AuHn_PARENT] = flags[AuHn_PARENT];
13537+ args->flags[AuHn_CHILD] = flags[AuHn_CHILD];
13538+ args->mask = mask;
13539+ args->dir = dir;
13540+ args->h_dir = igrab(h_dir);
13541+ if (h_child_inode)
13542+ h_child_inode = igrab(h_child_inode); /* can be NULL */
13543+ args->h_child_inode = h_child_inode;
13544+ args->h_child_nlen = len;
13545+ if (len) {
13546+ p = (void *)args;
13547+ p += sizeof(*args);
13548+ memcpy(p, h_child_name, len);
13549+ p[len] = 0;
1308ab2a 13550+ }
1308ab2a 13551+
53392da6
AM
13552+ f = 0;
13553+ if (!dir->i_nlink)
13554+ f = AuWkq_NEST;
13555+ err = au_wkq_nowait(au_hn_bh, args, dir->i_sb, f);
4a4d8108
AM
13556+ if (unlikely(err)) {
13557+ pr_err("wkq %d\n", err);
13558+ iput(args->h_child_inode);
13559+ iput(args->h_dir);
13560+ iput(args->dir);
13561+ kfree(args);
1facf9fc 13562+ }
1facf9fc 13563+
4a4d8108 13564+out:
1facf9fc 13565+ return err;
13566+}
13567+
027c5e7a
AM
13568+/* ---------------------------------------------------------------------- */
13569+
13570+int au_hnotify_reset_br(unsigned int udba, struct au_branch *br, int perm)
13571+{
13572+ int err;
13573+
13574+ AuDebugOn(!(udba & AuOptMask_UDBA));
13575+
13576+ err = 0;
13577+ if (au_hnotify_op.reset_br)
13578+ err = au_hnotify_op.reset_br(udba, br, perm);
13579+
13580+ return err;
13581+}
13582+
13583+int au_hnotify_init_br(struct au_branch *br, int perm)
13584+{
13585+ int err;
13586+
13587+ err = 0;
13588+ if (au_hnotify_op.init_br)
13589+ err = au_hnotify_op.init_br(br, perm);
13590+
13591+ return err;
13592+}
13593+
13594+void au_hnotify_fin_br(struct au_branch *br)
13595+{
13596+ if (au_hnotify_op.fin_br)
13597+ au_hnotify_op.fin_br(br);
13598+}
13599+
4a4d8108
AM
13600+static void au_hn_destroy_cache(void)
13601+{
13602+ kmem_cache_destroy(au_cachep[AuCache_HNOTIFY]);
13603+ au_cachep[AuCache_HNOTIFY] = NULL;
13604+}
1308ab2a 13605+
4a4d8108 13606+int __init au_hnotify_init(void)
1facf9fc 13607+{
1308ab2a 13608+ int err;
1308ab2a 13609+
4a4d8108
AM
13610+ err = -ENOMEM;
13611+ au_cachep[AuCache_HNOTIFY] = AuCache(au_hnotify);
13612+ if (au_cachep[AuCache_HNOTIFY]) {
027c5e7a
AM
13613+ err = 0;
13614+ if (au_hnotify_op.init)
13615+ err = au_hnotify_op.init();
4a4d8108
AM
13616+ if (unlikely(err))
13617+ au_hn_destroy_cache();
1308ab2a 13618+ }
1308ab2a 13619+ AuTraceErr(err);
4a4d8108 13620+ return err;
1308ab2a 13621+}
13622+
4a4d8108 13623+void au_hnotify_fin(void)
1308ab2a 13624+{
027c5e7a
AM
13625+ if (au_hnotify_op.fin)
13626+ au_hnotify_op.fin();
4a4d8108
AM
13627+ /* cf. au_cache_fin() */
13628+ if (au_cachep[AuCache_HNOTIFY])
13629+ au_hn_destroy_cache();
dece6358 13630+}
7f207e10
AM
13631diff -urN /usr/share/empty/fs/aufs/iinfo.c linux/fs/aufs/iinfo.c
13632--- /usr/share/empty/fs/aufs/iinfo.c 1970-01-01 01:00:00.000000000 +0100
0c3ec466 13633+++ linux/fs/aufs/iinfo.c 2012-07-22 19:57:03.164337936 +0200
027c5e7a 13634@@ -0,0 +1,264 @@
dece6358 13635+/*
f6c5ef8b 13636+ * Copyright (C) 2005-2012 Junjiro R. Okajima
dece6358
AM
13637+ *
13638+ * This program, aufs is free software; you can redistribute it and/or modify
13639+ * it under the terms of the GNU General Public License as published by
13640+ * the Free Software Foundation; either version 2 of the License, or
13641+ * (at your option) any later version.
13642+ *
13643+ * This program is distributed in the hope that it will be useful,
13644+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
13645+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13646+ * GNU General Public License for more details.
13647+ *
13648+ * You should have received a copy of the GNU General Public License
13649+ * along with this program; if not, write to the Free Software
13650+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
13651+ */
1facf9fc 13652+
dece6358 13653+/*
4a4d8108 13654+ * inode private data
dece6358 13655+ */
1facf9fc 13656+
1308ab2a 13657+#include "aufs.h"
1facf9fc 13658+
4a4d8108 13659+struct inode *au_h_iptr(struct inode *inode, aufs_bindex_t bindex)
1308ab2a 13660+{
4a4d8108 13661+ struct inode *h_inode;
1facf9fc 13662+
4a4d8108 13663+ IiMustAnyLock(inode);
1facf9fc 13664+
4a4d8108
AM
13665+ h_inode = au_ii(inode)->ii_hinode[0 + bindex].hi_inode;
13666+ AuDebugOn(h_inode && atomic_read(&h_inode->i_count) <= 0);
13667+ return h_inode;
13668+}
1facf9fc 13669+
4a4d8108
AM
13670+/* todo: hard/soft set? */
13671+void au_hiput(struct au_hinode *hinode)
13672+{
13673+ au_hn_free(hinode);
13674+ dput(hinode->hi_whdentry);
13675+ iput(hinode->hi_inode);
13676+}
1facf9fc 13677+
4a4d8108
AM
13678+unsigned int au_hi_flags(struct inode *inode, int isdir)
13679+{
13680+ unsigned int flags;
13681+ const unsigned int mnt_flags = au_mntflags(inode->i_sb);
1facf9fc 13682+
4a4d8108
AM
13683+ flags = 0;
13684+ if (au_opt_test(mnt_flags, XINO))
13685+ au_fset_hi(flags, XINO);
13686+ if (isdir && au_opt_test(mnt_flags, UDBA_HNOTIFY))
13687+ au_fset_hi(flags, HNOTIFY);
13688+ return flags;
1facf9fc 13689+}
13690+
4a4d8108
AM
13691+void au_set_h_iptr(struct inode *inode, aufs_bindex_t bindex,
13692+ struct inode *h_inode, unsigned int flags)
1308ab2a 13693+{
4a4d8108
AM
13694+ struct au_hinode *hinode;
13695+ struct inode *hi;
13696+ struct au_iinfo *iinfo = au_ii(inode);
1facf9fc 13697+
4a4d8108 13698+ IiMustWriteLock(inode);
dece6358 13699+
4a4d8108
AM
13700+ hinode = iinfo->ii_hinode + bindex;
13701+ hi = hinode->hi_inode;
13702+ AuDebugOn(h_inode && atomic_read(&h_inode->i_count) <= 0);
13703+
13704+ if (hi)
13705+ au_hiput(hinode);
13706+ hinode->hi_inode = h_inode;
13707+ if (h_inode) {
13708+ int err;
13709+ struct super_block *sb = inode->i_sb;
13710+ struct au_branch *br;
13711+
027c5e7a
AM
13712+ AuDebugOn(inode->i_mode
13713+ && (h_inode->i_mode & S_IFMT)
13714+ != (inode->i_mode & S_IFMT));
4a4d8108
AM
13715+ if (bindex == iinfo->ii_bstart)
13716+ au_cpup_igen(inode, h_inode);
13717+ br = au_sbr(sb, bindex);
13718+ hinode->hi_id = br->br_id;
13719+ if (au_ftest_hi(flags, XINO)) {
13720+ err = au_xino_write(sb, bindex, h_inode->i_ino,
13721+ inode->i_ino);
13722+ if (unlikely(err))
13723+ AuIOErr1("failed au_xino_write() %d\n", err);
13724+ }
13725+
13726+ if (au_ftest_hi(flags, HNOTIFY)
13727+ && au_br_hnotifyable(br->br_perm)) {
027c5e7a 13728+ err = au_hn_alloc(hinode, inode);
4a4d8108
AM
13729+ if (unlikely(err))
13730+ AuIOErr1("au_hn_alloc() %d\n", err);
1308ab2a 13731+ }
13732+ }
4a4d8108 13733+}
dece6358 13734+
4a4d8108
AM
13735+void au_set_hi_wh(struct inode *inode, aufs_bindex_t bindex,
13736+ struct dentry *h_wh)
13737+{
13738+ struct au_hinode *hinode;
dece6358 13739+
4a4d8108
AM
13740+ IiMustWriteLock(inode);
13741+
13742+ hinode = au_ii(inode)->ii_hinode + bindex;
13743+ AuDebugOn(hinode->hi_whdentry);
13744+ hinode->hi_whdentry = h_wh;
1facf9fc 13745+}
13746+
4a4d8108 13747+void au_update_iigen(struct inode *inode)
1308ab2a 13748+{
4a4d8108
AM
13749+ atomic_set(&au_ii(inode)->ii_generation, au_sigen(inode->i_sb));
13750+ /* smp_mb(); */ /* atomic_set */
13751+}
1facf9fc 13752+
4a4d8108
AM
13753+/* it may be called at remount time, too */
13754+void au_update_ibrange(struct inode *inode, int do_put_zero)
13755+{
13756+ struct au_iinfo *iinfo;
027c5e7a 13757+ aufs_bindex_t bindex, bend;
1facf9fc 13758+
4a4d8108 13759+ iinfo = au_ii(inode);
027c5e7a 13760+ if (!iinfo)
4a4d8108 13761+ return;
1facf9fc 13762+
4a4d8108 13763+ IiMustWriteLock(inode);
1facf9fc 13764+
027c5e7a 13765+ if (do_put_zero && iinfo->ii_bstart >= 0) {
4a4d8108
AM
13766+ for (bindex = iinfo->ii_bstart; bindex <= iinfo->ii_bend;
13767+ bindex++) {
13768+ struct inode *h_i;
1facf9fc 13769+
4a4d8108 13770+ h_i = iinfo->ii_hinode[0 + bindex].hi_inode;
027c5e7a
AM
13771+ if (h_i && !h_i->i_nlink)
13772+ au_set_h_iptr(inode, bindex, NULL, 0);
13773+ }
4a4d8108
AM
13774+ }
13775+
027c5e7a
AM
13776+ iinfo->ii_bstart = -1;
13777+ iinfo->ii_bend = -1;
13778+ bend = au_sbend(inode->i_sb);
13779+ for (bindex = 0; bindex <= bend; bindex++)
13780+ if (iinfo->ii_hinode[0 + bindex].hi_inode) {
13781+ iinfo->ii_bstart = bindex;
4a4d8108 13782+ break;
027c5e7a
AM
13783+ }
13784+ if (iinfo->ii_bstart >= 0)
13785+ for (bindex = bend; bindex >= iinfo->ii_bstart; bindex--)
13786+ if (iinfo->ii_hinode[0 + bindex].hi_inode) {
13787+ iinfo->ii_bend = bindex;
13788+ break;
13789+ }
13790+ AuDebugOn(iinfo->ii_bstart > iinfo->ii_bend);
1308ab2a 13791+}
1facf9fc 13792+
dece6358 13793+/* ---------------------------------------------------------------------- */
1facf9fc 13794+
4a4d8108 13795+void au_icntnr_init_once(void *_c)
dece6358 13796+{
4a4d8108
AM
13797+ struct au_icntnr *c = _c;
13798+ struct au_iinfo *iinfo = &c->iinfo;
e49829fe 13799+ static struct lock_class_key aufs_ii;
1facf9fc 13800+
4a4d8108 13801+ au_rw_init(&iinfo->ii_rwsem);
e49829fe 13802+ au_rw_class(&iinfo->ii_rwsem, &aufs_ii);
4a4d8108
AM
13803+ inode_init_once(&c->vfs_inode);
13804+}
1facf9fc 13805+
4a4d8108
AM
13806+int au_iinfo_init(struct inode *inode)
13807+{
13808+ struct au_iinfo *iinfo;
13809+ struct super_block *sb;
13810+ int nbr, i;
1facf9fc 13811+
4a4d8108
AM
13812+ sb = inode->i_sb;
13813+ iinfo = &(container_of(inode, struct au_icntnr, vfs_inode)->iinfo);
13814+ nbr = au_sbend(sb) + 1;
13815+ if (unlikely(nbr <= 0))
13816+ nbr = 1;
13817+ iinfo->ii_hinode = kcalloc(nbr, sizeof(*iinfo->ii_hinode), GFP_NOFS);
13818+ if (iinfo->ii_hinode) {
7f207e10 13819+ au_ninodes_inc(sb);
4a4d8108
AM
13820+ for (i = 0; i < nbr; i++)
13821+ iinfo->ii_hinode[i].hi_id = -1;
1facf9fc 13822+
4a4d8108
AM
13823+ atomic_set(&iinfo->ii_generation, au_sigen(sb));
13824+ /* smp_mb(); */ /* atomic_set */
13825+ iinfo->ii_bstart = -1;
13826+ iinfo->ii_bend = -1;
13827+ iinfo->ii_vdir = NULL;
13828+ return 0;
1308ab2a 13829+ }
4a4d8108
AM
13830+ return -ENOMEM;
13831+}
1facf9fc 13832+
4a4d8108
AM
13833+int au_ii_realloc(struct au_iinfo *iinfo, int nbr)
13834+{
13835+ int err, sz;
13836+ struct au_hinode *hip;
1facf9fc 13837+
4a4d8108
AM
13838+ AuRwMustWriteLock(&iinfo->ii_rwsem);
13839+
13840+ err = -ENOMEM;
13841+ sz = sizeof(*hip) * (iinfo->ii_bend + 1);
13842+ if (!sz)
13843+ sz = sizeof(*hip);
13844+ hip = au_kzrealloc(iinfo->ii_hinode, sz, sizeof(*hip) * nbr, GFP_NOFS);
13845+ if (hip) {
13846+ iinfo->ii_hinode = hip;
13847+ err = 0;
1308ab2a 13848+ }
4a4d8108 13849+
1308ab2a 13850+ return err;
1facf9fc 13851+}
13852+
4a4d8108 13853+void au_iinfo_fin(struct inode *inode)
1facf9fc 13854+{
4a4d8108
AM
13855+ struct au_iinfo *iinfo;
13856+ struct au_hinode *hi;
13857+ struct super_block *sb;
b752ccd1
AM
13858+ aufs_bindex_t bindex, bend;
13859+ const unsigned char unlinked = !inode->i_nlink;
1308ab2a 13860+
4a4d8108
AM
13861+ iinfo = au_ii(inode);
13862+ /* bad_inode case */
13863+ if (!iinfo)
13864+ return;
1308ab2a 13865+
b752ccd1 13866+ sb = inode->i_sb;
7f207e10 13867+ au_ninodes_dec(sb);
b752ccd1
AM
13868+ if (si_pid_test(sb))
13869+ au_xino_delete_inode(inode, unlinked);
13870+ else {
13871+ /*
13872+ * it is safe to hide the dependency between sbinfo and
13873+ * sb->s_umount.
13874+ */
13875+ lockdep_off();
13876+ si_noflush_read_lock(sb);
13877+ au_xino_delete_inode(inode, unlinked);
13878+ si_read_unlock(sb);
13879+ lockdep_on();
13880+ }
13881+
4a4d8108
AM
13882+ if (iinfo->ii_vdir)
13883+ au_vdir_free(iinfo->ii_vdir);
1308ab2a 13884+
b752ccd1
AM
13885+ bindex = iinfo->ii_bstart;
13886+ if (bindex >= 0) {
13887+ hi = iinfo->ii_hinode + bindex;
4a4d8108 13888+ bend = iinfo->ii_bend;
b752ccd1
AM
13889+ while (bindex++ <= bend) {
13890+ if (hi->hi_inode)
4a4d8108 13891+ au_hiput(hi);
4a4d8108
AM
13892+ hi++;
13893+ }
13894+ }
4a4d8108 13895+ kfree(iinfo->ii_hinode);
027c5e7a 13896+ iinfo->ii_hinode = NULL;
4a4d8108 13897+ AuRwDestroy(&iinfo->ii_rwsem);
dece6358 13898+}
7f207e10
AM
13899diff -urN /usr/share/empty/fs/aufs/inode.c linux/fs/aufs/inode.c
13900--- /usr/share/empty/fs/aufs/inode.c 1970-01-01 01:00:00.000000000 +0100
0c3ec466 13901+++ linux/fs/aufs/inode.c 2012-07-22 19:57:03.164337936 +0200
027c5e7a 13902@@ -0,0 +1,471 @@
4a4d8108 13903+/*
f6c5ef8b 13904+ * Copyright (C) 2005-2012 Junjiro R. Okajima
4a4d8108
AM
13905+ *
13906+ * This program, aufs is free software; you can redistribute it and/or modify
13907+ * it under the terms of the GNU General Public License as published by
13908+ * the Free Software Foundation; either version 2 of the License, or
13909+ * (at your option) any later version.
13910+ *
13911+ * This program is distributed in the hope that it will be useful,
13912+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
13913+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13914+ * GNU General Public License for more details.
13915+ *
13916+ * You should have received a copy of the GNU General Public License
13917+ * along with this program; if not, write to the Free Software
13918+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
13919+ */
1facf9fc 13920+
4a4d8108
AM
13921+/*
13922+ * inode functions
13923+ */
1facf9fc 13924+
4a4d8108 13925+#include "aufs.h"
1308ab2a 13926+
4a4d8108
AM
13927+struct inode *au_igrab(struct inode *inode)
13928+{
13929+ if (inode) {
13930+ AuDebugOn(!atomic_read(&inode->i_count));
027c5e7a 13931+ ihold(inode);
1facf9fc 13932+ }
4a4d8108
AM
13933+ return inode;
13934+}
1facf9fc 13935+
4a4d8108
AM
13936+static void au_refresh_hinode_attr(struct inode *inode, int do_version)
13937+{
13938+ au_cpup_attr_all(inode, /*force*/0);
13939+ au_update_iigen(inode);
13940+ if (do_version)
13941+ inode->i_version++;
dece6358 13942+}
1facf9fc 13943+
027c5e7a 13944+static int au_ii_refresh(struct inode *inode, int *update)
dece6358 13945+{
4a4d8108 13946+ int err, e;
027c5e7a 13947+ umode_t type;
4a4d8108 13948+ aufs_bindex_t bindex, new_bindex;
1308ab2a 13949+ struct super_block *sb;
4a4d8108 13950+ struct au_iinfo *iinfo;
027c5e7a 13951+ struct au_hinode *p, *q, tmp;
1facf9fc 13952+
4a4d8108 13953+ IiMustWriteLock(inode);
1facf9fc 13954+
027c5e7a 13955+ *update = 0;
4a4d8108 13956+ sb = inode->i_sb;
027c5e7a 13957+ type = inode->i_mode & S_IFMT;
4a4d8108
AM
13958+ iinfo = au_ii(inode);
13959+ err = au_ii_realloc(iinfo, au_sbend(sb) + 1);
13960+ if (unlikely(err))
1308ab2a 13961+ goto out;
1facf9fc 13962+
027c5e7a 13963+ AuDebugOn(iinfo->ii_bstart < 0);
4a4d8108 13964+ p = iinfo->ii_hinode + iinfo->ii_bstart;
4a4d8108
AM
13965+ for (bindex = iinfo->ii_bstart; bindex <= iinfo->ii_bend;
13966+ bindex++, p++) {
13967+ if (!p->hi_inode)
13968+ continue;
1facf9fc 13969+
027c5e7a 13970+ AuDebugOn(type != (p->hi_inode->i_mode & S_IFMT));
4a4d8108
AM
13971+ new_bindex = au_br_index(sb, p->hi_id);
13972+ if (new_bindex == bindex)
13973+ continue;
1facf9fc 13974+
4a4d8108 13975+ if (new_bindex < 0) {
027c5e7a 13976+ *update = 1;
4a4d8108
AM
13977+ au_hiput(p);
13978+ p->hi_inode = NULL;
13979+ continue;
1308ab2a 13980+ }
4a4d8108
AM
13981+
13982+ if (new_bindex < iinfo->ii_bstart)
13983+ iinfo->ii_bstart = new_bindex;
13984+ if (iinfo->ii_bend < new_bindex)
13985+ iinfo->ii_bend = new_bindex;
13986+ /* swap two lower inode, and loop again */
13987+ q = iinfo->ii_hinode + new_bindex;
13988+ tmp = *q;
13989+ *q = *p;
13990+ *p = tmp;
13991+ if (tmp.hi_inode) {
13992+ bindex--;
13993+ p--;
1308ab2a 13994+ }
13995+ }
4a4d8108
AM
13996+ au_update_ibrange(inode, /*do_put_zero*/0);
13997+ e = au_dy_irefresh(inode);
13998+ if (unlikely(e && !err))
13999+ err = e;
1facf9fc 14000+
4f0767ce 14001+out:
027c5e7a
AM
14002+ AuTraceErr(err);
14003+ return err;
14004+}
14005+
14006+int au_refresh_hinode_self(struct inode *inode)
14007+{
14008+ int err, update;
14009+
14010+ err = au_ii_refresh(inode, &update);
14011+ if (!err)
14012+ au_refresh_hinode_attr(inode, update && S_ISDIR(inode->i_mode));
14013+
14014+ AuTraceErr(err);
4a4d8108
AM
14015+ return err;
14016+}
1facf9fc 14017+
4a4d8108
AM
14018+int au_refresh_hinode(struct inode *inode, struct dentry *dentry)
14019+{
027c5e7a 14020+ int err, e, update;
4a4d8108 14021+ unsigned int flags;
027c5e7a 14022+ umode_t mode;
4a4d8108 14023+ aufs_bindex_t bindex, bend;
027c5e7a 14024+ unsigned char isdir;
4a4d8108
AM
14025+ struct au_hinode *p;
14026+ struct au_iinfo *iinfo;
1facf9fc 14027+
027c5e7a 14028+ err = au_ii_refresh(inode, &update);
4a4d8108
AM
14029+ if (unlikely(err))
14030+ goto out;
14031+
14032+ update = 0;
14033+ iinfo = au_ii(inode);
14034+ p = iinfo->ii_hinode + iinfo->ii_bstart;
027c5e7a
AM
14035+ mode = (inode->i_mode & S_IFMT);
14036+ isdir = S_ISDIR(mode);
4a4d8108
AM
14037+ flags = au_hi_flags(inode, isdir);
14038+ bend = au_dbend(dentry);
14039+ for (bindex = au_dbstart(dentry); bindex <= bend; bindex++) {
14040+ struct inode *h_i;
14041+ struct dentry *h_d;
14042+
14043+ h_d = au_h_dptr(dentry, bindex);
14044+ if (!h_d || !h_d->d_inode)
14045+ continue;
14046+
027c5e7a 14047+ AuDebugOn(mode != (h_d->d_inode->i_mode & S_IFMT));
4a4d8108
AM
14048+ if (iinfo->ii_bstart <= bindex && bindex <= iinfo->ii_bend) {
14049+ h_i = au_h_iptr(inode, bindex);
14050+ if (h_i) {
14051+ if (h_i == h_d->d_inode)
14052+ continue;
14053+ err = -EIO;
14054+ break;
14055+ }
14056+ }
14057+ if (bindex < iinfo->ii_bstart)
14058+ iinfo->ii_bstart = bindex;
14059+ if (iinfo->ii_bend < bindex)
14060+ iinfo->ii_bend = bindex;
14061+ au_set_h_iptr(inode, bindex, au_igrab(h_d->d_inode), flags);
14062+ update = 1;
1308ab2a 14063+ }
4a4d8108
AM
14064+ au_update_ibrange(inode, /*do_put_zero*/0);
14065+ e = au_dy_irefresh(inode);
14066+ if (unlikely(e && !err))
14067+ err = e;
027c5e7a
AM
14068+ if (!err)
14069+ au_refresh_hinode_attr(inode, update && isdir);
4a4d8108 14070+
4f0767ce 14071+out:
4a4d8108 14072+ AuTraceErr(err);
1308ab2a 14073+ return err;
dece6358
AM
14074+}
14075+
4a4d8108 14076+static int set_inode(struct inode *inode, struct dentry *dentry)
dece6358 14077+{
4a4d8108
AM
14078+ int err;
14079+ unsigned int flags;
14080+ umode_t mode;
14081+ aufs_bindex_t bindex, bstart, btail;
14082+ unsigned char isdir;
14083+ struct dentry *h_dentry;
14084+ struct inode *h_inode;
14085+ struct au_iinfo *iinfo;
dece6358 14086+
4a4d8108 14087+ IiMustWriteLock(inode);
dece6358 14088+
4a4d8108
AM
14089+ err = 0;
14090+ isdir = 0;
14091+ bstart = au_dbstart(dentry);
14092+ h_inode = au_h_dptr(dentry, bstart)->d_inode;
14093+ mode = h_inode->i_mode;
14094+ switch (mode & S_IFMT) {
14095+ case S_IFREG:
14096+ btail = au_dbtail(dentry);
14097+ inode->i_op = &aufs_iop;
14098+ inode->i_fop = &aufs_file_fop;
14099+ err = au_dy_iaop(inode, bstart, h_inode);
14100+ if (unlikely(err))
14101+ goto out;
14102+ break;
14103+ case S_IFDIR:
14104+ isdir = 1;
14105+ btail = au_dbtaildir(dentry);
14106+ inode->i_op = &aufs_dir_iop;
14107+ inode->i_fop = &aufs_dir_fop;
14108+ break;
14109+ case S_IFLNK:
14110+ btail = au_dbtail(dentry);
14111+ inode->i_op = &aufs_symlink_iop;
14112+ break;
14113+ case S_IFBLK:
14114+ case S_IFCHR:
14115+ case S_IFIFO:
14116+ case S_IFSOCK:
14117+ btail = au_dbtail(dentry);
14118+ inode->i_op = &aufs_iop;
14119+ au_init_special_fop(inode, mode, h_inode->i_rdev);
14120+ break;
14121+ default:
14122+ AuIOErr("Unknown file type 0%o\n", mode);
14123+ err = -EIO;
1308ab2a 14124+ goto out;
4a4d8108 14125+ }
dece6358 14126+
4a4d8108
AM
14127+ /* do not set hnotify for whiteouted dirs (SHWH mode) */
14128+ flags = au_hi_flags(inode, isdir);
14129+ if (au_opt_test(au_mntflags(dentry->d_sb), SHWH)
14130+ && au_ftest_hi(flags, HNOTIFY)
14131+ && dentry->d_name.len > AUFS_WH_PFX_LEN
14132+ && !memcmp(dentry->d_name.name, AUFS_WH_PFX, AUFS_WH_PFX_LEN))
14133+ au_fclr_hi(flags, HNOTIFY);
14134+ iinfo = au_ii(inode);
14135+ iinfo->ii_bstart = bstart;
14136+ iinfo->ii_bend = btail;
14137+ for (bindex = bstart; bindex <= btail; bindex++) {
14138+ h_dentry = au_h_dptr(dentry, bindex);
14139+ if (h_dentry)
14140+ au_set_h_iptr(inode, bindex,
14141+ au_igrab(h_dentry->d_inode), flags);
14142+ }
14143+ au_cpup_attr_all(inode, /*force*/1);
dece6358 14144+
4f0767ce 14145+out:
4a4d8108
AM
14146+ return err;
14147+}
dece6358 14148+
027c5e7a
AM
14149+/*
14150+ * successful returns with iinfo write_locked
14151+ * minus: errno
14152+ * zero: success, matched
14153+ * plus: no error, but unmatched
14154+ */
14155+static int reval_inode(struct inode *inode, struct dentry *dentry)
4a4d8108
AM
14156+{
14157+ int err;
14158+ aufs_bindex_t bindex, bend;
14159+ struct inode *h_inode, *h_dinode;
dece6358 14160+
4a4d8108
AM
14161+ /*
14162+ * before this function, if aufs got any iinfo lock, it must be only
14163+ * one, the parent dir.
14164+ * it can happen by UDBA and the obsoleted inode number.
14165+ */
14166+ err = -EIO;
14167+ if (unlikely(inode->i_ino == parent_ino(dentry)))
14168+ goto out;
14169+
027c5e7a 14170+ err = 1;
4a4d8108
AM
14171+ ii_write_lock_new_child(inode);
14172+ h_dinode = au_h_dptr(dentry, au_dbstart(dentry))->d_inode;
14173+ bend = au_ibend(inode);
14174+ for (bindex = au_ibstart(inode); bindex <= bend; bindex++) {
14175+ h_inode = au_h_iptr(inode, bindex);
14176+ if (h_inode && h_inode == h_dinode) {
4a4d8108 14177+ err = 0;
027c5e7a 14178+ if (au_iigen_test(inode, au_digen(dentry)))
4a4d8108
AM
14179+ err = au_refresh_hinode(inode, dentry);
14180+ break;
1308ab2a 14181+ }
1facf9fc 14182+ }
dece6358 14183+
4a4d8108
AM
14184+ if (unlikely(err))
14185+ ii_write_unlock(inode);
4f0767ce 14186+out:
1facf9fc 14187+ return err;
14188+}
1facf9fc 14189+
4a4d8108
AM
14190+int au_ino(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino,
14191+ unsigned int d_type, ino_t *ino)
1facf9fc 14192+{
4a4d8108
AM
14193+ int err;
14194+ struct mutex *mtx;
1facf9fc 14195+
b752ccd1 14196+ /* prevent hardlinked inode number from race condition */
4a4d8108 14197+ mtx = NULL;
b752ccd1 14198+ if (d_type != DT_DIR) {
4a4d8108
AM
14199+ mtx = &au_sbr(sb, bindex)->br_xino.xi_nondir_mtx;
14200+ mutex_lock(mtx);
14201+ }
14202+ err = au_xino_read(sb, bindex, h_ino, ino);
14203+ if (unlikely(err))
14204+ goto out;
1308ab2a 14205+
4a4d8108
AM
14206+ if (!*ino) {
14207+ err = -EIO;
14208+ *ino = au_xino_new_ino(sb);
14209+ if (unlikely(!*ino))
1facf9fc 14210+ goto out;
4a4d8108
AM
14211+ err = au_xino_write(sb, bindex, h_ino, *ino);
14212+ if (unlikely(err))
1308ab2a 14213+ goto out;
1308ab2a 14214+ }
1facf9fc 14215+
4f0767ce 14216+out:
b752ccd1 14217+ if (mtx)
4a4d8108 14218+ mutex_unlock(mtx);
1facf9fc 14219+ return err;
14220+}
14221+
4a4d8108
AM
14222+/* successful returns with iinfo write_locked */
14223+/* todo: return with unlocked? */
14224+struct inode *au_new_inode(struct dentry *dentry, int must_new)
1facf9fc 14225+{
b752ccd1 14226+ struct inode *inode, *h_inode;
4a4d8108
AM
14227+ struct dentry *h_dentry;
14228+ struct super_block *sb;
b752ccd1 14229+ struct mutex *mtx;
4a4d8108 14230+ ino_t h_ino, ino;
027c5e7a 14231+ int err;
4a4d8108 14232+ aufs_bindex_t bstart;
1facf9fc 14233+
4a4d8108
AM
14234+ sb = dentry->d_sb;
14235+ bstart = au_dbstart(dentry);
14236+ h_dentry = au_h_dptr(dentry, bstart);
b752ccd1
AM
14237+ h_inode = h_dentry->d_inode;
14238+ h_ino = h_inode->i_ino;
14239+
14240+ /*
14241+ * stop 'race'-ing between hardlinks under different
14242+ * parents.
14243+ */
14244+ mtx = NULL;
14245+ if (!S_ISDIR(h_inode->i_mode))
14246+ mtx = &au_sbr(sb, bstart)->br_xino.xi_nondir_mtx;
14247+
4f0767ce 14248+new_ino:
b752ccd1
AM
14249+ if (mtx)
14250+ mutex_lock(mtx);
4a4d8108
AM
14251+ err = au_xino_read(sb, bstart, h_ino, &ino);
14252+ inode = ERR_PTR(err);
14253+ if (unlikely(err))
14254+ goto out;
b752ccd1 14255+
4a4d8108
AM
14256+ if (!ino) {
14257+ ino = au_xino_new_ino(sb);
14258+ if (unlikely(!ino)) {
14259+ inode = ERR_PTR(-EIO);
dece6358
AM
14260+ goto out;
14261+ }
14262+ }
1facf9fc 14263+
4a4d8108
AM
14264+ AuDbg("i%lu\n", (unsigned long)ino);
14265+ inode = au_iget_locked(sb, ino);
14266+ err = PTR_ERR(inode);
14267+ if (IS_ERR(inode))
1facf9fc 14268+ goto out;
1facf9fc 14269+
4a4d8108
AM
14270+ AuDbg("%lx, new %d\n", inode->i_state, !!(inode->i_state & I_NEW));
14271+ if (inode->i_state & I_NEW) {
14272+ ii_write_lock_new_child(inode);
14273+ err = set_inode(inode, dentry);
14274+ if (!err) {
14275+ unlock_new_inode(inode);
14276+ goto out; /* success */
14277+ }
1308ab2a 14278+
027c5e7a
AM
14279+ /*
14280+ * iget_failed() calls iput(), but we need to call
14281+ * ii_write_unlock() after iget_failed(). so dirty hack for
14282+ * i_count.
14283+ */
14284+ atomic_inc(&inode->i_count);
4a4d8108 14285+ iget_failed(inode);
027c5e7a
AM
14286+ ii_write_unlock(inode);
14287+ au_xino_write(sb, bstart, h_ino, /*ino*/0);
14288+ /* ignore this error */
14289+ goto out_iput;
14290+ } else if (!must_new && !IS_DEADDIR(inode) && inode->i_nlink) {
b752ccd1
AM
14291+ /*
14292+ * horrible race condition between lookup, readdir and copyup
14293+ * (or something).
14294+ */
14295+ if (mtx)
14296+ mutex_unlock(mtx);
027c5e7a
AM
14297+ err = reval_inode(inode, dentry);
14298+ if (unlikely(err < 0)) {
14299+ mtx = NULL;
14300+ goto out_iput;
14301+ }
14302+
b752ccd1
AM
14303+ if (!err) {
14304+ mtx = NULL;
4a4d8108 14305+ goto out; /* success */
b752ccd1
AM
14306+ } else if (mtx)
14307+ mutex_lock(mtx);
4a4d8108
AM
14308+ }
14309+
14310+ if (unlikely(au_test_fs_unique_ino(h_dentry->d_inode)))
14311+ AuWarn1("Warning: Un-notified UDBA or repeatedly renamed dir,"
14312+ " b%d, %s, %.*s, hi%lu, i%lu.\n",
14313+ bstart, au_sbtype(h_dentry->d_sb), AuDLNPair(dentry),
14314+ (unsigned long)h_ino, (unsigned long)ino);
14315+ ino = 0;
14316+ err = au_xino_write(sb, bstart, h_ino, /*ino*/0);
14317+ if (!err) {
14318+ iput(inode);
b752ccd1
AM
14319+ if (mtx)
14320+ mutex_unlock(mtx);
4a4d8108
AM
14321+ goto new_ino;
14322+ }
1308ab2a 14323+
4f0767ce 14324+out_iput:
4a4d8108 14325+ iput(inode);
4a4d8108 14326+ inode = ERR_PTR(err);
4f0767ce 14327+out:
b752ccd1
AM
14328+ if (mtx)
14329+ mutex_unlock(mtx);
4a4d8108 14330+ return inode;
1facf9fc 14331+}
14332+
4a4d8108 14333+/* ---------------------------------------------------------------------- */
1facf9fc 14334+
4a4d8108
AM
14335+int au_test_ro(struct super_block *sb, aufs_bindex_t bindex,
14336+ struct inode *inode)
14337+{
14338+ int err;
1facf9fc 14339+
4a4d8108 14340+ err = au_br_rdonly(au_sbr(sb, bindex));
1facf9fc 14341+
4a4d8108
AM
14342+ /* pseudo-link after flushed may happen out of bounds */
14343+ if (!err
14344+ && inode
14345+ && au_ibstart(inode) <= bindex
14346+ && bindex <= au_ibend(inode)) {
14347+ /*
14348+ * permission check is unnecessary since vfsub routine
14349+ * will be called later
14350+ */
14351+ struct inode *hi = au_h_iptr(inode, bindex);
14352+ if (hi)
14353+ err = IS_IMMUTABLE(hi) ? -EROFS : 0;
1facf9fc 14354+ }
14355+
4a4d8108
AM
14356+ return err;
14357+}
dece6358 14358+
4a4d8108
AM
14359+int au_test_h_perm(struct inode *h_inode, int mask)
14360+{
0c3ec466 14361+ if (current_fsuid() == GLOBAL_ROOT_GID)
4a4d8108
AM
14362+ return 0;
14363+ return inode_permission(h_inode, mask);
14364+}
1facf9fc 14365+
4a4d8108
AM
14366+int au_test_h_perm_sio(struct inode *h_inode, int mask)
14367+{
14368+ if (au_test_nfs(h_inode->i_sb)
14369+ && (mask & MAY_WRITE)
14370+ && S_ISDIR(h_inode->i_mode))
14371+ mask |= MAY_READ; /* force permission check */
14372+ return au_test_h_perm(h_inode, mask);
1facf9fc 14373+}
7f207e10
AM
14374diff -urN /usr/share/empty/fs/aufs/inode.h linux/fs/aufs/inode.h
14375--- /usr/share/empty/fs/aufs/inode.h 1970-01-01 01:00:00.000000000 +0100
0c3ec466 14376+++ linux/fs/aufs/inode.h 2012-07-22 19:57:03.164337936 +0200
7eafdf33 14377@@ -0,0 +1,560 @@
4a4d8108 14378+/*
f6c5ef8b 14379+ * Copyright (C) 2005-2012 Junjiro R. Okajima
4a4d8108
AM
14380+ *
14381+ * This program, aufs is free software; you can redistribute it and/or modify
14382+ * it under the terms of the GNU General Public License as published by
14383+ * the Free Software Foundation; either version 2 of the License, or
14384+ * (at your option) any later version.
14385+ *
14386+ * This program is distributed in the hope that it will be useful,
14387+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
14388+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14389+ * GNU General Public License for more details.
14390+ *
14391+ * You should have received a copy of the GNU General Public License
14392+ * along with this program; if not, write to the Free Software
14393+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
14394+ */
1facf9fc 14395+
1308ab2a 14396+/*
4a4d8108 14397+ * inode operations
1308ab2a 14398+ */
dece6358 14399+
4a4d8108
AM
14400+#ifndef __AUFS_INODE_H__
14401+#define __AUFS_INODE_H__
dece6358 14402+
4a4d8108 14403+#ifdef __KERNEL__
1308ab2a 14404+
4a4d8108 14405+#include <linux/fsnotify.h>
4a4d8108 14406+#include "rwsem.h"
1308ab2a 14407+
4a4d8108 14408+struct vfsmount;
1facf9fc 14409+
4a4d8108
AM
14410+struct au_hnotify {
14411+#ifdef CONFIG_AUFS_HNOTIFY
14412+#ifdef CONFIG_AUFS_HFSNOTIFY
7f207e10 14413+ /* never use fsnotify_add_vfsmount_mark() */
0c5527e5 14414+ struct fsnotify_mark hn_mark;
4a4d8108 14415+#endif
7f207e10 14416+ struct inode *hn_aufs_inode; /* no get/put */
4a4d8108
AM
14417+#endif
14418+} ____cacheline_aligned_in_smp;
1facf9fc 14419+
4a4d8108
AM
14420+struct au_hinode {
14421+ struct inode *hi_inode;
14422+ aufs_bindex_t hi_id;
14423+#ifdef CONFIG_AUFS_HNOTIFY
14424+ struct au_hnotify *hi_notify;
14425+#endif
dece6358 14426+
4a4d8108
AM
14427+ /* reference to the copied-up whiteout with get/put */
14428+ struct dentry *hi_whdentry;
14429+};
dece6358 14430+
4a4d8108
AM
14431+struct au_vdir;
14432+struct au_iinfo {
14433+ atomic_t ii_generation;
14434+ struct super_block *ii_hsb1; /* no get/put */
1facf9fc 14435+
4a4d8108
AM
14436+ struct au_rwsem ii_rwsem;
14437+ aufs_bindex_t ii_bstart, ii_bend;
14438+ __u32 ii_higen;
14439+ struct au_hinode *ii_hinode;
14440+ struct au_vdir *ii_vdir;
14441+};
1facf9fc 14442+
4a4d8108
AM
14443+struct au_icntnr {
14444+ struct au_iinfo iinfo;
14445+ struct inode vfs_inode;
14446+} ____cacheline_aligned_in_smp;
1308ab2a 14447+
4a4d8108
AM
14448+/* au_pin flags */
14449+#define AuPin_DI_LOCKED 1
14450+#define AuPin_MNT_WRITE (1 << 1)
14451+#define au_ftest_pin(flags, name) ((flags) & AuPin_##name)
7f207e10
AM
14452+#define au_fset_pin(flags, name) \
14453+ do { (flags) |= AuPin_##name; } while (0)
14454+#define au_fclr_pin(flags, name) \
14455+ do { (flags) &= ~AuPin_##name; } while (0)
4a4d8108
AM
14456+
14457+struct au_pin {
14458+ /* input */
14459+ struct dentry *dentry;
14460+ unsigned int udba;
14461+ unsigned char lsc_di, lsc_hi, flags;
14462+ aufs_bindex_t bindex;
14463+
14464+ /* output */
14465+ struct dentry *parent;
14466+ struct au_hinode *hdir;
14467+ struct vfsmount *h_mnt;
14468+};
1facf9fc 14469+
1308ab2a 14470+/* ---------------------------------------------------------------------- */
14471+
4a4d8108 14472+static inline struct au_iinfo *au_ii(struct inode *inode)
1facf9fc 14473+{
4a4d8108 14474+ struct au_iinfo *iinfo;
1facf9fc 14475+
4a4d8108
AM
14476+ iinfo = &(container_of(inode, struct au_icntnr, vfs_inode)->iinfo);
14477+ if (iinfo->ii_hinode)
14478+ return iinfo;
14479+ return NULL; /* debugging bad_inode case */
14480+}
1facf9fc 14481+
4a4d8108 14482+/* ---------------------------------------------------------------------- */
1facf9fc 14483+
4a4d8108
AM
14484+/* inode.c */
14485+struct inode *au_igrab(struct inode *inode);
027c5e7a 14486+int au_refresh_hinode_self(struct inode *inode);
4a4d8108
AM
14487+int au_refresh_hinode(struct inode *inode, struct dentry *dentry);
14488+int au_ino(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino,
14489+ unsigned int d_type, ino_t *ino);
14490+struct inode *au_new_inode(struct dentry *dentry, int must_new);
14491+int au_test_ro(struct super_block *sb, aufs_bindex_t bindex,
14492+ struct inode *inode);
14493+int au_test_h_perm(struct inode *h_inode, int mask);
14494+int au_test_h_perm_sio(struct inode *h_inode, int mask);
1facf9fc 14495+
4a4d8108
AM
14496+static inline int au_wh_ino(struct super_block *sb, aufs_bindex_t bindex,
14497+ ino_t h_ino, unsigned int d_type, ino_t *ino)
14498+{
14499+#ifdef CONFIG_AUFS_SHWH
14500+ return au_ino(sb, bindex, h_ino, d_type, ino);
14501+#else
14502+ return 0;
14503+#endif
14504+}
1facf9fc 14505+
4a4d8108
AM
14506+/* i_op.c */
14507+extern struct inode_operations aufs_iop, aufs_symlink_iop, aufs_dir_iop;
1308ab2a 14508+
4a4d8108
AM
14509+/* au_wr_dir flags */
14510+#define AuWrDir_ADD_ENTRY 1
14511+#define AuWrDir_ISDIR (1 << 1)
14512+#define au_ftest_wrdir(flags, name) ((flags) & AuWrDir_##name)
7f207e10
AM
14513+#define au_fset_wrdir(flags, name) \
14514+ do { (flags) |= AuWrDir_##name; } while (0)
14515+#define au_fclr_wrdir(flags, name) \
14516+ do { (flags) &= ~AuWrDir_##name; } while (0)
1facf9fc 14517+
4a4d8108
AM
14518+struct au_wr_dir_args {
14519+ aufs_bindex_t force_btgt;
14520+ unsigned char flags;
14521+};
14522+int au_wr_dir(struct dentry *dentry, struct dentry *src_dentry,
14523+ struct au_wr_dir_args *args);
dece6358 14524+
4a4d8108
AM
14525+struct dentry *au_pinned_h_parent(struct au_pin *pin);
14526+void au_pin_init(struct au_pin *pin, struct dentry *dentry,
14527+ aufs_bindex_t bindex, int lsc_di, int lsc_hi,
14528+ unsigned int udba, unsigned char flags);
14529+int au_pin(struct au_pin *pin, struct dentry *dentry, aufs_bindex_t bindex,
14530+ unsigned int udba, unsigned char flags) __must_check;
14531+int au_do_pin(struct au_pin *pin) __must_check;
14532+void au_unpin(struct au_pin *pin);
1facf9fc 14533+
4a4d8108
AM
14534+/* i_op_add.c */
14535+int au_may_add(struct dentry *dentry, aufs_bindex_t bindex,
14536+ struct dentry *h_parent, int isdir);
7eafdf33
AM
14537+int aufs_mknod(struct inode *dir, struct dentry *dentry, umode_t mode,
14538+ dev_t dev);
4a4d8108 14539+int aufs_symlink(struct inode *dir, struct dentry *dentry, const char *symname);
7eafdf33 14540+int aufs_create(struct inode *dir, struct dentry *dentry, umode_t mode,
4a4d8108
AM
14541+ struct nameidata *nd);
14542+int aufs_link(struct dentry *src_dentry, struct inode *dir,
14543+ struct dentry *dentry);
7eafdf33 14544+int aufs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode);
1facf9fc 14545+
4a4d8108
AM
14546+/* i_op_del.c */
14547+int au_wr_dir_need_wh(struct dentry *dentry, int isdir, aufs_bindex_t *bcpup);
14548+int au_may_del(struct dentry *dentry, aufs_bindex_t bindex,
14549+ struct dentry *h_parent, int isdir);
14550+int aufs_unlink(struct inode *dir, struct dentry *dentry);
14551+int aufs_rmdir(struct inode *dir, struct dentry *dentry);
1308ab2a 14552+
4a4d8108
AM
14553+/* i_op_ren.c */
14554+int au_wbr(struct dentry *dentry, aufs_bindex_t btgt);
14555+int aufs_rename(struct inode *src_dir, struct dentry *src_dentry,
14556+ struct inode *dir, struct dentry *dentry);
1facf9fc 14557+
4a4d8108
AM
14558+/* iinfo.c */
14559+struct inode *au_h_iptr(struct inode *inode, aufs_bindex_t bindex);
14560+void au_hiput(struct au_hinode *hinode);
14561+void au_set_hi_wh(struct inode *inode, aufs_bindex_t bindex,
14562+ struct dentry *h_wh);
14563+unsigned int au_hi_flags(struct inode *inode, int isdir);
1308ab2a 14564+
4a4d8108
AM
14565+/* hinode flags */
14566+#define AuHi_XINO 1
14567+#define AuHi_HNOTIFY (1 << 1)
14568+#define au_ftest_hi(flags, name) ((flags) & AuHi_##name)
7f207e10
AM
14569+#define au_fset_hi(flags, name) \
14570+ do { (flags) |= AuHi_##name; } while (0)
14571+#define au_fclr_hi(flags, name) \
14572+ do { (flags) &= ~AuHi_##name; } while (0)
1facf9fc 14573+
4a4d8108
AM
14574+#ifndef CONFIG_AUFS_HNOTIFY
14575+#undef AuHi_HNOTIFY
14576+#define AuHi_HNOTIFY 0
14577+#endif
1facf9fc 14578+
4a4d8108
AM
14579+void au_set_h_iptr(struct inode *inode, aufs_bindex_t bindex,
14580+ struct inode *h_inode, unsigned int flags);
1facf9fc 14581+
4a4d8108
AM
14582+void au_update_iigen(struct inode *inode);
14583+void au_update_ibrange(struct inode *inode, int do_put_zero);
1facf9fc 14584+
4a4d8108
AM
14585+void au_icntnr_init_once(void *_c);
14586+int au_iinfo_init(struct inode *inode);
14587+void au_iinfo_fin(struct inode *inode);
14588+int au_ii_realloc(struct au_iinfo *iinfo, int nbr);
1308ab2a 14589+
e49829fe 14590+#ifdef CONFIG_PROC_FS
4a4d8108 14591+/* plink.c */
e49829fe
JR
14592+int au_plink_maint(struct super_block *sb, int flags);
14593+void au_plink_maint_leave(struct au_sbinfo *sbinfo);
14594+int au_plink_maint_enter(struct super_block *sb);
4a4d8108
AM
14595+#ifdef CONFIG_AUFS_DEBUG
14596+void au_plink_list(struct super_block *sb);
14597+#else
14598+AuStubVoid(au_plink_list, struct super_block *sb)
14599+#endif
14600+int au_plink_test(struct inode *inode);
14601+struct dentry *au_plink_lkup(struct inode *inode, aufs_bindex_t bindex);
14602+void au_plink_append(struct inode *inode, aufs_bindex_t bindex,
14603+ struct dentry *h_dentry);
e49829fe
JR
14604+void au_plink_put(struct super_block *sb, int verbose);
14605+void au_plink_clean(struct super_block *sb, int verbose);
4a4d8108 14606+void au_plink_half_refresh(struct super_block *sb, aufs_bindex_t br_id);
e49829fe
JR
14607+#else
14608+AuStubInt0(au_plink_maint, struct super_block *sb, int flags);
14609+AuStubVoid(au_plink_maint_leave, struct au_sbinfo *sbinfo);
14610+AuStubInt0(au_plink_maint_enter, struct super_block *sb);
14611+AuStubVoid(au_plink_list, struct super_block *sb);
14612+AuStubInt0(au_plink_test, struct inode *inode);
14613+AuStub(struct dentry *, au_plink_lkup, return NULL,
14614+ struct inode *inode, aufs_bindex_t bindex);
14615+AuStubVoid(au_plink_append, struct inode *inode, aufs_bindex_t bindex,
14616+ struct dentry *h_dentry);
14617+AuStubVoid(au_plink_put, struct super_block *sb, int verbose);
14618+AuStubVoid(au_plink_clean, struct super_block *sb, int verbose);
14619+AuStubVoid(au_plink_half_refresh, struct super_block *sb, aufs_bindex_t br_id);
14620+#endif /* CONFIG_PROC_FS */
1facf9fc 14621+
4a4d8108 14622+/* ---------------------------------------------------------------------- */
1308ab2a 14623+
4a4d8108
AM
14624+/* lock subclass for iinfo */
14625+enum {
14626+ AuLsc_II_CHILD, /* child first */
14627+ AuLsc_II_CHILD2, /* rename(2), link(2), and cpup at hnotify */
14628+ AuLsc_II_CHILD3, /* copyup dirs */
14629+ AuLsc_II_PARENT, /* see AuLsc_I_PARENT in vfsub.h */
14630+ AuLsc_II_PARENT2,
14631+ AuLsc_II_PARENT3, /* copyup dirs */
14632+ AuLsc_II_NEW_CHILD
14633+};
1308ab2a 14634+
1facf9fc 14635+/*
4a4d8108
AM
14636+ * ii_read_lock_child, ii_write_lock_child,
14637+ * ii_read_lock_child2, ii_write_lock_child2,
14638+ * ii_read_lock_child3, ii_write_lock_child3,
14639+ * ii_read_lock_parent, ii_write_lock_parent,
14640+ * ii_read_lock_parent2, ii_write_lock_parent2,
14641+ * ii_read_lock_parent3, ii_write_lock_parent3,
14642+ * ii_read_lock_new_child, ii_write_lock_new_child,
1facf9fc 14643+ */
4a4d8108
AM
14644+#define AuReadLockFunc(name, lsc) \
14645+static inline void ii_read_lock_##name(struct inode *i) \
14646+{ \
14647+ au_rw_read_lock_nested(&au_ii(i)->ii_rwsem, AuLsc_II_##lsc); \
14648+}
14649+
14650+#define AuWriteLockFunc(name, lsc) \
14651+static inline void ii_write_lock_##name(struct inode *i) \
14652+{ \
14653+ au_rw_write_lock_nested(&au_ii(i)->ii_rwsem, AuLsc_II_##lsc); \
14654+}
14655+
14656+#define AuRWLockFuncs(name, lsc) \
14657+ AuReadLockFunc(name, lsc) \
14658+ AuWriteLockFunc(name, lsc)
14659+
14660+AuRWLockFuncs(child, CHILD);
14661+AuRWLockFuncs(child2, CHILD2);
14662+AuRWLockFuncs(child3, CHILD3);
14663+AuRWLockFuncs(parent, PARENT);
14664+AuRWLockFuncs(parent2, PARENT2);
14665+AuRWLockFuncs(parent3, PARENT3);
14666+AuRWLockFuncs(new_child, NEW_CHILD);
14667+
14668+#undef AuReadLockFunc
14669+#undef AuWriteLockFunc
14670+#undef AuRWLockFuncs
1facf9fc 14671+
14672+/*
4a4d8108 14673+ * ii_read_unlock, ii_write_unlock, ii_downgrade_lock
1facf9fc 14674+ */
4a4d8108 14675+AuSimpleUnlockRwsemFuncs(ii, struct inode *i, &au_ii(i)->ii_rwsem);
1facf9fc 14676+
4a4d8108
AM
14677+#define IiMustNoWaiters(i) AuRwMustNoWaiters(&au_ii(i)->ii_rwsem)
14678+#define IiMustAnyLock(i) AuRwMustAnyLock(&au_ii(i)->ii_rwsem)
14679+#define IiMustWriteLock(i) AuRwMustWriteLock(&au_ii(i)->ii_rwsem)
1facf9fc 14680+
4a4d8108 14681+/* ---------------------------------------------------------------------- */
1308ab2a 14682+
027c5e7a
AM
14683+static inline void au_icntnr_init(struct au_icntnr *c)
14684+{
14685+#ifdef CONFIG_AUFS_DEBUG
14686+ c->vfs_inode.i_mode = 0;
14687+#endif
14688+}
14689+
4a4d8108
AM
14690+static inline unsigned int au_iigen(struct inode *inode)
14691+{
14692+ return atomic_read(&au_ii(inode)->ii_generation);
14693+}
1308ab2a 14694+
4a4d8108
AM
14695+/* tiny test for inode number */
14696+/* tmpfs generation is too rough */
14697+static inline int au_test_higen(struct inode *inode, struct inode *h_inode)
14698+{
14699+ struct au_iinfo *iinfo;
1308ab2a 14700+
4a4d8108
AM
14701+ iinfo = au_ii(inode);
14702+ AuRwMustAnyLock(&iinfo->ii_rwsem);
14703+ return !(iinfo->ii_hsb1 == h_inode->i_sb
14704+ && iinfo->ii_higen == h_inode->i_generation);
14705+}
1308ab2a 14706+
4a4d8108
AM
14707+static inline void au_iigen_dec(struct inode *inode)
14708+{
e49829fe 14709+ atomic_dec(&au_ii(inode)->ii_generation);
027c5e7a
AM
14710+}
14711+
14712+static inline int au_iigen_test(struct inode *inode, unsigned int sigen)
14713+{
14714+ int err;
14715+
14716+ err = 0;
14717+ if (unlikely(inode && au_iigen(inode) != sigen))
14718+ err = -EIO;
14719+
14720+ return err;
4a4d8108 14721+}
1308ab2a 14722+
4a4d8108 14723+/* ---------------------------------------------------------------------- */
1308ab2a 14724+
4a4d8108
AM
14725+static inline aufs_bindex_t au_ii_br_id(struct inode *inode,
14726+ aufs_bindex_t bindex)
14727+{
14728+ IiMustAnyLock(inode);
14729+ return au_ii(inode)->ii_hinode[0 + bindex].hi_id;
14730+}
1308ab2a 14731+
4a4d8108
AM
14732+static inline aufs_bindex_t au_ibstart(struct inode *inode)
14733+{
14734+ IiMustAnyLock(inode);
14735+ return au_ii(inode)->ii_bstart;
14736+}
1308ab2a 14737+
4a4d8108
AM
14738+static inline aufs_bindex_t au_ibend(struct inode *inode)
14739+{
14740+ IiMustAnyLock(inode);
14741+ return au_ii(inode)->ii_bend;
14742+}
1308ab2a 14743+
4a4d8108
AM
14744+static inline struct au_vdir *au_ivdir(struct inode *inode)
14745+{
14746+ IiMustAnyLock(inode);
14747+ return au_ii(inode)->ii_vdir;
14748+}
1308ab2a 14749+
4a4d8108
AM
14750+static inline struct dentry *au_hi_wh(struct inode *inode, aufs_bindex_t bindex)
14751+{
14752+ IiMustAnyLock(inode);
14753+ return au_ii(inode)->ii_hinode[0 + bindex].hi_whdentry;
14754+}
1308ab2a 14755+
4a4d8108 14756+static inline void au_set_ibstart(struct inode *inode, aufs_bindex_t bindex)
1308ab2a 14757+{
4a4d8108
AM
14758+ IiMustWriteLock(inode);
14759+ au_ii(inode)->ii_bstart = bindex;
14760+}
1308ab2a 14761+
4a4d8108
AM
14762+static inline void au_set_ibend(struct inode *inode, aufs_bindex_t bindex)
14763+{
14764+ IiMustWriteLock(inode);
14765+ au_ii(inode)->ii_bend = bindex;
1308ab2a 14766+}
14767+
4a4d8108
AM
14768+static inline void au_set_ivdir(struct inode *inode, struct au_vdir *vdir)
14769+{
14770+ IiMustWriteLock(inode);
14771+ au_ii(inode)->ii_vdir = vdir;
14772+}
1facf9fc 14773+
4a4d8108 14774+static inline struct au_hinode *au_hi(struct inode *inode, aufs_bindex_t bindex)
1308ab2a 14775+{
4a4d8108
AM
14776+ IiMustAnyLock(inode);
14777+ return au_ii(inode)->ii_hinode + bindex;
14778+}
dece6358 14779+
4a4d8108 14780+/* ---------------------------------------------------------------------- */
1facf9fc 14781+
4a4d8108
AM
14782+static inline struct dentry *au_pinned_parent(struct au_pin *pin)
14783+{
14784+ if (pin)
14785+ return pin->parent;
14786+ return NULL;
1facf9fc 14787+}
14788+
4a4d8108 14789+static inline struct inode *au_pinned_h_dir(struct au_pin *pin)
1facf9fc 14790+{
4a4d8108
AM
14791+ if (pin && pin->hdir)
14792+ return pin->hdir->hi_inode;
14793+ return NULL;
1308ab2a 14794+}
1facf9fc 14795+
4a4d8108
AM
14796+static inline struct au_hinode *au_pinned_hdir(struct au_pin *pin)
14797+{
14798+ if (pin)
14799+ return pin->hdir;
14800+ return NULL;
14801+}
1facf9fc 14802+
4a4d8108 14803+static inline void au_pin_set_dentry(struct au_pin *pin, struct dentry *dentry)
1308ab2a 14804+{
4a4d8108
AM
14805+ if (pin)
14806+ pin->dentry = dentry;
14807+}
1308ab2a 14808+
4a4d8108
AM
14809+static inline void au_pin_set_parent_lflag(struct au_pin *pin,
14810+ unsigned char lflag)
14811+{
14812+ if (pin) {
7f207e10 14813+ if (lflag)
4a4d8108 14814+ au_fset_pin(pin->flags, DI_LOCKED);
7f207e10 14815+ else
4a4d8108 14816+ au_fclr_pin(pin->flags, DI_LOCKED);
1308ab2a 14817+ }
4a4d8108
AM
14818+}
14819+
14820+static inline void au_pin_set_parent(struct au_pin *pin, struct dentry *parent)
14821+{
14822+ if (pin) {
14823+ dput(pin->parent);
14824+ pin->parent = dget(parent);
1facf9fc 14825+ }
4a4d8108 14826+}
1facf9fc 14827+
4a4d8108
AM
14828+/* ---------------------------------------------------------------------- */
14829+
027c5e7a 14830+struct au_branch;
4a4d8108
AM
14831+#ifdef CONFIG_AUFS_HNOTIFY
14832+struct au_hnotify_op {
14833+ void (*ctl)(struct au_hinode *hinode, int do_set);
027c5e7a 14834+ int (*alloc)(struct au_hinode *hinode);
7eafdf33
AM
14835+
14836+ /*
14837+ * if it returns true, the the caller should free hinode->hi_notify,
14838+ * otherwise ->free() frees it.
14839+ */
14840+ int (*free)(struct au_hinode *hinode,
14841+ struct au_hnotify *hn) __must_check;
4a4d8108
AM
14842+
14843+ void (*fin)(void);
14844+ int (*init)(void);
027c5e7a
AM
14845+
14846+ int (*reset_br)(unsigned int udba, struct au_branch *br, int perm);
14847+ void (*fin_br)(struct au_branch *br);
14848+ int (*init_br)(struct au_branch *br, int perm);
4a4d8108
AM
14849+};
14850+
14851+/* hnotify.c */
027c5e7a 14852+int au_hn_alloc(struct au_hinode *hinode, struct inode *inode);
4a4d8108
AM
14853+void au_hn_free(struct au_hinode *hinode);
14854+void au_hn_ctl(struct au_hinode *hinode, int do_set);
14855+void au_hn_reset(struct inode *inode, unsigned int flags);
14856+int au_hnotify(struct inode *h_dir, struct au_hnotify *hnotify, u32 mask,
14857+ struct qstr *h_child_qstr, struct inode *h_child_inode);
027c5e7a
AM
14858+int au_hnotify_reset_br(unsigned int udba, struct au_branch *br, int perm);
14859+int au_hnotify_init_br(struct au_branch *br, int perm);
14860+void au_hnotify_fin_br(struct au_branch *br);
4a4d8108
AM
14861+int __init au_hnotify_init(void);
14862+void au_hnotify_fin(void);
14863+
7f207e10 14864+/* hfsnotify.c */
4a4d8108
AM
14865+extern const struct au_hnotify_op au_hnotify_op;
14866+
14867+static inline
14868+void au_hn_init(struct au_hinode *hinode)
14869+{
14870+ hinode->hi_notify = NULL;
1308ab2a 14871+}
14872+
53392da6
AM
14873+static inline struct au_hnotify *au_hn(struct au_hinode *hinode)
14874+{
14875+ return hinode->hi_notify;
14876+}
14877+
4a4d8108
AM
14878+#else
14879+static inline
14880+int au_hn_alloc(struct au_hinode *hinode __maybe_unused,
027c5e7a 14881+ struct inode *inode __maybe_unused)
1308ab2a 14882+{
4a4d8108
AM
14883+ return -EOPNOTSUPP;
14884+}
1308ab2a 14885+
53392da6
AM
14886+static inline struct au_hnotify *au_hn(struct au_hinode *hinode)
14887+{
14888+ return NULL;
14889+}
14890+
4a4d8108
AM
14891+AuStubVoid(au_hn_free, struct au_hinode *hinode __maybe_unused)
14892+AuStubVoid(au_hn_ctl, struct au_hinode *hinode __maybe_unused,
14893+ int do_set __maybe_unused)
14894+AuStubVoid(au_hn_reset, struct inode *inode __maybe_unused,
14895+ unsigned int flags __maybe_unused)
027c5e7a
AM
14896+AuStubInt0(au_hnotify_reset_br, unsigned int udba __maybe_unused,
14897+ struct au_branch *br __maybe_unused,
14898+ int perm __maybe_unused)
14899+AuStubInt0(au_hnotify_init_br, struct au_branch *br __maybe_unused,
14900+ int perm __maybe_unused)
14901+AuStubVoid(au_hnotify_fin_br, struct au_branch *br __maybe_unused)
4a4d8108
AM
14902+AuStubInt0(__init au_hnotify_init, void)
14903+AuStubVoid(au_hnotify_fin, void)
14904+AuStubVoid(au_hn_init, struct au_hinode *hinode __maybe_unused)
14905+#endif /* CONFIG_AUFS_HNOTIFY */
14906+
14907+static inline void au_hn_suspend(struct au_hinode *hdir)
14908+{
14909+ au_hn_ctl(hdir, /*do_set*/0);
1308ab2a 14910+}
14911+
4a4d8108 14912+static inline void au_hn_resume(struct au_hinode *hdir)
1308ab2a 14913+{
4a4d8108
AM
14914+ au_hn_ctl(hdir, /*do_set*/1);
14915+}
1308ab2a 14916+
4a4d8108
AM
14917+static inline void au_hn_imtx_lock(struct au_hinode *hdir)
14918+{
14919+ mutex_lock(&hdir->hi_inode->i_mutex);
14920+ au_hn_suspend(hdir);
14921+}
dece6358 14922+
4a4d8108
AM
14923+static inline void au_hn_imtx_lock_nested(struct au_hinode *hdir,
14924+ unsigned int sc __maybe_unused)
14925+{
14926+ mutex_lock_nested(&hdir->hi_inode->i_mutex, sc);
14927+ au_hn_suspend(hdir);
1facf9fc 14928+}
1facf9fc 14929+
4a4d8108
AM
14930+static inline void au_hn_imtx_unlock(struct au_hinode *hdir)
14931+{
14932+ au_hn_resume(hdir);
14933+ mutex_unlock(&hdir->hi_inode->i_mutex);
14934+}
14935+
14936+#endif /* __KERNEL__ */
14937+#endif /* __AUFS_INODE_H__ */
7f207e10
AM
14938diff -urN /usr/share/empty/fs/aufs/ioctl.c linux/fs/aufs/ioctl.c
14939--- /usr/share/empty/fs/aufs/ioctl.c 1970-01-01 01:00:00.000000000 +0100
0c3ec466 14940+++ linux/fs/aufs/ioctl.c 2012-07-22 19:57:03.164337936 +0200
f6c5ef8b 14941@@ -0,0 +1,196 @@
4a4d8108 14942+/*
f6c5ef8b 14943+ * Copyright (C) 2005-2012 Junjiro R. Okajima
4a4d8108
AM
14944+ *
14945+ * This program, aufs is free software; you can redistribute it and/or modify
14946+ * it under the terms of the GNU General Public License as published by
14947+ * the Free Software Foundation; either version 2 of the License, or
14948+ * (at your option) any later version.
14949+ *
14950+ * This program is distributed in the hope that it will be useful,
14951+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
14952+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14953+ * GNU General Public License for more details.
14954+ *
14955+ * You should have received a copy of the GNU General Public License
14956+ * along with this program; if not, write to the Free Software
14957+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
14958+ */
14959+
14960+/*
14961+ * ioctl
14962+ * plink-management and readdir in userspace.
14963+ * assist the pathconf(3) wrapper library.
14964+ */
14965+
4a4d8108
AM
14966+#include "aufs.h"
14967+
1e00d052 14968+static int au_wbr_fd(struct path *path, struct aufs_wbr_fd __user *arg)
4a4d8108
AM
14969+{
14970+ int err, fd;
14971+ aufs_bindex_t wbi, bindex, bend;
14972+ struct file *h_file;
14973+ struct super_block *sb;
14974+ struct dentry *root;
1e00d052
AM
14975+ struct au_branch *br;
14976+ struct aufs_wbr_fd wbrfd = {
14977+ .oflags = au_dir_roflags,
14978+ .brid = -1
14979+ };
14980+ const int valid = O_RDONLY | O_NONBLOCK | O_LARGEFILE | O_DIRECTORY
14981+ | O_NOATIME | O_CLOEXEC;
4a4d8108 14982+
1e00d052
AM
14983+ AuDebugOn(wbrfd.oflags & ~valid);
14984+
14985+ if (arg) {
14986+ err = copy_from_user(&wbrfd, arg, sizeof(wbrfd));
14987+ if (unlikely(err)) {
14988+ err = -EFAULT;
14989+ goto out;
14990+ }
14991+
14992+ err = -EINVAL;
14993+ AuDbg("wbrfd{0%o, %d}\n", wbrfd.oflags, wbrfd.brid);
14994+ wbrfd.oflags |= au_dir_roflags;
14995+ AuDbg("0%o\n", wbrfd.oflags);
14996+ if (unlikely(wbrfd.oflags & ~valid))
14997+ goto out;
14998+ }
14999+
15000+ fd = get_unused_fd();
15001+ err = fd;
15002+ if (unlikely(fd < 0))
4a4d8108 15003+ goto out;
4a4d8108 15004+
1e00d052 15005+ h_file = ERR_PTR(-EINVAL);
4a4d8108 15006+ wbi = 0;
1e00d052 15007+ br = NULL;
4a4d8108
AM
15008+ sb = path->dentry->d_sb;
15009+ root = sb->s_root;
15010+ aufs_read_lock(root, AuLock_IR);
1e00d052
AM
15011+ bend = au_sbend(sb);
15012+ if (wbrfd.brid >= 0) {
15013+ wbi = au_br_index(sb, wbrfd.brid);
15014+ if (unlikely(wbi < 0 || wbi > bend))
15015+ goto out_unlock;
15016+ }
15017+
15018+ h_file = ERR_PTR(-ENOENT);
15019+ br = au_sbr(sb, wbi);
15020+ if (!au_br_writable(br->br_perm)) {
15021+ if (arg)
15022+ goto out_unlock;
15023+
15024+ bindex = wbi + 1;
15025+ wbi = -1;
15026+ for (; bindex <= bend; bindex++) {
15027+ br = au_sbr(sb, bindex);
15028+ if (au_br_writable(br->br_perm)) {
4a4d8108 15029+ wbi = bindex;
1e00d052 15030+ br = au_sbr(sb, wbi);
4a4d8108
AM
15031+ break;
15032+ }
15033+ }
4a4d8108
AM
15034+ }
15035+ AuDbg("wbi %d\n", wbi);
1e00d052
AM
15036+ if (wbi >= 0)
15037+ h_file = au_h_open(root, wbi, wbrfd.oflags, NULL);
15038+
15039+out_unlock:
4a4d8108
AM
15040+ aufs_read_unlock(root, AuLock_IR);
15041+ err = PTR_ERR(h_file);
15042+ if (IS_ERR(h_file))
15043+ goto out_fd;
15044+
1e00d052 15045+ atomic_dec(&br->br_count); /* cf. au_h_open() */
4a4d8108
AM
15046+ fd_install(fd, h_file);
15047+ err = fd;
15048+ goto out; /* success */
15049+
4f0767ce 15050+out_fd:
4a4d8108 15051+ put_unused_fd(fd);
4f0767ce 15052+out:
1e00d052 15053+ AuTraceErr(err);
4a4d8108
AM
15054+ return err;
15055+}
15056+
15057+/* ---------------------------------------------------------------------- */
15058+
15059+long aufs_ioctl_dir(struct file *file, unsigned int cmd, unsigned long arg)
15060+{
15061+ long err;
15062+
15063+ switch (cmd) {
4a4d8108
AM
15064+ case AUFS_CTL_RDU:
15065+ case AUFS_CTL_RDU_INO:
15066+ err = au_rdu_ioctl(file, cmd, arg);
15067+ break;
15068+
15069+ case AUFS_CTL_WBR_FD:
1e00d052 15070+ err = au_wbr_fd(&file->f_path, (void __user *)arg);
4a4d8108
AM
15071+ break;
15072+
027c5e7a
AM
15073+ case AUFS_CTL_IBUSY:
15074+ err = au_ibusy_ioctl(file, arg);
15075+ break;
15076+
4a4d8108
AM
15077+ default:
15078+ /* do not call the lower */
15079+ AuDbg("0x%x\n", cmd);
15080+ err = -ENOTTY;
15081+ }
15082+
15083+ AuTraceErr(err);
15084+ return err;
15085+}
15086+
15087+long aufs_ioctl_nondir(struct file *file, unsigned int cmd, unsigned long arg)
15088+{
15089+ long err;
15090+
15091+ switch (cmd) {
15092+ case AUFS_CTL_WBR_FD:
1e00d052 15093+ err = au_wbr_fd(&file->f_path, (void __user *)arg);
4a4d8108
AM
15094+ break;
15095+
15096+ default:
15097+ /* do not call the lower */
15098+ AuDbg("0x%x\n", cmd);
15099+ err = -ENOTTY;
15100+ }
15101+
15102+ AuTraceErr(err);
15103+ return err;
15104+}
b752ccd1
AM
15105+
15106+#ifdef CONFIG_COMPAT
15107+long aufs_compat_ioctl_dir(struct file *file, unsigned int cmd,
15108+ unsigned long arg)
15109+{
15110+ long err;
15111+
15112+ switch (cmd) {
15113+ case AUFS_CTL_RDU:
15114+ case AUFS_CTL_RDU_INO:
15115+ err = au_rdu_compat_ioctl(file, cmd, arg);
15116+ break;
15117+
027c5e7a
AM
15118+ case AUFS_CTL_IBUSY:
15119+ err = au_ibusy_compat_ioctl(file, arg);
15120+ break;
15121+
b752ccd1
AM
15122+ default:
15123+ err = aufs_ioctl_dir(file, cmd, arg);
15124+ }
15125+
15126+ AuTraceErr(err);
15127+ return err;
15128+}
15129+
15130+#if 0 /* unused yet */
15131+long aufs_compat_ioctl_nondir(struct file *file, unsigned int cmd,
15132+ unsigned long arg)
15133+{
15134+ return aufs_ioctl_nondir(file, cmd, (unsigned long)compat_ptr(arg));
15135+}
15136+#endif
15137+#endif
7f207e10
AM
15138diff -urN /usr/share/empty/fs/aufs/i_op_add.c linux/fs/aufs/i_op_add.c
15139--- /usr/share/empty/fs/aufs/i_op_add.c 1970-01-01 01:00:00.000000000 +0100
0c3ec466 15140+++ linux/fs/aufs/i_op_add.c 2012-07-22 19:57:03.164337936 +0200
7eafdf33 15141@@ -0,0 +1,712 @@
4a4d8108 15142+/*
f6c5ef8b 15143+ * Copyright (C) 2005-2012 Junjiro R. Okajima
4a4d8108
AM
15144+ *
15145+ * This program, aufs is free software; you can redistribute it and/or modify
15146+ * it under the terms of the GNU General Public License as published by
15147+ * the Free Software Foundation; either version 2 of the License, or
15148+ * (at your option) any later version.
15149+ *
15150+ * This program is distributed in the hope that it will be useful,
15151+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
15152+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15153+ * GNU General Public License for more details.
15154+ *
15155+ * You should have received a copy of the GNU General Public License
15156+ * along with this program; if not, write to the Free Software
15157+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
15158+ */
15159+
15160+/*
15161+ * inode operations (add entry)
15162+ */
15163+
15164+#include "aufs.h"
15165+
15166+/*
15167+ * final procedure of adding a new entry, except link(2).
15168+ * remove whiteout, instantiate, copyup the parent dir's times and size
15169+ * and update version.
15170+ * if it failed, re-create the removed whiteout.
15171+ */
15172+static int epilog(struct inode *dir, aufs_bindex_t bindex,
15173+ struct dentry *wh_dentry, struct dentry *dentry)
15174+{
15175+ int err, rerr;
15176+ aufs_bindex_t bwh;
15177+ struct path h_path;
15178+ struct inode *inode, *h_dir;
15179+ struct dentry *wh;
15180+
15181+ bwh = -1;
15182+ if (wh_dentry) {
15183+ h_dir = wh_dentry->d_parent->d_inode; /* dir inode is locked */
15184+ IMustLock(h_dir);
15185+ AuDebugOn(au_h_iptr(dir, bindex) != h_dir);
15186+ bwh = au_dbwh(dentry);
15187+ h_path.dentry = wh_dentry;
15188+ h_path.mnt = au_sbr_mnt(dir->i_sb, bindex);
15189+ err = au_wh_unlink_dentry(au_h_iptr(dir, bindex), &h_path,
15190+ dentry);
15191+ if (unlikely(err))
15192+ goto out;
15193+ }
15194+
15195+ inode = au_new_inode(dentry, /*must_new*/1);
15196+ if (!IS_ERR(inode)) {
15197+ d_instantiate(dentry, inode);
15198+ dir = dentry->d_parent->d_inode; /* dir inode is locked */
15199+ IMustLock(dir);
15200+ if (au_ibstart(dir) == au_dbstart(dentry))
15201+ au_cpup_attr_timesizes(dir);
15202+ dir->i_version++;
15203+ return 0; /* success */
15204+ }
15205+
15206+ err = PTR_ERR(inode);
15207+ if (!wh_dentry)
15208+ goto out;
15209+
15210+ /* revert */
15211+ /* dir inode is locked */
15212+ wh = au_wh_create(dentry, bwh, wh_dentry->d_parent);
15213+ rerr = PTR_ERR(wh);
15214+ if (IS_ERR(wh)) {
15215+ AuIOErr("%.*s reverting whiteout failed(%d, %d)\n",
15216+ AuDLNPair(dentry), err, rerr);
15217+ err = -EIO;
15218+ } else
15219+ dput(wh);
15220+
4f0767ce 15221+out:
4a4d8108
AM
15222+ return err;
15223+}
15224+
027c5e7a
AM
15225+static int au_d_may_add(struct dentry *dentry)
15226+{
15227+ int err;
15228+
15229+ err = 0;
15230+ if (unlikely(d_unhashed(dentry)))
15231+ err = -ENOENT;
15232+ if (unlikely(dentry->d_inode))
15233+ err = -EEXIST;
15234+ return err;
15235+}
15236+
4a4d8108
AM
15237+/*
15238+ * simple tests for the adding inode operations.
15239+ * following the checks in vfs, plus the parent-child relationship.
15240+ */
15241+int au_may_add(struct dentry *dentry, aufs_bindex_t bindex,
15242+ struct dentry *h_parent, int isdir)
15243+{
15244+ int err;
15245+ umode_t h_mode;
15246+ struct dentry *h_dentry;
15247+ struct inode *h_inode;
15248+
15249+ err = -ENAMETOOLONG;
15250+ if (unlikely(dentry->d_name.len > AUFS_MAX_NAMELEN))
15251+ goto out;
15252+
15253+ h_dentry = au_h_dptr(dentry, bindex);
15254+ h_inode = h_dentry->d_inode;
15255+ if (!dentry->d_inode) {
15256+ err = -EEXIST;
15257+ if (unlikely(h_inode))
15258+ goto out;
15259+ } else {
15260+ /* rename(2) case */
15261+ err = -EIO;
15262+ if (unlikely(!h_inode || !h_inode->i_nlink))
15263+ goto out;
15264+
15265+ h_mode = h_inode->i_mode;
15266+ if (!isdir) {
15267+ err = -EISDIR;
15268+ if (unlikely(S_ISDIR(h_mode)))
15269+ goto out;
15270+ } else if (unlikely(!S_ISDIR(h_mode))) {
15271+ err = -ENOTDIR;
15272+ goto out;
15273+ }
15274+ }
15275+
15276+ err = 0;
15277+ /* expected parent dir is locked */
15278+ if (unlikely(h_parent != h_dentry->d_parent))
15279+ err = -EIO;
15280+
4f0767ce 15281+out:
4a4d8108
AM
15282+ AuTraceErr(err);
15283+ return err;
15284+}
15285+
15286+/*
15287+ * initial procedure of adding a new entry.
15288+ * prepare writable branch and the parent dir, lock it,
15289+ * and lookup whiteout for the new entry.
15290+ */
15291+static struct dentry*
15292+lock_hdir_lkup_wh(struct dentry *dentry, struct au_dtime *dt,
15293+ struct dentry *src_dentry, struct au_pin *pin,
15294+ struct au_wr_dir_args *wr_dir_args)
15295+{
15296+ struct dentry *wh_dentry, *h_parent;
15297+ struct super_block *sb;
15298+ struct au_branch *br;
15299+ int err;
15300+ unsigned int udba;
15301+ aufs_bindex_t bcpup;
15302+
15303+ AuDbg("%.*s\n", AuDLNPair(dentry));
15304+
15305+ err = au_wr_dir(dentry, src_dentry, wr_dir_args);
15306+ bcpup = err;
15307+ wh_dentry = ERR_PTR(err);
15308+ if (unlikely(err < 0))
15309+ goto out;
15310+
15311+ sb = dentry->d_sb;
15312+ udba = au_opt_udba(sb);
15313+ err = au_pin(pin, dentry, bcpup, udba,
15314+ AuPin_DI_LOCKED | AuPin_MNT_WRITE);
15315+ wh_dentry = ERR_PTR(err);
15316+ if (unlikely(err))
15317+ goto out;
15318+
15319+ h_parent = au_pinned_h_parent(pin);
15320+ if (udba != AuOpt_UDBA_NONE
15321+ && au_dbstart(dentry) == bcpup)
15322+ err = au_may_add(dentry, bcpup, h_parent,
15323+ au_ftest_wrdir(wr_dir_args->flags, ISDIR));
15324+ else if (unlikely(dentry->d_name.len > AUFS_MAX_NAMELEN))
15325+ err = -ENAMETOOLONG;
15326+ wh_dentry = ERR_PTR(err);
15327+ if (unlikely(err))
15328+ goto out_unpin;
15329+
15330+ br = au_sbr(sb, bcpup);
15331+ if (dt) {
15332+ struct path tmp = {
15333+ .dentry = h_parent,
15334+ .mnt = br->br_mnt
15335+ };
15336+ au_dtime_store(dt, au_pinned_parent(pin), &tmp);
15337+ }
15338+
15339+ wh_dentry = NULL;
15340+ if (bcpup != au_dbwh(dentry))
15341+ goto out; /* success */
15342+
15343+ wh_dentry = au_wh_lkup(h_parent, &dentry->d_name, br);
15344+
4f0767ce 15345+out_unpin:
4a4d8108
AM
15346+ if (IS_ERR(wh_dentry))
15347+ au_unpin(pin);
4f0767ce 15348+out:
4a4d8108
AM
15349+ return wh_dentry;
15350+}
15351+
15352+/* ---------------------------------------------------------------------- */
15353+
15354+enum { Mknod, Symlink, Creat };
15355+struct simple_arg {
15356+ int type;
15357+ union {
15358+ struct {
7eafdf33 15359+ umode_t mode;
4a4d8108
AM
15360+ struct nameidata *nd;
15361+ } c;
15362+ struct {
15363+ const char *symname;
15364+ } s;
15365+ struct {
7eafdf33 15366+ umode_t mode;
4a4d8108
AM
15367+ dev_t dev;
15368+ } m;
15369+ } u;
15370+};
15371+
15372+static int add_simple(struct inode *dir, struct dentry *dentry,
15373+ struct simple_arg *arg)
15374+{
15375+ int err;
15376+ aufs_bindex_t bstart;
15377+ unsigned char created;
15378+ struct au_dtime dt;
15379+ struct au_pin pin;
15380+ struct path h_path;
15381+ struct dentry *wh_dentry, *parent;
15382+ struct inode *h_dir;
15383+ struct au_wr_dir_args wr_dir_args = {
15384+ .force_btgt = -1,
15385+ .flags = AuWrDir_ADD_ENTRY
15386+ };
15387+
15388+ AuDbg("%.*s\n", AuDLNPair(dentry));
15389+ IMustLock(dir);
15390+
15391+ parent = dentry->d_parent; /* dir inode is locked */
027c5e7a
AM
15392+ err = aufs_read_lock(dentry, AuLock_DW | AuLock_GEN);
15393+ if (unlikely(err))
15394+ goto out;
15395+ err = au_d_may_add(dentry);
15396+ if (unlikely(err))
15397+ goto out_unlock;
4a4d8108
AM
15398+ di_write_lock_parent(parent);
15399+ wh_dentry = lock_hdir_lkup_wh(dentry, &dt, /*src_dentry*/NULL, &pin,
15400+ &wr_dir_args);
15401+ err = PTR_ERR(wh_dentry);
15402+ if (IS_ERR(wh_dentry))
027c5e7a 15403+ goto out_parent;
4a4d8108
AM
15404+
15405+ bstart = au_dbstart(dentry);
15406+ h_path.dentry = au_h_dptr(dentry, bstart);
15407+ h_path.mnt = au_sbr_mnt(dentry->d_sb, bstart);
15408+ h_dir = au_pinned_h_dir(&pin);
15409+ switch (arg->type) {
15410+ case Creat:
15411+ err = vfsub_create(h_dir, &h_path, arg->u.c.mode);
15412+ break;
15413+ case Symlink:
15414+ err = vfsub_symlink(h_dir, &h_path, arg->u.s.symname);
15415+ break;
15416+ case Mknod:
15417+ err = vfsub_mknod(h_dir, &h_path, arg->u.m.mode, arg->u.m.dev);
15418+ break;
15419+ default:
15420+ BUG();
15421+ }
15422+ created = !err;
15423+ if (!err)
15424+ err = epilog(dir, bstart, wh_dentry, dentry);
15425+
15426+ /* revert */
15427+ if (unlikely(created && err && h_path.dentry->d_inode)) {
15428+ int rerr;
15429+ rerr = vfsub_unlink(h_dir, &h_path, /*force*/0);
15430+ if (rerr) {
15431+ AuIOErr("%.*s revert failure(%d, %d)\n",
15432+ AuDLNPair(dentry), err, rerr);
15433+ err = -EIO;
15434+ }
15435+ au_dtime_revert(&dt);
4a4d8108
AM
15436+ }
15437+
15438+ au_unpin(&pin);
15439+ dput(wh_dentry);
15440+
027c5e7a
AM
15441+out_parent:
15442+ di_write_unlock(parent);
15443+out_unlock:
4a4d8108
AM
15444+ if (unlikely(err)) {
15445+ au_update_dbstart(dentry);
15446+ d_drop(dentry);
15447+ }
4a4d8108 15448+ aufs_read_unlock(dentry, AuLock_DW);
027c5e7a 15449+out:
4a4d8108
AM
15450+ return err;
15451+}
15452+
7eafdf33
AM
15453+int aufs_mknod(struct inode *dir, struct dentry *dentry, umode_t mode,
15454+ dev_t dev)
4a4d8108
AM
15455+{
15456+ struct simple_arg arg = {
15457+ .type = Mknod,
15458+ .u.m = {
15459+ .mode = mode,
15460+ .dev = dev
15461+ }
15462+ };
15463+ return add_simple(dir, dentry, &arg);
15464+}
15465+
15466+int aufs_symlink(struct inode *dir, struct dentry *dentry, const char *symname)
15467+{
15468+ struct simple_arg arg = {
15469+ .type = Symlink,
15470+ .u.s.symname = symname
15471+ };
15472+ return add_simple(dir, dentry, &arg);
15473+}
15474+
7eafdf33 15475+int aufs_create(struct inode *dir, struct dentry *dentry, umode_t mode,
4a4d8108
AM
15476+ struct nameidata *nd)
15477+{
15478+ struct simple_arg arg = {
15479+ .type = Creat,
15480+ .u.c = {
15481+ .mode = mode,
15482+ .nd = nd
15483+ }
15484+ };
15485+ return add_simple(dir, dentry, &arg);
15486+}
15487+
15488+/* ---------------------------------------------------------------------- */
15489+
15490+struct au_link_args {
15491+ aufs_bindex_t bdst, bsrc;
15492+ struct au_pin pin;
15493+ struct path h_path;
15494+ struct dentry *src_parent, *parent;
15495+};
15496+
15497+static int au_cpup_before_link(struct dentry *src_dentry,
15498+ struct au_link_args *a)
15499+{
15500+ int err;
15501+ struct dentry *h_src_dentry;
15502+ struct mutex *h_mtx;
15503+ struct file *h_file;
15504+
15505+ di_read_lock_parent(a->src_parent, AuLock_IR);
15506+ err = au_test_and_cpup_dirs(src_dentry, a->bdst);
15507+ if (unlikely(err))
15508+ goto out;
15509+
15510+ h_src_dentry = au_h_dptr(src_dentry, a->bsrc);
15511+ h_mtx = &h_src_dentry->d_inode->i_mutex;
15512+ err = au_pin(&a->pin, src_dentry, a->bdst,
15513+ au_opt_udba(src_dentry->d_sb),
15514+ AuPin_DI_LOCKED | AuPin_MNT_WRITE);
15515+ if (unlikely(err))
15516+ goto out;
15517+ mutex_lock_nested(h_mtx, 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
1e00d052 15523+ err = au_sio_cpup_simple(src_dentry, a->bdst, -1,
4a4d8108
AM
15524+ AuCpup_DTIME /* | AuCpup_KEEPLINO */);
15525+ mutex_unlock(h_mtx);
15526+ au_h_open_post(src_dentry, a->bsrc, h_file);
15527+ au_unpin(&a->pin);
15528+
4f0767ce 15529+out:
4a4d8108
AM
15530+ di_read_unlock(a->src_parent, AuLock_IR);
15531+ return err;
15532+}
15533+
15534+static int au_cpup_or_link(struct dentry *src_dentry, struct au_link_args *a)
15535+{
15536+ int err;
15537+ unsigned char plink;
15538+ struct inode *h_inode, *inode;
15539+ struct dentry *h_src_dentry;
15540+ struct super_block *sb;
15541+ struct file *h_file;
15542+
15543+ plink = 0;
15544+ h_inode = NULL;
15545+ sb = src_dentry->d_sb;
15546+ inode = src_dentry->d_inode;
15547+ if (au_ibstart(inode) <= a->bdst)
15548+ h_inode = au_h_iptr(inode, a->bdst);
15549+ if (!h_inode || !h_inode->i_nlink) {
15550+ /* copyup src_dentry as the name of dentry. */
15551+ au_set_dbstart(src_dentry, a->bdst);
15552+ au_set_h_dptr(src_dentry, a->bdst, dget(a->h_path.dentry));
15553+ h_inode = au_h_dptr(src_dentry, a->bsrc)->d_inode;
15554+ mutex_lock_nested(&h_inode->i_mutex, AuLsc_I_CHILD);
15555+ h_file = au_h_open_pre(src_dentry, a->bsrc);
15556+ if (IS_ERR(h_file)) {
15557+ err = PTR_ERR(h_file);
15558+ h_file = NULL;
15559+ } else
15560+ err = au_sio_cpup_single(src_dentry, a->bdst, a->bsrc,
15561+ -1, AuCpup_KEEPLINO,
15562+ a->parent);
15563+ mutex_unlock(&h_inode->i_mutex);
15564+ au_h_open_post(src_dentry, a->bsrc, h_file);
15565+ au_set_h_dptr(src_dentry, a->bdst, NULL);
15566+ au_set_dbstart(src_dentry, a->bsrc);
15567+ } else {
15568+ /* the inode of src_dentry already exists on a.bdst branch */
15569+ h_src_dentry = d_find_alias(h_inode);
15570+ if (!h_src_dentry && au_plink_test(inode)) {
15571+ plink = 1;
15572+ h_src_dentry = au_plink_lkup(inode, a->bdst);
15573+ err = PTR_ERR(h_src_dentry);
15574+ if (IS_ERR(h_src_dentry))
15575+ goto out;
15576+
15577+ if (unlikely(!h_src_dentry->d_inode)) {
15578+ dput(h_src_dentry);
15579+ h_src_dentry = NULL;
15580+ }
15581+
15582+ }
15583+ if (h_src_dentry) {
15584+ err = vfsub_link(h_src_dentry, au_pinned_h_dir(&a->pin),
15585+ &a->h_path);
15586+ dput(h_src_dentry);
15587+ } else {
15588+ AuIOErr("no dentry found for hi%lu on b%d\n",
15589+ h_inode->i_ino, a->bdst);
15590+ err = -EIO;
15591+ }
15592+ }
15593+
15594+ if (!err && !plink)
15595+ au_plink_append(inode, a->bdst, a->h_path.dentry);
15596+
15597+out:
2cbb1c4b 15598+ AuTraceErr(err);
4a4d8108
AM
15599+ return err;
15600+}
15601+
15602+int aufs_link(struct dentry *src_dentry, struct inode *dir,
15603+ struct dentry *dentry)
15604+{
15605+ int err, rerr;
15606+ struct au_dtime dt;
15607+ struct au_link_args *a;
15608+ struct dentry *wh_dentry, *h_src_dentry;
15609+ struct inode *inode;
15610+ struct super_block *sb;
15611+ struct au_wr_dir_args wr_dir_args = {
15612+ /* .force_btgt = -1, */
15613+ .flags = AuWrDir_ADD_ENTRY
15614+ };
15615+
15616+ IMustLock(dir);
15617+ inode = src_dentry->d_inode;
15618+ IMustLock(inode);
15619+
4a4d8108
AM
15620+ err = -ENOMEM;
15621+ a = kzalloc(sizeof(*a), GFP_NOFS);
15622+ if (unlikely(!a))
15623+ goto out;
15624+
15625+ a->parent = dentry->d_parent; /* dir inode is locked */
027c5e7a
AM
15626+ err = aufs_read_and_write_lock2(dentry, src_dentry,
15627+ AuLock_NOPLM | AuLock_GEN);
e49829fe
JR
15628+ if (unlikely(err))
15629+ goto out_kfree;
027c5e7a
AM
15630+ err = au_d_hashed_positive(src_dentry);
15631+ if (unlikely(err))
15632+ goto out_unlock;
15633+ err = au_d_may_add(dentry);
15634+ if (unlikely(err))
15635+ goto out_unlock;
e49829fe 15636+
4a4d8108 15637+ a->src_parent = dget_parent(src_dentry);
2cbb1c4b 15638+ wr_dir_args.force_btgt = au_ibstart(inode);
4a4d8108
AM
15639+
15640+ di_write_lock_parent(a->parent);
15641+ wr_dir_args.force_btgt = au_wbr(dentry, wr_dir_args.force_btgt);
15642+ wh_dentry = lock_hdir_lkup_wh(dentry, &dt, src_dentry, &a->pin,
15643+ &wr_dir_args);
15644+ err = PTR_ERR(wh_dentry);
15645+ if (IS_ERR(wh_dentry))
027c5e7a 15646+ goto out_parent;
4a4d8108
AM
15647+
15648+ err = 0;
15649+ sb = dentry->d_sb;
15650+ a->bdst = au_dbstart(dentry);
15651+ a->h_path.dentry = au_h_dptr(dentry, a->bdst);
15652+ a->h_path.mnt = au_sbr_mnt(sb, a->bdst);
2cbb1c4b
JR
15653+ a->bsrc = au_ibstart(inode);
15654+ h_src_dentry = au_h_d_alias(src_dentry, a->bsrc);
15655+ if (!h_src_dentry) {
15656+ a->bsrc = au_dbstart(src_dentry);
15657+ h_src_dentry = au_h_d_alias(src_dentry, a->bsrc);
15658+ AuDebugOn(!h_src_dentry);
15659+ } else if (IS_ERR(h_src_dentry))
15660+ goto out_parent;
15661+
4a4d8108
AM
15662+ if (au_opt_test(au_mntflags(sb), PLINK)) {
15663+ if (a->bdst < a->bsrc
15664+ /* && h_src_dentry->d_sb != a->h_path.dentry->d_sb */)
15665+ err = au_cpup_or_link(src_dentry, a);
2cbb1c4b 15666+ else
4a4d8108
AM
15667+ err = vfsub_link(h_src_dentry, au_pinned_h_dir(&a->pin),
15668+ &a->h_path);
2cbb1c4b 15669+ dput(h_src_dentry);
4a4d8108
AM
15670+ } else {
15671+ /*
15672+ * copyup src_dentry to the branch we process,
15673+ * and then link(2) to it.
15674+ */
2cbb1c4b 15675+ dput(h_src_dentry);
4a4d8108
AM
15676+ if (a->bdst < a->bsrc
15677+ /* && h_src_dentry->d_sb != a->h_path.dentry->d_sb */) {
15678+ au_unpin(&a->pin);
15679+ di_write_unlock(a->parent);
15680+ err = au_cpup_before_link(src_dentry, a);
15681+ di_write_lock_parent(a->parent);
15682+ if (!err)
15683+ err = au_pin(&a->pin, dentry, a->bdst,
15684+ au_opt_udba(sb),
15685+ AuPin_DI_LOCKED | AuPin_MNT_WRITE);
15686+ if (unlikely(err))
15687+ goto out_wh;
15688+ }
15689+ if (!err) {
15690+ h_src_dentry = au_h_dptr(src_dentry, a->bdst);
15691+ err = -ENOENT;
15692+ if (h_src_dentry && h_src_dentry->d_inode)
15693+ err = vfsub_link(h_src_dentry,
15694+ au_pinned_h_dir(&a->pin),
15695+ &a->h_path);
15696+ }
15697+ }
15698+ if (unlikely(err))
15699+ goto out_unpin;
15700+
15701+ if (wh_dentry) {
15702+ a->h_path.dentry = wh_dentry;
15703+ err = au_wh_unlink_dentry(au_pinned_h_dir(&a->pin), &a->h_path,
15704+ dentry);
15705+ if (unlikely(err))
15706+ goto out_revert;
15707+ }
15708+
15709+ dir->i_version++;
15710+ if (au_ibstart(dir) == au_dbstart(dentry))
15711+ au_cpup_attr_timesizes(dir);
15712+ inc_nlink(inode);
15713+ inode->i_ctime = dir->i_ctime;
027c5e7a
AM
15714+ d_instantiate(dentry, au_igrab(inode));
15715+ if (d_unhashed(a->h_path.dentry))
4a4d8108
AM
15716+ /* some filesystem calls d_drop() */
15717+ d_drop(dentry);
15718+ goto out_unpin; /* success */
15719+
4f0767ce 15720+out_revert:
4a4d8108 15721+ rerr = vfsub_unlink(au_pinned_h_dir(&a->pin), &a->h_path, /*force*/0);
027c5e7a
AM
15722+ if (unlikely(rerr)) {
15723+ AuIOErr("%.*s reverting failed(%d, %d)\n",
15724+ AuDLNPair(dentry), err, rerr);
15725+ err = -EIO;
15726+ }
4a4d8108 15727+ au_dtime_revert(&dt);
4f0767ce 15728+out_unpin:
4a4d8108 15729+ au_unpin(&a->pin);
4f0767ce 15730+out_wh:
4a4d8108 15731+ dput(wh_dentry);
027c5e7a
AM
15732+out_parent:
15733+ di_write_unlock(a->parent);
15734+ dput(a->src_parent);
4f0767ce 15735+out_unlock:
4a4d8108
AM
15736+ if (unlikely(err)) {
15737+ au_update_dbstart(dentry);
15738+ d_drop(dentry);
15739+ }
4a4d8108 15740+ aufs_read_and_write_unlock2(dentry, src_dentry);
e49829fe 15741+out_kfree:
4a4d8108 15742+ kfree(a);
4f0767ce 15743+out:
4a4d8108
AM
15744+ return err;
15745+}
15746+
7eafdf33 15747+int aufs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
4a4d8108
AM
15748+{
15749+ int err, rerr;
15750+ aufs_bindex_t bindex;
15751+ unsigned char diropq;
15752+ struct path h_path;
15753+ struct dentry *wh_dentry, *parent, *opq_dentry;
15754+ struct mutex *h_mtx;
15755+ struct super_block *sb;
15756+ struct {
15757+ struct au_pin pin;
15758+ struct au_dtime dt;
15759+ } *a; /* reduce the stack usage */
15760+ struct au_wr_dir_args wr_dir_args = {
15761+ .force_btgt = -1,
15762+ .flags = AuWrDir_ADD_ENTRY | AuWrDir_ISDIR
15763+ };
15764+
15765+ IMustLock(dir);
15766+
15767+ err = -ENOMEM;
15768+ a = kmalloc(sizeof(*a), GFP_NOFS);
15769+ if (unlikely(!a))
15770+ goto out;
15771+
027c5e7a
AM
15772+ err = aufs_read_lock(dentry, AuLock_DW | AuLock_GEN);
15773+ if (unlikely(err))
15774+ goto out_free;
15775+ err = au_d_may_add(dentry);
15776+ if (unlikely(err))
15777+ goto out_unlock;
15778+
4a4d8108
AM
15779+ parent = dentry->d_parent; /* dir inode is locked */
15780+ di_write_lock_parent(parent);
15781+ wh_dentry = lock_hdir_lkup_wh(dentry, &a->dt, /*src_dentry*/NULL,
15782+ &a->pin, &wr_dir_args);
15783+ err = PTR_ERR(wh_dentry);
15784+ if (IS_ERR(wh_dentry))
027c5e7a 15785+ goto out_parent;
4a4d8108
AM
15786+
15787+ sb = dentry->d_sb;
15788+ bindex = au_dbstart(dentry);
15789+ h_path.dentry = au_h_dptr(dentry, bindex);
15790+ h_path.mnt = au_sbr_mnt(sb, bindex);
15791+ err = vfsub_mkdir(au_pinned_h_dir(&a->pin), &h_path, mode);
15792+ if (unlikely(err))
027c5e7a 15793+ goto out_unpin;
4a4d8108
AM
15794+
15795+ /* make the dir opaque */
15796+ diropq = 0;
15797+ h_mtx = &h_path.dentry->d_inode->i_mutex;
15798+ if (wh_dentry
15799+ || au_opt_test(au_mntflags(sb), ALWAYS_DIROPQ)) {
15800+ mutex_lock_nested(h_mtx, AuLsc_I_CHILD);
15801+ opq_dentry = au_diropq_create(dentry, bindex);
15802+ mutex_unlock(h_mtx);
15803+ err = PTR_ERR(opq_dentry);
15804+ if (IS_ERR(opq_dentry))
15805+ goto out_dir;
15806+ dput(opq_dentry);
15807+ diropq = 1;
15808+ }
15809+
15810+ err = epilog(dir, bindex, wh_dentry, dentry);
15811+ if (!err) {
15812+ inc_nlink(dir);
027c5e7a 15813+ goto out_unpin; /* success */
4a4d8108
AM
15814+ }
15815+
15816+ /* revert */
15817+ if (diropq) {
15818+ AuLabel(revert opq);
15819+ mutex_lock_nested(h_mtx, AuLsc_I_CHILD);
15820+ rerr = au_diropq_remove(dentry, bindex);
15821+ mutex_unlock(h_mtx);
15822+ if (rerr) {
15823+ AuIOErr("%.*s reverting diropq failed(%d, %d)\n",
15824+ AuDLNPair(dentry), err, rerr);
15825+ err = -EIO;
15826+ }
15827+ }
15828+
4f0767ce 15829+out_dir:
4a4d8108
AM
15830+ AuLabel(revert dir);
15831+ rerr = vfsub_rmdir(au_pinned_h_dir(&a->pin), &h_path);
15832+ if (rerr) {
15833+ AuIOErr("%.*s reverting dir failed(%d, %d)\n",
15834+ AuDLNPair(dentry), err, rerr);
15835+ err = -EIO;
15836+ }
4a4d8108 15837+ au_dtime_revert(&a->dt);
027c5e7a 15838+out_unpin:
4a4d8108
AM
15839+ au_unpin(&a->pin);
15840+ dput(wh_dentry);
027c5e7a
AM
15841+out_parent:
15842+ di_write_unlock(parent);
15843+out_unlock:
4a4d8108
AM
15844+ if (unlikely(err)) {
15845+ au_update_dbstart(dentry);
15846+ d_drop(dentry);
15847+ }
4a4d8108 15848+ aufs_read_unlock(dentry, AuLock_DW);
027c5e7a 15849+out_free:
4a4d8108 15850+ kfree(a);
4f0767ce 15851+out:
4a4d8108
AM
15852+ return err;
15853+}
7f207e10
AM
15854diff -urN /usr/share/empty/fs/aufs/i_op.c linux/fs/aufs/i_op.c
15855--- /usr/share/empty/fs/aufs/i_op.c 1970-01-01 01:00:00.000000000 +0100
0c3ec466
AM
15856+++ linux/fs/aufs/i_op.c 2012-07-22 19:57:03.164337936 +0200
15857@@ -0,0 +1,1014 @@
4a4d8108 15858+/*
f6c5ef8b 15859+ * Copyright (C) 2005-2012 Junjiro R. Okajima
4a4d8108
AM
15860+ *
15861+ * This program, aufs is free software; you can redistribute it and/or modify
15862+ * it under the terms of the GNU General Public License as published by
15863+ * the Free Software Foundation; either version 2 of the License, or
15864+ * (at your option) any later version.
15865+ *
15866+ * This program is distributed in the hope that it will be useful,
15867+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
15868+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15869+ * GNU General Public License for more details.
15870+ *
15871+ * You should have received a copy of the GNU General Public License
15872+ * along with this program; if not, write to the Free Software
15873+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
15874+ */
1facf9fc 15875+
1308ab2a 15876+/*
4a4d8108 15877+ * inode operations (except add/del/rename)
1308ab2a 15878+ */
4a4d8108
AM
15879+
15880+#include <linux/device_cgroup.h>
15881+#include <linux/fs_stack.h>
92d182d2 15882+#include <linux/mm.h>
4a4d8108
AM
15883+#include <linux/namei.h>
15884+#include <linux/security.h>
4a4d8108
AM
15885+#include "aufs.h"
15886+
1e00d052 15887+static int h_permission(struct inode *h_inode, int mask,
4a4d8108 15888+ struct vfsmount *h_mnt, int brperm)
1facf9fc 15889+{
1308ab2a 15890+ int err;
4a4d8108 15891+ const unsigned char write_mask = !!(mask & (MAY_WRITE | MAY_APPEND));
1facf9fc 15892+
4a4d8108
AM
15893+ err = -EACCES;
15894+ if ((write_mask && IS_IMMUTABLE(h_inode))
15895+ || ((mask & MAY_EXEC)
15896+ && S_ISREG(h_inode->i_mode)
15897+ && ((h_mnt->mnt_flags & MNT_NOEXEC)
15898+ || !(h_inode->i_mode & S_IXUGO))))
15899+ goto out;
15900+
15901+ /*
15902+ * - skip the lower fs test in the case of write to ro branch.
15903+ * - nfs dir permission write check is optimized, but a policy for
15904+ * link/rename requires a real check.
15905+ */
15906+ if ((write_mask && !au_br_writable(brperm))
15907+ || (au_test_nfs(h_inode->i_sb) && S_ISDIR(h_inode->i_mode)
15908+ && write_mask && !(mask & MAY_READ))
15909+ || !h_inode->i_op->permission) {
15910+ /* AuLabel(generic_permission); */
1e00d052 15911+ err = generic_permission(h_inode, mask);
1308ab2a 15912+ } else {
4a4d8108 15913+ /* AuLabel(h_inode->permission); */
1e00d052 15914+ err = h_inode->i_op->permission(h_inode, mask);
4a4d8108
AM
15915+ AuTraceErr(err);
15916+ }
1facf9fc 15917+
4a4d8108
AM
15918+ if (!err)
15919+ err = devcgroup_inode_permission(h_inode, mask);
7f207e10 15920+ if (!err)
4a4d8108 15921+ err = security_inode_permission(h_inode, mask);
4a4d8108
AM
15922+
15923+#if 0
15924+ if (!err) {
15925+ /* todo: do we need to call ima_path_check()? */
15926+ struct path h_path = {
15927+ .dentry =
15928+ .mnt = h_mnt
15929+ };
15930+ err = ima_path_check(&h_path,
15931+ mask & (MAY_READ | MAY_WRITE | MAY_EXEC),
15932+ IMA_COUNT_LEAVE);
1308ab2a 15933+ }
4a4d8108 15934+#endif
dece6358 15935+
4f0767ce 15936+out:
1308ab2a 15937+ return err;
15938+}
dece6358 15939+
1e00d052 15940+static int aufs_permission(struct inode *inode, int mask)
1308ab2a 15941+{
15942+ int err;
4a4d8108
AM
15943+ aufs_bindex_t bindex, bend;
15944+ const unsigned char isdir = !!S_ISDIR(inode->i_mode),
15945+ write_mask = !!(mask & (MAY_WRITE | MAY_APPEND));
15946+ struct inode *h_inode;
15947+ struct super_block *sb;
15948+ struct au_branch *br;
1facf9fc 15949+
027c5e7a 15950+ /* todo: support rcu-walk? */
1e00d052 15951+ if (mask & MAY_NOT_BLOCK)
027c5e7a
AM
15952+ return -ECHILD;
15953+
4a4d8108
AM
15954+ sb = inode->i_sb;
15955+ si_read_lock(sb, AuLock_FLUSH);
15956+ ii_read_lock_child(inode);
027c5e7a
AM
15957+#if 0
15958+ err = au_iigen_test(inode, au_sigen(sb));
15959+ if (unlikely(err))
15960+ goto out;
15961+#endif
dece6358 15962+
4a4d8108
AM
15963+ if (!isdir || write_mask) {
15964+ err = au_busy_or_stale();
15965+ h_inode = au_h_iptr(inode, au_ibstart(inode));
15966+ if (unlikely(!h_inode
15967+ || (h_inode->i_mode & S_IFMT)
15968+ != (inode->i_mode & S_IFMT)))
15969+ goto out;
1facf9fc 15970+
4a4d8108
AM
15971+ err = 0;
15972+ bindex = au_ibstart(inode);
15973+ br = au_sbr(sb, bindex);
1e00d052 15974+ err = h_permission(h_inode, mask, br->br_mnt, br->br_perm);
4a4d8108
AM
15975+ if (write_mask
15976+ && !err
15977+ && !special_file(h_inode->i_mode)) {
15978+ /* test whether the upper writable branch exists */
15979+ err = -EROFS;
15980+ for (; bindex >= 0; bindex--)
15981+ if (!au_br_rdonly(au_sbr(sb, bindex))) {
15982+ err = 0;
15983+ break;
15984+ }
15985+ }
15986+ goto out;
15987+ }
dece6358 15988+
4a4d8108 15989+ /* non-write to dir */
1308ab2a 15990+ err = 0;
4a4d8108
AM
15991+ bend = au_ibend(inode);
15992+ for (bindex = au_ibstart(inode); !err && bindex <= bend; bindex++) {
15993+ h_inode = au_h_iptr(inode, bindex);
15994+ if (h_inode) {
15995+ err = au_busy_or_stale();
15996+ if (unlikely(!S_ISDIR(h_inode->i_mode)))
15997+ break;
15998+
15999+ br = au_sbr(sb, bindex);
1e00d052 16000+ err = h_permission(h_inode, mask, br->br_mnt,
4a4d8108
AM
16001+ br->br_perm);
16002+ }
16003+ }
1308ab2a 16004+
4f0767ce 16005+out:
4a4d8108
AM
16006+ ii_read_unlock(inode);
16007+ si_read_unlock(sb);
1308ab2a 16008+ return err;
16009+}
16010+
4a4d8108 16011+/* ---------------------------------------------------------------------- */
1facf9fc 16012+
4a4d8108
AM
16013+static struct dentry *aufs_lookup(struct inode *dir, struct dentry *dentry,
16014+ struct nameidata *nd)
16015+{
16016+ struct dentry *ret, *parent;
b752ccd1 16017+ struct inode *inode;
4a4d8108 16018+ struct super_block *sb;
9dbd164d 16019+ int err, npositive, lc_idx;
dece6358 16020+
4a4d8108 16021+ IMustLock(dir);
1308ab2a 16022+
4a4d8108 16023+ sb = dir->i_sb;
7f207e10
AM
16024+ err = si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLM);
16025+ ret = ERR_PTR(err);
16026+ if (unlikely(err))
16027+ goto out;
16028+
4a4d8108
AM
16029+ ret = ERR_PTR(-ENAMETOOLONG);
16030+ if (unlikely(dentry->d_name.len > AUFS_MAX_NAMELEN))
7f207e10 16031+ goto out_si;
4a4d8108
AM
16032+ err = au_di_init(dentry);
16033+ ret = ERR_PTR(err);
16034+ if (unlikely(err))
7f207e10 16035+ goto out_si;
1308ab2a 16036+
9dbd164d 16037+ inode = NULL;
027c5e7a 16038+ npositive = 0; /* suppress a warning */
4a4d8108
AM
16039+ parent = dentry->d_parent; /* dir inode is locked */
16040+ di_read_lock_parent(parent, AuLock_IR);
027c5e7a
AM
16041+ err = au_alive_dir(parent);
16042+ if (!err)
16043+ err = au_digen_test(parent, au_sigen(sb));
16044+ if (!err) {
16045+ npositive = au_lkup_dentry(dentry, au_dbstart(parent),
16046+ /*type*/0, nd);
16047+ err = npositive;
16048+ }
4a4d8108 16049+ di_read_unlock(parent, AuLock_IR);
4a4d8108
AM
16050+ ret = ERR_PTR(err);
16051+ if (unlikely(err < 0))
16052+ goto out_unlock;
1308ab2a 16053+
4a4d8108 16054+ if (npositive) {
b752ccd1 16055+ inode = au_new_inode(dentry, /*must_new*/0);
4a4d8108 16056+ ret = (void *)inode;
1facf9fc 16057+ }
9dbd164d
AM
16058+ if (IS_ERR(inode)) {
16059+ inode = NULL;
4a4d8108 16060+ goto out_unlock;
9dbd164d 16061+ }
4a4d8108
AM
16062+
16063+ ret = d_splice_alias(inode, dentry);
7f207e10 16064+ if (unlikely(IS_ERR(ret) && inode)) {
4a4d8108 16065+ ii_write_unlock(inode);
9dbd164d
AM
16066+ lc_idx = AuLcNonDir_IIINFO;
16067+ if (S_ISLNK(inode->i_mode))
16068+ lc_idx = AuLcSymlink_IIINFO;
16069+ else if (S_ISDIR(inode->i_mode))
16070+ lc_idx = AuLcDir_IIINFO;
16071+ au_rw_class(&au_ii(inode)->ii_rwsem, au_lc_key + lc_idx);
7f207e10
AM
16072+ iput(inode);
16073+ }
1facf9fc 16074+
4f0767ce 16075+out_unlock:
4a4d8108 16076+ di_write_unlock(dentry);
9dbd164d
AM
16077+ if (unlikely(IS_ERR(ret) && inode)) {
16078+ lc_idx = AuLcNonDir_DIINFO;
16079+ if (S_ISLNK(inode->i_mode))
16080+ lc_idx = AuLcSymlink_DIINFO;
16081+ else if (S_ISDIR(inode->i_mode))
16082+ lc_idx = AuLcDir_DIINFO;
16083+ au_rw_class(&au_di(dentry)->di_rwsem, au_lc_key + lc_idx);
16084+ }
7f207e10 16085+out_si:
4a4d8108 16086+ si_read_unlock(sb);
7f207e10 16087+out:
4a4d8108
AM
16088+ return ret;
16089+}
1facf9fc 16090+
4a4d8108 16091+/* ---------------------------------------------------------------------- */
1facf9fc 16092+
4a4d8108
AM
16093+static int au_wr_dir_cpup(struct dentry *dentry, struct dentry *parent,
16094+ const unsigned char add_entry, aufs_bindex_t bcpup,
16095+ aufs_bindex_t bstart)
16096+{
16097+ int err;
16098+ struct dentry *h_parent;
16099+ struct inode *h_dir;
1facf9fc 16100+
027c5e7a 16101+ if (add_entry)
4a4d8108 16102+ IMustLock(parent->d_inode);
027c5e7a 16103+ else
4a4d8108
AM
16104+ di_write_lock_parent(parent);
16105+
16106+ err = 0;
16107+ if (!au_h_dptr(parent, bcpup)) {
16108+ if (bstart < bcpup)
16109+ err = au_cpdown_dirs(dentry, bcpup);
16110+ else
16111+ err = au_cpup_dirs(dentry, bcpup);
16112+ }
16113+ if (!err && add_entry) {
16114+ h_parent = au_h_dptr(parent, bcpup);
16115+ h_dir = h_parent->d_inode;
16116+ mutex_lock_nested(&h_dir->i_mutex, AuLsc_I_PARENT);
16117+ err = au_lkup_neg(dentry, bcpup);
16118+ /* todo: no unlock here */
16119+ mutex_unlock(&h_dir->i_mutex);
027c5e7a
AM
16120+
16121+ AuDbg("bcpup %d\n", bcpup);
16122+ if (!err) {
16123+ if (!dentry->d_inode)
16124+ au_set_h_dptr(dentry, bstart, NULL);
4a4d8108
AM
16125+ au_update_dbrange(dentry, /*do_put_zero*/0);
16126+ }
1308ab2a 16127+ }
1facf9fc 16128+
4a4d8108
AM
16129+ if (!add_entry)
16130+ di_write_unlock(parent);
16131+ if (!err)
16132+ err = bcpup; /* success */
1308ab2a 16133+
027c5e7a 16134+ AuTraceErr(err);
4a4d8108
AM
16135+ return err;
16136+}
1facf9fc 16137+
4a4d8108
AM
16138+/*
16139+ * decide the branch and the parent dir where we will create a new entry.
16140+ * returns new bindex or an error.
16141+ * copyup the parent dir if needed.
16142+ */
16143+int au_wr_dir(struct dentry *dentry, struct dentry *src_dentry,
16144+ struct au_wr_dir_args *args)
16145+{
16146+ int err;
16147+ aufs_bindex_t bcpup, bstart, src_bstart;
16148+ const unsigned char add_entry = !!au_ftest_wrdir(args->flags,
16149+ ADD_ENTRY);
16150+ struct super_block *sb;
16151+ struct dentry *parent;
16152+ struct au_sbinfo *sbinfo;
1facf9fc 16153+
4a4d8108
AM
16154+ sb = dentry->d_sb;
16155+ sbinfo = au_sbi(sb);
16156+ parent = dget_parent(dentry);
16157+ bstart = au_dbstart(dentry);
16158+ bcpup = bstart;
16159+ if (args->force_btgt < 0) {
16160+ if (src_dentry) {
16161+ src_bstart = au_dbstart(src_dentry);
16162+ if (src_bstart < bstart)
16163+ bcpup = src_bstart;
16164+ } else if (add_entry) {
16165+ err = AuWbrCreate(sbinfo, dentry,
16166+ au_ftest_wrdir(args->flags, ISDIR));
16167+ bcpup = err;
16168+ }
1facf9fc 16169+
4a4d8108
AM
16170+ if (bcpup < 0 || au_test_ro(sb, bcpup, dentry->d_inode)) {
16171+ if (add_entry)
16172+ err = AuWbrCopyup(sbinfo, dentry);
16173+ else {
16174+ if (!IS_ROOT(dentry)) {
16175+ di_read_lock_parent(parent, !AuLock_IR);
16176+ err = AuWbrCopyup(sbinfo, dentry);
16177+ di_read_unlock(parent, !AuLock_IR);
16178+ } else
16179+ err = AuWbrCopyup(sbinfo, dentry);
16180+ }
16181+ bcpup = err;
16182+ if (unlikely(err < 0))
16183+ goto out;
16184+ }
16185+ } else {
16186+ bcpup = args->force_btgt;
16187+ AuDebugOn(au_test_ro(sb, bcpup, dentry->d_inode));
1308ab2a 16188+ }
027c5e7a 16189+
4a4d8108
AM
16190+ AuDbg("bstart %d, bcpup %d\n", bstart, bcpup);
16191+ err = bcpup;
16192+ if (bcpup == bstart)
16193+ goto out; /* success */
4a4d8108
AM
16194+
16195+ /* copyup the new parent into the branch we process */
16196+ err = au_wr_dir_cpup(dentry, parent, add_entry, bcpup, bstart);
027c5e7a
AM
16197+ if (err >= 0) {
16198+ if (!dentry->d_inode) {
16199+ au_set_h_dptr(dentry, bstart, NULL);
16200+ au_set_dbstart(dentry, bcpup);
16201+ au_set_dbend(dentry, bcpup);
16202+ }
16203+ AuDebugOn(add_entry && !au_h_dptr(dentry, bcpup));
16204+ }
4a4d8108 16205+
4f0767ce 16206+out:
4a4d8108 16207+ dput(parent);
dece6358
AM
16208+ return err;
16209+}
1facf9fc 16210+
1308ab2a 16211+/* ---------------------------------------------------------------------- */
16212+
4a4d8108 16213+struct dentry *au_pinned_h_parent(struct au_pin *pin)
1308ab2a 16214+{
4a4d8108
AM
16215+ if (pin && pin->parent)
16216+ return au_h_dptr(pin->parent, pin->bindex);
16217+ return NULL;
dece6358 16218+}
1facf9fc 16219+
4a4d8108 16220+void au_unpin(struct au_pin *p)
dece6358 16221+{
e49829fe 16222+ if (p->h_mnt && au_ftest_pin(p->flags, MNT_WRITE))
4a4d8108
AM
16223+ mnt_drop_write(p->h_mnt);
16224+ if (!p->hdir)
16225+ return;
1facf9fc 16226+
4a4d8108
AM
16227+ au_hn_imtx_unlock(p->hdir);
16228+ if (!au_ftest_pin(p->flags, DI_LOCKED))
16229+ di_read_unlock(p->parent, AuLock_IR);
16230+ iput(p->hdir->hi_inode);
16231+ dput(p->parent);
16232+ p->parent = NULL;
16233+ p->hdir = NULL;
16234+ p->h_mnt = NULL;
16235+}
1308ab2a 16236+
4a4d8108
AM
16237+int au_do_pin(struct au_pin *p)
16238+{
16239+ int err;
16240+ struct super_block *sb;
16241+ struct dentry *h_dentry, *h_parent;
16242+ struct au_branch *br;
16243+ struct inode *h_dir;
16244+
16245+ err = 0;
16246+ sb = p->dentry->d_sb;
16247+ br = au_sbr(sb, p->bindex);
16248+ if (IS_ROOT(p->dentry)) {
16249+ if (au_ftest_pin(p->flags, MNT_WRITE)) {
16250+ p->h_mnt = br->br_mnt;
16251+ err = mnt_want_write(p->h_mnt);
16252+ if (unlikely(err)) {
16253+ au_fclr_pin(p->flags, MNT_WRITE);
16254+ goto out_err;
16255+ }
16256+ }
dece6358 16257+ goto out;
1facf9fc 16258+ }
16259+
4a4d8108
AM
16260+ h_dentry = NULL;
16261+ if (p->bindex <= au_dbend(p->dentry))
16262+ h_dentry = au_h_dptr(p->dentry, p->bindex);
dece6358 16263+
4a4d8108
AM
16264+ p->parent = dget_parent(p->dentry);
16265+ if (!au_ftest_pin(p->flags, DI_LOCKED))
16266+ di_read_lock(p->parent, AuLock_IR, p->lsc_di);
dece6358 16267+
4a4d8108
AM
16268+ h_dir = NULL;
16269+ h_parent = au_h_dptr(p->parent, p->bindex);
16270+ p->hdir = au_hi(p->parent->d_inode, p->bindex);
16271+ if (p->hdir)
16272+ h_dir = p->hdir->hi_inode;
dece6358 16273+
b752ccd1
AM
16274+ /*
16275+ * udba case, or
16276+ * if DI_LOCKED is not set, then p->parent may be different
16277+ * and h_parent can be NULL.
16278+ */
16279+ if (unlikely(!p->hdir || !h_dir || !h_parent)) {
e49829fe 16280+ err = -EBUSY;
4a4d8108
AM
16281+ if (!au_ftest_pin(p->flags, DI_LOCKED))
16282+ di_read_unlock(p->parent, AuLock_IR);
16283+ dput(p->parent);
16284+ p->parent = NULL;
16285+ goto out_err;
16286+ }
1308ab2a 16287+
4a4d8108
AM
16288+ au_igrab(h_dir);
16289+ au_hn_imtx_lock_nested(p->hdir, p->lsc_hi);
1308ab2a 16290+
4a4d8108
AM
16291+ if (unlikely(p->hdir->hi_inode != h_parent->d_inode)) {
16292+ err = -EBUSY;
16293+ goto out_unpin;
16294+ }
16295+ if (h_dentry) {
16296+ err = au_h_verify(h_dentry, p->udba, h_dir, h_parent, br);
16297+ if (unlikely(err)) {
16298+ au_fclr_pin(p->flags, MNT_WRITE);
16299+ goto out_unpin;
16300+ }
1facf9fc 16301+ }
dece6358 16302+
4a4d8108
AM
16303+ if (au_ftest_pin(p->flags, MNT_WRITE)) {
16304+ p->h_mnt = br->br_mnt;
16305+ err = mnt_want_write(p->h_mnt);
dece6358 16306+ if (unlikely(err)) {
4a4d8108
AM
16307+ au_fclr_pin(p->flags, MNT_WRITE);
16308+ goto out_unpin;
dece6358
AM
16309+ }
16310+ }
4a4d8108
AM
16311+ goto out; /* success */
16312+
4f0767ce 16313+out_unpin:
4a4d8108 16314+ au_unpin(p);
4f0767ce 16315+out_err:
4a4d8108
AM
16316+ pr_err("err %d\n", err);
16317+ err = au_busy_or_stale();
4f0767ce 16318+out:
1facf9fc 16319+ return err;
16320+}
16321+
4a4d8108
AM
16322+void au_pin_init(struct au_pin *p, struct dentry *dentry,
16323+ aufs_bindex_t bindex, int lsc_di, int lsc_hi,
16324+ unsigned int udba, unsigned char flags)
16325+{
16326+ p->dentry = dentry;
16327+ p->udba = udba;
16328+ p->lsc_di = lsc_di;
16329+ p->lsc_hi = lsc_hi;
16330+ p->flags = flags;
16331+ p->bindex = bindex;
16332+
16333+ p->parent = NULL;
16334+ p->hdir = NULL;
16335+ p->h_mnt = NULL;
16336+}
16337+
16338+int au_pin(struct au_pin *pin, struct dentry *dentry, aufs_bindex_t bindex,
16339+ unsigned int udba, unsigned char flags)
16340+{
16341+ au_pin_init(pin, dentry, bindex, AuLsc_DI_PARENT, AuLsc_I_PARENT2,
16342+ udba, flags);
16343+ return au_do_pin(pin);
16344+}
16345+
dece6358
AM
16346+/* ---------------------------------------------------------------------- */
16347+
1308ab2a 16348+/*
4a4d8108
AM
16349+ * ->setattr() and ->getattr() are called in various cases.
16350+ * chmod, stat: dentry is revalidated.
16351+ * fchmod, fstat: file and dentry are not revalidated, additionally they may be
16352+ * unhashed.
16353+ * for ->setattr(), ia->ia_file is passed from ftruncate only.
1308ab2a 16354+ */
027c5e7a 16355+/* todo: consolidate with do_refresh() and simple_reval_dpath() */
4a4d8108 16356+static int au_reval_for_attr(struct dentry *dentry, unsigned int sigen)
1facf9fc 16357+{
4a4d8108
AM
16358+ int err;
16359+ struct inode *inode;
16360+ struct dentry *parent;
1facf9fc 16361+
1308ab2a 16362+ err = 0;
4a4d8108 16363+ inode = dentry->d_inode;
027c5e7a 16364+ if (au_digen_test(dentry, sigen)) {
4a4d8108
AM
16365+ parent = dget_parent(dentry);
16366+ di_read_lock_parent(parent, AuLock_IR);
027c5e7a 16367+ err = au_refresh_dentry(dentry, parent);
4a4d8108
AM
16368+ di_read_unlock(parent, AuLock_IR);
16369+ dput(parent);
dece6358 16370+ }
1facf9fc 16371+
4a4d8108 16372+ AuTraceErr(err);
1308ab2a 16373+ return err;
16374+}
dece6358 16375+
4a4d8108
AM
16376+#define AuIcpup_DID_CPUP 1
16377+#define au_ftest_icpup(flags, name) ((flags) & AuIcpup_##name)
7f207e10
AM
16378+#define au_fset_icpup(flags, name) \
16379+ do { (flags) |= AuIcpup_##name; } while (0)
16380+#define au_fclr_icpup(flags, name) \
16381+ do { (flags) &= ~AuIcpup_##name; } while (0)
1308ab2a 16382+
4a4d8108
AM
16383+struct au_icpup_args {
16384+ unsigned char flags;
16385+ unsigned char pin_flags;
16386+ aufs_bindex_t btgt;
16387+ unsigned int udba;
16388+ struct au_pin pin;
16389+ struct path h_path;
16390+ struct inode *h_inode;
16391+};
1308ab2a 16392+
4a4d8108
AM
16393+static int au_pin_and_icpup(struct dentry *dentry, struct iattr *ia,
16394+ struct au_icpup_args *a)
1308ab2a 16395+{
16396+ int err;
4a4d8108 16397+ loff_t sz;
e49829fe 16398+ aufs_bindex_t bstart, ibstart;
4a4d8108
AM
16399+ struct dentry *hi_wh, *parent;
16400+ struct inode *inode;
16401+ struct file *h_file;
16402+ struct au_wr_dir_args wr_dir_args = {
16403+ .force_btgt = -1,
16404+ .flags = 0
16405+ };
16406+
16407+ bstart = au_dbstart(dentry);
16408+ inode = dentry->d_inode;
16409+ if (S_ISDIR(inode->i_mode))
16410+ au_fset_wrdir(wr_dir_args.flags, ISDIR);
16411+ /* plink or hi_wh() case */
e49829fe 16412+ ibstart = au_ibstart(inode);
027c5e7a 16413+ if (bstart != ibstart && !au_test_ro(inode->i_sb, ibstart, inode))
e49829fe 16414+ wr_dir_args.force_btgt = ibstart;
4a4d8108
AM
16415+ err = au_wr_dir(dentry, /*src_dentry*/NULL, &wr_dir_args);
16416+ if (unlikely(err < 0))
16417+ goto out;
16418+ a->btgt = err;
16419+ if (err != bstart)
16420+ au_fset_icpup(a->flags, DID_CPUP);
16421+
16422+ err = 0;
16423+ a->pin_flags = AuPin_MNT_WRITE;
16424+ parent = NULL;
16425+ if (!IS_ROOT(dentry)) {
16426+ au_fset_pin(a->pin_flags, DI_LOCKED);
16427+ parent = dget_parent(dentry);
16428+ di_write_lock_parent(parent);
16429+ }
16430+
16431+ err = au_pin(&a->pin, dentry, a->btgt, a->udba, a->pin_flags);
16432+ if (unlikely(err))
16433+ goto out_parent;
16434+
16435+ a->h_path.dentry = au_h_dptr(dentry, bstart);
16436+ a->h_inode = a->h_path.dentry->d_inode;
16437+ mutex_lock_nested(&a->h_inode->i_mutex, AuLsc_I_CHILD);
16438+ sz = -1;
16439+ if ((ia->ia_valid & ATTR_SIZE) && ia->ia_size < i_size_read(a->h_inode))
16440+ sz = ia->ia_size;
16441+
16442+ h_file = NULL;
16443+ hi_wh = NULL;
027c5e7a 16444+ if (au_ftest_icpup(a->flags, DID_CPUP) && d_unlinked(dentry)) {
4a4d8108
AM
16445+ hi_wh = au_hi_wh(inode, a->btgt);
16446+ if (!hi_wh) {
16447+ err = au_sio_cpup_wh(dentry, a->btgt, sz, /*file*/NULL);
16448+ if (unlikely(err))
16449+ goto out_unlock;
16450+ hi_wh = au_hi_wh(inode, a->btgt);
16451+ /* todo: revalidate hi_wh? */
16452+ }
16453+ }
16454+
16455+ if (parent) {
16456+ au_pin_set_parent_lflag(&a->pin, /*lflag*/0);
16457+ di_downgrade_lock(parent, AuLock_IR);
16458+ dput(parent);
16459+ parent = NULL;
16460+ }
16461+ if (!au_ftest_icpup(a->flags, DID_CPUP))
16462+ goto out; /* success */
16463+
16464+ if (!d_unhashed(dentry)) {
16465+ h_file = au_h_open_pre(dentry, bstart);
16466+ if (IS_ERR(h_file)) {
16467+ err = PTR_ERR(h_file);
16468+ h_file = NULL;
16469+ } else
16470+ err = au_sio_cpup_simple(dentry, a->btgt, sz,
16471+ AuCpup_DTIME);
16472+ if (!err)
16473+ a->h_path.dentry = au_h_dptr(dentry, a->btgt);
16474+ } else if (!hi_wh)
16475+ a->h_path.dentry = au_h_dptr(dentry, a->btgt);
16476+ else
16477+ a->h_path.dentry = hi_wh; /* do not dget here */
1308ab2a 16478+
4f0767ce 16479+out_unlock:
4a4d8108
AM
16480+ mutex_unlock(&a->h_inode->i_mutex);
16481+ au_h_open_post(dentry, bstart, h_file);
16482+ a->h_inode = a->h_path.dentry->d_inode;
dece6358 16483+ if (!err) {
4a4d8108 16484+ mutex_lock_nested(&a->h_inode->i_mutex, AuLsc_I_CHILD);
dece6358 16485+ goto out; /* success */
1facf9fc 16486+ }
dece6358 16487+
4a4d8108 16488+ au_unpin(&a->pin);
4f0767ce 16489+out_parent:
4a4d8108
AM
16490+ if (parent) {
16491+ di_write_unlock(parent);
16492+ dput(parent);
16493+ }
4f0767ce 16494+out:
1facf9fc 16495+ return err;
16496+}
16497+
4a4d8108 16498+static int aufs_setattr(struct dentry *dentry, struct iattr *ia)
1facf9fc 16499+{
4a4d8108
AM
16500+ int err;
16501+ struct inode *inode;
16502+ struct super_block *sb;
16503+ struct file *file;
16504+ struct au_icpup_args *a;
1facf9fc 16505+
4a4d8108
AM
16506+ inode = dentry->d_inode;
16507+ IMustLock(inode);
dece6358 16508+
4a4d8108
AM
16509+ err = -ENOMEM;
16510+ a = kzalloc(sizeof(*a), GFP_NOFS);
16511+ if (unlikely(!a))
16512+ goto out;
1facf9fc 16513+
4a4d8108
AM
16514+ if (ia->ia_valid & (ATTR_KILL_SUID | ATTR_KILL_SGID))
16515+ ia->ia_valid &= ~ATTR_MODE;
dece6358 16516+
4a4d8108
AM
16517+ file = NULL;
16518+ sb = dentry->d_sb;
e49829fe
JR
16519+ err = si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLM);
16520+ if (unlikely(err))
16521+ goto out_kfree;
16522+
4a4d8108
AM
16523+ if (ia->ia_valid & ATTR_FILE) {
16524+ /* currently ftruncate(2) only */
16525+ AuDebugOn(!S_ISREG(inode->i_mode));
16526+ file = ia->ia_file;
16527+ err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/1);
16528+ if (unlikely(err))
16529+ goto out_si;
16530+ ia->ia_file = au_hf_top(file);
16531+ a->udba = AuOpt_UDBA_NONE;
16532+ } else {
16533+ /* fchmod() doesn't pass ia_file */
16534+ a->udba = au_opt_udba(sb);
027c5e7a
AM
16535+ di_write_lock_child(dentry);
16536+ /* no d_unlinked(), to set UDBA_NONE for root */
4a4d8108
AM
16537+ if (d_unhashed(dentry))
16538+ a->udba = AuOpt_UDBA_NONE;
4a4d8108
AM
16539+ if (a->udba != AuOpt_UDBA_NONE) {
16540+ AuDebugOn(IS_ROOT(dentry));
16541+ err = au_reval_for_attr(dentry, au_sigen(sb));
16542+ if (unlikely(err))
16543+ goto out_dentry;
16544+ }
dece6358 16545+ }
dece6358 16546+
4a4d8108
AM
16547+ err = au_pin_and_icpup(dentry, ia, a);
16548+ if (unlikely(err < 0))
16549+ goto out_dentry;
16550+ if (au_ftest_icpup(a->flags, DID_CPUP)) {
16551+ ia->ia_file = NULL;
16552+ ia->ia_valid &= ~ATTR_FILE;
1308ab2a 16553+ }
dece6358 16554+
4a4d8108
AM
16555+ a->h_path.mnt = au_sbr_mnt(sb, a->btgt);
16556+ if ((ia->ia_valid & (ATTR_MODE | ATTR_CTIME))
16557+ == (ATTR_MODE | ATTR_CTIME)) {
7eafdf33 16558+ err = security_path_chmod(&a->h_path, ia->ia_mode);
4a4d8108
AM
16559+ if (unlikely(err))
16560+ goto out_unlock;
16561+ } else if ((ia->ia_valid & (ATTR_UID | ATTR_GID))
16562+ && (ia->ia_valid & ATTR_CTIME)) {
0c3ec466
AM
16563+ err = security_path_chown(&a->h_path, vfsub_ia_uid(ia),
16564+ vfsub_ia_gid(ia));
4a4d8108
AM
16565+ if (unlikely(err))
16566+ goto out_unlock;
16567+ }
dece6358 16568+
4a4d8108
AM
16569+ if (ia->ia_valid & ATTR_SIZE) {
16570+ struct file *f;
1308ab2a 16571+
953406b4 16572+ if (ia->ia_size < i_size_read(inode))
4a4d8108 16573+ /* unmap only */
953406b4 16574+ truncate_setsize(inode, ia->ia_size);
1308ab2a 16575+
4a4d8108
AM
16576+ f = NULL;
16577+ if (ia->ia_valid & ATTR_FILE)
16578+ f = ia->ia_file;
16579+ mutex_unlock(&a->h_inode->i_mutex);
16580+ err = vfsub_trunc(&a->h_path, ia->ia_size, ia->ia_valid, f);
16581+ mutex_lock_nested(&a->h_inode->i_mutex, AuLsc_I_CHILD);
16582+ } else
16583+ err = vfsub_notify_change(&a->h_path, ia);
16584+ if (!err)
16585+ au_cpup_attr_changeable(inode);
1308ab2a 16586+
4f0767ce 16587+out_unlock:
4a4d8108
AM
16588+ mutex_unlock(&a->h_inode->i_mutex);
16589+ au_unpin(&a->pin);
027c5e7a
AM
16590+ if (unlikely(err))
16591+ au_update_dbstart(dentry);
4f0767ce 16592+out_dentry:
4a4d8108
AM
16593+ di_write_unlock(dentry);
16594+ if (file) {
16595+ fi_write_unlock(file);
16596+ ia->ia_file = file;
16597+ ia->ia_valid |= ATTR_FILE;
16598+ }
4f0767ce 16599+out_si:
4a4d8108 16600+ si_read_unlock(sb);
e49829fe 16601+out_kfree:
4a4d8108 16602+ kfree(a);
4f0767ce 16603+out:
4a4d8108
AM
16604+ AuTraceErr(err);
16605+ return err;
1facf9fc 16606+}
16607+
4a4d8108
AM
16608+static void au_refresh_iattr(struct inode *inode, struct kstat *st,
16609+ unsigned int nlink)
1facf9fc 16610+{
9dbd164d
AM
16611+ unsigned int n;
16612+
4a4d8108 16613+ inode->i_mode = st->mode;
0c3ec466
AM
16614+ i_uid_write(inode, st->uid);
16615+ i_gid_write(inode, st->gid);
4a4d8108
AM
16616+ inode->i_atime = st->atime;
16617+ inode->i_mtime = st->mtime;
16618+ inode->i_ctime = st->ctime;
1facf9fc 16619+
4a4d8108
AM
16620+ au_cpup_attr_nlink(inode, /*force*/0);
16621+ if (S_ISDIR(inode->i_mode)) {
9dbd164d
AM
16622+ n = inode->i_nlink;
16623+ n -= nlink;
16624+ n += st->nlink;
7eafdf33 16625+ /* 0 can happen */
92d182d2 16626+ set_nlink(inode, n);
4a4d8108 16627+ }
1facf9fc 16628+
4a4d8108
AM
16629+ spin_lock(&inode->i_lock);
16630+ inode->i_blocks = st->blocks;
16631+ i_size_write(inode, st->size);
16632+ spin_unlock(&inode->i_lock);
1facf9fc 16633+}
16634+
4a4d8108
AM
16635+static int aufs_getattr(struct vfsmount *mnt __maybe_unused,
16636+ struct dentry *dentry, struct kstat *st)
1facf9fc 16637+{
4a4d8108
AM
16638+ int err;
16639+ unsigned int mnt_flags;
16640+ aufs_bindex_t bindex;
16641+ unsigned char udba_none, positive;
16642+ struct super_block *sb, *h_sb;
16643+ struct inode *inode;
16644+ struct vfsmount *h_mnt;
16645+ struct dentry *h_dentry;
1facf9fc 16646+
4a4d8108
AM
16647+ sb = dentry->d_sb;
16648+ inode = dentry->d_inode;
7f207e10
AM
16649+ err = si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLM);
16650+ if (unlikely(err))
16651+ goto out;
4a4d8108
AM
16652+ mnt_flags = au_mntflags(sb);
16653+ udba_none = !!au_opt_test(mnt_flags, UDBA_NONE);
1facf9fc 16654+
4a4d8108 16655+ /* support fstat(2) */
027c5e7a 16656+ if (!d_unlinked(dentry) && !udba_none) {
4a4d8108 16657+ unsigned int sigen = au_sigen(sb);
027c5e7a
AM
16658+ err = au_digen_test(dentry, sigen);
16659+ if (!err) {
4a4d8108 16660+ di_read_lock_child(dentry, AuLock_IR);
027c5e7a
AM
16661+ err = au_dbrange_test(dentry);
16662+ if (unlikely(err))
16663+ goto out_unlock;
16664+ } else {
4a4d8108
AM
16665+ AuDebugOn(IS_ROOT(dentry));
16666+ di_write_lock_child(dentry);
027c5e7a
AM
16667+ err = au_dbrange_test(dentry);
16668+ if (!err)
16669+ err = au_reval_for_attr(dentry, sigen);
4a4d8108
AM
16670+ di_downgrade_lock(dentry, AuLock_IR);
16671+ if (unlikely(err))
7f207e10 16672+ goto out_unlock;
4a4d8108
AM
16673+ }
16674+ } else
16675+ di_read_lock_child(dentry, AuLock_IR);
1facf9fc 16676+
4a4d8108
AM
16677+ bindex = au_ibstart(inode);
16678+ h_mnt = au_sbr_mnt(sb, bindex);
16679+ h_sb = h_mnt->mnt_sb;
16680+ if (!au_test_fs_bad_iattr(h_sb) && udba_none)
16681+ goto out_fill; /* success */
1facf9fc 16682+
4a4d8108
AM
16683+ h_dentry = NULL;
16684+ if (au_dbstart(dentry) == bindex)
16685+ h_dentry = dget(au_h_dptr(dentry, bindex));
16686+ else if (au_opt_test(mnt_flags, PLINK) && au_plink_test(inode)) {
16687+ h_dentry = au_plink_lkup(inode, bindex);
16688+ if (IS_ERR(h_dentry))
16689+ goto out_fill; /* pretending success */
16690+ }
16691+ /* illegally overlapped or something */
16692+ if (unlikely(!h_dentry))
16693+ goto out_fill; /* pretending success */
16694+
16695+ positive = !!h_dentry->d_inode;
16696+ if (positive)
16697+ err = vfs_getattr(h_mnt, h_dentry, st);
16698+ dput(h_dentry);
16699+ if (!err) {
16700+ if (positive)
16701+ au_refresh_iattr(inode, st, h_dentry->d_inode->i_nlink);
16702+ goto out_fill; /* success */
1facf9fc 16703+ }
7f207e10
AM
16704+ AuTraceErr(err);
16705+ goto out_unlock;
4a4d8108 16706+
4f0767ce 16707+out_fill:
4a4d8108 16708+ generic_fillattr(inode, st);
7f207e10 16709+out_unlock:
4a4d8108
AM
16710+ di_read_unlock(dentry, AuLock_IR);
16711+ si_read_unlock(sb);
7f207e10
AM
16712+out:
16713+ AuTraceErr(err);
4a4d8108 16714+ return err;
1facf9fc 16715+}
16716+
16717+/* ---------------------------------------------------------------------- */
16718+
4a4d8108
AM
16719+static int h_readlink(struct dentry *dentry, int bindex, char __user *buf,
16720+ int bufsiz)
1facf9fc 16721+{
16722+ int err;
4a4d8108
AM
16723+ struct super_block *sb;
16724+ struct dentry *h_dentry;
1facf9fc 16725+
4a4d8108
AM
16726+ err = -EINVAL;
16727+ h_dentry = au_h_dptr(dentry, bindex);
16728+ if (unlikely(!h_dentry->d_inode->i_op->readlink))
16729+ goto out;
1facf9fc 16730+
4a4d8108
AM
16731+ err = security_inode_readlink(h_dentry);
16732+ if (unlikely(err))
dece6358 16733+ goto out;
1facf9fc 16734+
4a4d8108
AM
16735+ sb = dentry->d_sb;
16736+ if (!au_test_ro(sb, bindex, dentry->d_inode)) {
16737+ vfsub_touch_atime(au_sbr_mnt(sb, bindex), h_dentry);
16738+ fsstack_copy_attr_atime(dentry->d_inode, h_dentry->d_inode);
1facf9fc 16739+ }
4a4d8108 16740+ err = h_dentry->d_inode->i_op->readlink(h_dentry, buf, bufsiz);
1facf9fc 16741+
4f0767ce 16742+out:
4a4d8108
AM
16743+ return err;
16744+}
1facf9fc 16745+
4a4d8108
AM
16746+static int aufs_readlink(struct dentry *dentry, char __user *buf, int bufsiz)
16747+{
16748+ int err;
1facf9fc 16749+
027c5e7a
AM
16750+ err = aufs_read_lock(dentry, AuLock_IR | AuLock_GEN);
16751+ if (unlikely(err))
16752+ goto out;
16753+ err = au_d_hashed_positive(dentry);
16754+ if (!err)
16755+ err = h_readlink(dentry, au_dbstart(dentry), buf, bufsiz);
4a4d8108 16756+ aufs_read_unlock(dentry, AuLock_IR);
1facf9fc 16757+
027c5e7a 16758+out:
4a4d8108
AM
16759+ return err;
16760+}
1facf9fc 16761+
4a4d8108
AM
16762+static void *aufs_follow_link(struct dentry *dentry, struct nameidata *nd)
16763+{
16764+ int err;
4a4d8108 16765+ mm_segment_t old_fs;
b752ccd1
AM
16766+ union {
16767+ char *k;
16768+ char __user *u;
16769+ } buf;
1facf9fc 16770+
4a4d8108 16771+ err = -ENOMEM;
b752ccd1
AM
16772+ buf.k = __getname_gfp(GFP_NOFS);
16773+ if (unlikely(!buf.k))
4a4d8108 16774+ goto out;
1facf9fc 16775+
027c5e7a
AM
16776+ err = aufs_read_lock(dentry, AuLock_IR | AuLock_GEN);
16777+ if (unlikely(err))
16778+ goto out_name;
16779+
16780+ err = au_d_hashed_positive(dentry);
16781+ if (!err) {
16782+ old_fs = get_fs();
16783+ set_fs(KERNEL_DS);
16784+ err = h_readlink(dentry, au_dbstart(dentry), buf.u, PATH_MAX);
16785+ set_fs(old_fs);
16786+ }
4a4d8108 16787+ aufs_read_unlock(dentry, AuLock_IR);
1facf9fc 16788+
4a4d8108 16789+ if (err >= 0) {
b752ccd1 16790+ buf.k[err] = 0;
4a4d8108 16791+ /* will be freed by put_link */
b752ccd1 16792+ nd_set_link(nd, buf.k);
4a4d8108 16793+ return NULL; /* success */
1308ab2a 16794+ }
1facf9fc 16795+
027c5e7a
AM
16796+out_name:
16797+ __putname(buf.k);
4f0767ce 16798+out:
4a4d8108
AM
16799+ path_put(&nd->path);
16800+ AuTraceErr(err);
16801+ return ERR_PTR(err);
16802+}
1facf9fc 16803+
4a4d8108
AM
16804+static void aufs_put_link(struct dentry *dentry __maybe_unused,
16805+ struct nameidata *nd, void *cookie __maybe_unused)
16806+{
16807+ __putname(nd_get_link(nd));
16808+}
1facf9fc 16809+
4a4d8108 16810+/* ---------------------------------------------------------------------- */
1facf9fc 16811+
0c3ec466 16812+static int aufs_update_time(struct inode *inode, struct timespec *ts, int flags)
4a4d8108 16813+{
0c3ec466
AM
16814+ int err;
16815+ struct super_block *sb;
16816+ struct inode *h_inode;
16817+
16818+ sb = inode->i_sb;
16819+ /* mmap_sem might be acquired already, cf. aufs_mmap() */
16820+ lockdep_off();
16821+ si_read_lock(sb, AuLock_FLUSH);
16822+ ii_write_lock_child(inode);
16823+ lockdep_on();
16824+ h_inode = au_h_iptr(inode, au_ibstart(inode));
16825+ err = vfsub_update_time(h_inode, ts, flags);
16826+ lockdep_off();
16827+ ii_write_unlock(inode);
16828+ si_read_unlock(sb);
16829+ lockdep_on();
16830+ return err;
4a4d8108 16831+}
1facf9fc 16832+
4a4d8108 16833+/* ---------------------------------------------------------------------- */
1308ab2a 16834+
4a4d8108
AM
16835+struct inode_operations aufs_symlink_iop = {
16836+ .permission = aufs_permission,
16837+ .setattr = aufs_setattr,
16838+ .getattr = aufs_getattr,
0c3ec466 16839+
4a4d8108
AM
16840+ .readlink = aufs_readlink,
16841+ .follow_link = aufs_follow_link,
0c3ec466
AM
16842+ .put_link = aufs_put_link,
16843+
16844+ /* .update_time = aufs_update_time */
4a4d8108
AM
16845+};
16846+
16847+struct inode_operations aufs_dir_iop = {
16848+ .create = aufs_create,
16849+ .lookup = aufs_lookup,
16850+ .link = aufs_link,
16851+ .unlink = aufs_unlink,
16852+ .symlink = aufs_symlink,
16853+ .mkdir = aufs_mkdir,
16854+ .rmdir = aufs_rmdir,
16855+ .mknod = aufs_mknod,
16856+ .rename = aufs_rename,
16857+
16858+ .permission = aufs_permission,
16859+ .setattr = aufs_setattr,
0c3ec466
AM
16860+ .getattr = aufs_getattr,
16861+
16862+ .update_time = aufs_update_time
4a4d8108
AM
16863+};
16864+
16865+struct inode_operations aufs_iop = {
16866+ .permission = aufs_permission,
16867+ .setattr = aufs_setattr,
16868+ .getattr = aufs_getattr,
0c3ec466
AM
16869+
16870+ .update_time = aufs_update_time
4a4d8108 16871+};
7f207e10
AM
16872diff -urN /usr/share/empty/fs/aufs/i_op_del.c linux/fs/aufs/i_op_del.c
16873--- /usr/share/empty/fs/aufs/i_op_del.c 1970-01-01 01:00:00.000000000 +0100
0c3ec466 16874+++ linux/fs/aufs/i_op_del.c 2012-07-22 19:57:03.164337936 +0200
53392da6 16875@@ -0,0 +1,478 @@
1facf9fc 16876+/*
f6c5ef8b 16877+ * Copyright (C) 2005-2012 Junjiro R. Okajima
1facf9fc 16878+ *
16879+ * This program, aufs is free software; you can redistribute it and/or modify
16880+ * it under the terms of the GNU General Public License as published by
16881+ * the Free Software Foundation; either version 2 of the License, or
16882+ * (at your option) any later version.
dece6358
AM
16883+ *
16884+ * This program is distributed in the hope that it will be useful,
16885+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
16886+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16887+ * GNU General Public License for more details.
16888+ *
16889+ * You should have received a copy of the GNU General Public License
16890+ * along with this program; if not, write to the Free Software
16891+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 16892+ */
16893+
16894+/*
4a4d8108 16895+ * inode operations (del entry)
1308ab2a 16896+ */
dece6358 16897+
1308ab2a 16898+#include "aufs.h"
dece6358 16899+
4a4d8108
AM
16900+/*
16901+ * decide if a new whiteout for @dentry is necessary or not.
16902+ * when it is necessary, prepare the parent dir for the upper branch whose
16903+ * branch index is @bcpup for creation. the actual creation of the whiteout will
16904+ * be done by caller.
16905+ * return value:
16906+ * 0: wh is unnecessary
16907+ * plus: wh is necessary
16908+ * minus: error
16909+ */
16910+int au_wr_dir_need_wh(struct dentry *dentry, int isdir, aufs_bindex_t *bcpup)
1308ab2a 16911+{
4a4d8108
AM
16912+ int need_wh, err;
16913+ aufs_bindex_t bstart;
16914+ struct super_block *sb;
dece6358 16915+
4a4d8108
AM
16916+ sb = dentry->d_sb;
16917+ bstart = au_dbstart(dentry);
16918+ if (*bcpup < 0) {
16919+ *bcpup = bstart;
16920+ if (au_test_ro(sb, bstart, dentry->d_inode)) {
16921+ err = AuWbrCopyup(au_sbi(sb), dentry);
16922+ *bcpup = err;
16923+ if (unlikely(err < 0))
16924+ goto out;
16925+ }
16926+ } else
16927+ AuDebugOn(bstart < *bcpup
16928+ || au_test_ro(sb, *bcpup, dentry->d_inode));
16929+ AuDbg("bcpup %d, bstart %d\n", *bcpup, bstart);
1308ab2a 16930+
4a4d8108
AM
16931+ if (*bcpup != bstart) {
16932+ err = au_cpup_dirs(dentry, *bcpup);
16933+ if (unlikely(err))
16934+ goto out;
16935+ need_wh = 1;
16936+ } else {
027c5e7a 16937+ struct au_dinfo *dinfo, *tmp;
4a4d8108 16938+
027c5e7a
AM
16939+ need_wh = -ENOMEM;
16940+ dinfo = au_di(dentry);
16941+ tmp = au_di_alloc(sb, AuLsc_DI_TMP);
16942+ if (tmp) {
16943+ au_di_cp(tmp, dinfo);
16944+ au_di_swap(tmp, dinfo);
16945+ /* returns the number of positive dentries */
16946+ need_wh = au_lkup_dentry(dentry, bstart + 1, /*type*/0,
16947+ /*nd*/NULL);
16948+ au_di_swap(tmp, dinfo);
16949+ au_rw_write_unlock(&tmp->di_rwsem);
16950+ au_di_free(tmp);
4a4d8108
AM
16951+ }
16952+ }
16953+ AuDbg("need_wh %d\n", need_wh);
16954+ err = need_wh;
16955+
4f0767ce 16956+out:
4a4d8108 16957+ return err;
1facf9fc 16958+}
16959+
4a4d8108
AM
16960+/*
16961+ * simple tests for the del-entry operations.
16962+ * following the checks in vfs, plus the parent-child relationship.
16963+ */
16964+int au_may_del(struct dentry *dentry, aufs_bindex_t bindex,
16965+ struct dentry *h_parent, int isdir)
1facf9fc 16966+{
4a4d8108
AM
16967+ int err;
16968+ umode_t h_mode;
16969+ struct dentry *h_dentry, *h_latest;
1308ab2a 16970+ struct inode *h_inode;
1facf9fc 16971+
4a4d8108
AM
16972+ h_dentry = au_h_dptr(dentry, bindex);
16973+ h_inode = h_dentry->d_inode;
16974+ if (dentry->d_inode) {
16975+ err = -ENOENT;
16976+ if (unlikely(!h_inode || !h_inode->i_nlink))
16977+ goto out;
1facf9fc 16978+
4a4d8108
AM
16979+ h_mode = h_inode->i_mode;
16980+ if (!isdir) {
16981+ err = -EISDIR;
16982+ if (unlikely(S_ISDIR(h_mode)))
16983+ goto out;
16984+ } else if (unlikely(!S_ISDIR(h_mode))) {
16985+ err = -ENOTDIR;
16986+ goto out;
16987+ }
16988+ } else {
16989+ /* rename(2) case */
16990+ err = -EIO;
16991+ if (unlikely(h_inode))
16992+ goto out;
16993+ }
1facf9fc 16994+
4a4d8108
AM
16995+ err = -ENOENT;
16996+ /* expected parent dir is locked */
16997+ if (unlikely(h_parent != h_dentry->d_parent))
16998+ goto out;
16999+ err = 0;
17000+
17001+ /*
17002+ * rmdir a dir may break the consistency on some filesystem.
17003+ * let's try heavy test.
17004+ */
17005+ err = -EACCES;
17006+ if (unlikely(au_test_h_perm(h_parent->d_inode, MAY_EXEC | MAY_WRITE)))
17007+ goto out;
17008+
17009+ h_latest = au_sio_lkup_one(&dentry->d_name, h_parent,
17010+ au_sbr(dentry->d_sb, bindex));
17011+ err = -EIO;
17012+ if (IS_ERR(h_latest))
17013+ goto out;
17014+ if (h_latest == h_dentry)
17015+ err = 0;
17016+ dput(h_latest);
17017+
4f0767ce 17018+out:
4a4d8108 17019+ return err;
1308ab2a 17020+}
1facf9fc 17021+
4a4d8108
AM
17022+/*
17023+ * decide the branch where we operate for @dentry. the branch index will be set
17024+ * @rbcpup. after diciding it, 'pin' it and store the timestamps of the parent
17025+ * dir for reverting.
17026+ * when a new whiteout is necessary, create it.
17027+ */
17028+static struct dentry*
17029+lock_hdir_create_wh(struct dentry *dentry, int isdir, aufs_bindex_t *rbcpup,
17030+ struct au_dtime *dt, struct au_pin *pin)
1308ab2a 17031+{
4a4d8108
AM
17032+ struct dentry *wh_dentry;
17033+ struct super_block *sb;
17034+ struct path h_path;
17035+ int err, need_wh;
17036+ unsigned int udba;
17037+ aufs_bindex_t bcpup;
dece6358 17038+
4a4d8108
AM
17039+ need_wh = au_wr_dir_need_wh(dentry, isdir, rbcpup);
17040+ wh_dentry = ERR_PTR(need_wh);
17041+ if (unlikely(need_wh < 0))
17042+ goto out;
17043+
17044+ sb = dentry->d_sb;
17045+ udba = au_opt_udba(sb);
17046+ bcpup = *rbcpup;
17047+ err = au_pin(pin, dentry, bcpup, udba,
17048+ AuPin_DI_LOCKED | AuPin_MNT_WRITE);
17049+ wh_dentry = ERR_PTR(err);
17050+ if (unlikely(err))
17051+ goto out;
17052+
17053+ h_path.dentry = au_pinned_h_parent(pin);
17054+ if (udba != AuOpt_UDBA_NONE
17055+ && au_dbstart(dentry) == bcpup) {
17056+ err = au_may_del(dentry, bcpup, h_path.dentry, isdir);
17057+ wh_dentry = ERR_PTR(err);
17058+ if (unlikely(err))
17059+ goto out_unpin;
17060+ }
17061+
17062+ h_path.mnt = au_sbr_mnt(sb, bcpup);
17063+ au_dtime_store(dt, au_pinned_parent(pin), &h_path);
17064+ wh_dentry = NULL;
17065+ if (!need_wh)
17066+ goto out; /* success, no need to create whiteout */
17067+
17068+ wh_dentry = au_wh_create(dentry, bcpup, h_path.dentry);
17069+ if (IS_ERR(wh_dentry))
17070+ goto out_unpin;
17071+
17072+ /* returns with the parent is locked and wh_dentry is dget-ed */
17073+ goto out; /* success */
17074+
4f0767ce 17075+out_unpin:
4a4d8108 17076+ au_unpin(pin);
4f0767ce 17077+out:
4a4d8108 17078+ return wh_dentry;
1facf9fc 17079+}
17080+
4a4d8108
AM
17081+/*
17082+ * when removing a dir, rename it to a unique temporary whiteout-ed name first
17083+ * in order to be revertible and save time for removing many child whiteouts
17084+ * under the dir.
17085+ * returns 1 when there are too many child whiteout and caller should remove
17086+ * them asynchronously. returns 0 when the number of children is enough small to
17087+ * remove now or the branch fs is a remote fs.
17088+ * otherwise return an error.
17089+ */
17090+static int renwh_and_rmdir(struct dentry *dentry, aufs_bindex_t bindex,
17091+ struct au_nhash *whlist, struct inode *dir)
1facf9fc 17092+{
4a4d8108
AM
17093+ int rmdir_later, err, dirwh;
17094+ struct dentry *h_dentry;
17095+ struct super_block *sb;
17096+
17097+ sb = dentry->d_sb;
17098+ SiMustAnyLock(sb);
17099+ h_dentry = au_h_dptr(dentry, bindex);
17100+ err = au_whtmp_ren(h_dentry, au_sbr(sb, bindex));
17101+ if (unlikely(err))
17102+ goto out;
17103+
17104+ /* stop monitoring */
17105+ au_hn_free(au_hi(dentry->d_inode, bindex));
17106+
17107+ if (!au_test_fs_remote(h_dentry->d_sb)) {
17108+ dirwh = au_sbi(sb)->si_dirwh;
17109+ rmdir_later = (dirwh <= 1);
17110+ if (!rmdir_later)
17111+ rmdir_later = au_nhash_test_longer_wh(whlist, bindex,
17112+ dirwh);
17113+ if (rmdir_later)
17114+ return rmdir_later;
17115+ }
1facf9fc 17116+
4a4d8108
AM
17117+ err = au_whtmp_rmdir(dir, bindex, h_dentry, whlist);
17118+ if (unlikely(err)) {
17119+ AuIOErr("rmdir %.*s, b%d failed, %d. ignored\n",
17120+ AuDLNPair(h_dentry), bindex, err);
17121+ err = 0;
17122+ }
dece6358 17123+
4f0767ce 17124+out:
4a4d8108
AM
17125+ AuTraceErr(err);
17126+ return err;
17127+}
1308ab2a 17128+
4a4d8108
AM
17129+/*
17130+ * final procedure for deleting a entry.
17131+ * maintain dentry and iattr.
17132+ */
17133+static void epilog(struct inode *dir, struct dentry *dentry,
17134+ aufs_bindex_t bindex)
17135+{
17136+ struct inode *inode;
1308ab2a 17137+
4a4d8108
AM
17138+ inode = dentry->d_inode;
17139+ d_drop(dentry);
17140+ inode->i_ctime = dir->i_ctime;
1308ab2a 17141+
4a4d8108
AM
17142+ if (au_ibstart(dir) == bindex)
17143+ au_cpup_attr_timesizes(dir);
17144+ dir->i_version++;
1facf9fc 17145+}
17146+
4a4d8108
AM
17147+/*
17148+ * when an error happened, remove the created whiteout and revert everything.
17149+ */
7f207e10
AM
17150+static int do_revert(int err, struct inode *dir, aufs_bindex_t bindex,
17151+ aufs_bindex_t bwh, struct dentry *wh_dentry,
17152+ struct dentry *dentry, struct au_dtime *dt)
1facf9fc 17153+{
4a4d8108
AM
17154+ int rerr;
17155+ struct path h_path = {
17156+ .dentry = wh_dentry,
7f207e10 17157+ .mnt = au_sbr_mnt(dir->i_sb, bindex)
4a4d8108 17158+ };
dece6358 17159+
7f207e10 17160+ rerr = au_wh_unlink_dentry(au_h_iptr(dir, bindex), &h_path, dentry);
4a4d8108
AM
17161+ if (!rerr) {
17162+ au_set_dbwh(dentry, bwh);
17163+ au_dtime_revert(dt);
17164+ return 0;
17165+ }
dece6358 17166+
4a4d8108
AM
17167+ AuIOErr("%.*s reverting whiteout failed(%d, %d)\n",
17168+ AuDLNPair(dentry), err, rerr);
17169+ return -EIO;
1facf9fc 17170+}
17171+
4a4d8108 17172+/* ---------------------------------------------------------------------- */
1facf9fc 17173+
4a4d8108 17174+int aufs_unlink(struct inode *dir, struct dentry *dentry)
1308ab2a 17175+{
4a4d8108
AM
17176+ int err;
17177+ aufs_bindex_t bwh, bindex, bstart;
17178+ struct au_dtime dt;
17179+ struct au_pin pin;
17180+ struct path h_path;
17181+ struct inode *inode, *h_dir;
17182+ struct dentry *parent, *wh_dentry;
1facf9fc 17183+
4a4d8108 17184+ IMustLock(dir);
027c5e7a
AM
17185+
17186+ err = aufs_read_lock(dentry, AuLock_DW | AuLock_GEN);
17187+ if (unlikely(err))
17188+ goto out;
17189+ err = au_d_hashed_positive(dentry);
17190+ if (unlikely(err))
17191+ goto out_unlock;
4a4d8108 17192+ inode = dentry->d_inode;
4a4d8108 17193+ IMustLock(inode);
027c5e7a
AM
17194+ err = -EISDIR;
17195+ if (unlikely(S_ISDIR(inode->i_mode)))
17196+ goto out_unlock; /* possible? */
1facf9fc 17197+
4a4d8108
AM
17198+ bstart = au_dbstart(dentry);
17199+ bwh = au_dbwh(dentry);
17200+ bindex = -1;
027c5e7a
AM
17201+ parent = dentry->d_parent; /* dir inode is locked */
17202+ di_write_lock_parent(parent);
4a4d8108
AM
17203+ wh_dentry = lock_hdir_create_wh(dentry, /*isdir*/0, &bindex, &dt, &pin);
17204+ err = PTR_ERR(wh_dentry);
17205+ if (IS_ERR(wh_dentry))
027c5e7a 17206+ goto out_parent;
1facf9fc 17207+
4a4d8108
AM
17208+ h_path.mnt = au_sbr_mnt(dentry->d_sb, bstart);
17209+ h_path.dentry = au_h_dptr(dentry, bstart);
17210+ dget(h_path.dentry);
17211+ if (bindex == bstart) {
17212+ h_dir = au_pinned_h_dir(&pin);
17213+ err = vfsub_unlink(h_dir, &h_path, /*force*/0);
17214+ } else {
17215+ /* dir inode is locked */
17216+ h_dir = wh_dentry->d_parent->d_inode;
17217+ IMustLock(h_dir);
17218+ err = 0;
17219+ }
dece6358 17220+
4a4d8108 17221+ if (!err) {
7f207e10 17222+ vfsub_drop_nlink(inode);
4a4d8108
AM
17223+ epilog(dir, dentry, bindex);
17224+
17225+ /* update target timestamps */
17226+ if (bindex == bstart) {
17227+ vfsub_update_h_iattr(&h_path, /*did*/NULL); /*ignore*/
17228+ inode->i_ctime = h_path.dentry->d_inode->i_ctime;
17229+ } else
17230+ /* todo: this timestamp may be reverted later */
17231+ inode->i_ctime = h_dir->i_ctime;
027c5e7a 17232+ goto out_unpin; /* success */
1facf9fc 17233+ }
17234+
4a4d8108
AM
17235+ /* revert */
17236+ if (wh_dentry) {
17237+ int rerr;
17238+
7f207e10 17239+ rerr = do_revert(err, dir, bindex, bwh, wh_dentry, dentry, &dt);
4a4d8108
AM
17240+ if (rerr)
17241+ err = rerr;
dece6358 17242+ }
1facf9fc 17243+
027c5e7a 17244+out_unpin:
4a4d8108
AM
17245+ au_unpin(&pin);
17246+ dput(wh_dentry);
17247+ dput(h_path.dentry);
027c5e7a 17248+out_parent:
4a4d8108 17249+ di_write_unlock(parent);
027c5e7a 17250+out_unlock:
4a4d8108 17251+ aufs_read_unlock(dentry, AuLock_DW);
027c5e7a 17252+out:
4a4d8108 17253+ return err;
dece6358
AM
17254+}
17255+
4a4d8108 17256+int aufs_rmdir(struct inode *dir, struct dentry *dentry)
1308ab2a 17257+{
4a4d8108
AM
17258+ int err, rmdir_later;
17259+ aufs_bindex_t bwh, bindex, bstart;
17260+ struct au_dtime dt;
17261+ struct au_pin pin;
17262+ struct inode *inode;
17263+ struct dentry *parent, *wh_dentry, *h_dentry;
17264+ struct au_whtmp_rmdir *args;
1facf9fc 17265+
4a4d8108 17266+ IMustLock(dir);
027c5e7a
AM
17267+
17268+ err = aufs_read_lock(dentry, AuLock_DW | AuLock_FLUSH | AuLock_GEN);
17269+ if (unlikely(err))
4a4d8108 17270+ goto out;
53392da6
AM
17271+ err = au_alive_dir(dentry);
17272+ if (unlikely(err))
027c5e7a 17273+ goto out_unlock;
53392da6 17274+ inode = dentry->d_inode;
4a4d8108 17275+ IMustLock(inode);
027c5e7a
AM
17276+ err = -ENOTDIR;
17277+ if (unlikely(!S_ISDIR(inode->i_mode)))
17278+ goto out_unlock; /* possible? */
dece6358 17279+
4a4d8108
AM
17280+ err = -ENOMEM;
17281+ args = au_whtmp_rmdir_alloc(dir->i_sb, GFP_NOFS);
17282+ if (unlikely(!args))
17283+ goto out_unlock;
dece6358 17284+
4a4d8108
AM
17285+ parent = dentry->d_parent; /* dir inode is locked */
17286+ di_write_lock_parent(parent);
17287+ err = au_test_empty(dentry, &args->whlist);
17288+ if (unlikely(err))
027c5e7a 17289+ goto out_parent;
1facf9fc 17290+
4a4d8108
AM
17291+ bstart = au_dbstart(dentry);
17292+ bwh = au_dbwh(dentry);
17293+ bindex = -1;
17294+ wh_dentry = lock_hdir_create_wh(dentry, /*isdir*/1, &bindex, &dt, &pin);
17295+ err = PTR_ERR(wh_dentry);
17296+ if (IS_ERR(wh_dentry))
027c5e7a 17297+ goto out_parent;
1facf9fc 17298+
4a4d8108
AM
17299+ h_dentry = au_h_dptr(dentry, bstart);
17300+ dget(h_dentry);
17301+ rmdir_later = 0;
17302+ if (bindex == bstart) {
17303+ err = renwh_and_rmdir(dentry, bstart, &args->whlist, dir);
17304+ if (err > 0) {
17305+ rmdir_later = err;
17306+ err = 0;
17307+ }
17308+ } else {
17309+ /* stop monitoring */
17310+ au_hn_free(au_hi(inode, bstart));
17311+
17312+ /* dir inode is locked */
17313+ IMustLock(wh_dentry->d_parent->d_inode);
1facf9fc 17314+ err = 0;
17315+ }
17316+
4a4d8108 17317+ if (!err) {
027c5e7a 17318+ vfsub_dead_dir(inode);
4a4d8108
AM
17319+ au_set_dbdiropq(dentry, -1);
17320+ epilog(dir, dentry, bindex);
1308ab2a 17321+
4a4d8108
AM
17322+ if (rmdir_later) {
17323+ au_whtmp_kick_rmdir(dir, bstart, h_dentry, args);
17324+ args = NULL;
17325+ }
1308ab2a 17326+
4a4d8108 17327+ goto out_unpin; /* success */
1facf9fc 17328+ }
17329+
4a4d8108
AM
17330+ /* revert */
17331+ AuLabel(revert);
17332+ if (wh_dentry) {
17333+ int rerr;
1308ab2a 17334+
7f207e10 17335+ rerr = do_revert(err, dir, bindex, bwh, wh_dentry, dentry, &dt);
4a4d8108
AM
17336+ if (rerr)
17337+ err = rerr;
1facf9fc 17338+ }
17339+
4f0767ce 17340+out_unpin:
4a4d8108
AM
17341+ au_unpin(&pin);
17342+ dput(wh_dentry);
17343+ dput(h_dentry);
027c5e7a 17344+out_parent:
4a4d8108
AM
17345+ di_write_unlock(parent);
17346+ if (args)
17347+ au_whtmp_rmdir_free(args);
4f0767ce 17348+out_unlock:
4a4d8108 17349+ aufs_read_unlock(dentry, AuLock_DW);
4f0767ce 17350+out:
4a4d8108
AM
17351+ AuTraceErr(err);
17352+ return err;
dece6358 17353+}
7f207e10
AM
17354diff -urN /usr/share/empty/fs/aufs/i_op_ren.c linux/fs/aufs/i_op_ren.c
17355--- /usr/share/empty/fs/aufs/i_op_ren.c 1970-01-01 01:00:00.000000000 +0100
0c3ec466 17356+++ linux/fs/aufs/i_op_ren.c 2012-07-22 19:57:03.164337936 +0200
7eafdf33 17357@@ -0,0 +1,1026 @@
1facf9fc 17358+/*
f6c5ef8b 17359+ * Copyright (C) 2005-2012 Junjiro R. Okajima
1facf9fc 17360+ *
17361+ * This program, aufs is free software; you can redistribute it and/or modify
17362+ * it under the terms of the GNU General Public License as published by
17363+ * the Free Software Foundation; either version 2 of the License, or
17364+ * (at your option) any later version.
dece6358
AM
17365+ *
17366+ * This program is distributed in the hope that it will be useful,
17367+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
17368+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17369+ * GNU General Public License for more details.
17370+ *
17371+ * You should have received a copy of the GNU General Public License
17372+ * along with this program; if not, write to the Free Software
17373+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 17374+ */
17375+
17376+/*
4a4d8108
AM
17377+ * inode operation (rename entry)
17378+ * todo: this is crazy monster
1facf9fc 17379+ */
17380+
17381+#include "aufs.h"
17382+
4a4d8108
AM
17383+enum { AuSRC, AuDST, AuSrcDst };
17384+enum { AuPARENT, AuCHILD, AuParentChild };
1facf9fc 17385+
4a4d8108
AM
17386+#define AuRen_ISDIR 1
17387+#define AuRen_ISSAMEDIR (1 << 1)
17388+#define AuRen_WHSRC (1 << 2)
17389+#define AuRen_WHDST (1 << 3)
17390+#define AuRen_MNT_WRITE (1 << 4)
17391+#define AuRen_DT_DSTDIR (1 << 5)
17392+#define AuRen_DIROPQ (1 << 6)
17393+#define AuRen_CPUP (1 << 7)
17394+#define au_ftest_ren(flags, name) ((flags) & AuRen_##name)
7f207e10
AM
17395+#define au_fset_ren(flags, name) \
17396+ do { (flags) |= AuRen_##name; } while (0)
17397+#define au_fclr_ren(flags, name) \
17398+ do { (flags) &= ~AuRen_##name; } while (0)
1facf9fc 17399+
4a4d8108
AM
17400+struct au_ren_args {
17401+ struct {
17402+ struct dentry *dentry, *h_dentry, *parent, *h_parent,
17403+ *wh_dentry;
17404+ struct inode *dir, *inode;
17405+ struct au_hinode *hdir;
17406+ struct au_dtime dt[AuParentChild];
17407+ aufs_bindex_t bstart;
17408+ } sd[AuSrcDst];
1facf9fc 17409+
4a4d8108
AM
17410+#define src_dentry sd[AuSRC].dentry
17411+#define src_dir sd[AuSRC].dir
17412+#define src_inode sd[AuSRC].inode
17413+#define src_h_dentry sd[AuSRC].h_dentry
17414+#define src_parent sd[AuSRC].parent
17415+#define src_h_parent sd[AuSRC].h_parent
17416+#define src_wh_dentry sd[AuSRC].wh_dentry
17417+#define src_hdir sd[AuSRC].hdir
17418+#define src_h_dir sd[AuSRC].hdir->hi_inode
17419+#define src_dt sd[AuSRC].dt
17420+#define src_bstart sd[AuSRC].bstart
1facf9fc 17421+
4a4d8108
AM
17422+#define dst_dentry sd[AuDST].dentry
17423+#define dst_dir sd[AuDST].dir
17424+#define dst_inode sd[AuDST].inode
17425+#define dst_h_dentry sd[AuDST].h_dentry
17426+#define dst_parent sd[AuDST].parent
17427+#define dst_h_parent sd[AuDST].h_parent
17428+#define dst_wh_dentry sd[AuDST].wh_dentry
17429+#define dst_hdir sd[AuDST].hdir
17430+#define dst_h_dir sd[AuDST].hdir->hi_inode
17431+#define dst_dt sd[AuDST].dt
17432+#define dst_bstart sd[AuDST].bstart
17433+
17434+ struct dentry *h_trap;
17435+ struct au_branch *br;
17436+ struct au_hinode *src_hinode;
17437+ struct path h_path;
17438+ struct au_nhash whlist;
027c5e7a 17439+ aufs_bindex_t btgt, src_bwh, src_bdiropq;
1facf9fc 17440+
1308ab2a 17441+ unsigned int flags;
1facf9fc 17442+
4a4d8108
AM
17443+ struct au_whtmp_rmdir *thargs;
17444+ struct dentry *h_dst;
17445+};
1308ab2a 17446+
4a4d8108 17447+/* ---------------------------------------------------------------------- */
1308ab2a 17448+
4a4d8108
AM
17449+/*
17450+ * functions for reverting.
17451+ * when an error happened in a single rename systemcall, we should revert
17452+ * everything as if nothing happend.
17453+ * we don't need to revert the copied-up/down the parent dir since they are
17454+ * harmless.
17455+ */
1facf9fc 17456+
4a4d8108
AM
17457+#define RevertFailure(fmt, ...) do { \
17458+ AuIOErr("revert failure: " fmt " (%d, %d)\n", \
17459+ ##__VA_ARGS__, err, rerr); \
17460+ err = -EIO; \
17461+} while (0)
1facf9fc 17462+
4a4d8108 17463+static void au_ren_rev_diropq(int err, struct au_ren_args *a)
1facf9fc 17464+{
4a4d8108 17465+ int rerr;
1facf9fc 17466+
4a4d8108
AM
17467+ au_hn_imtx_lock_nested(a->src_hinode, AuLsc_I_CHILD);
17468+ rerr = au_diropq_remove(a->src_dentry, a->btgt);
17469+ au_hn_imtx_unlock(a->src_hinode);
027c5e7a 17470+ au_set_dbdiropq(a->src_dentry, a->src_bdiropq);
4a4d8108
AM
17471+ if (rerr)
17472+ RevertFailure("remove diropq %.*s", AuDLNPair(a->src_dentry));
17473+}
1facf9fc 17474+
4a4d8108
AM
17475+static void au_ren_rev_rename(int err, struct au_ren_args *a)
17476+{
17477+ int rerr;
1facf9fc 17478+
4a4d8108
AM
17479+ a->h_path.dentry = au_lkup_one(&a->src_dentry->d_name, a->src_h_parent,
17480+ a->br, /*nd*/NULL);
17481+ rerr = PTR_ERR(a->h_path.dentry);
17482+ if (IS_ERR(a->h_path.dentry)) {
17483+ RevertFailure("au_lkup_one %.*s", AuDLNPair(a->src_dentry));
17484+ return;
1facf9fc 17485+ }
17486+
4a4d8108
AM
17487+ rerr = vfsub_rename(a->dst_h_dir,
17488+ au_h_dptr(a->src_dentry, a->btgt),
17489+ a->src_h_dir, &a->h_path);
17490+ d_drop(a->h_path.dentry);
17491+ dput(a->h_path.dentry);
17492+ /* au_set_h_dptr(a->src_dentry, a->btgt, NULL); */
17493+ if (rerr)
17494+ RevertFailure("rename %.*s", AuDLNPair(a->src_dentry));
1facf9fc 17495+}
17496+
4a4d8108 17497+static void au_ren_rev_cpup(int err, struct au_ren_args *a)
1facf9fc 17498+{
4a4d8108 17499+ int rerr;
1facf9fc 17500+
4a4d8108
AM
17501+ a->h_path.dentry = a->dst_h_dentry;
17502+ rerr = vfsub_unlink(a->dst_h_dir, &a->h_path, /*force*/0);
17503+ au_set_h_dptr(a->src_dentry, a->btgt, NULL);
17504+ au_set_dbstart(a->src_dentry, a->src_bstart);
17505+ if (rerr)
17506+ RevertFailure("unlink %.*s", AuDLNPair(a->dst_h_dentry));
1facf9fc 17507+}
17508+
4a4d8108 17509+static void au_ren_rev_whtmp(int err, struct au_ren_args *a)
1facf9fc 17510+{
4a4d8108 17511+ int rerr;
dece6358 17512+
4a4d8108
AM
17513+ a->h_path.dentry = au_lkup_one(&a->dst_dentry->d_name, a->dst_h_parent,
17514+ a->br, /*nd*/NULL);
17515+ rerr = PTR_ERR(a->h_path.dentry);
17516+ if (IS_ERR(a->h_path.dentry)) {
17517+ RevertFailure("lookup %.*s", AuDLNPair(a->dst_dentry));
17518+ return;
17519+ }
17520+ if (a->h_path.dentry->d_inode) {
17521+ d_drop(a->h_path.dentry);
17522+ dput(a->h_path.dentry);
17523+ return;
dece6358
AM
17524+ }
17525+
4a4d8108
AM
17526+ rerr = vfsub_rename(a->dst_h_dir, a->h_dst, a->dst_h_dir, &a->h_path);
17527+ d_drop(a->h_path.dentry);
17528+ dput(a->h_path.dentry);
17529+ if (!rerr)
17530+ au_set_h_dptr(a->dst_dentry, a->btgt, dget(a->h_dst));
17531+ else
17532+ RevertFailure("rename %.*s", AuDLNPair(a->h_dst));
17533+}
1308ab2a 17534+
4a4d8108
AM
17535+static void au_ren_rev_whsrc(int err, struct au_ren_args *a)
17536+{
17537+ int rerr;
1308ab2a 17538+
4a4d8108
AM
17539+ a->h_path.dentry = a->src_wh_dentry;
17540+ rerr = au_wh_unlink_dentry(a->src_h_dir, &a->h_path, a->src_dentry);
027c5e7a 17541+ au_set_dbwh(a->src_dentry, a->src_bwh);
4a4d8108
AM
17542+ if (rerr)
17543+ RevertFailure("unlink %.*s", AuDLNPair(a->src_wh_dentry));
17544+}
4a4d8108 17545+#undef RevertFailure
1facf9fc 17546+
1308ab2a 17547+/* ---------------------------------------------------------------------- */
17548+
4a4d8108
AM
17549+/*
17550+ * when we have to copyup the renaming entry, do it with the rename-target name
17551+ * in order to minimize the cost (the later actual rename is unnecessary).
17552+ * otherwise rename it on the target branch.
17553+ */
17554+static int au_ren_or_cpup(struct au_ren_args *a)
1facf9fc 17555+{
dece6358 17556+ int err;
4a4d8108 17557+ struct dentry *d;
1facf9fc 17558+
4a4d8108
AM
17559+ d = a->src_dentry;
17560+ if (au_dbstart(d) == a->btgt) {
17561+ a->h_path.dentry = a->dst_h_dentry;
17562+ if (au_ftest_ren(a->flags, DIROPQ)
17563+ && au_dbdiropq(d) == a->btgt)
17564+ au_fclr_ren(a->flags, DIROPQ);
17565+ AuDebugOn(au_dbstart(d) != a->btgt);
17566+ err = vfsub_rename(a->src_h_dir, au_h_dptr(d, a->btgt),
17567+ a->dst_h_dir, &a->h_path);
17568+ } else {
17569+ struct mutex *h_mtx = &a->src_h_dentry->d_inode->i_mutex;
17570+ struct file *h_file;
1308ab2a 17571+
4a4d8108
AM
17572+ au_fset_ren(a->flags, CPUP);
17573+ mutex_lock_nested(h_mtx, AuLsc_I_CHILD);
17574+ au_set_dbstart(d, a->btgt);
17575+ au_set_h_dptr(d, a->btgt, dget(a->dst_h_dentry));
17576+ h_file = au_h_open_pre(d, a->src_bstart);
17577+ if (IS_ERR(h_file)) {
17578+ err = PTR_ERR(h_file);
17579+ h_file = NULL;
17580+ } else
17581+ err = au_sio_cpup_single(d, a->btgt, a->src_bstart, -1,
17582+ !AuCpup_DTIME, a->dst_parent);
17583+ mutex_unlock(h_mtx);
17584+ au_h_open_post(d, a->src_bstart, h_file);
17585+ if (!err) {
17586+ d = a->dst_dentry;
17587+ au_set_h_dptr(d, a->btgt, NULL);
17588+ au_update_dbstart(d);
17589+ } else {
17590+ au_set_h_dptr(d, a->btgt, NULL);
17591+ au_set_dbstart(d, a->src_bstart);
17592+ }
1308ab2a 17593+ }
027c5e7a
AM
17594+ if (!err && a->h_dst)
17595+ /* it will be set to dinfo later */
17596+ dget(a->h_dst);
1facf9fc 17597+
dece6358
AM
17598+ return err;
17599+}
1facf9fc 17600+
4a4d8108
AM
17601+/* cf. aufs_rmdir() */
17602+static int au_ren_del_whtmp(struct au_ren_args *a)
dece6358 17603+{
4a4d8108
AM
17604+ int err;
17605+ struct inode *dir;
1facf9fc 17606+
4a4d8108
AM
17607+ dir = a->dst_dir;
17608+ SiMustAnyLock(dir->i_sb);
17609+ if (!au_nhash_test_longer_wh(&a->whlist, a->btgt,
17610+ au_sbi(dir->i_sb)->si_dirwh)
17611+ || au_test_fs_remote(a->h_dst->d_sb)) {
17612+ err = au_whtmp_rmdir(dir, a->btgt, a->h_dst, &a->whlist);
17613+ if (unlikely(err))
0c3ec466
AM
17614+ pr_warn("failed removing whtmp dir %.*s (%d), "
17615+ "ignored.\n", AuDLNPair(a->h_dst), err);
4a4d8108
AM
17616+ } else {
17617+ au_nhash_wh_free(&a->thargs->whlist);
17618+ a->thargs->whlist = a->whlist;
17619+ a->whlist.nh_num = 0;
17620+ au_whtmp_kick_rmdir(dir, a->btgt, a->h_dst, a->thargs);
17621+ dput(a->h_dst);
17622+ a->thargs = NULL;
17623+ }
17624+
17625+ return 0;
1308ab2a 17626+}
1facf9fc 17627+
4a4d8108
AM
17628+/* make it 'opaque' dir. */
17629+static int au_ren_diropq(struct au_ren_args *a)
17630+{
17631+ int err;
17632+ struct dentry *diropq;
1facf9fc 17633+
4a4d8108 17634+ err = 0;
027c5e7a 17635+ a->src_bdiropq = au_dbdiropq(a->src_dentry);
4a4d8108
AM
17636+ a->src_hinode = au_hi(a->src_inode, a->btgt);
17637+ au_hn_imtx_lock_nested(a->src_hinode, AuLsc_I_CHILD);
17638+ diropq = au_diropq_create(a->src_dentry, a->btgt);
17639+ au_hn_imtx_unlock(a->src_hinode);
17640+ if (IS_ERR(diropq))
17641+ err = PTR_ERR(diropq);
17642+ dput(diropq);
1facf9fc 17643+
4a4d8108
AM
17644+ return err;
17645+}
1facf9fc 17646+
4a4d8108
AM
17647+static int do_rename(struct au_ren_args *a)
17648+{
17649+ int err;
17650+ struct dentry *d, *h_d;
1facf9fc 17651+
4a4d8108
AM
17652+ /* prepare workqueue args for asynchronous rmdir */
17653+ h_d = a->dst_h_dentry;
17654+ if (au_ftest_ren(a->flags, ISDIR) && h_d->d_inode) {
17655+ err = -ENOMEM;
17656+ a->thargs = au_whtmp_rmdir_alloc(a->src_dentry->d_sb, GFP_NOFS);
17657+ if (unlikely(!a->thargs))
17658+ goto out;
17659+ a->h_dst = dget(h_d);
17660+ }
1facf9fc 17661+
4a4d8108
AM
17662+ /* create whiteout for src_dentry */
17663+ if (au_ftest_ren(a->flags, WHSRC)) {
027c5e7a
AM
17664+ a->src_bwh = au_dbwh(a->src_dentry);
17665+ AuDebugOn(a->src_bwh >= 0);
4a4d8108
AM
17666+ a->src_wh_dentry
17667+ = au_wh_create(a->src_dentry, a->btgt, a->src_h_parent);
17668+ err = PTR_ERR(a->src_wh_dentry);
17669+ if (IS_ERR(a->src_wh_dentry))
17670+ goto out_thargs;
17671+ }
1facf9fc 17672+
4a4d8108
AM
17673+ /* lookup whiteout for dentry */
17674+ if (au_ftest_ren(a->flags, WHDST)) {
17675+ h_d = au_wh_lkup(a->dst_h_parent, &a->dst_dentry->d_name,
17676+ a->br);
17677+ err = PTR_ERR(h_d);
17678+ if (IS_ERR(h_d))
17679+ goto out_whsrc;
17680+ if (!h_d->d_inode)
17681+ dput(h_d);
17682+ else
17683+ a->dst_wh_dentry = h_d;
17684+ }
1facf9fc 17685+
4a4d8108
AM
17686+ /* rename dentry to tmpwh */
17687+ if (a->thargs) {
17688+ err = au_whtmp_ren(a->dst_h_dentry, a->br);
17689+ if (unlikely(err))
17690+ goto out_whdst;
dece6358 17691+
4a4d8108
AM
17692+ d = a->dst_dentry;
17693+ au_set_h_dptr(d, a->btgt, NULL);
17694+ err = au_lkup_neg(d, a->btgt);
17695+ if (unlikely(err))
17696+ goto out_whtmp;
17697+ a->dst_h_dentry = au_h_dptr(d, a->btgt);
17698+ }
1facf9fc 17699+
4a4d8108
AM
17700+ /* cpup src */
17701+ if (a->dst_h_dentry->d_inode && a->src_bstart != a->btgt) {
17702+ struct mutex *h_mtx = &a->src_h_dentry->d_inode->i_mutex;
17703+ struct file *h_file;
1facf9fc 17704+
4a4d8108
AM
17705+ mutex_lock_nested(h_mtx, AuLsc_I_CHILD);
17706+ AuDebugOn(au_dbstart(a->src_dentry) != a->src_bstart);
17707+ h_file = au_h_open_pre(a->src_dentry, a->src_bstart);
17708+ if (IS_ERR(h_file)) {
17709+ err = PTR_ERR(h_file);
17710+ h_file = NULL;
17711+ } else
17712+ err = au_sio_cpup_simple(a->src_dentry, a->btgt, -1,
17713+ !AuCpup_DTIME);
17714+ mutex_unlock(h_mtx);
17715+ au_h_open_post(a->src_dentry, a->src_bstart, h_file);
17716+ if (unlikely(err))
17717+ goto out_whtmp;
17718+ }
1facf9fc 17719+
4a4d8108
AM
17720+ /* rename by vfs_rename or cpup */
17721+ d = a->dst_dentry;
17722+ if (au_ftest_ren(a->flags, ISDIR)
17723+ && (a->dst_wh_dentry
17724+ || au_dbdiropq(d) == a->btgt
17725+ /* hide the lower to keep xino */
17726+ || a->btgt < au_dbend(d)
17727+ || au_opt_test(au_mntflags(d->d_sb), ALWAYS_DIROPQ)))
17728+ au_fset_ren(a->flags, DIROPQ);
17729+ err = au_ren_or_cpup(a);
17730+ if (unlikely(err))
17731+ /* leave the copied-up one */
17732+ goto out_whtmp;
1308ab2a 17733+
4a4d8108
AM
17734+ /* make dir opaque */
17735+ if (au_ftest_ren(a->flags, DIROPQ)) {
17736+ err = au_ren_diropq(a);
17737+ if (unlikely(err))
17738+ goto out_rename;
17739+ }
1308ab2a 17740+
4a4d8108
AM
17741+ /* update target timestamps */
17742+ AuDebugOn(au_dbstart(a->src_dentry) != a->btgt);
17743+ a->h_path.dentry = au_h_dptr(a->src_dentry, a->btgt);
17744+ vfsub_update_h_iattr(&a->h_path, /*did*/NULL); /*ignore*/
17745+ a->src_inode->i_ctime = a->h_path.dentry->d_inode->i_ctime;
1facf9fc 17746+
4a4d8108
AM
17747+ /* remove whiteout for dentry */
17748+ if (a->dst_wh_dentry) {
17749+ a->h_path.dentry = a->dst_wh_dentry;
17750+ err = au_wh_unlink_dentry(a->dst_h_dir, &a->h_path,
17751+ a->dst_dentry);
17752+ if (unlikely(err))
17753+ goto out_diropq;
17754+ }
1facf9fc 17755+
4a4d8108
AM
17756+ /* remove whtmp */
17757+ if (a->thargs)
17758+ au_ren_del_whtmp(a); /* ignore this error */
1308ab2a 17759+
4a4d8108
AM
17760+ err = 0;
17761+ goto out_success;
17762+
4f0767ce 17763+out_diropq:
4a4d8108
AM
17764+ if (au_ftest_ren(a->flags, DIROPQ))
17765+ au_ren_rev_diropq(err, a);
4f0767ce 17766+out_rename:
4a4d8108
AM
17767+ if (!au_ftest_ren(a->flags, CPUP))
17768+ au_ren_rev_rename(err, a);
17769+ else
17770+ au_ren_rev_cpup(err, a);
027c5e7a 17771+ dput(a->h_dst);
4f0767ce 17772+out_whtmp:
4a4d8108
AM
17773+ if (a->thargs)
17774+ au_ren_rev_whtmp(err, a);
4f0767ce 17775+out_whdst:
4a4d8108
AM
17776+ dput(a->dst_wh_dentry);
17777+ a->dst_wh_dentry = NULL;
4f0767ce 17778+out_whsrc:
4a4d8108
AM
17779+ if (a->src_wh_dentry)
17780+ au_ren_rev_whsrc(err, a);
4f0767ce 17781+out_success:
4a4d8108
AM
17782+ dput(a->src_wh_dentry);
17783+ dput(a->dst_wh_dentry);
4f0767ce 17784+out_thargs:
4a4d8108
AM
17785+ if (a->thargs) {
17786+ dput(a->h_dst);
17787+ au_whtmp_rmdir_free(a->thargs);
17788+ a->thargs = NULL;
17789+ }
4f0767ce 17790+out:
4a4d8108 17791+ return err;
dece6358 17792+}
1facf9fc 17793+
1308ab2a 17794+/* ---------------------------------------------------------------------- */
1facf9fc 17795+
4a4d8108
AM
17796+/*
17797+ * test if @dentry dir can be rename destination or not.
17798+ * success means, it is a logically empty dir.
17799+ */
17800+static int may_rename_dstdir(struct dentry *dentry, struct au_nhash *whlist)
1308ab2a 17801+{
4a4d8108 17802+ return au_test_empty(dentry, whlist);
1308ab2a 17803+}
1facf9fc 17804+
4a4d8108
AM
17805+/*
17806+ * test if @dentry dir can be rename source or not.
17807+ * if it can, return 0 and @children is filled.
17808+ * success means,
17809+ * - it is a logically empty dir.
17810+ * - or, it exists on writable branch and has no children including whiteouts
17811+ * on the lower branch.
17812+ */
17813+static int may_rename_srcdir(struct dentry *dentry, aufs_bindex_t btgt)
17814+{
17815+ int err;
17816+ unsigned int rdhash;
17817+ aufs_bindex_t bstart;
1facf9fc 17818+
4a4d8108
AM
17819+ bstart = au_dbstart(dentry);
17820+ if (bstart != btgt) {
17821+ struct au_nhash whlist;
dece6358 17822+
4a4d8108
AM
17823+ SiMustAnyLock(dentry->d_sb);
17824+ rdhash = au_sbi(dentry->d_sb)->si_rdhash;
17825+ if (!rdhash)
17826+ rdhash = au_rdhash_est(au_dir_size(/*file*/NULL,
17827+ dentry));
17828+ err = au_nhash_alloc(&whlist, rdhash, GFP_NOFS);
17829+ if (unlikely(err))
17830+ goto out;
17831+ err = au_test_empty(dentry, &whlist);
17832+ au_nhash_wh_free(&whlist);
17833+ goto out;
17834+ }
dece6358 17835+
4a4d8108
AM
17836+ if (bstart == au_dbtaildir(dentry))
17837+ return 0; /* success */
dece6358 17838+
4a4d8108 17839+ err = au_test_empty_lower(dentry);
1facf9fc 17840+
4f0767ce 17841+out:
4a4d8108
AM
17842+ if (err == -ENOTEMPTY) {
17843+ AuWarn1("renaming dir who has child(ren) on multiple branches,"
17844+ " is not supported\n");
17845+ err = -EXDEV;
17846+ }
17847+ return err;
17848+}
1308ab2a 17849+
4a4d8108
AM
17850+/* side effect: sets whlist and h_dentry */
17851+static int au_ren_may_dir(struct au_ren_args *a)
1308ab2a 17852+{
4a4d8108
AM
17853+ int err;
17854+ unsigned int rdhash;
17855+ struct dentry *d;
1facf9fc 17856+
4a4d8108
AM
17857+ d = a->dst_dentry;
17858+ SiMustAnyLock(d->d_sb);
1facf9fc 17859+
4a4d8108
AM
17860+ err = 0;
17861+ if (au_ftest_ren(a->flags, ISDIR) && a->dst_inode) {
17862+ rdhash = au_sbi(d->d_sb)->si_rdhash;
17863+ if (!rdhash)
17864+ rdhash = au_rdhash_est(au_dir_size(/*file*/NULL, d));
17865+ err = au_nhash_alloc(&a->whlist, rdhash, GFP_NOFS);
17866+ if (unlikely(err))
17867+ goto out;
1308ab2a 17868+
4a4d8108
AM
17869+ au_set_dbstart(d, a->dst_bstart);
17870+ err = may_rename_dstdir(d, &a->whlist);
17871+ au_set_dbstart(d, a->btgt);
17872+ }
17873+ a->dst_h_dentry = au_h_dptr(d, au_dbstart(d));
17874+ if (unlikely(err))
17875+ goto out;
17876+
17877+ d = a->src_dentry;
17878+ a->src_h_dentry = au_h_dptr(d, au_dbstart(d));
17879+ if (au_ftest_ren(a->flags, ISDIR)) {
17880+ err = may_rename_srcdir(d, a->btgt);
17881+ if (unlikely(err)) {
17882+ au_nhash_wh_free(&a->whlist);
17883+ a->whlist.nh_num = 0;
17884+ }
17885+ }
4f0767ce 17886+out:
4a4d8108 17887+ return err;
1facf9fc 17888+}
17889+
4a4d8108 17890+/* ---------------------------------------------------------------------- */
1facf9fc 17891+
4a4d8108
AM
17892+/*
17893+ * simple tests for rename.
17894+ * following the checks in vfs, plus the parent-child relationship.
17895+ */
17896+static int au_may_ren(struct au_ren_args *a)
17897+{
17898+ int err, isdir;
17899+ struct inode *h_inode;
1facf9fc 17900+
4a4d8108
AM
17901+ if (a->src_bstart == a->btgt) {
17902+ err = au_may_del(a->src_dentry, a->btgt, a->src_h_parent,
17903+ au_ftest_ren(a->flags, ISDIR));
17904+ if (unlikely(err))
17905+ goto out;
17906+ err = -EINVAL;
17907+ if (unlikely(a->src_h_dentry == a->h_trap))
17908+ goto out;
17909+ }
1facf9fc 17910+
4a4d8108
AM
17911+ err = 0;
17912+ if (a->dst_bstart != a->btgt)
17913+ goto out;
1facf9fc 17914+
027c5e7a
AM
17915+ err = -ENOTEMPTY;
17916+ if (unlikely(a->dst_h_dentry == a->h_trap))
17917+ goto out;
17918+
4a4d8108
AM
17919+ err = -EIO;
17920+ h_inode = a->dst_h_dentry->d_inode;
17921+ isdir = !!au_ftest_ren(a->flags, ISDIR);
17922+ if (!a->dst_dentry->d_inode) {
17923+ if (unlikely(h_inode))
17924+ goto out;
17925+ err = au_may_add(a->dst_dentry, a->btgt, a->dst_h_parent,
17926+ isdir);
17927+ } else {
17928+ if (unlikely(!h_inode || !h_inode->i_nlink))
17929+ goto out;
17930+ err = au_may_del(a->dst_dentry, a->btgt, a->dst_h_parent,
17931+ isdir);
17932+ if (unlikely(err))
17933+ goto out;
4a4d8108 17934+ }
1facf9fc 17935+
4f0767ce 17936+out:
4a4d8108
AM
17937+ if (unlikely(err == -ENOENT || err == -EEXIST))
17938+ err = -EIO;
17939+ AuTraceErr(err);
17940+ return err;
17941+}
1facf9fc 17942+
1308ab2a 17943+/* ---------------------------------------------------------------------- */
1facf9fc 17944+
4a4d8108
AM
17945+/*
17946+ * locking order
17947+ * (VFS)
17948+ * - src_dir and dir by lock_rename()
17949+ * - inode if exitsts
17950+ * (aufs)
17951+ * - lock all
17952+ * + src_dentry and dentry by aufs_read_and_write_lock2() which calls,
17953+ * + si_read_lock
17954+ * + di_write_lock2_child()
17955+ * + di_write_lock_child()
17956+ * + ii_write_lock_child()
17957+ * + di_write_lock_child2()
17958+ * + ii_write_lock_child2()
17959+ * + src_parent and parent
17960+ * + di_write_lock_parent()
17961+ * + ii_write_lock_parent()
17962+ * + di_write_lock_parent2()
17963+ * + ii_write_lock_parent2()
17964+ * + lower src_dir and dir by vfsub_lock_rename()
17965+ * + verify the every relationships between child and parent. if any
17966+ * of them failed, unlock all and return -EBUSY.
17967+ */
17968+static void au_ren_unlock(struct au_ren_args *a)
1308ab2a 17969+{
4a4d8108
AM
17970+ struct super_block *sb;
17971+
17972+ sb = a->dst_dentry->d_sb;
17973+ if (au_ftest_ren(a->flags, MNT_WRITE))
17974+ mnt_drop_write(a->br->br_mnt);
17975+ vfsub_unlock_rename(a->src_h_parent, a->src_hdir,
17976+ a->dst_h_parent, a->dst_hdir);
1308ab2a 17977+}
17978+
4a4d8108 17979+static int au_ren_lock(struct au_ren_args *a)
1308ab2a 17980+{
4a4d8108
AM
17981+ int err;
17982+ unsigned int udba;
1308ab2a 17983+
4a4d8108
AM
17984+ err = 0;
17985+ a->src_h_parent = au_h_dptr(a->src_parent, a->btgt);
17986+ a->src_hdir = au_hi(a->src_dir, a->btgt);
17987+ a->dst_h_parent = au_h_dptr(a->dst_parent, a->btgt);
17988+ a->dst_hdir = au_hi(a->dst_dir, a->btgt);
17989+ a->h_trap = vfsub_lock_rename(a->src_h_parent, a->src_hdir,
17990+ a->dst_h_parent, a->dst_hdir);
17991+ udba = au_opt_udba(a->src_dentry->d_sb);
17992+ if (unlikely(a->src_hdir->hi_inode != a->src_h_parent->d_inode
17993+ || a->dst_hdir->hi_inode != a->dst_h_parent->d_inode))
17994+ err = au_busy_or_stale();
17995+ if (!err && au_dbstart(a->src_dentry) == a->btgt)
17996+ err = au_h_verify(a->src_h_dentry, udba,
17997+ a->src_h_parent->d_inode, a->src_h_parent,
17998+ a->br);
17999+ if (!err && au_dbstart(a->dst_dentry) == a->btgt)
18000+ err = au_h_verify(a->dst_h_dentry, udba,
18001+ a->dst_h_parent->d_inode, a->dst_h_parent,
18002+ a->br);
18003+ if (!err) {
18004+ err = mnt_want_write(a->br->br_mnt);
18005+ if (unlikely(err))
18006+ goto out_unlock;
18007+ au_fset_ren(a->flags, MNT_WRITE);
18008+ goto out; /* success */
18009+ }
18010+
18011+ err = au_busy_or_stale();
18012+
4f0767ce 18013+out_unlock:
4a4d8108 18014+ au_ren_unlock(a);
4f0767ce 18015+out:
4a4d8108 18016+ return err;
1facf9fc 18017+}
18018+
18019+/* ---------------------------------------------------------------------- */
18020+
4a4d8108 18021+static void au_ren_refresh_dir(struct au_ren_args *a)
1facf9fc 18022+{
4a4d8108 18023+ struct inode *dir;
dece6358 18024+
4a4d8108
AM
18025+ dir = a->dst_dir;
18026+ dir->i_version++;
18027+ if (au_ftest_ren(a->flags, ISDIR)) {
18028+ /* is this updating defined in POSIX? */
18029+ au_cpup_attr_timesizes(a->src_inode);
18030+ au_cpup_attr_nlink(dir, /*force*/1);
4a4d8108 18031+ }
027c5e7a 18032+
4a4d8108
AM
18033+ if (au_ibstart(dir) == a->btgt)
18034+ au_cpup_attr_timesizes(dir);
dece6358 18035+
4a4d8108
AM
18036+ if (au_ftest_ren(a->flags, ISSAMEDIR))
18037+ return;
dece6358 18038+
4a4d8108
AM
18039+ dir = a->src_dir;
18040+ dir->i_version++;
18041+ if (au_ftest_ren(a->flags, ISDIR))
18042+ au_cpup_attr_nlink(dir, /*force*/1);
18043+ if (au_ibstart(dir) == a->btgt)
18044+ au_cpup_attr_timesizes(dir);
1facf9fc 18045+}
18046+
4a4d8108 18047+static void au_ren_refresh(struct au_ren_args *a)
1facf9fc 18048+{
4a4d8108
AM
18049+ aufs_bindex_t bend, bindex;
18050+ struct dentry *d, *h_d;
18051+ struct inode *i, *h_i;
18052+ struct super_block *sb;
dece6358 18053+
027c5e7a
AM
18054+ d = a->dst_dentry;
18055+ d_drop(d);
18056+ if (a->h_dst)
18057+ /* already dget-ed by au_ren_or_cpup() */
18058+ au_set_h_dptr(d, a->btgt, a->h_dst);
18059+
18060+ i = a->dst_inode;
18061+ if (i) {
18062+ if (!au_ftest_ren(a->flags, ISDIR))
18063+ vfsub_drop_nlink(i);
18064+ else {
18065+ vfsub_dead_dir(i);
18066+ au_cpup_attr_timesizes(i);
18067+ }
18068+ au_update_dbrange(d, /*do_put_zero*/1);
18069+ } else {
18070+ bend = a->btgt;
18071+ for (bindex = au_dbstart(d); bindex < bend; bindex++)
18072+ au_set_h_dptr(d, bindex, NULL);
18073+ bend = au_dbend(d);
18074+ for (bindex = a->btgt + 1; bindex <= bend; bindex++)
18075+ au_set_h_dptr(d, bindex, NULL);
18076+ au_update_dbrange(d, /*do_put_zero*/0);
18077+ }
18078+
4a4d8108
AM
18079+ d = a->src_dentry;
18080+ au_set_dbwh(d, -1);
18081+ bend = au_dbend(d);
18082+ for (bindex = a->btgt + 1; bindex <= bend; bindex++) {
18083+ h_d = au_h_dptr(d, bindex);
18084+ if (h_d)
18085+ au_set_h_dptr(d, bindex, NULL);
18086+ }
18087+ au_set_dbend(d, a->btgt);
18088+
18089+ sb = d->d_sb;
18090+ i = a->src_inode;
18091+ if (au_opt_test(au_mntflags(sb), PLINK) && au_plink_test(i))
18092+ return; /* success */
18093+
18094+ bend = au_ibend(i);
18095+ for (bindex = a->btgt + 1; bindex <= bend; bindex++) {
18096+ h_i = au_h_iptr(i, bindex);
18097+ if (h_i) {
18098+ au_xino_write(sb, bindex, h_i->i_ino, /*ino*/0);
18099+ /* ignore this error */
18100+ au_set_h_iptr(i, bindex, NULL, 0);
18101+ }
18102+ }
18103+ au_set_ibend(i, a->btgt);
1308ab2a 18104+}
dece6358 18105+
4a4d8108
AM
18106+/* ---------------------------------------------------------------------- */
18107+
18108+/* mainly for link(2) and rename(2) */
18109+int au_wbr(struct dentry *dentry, aufs_bindex_t btgt)
1308ab2a 18110+{
4a4d8108
AM
18111+ aufs_bindex_t bdiropq, bwh;
18112+ struct dentry *parent;
18113+ struct au_branch *br;
18114+
18115+ parent = dentry->d_parent;
18116+ IMustLock(parent->d_inode); /* dir is locked */
18117+
18118+ bdiropq = au_dbdiropq(parent);
18119+ bwh = au_dbwh(dentry);
18120+ br = au_sbr(dentry->d_sb, btgt);
18121+ if (au_br_rdonly(br)
18122+ || (0 <= bdiropq && bdiropq < btgt)
18123+ || (0 <= bwh && bwh < btgt))
18124+ btgt = -1;
18125+
18126+ AuDbg("btgt %d\n", btgt);
18127+ return btgt;
1facf9fc 18128+}
18129+
4a4d8108
AM
18130+/* sets src_bstart, dst_bstart and btgt */
18131+static int au_ren_wbr(struct au_ren_args *a)
1facf9fc 18132+{
4a4d8108
AM
18133+ int err;
18134+ struct au_wr_dir_args wr_dir_args = {
18135+ /* .force_btgt = -1, */
18136+ .flags = AuWrDir_ADD_ENTRY
18137+ };
dece6358 18138+
4a4d8108
AM
18139+ a->src_bstart = au_dbstart(a->src_dentry);
18140+ a->dst_bstart = au_dbstart(a->dst_dentry);
18141+ if (au_ftest_ren(a->flags, ISDIR))
18142+ au_fset_wrdir(wr_dir_args.flags, ISDIR);
18143+ wr_dir_args.force_btgt = a->src_bstart;
18144+ if (a->dst_inode && a->dst_bstart < a->src_bstart)
18145+ wr_dir_args.force_btgt = a->dst_bstart;
18146+ wr_dir_args.force_btgt = au_wbr(a->dst_dentry, wr_dir_args.force_btgt);
18147+ err = au_wr_dir(a->dst_dentry, a->src_dentry, &wr_dir_args);
18148+ a->btgt = err;
dece6358 18149+
4a4d8108 18150+ return err;
1facf9fc 18151+}
18152+
4a4d8108 18153+static void au_ren_dt(struct au_ren_args *a)
1facf9fc 18154+{
4a4d8108
AM
18155+ a->h_path.dentry = a->src_h_parent;
18156+ au_dtime_store(a->src_dt + AuPARENT, a->src_parent, &a->h_path);
18157+ if (!au_ftest_ren(a->flags, ISSAMEDIR)) {
18158+ a->h_path.dentry = a->dst_h_parent;
18159+ au_dtime_store(a->dst_dt + AuPARENT, a->dst_parent, &a->h_path);
18160+ }
1facf9fc 18161+
4a4d8108
AM
18162+ au_fclr_ren(a->flags, DT_DSTDIR);
18163+ if (!au_ftest_ren(a->flags, ISDIR))
18164+ return;
dece6358 18165+
4a4d8108
AM
18166+ a->h_path.dentry = a->src_h_dentry;
18167+ au_dtime_store(a->src_dt + AuCHILD, a->src_dentry, &a->h_path);
18168+ if (a->dst_h_dentry->d_inode) {
18169+ au_fset_ren(a->flags, DT_DSTDIR);
18170+ a->h_path.dentry = a->dst_h_dentry;
18171+ au_dtime_store(a->dst_dt + AuCHILD, a->dst_dentry, &a->h_path);
18172+ }
1308ab2a 18173+}
dece6358 18174+
4a4d8108 18175+static void au_ren_rev_dt(int err, struct au_ren_args *a)
1308ab2a 18176+{
4a4d8108
AM
18177+ struct dentry *h_d;
18178+ struct mutex *h_mtx;
18179+
18180+ au_dtime_revert(a->src_dt + AuPARENT);
18181+ if (!au_ftest_ren(a->flags, ISSAMEDIR))
18182+ au_dtime_revert(a->dst_dt + AuPARENT);
18183+
18184+ if (au_ftest_ren(a->flags, ISDIR) && err != -EIO) {
18185+ h_d = a->src_dt[AuCHILD].dt_h_path.dentry;
18186+ h_mtx = &h_d->d_inode->i_mutex;
18187+ mutex_lock_nested(h_mtx, AuLsc_I_CHILD);
18188+ au_dtime_revert(a->src_dt + AuCHILD);
18189+ mutex_unlock(h_mtx);
18190+
18191+ if (au_ftest_ren(a->flags, DT_DSTDIR)) {
18192+ h_d = a->dst_dt[AuCHILD].dt_h_path.dentry;
18193+ h_mtx = &h_d->d_inode->i_mutex;
18194+ mutex_lock_nested(h_mtx, AuLsc_I_CHILD);
18195+ au_dtime_revert(a->dst_dt + AuCHILD);
18196+ mutex_unlock(h_mtx);
1facf9fc 18197+ }
18198+ }
18199+}
18200+
4a4d8108
AM
18201+/* ---------------------------------------------------------------------- */
18202+
18203+int aufs_rename(struct inode *_src_dir, struct dentry *_src_dentry,
18204+ struct inode *_dst_dir, struct dentry *_dst_dentry)
1facf9fc 18205+{
e49829fe 18206+ int err, flags;
4a4d8108
AM
18207+ /* reduce stack space */
18208+ struct au_ren_args *a;
18209+
18210+ AuDbg("%.*s, %.*s\n", AuDLNPair(_src_dentry), AuDLNPair(_dst_dentry));
18211+ IMustLock(_src_dir);
18212+ IMustLock(_dst_dir);
18213+
18214+ err = -ENOMEM;
18215+ BUILD_BUG_ON(sizeof(*a) > PAGE_SIZE);
18216+ a = kzalloc(sizeof(*a), GFP_NOFS);
18217+ if (unlikely(!a))
18218+ goto out;
18219+
18220+ a->src_dir = _src_dir;
18221+ a->src_dentry = _src_dentry;
18222+ a->src_inode = a->src_dentry->d_inode;
18223+ a->src_parent = a->src_dentry->d_parent; /* dir inode is locked */
18224+ a->dst_dir = _dst_dir;
18225+ a->dst_dentry = _dst_dentry;
18226+ a->dst_inode = a->dst_dentry->d_inode;
18227+ a->dst_parent = a->dst_dentry->d_parent; /* dir inode is locked */
18228+ if (a->dst_inode) {
18229+ IMustLock(a->dst_inode);
18230+ au_igrab(a->dst_inode);
1facf9fc 18231+ }
1facf9fc 18232+
4a4d8108 18233+ err = -ENOTDIR;
027c5e7a 18234+ flags = AuLock_FLUSH | AuLock_NOPLM | AuLock_GEN;
4a4d8108
AM
18235+ if (S_ISDIR(a->src_inode->i_mode)) {
18236+ au_fset_ren(a->flags, ISDIR);
18237+ if (unlikely(a->dst_inode && !S_ISDIR(a->dst_inode->i_mode)))
18238+ goto out_free;
e49829fe
JR
18239+ err = aufs_read_and_write_lock2(a->dst_dentry, a->src_dentry,
18240+ AuLock_DIR | flags);
4a4d8108 18241+ } else
e49829fe
JR
18242+ err = aufs_read_and_write_lock2(a->dst_dentry, a->src_dentry,
18243+ flags);
18244+ if (unlikely(err))
18245+ goto out_free;
1facf9fc 18246+
027c5e7a
AM
18247+ err = au_d_hashed_positive(a->src_dentry);
18248+ if (unlikely(err))
18249+ goto out_unlock;
18250+ err = -ENOENT;
18251+ if (a->dst_inode) {
18252+ /*
18253+ * If it is a dir, VFS unhash dst_dentry before this
18254+ * function. It means we cannot rely upon d_unhashed().
18255+ */
18256+ if (unlikely(!a->dst_inode->i_nlink))
18257+ goto out_unlock;
18258+ if (!S_ISDIR(a->dst_inode->i_mode)) {
18259+ err = au_d_hashed_positive(a->dst_dentry);
18260+ if (unlikely(err))
18261+ goto out_unlock;
18262+ } else if (unlikely(IS_DEADDIR(a->dst_inode)))
18263+ goto out_unlock;
18264+ } else if (unlikely(d_unhashed(a->dst_dentry)))
18265+ goto out_unlock;
18266+
7eafdf33
AM
18267+ /*
18268+ * is it possible?
18269+ * yes, it happend (in linux-3.3-rcN) but I don't know why.
18270+ * there may exist a problem somewhere else.
18271+ */
18272+ err = -EINVAL;
18273+ if (unlikely(a->dst_parent->d_inode == a->src_dentry->d_inode))
18274+ goto out_unlock;
18275+
4a4d8108
AM
18276+ au_fset_ren(a->flags, ISSAMEDIR); /* temporary */
18277+ di_write_lock_parent(a->dst_parent);
1facf9fc 18278+
4a4d8108
AM
18279+ /* which branch we process */
18280+ err = au_ren_wbr(a);
18281+ if (unlikely(err < 0))
027c5e7a 18282+ goto out_parent;
4a4d8108
AM
18283+ a->br = au_sbr(a->dst_dentry->d_sb, a->btgt);
18284+ a->h_path.mnt = a->br->br_mnt;
1facf9fc 18285+
4a4d8108
AM
18286+ /* are they available to be renamed */
18287+ err = au_ren_may_dir(a);
18288+ if (unlikely(err))
18289+ goto out_children;
1facf9fc 18290+
4a4d8108
AM
18291+ /* prepare the writable parent dir on the same branch */
18292+ if (a->dst_bstart == a->btgt) {
18293+ au_fset_ren(a->flags, WHDST);
18294+ } else {
18295+ err = au_cpup_dirs(a->dst_dentry, a->btgt);
18296+ if (unlikely(err))
18297+ goto out_children;
18298+ }
1facf9fc 18299+
4a4d8108
AM
18300+ if (a->src_dir != a->dst_dir) {
18301+ /*
18302+ * this temporary unlock is safe,
18303+ * because both dir->i_mutex are locked.
18304+ */
18305+ di_write_unlock(a->dst_parent);
18306+ di_write_lock_parent(a->src_parent);
18307+ err = au_wr_dir_need_wh(a->src_dentry,
18308+ au_ftest_ren(a->flags, ISDIR),
18309+ &a->btgt);
18310+ di_write_unlock(a->src_parent);
18311+ di_write_lock2_parent(a->src_parent, a->dst_parent, /*isdir*/1);
18312+ au_fclr_ren(a->flags, ISSAMEDIR);
18313+ } else
18314+ err = au_wr_dir_need_wh(a->src_dentry,
18315+ au_ftest_ren(a->flags, ISDIR),
18316+ &a->btgt);
18317+ if (unlikely(err < 0))
18318+ goto out_children;
18319+ if (err)
18320+ au_fset_ren(a->flags, WHSRC);
1facf9fc 18321+
4a4d8108
AM
18322+ /* lock them all */
18323+ err = au_ren_lock(a);
18324+ if (unlikely(err))
18325+ goto out_children;
1facf9fc 18326+
4a4d8108
AM
18327+ if (!au_opt_test(au_mntflags(a->dst_dir->i_sb), UDBA_NONE))
18328+ err = au_may_ren(a);
18329+ else if (unlikely(a->dst_dentry->d_name.len > AUFS_MAX_NAMELEN))
18330+ err = -ENAMETOOLONG;
18331+ if (unlikely(err))
18332+ goto out_hdir;
1facf9fc 18333+
4a4d8108
AM
18334+ /* store timestamps to be revertible */
18335+ au_ren_dt(a);
1facf9fc 18336+
4a4d8108
AM
18337+ /* here we go */
18338+ err = do_rename(a);
18339+ if (unlikely(err))
18340+ goto out_dt;
18341+
18342+ /* update dir attributes */
18343+ au_ren_refresh_dir(a);
18344+
18345+ /* dput/iput all lower dentries */
18346+ au_ren_refresh(a);
18347+
18348+ goto out_hdir; /* success */
18349+
4f0767ce 18350+out_dt:
4a4d8108 18351+ au_ren_rev_dt(err, a);
4f0767ce 18352+out_hdir:
4a4d8108 18353+ au_ren_unlock(a);
4f0767ce 18354+out_children:
4a4d8108 18355+ au_nhash_wh_free(&a->whlist);
027c5e7a
AM
18356+ if (err && a->dst_inode && a->dst_bstart != a->btgt) {
18357+ AuDbg("bstart %d, btgt %d\n", a->dst_bstart, a->btgt);
18358+ au_set_h_dptr(a->dst_dentry, a->btgt, NULL);
18359+ au_set_dbstart(a->dst_dentry, a->dst_bstart);
4a4d8108 18360+ }
027c5e7a 18361+out_parent:
4a4d8108
AM
18362+ if (!err)
18363+ d_move(a->src_dentry, a->dst_dentry);
027c5e7a
AM
18364+ else {
18365+ au_update_dbstart(a->dst_dentry);
18366+ if (!a->dst_inode)
18367+ d_drop(a->dst_dentry);
18368+ }
4a4d8108
AM
18369+ if (au_ftest_ren(a->flags, ISSAMEDIR))
18370+ di_write_unlock(a->dst_parent);
18371+ else
18372+ di_write_unlock2(a->src_parent, a->dst_parent);
027c5e7a 18373+out_unlock:
4a4d8108 18374+ aufs_read_and_write_unlock2(a->dst_dentry, a->src_dentry);
4f0767ce 18375+out_free:
4a4d8108
AM
18376+ iput(a->dst_inode);
18377+ if (a->thargs)
18378+ au_whtmp_rmdir_free(a->thargs);
18379+ kfree(a);
4f0767ce 18380+out:
4a4d8108
AM
18381+ AuTraceErr(err);
18382+ return err;
1308ab2a 18383+}
7f207e10
AM
18384diff -urN /usr/share/empty/fs/aufs/Kconfig linux/fs/aufs/Kconfig
18385--- /usr/share/empty/fs/aufs/Kconfig 1970-01-01 01:00:00.000000000 +0100
0c3ec466 18386+++ linux/fs/aufs/Kconfig 2012-07-22 19:57:03.161004531 +0200
2cbb1c4b 18387@@ -0,0 +1,203 @@
4a4d8108
AM
18388+config AUFS_FS
18389+ tristate "Aufs (Advanced multi layered unification filesystem) support"
18390+ depends on EXPERIMENTAL
18391+ help
18392+ Aufs is a stackable unification filesystem such as Unionfs,
18393+ which unifies several directories and provides a merged single
18394+ directory.
18395+ In the early days, aufs was entirely re-designed and
18396+ re-implemented Unionfs Version 1.x series. Introducing many
18397+ original ideas, approaches and improvements, it becomes totally
18398+ different from Unionfs while keeping the basic features.
1facf9fc 18399+
4a4d8108
AM
18400+if AUFS_FS
18401+choice
18402+ prompt "Maximum number of branches"
18403+ default AUFS_BRANCH_MAX_127
18404+ help
18405+ Specifies the maximum number of branches (or member directories)
18406+ in a single aufs. The larger value consumes more system
18407+ resources and has a minor impact to performance.
18408+config AUFS_BRANCH_MAX_127
18409+ bool "127"
18410+ help
18411+ Specifies the maximum number of branches (or member directories)
18412+ in a single aufs. The larger value consumes more system
18413+ resources and has a minor impact to performance.
18414+config AUFS_BRANCH_MAX_511
18415+ bool "511"
18416+ help
18417+ Specifies the maximum number of branches (or member directories)
18418+ in a single aufs. The larger value consumes more system
18419+ resources and has a minor impact to performance.
18420+config AUFS_BRANCH_MAX_1023
18421+ bool "1023"
18422+ help
18423+ Specifies the maximum number of branches (or member directories)
18424+ in a single aufs. The larger value consumes more system
18425+ resources and has a minor impact to performance.
18426+config AUFS_BRANCH_MAX_32767
18427+ bool "32767"
18428+ help
18429+ Specifies the maximum number of branches (or member directories)
18430+ in a single aufs. The larger value consumes more system
18431+ resources and has a minor impact to performance.
18432+endchoice
1facf9fc 18433+
e49829fe
JR
18434+config AUFS_SBILIST
18435+ bool
18436+ depends on AUFS_MAGIC_SYSRQ || PROC_FS
18437+ default y
18438+ help
18439+ Automatic configuration for internal use.
18440+ When aufs supports Magic SysRq or /proc, enabled automatically.
18441+
4a4d8108
AM
18442+config AUFS_HNOTIFY
18443+ bool "Detect direct branch access (bypassing aufs)"
18444+ help
18445+ If you want to modify files on branches directly, eg. bypassing aufs,
18446+ and want aufs to detect the changes of them fully, then enable this
18447+ option and use 'udba=notify' mount option.
7f207e10 18448+ Currently there is only one available configuration, "fsnotify".
4a4d8108
AM
18449+ It will have a negative impact to the performance.
18450+ See detail in aufs.5.
dece6358 18451+
4a4d8108
AM
18452+choice
18453+ prompt "method" if AUFS_HNOTIFY
18454+ default AUFS_HFSNOTIFY
18455+config AUFS_HFSNOTIFY
18456+ bool "fsnotify"
18457+ select FSNOTIFY
4a4d8108 18458+endchoice
1facf9fc 18459+
4a4d8108
AM
18460+config AUFS_EXPORT
18461+ bool "NFS-exportable aufs"
2cbb1c4b 18462+ depends on EXPORTFS
4a4d8108
AM
18463+ help
18464+ If you want to export your mounted aufs via NFS, then enable this
18465+ option. There are several requirements for this configuration.
18466+ See detail in aufs.5.
1facf9fc 18467+
4a4d8108
AM
18468+config AUFS_INO_T_64
18469+ bool
18470+ depends on AUFS_EXPORT
18471+ depends on 64BIT && !(ALPHA || S390)
18472+ default y
18473+ help
18474+ Automatic configuration for internal use.
18475+ /* typedef unsigned long/int __kernel_ino_t */
18476+ /* alpha and s390x are int */
1facf9fc 18477+
4a4d8108
AM
18478+config AUFS_RDU
18479+ bool "Readdir in userspace"
18480+ help
18481+ Aufs has two methods to provide a merged view for a directory,
18482+ by a user-space library and by kernel-space natively. The latter
18483+ is always enabled but sometimes large and slow.
18484+ If you enable this option, install the library in aufs2-util
18485+ package, and set some environment variables for your readdir(3),
18486+ then the work will be handled in user-space which generally
18487+ shows better performance in most cases.
18488+ See detail in aufs.5.
1facf9fc 18489+
2cbb1c4b
JR
18490+config AUFS_PROC_MAP
18491+ bool "support for /proc/maps and lsof(1)"
18492+ depends on PROC_FS
18493+ help
18494+ When you issue mmap(2) in aufs, it is actually a direct mmap(2)
18495+ call to the file on the branch fs since the file in aufs is
18496+ purely virtual. And the file path printed in /proc/maps (and
18497+ others) will be the path on the branch fs. In most cases, it
18498+ does no harm. But some utilities like lsof(1) may confuse since
18499+ the utility or user may expect the file path in aufs to be
18500+ printed.
18501+ To address this issue, aufs provides a patch which introduces a
18502+ new member called vm_prfile into struct vm_are_struct. The patch
18503+ is meaningless without enabling this configuration since nobody
18504+ sets the new vm_prfile member.
18505+ If you don't apply the patch, then enabling this configuration
18506+ will cause a compile error.
18507+ This approach is fragile since if someone else make some changes
18508+ around vm_file, then vm_prfile may not work anymore. As a
18509+ workaround such case, aufs provides this configuration. If you
18510+ disable it, then lsof(1) may produce incorrect result but the
18511+ problem will be gone even if the aufs patch is applied (I hope).
18512+
4a4d8108
AM
18513+config AUFS_SP_IATTR
18514+ bool "Respect the attributes (mtime/ctime mainly) of special files"
18515+ help
18516+ When you write something to a special file, some attributes of it
18517+ (mtime/ctime mainly) may be updated. Generally such updates are
18518+ less important (actually some device drivers and NFS ignore
18519+ it). But some applications (such like test program) requires
18520+ such updates. If you need these updates, then enable this
18521+ configuration which introduces some overhead.
18522+ Currently this configuration handles FIFO only.
1facf9fc 18523+
4a4d8108
AM
18524+config AUFS_SHWH
18525+ bool "Show whiteouts"
18526+ help
18527+ If you want to make the whiteouts in aufs visible, then enable
18528+ this option and specify 'shwh' mount option. Although it may
18529+ sounds like philosophy or something, but in technically it
18530+ simply shows the name of whiteout with keeping its behaviour.
1facf9fc 18531+
4a4d8108
AM
18532+config AUFS_BR_RAMFS
18533+ bool "Ramfs (initramfs/rootfs) as an aufs branch"
18534+ help
18535+ If you want to use ramfs as an aufs branch fs, then enable this
18536+ option. Generally tmpfs is recommended.
18537+ Aufs prohibited them to be a branch fs by default, because
18538+ initramfs becomes unusable after switch_root or something
18539+ generally. If you sets initramfs as an aufs branch and boot your
18540+ system by switch_root, you will meet a problem easily since the
18541+ files in initramfs may be inaccessible.
18542+ Unless you are going to use ramfs as an aufs branch fs without
18543+ switch_root or something, leave it N.
1facf9fc 18544+
4a4d8108
AM
18545+config AUFS_BR_FUSE
18546+ bool "Fuse fs as an aufs branch"
18547+ depends on FUSE_FS
18548+ select AUFS_POLL
18549+ help
18550+ If you want to use fuse-based userspace filesystem as an aufs
18551+ branch fs, then enable this option.
18552+ It implements the internal poll(2) operation which is
18553+ implemented by fuse only (curretnly).
1facf9fc 18554+
4a4d8108
AM
18555+config AUFS_POLL
18556+ bool
18557+ help
18558+ Automatic configuration for internal use.
1facf9fc 18559+
4a4d8108
AM
18560+config AUFS_BR_HFSPLUS
18561+ bool "Hfsplus as an aufs branch"
18562+ depends on HFSPLUS_FS
18563+ default y
18564+ help
18565+ If you want to use hfsplus fs as an aufs branch fs, then enable
18566+ this option. This option introduces a small overhead at
18567+ copying-up a file on hfsplus.
1facf9fc 18568+
4a4d8108
AM
18569+config AUFS_BDEV_LOOP
18570+ bool
18571+ depends on BLK_DEV_LOOP
18572+ default y
18573+ help
18574+ Automatic configuration for internal use.
18575+ Convert =[ym] into =y.
1308ab2a 18576+
4a4d8108
AM
18577+config AUFS_DEBUG
18578+ bool "Debug aufs"
18579+ help
18580+ Enable this to compile aufs internal debug code.
18581+ It will have a negative impact to the performance.
18582+
18583+config AUFS_MAGIC_SYSRQ
18584+ bool
18585+ depends on AUFS_DEBUG && MAGIC_SYSRQ
18586+ default y
18587+ help
18588+ Automatic configuration for internal use.
18589+ When aufs supports Magic SysRq, enabled automatically.
18590+endif
7f207e10
AM
18591diff -urN /usr/share/empty/fs/aufs/loop.c linux/fs/aufs/loop.c
18592--- /usr/share/empty/fs/aufs/loop.c 1970-01-01 01:00:00.000000000 +0100
0c3ec466 18593+++ linux/fs/aufs/loop.c 2012-07-22 19:57:03.164337936 +0200
87a755f4 18594@@ -0,0 +1,133 @@
1facf9fc 18595+/*
f6c5ef8b 18596+ * Copyright (C) 2005-2012 Junjiro R. Okajima
1facf9fc 18597+ *
18598+ * This program, aufs is free software; you can redistribute it and/or modify
18599+ * it under the terms of the GNU General Public License as published by
18600+ * the Free Software Foundation; either version 2 of the License, or
18601+ * (at your option) any later version.
dece6358
AM
18602+ *
18603+ * This program is distributed in the hope that it will be useful,
18604+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
18605+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18606+ * GNU General Public License for more details.
18607+ *
18608+ * You should have received a copy of the GNU General Public License
18609+ * along with this program; if not, write to the Free Software
18610+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 18611+ */
18612+
18613+/*
18614+ * support for loopback block device as a branch
18615+ */
18616+
18617+#include <linux/loop.h>
18618+#include "aufs.h"
18619+
18620+/*
18621+ * test if two lower dentries have overlapping branches.
18622+ */
b752ccd1 18623+int au_test_loopback_overlap(struct super_block *sb, struct dentry *h_adding)
1facf9fc 18624+{
b752ccd1 18625+ struct super_block *h_sb;
1facf9fc 18626+ struct loop_device *l;
18627+
b752ccd1
AM
18628+ h_sb = h_adding->d_sb;
18629+ if (MAJOR(h_sb->s_dev) != LOOP_MAJOR)
1facf9fc 18630+ return 0;
18631+
b752ccd1
AM
18632+ l = h_sb->s_bdev->bd_disk->private_data;
18633+ h_adding = l->lo_backing_file->f_dentry;
18634+ /*
18635+ * h_adding can be local NFS.
18636+ * in this case aufs cannot detect the loop.
18637+ */
18638+ if (unlikely(h_adding->d_sb == sb))
1facf9fc 18639+ return 1;
b752ccd1 18640+ return !!au_test_subdir(h_adding, sb->s_root);
1facf9fc 18641+}
18642+
18643+/* true if a kernel thread named 'loop[0-9].*' accesses a file */
18644+int au_test_loopback_kthread(void)
18645+{
b752ccd1
AM
18646+ int ret;
18647+ struct task_struct *tsk = current;
18648+
18649+ ret = 0;
18650+ if (tsk->flags & PF_KTHREAD) {
18651+ const char c = tsk->comm[4];
18652+ ret = ('0' <= c && c <= '9'
18653+ && !strncmp(tsk->comm, "loop", 4));
18654+ }
1facf9fc 18655+
b752ccd1 18656+ return ret;
1facf9fc 18657+}
87a755f4
AM
18658+
18659+/* ---------------------------------------------------------------------- */
18660+
18661+#define au_warn_loopback_step 16
18662+static int au_warn_loopback_nelem = au_warn_loopback_step;
18663+static unsigned long *au_warn_loopback_array;
18664+
18665+void au_warn_loopback(struct super_block *h_sb)
18666+{
18667+ int i, new_nelem;
18668+ unsigned long *a, magic;
18669+ static DEFINE_SPINLOCK(spin);
18670+
18671+ magic = h_sb->s_magic;
18672+ spin_lock(&spin);
18673+ a = au_warn_loopback_array;
18674+ for (i = 0; i < au_warn_loopback_nelem && *a; i++)
18675+ if (a[i] == magic) {
18676+ spin_unlock(&spin);
18677+ return;
18678+ }
18679+
18680+ /* h_sb is new to us, print it */
18681+ if (i < au_warn_loopback_nelem) {
18682+ a[i] = magic;
18683+ goto pr;
18684+ }
18685+
18686+ /* expand the array */
18687+ new_nelem = au_warn_loopback_nelem + au_warn_loopback_step;
18688+ a = au_kzrealloc(au_warn_loopback_array,
18689+ au_warn_loopback_nelem * sizeof(unsigned long),
18690+ new_nelem * sizeof(unsigned long), GFP_ATOMIC);
18691+ if (a) {
18692+ au_warn_loopback_nelem = new_nelem;
18693+ au_warn_loopback_array = a;
18694+ a[i] = magic;
18695+ goto pr;
18696+ }
18697+
18698+ spin_unlock(&spin);
18699+ AuWarn1("realloc failed, ignored\n");
18700+ return;
18701+
18702+pr:
18703+ spin_unlock(&spin);
0c3ec466
AM
18704+ pr_warn("you may want to try another patch for loopback file "
18705+ "on %s(0x%lx) branch\n", au_sbtype(h_sb), magic);
87a755f4
AM
18706+}
18707+
18708+int au_loopback_init(void)
18709+{
18710+ int err;
18711+ struct super_block *sb __maybe_unused;
18712+
18713+ AuDebugOn(sizeof(sb->s_magic) != sizeof(unsigned long));
18714+
18715+ err = 0;
18716+ au_warn_loopback_array = kcalloc(au_warn_loopback_step,
18717+ sizeof(unsigned long), GFP_NOFS);
18718+ if (unlikely(!au_warn_loopback_array))
18719+ err = -ENOMEM;
18720+
18721+ return err;
18722+}
18723+
18724+void au_loopback_fin(void)
18725+{
18726+ kfree(au_warn_loopback_array);
18727+}
7f207e10
AM
18728diff -urN /usr/share/empty/fs/aufs/loop.h linux/fs/aufs/loop.h
18729--- /usr/share/empty/fs/aufs/loop.h 1970-01-01 01:00:00.000000000 +0100
0c3ec466 18730+++ linux/fs/aufs/loop.h 2012-07-22 19:57:03.164337936 +0200
87a755f4 18731@@ -0,0 +1,50 @@
1facf9fc 18732+/*
f6c5ef8b 18733+ * Copyright (C) 2005-2012 Junjiro R. Okajima
1facf9fc 18734+ *
18735+ * This program, aufs is free software; you can redistribute it and/or modify
18736+ * it under the terms of the GNU General Public License as published by
18737+ * the Free Software Foundation; either version 2 of the License, or
18738+ * (at your option) any later version.
dece6358
AM
18739+ *
18740+ * This program is distributed in the hope that it will be useful,
18741+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
18742+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18743+ * GNU General Public License for more details.
18744+ *
18745+ * You should have received a copy of the GNU General Public License
18746+ * along with this program; if not, write to the Free Software
18747+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 18748+ */
18749+
18750+/*
18751+ * support for loopback mount as a branch
18752+ */
18753+
18754+#ifndef __AUFS_LOOP_H__
18755+#define __AUFS_LOOP_H__
18756+
18757+#ifdef __KERNEL__
18758+
dece6358
AM
18759+struct dentry;
18760+struct super_block;
1facf9fc 18761+
18762+#ifdef CONFIG_AUFS_BDEV_LOOP
18763+/* loop.c */
b752ccd1 18764+int au_test_loopback_overlap(struct super_block *sb, struct dentry *h_adding);
1facf9fc 18765+int au_test_loopback_kthread(void);
87a755f4
AM
18766+void au_warn_loopback(struct super_block *h_sb);
18767+
18768+int au_loopback_init(void);
18769+void au_loopback_fin(void);
1facf9fc 18770+#else
4a4d8108 18771+AuStubInt0(au_test_loopback_overlap, struct super_block *sb,
b752ccd1 18772+ struct dentry *h_adding)
4a4d8108 18773+AuStubInt0(au_test_loopback_kthread, void)
87a755f4
AM
18774+AuStubVoid(au_warn_loopback, struct super_block *h_sb)
18775+
18776+AuStubInt0(au_loopback_init, void)
18777+AuStubVoid(au_loopback_fin, void)
1facf9fc 18778+#endif /* BLK_DEV_LOOP */
18779+
18780+#endif /* __KERNEL__ */
18781+#endif /* __AUFS_LOOP_H__ */
7f207e10
AM
18782diff -urN /usr/share/empty/fs/aufs/magic.mk linux/fs/aufs/magic.mk
18783--- /usr/share/empty/fs/aufs/magic.mk 1970-01-01 01:00:00.000000000 +0100
0c3ec466 18784+++ linux/fs/aufs/magic.mk 2012-07-22 19:57:03.164337936 +0200
4a4d8108 18785@@ -0,0 +1,54 @@
1facf9fc 18786+
18787+# defined in ${srctree}/fs/fuse/inode.c
18788+# tristate
18789+ifdef CONFIG_FUSE_FS
18790+ccflags-y += -DFUSE_SUPER_MAGIC=0x65735546
18791+endif
18792+
18793+# defined in ${srctree}/fs/ocfs2/ocfs2_fs.h
18794+# tristate
18795+ifdef CONFIG_OCFS2_FS
18796+ccflags-y += -DOCFS2_SUPER_MAGIC=0x7461636f
18797+endif
18798+
18799+# defined in ${srctree}/fs/ocfs2/dlm/userdlm.h
18800+# tristate
18801+ifdef CONFIG_OCFS2_FS_O2CB
18802+ccflags-y += -DDLMFS_MAGIC=0x76a9f425
18803+endif
18804+
1facf9fc 18805+# defined in ${srctree}/fs/cifs/cifsfs.c
18806+# tristate
18807+ifdef CONFIG_CIFS_FS
18808+ccflags-y += -DCIFS_MAGIC_NUMBER=0xFF534D42
18809+endif
18810+
18811+# defined in ${srctree}/fs/xfs/xfs_sb.h
18812+# tristate
18813+ifdef CONFIG_XFS_FS
18814+ccflags-y += -DXFS_SB_MAGIC=0x58465342
18815+endif
18816+
18817+# defined in ${srctree}/fs/configfs/mount.c
18818+# tristate
18819+ifdef CONFIG_CONFIGFS_FS
18820+ccflags-y += -DCONFIGFS_MAGIC=0x62656570
18821+endif
18822+
18823+# defined in ${srctree}/fs/9p/v9fs.h
18824+# tristate
18825+ifdef CONFIG_9P_FS
18826+ccflags-y += -DV9FS_MAGIC=0x01021997
18827+endif
18828+
18829+# defined in ${srctree}/fs/ubifs/ubifs.h
18830+# tristate
18831+ifdef CONFIG_UBIFS_FS
18832+ccflags-y += -DUBIFS_SUPER_MAGIC=0x24051905
18833+endif
4a4d8108
AM
18834+
18835+# defined in ${srctree}/fs/hfsplus/hfsplus_raw.h
18836+# tristate
18837+ifdef CONFIG_HFSPLUS_FS
18838+ccflags-y += -DHFSPLUS_SUPER_MAGIC=0x482b
18839+endif
7f207e10
AM
18840diff -urN /usr/share/empty/fs/aufs/Makefile linux/fs/aufs/Makefile
18841--- /usr/share/empty/fs/aufs/Makefile 1970-01-01 01:00:00.000000000 +0100
0c3ec466
AM
18842+++ linux/fs/aufs/Makefile 2012-07-22 19:57:03.161004531 +0200
18843@@ -0,0 +1,45 @@
4a4d8108
AM
18844+
18845+include ${src}/magic.mk
18846+ifeq (${CONFIG_AUFS_FS},m)
18847+include ${src}/conf.mk
18848+endif
18849+-include ${src}/priv_def.mk
18850+
18851+# cf. include/linux/kernel.h
18852+# enable pr_debug
18853+ccflags-y += -DDEBUG
f6c5ef8b
AM
18854+# sparse requires the full pathname
18855+ifdef M
18856+ccflags-y += -include ${M}/../../include/linux/aufs_type.h
18857+else
18858+ccflags-y += -include ${srctree}/include/linux/aufs_type.h
18859+endif
4a4d8108
AM
18860+
18861+obj-$(CONFIG_AUFS_FS) += aufs.o
18862+aufs-y := module.o sbinfo.o super.o branch.o xino.o sysaufs.o opts.o \
18863+ wkq.o vfsub.o dcsub.o \
e49829fe 18864+ cpup.o whout.o wbr_policy.o \
4a4d8108
AM
18865+ dinfo.o dentry.o \
18866+ dynop.o \
18867+ finfo.o file.o f_op.o \
18868+ dir.o vdir.o \
18869+ iinfo.o inode.o i_op.o i_op_add.o i_op_del.o i_op_ren.o \
18870+ ioctl.o
18871+
18872+# all are boolean
e49829fe 18873+aufs-$(CONFIG_PROC_FS) += procfs.o plink.o
4a4d8108
AM
18874+aufs-$(CONFIG_SYSFS) += sysfs.o
18875+aufs-$(CONFIG_DEBUG_FS) += dbgaufs.o
18876+aufs-$(CONFIG_AUFS_BDEV_LOOP) += loop.o
18877+aufs-$(CONFIG_AUFS_HNOTIFY) += hnotify.o
18878+aufs-$(CONFIG_AUFS_HFSNOTIFY) += hfsnotify.o
4a4d8108
AM
18879+aufs-$(CONFIG_AUFS_EXPORT) += export.o
18880+aufs-$(CONFIG_AUFS_POLL) += poll.o
18881+aufs-$(CONFIG_AUFS_RDU) += rdu.o
18882+aufs-$(CONFIG_AUFS_SP_IATTR) += f_op_sp.o
0c3ec466
AM
18883+ifdef CONFIG_MMU
18884+aufs-$(CONFIG_SECURITY) += security.o
18885+endif
4a4d8108
AM
18886+aufs-$(CONFIG_AUFS_BR_HFSPLUS) += hfsplus.o
18887+aufs-$(CONFIG_AUFS_DEBUG) += debug.o
18888+aufs-$(CONFIG_AUFS_MAGIC_SYSRQ) += sysrq.o
7f207e10
AM
18889diff -urN /usr/share/empty/fs/aufs/module.c linux/fs/aufs/module.c
18890--- /usr/share/empty/fs/aufs/module.c 1970-01-01 01:00:00.000000000 +0100
0c3ec466 18891+++ linux/fs/aufs/module.c 2012-07-22 19:57:03.164337936 +0200
7eafdf33 18892@@ -0,0 +1,196 @@
1facf9fc 18893+/*
f6c5ef8b 18894+ * Copyright (C) 2005-2012 Junjiro R. Okajima
1facf9fc 18895+ *
18896+ * This program, aufs is free software; you can redistribute it and/or modify
18897+ * it under the terms of the GNU General Public License as published by
18898+ * the Free Software Foundation; either version 2 of the License, or
18899+ * (at your option) any later version.
dece6358
AM
18900+ *
18901+ * This program is distributed in the hope that it will be useful,
18902+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
18903+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18904+ * GNU General Public License for more details.
18905+ *
18906+ * You should have received a copy of the GNU General Public License
18907+ * along with this program; if not, write to the Free Software
18908+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 18909+ */
18910+
18911+/*
18912+ * module global variables and operations
18913+ */
18914+
18915+#include <linux/module.h>
18916+#include <linux/seq_file.h>
18917+#include "aufs.h"
18918+
18919+void *au_kzrealloc(void *p, unsigned int nused, unsigned int new_sz, gfp_t gfp)
18920+{
18921+ if (new_sz <= nused)
18922+ return p;
18923+
18924+ p = krealloc(p, new_sz, gfp);
18925+ if (p)
18926+ memset(p + nused, 0, new_sz - nused);
18927+ return p;
18928+}
18929+
18930+/* ---------------------------------------------------------------------- */
18931+
18932+/*
18933+ * aufs caches
18934+ */
18935+struct kmem_cache *au_cachep[AuCache_Last];
18936+static int __init au_cache_init(void)
18937+{
4a4d8108 18938+ au_cachep[AuCache_DINFO] = AuCacheCtor(au_dinfo, au_di_init_once);
1facf9fc 18939+ if (au_cachep[AuCache_DINFO])
027c5e7a 18940+ /* SLAB_DESTROY_BY_RCU */
4a4d8108
AM
18941+ au_cachep[AuCache_ICNTNR] = AuCacheCtor(au_icntnr,
18942+ au_icntnr_init_once);
1facf9fc 18943+ if (au_cachep[AuCache_ICNTNR])
4a4d8108
AM
18944+ au_cachep[AuCache_FINFO] = AuCacheCtor(au_finfo,
18945+ au_fi_init_once);
1facf9fc 18946+ if (au_cachep[AuCache_FINFO])
18947+ au_cachep[AuCache_VDIR] = AuCache(au_vdir);
18948+ if (au_cachep[AuCache_VDIR])
18949+ au_cachep[AuCache_DEHSTR] = AuCache(au_vdir_dehstr);
18950+ if (au_cachep[AuCache_DEHSTR])
18951+ return 0;
18952+
18953+ return -ENOMEM;
18954+}
18955+
18956+static void au_cache_fin(void)
18957+{
18958+ int i;
4a4d8108 18959+
7eafdf33
AM
18960+ /* excluding AuCache_HNOTIFY */
18961+ BUILD_BUG_ON(AuCache_HNOTIFY + 1 != AuCache_Last);
18962+ for (i = 0; i < AuCache_HNOTIFY; i++)
1facf9fc 18963+ if (au_cachep[i]) {
18964+ kmem_cache_destroy(au_cachep[i]);
18965+ au_cachep[i] = NULL;
18966+ }
18967+}
18968+
18969+/* ---------------------------------------------------------------------- */
18970+
18971+int au_dir_roflags;
18972+
e49829fe 18973+#ifdef CONFIG_AUFS_SBILIST
1e00d052
AM
18974+/*
18975+ * iterate_supers_type() doesn't protect us from
18976+ * remounting (branch management)
18977+ */
e49829fe
JR
18978+struct au_splhead au_sbilist;
18979+#endif
18980+
9dbd164d
AM
18981+struct lock_class_key au_lc_key[AuLcKey_Last];
18982+
1facf9fc 18983+/*
18984+ * functions for module interface.
18985+ */
18986+MODULE_LICENSE("GPL");
18987+/* MODULE_LICENSE("GPL v2"); */
dece6358 18988+MODULE_AUTHOR("Junjiro R. Okajima <aufs-users@lists.sourceforge.net>");
1facf9fc 18989+MODULE_DESCRIPTION(AUFS_NAME
18990+ " -- Advanced multi layered unification filesystem");
18991+MODULE_VERSION(AUFS_VERSION);
18992+
1facf9fc 18993+/* this module parameter has no meaning when SYSFS is disabled */
18994+int sysaufs_brs = 1;
18995+MODULE_PARM_DESC(brs, "use <sysfs>/fs/aufs/si_*/brN");
18996+module_param_named(brs, sysaufs_brs, int, S_IRUGO);
18997+
18998+/* ---------------------------------------------------------------------- */
18999+
19000+static char au_esc_chars[0x20 + 3]; /* 0x01-0x20, backslash, del, and NULL */
19001+
19002+int au_seq_path(struct seq_file *seq, struct path *path)
19003+{
19004+ return seq_path(seq, path, au_esc_chars);
19005+}
19006+
19007+/* ---------------------------------------------------------------------- */
19008+
19009+static int __init aufs_init(void)
19010+{
19011+ int err, i;
19012+ char *p;
19013+
19014+ p = au_esc_chars;
19015+ for (i = 1; i <= ' '; i++)
19016+ *p++ = i;
19017+ *p++ = '\\';
19018+ *p++ = '\x7f';
19019+ *p = 0;
19020+
19021+ au_dir_roflags = au_file_roflags(O_DIRECTORY | O_LARGEFILE);
19022+
e49829fe 19023+ au_sbilist_init();
1facf9fc 19024+ sysaufs_brs_init();
19025+ au_debug_init();
4a4d8108 19026+ au_dy_init();
1facf9fc 19027+ err = sysaufs_init();
19028+ if (unlikely(err))
19029+ goto out;
e49829fe 19030+ err = au_procfs_init();
4f0767ce 19031+ if (unlikely(err))
953406b4 19032+ goto out_sysaufs;
e49829fe
JR
19033+ err = au_wkq_init();
19034+ if (unlikely(err))
19035+ goto out_procfs;
87a755f4 19036+ err = au_loopback_init();
1facf9fc 19037+ if (unlikely(err))
19038+ goto out_wkq;
87a755f4
AM
19039+ err = au_hnotify_init();
19040+ if (unlikely(err))
19041+ goto out_loopback;
1facf9fc 19042+ err = au_sysrq_init();
19043+ if (unlikely(err))
19044+ goto out_hin;
19045+ err = au_cache_init();
19046+ if (unlikely(err))
19047+ goto out_sysrq;
19048+ err = register_filesystem(&aufs_fs_type);
19049+ if (unlikely(err))
19050+ goto out_cache;
4a4d8108
AM
19051+ /* since we define pr_fmt, call printk directly */
19052+ printk(KERN_INFO AUFS_NAME " " AUFS_VERSION "\n");
1facf9fc 19053+ goto out; /* success */
19054+
4f0767ce 19055+out_cache:
1facf9fc 19056+ au_cache_fin();
4f0767ce 19057+out_sysrq:
1facf9fc 19058+ au_sysrq_fin();
4f0767ce 19059+out_hin:
4a4d8108 19060+ au_hnotify_fin();
87a755f4
AM
19061+out_loopback:
19062+ au_loopback_fin();
4f0767ce 19063+out_wkq:
1facf9fc 19064+ au_wkq_fin();
e49829fe
JR
19065+out_procfs:
19066+ au_procfs_fin();
4f0767ce 19067+out_sysaufs:
1facf9fc 19068+ sysaufs_fin();
4a4d8108 19069+ au_dy_fin();
4f0767ce 19070+out:
1facf9fc 19071+ return err;
19072+}
19073+
19074+static void __exit aufs_exit(void)
19075+{
19076+ unregister_filesystem(&aufs_fs_type);
19077+ au_cache_fin();
19078+ au_sysrq_fin();
4a4d8108 19079+ au_hnotify_fin();
87a755f4 19080+ au_loopback_fin();
1facf9fc 19081+ au_wkq_fin();
e49829fe 19082+ au_procfs_fin();
1facf9fc 19083+ sysaufs_fin();
4a4d8108 19084+ au_dy_fin();
1facf9fc 19085+}
19086+
19087+module_init(aufs_init);
19088+module_exit(aufs_exit);
7f207e10
AM
19089diff -urN /usr/share/empty/fs/aufs/module.h linux/fs/aufs/module.h
19090--- /usr/share/empty/fs/aufs/module.h 1970-01-01 01:00:00.000000000 +0100
0c3ec466 19091+++ linux/fs/aufs/module.h 2012-07-22 19:57:03.164337936 +0200
7eafdf33 19092@@ -0,0 +1,105 @@
1facf9fc 19093+/*
f6c5ef8b 19094+ * Copyright (C) 2005-2012 Junjiro R. Okajima
1facf9fc 19095+ *
19096+ * This program, aufs is free software; you can redistribute it and/or modify
19097+ * it under the terms of the GNU General Public License as published by
19098+ * the Free Software Foundation; either version 2 of the License, or
19099+ * (at your option) any later version.
dece6358
AM
19100+ *
19101+ * This program is distributed in the hope that it will be useful,
19102+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
19103+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19104+ * GNU General Public License for more details.
19105+ *
19106+ * You should have received a copy of the GNU General Public License
19107+ * along with this program; if not, write to the Free Software
19108+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 19109+ */
19110+
19111+/*
19112+ * module initialization and module-global
19113+ */
19114+
19115+#ifndef __AUFS_MODULE_H__
19116+#define __AUFS_MODULE_H__
19117+
19118+#ifdef __KERNEL__
19119+
19120+#include <linux/slab.h>
19121+
dece6358
AM
19122+struct path;
19123+struct seq_file;
19124+
1facf9fc 19125+/* module parameters */
1facf9fc 19126+extern int sysaufs_brs;
19127+
19128+/* ---------------------------------------------------------------------- */
19129+
19130+extern int au_dir_roflags;
19131+
9dbd164d
AM
19132+enum {
19133+ AuLcNonDir_FIINFO,
19134+ AuLcNonDir_DIINFO,
19135+ AuLcNonDir_IIINFO,
19136+
19137+ AuLcDir_FIINFO,
19138+ AuLcDir_DIINFO,
19139+ AuLcDir_IIINFO,
19140+
19141+ AuLcSymlink_DIINFO,
19142+ AuLcSymlink_IIINFO,
19143+
19144+ AuLcKey_Last
19145+};
19146+extern struct lock_class_key au_lc_key[AuLcKey_Last];
19147+
1facf9fc 19148+void *au_kzrealloc(void *p, unsigned int nused, unsigned int new_sz, gfp_t gfp);
19149+int au_seq_path(struct seq_file *seq, struct path *path);
19150+
e49829fe
JR
19151+#ifdef CONFIG_PROC_FS
19152+/* procfs.c */
19153+int __init au_procfs_init(void);
19154+void au_procfs_fin(void);
19155+#else
19156+AuStubInt0(au_procfs_init, void);
19157+AuStubVoid(au_procfs_fin, void);
19158+#endif
19159+
4f0767ce
JR
19160+/* ---------------------------------------------------------------------- */
19161+
19162+/* kmem cache */
1facf9fc 19163+enum {
19164+ AuCache_DINFO,
19165+ AuCache_ICNTNR,
19166+ AuCache_FINFO,
19167+ AuCache_VDIR,
19168+ AuCache_DEHSTR,
7eafdf33 19169+ AuCache_HNOTIFY, /* must be last */
1facf9fc 19170+ AuCache_Last
19171+};
19172+
4a4d8108
AM
19173+#define AuCacheFlags (SLAB_RECLAIM_ACCOUNT | SLAB_MEM_SPREAD)
19174+#define AuCache(type) KMEM_CACHE(type, AuCacheFlags)
19175+#define AuCacheCtor(type, ctor) \
19176+ kmem_cache_create(#type, sizeof(struct type), \
19177+ __alignof__(struct type), AuCacheFlags, ctor)
1facf9fc 19178+
19179+extern struct kmem_cache *au_cachep[];
19180+
19181+#define AuCacheFuncs(name, index) \
4a4d8108 19182+static inline struct au_##name *au_cache_alloc_##name(void) \
1facf9fc 19183+{ return kmem_cache_alloc(au_cachep[AuCache_##index], GFP_NOFS); } \
4a4d8108 19184+static inline void au_cache_free_##name(struct au_##name *p) \
1facf9fc 19185+{ kmem_cache_free(au_cachep[AuCache_##index], p); }
19186+
19187+AuCacheFuncs(dinfo, DINFO);
19188+AuCacheFuncs(icntnr, ICNTNR);
19189+AuCacheFuncs(finfo, FINFO);
19190+AuCacheFuncs(vdir, VDIR);
4a4d8108
AM
19191+AuCacheFuncs(vdir_dehstr, DEHSTR);
19192+#ifdef CONFIG_AUFS_HNOTIFY
19193+AuCacheFuncs(hnotify, HNOTIFY);
19194+#endif
1facf9fc 19195+
4a4d8108
AM
19196+#endif /* __KERNEL__ */
19197+#endif /* __AUFS_MODULE_H__ */
7f207e10
AM
19198diff -urN /usr/share/empty/fs/aufs/opts.c linux/fs/aufs/opts.c
19199--- /usr/share/empty/fs/aufs/opts.c 1970-01-01 01:00:00.000000000 +0100
0c3ec466 19200+++ linux/fs/aufs/opts.c 2012-07-22 19:57:03.164337936 +0200
f6c5ef8b 19201@@ -0,0 +1,1677 @@
1facf9fc 19202+/*
f6c5ef8b 19203+ * Copyright (C) 2005-2012 Junjiro R. Okajima
1facf9fc 19204+ *
19205+ * This program, aufs is free software; you can redistribute it and/or modify
19206+ * it under the terms of the GNU General Public License as published by
19207+ * the Free Software Foundation; either version 2 of the License, or
19208+ * (at your option) any later version.
dece6358
AM
19209+ *
19210+ * This program is distributed in the hope that it will be useful,
19211+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
19212+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19213+ * GNU General Public License for more details.
19214+ *
19215+ * You should have received a copy of the GNU General Public License
19216+ * along with this program; if not, write to the Free Software
19217+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 19218+ */
19219+
19220+/*
19221+ * mount options/flags
19222+ */
19223+
dece6358 19224+#include <linux/namei.h>
1facf9fc 19225+#include <linux/types.h> /* a distribution requires */
19226+#include <linux/parser.h>
19227+#include "aufs.h"
19228+
19229+/* ---------------------------------------------------------------------- */
19230+
19231+enum {
19232+ Opt_br,
19233+ Opt_add, Opt_del, Opt_mod, Opt_reorder, Opt_append, Opt_prepend,
19234+ Opt_idel, Opt_imod, Opt_ireorder,
19235+ Opt_dirwh, Opt_rdcache, Opt_rdblk, Opt_rdhash, Opt_rendir,
dece6358 19236+ Opt_rdblk_def, Opt_rdhash_def,
1facf9fc 19237+ Opt_xino, Opt_zxino, Opt_noxino,
19238+ Opt_trunc_xino, Opt_trunc_xino_v, Opt_notrunc_xino,
19239+ Opt_trunc_xino_path, Opt_itrunc_xino,
19240+ Opt_trunc_xib, Opt_notrunc_xib,
dece6358 19241+ Opt_shwh, Opt_noshwh,
1facf9fc 19242+ Opt_plink, Opt_noplink, Opt_list_plink,
19243+ Opt_udba,
4a4d8108 19244+ Opt_dio, Opt_nodio,
1facf9fc 19245+ /* Opt_lock, Opt_unlock, */
19246+ Opt_cmd, Opt_cmd_args,
19247+ Opt_diropq_a, Opt_diropq_w,
19248+ Opt_warn_perm, Opt_nowarn_perm,
19249+ Opt_wbr_copyup, Opt_wbr_create,
19250+ Opt_refrof, Opt_norefrof,
19251+ Opt_verbose, Opt_noverbose,
19252+ Opt_sum, Opt_nosum, Opt_wsum,
19253+ Opt_tail, Opt_ignore, Opt_ignore_silent, Opt_err
19254+};
19255+
19256+static match_table_t options = {
19257+ {Opt_br, "br=%s"},
19258+ {Opt_br, "br:%s"},
19259+
19260+ {Opt_add, "add=%d:%s"},
19261+ {Opt_add, "add:%d:%s"},
19262+ {Opt_add, "ins=%d:%s"},
19263+ {Opt_add, "ins:%d:%s"},
19264+ {Opt_append, "append=%s"},
19265+ {Opt_append, "append:%s"},
19266+ {Opt_prepend, "prepend=%s"},
19267+ {Opt_prepend, "prepend:%s"},
19268+
19269+ {Opt_del, "del=%s"},
19270+ {Opt_del, "del:%s"},
19271+ /* {Opt_idel, "idel:%d"}, */
19272+ {Opt_mod, "mod=%s"},
19273+ {Opt_mod, "mod:%s"},
19274+ /* {Opt_imod, "imod:%d:%s"}, */
19275+
19276+ {Opt_dirwh, "dirwh=%d"},
19277+
19278+ {Opt_xino, "xino=%s"},
19279+ {Opt_noxino, "noxino"},
19280+ {Opt_trunc_xino, "trunc_xino"},
19281+ {Opt_trunc_xino_v, "trunc_xino_v=%d:%d"},
19282+ {Opt_notrunc_xino, "notrunc_xino"},
19283+ {Opt_trunc_xino_path, "trunc_xino=%s"},
19284+ {Opt_itrunc_xino, "itrunc_xino=%d"},
19285+ /* {Opt_zxino, "zxino=%s"}, */
19286+ {Opt_trunc_xib, "trunc_xib"},
19287+ {Opt_notrunc_xib, "notrunc_xib"},
19288+
e49829fe 19289+#ifdef CONFIG_PROC_FS
1facf9fc 19290+ {Opt_plink, "plink"},
e49829fe
JR
19291+#else
19292+ {Opt_ignore_silent, "plink"},
19293+#endif
19294+
1facf9fc 19295+ {Opt_noplink, "noplink"},
e49829fe 19296+
1facf9fc 19297+#ifdef CONFIG_AUFS_DEBUG
19298+ {Opt_list_plink, "list_plink"},
19299+#endif
19300+
19301+ {Opt_udba, "udba=%s"},
19302+
4a4d8108
AM
19303+ {Opt_dio, "dio"},
19304+ {Opt_nodio, "nodio"},
19305+
1facf9fc 19306+ {Opt_diropq_a, "diropq=always"},
19307+ {Opt_diropq_a, "diropq=a"},
19308+ {Opt_diropq_w, "diropq=whiteouted"},
19309+ {Opt_diropq_w, "diropq=w"},
19310+
19311+ {Opt_warn_perm, "warn_perm"},
19312+ {Opt_nowarn_perm, "nowarn_perm"},
19313+
19314+ /* keep them temporary */
19315+ {Opt_ignore_silent, "coo=%s"},
19316+ {Opt_ignore_silent, "nodlgt"},
19317+ {Opt_ignore_silent, "nodirperm1"},
1facf9fc 19318+ {Opt_ignore_silent, "clean_plink"},
19319+
dece6358
AM
19320+#ifdef CONFIG_AUFS_SHWH
19321+ {Opt_shwh, "shwh"},
19322+#endif
19323+ {Opt_noshwh, "noshwh"},
19324+
1facf9fc 19325+ {Opt_rendir, "rendir=%d"},
19326+
19327+ {Opt_refrof, "refrof"},
19328+ {Opt_norefrof, "norefrof"},
19329+
19330+ {Opt_verbose, "verbose"},
19331+ {Opt_verbose, "v"},
19332+ {Opt_noverbose, "noverbose"},
19333+ {Opt_noverbose, "quiet"},
19334+ {Opt_noverbose, "q"},
19335+ {Opt_noverbose, "silent"},
19336+
19337+ {Opt_sum, "sum"},
19338+ {Opt_nosum, "nosum"},
19339+ {Opt_wsum, "wsum"},
19340+
19341+ {Opt_rdcache, "rdcache=%d"},
19342+ {Opt_rdblk, "rdblk=%d"},
dece6358 19343+ {Opt_rdblk_def, "rdblk=def"},
1facf9fc 19344+ {Opt_rdhash, "rdhash=%d"},
dece6358 19345+ {Opt_rdhash_def, "rdhash=def"},
1facf9fc 19346+
19347+ {Opt_wbr_create, "create=%s"},
19348+ {Opt_wbr_create, "create_policy=%s"},
19349+ {Opt_wbr_copyup, "cpup=%s"},
19350+ {Opt_wbr_copyup, "copyup=%s"},
19351+ {Opt_wbr_copyup, "copyup_policy=%s"},
19352+
19353+ /* internal use for the scripts */
19354+ {Opt_ignore_silent, "si=%s"},
19355+
19356+ {Opt_br, "dirs=%s"},
19357+ {Opt_ignore, "debug=%d"},
19358+ {Opt_ignore, "delete=whiteout"},
19359+ {Opt_ignore, "delete=all"},
19360+ {Opt_ignore, "imap=%s"},
19361+
1308ab2a 19362+ /* temporary workaround, due to old mount(8)? */
19363+ {Opt_ignore_silent, "relatime"},
19364+
1facf9fc 19365+ {Opt_err, NULL}
19366+};
19367+
19368+/* ---------------------------------------------------------------------- */
19369+
19370+static const char *au_parser_pattern(int val, struct match_token *token)
19371+{
19372+ while (token->pattern) {
19373+ if (token->token == val)
19374+ return token->pattern;
19375+ token++;
19376+ }
19377+ BUG();
19378+ return "??";
19379+}
19380+
19381+/* ---------------------------------------------------------------------- */
19382+
1e00d052 19383+static match_table_t brperm = {
1facf9fc 19384+ {AuBrPerm_RO, AUFS_BRPERM_RO},
19385+ {AuBrPerm_RR, AUFS_BRPERM_RR},
19386+ {AuBrPerm_RW, AUFS_BRPERM_RW},
1e00d052
AM
19387+ {0, NULL}
19388+};
1facf9fc 19389+
1e00d052
AM
19390+static match_table_t brrattr = {
19391+ {AuBrRAttr_WH, AUFS_BRRATTR_WH},
19392+ {0, NULL}
19393+};
1facf9fc 19394+
1e00d052
AM
19395+static match_table_t brwattr = {
19396+ {AuBrWAttr_NoLinkWH, AUFS_BRWATTR_NLWH},
19397+ {0, NULL}
1facf9fc 19398+};
19399+
1e00d052
AM
19400+#define AuBrStr_LONGEST AUFS_BRPERM_RW "+" AUFS_BRWATTR_NLWH
19401+
19402+static int br_attr_val(char *str, match_table_t table, substring_t args[])
19403+{
19404+ int attr, v;
19405+ char *p;
19406+
19407+ attr = 0;
19408+ do {
19409+ p = strchr(str, '+');
19410+ if (p)
19411+ *p = 0;
19412+ v = match_token(str, table, args);
19413+ if (v)
19414+ attr |= v;
19415+ else {
19416+ if (p)
19417+ *p = '+';
0c3ec466 19418+ pr_warn("ignored branch attribute %s\n", str);
1e00d052
AM
19419+ break;
19420+ }
19421+ if (p)
19422+ str = p + 1;
19423+ } while (p);
19424+
19425+ return attr;
19426+}
19427+
4a4d8108 19428+static int noinline_for_stack br_perm_val(char *perm)
1facf9fc 19429+{
19430+ int val;
1e00d052 19431+ char *p;
1facf9fc 19432+ substring_t args[MAX_OPT_ARGS];
19433+
1e00d052
AM
19434+ p = strchr(perm, '+');
19435+ if (p)
19436+ *p = 0;
19437+ val = match_token(perm, brperm, args);
19438+ if (!val) {
19439+ if (p)
19440+ *p = '+';
0c3ec466 19441+ pr_warn("ignored branch permission %s\n", perm);
1e00d052
AM
19442+ val = AuBrPerm_RO;
19443+ goto out;
19444+ }
19445+ if (!p)
19446+ goto out;
19447+
19448+ switch (val) {
19449+ case AuBrPerm_RO:
19450+ case AuBrPerm_RR:
19451+ val |= br_attr_val(p + 1, brrattr, args);
19452+ break;
19453+ case AuBrPerm_RW:
19454+ val |= br_attr_val(p + 1, brwattr, args);
19455+ break;
19456+ }
19457+
19458+out:
1facf9fc 19459+ return val;
19460+}
19461+
1e00d052
AM
19462+/* Caller should free the return value */
19463+char *au_optstr_br_perm(int brperm)
1facf9fc 19464+{
1e00d052
AM
19465+ char *p, a[sizeof(AuBrStr_LONGEST)];
19466+ int sz;
19467+
19468+#define SetPerm(str) do { \
19469+ sz = sizeof(str); \
19470+ memcpy(a, str, sz); \
19471+ p = a + sz - 1; \
19472+ } while (0)
19473+
19474+#define AppendAttr(flag, str) do { \
19475+ if (brperm & flag) { \
19476+ sz = sizeof(str); \
19477+ *p++ = '+'; \
19478+ memcpy(p, str, sz); \
19479+ p += sz - 1; \
19480+ } \
19481+ } while (0)
19482+
19483+ switch (brperm & AuBrPerm_Mask) {
19484+ case AuBrPerm_RO:
19485+ SetPerm(AUFS_BRPERM_RO);
19486+ break;
19487+ case AuBrPerm_RR:
19488+ SetPerm(AUFS_BRPERM_RR);
19489+ break;
19490+ case AuBrPerm_RW:
19491+ SetPerm(AUFS_BRPERM_RW);
19492+ break;
19493+ default:
19494+ AuDebugOn(1);
19495+ }
19496+
19497+ AppendAttr(AuBrRAttr_WH, AUFS_BRRATTR_WH);
19498+ AppendAttr(AuBrWAttr_NoLinkWH, AUFS_BRWATTR_NLWH);
19499+
19500+ AuDebugOn(strlen(a) >= sizeof(a));
19501+ return kstrdup(a, GFP_NOFS);
19502+#undef SetPerm
19503+#undef AppendAttr
1facf9fc 19504+}
19505+
19506+/* ---------------------------------------------------------------------- */
19507+
19508+static match_table_t udbalevel = {
19509+ {AuOpt_UDBA_REVAL, "reval"},
19510+ {AuOpt_UDBA_NONE, "none"},
4a4d8108
AM
19511+#ifdef CONFIG_AUFS_HNOTIFY
19512+ {AuOpt_UDBA_HNOTIFY, "notify"}, /* abstraction */
19513+#ifdef CONFIG_AUFS_HFSNOTIFY
19514+ {AuOpt_UDBA_HNOTIFY, "fsnotify"},
4a4d8108 19515+#endif
1facf9fc 19516+#endif
19517+ {-1, NULL}
19518+};
19519+
4a4d8108 19520+static int noinline_for_stack udba_val(char *str)
1facf9fc 19521+{
19522+ substring_t args[MAX_OPT_ARGS];
19523+
7f207e10 19524+ return match_token(str, udbalevel, args);
1facf9fc 19525+}
19526+
19527+const char *au_optstr_udba(int udba)
19528+{
19529+ return au_parser_pattern(udba, (void *)udbalevel);
19530+}
19531+
19532+/* ---------------------------------------------------------------------- */
19533+
19534+static match_table_t au_wbr_create_policy = {
19535+ {AuWbrCreate_TDP, "tdp"},
19536+ {AuWbrCreate_TDP, "top-down-parent"},
19537+ {AuWbrCreate_RR, "rr"},
19538+ {AuWbrCreate_RR, "round-robin"},
19539+ {AuWbrCreate_MFS, "mfs"},
19540+ {AuWbrCreate_MFS, "most-free-space"},
19541+ {AuWbrCreate_MFSV, "mfs:%d"},
19542+ {AuWbrCreate_MFSV, "most-free-space:%d"},
19543+
19544+ {AuWbrCreate_MFSRR, "mfsrr:%d"},
19545+ {AuWbrCreate_MFSRRV, "mfsrr:%d:%d"},
19546+ {AuWbrCreate_PMFS, "pmfs"},
19547+ {AuWbrCreate_PMFSV, "pmfs:%d"},
19548+
19549+ {-1, NULL}
19550+};
19551+
dece6358
AM
19552+/*
19553+ * cf. linux/lib/parser.c and cmdline.c
19554+ * gave up calling memparse() since it uses simple_strtoull() instead of
9dbd164d 19555+ * kstrto...().
dece6358 19556+ */
4a4d8108
AM
19557+static int noinline_for_stack
19558+au_match_ull(substring_t *s, unsigned long long *result)
1facf9fc 19559+{
19560+ int err;
19561+ unsigned int len;
19562+ char a[32];
19563+
19564+ err = -ERANGE;
19565+ len = s->to - s->from;
19566+ if (len + 1 <= sizeof(a)) {
19567+ memcpy(a, s->from, len);
19568+ a[len] = '\0';
9dbd164d 19569+ err = kstrtoull(a, 0, result);
1facf9fc 19570+ }
19571+ return err;
19572+}
19573+
19574+static int au_wbr_mfs_wmark(substring_t *arg, char *str,
19575+ struct au_opt_wbr_create *create)
19576+{
19577+ int err;
19578+ unsigned long long ull;
19579+
19580+ err = 0;
19581+ if (!au_match_ull(arg, &ull))
19582+ create->mfsrr_watermark = ull;
19583+ else {
4a4d8108 19584+ pr_err("bad integer in %s\n", str);
1facf9fc 19585+ err = -EINVAL;
19586+ }
19587+
19588+ return err;
19589+}
19590+
19591+static int au_wbr_mfs_sec(substring_t *arg, char *str,
19592+ struct au_opt_wbr_create *create)
19593+{
19594+ int n, err;
19595+
19596+ err = 0;
027c5e7a 19597+ if (!match_int(arg, &n) && 0 <= n && n <= AUFS_MFS_MAX_SEC)
1facf9fc 19598+ create->mfs_second = n;
19599+ else {
4a4d8108 19600+ pr_err("bad integer in %s\n", str);
1facf9fc 19601+ err = -EINVAL;
19602+ }
19603+
19604+ return err;
19605+}
19606+
4a4d8108
AM
19607+static int noinline_for_stack
19608+au_wbr_create_val(char *str, struct au_opt_wbr_create *create)
1facf9fc 19609+{
19610+ int err, e;
19611+ substring_t args[MAX_OPT_ARGS];
19612+
19613+ err = match_token(str, au_wbr_create_policy, args);
19614+ create->wbr_create = err;
19615+ switch (err) {
19616+ case AuWbrCreate_MFSRRV:
19617+ e = au_wbr_mfs_wmark(&args[0], str, create);
19618+ if (!e)
19619+ e = au_wbr_mfs_sec(&args[1], str, create);
19620+ if (unlikely(e))
19621+ err = e;
19622+ break;
19623+ case AuWbrCreate_MFSRR:
19624+ e = au_wbr_mfs_wmark(&args[0], str, create);
19625+ if (unlikely(e)) {
19626+ err = e;
19627+ break;
19628+ }
19629+ /*FALLTHROUGH*/
19630+ case AuWbrCreate_MFS:
19631+ case AuWbrCreate_PMFS:
027c5e7a 19632+ create->mfs_second = AUFS_MFS_DEF_SEC;
1facf9fc 19633+ break;
19634+ case AuWbrCreate_MFSV:
19635+ case AuWbrCreate_PMFSV:
19636+ e = au_wbr_mfs_sec(&args[0], str, create);
19637+ if (unlikely(e))
19638+ err = e;
19639+ break;
19640+ }
19641+
19642+ return err;
19643+}
19644+
19645+const char *au_optstr_wbr_create(int wbr_create)
19646+{
19647+ return au_parser_pattern(wbr_create, (void *)au_wbr_create_policy);
19648+}
19649+
19650+static match_table_t au_wbr_copyup_policy = {
19651+ {AuWbrCopyup_TDP, "tdp"},
19652+ {AuWbrCopyup_TDP, "top-down-parent"},
19653+ {AuWbrCopyup_BUP, "bup"},
19654+ {AuWbrCopyup_BUP, "bottom-up-parent"},
19655+ {AuWbrCopyup_BU, "bu"},
19656+ {AuWbrCopyup_BU, "bottom-up"},
19657+ {-1, NULL}
19658+};
19659+
4a4d8108 19660+static int noinline_for_stack au_wbr_copyup_val(char *str)
1facf9fc 19661+{
19662+ substring_t args[MAX_OPT_ARGS];
19663+
19664+ return match_token(str, au_wbr_copyup_policy, args);
19665+}
19666+
19667+const char *au_optstr_wbr_copyup(int wbr_copyup)
19668+{
19669+ return au_parser_pattern(wbr_copyup, (void *)au_wbr_copyup_policy);
19670+}
19671+
19672+/* ---------------------------------------------------------------------- */
19673+
19674+static const int lkup_dirflags = LOOKUP_FOLLOW | LOOKUP_DIRECTORY;
19675+
19676+static void dump_opts(struct au_opts *opts)
19677+{
19678+#ifdef CONFIG_AUFS_DEBUG
19679+ /* reduce stack space */
19680+ union {
19681+ struct au_opt_add *add;
19682+ struct au_opt_del *del;
19683+ struct au_opt_mod *mod;
19684+ struct au_opt_xino *xino;
19685+ struct au_opt_xino_itrunc *xino_itrunc;
19686+ struct au_opt_wbr_create *create;
19687+ } u;
19688+ struct au_opt *opt;
19689+
19690+ opt = opts->opt;
19691+ while (opt->type != Opt_tail) {
19692+ switch (opt->type) {
19693+ case Opt_add:
19694+ u.add = &opt->add;
19695+ AuDbg("add {b%d, %s, 0x%x, %p}\n",
19696+ u.add->bindex, u.add->pathname, u.add->perm,
19697+ u.add->path.dentry);
19698+ break;
19699+ case Opt_del:
19700+ case Opt_idel:
19701+ u.del = &opt->del;
19702+ AuDbg("del {%s, %p}\n",
19703+ u.del->pathname, u.del->h_path.dentry);
19704+ break;
19705+ case Opt_mod:
19706+ case Opt_imod:
19707+ u.mod = &opt->mod;
19708+ AuDbg("mod {%s, 0x%x, %p}\n",
19709+ u.mod->path, u.mod->perm, u.mod->h_root);
19710+ break;
19711+ case Opt_append:
19712+ u.add = &opt->add;
19713+ AuDbg("append {b%d, %s, 0x%x, %p}\n",
19714+ u.add->bindex, u.add->pathname, u.add->perm,
19715+ u.add->path.dentry);
19716+ break;
19717+ case Opt_prepend:
19718+ u.add = &opt->add;
19719+ AuDbg("prepend {b%d, %s, 0x%x, %p}\n",
19720+ u.add->bindex, u.add->pathname, u.add->perm,
19721+ u.add->path.dentry);
19722+ break;
19723+ case Opt_dirwh:
19724+ AuDbg("dirwh %d\n", opt->dirwh);
19725+ break;
19726+ case Opt_rdcache:
19727+ AuDbg("rdcache %d\n", opt->rdcache);
19728+ break;
19729+ case Opt_rdblk:
19730+ AuDbg("rdblk %u\n", opt->rdblk);
19731+ break;
dece6358
AM
19732+ case Opt_rdblk_def:
19733+ AuDbg("rdblk_def\n");
19734+ break;
1facf9fc 19735+ case Opt_rdhash:
19736+ AuDbg("rdhash %u\n", opt->rdhash);
19737+ break;
dece6358
AM
19738+ case Opt_rdhash_def:
19739+ AuDbg("rdhash_def\n");
19740+ break;
1facf9fc 19741+ case Opt_xino:
19742+ u.xino = &opt->xino;
19743+ AuDbg("xino {%s %.*s}\n",
19744+ u.xino->path,
19745+ AuDLNPair(u.xino->file->f_dentry));
19746+ break;
19747+ case Opt_trunc_xino:
19748+ AuLabel(trunc_xino);
19749+ break;
19750+ case Opt_notrunc_xino:
19751+ AuLabel(notrunc_xino);
19752+ break;
19753+ case Opt_trunc_xino_path:
19754+ case Opt_itrunc_xino:
19755+ u.xino_itrunc = &opt->xino_itrunc;
19756+ AuDbg("trunc_xino %d\n", u.xino_itrunc->bindex);
19757+ break;
19758+
19759+ case Opt_noxino:
19760+ AuLabel(noxino);
19761+ break;
19762+ case Opt_trunc_xib:
19763+ AuLabel(trunc_xib);
19764+ break;
19765+ case Opt_notrunc_xib:
19766+ AuLabel(notrunc_xib);
19767+ break;
dece6358
AM
19768+ case Opt_shwh:
19769+ AuLabel(shwh);
19770+ break;
19771+ case Opt_noshwh:
19772+ AuLabel(noshwh);
19773+ break;
1facf9fc 19774+ case Opt_plink:
19775+ AuLabel(plink);
19776+ break;
19777+ case Opt_noplink:
19778+ AuLabel(noplink);
19779+ break;
19780+ case Opt_list_plink:
19781+ AuLabel(list_plink);
19782+ break;
19783+ case Opt_udba:
19784+ AuDbg("udba %d, %s\n",
19785+ opt->udba, au_optstr_udba(opt->udba));
19786+ break;
4a4d8108
AM
19787+ case Opt_dio:
19788+ AuLabel(dio);
19789+ break;
19790+ case Opt_nodio:
19791+ AuLabel(nodio);
19792+ break;
1facf9fc 19793+ case Opt_diropq_a:
19794+ AuLabel(diropq_a);
19795+ break;
19796+ case Opt_diropq_w:
19797+ AuLabel(diropq_w);
19798+ break;
19799+ case Opt_warn_perm:
19800+ AuLabel(warn_perm);
19801+ break;
19802+ case Opt_nowarn_perm:
19803+ AuLabel(nowarn_perm);
19804+ break;
19805+ case Opt_refrof:
19806+ AuLabel(refrof);
19807+ break;
19808+ case Opt_norefrof:
19809+ AuLabel(norefrof);
19810+ break;
19811+ case Opt_verbose:
19812+ AuLabel(verbose);
19813+ break;
19814+ case Opt_noverbose:
19815+ AuLabel(noverbose);
19816+ break;
19817+ case Opt_sum:
19818+ AuLabel(sum);
19819+ break;
19820+ case Opt_nosum:
19821+ AuLabel(nosum);
19822+ break;
19823+ case Opt_wsum:
19824+ AuLabel(wsum);
19825+ break;
19826+ case Opt_wbr_create:
19827+ u.create = &opt->wbr_create;
19828+ AuDbg("create %d, %s\n", u.create->wbr_create,
19829+ au_optstr_wbr_create(u.create->wbr_create));
19830+ switch (u.create->wbr_create) {
19831+ case AuWbrCreate_MFSV:
19832+ case AuWbrCreate_PMFSV:
19833+ AuDbg("%d sec\n", u.create->mfs_second);
19834+ break;
19835+ case AuWbrCreate_MFSRR:
19836+ AuDbg("%llu watermark\n",
19837+ u.create->mfsrr_watermark);
19838+ break;
19839+ case AuWbrCreate_MFSRRV:
19840+ AuDbg("%llu watermark, %d sec\n",
19841+ u.create->mfsrr_watermark,
19842+ u.create->mfs_second);
19843+ break;
19844+ }
19845+ break;
19846+ case Opt_wbr_copyup:
19847+ AuDbg("copyup %d, %s\n", opt->wbr_copyup,
19848+ au_optstr_wbr_copyup(opt->wbr_copyup));
19849+ break;
19850+ default:
19851+ BUG();
19852+ }
19853+ opt++;
19854+ }
19855+#endif
19856+}
19857+
19858+void au_opts_free(struct au_opts *opts)
19859+{
19860+ struct au_opt *opt;
19861+
19862+ opt = opts->opt;
19863+ while (opt->type != Opt_tail) {
19864+ switch (opt->type) {
19865+ case Opt_add:
19866+ case Opt_append:
19867+ case Opt_prepend:
19868+ path_put(&opt->add.path);
19869+ break;
19870+ case Opt_del:
19871+ case Opt_idel:
19872+ path_put(&opt->del.h_path);
19873+ break;
19874+ case Opt_mod:
19875+ case Opt_imod:
19876+ dput(opt->mod.h_root);
19877+ break;
19878+ case Opt_xino:
19879+ fput(opt->xino.file);
19880+ break;
19881+ }
19882+ opt++;
19883+ }
19884+}
19885+
19886+static int opt_add(struct au_opt *opt, char *opt_str, unsigned long sb_flags,
19887+ aufs_bindex_t bindex)
19888+{
19889+ int err;
19890+ struct au_opt_add *add = &opt->add;
19891+ char *p;
19892+
19893+ add->bindex = bindex;
1e00d052 19894+ add->perm = AuBrPerm_RO;
1facf9fc 19895+ add->pathname = opt_str;
19896+ p = strchr(opt_str, '=');
19897+ if (p) {
19898+ *p++ = 0;
19899+ if (*p)
19900+ add->perm = br_perm_val(p);
19901+ }
19902+
19903+ err = vfsub_kern_path(add->pathname, lkup_dirflags, &add->path);
19904+ if (!err) {
19905+ if (!p) {
19906+ add->perm = AuBrPerm_RO;
19907+ if (au_test_fs_rr(add->path.dentry->d_sb))
19908+ add->perm = AuBrPerm_RR;
19909+ else if (!bindex && !(sb_flags & MS_RDONLY))
19910+ add->perm = AuBrPerm_RW;
19911+ }
19912+ opt->type = Opt_add;
19913+ goto out;
19914+ }
4a4d8108 19915+ pr_err("lookup failed %s (%d)\n", add->pathname, err);
1facf9fc 19916+ err = -EINVAL;
19917+
4f0767ce 19918+out:
1facf9fc 19919+ return err;
19920+}
19921+
19922+static int au_opts_parse_del(struct au_opt_del *del, substring_t args[])
19923+{
19924+ int err;
19925+
19926+ del->pathname = args[0].from;
19927+ AuDbg("del path %s\n", del->pathname);
19928+
19929+ err = vfsub_kern_path(del->pathname, lkup_dirflags, &del->h_path);
19930+ if (unlikely(err))
4a4d8108 19931+ pr_err("lookup failed %s (%d)\n", del->pathname, err);
1facf9fc 19932+
19933+ return err;
19934+}
19935+
19936+#if 0 /* reserved for future use */
19937+static int au_opts_parse_idel(struct super_block *sb, aufs_bindex_t bindex,
19938+ struct au_opt_del *del, substring_t args[])
19939+{
19940+ int err;
19941+ struct dentry *root;
19942+
19943+ err = -EINVAL;
19944+ root = sb->s_root;
19945+ aufs_read_lock(root, AuLock_FLUSH);
19946+ if (bindex < 0 || au_sbend(sb) < bindex) {
4a4d8108 19947+ pr_err("out of bounds, %d\n", bindex);
1facf9fc 19948+ goto out;
19949+ }
19950+
19951+ err = 0;
19952+ del->h_path.dentry = dget(au_h_dptr(root, bindex));
19953+ del->h_path.mnt = mntget(au_sbr_mnt(sb, bindex));
19954+
4f0767ce 19955+out:
1facf9fc 19956+ aufs_read_unlock(root, !AuLock_IR);
19957+ return err;
19958+}
19959+#endif
19960+
4a4d8108
AM
19961+static int noinline_for_stack
19962+au_opts_parse_mod(struct au_opt_mod *mod, substring_t args[])
1facf9fc 19963+{
19964+ int err;
19965+ struct path path;
19966+ char *p;
19967+
19968+ err = -EINVAL;
19969+ mod->path = args[0].from;
19970+ p = strchr(mod->path, '=');
19971+ if (unlikely(!p)) {
4a4d8108 19972+ pr_err("no permssion %s\n", args[0].from);
1facf9fc 19973+ goto out;
19974+ }
19975+
19976+ *p++ = 0;
19977+ err = vfsub_kern_path(mod->path, lkup_dirflags, &path);
19978+ if (unlikely(err)) {
4a4d8108 19979+ pr_err("lookup failed %s (%d)\n", mod->path, err);
1facf9fc 19980+ goto out;
19981+ }
19982+
19983+ mod->perm = br_perm_val(p);
19984+ AuDbg("mod path %s, perm 0x%x, %s\n", mod->path, mod->perm, p);
19985+ mod->h_root = dget(path.dentry);
19986+ path_put(&path);
19987+
4f0767ce 19988+out:
1facf9fc 19989+ return err;
19990+}
19991+
19992+#if 0 /* reserved for future use */
19993+static int au_opts_parse_imod(struct super_block *sb, aufs_bindex_t bindex,
19994+ struct au_opt_mod *mod, substring_t args[])
19995+{
19996+ int err;
19997+ struct dentry *root;
19998+
19999+ err = -EINVAL;
20000+ root = sb->s_root;
20001+ aufs_read_lock(root, AuLock_FLUSH);
20002+ if (bindex < 0 || au_sbend(sb) < bindex) {
4a4d8108 20003+ pr_err("out of bounds, %d\n", bindex);
1facf9fc 20004+ goto out;
20005+ }
20006+
20007+ err = 0;
20008+ mod->perm = br_perm_val(args[1].from);
20009+ AuDbg("mod path %s, perm 0x%x, %s\n",
20010+ mod->path, mod->perm, args[1].from);
20011+ mod->h_root = dget(au_h_dptr(root, bindex));
20012+
4f0767ce 20013+out:
1facf9fc 20014+ aufs_read_unlock(root, !AuLock_IR);
20015+ return err;
20016+}
20017+#endif
20018+
20019+static int au_opts_parse_xino(struct super_block *sb, struct au_opt_xino *xino,
20020+ substring_t args[])
20021+{
20022+ int err;
20023+ struct file *file;
20024+
20025+ file = au_xino_create(sb, args[0].from, /*silent*/0);
20026+ err = PTR_ERR(file);
20027+ if (IS_ERR(file))
20028+ goto out;
20029+
20030+ err = -EINVAL;
20031+ if (unlikely(file->f_dentry->d_sb == sb)) {
20032+ fput(file);
4a4d8108 20033+ pr_err("%s must be outside\n", args[0].from);
1facf9fc 20034+ goto out;
20035+ }
20036+
20037+ err = 0;
20038+ xino->file = file;
20039+ xino->path = args[0].from;
20040+
4f0767ce 20041+out:
1facf9fc 20042+ return err;
20043+}
20044+
4a4d8108
AM
20045+static int noinline_for_stack
20046+au_opts_parse_xino_itrunc_path(struct super_block *sb,
20047+ struct au_opt_xino_itrunc *xino_itrunc,
20048+ substring_t args[])
1facf9fc 20049+{
20050+ int err;
20051+ aufs_bindex_t bend, bindex;
20052+ struct path path;
20053+ struct dentry *root;
20054+
20055+ err = vfsub_kern_path(args[0].from, lkup_dirflags, &path);
20056+ if (unlikely(err)) {
4a4d8108 20057+ pr_err("lookup failed %s (%d)\n", args[0].from, err);
1facf9fc 20058+ goto out;
20059+ }
20060+
20061+ xino_itrunc->bindex = -1;
20062+ root = sb->s_root;
20063+ aufs_read_lock(root, AuLock_FLUSH);
20064+ bend = au_sbend(sb);
20065+ for (bindex = 0; bindex <= bend; bindex++) {
20066+ if (au_h_dptr(root, bindex) == path.dentry) {
20067+ xino_itrunc->bindex = bindex;
20068+ break;
20069+ }
20070+ }
20071+ aufs_read_unlock(root, !AuLock_IR);
20072+ path_put(&path);
20073+
20074+ if (unlikely(xino_itrunc->bindex < 0)) {
4a4d8108 20075+ pr_err("no such branch %s\n", args[0].from);
1facf9fc 20076+ err = -EINVAL;
20077+ }
20078+
4f0767ce 20079+out:
1facf9fc 20080+ return err;
20081+}
20082+
20083+/* called without aufs lock */
20084+int au_opts_parse(struct super_block *sb, char *str, struct au_opts *opts)
20085+{
20086+ int err, n, token;
20087+ aufs_bindex_t bindex;
20088+ unsigned char skipped;
20089+ struct dentry *root;
20090+ struct au_opt *opt, *opt_tail;
20091+ char *opt_str;
20092+ /* reduce the stack space */
20093+ union {
20094+ struct au_opt_xino_itrunc *xino_itrunc;
20095+ struct au_opt_wbr_create *create;
20096+ } u;
20097+ struct {
20098+ substring_t args[MAX_OPT_ARGS];
20099+ } *a;
20100+
20101+ err = -ENOMEM;
20102+ a = kmalloc(sizeof(*a), GFP_NOFS);
20103+ if (unlikely(!a))
20104+ goto out;
20105+
20106+ root = sb->s_root;
20107+ err = 0;
20108+ bindex = 0;
20109+ opt = opts->opt;
20110+ opt_tail = opt + opts->max_opt - 1;
20111+ opt->type = Opt_tail;
20112+ while (!err && (opt_str = strsep(&str, ",")) && *opt_str) {
20113+ err = -EINVAL;
20114+ skipped = 0;
20115+ token = match_token(opt_str, options, a->args);
20116+ switch (token) {
20117+ case Opt_br:
20118+ err = 0;
20119+ while (!err && (opt_str = strsep(&a->args[0].from, ":"))
20120+ && *opt_str) {
20121+ err = opt_add(opt, opt_str, opts->sb_flags,
20122+ bindex++);
20123+ if (unlikely(!err && ++opt > opt_tail)) {
20124+ err = -E2BIG;
20125+ break;
20126+ }
20127+ opt->type = Opt_tail;
20128+ skipped = 1;
20129+ }
20130+ break;
20131+ case Opt_add:
20132+ if (unlikely(match_int(&a->args[0], &n))) {
4a4d8108 20133+ pr_err("bad integer in %s\n", opt_str);
1facf9fc 20134+ break;
20135+ }
20136+ bindex = n;
20137+ err = opt_add(opt, a->args[1].from, opts->sb_flags,
20138+ bindex);
20139+ if (!err)
20140+ opt->type = token;
20141+ break;
20142+ case Opt_append:
20143+ err = opt_add(opt, a->args[0].from, opts->sb_flags,
20144+ /*dummy bindex*/1);
20145+ if (!err)
20146+ opt->type = token;
20147+ break;
20148+ case Opt_prepend:
20149+ err = opt_add(opt, a->args[0].from, opts->sb_flags,
20150+ /*bindex*/0);
20151+ if (!err)
20152+ opt->type = token;
20153+ break;
20154+ case Opt_del:
20155+ err = au_opts_parse_del(&opt->del, a->args);
20156+ if (!err)
20157+ opt->type = token;
20158+ break;
20159+#if 0 /* reserved for future use */
20160+ case Opt_idel:
20161+ del->pathname = "(indexed)";
20162+ if (unlikely(match_int(&args[0], &n))) {
4a4d8108 20163+ pr_err("bad integer in %s\n", opt_str);
1facf9fc 20164+ break;
20165+ }
20166+ err = au_opts_parse_idel(sb, n, &opt->del, a->args);
20167+ if (!err)
20168+ opt->type = token;
20169+ break;
20170+#endif
20171+ case Opt_mod:
20172+ err = au_opts_parse_mod(&opt->mod, a->args);
20173+ if (!err)
20174+ opt->type = token;
20175+ break;
20176+#ifdef IMOD /* reserved for future use */
20177+ case Opt_imod:
20178+ u.mod->path = "(indexed)";
20179+ if (unlikely(match_int(&a->args[0], &n))) {
4a4d8108 20180+ pr_err("bad integer in %s\n", opt_str);
1facf9fc 20181+ break;
20182+ }
20183+ err = au_opts_parse_imod(sb, n, &opt->mod, a->args);
20184+ if (!err)
20185+ opt->type = token;
20186+ break;
20187+#endif
20188+ case Opt_xino:
20189+ err = au_opts_parse_xino(sb, &opt->xino, a->args);
20190+ if (!err)
20191+ opt->type = token;
20192+ break;
20193+
20194+ case Opt_trunc_xino_path:
20195+ err = au_opts_parse_xino_itrunc_path
20196+ (sb, &opt->xino_itrunc, a->args);
20197+ if (!err)
20198+ opt->type = token;
20199+ break;
20200+
20201+ case Opt_itrunc_xino:
20202+ u.xino_itrunc = &opt->xino_itrunc;
20203+ if (unlikely(match_int(&a->args[0], &n))) {
4a4d8108 20204+ pr_err("bad integer in %s\n", opt_str);
1facf9fc 20205+ break;
20206+ }
20207+ u.xino_itrunc->bindex = n;
20208+ aufs_read_lock(root, AuLock_FLUSH);
20209+ if (n < 0 || au_sbend(sb) < n) {
4a4d8108 20210+ pr_err("out of bounds, %d\n", n);
1facf9fc 20211+ aufs_read_unlock(root, !AuLock_IR);
20212+ break;
20213+ }
20214+ aufs_read_unlock(root, !AuLock_IR);
20215+ err = 0;
20216+ opt->type = token;
20217+ break;
20218+
20219+ case Opt_dirwh:
20220+ if (unlikely(match_int(&a->args[0], &opt->dirwh)))
20221+ break;
20222+ err = 0;
20223+ opt->type = token;
20224+ break;
20225+
20226+ case Opt_rdcache:
027c5e7a
AM
20227+ if (unlikely(match_int(&a->args[0], &n))) {
20228+ pr_err("bad integer in %s\n", opt_str);
1facf9fc 20229+ break;
027c5e7a
AM
20230+ }
20231+ if (unlikely(n > AUFS_RDCACHE_MAX)) {
20232+ pr_err("rdcache must be smaller than %d\n",
20233+ AUFS_RDCACHE_MAX);
20234+ break;
20235+ }
20236+ opt->rdcache = n;
1facf9fc 20237+ err = 0;
20238+ opt->type = token;
20239+ break;
20240+ case Opt_rdblk:
20241+ if (unlikely(match_int(&a->args[0], &n)
1308ab2a 20242+ || n < 0
1facf9fc 20243+ || n > KMALLOC_MAX_SIZE)) {
4a4d8108 20244+ pr_err("bad integer in %s\n", opt_str);
1facf9fc 20245+ break;
20246+ }
1308ab2a 20247+ if (unlikely(n && n < NAME_MAX)) {
4a4d8108
AM
20248+ pr_err("rdblk must be larger than %d\n",
20249+ NAME_MAX);
1facf9fc 20250+ break;
20251+ }
20252+ opt->rdblk = n;
20253+ err = 0;
20254+ opt->type = token;
20255+ break;
20256+ case Opt_rdhash:
20257+ if (unlikely(match_int(&a->args[0], &n)
1308ab2a 20258+ || n < 0
1facf9fc 20259+ || n * sizeof(struct hlist_head)
20260+ > KMALLOC_MAX_SIZE)) {
4a4d8108 20261+ pr_err("bad integer in %s\n", opt_str);
1facf9fc 20262+ break;
20263+ }
20264+ opt->rdhash = n;
20265+ err = 0;
20266+ opt->type = token;
20267+ break;
20268+
20269+ case Opt_trunc_xino:
20270+ case Opt_notrunc_xino:
20271+ case Opt_noxino:
20272+ case Opt_trunc_xib:
20273+ case Opt_notrunc_xib:
dece6358
AM
20274+ case Opt_shwh:
20275+ case Opt_noshwh:
1facf9fc 20276+ case Opt_plink:
20277+ case Opt_noplink:
20278+ case Opt_list_plink:
4a4d8108
AM
20279+ case Opt_dio:
20280+ case Opt_nodio:
1facf9fc 20281+ case Opt_diropq_a:
20282+ case Opt_diropq_w:
20283+ case Opt_warn_perm:
20284+ case Opt_nowarn_perm:
20285+ case Opt_refrof:
20286+ case Opt_norefrof:
20287+ case Opt_verbose:
20288+ case Opt_noverbose:
20289+ case Opt_sum:
20290+ case Opt_nosum:
20291+ case Opt_wsum:
dece6358
AM
20292+ case Opt_rdblk_def:
20293+ case Opt_rdhash_def:
1facf9fc 20294+ err = 0;
20295+ opt->type = token;
20296+ break;
20297+
20298+ case Opt_udba:
20299+ opt->udba = udba_val(a->args[0].from);
20300+ if (opt->udba >= 0) {
20301+ err = 0;
20302+ opt->type = token;
20303+ } else
4a4d8108 20304+ pr_err("wrong value, %s\n", opt_str);
1facf9fc 20305+ break;
20306+
20307+ case Opt_wbr_create:
20308+ u.create = &opt->wbr_create;
20309+ u.create->wbr_create
20310+ = au_wbr_create_val(a->args[0].from, u.create);
20311+ if (u.create->wbr_create >= 0) {
20312+ err = 0;
20313+ opt->type = token;
20314+ } else
4a4d8108 20315+ pr_err("wrong value, %s\n", opt_str);
1facf9fc 20316+ break;
20317+ case Opt_wbr_copyup:
20318+ opt->wbr_copyup = au_wbr_copyup_val(a->args[0].from);
20319+ if (opt->wbr_copyup >= 0) {
20320+ err = 0;
20321+ opt->type = token;
20322+ } else
4a4d8108 20323+ pr_err("wrong value, %s\n", opt_str);
1facf9fc 20324+ break;
20325+
20326+ case Opt_ignore:
0c3ec466 20327+ pr_warn("ignored %s\n", opt_str);
1facf9fc 20328+ /*FALLTHROUGH*/
20329+ case Opt_ignore_silent:
20330+ skipped = 1;
20331+ err = 0;
20332+ break;
20333+ case Opt_err:
4a4d8108 20334+ pr_err("unknown option %s\n", opt_str);
1facf9fc 20335+ break;
20336+ }
20337+
20338+ if (!err && !skipped) {
20339+ if (unlikely(++opt > opt_tail)) {
20340+ err = -E2BIG;
20341+ opt--;
20342+ opt->type = Opt_tail;
20343+ break;
20344+ }
20345+ opt->type = Opt_tail;
20346+ }
20347+ }
20348+
20349+ kfree(a);
20350+ dump_opts(opts);
20351+ if (unlikely(err))
20352+ au_opts_free(opts);
20353+
4f0767ce 20354+out:
1facf9fc 20355+ return err;
20356+}
20357+
20358+static int au_opt_wbr_create(struct super_block *sb,
20359+ struct au_opt_wbr_create *create)
20360+{
20361+ int err;
20362+ struct au_sbinfo *sbinfo;
20363+
dece6358
AM
20364+ SiMustWriteLock(sb);
20365+
1facf9fc 20366+ err = 1; /* handled */
20367+ sbinfo = au_sbi(sb);
20368+ if (sbinfo->si_wbr_create_ops->fin) {
20369+ err = sbinfo->si_wbr_create_ops->fin(sb);
20370+ if (!err)
20371+ err = 1;
20372+ }
20373+
20374+ sbinfo->si_wbr_create = create->wbr_create;
20375+ sbinfo->si_wbr_create_ops = au_wbr_create_ops + create->wbr_create;
20376+ switch (create->wbr_create) {
20377+ case AuWbrCreate_MFSRRV:
20378+ case AuWbrCreate_MFSRR:
20379+ sbinfo->si_wbr_mfs.mfsrr_watermark = create->mfsrr_watermark;
20380+ /*FALLTHROUGH*/
20381+ case AuWbrCreate_MFS:
20382+ case AuWbrCreate_MFSV:
20383+ case AuWbrCreate_PMFS:
20384+ case AuWbrCreate_PMFSV:
e49829fe
JR
20385+ sbinfo->si_wbr_mfs.mfs_expire
20386+ = msecs_to_jiffies(create->mfs_second * MSEC_PER_SEC);
1facf9fc 20387+ break;
20388+ }
20389+
20390+ if (sbinfo->si_wbr_create_ops->init)
20391+ sbinfo->si_wbr_create_ops->init(sb); /* ignore */
20392+
20393+ return err;
20394+}
20395+
20396+/*
20397+ * returns,
20398+ * plus: processed without an error
20399+ * zero: unprocessed
20400+ */
20401+static int au_opt_simple(struct super_block *sb, struct au_opt *opt,
20402+ struct au_opts *opts)
20403+{
20404+ int err;
20405+ struct au_sbinfo *sbinfo;
20406+
dece6358
AM
20407+ SiMustWriteLock(sb);
20408+
1facf9fc 20409+ err = 1; /* handled */
20410+ sbinfo = au_sbi(sb);
20411+ switch (opt->type) {
20412+ case Opt_udba:
20413+ sbinfo->si_mntflags &= ~AuOptMask_UDBA;
20414+ sbinfo->si_mntflags |= opt->udba;
20415+ opts->given_udba |= opt->udba;
20416+ break;
20417+
20418+ case Opt_plink:
20419+ au_opt_set(sbinfo->si_mntflags, PLINK);
20420+ break;
20421+ case Opt_noplink:
20422+ if (au_opt_test(sbinfo->si_mntflags, PLINK))
e49829fe 20423+ au_plink_put(sb, /*verbose*/1);
1facf9fc 20424+ au_opt_clr(sbinfo->si_mntflags, PLINK);
20425+ break;
20426+ case Opt_list_plink:
20427+ if (au_opt_test(sbinfo->si_mntflags, PLINK))
20428+ au_plink_list(sb);
20429+ break;
20430+
4a4d8108
AM
20431+ case Opt_dio:
20432+ au_opt_set(sbinfo->si_mntflags, DIO);
20433+ au_fset_opts(opts->flags, REFRESH_DYAOP);
20434+ break;
20435+ case Opt_nodio:
20436+ au_opt_clr(sbinfo->si_mntflags, DIO);
20437+ au_fset_opts(opts->flags, REFRESH_DYAOP);
20438+ break;
20439+
1facf9fc 20440+ case Opt_diropq_a:
20441+ au_opt_set(sbinfo->si_mntflags, ALWAYS_DIROPQ);
20442+ break;
20443+ case Opt_diropq_w:
20444+ au_opt_clr(sbinfo->si_mntflags, ALWAYS_DIROPQ);
20445+ break;
20446+
20447+ case Opt_warn_perm:
20448+ au_opt_set(sbinfo->si_mntflags, WARN_PERM);
20449+ break;
20450+ case Opt_nowarn_perm:
20451+ au_opt_clr(sbinfo->si_mntflags, WARN_PERM);
20452+ break;
20453+
20454+ case Opt_refrof:
20455+ au_opt_set(sbinfo->si_mntflags, REFROF);
20456+ break;
20457+ case Opt_norefrof:
20458+ au_opt_clr(sbinfo->si_mntflags, REFROF);
20459+ break;
20460+
20461+ case Opt_verbose:
20462+ au_opt_set(sbinfo->si_mntflags, VERBOSE);
20463+ break;
20464+ case Opt_noverbose:
20465+ au_opt_clr(sbinfo->si_mntflags, VERBOSE);
20466+ break;
20467+
20468+ case Opt_sum:
20469+ au_opt_set(sbinfo->si_mntflags, SUM);
20470+ break;
20471+ case Opt_wsum:
20472+ au_opt_clr(sbinfo->si_mntflags, SUM);
20473+ au_opt_set(sbinfo->si_mntflags, SUM_W);
20474+ case Opt_nosum:
20475+ au_opt_clr(sbinfo->si_mntflags, SUM);
20476+ au_opt_clr(sbinfo->si_mntflags, SUM_W);
20477+ break;
20478+
20479+ case Opt_wbr_create:
20480+ err = au_opt_wbr_create(sb, &opt->wbr_create);
20481+ break;
20482+ case Opt_wbr_copyup:
20483+ sbinfo->si_wbr_copyup = opt->wbr_copyup;
20484+ sbinfo->si_wbr_copyup_ops = au_wbr_copyup_ops + opt->wbr_copyup;
20485+ break;
20486+
20487+ case Opt_dirwh:
20488+ sbinfo->si_dirwh = opt->dirwh;
20489+ break;
20490+
20491+ case Opt_rdcache:
e49829fe
JR
20492+ sbinfo->si_rdcache
20493+ = msecs_to_jiffies(opt->rdcache * MSEC_PER_SEC);
1facf9fc 20494+ break;
20495+ case Opt_rdblk:
20496+ sbinfo->si_rdblk = opt->rdblk;
20497+ break;
dece6358
AM
20498+ case Opt_rdblk_def:
20499+ sbinfo->si_rdblk = AUFS_RDBLK_DEF;
20500+ break;
1facf9fc 20501+ case Opt_rdhash:
20502+ sbinfo->si_rdhash = opt->rdhash;
20503+ break;
dece6358
AM
20504+ case Opt_rdhash_def:
20505+ sbinfo->si_rdhash = AUFS_RDHASH_DEF;
20506+ break;
20507+
20508+ case Opt_shwh:
20509+ au_opt_set(sbinfo->si_mntflags, SHWH);
20510+ break;
20511+ case Opt_noshwh:
20512+ au_opt_clr(sbinfo->si_mntflags, SHWH);
20513+ break;
1facf9fc 20514+
20515+ case Opt_trunc_xino:
20516+ au_opt_set(sbinfo->si_mntflags, TRUNC_XINO);
20517+ break;
20518+ case Opt_notrunc_xino:
20519+ au_opt_clr(sbinfo->si_mntflags, TRUNC_XINO);
20520+ break;
20521+
20522+ case Opt_trunc_xino_path:
20523+ case Opt_itrunc_xino:
20524+ err = au_xino_trunc(sb, opt->xino_itrunc.bindex);
20525+ if (!err)
20526+ err = 1;
20527+ break;
20528+
20529+ case Opt_trunc_xib:
20530+ au_fset_opts(opts->flags, TRUNC_XIB);
20531+ break;
20532+ case Opt_notrunc_xib:
20533+ au_fclr_opts(opts->flags, TRUNC_XIB);
20534+ break;
20535+
20536+ default:
20537+ err = 0;
20538+ break;
20539+ }
20540+
20541+ return err;
20542+}
20543+
20544+/*
20545+ * returns tri-state.
20546+ * plus: processed without an error
20547+ * zero: unprocessed
20548+ * minus: error
20549+ */
20550+static int au_opt_br(struct super_block *sb, struct au_opt *opt,
20551+ struct au_opts *opts)
20552+{
20553+ int err, do_refresh;
20554+
20555+ err = 0;
20556+ switch (opt->type) {
20557+ case Opt_append:
20558+ opt->add.bindex = au_sbend(sb) + 1;
20559+ if (opt->add.bindex < 0)
20560+ opt->add.bindex = 0;
20561+ goto add;
20562+ case Opt_prepend:
20563+ opt->add.bindex = 0;
20564+ add:
20565+ case Opt_add:
20566+ err = au_br_add(sb, &opt->add,
20567+ au_ftest_opts(opts->flags, REMOUNT));
20568+ if (!err) {
20569+ err = 1;
027c5e7a 20570+ au_fset_opts(opts->flags, REFRESH);
1facf9fc 20571+ }
20572+ break;
20573+
20574+ case Opt_del:
20575+ case Opt_idel:
20576+ err = au_br_del(sb, &opt->del,
20577+ au_ftest_opts(opts->flags, REMOUNT));
20578+ if (!err) {
20579+ err = 1;
20580+ au_fset_opts(opts->flags, TRUNC_XIB);
027c5e7a 20581+ au_fset_opts(opts->flags, REFRESH);
1facf9fc 20582+ }
20583+ break;
20584+
20585+ case Opt_mod:
20586+ case Opt_imod:
20587+ err = au_br_mod(sb, &opt->mod,
20588+ au_ftest_opts(opts->flags, REMOUNT),
20589+ &do_refresh);
20590+ if (!err) {
20591+ err = 1;
027c5e7a
AM
20592+ if (do_refresh)
20593+ au_fset_opts(opts->flags, REFRESH);
1facf9fc 20594+ }
20595+ break;
20596+ }
20597+
20598+ return err;
20599+}
20600+
20601+static int au_opt_xino(struct super_block *sb, struct au_opt *opt,
20602+ struct au_opt_xino **opt_xino,
20603+ struct au_opts *opts)
20604+{
20605+ int err;
20606+ aufs_bindex_t bend, bindex;
20607+ struct dentry *root, *parent, *h_root;
20608+
20609+ err = 0;
20610+ switch (opt->type) {
20611+ case Opt_xino:
20612+ err = au_xino_set(sb, &opt->xino,
20613+ !!au_ftest_opts(opts->flags, REMOUNT));
20614+ if (unlikely(err))
20615+ break;
20616+
20617+ *opt_xino = &opt->xino;
20618+ au_xino_brid_set(sb, -1);
20619+
20620+ /* safe d_parent access */
20621+ parent = opt->xino.file->f_dentry->d_parent;
20622+ root = sb->s_root;
20623+ bend = au_sbend(sb);
20624+ for (bindex = 0; bindex <= bend; bindex++) {
20625+ h_root = au_h_dptr(root, bindex);
20626+ if (h_root == parent) {
20627+ au_xino_brid_set(sb, au_sbr_id(sb, bindex));
20628+ break;
20629+ }
20630+ }
20631+ break;
20632+
20633+ case Opt_noxino:
20634+ au_xino_clr(sb);
20635+ au_xino_brid_set(sb, -1);
20636+ *opt_xino = (void *)-1;
20637+ break;
20638+ }
20639+
20640+ return err;
20641+}
20642+
20643+int au_opts_verify(struct super_block *sb, unsigned long sb_flags,
20644+ unsigned int pending)
20645+{
20646+ int err;
20647+ aufs_bindex_t bindex, bend;
20648+ unsigned char do_plink, skip, do_free;
20649+ struct au_branch *br;
20650+ struct au_wbr *wbr;
20651+ struct dentry *root;
20652+ struct inode *dir, *h_dir;
20653+ struct au_sbinfo *sbinfo;
20654+ struct au_hinode *hdir;
20655+
dece6358
AM
20656+ SiMustAnyLock(sb);
20657+
1facf9fc 20658+ sbinfo = au_sbi(sb);
20659+ AuDebugOn(!(sbinfo->si_mntflags & AuOptMask_UDBA));
20660+
dece6358
AM
20661+ if (!(sb_flags & MS_RDONLY)) {
20662+ if (unlikely(!au_br_writable(au_sbr_perm(sb, 0))))
0c3ec466 20663+ pr_warn("first branch should be rw\n");
dece6358 20664+ if (unlikely(au_opt_test(sbinfo->si_mntflags, SHWH)))
0c3ec466 20665+ pr_warn("shwh should be used with ro\n");
dece6358 20666+ }
1facf9fc 20667+
4a4d8108 20668+ if (au_opt_test((sbinfo->si_mntflags | pending), UDBA_HNOTIFY)
1facf9fc 20669+ && !au_opt_test(sbinfo->si_mntflags, XINO))
0c3ec466 20670+ pr_warn("udba=*notify requires xino\n");
1facf9fc 20671+
20672+ err = 0;
20673+ root = sb->s_root;
4a4d8108 20674+ dir = root->d_inode;
1facf9fc 20675+ do_plink = !!au_opt_test(sbinfo->si_mntflags, PLINK);
20676+ bend = au_sbend(sb);
20677+ for (bindex = 0; !err && bindex <= bend; bindex++) {
20678+ skip = 0;
20679+ h_dir = au_h_iptr(dir, bindex);
20680+ br = au_sbr(sb, bindex);
20681+ do_free = 0;
20682+
20683+ wbr = br->br_wbr;
20684+ if (wbr)
20685+ wbr_wh_read_lock(wbr);
20686+
1e00d052 20687+ if (!au_br_writable(br->br_perm)) {
1facf9fc 20688+ do_free = !!wbr;
20689+ skip = (!wbr
20690+ || (!wbr->wbr_whbase
20691+ && !wbr->wbr_plink
20692+ && !wbr->wbr_orph));
1e00d052 20693+ } else if (!au_br_wh_linkable(br->br_perm)) {
1facf9fc 20694+ /* skip = (!br->br_whbase && !br->br_orph); */
20695+ skip = (!wbr || !wbr->wbr_whbase);
20696+ if (skip && wbr) {
20697+ if (do_plink)
20698+ skip = !!wbr->wbr_plink;
20699+ else
20700+ skip = !wbr->wbr_plink;
20701+ }
1e00d052 20702+ } else {
1facf9fc 20703+ /* skip = (br->br_whbase && br->br_ohph); */
20704+ skip = (wbr && wbr->wbr_whbase);
20705+ if (skip) {
20706+ if (do_plink)
20707+ skip = !!wbr->wbr_plink;
20708+ else
20709+ skip = !wbr->wbr_plink;
20710+ }
1facf9fc 20711+ }
20712+ if (wbr)
20713+ wbr_wh_read_unlock(wbr);
20714+
20715+ if (skip)
20716+ continue;
20717+
20718+ hdir = au_hi(dir, bindex);
4a4d8108 20719+ au_hn_imtx_lock_nested(hdir, AuLsc_I_PARENT);
1facf9fc 20720+ if (wbr)
20721+ wbr_wh_write_lock(wbr);
20722+ err = au_wh_init(au_h_dptr(root, bindex), br, sb);
20723+ if (wbr)
20724+ wbr_wh_write_unlock(wbr);
4a4d8108 20725+ au_hn_imtx_unlock(hdir);
1facf9fc 20726+
20727+ if (!err && do_free) {
20728+ kfree(wbr);
20729+ br->br_wbr = NULL;
20730+ }
20731+ }
20732+
20733+ return err;
20734+}
20735+
20736+int au_opts_mount(struct super_block *sb, struct au_opts *opts)
20737+{
20738+ int err;
20739+ unsigned int tmp;
027c5e7a 20740+ aufs_bindex_t bindex, bend;
1facf9fc 20741+ struct au_opt *opt;
20742+ struct au_opt_xino *opt_xino, xino;
20743+ struct au_sbinfo *sbinfo;
027c5e7a 20744+ struct au_branch *br;
1facf9fc 20745+
dece6358
AM
20746+ SiMustWriteLock(sb);
20747+
1facf9fc 20748+ err = 0;
20749+ opt_xino = NULL;
20750+ opt = opts->opt;
20751+ while (err >= 0 && opt->type != Opt_tail)
20752+ err = au_opt_simple(sb, opt++, opts);
20753+ if (err > 0)
20754+ err = 0;
20755+ else if (unlikely(err < 0))
20756+ goto out;
20757+
20758+ /* disable xino and udba temporary */
20759+ sbinfo = au_sbi(sb);
20760+ tmp = sbinfo->si_mntflags;
20761+ au_opt_clr(sbinfo->si_mntflags, XINO);
20762+ au_opt_set_udba(sbinfo->si_mntflags, UDBA_REVAL);
20763+
20764+ opt = opts->opt;
20765+ while (err >= 0 && opt->type != Opt_tail)
20766+ err = au_opt_br(sb, opt++, opts);
20767+ if (err > 0)
20768+ err = 0;
20769+ else if (unlikely(err < 0))
20770+ goto out;
20771+
20772+ bend = au_sbend(sb);
20773+ if (unlikely(bend < 0)) {
20774+ err = -EINVAL;
4a4d8108 20775+ pr_err("no branches\n");
1facf9fc 20776+ goto out;
20777+ }
20778+
20779+ if (au_opt_test(tmp, XINO))
20780+ au_opt_set(sbinfo->si_mntflags, XINO);
20781+ opt = opts->opt;
20782+ while (!err && opt->type != Opt_tail)
20783+ err = au_opt_xino(sb, opt++, &opt_xino, opts);
20784+ if (unlikely(err))
20785+ goto out;
20786+
20787+ err = au_opts_verify(sb, sb->s_flags, tmp);
20788+ if (unlikely(err))
20789+ goto out;
20790+
20791+ /* restore xino */
20792+ if (au_opt_test(tmp, XINO) && !opt_xino) {
20793+ xino.file = au_xino_def(sb);
20794+ err = PTR_ERR(xino.file);
20795+ if (IS_ERR(xino.file))
20796+ goto out;
20797+
20798+ err = au_xino_set(sb, &xino, /*remount*/0);
20799+ fput(xino.file);
20800+ if (unlikely(err))
20801+ goto out;
20802+ }
20803+
20804+ /* restore udba */
027c5e7a 20805+ tmp &= AuOptMask_UDBA;
1facf9fc 20806+ sbinfo->si_mntflags &= ~AuOptMask_UDBA;
027c5e7a
AM
20807+ sbinfo->si_mntflags |= tmp;
20808+ bend = au_sbend(sb);
20809+ for (bindex = 0; bindex <= bend; bindex++) {
20810+ br = au_sbr(sb, bindex);
20811+ err = au_hnotify_reset_br(tmp, br, br->br_perm);
20812+ if (unlikely(err))
20813+ AuIOErr("hnotify failed on br %d, %d, ignored\n",
20814+ bindex, err);
20815+ /* go on even if err */
20816+ }
4a4d8108 20817+ if (au_opt_test(tmp, UDBA_HNOTIFY)) {
1facf9fc 20818+ struct inode *dir = sb->s_root->d_inode;
4a4d8108 20819+ au_hn_reset(dir, au_hi_flags(dir, /*isdir*/1) & ~AuHi_XINO);
1facf9fc 20820+ }
20821+
4f0767ce 20822+out:
1facf9fc 20823+ return err;
20824+}
20825+
20826+int au_opts_remount(struct super_block *sb, struct au_opts *opts)
20827+{
20828+ int err, rerr;
20829+ struct inode *dir;
20830+ struct au_opt_xino *opt_xino;
20831+ struct au_opt *opt;
20832+ struct au_sbinfo *sbinfo;
20833+
dece6358
AM
20834+ SiMustWriteLock(sb);
20835+
1facf9fc 20836+ dir = sb->s_root->d_inode;
20837+ sbinfo = au_sbi(sb);
20838+ err = 0;
20839+ opt_xino = NULL;
20840+ opt = opts->opt;
20841+ while (err >= 0 && opt->type != Opt_tail) {
20842+ err = au_opt_simple(sb, opt, opts);
20843+ if (!err)
20844+ err = au_opt_br(sb, opt, opts);
20845+ if (!err)
20846+ err = au_opt_xino(sb, opt, &opt_xino, opts);
20847+ opt++;
20848+ }
20849+ if (err > 0)
20850+ err = 0;
20851+ AuTraceErr(err);
20852+ /* go on even err */
20853+
20854+ rerr = au_opts_verify(sb, opts->sb_flags, /*pending*/0);
20855+ if (unlikely(rerr && !err))
20856+ err = rerr;
20857+
20858+ if (au_ftest_opts(opts->flags, TRUNC_XIB)) {
20859+ rerr = au_xib_trunc(sb);
20860+ if (unlikely(rerr && !err))
20861+ err = rerr;
20862+ }
20863+
20864+ /* will be handled by the caller */
027c5e7a 20865+ if (!au_ftest_opts(opts->flags, REFRESH)
1facf9fc 20866+ && (opts->given_udba || au_opt_test(sbinfo->si_mntflags, XINO)))
027c5e7a 20867+ au_fset_opts(opts->flags, REFRESH);
1facf9fc 20868+
20869+ AuDbg("status 0x%x\n", opts->flags);
20870+ return err;
20871+}
20872+
20873+/* ---------------------------------------------------------------------- */
20874+
20875+unsigned int au_opt_udba(struct super_block *sb)
20876+{
20877+ return au_mntflags(sb) & AuOptMask_UDBA;
20878+}
7f207e10
AM
20879diff -urN /usr/share/empty/fs/aufs/opts.h linux/fs/aufs/opts.h
20880--- /usr/share/empty/fs/aufs/opts.h 1970-01-01 01:00:00.000000000 +0100
0c3ec466 20881+++ linux/fs/aufs/opts.h 2012-07-22 19:57:03.164337936 +0200
f6c5ef8b 20882@@ -0,0 +1,209 @@
1facf9fc 20883+/*
f6c5ef8b 20884+ * Copyright (C) 2005-2012 Junjiro R. Okajima
1facf9fc 20885+ *
20886+ * This program, aufs is free software; you can redistribute it and/or modify
20887+ * it under the terms of the GNU General Public License as published by
20888+ * the Free Software Foundation; either version 2 of the License, or
20889+ * (at your option) any later version.
dece6358
AM
20890+ *
20891+ * This program is distributed in the hope that it will be useful,
20892+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
20893+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20894+ * GNU General Public License for more details.
20895+ *
20896+ * You should have received a copy of the GNU General Public License
20897+ * along with this program; if not, write to the Free Software
20898+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 20899+ */
20900+
20901+/*
20902+ * mount options/flags
20903+ */
20904+
20905+#ifndef __AUFS_OPTS_H__
20906+#define __AUFS_OPTS_H__
20907+
20908+#ifdef __KERNEL__
20909+
dece6358 20910+#include <linux/path.h>
1facf9fc 20911+
dece6358
AM
20912+struct file;
20913+struct super_block;
20914+
1facf9fc 20915+/* ---------------------------------------------------------------------- */
20916+
20917+/* mount flags */
20918+#define AuOpt_XINO 1 /* external inode number bitmap
20919+ and translation table */
20920+#define AuOpt_TRUNC_XINO (1 << 1) /* truncate xino files */
20921+#define AuOpt_UDBA_NONE (1 << 2) /* users direct branch access */
20922+#define AuOpt_UDBA_REVAL (1 << 3)
4a4d8108 20923+#define AuOpt_UDBA_HNOTIFY (1 << 4)
dece6358
AM
20924+#define AuOpt_SHWH (1 << 5) /* show whiteout */
20925+#define AuOpt_PLINK (1 << 6) /* pseudo-link */
20926+#define AuOpt_DIRPERM1 (1 << 7) /* unimplemented */
20927+#define AuOpt_REFROF (1 << 8) /* unimplemented */
20928+#define AuOpt_ALWAYS_DIROPQ (1 << 9) /* policy to creating diropq */
20929+#define AuOpt_SUM (1 << 10) /* summation for statfs(2) */
20930+#define AuOpt_SUM_W (1 << 11) /* unimplemented */
20931+#define AuOpt_WARN_PERM (1 << 12) /* warn when add-branch */
20932+#define AuOpt_VERBOSE (1 << 13) /* busy inode when del-branch */
4a4d8108 20933+#define AuOpt_DIO (1 << 14) /* direct io */
1facf9fc 20934+
4a4d8108
AM
20935+#ifndef CONFIG_AUFS_HNOTIFY
20936+#undef AuOpt_UDBA_HNOTIFY
20937+#define AuOpt_UDBA_HNOTIFY 0
1facf9fc 20938+#endif
dece6358
AM
20939+#ifndef CONFIG_AUFS_SHWH
20940+#undef AuOpt_SHWH
20941+#define AuOpt_SHWH 0
20942+#endif
1facf9fc 20943+
20944+#define AuOpt_Def (AuOpt_XINO \
20945+ | AuOpt_UDBA_REVAL \
20946+ | AuOpt_PLINK \
20947+ /* | AuOpt_DIRPERM1 */ \
20948+ | AuOpt_WARN_PERM)
20949+#define AuOptMask_UDBA (AuOpt_UDBA_NONE \
20950+ | AuOpt_UDBA_REVAL \
4a4d8108 20951+ | AuOpt_UDBA_HNOTIFY)
1facf9fc 20952+
20953+#define au_opt_test(flags, name) (flags & AuOpt_##name)
20954+#define au_opt_set(flags, name) do { \
20955+ BUILD_BUG_ON(AuOpt_##name & AuOptMask_UDBA); \
20956+ ((flags) |= AuOpt_##name); \
20957+} while (0)
20958+#define au_opt_set_udba(flags, name) do { \
20959+ (flags) &= ~AuOptMask_UDBA; \
20960+ ((flags) |= AuOpt_##name); \
20961+} while (0)
7f207e10
AM
20962+#define au_opt_clr(flags, name) do { \
20963+ ((flags) &= ~AuOpt_##name); \
20964+} while (0)
1facf9fc 20965+
e49829fe
JR
20966+static inline unsigned int au_opts_plink(unsigned int mntflags)
20967+{
20968+#ifdef CONFIG_PROC_FS
20969+ return mntflags;
20970+#else
20971+ return mntflags & ~AuOpt_PLINK;
20972+#endif
20973+}
20974+
1facf9fc 20975+/* ---------------------------------------------------------------------- */
20976+
20977+/* policies to select one among multiple writable branches */
20978+enum {
20979+ AuWbrCreate_TDP, /* top down parent */
20980+ AuWbrCreate_RR, /* round robin */
20981+ AuWbrCreate_MFS, /* most free space */
20982+ AuWbrCreate_MFSV, /* mfs with seconds */
20983+ AuWbrCreate_MFSRR, /* mfs then rr */
20984+ AuWbrCreate_MFSRRV, /* mfs then rr with seconds */
20985+ AuWbrCreate_PMFS, /* parent and mfs */
20986+ AuWbrCreate_PMFSV, /* parent and mfs with seconds */
20987+
20988+ AuWbrCreate_Def = AuWbrCreate_TDP
20989+};
20990+
20991+enum {
20992+ AuWbrCopyup_TDP, /* top down parent */
20993+ AuWbrCopyup_BUP, /* bottom up parent */
20994+ AuWbrCopyup_BU, /* bottom up */
20995+
20996+ AuWbrCopyup_Def = AuWbrCopyup_TDP
20997+};
20998+
20999+/* ---------------------------------------------------------------------- */
21000+
21001+struct au_opt_add {
21002+ aufs_bindex_t bindex;
21003+ char *pathname;
21004+ int perm;
21005+ struct path path;
21006+};
21007+
21008+struct au_opt_del {
21009+ char *pathname;
21010+ struct path h_path;
21011+};
21012+
21013+struct au_opt_mod {
21014+ char *path;
21015+ int perm;
21016+ struct dentry *h_root;
21017+};
21018+
21019+struct au_opt_xino {
21020+ char *path;
21021+ struct file *file;
21022+};
21023+
21024+struct au_opt_xino_itrunc {
21025+ aufs_bindex_t bindex;
21026+};
21027+
21028+struct au_opt_wbr_create {
21029+ int wbr_create;
21030+ int mfs_second;
21031+ unsigned long long mfsrr_watermark;
21032+};
21033+
21034+struct au_opt {
21035+ int type;
21036+ union {
21037+ struct au_opt_xino xino;
21038+ struct au_opt_xino_itrunc xino_itrunc;
21039+ struct au_opt_add add;
21040+ struct au_opt_del del;
21041+ struct au_opt_mod mod;
21042+ int dirwh;
21043+ int rdcache;
21044+ unsigned int rdblk;
21045+ unsigned int rdhash;
21046+ int udba;
21047+ struct au_opt_wbr_create wbr_create;
21048+ int wbr_copyup;
21049+ };
21050+};
21051+
21052+/* opts flags */
21053+#define AuOpts_REMOUNT 1
027c5e7a
AM
21054+#define AuOpts_REFRESH (1 << 1)
21055+#define AuOpts_TRUNC_XIB (1 << 2)
21056+#define AuOpts_REFRESH_DYAOP (1 << 3)
1facf9fc 21057+#define au_ftest_opts(flags, name) ((flags) & AuOpts_##name)
7f207e10
AM
21058+#define au_fset_opts(flags, name) \
21059+ do { (flags) |= AuOpts_##name; } while (0)
21060+#define au_fclr_opts(flags, name) \
21061+ do { (flags) &= ~AuOpts_##name; } while (0)
1facf9fc 21062+
21063+struct au_opts {
21064+ struct au_opt *opt;
21065+ int max_opt;
21066+
21067+ unsigned int given_udba;
21068+ unsigned int flags;
21069+ unsigned long sb_flags;
21070+};
21071+
21072+/* ---------------------------------------------------------------------- */
21073+
1e00d052 21074+char *au_optstr_br_perm(int brperm);
1facf9fc 21075+const char *au_optstr_udba(int udba);
21076+const char *au_optstr_wbr_copyup(int wbr_copyup);
21077+const char *au_optstr_wbr_create(int wbr_create);
21078+
21079+void au_opts_free(struct au_opts *opts);
21080+int au_opts_parse(struct super_block *sb, char *str, struct au_opts *opts);
21081+int au_opts_verify(struct super_block *sb, unsigned long sb_flags,
21082+ unsigned int pending);
21083+int au_opts_mount(struct super_block *sb, struct au_opts *opts);
21084+int au_opts_remount(struct super_block *sb, struct au_opts *opts);
21085+
21086+unsigned int au_opt_udba(struct super_block *sb);
21087+
21088+/* ---------------------------------------------------------------------- */
21089+
21090+#endif /* __KERNEL__ */
21091+#endif /* __AUFS_OPTS_H__ */
7f207e10
AM
21092diff -urN /usr/share/empty/fs/aufs/plink.c linux/fs/aufs/plink.c
21093--- /usr/share/empty/fs/aufs/plink.c 1970-01-01 01:00:00.000000000 +0100
0c3ec466
AM
21094+++ linux/fs/aufs/plink.c 2012-07-22 19:57:03.164337936 +0200
21095@@ -0,0 +1,511 @@
1facf9fc 21096+/*
f6c5ef8b 21097+ * Copyright (C) 2005-2012 Junjiro R. Okajima
1facf9fc 21098+ *
21099+ * This program, aufs is free software; you can redistribute it and/or modify
21100+ * it under the terms of the GNU General Public License as published by
21101+ * the Free Software Foundation; either version 2 of the License, or
21102+ * (at your option) any later version.
dece6358
AM
21103+ *
21104+ * This program is distributed in the hope that it will be useful,
21105+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
21106+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21107+ * GNU General Public License for more details.
21108+ *
21109+ * You should have received a copy of the GNU General Public License
21110+ * along with this program; if not, write to the Free Software
21111+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 21112+ */
21113+
21114+/*
21115+ * pseudo-link
21116+ */
21117+
21118+#include "aufs.h"
21119+
21120+/*
e49829fe 21121+ * the pseudo-link maintenance mode.
1facf9fc 21122+ * during a user process maintains the pseudo-links,
21123+ * prohibit adding a new plink and branch manipulation.
e49829fe
JR
21124+ *
21125+ * Flags
21126+ * NOPLM:
21127+ * For entry functions which will handle plink, and i_mutex is already held
21128+ * in VFS.
21129+ * They cannot wait and should return an error at once.
21130+ * Callers has to check the error.
21131+ * NOPLMW:
21132+ * For entry functions which will handle plink, but i_mutex is not held
21133+ * in VFS.
21134+ * They can wait the plink maintenance mode to finish.
21135+ *
21136+ * They behave like F_SETLK and F_SETLKW.
21137+ * If the caller never handle plink, then both flags are unnecessary.
1facf9fc 21138+ */
e49829fe
JR
21139+
21140+int au_plink_maint(struct super_block *sb, int flags)
1facf9fc 21141+{
e49829fe
JR
21142+ int err;
21143+ pid_t pid, ppid;
21144+ struct au_sbinfo *sbi;
dece6358
AM
21145+
21146+ SiMustAnyLock(sb);
21147+
e49829fe
JR
21148+ err = 0;
21149+ if (!au_opt_test(au_mntflags(sb), PLINK))
21150+ goto out;
21151+
21152+ sbi = au_sbi(sb);
21153+ pid = sbi->si_plink_maint_pid;
21154+ if (!pid || pid == current->pid)
21155+ goto out;
21156+
21157+ /* todo: it highly depends upon /sbin/mount.aufs */
21158+ rcu_read_lock();
21159+ ppid = task_pid_vnr(rcu_dereference(current->real_parent));
21160+ rcu_read_unlock();
21161+ if (pid == ppid)
21162+ goto out;
21163+
21164+ if (au_ftest_lock(flags, NOPLMW)) {
027c5e7a
AM
21165+ /* if there is no i_mutex lock in VFS, we don't need to wait */
21166+ /* AuDebugOn(!lockdep_depth(current)); */
e49829fe
JR
21167+ while (sbi->si_plink_maint_pid) {
21168+ si_read_unlock(sb);
21169+ /* gave up wake_up_bit() */
21170+ wait_event(sbi->si_plink_wq, !sbi->si_plink_maint_pid);
21171+
21172+ if (au_ftest_lock(flags, FLUSH))
21173+ au_nwt_flush(&sbi->si_nowait);
21174+ si_noflush_read_lock(sb);
21175+ }
21176+ } else if (au_ftest_lock(flags, NOPLM)) {
21177+ AuDbg("ppid %d, pid %d\n", ppid, pid);
21178+ err = -EAGAIN;
21179+ }
21180+
21181+out:
21182+ return err;
4a4d8108
AM
21183+}
21184+
e49829fe 21185+void au_plink_maint_leave(struct au_sbinfo *sbinfo)
4a4d8108 21186+{
4a4d8108 21187+ spin_lock(&sbinfo->si_plink_maint_lock);
027c5e7a 21188+ sbinfo->si_plink_maint_pid = 0;
4a4d8108 21189+ spin_unlock(&sbinfo->si_plink_maint_lock);
027c5e7a 21190+ wake_up_all(&sbinfo->si_plink_wq);
4a4d8108
AM
21191+}
21192+
e49829fe 21193+int au_plink_maint_enter(struct super_block *sb)
4a4d8108
AM
21194+{
21195+ int err;
4a4d8108
AM
21196+ struct au_sbinfo *sbinfo;
21197+
21198+ err = 0;
4a4d8108
AM
21199+ sbinfo = au_sbi(sb);
21200+ /* make sure i am the only one in this fs */
e49829fe
JR
21201+ si_write_lock(sb, AuLock_FLUSH);
21202+ if (au_opt_test(au_mntflags(sb), PLINK)) {
21203+ spin_lock(&sbinfo->si_plink_maint_lock);
21204+ if (!sbinfo->si_plink_maint_pid)
21205+ sbinfo->si_plink_maint_pid = current->pid;
21206+ else
21207+ err = -EBUSY;
21208+ spin_unlock(&sbinfo->si_plink_maint_lock);
21209+ }
4a4d8108
AM
21210+ si_write_unlock(sb);
21211+
21212+ return err;
1facf9fc 21213+}
21214+
21215+/* ---------------------------------------------------------------------- */
21216+
21217+struct pseudo_link {
4a4d8108
AM
21218+ union {
21219+ struct list_head list;
21220+ struct rcu_head rcu;
21221+ };
1facf9fc 21222+ struct inode *inode;
21223+};
21224+
21225+#ifdef CONFIG_AUFS_DEBUG
21226+void au_plink_list(struct super_block *sb)
21227+{
21228+ struct au_sbinfo *sbinfo;
21229+ struct list_head *plink_list;
21230+ struct pseudo_link *plink;
21231+
dece6358
AM
21232+ SiMustAnyLock(sb);
21233+
1facf9fc 21234+ sbinfo = au_sbi(sb);
21235+ AuDebugOn(!au_opt_test(au_mntflags(sb), PLINK));
e49829fe 21236+ AuDebugOn(au_plink_maint(sb, AuLock_NOPLM));
1facf9fc 21237+
21238+ plink_list = &sbinfo->si_plink.head;
4a4d8108
AM
21239+ rcu_read_lock();
21240+ list_for_each_entry_rcu(plink, plink_list, list)
1facf9fc 21241+ AuDbg("%lu\n", plink->inode->i_ino);
4a4d8108 21242+ rcu_read_unlock();
1facf9fc 21243+}
21244+#endif
21245+
21246+/* is the inode pseudo-linked? */
21247+int au_plink_test(struct inode *inode)
21248+{
21249+ int found;
21250+ struct au_sbinfo *sbinfo;
21251+ struct list_head *plink_list;
21252+ struct pseudo_link *plink;
21253+
21254+ sbinfo = au_sbi(inode->i_sb);
dece6358 21255+ AuRwMustAnyLock(&sbinfo->si_rwsem);
1facf9fc 21256+ AuDebugOn(!au_opt_test(au_mntflags(inode->i_sb), PLINK));
e49829fe 21257+ AuDebugOn(au_plink_maint(inode->i_sb, AuLock_NOPLM));
1facf9fc 21258+
21259+ found = 0;
21260+ plink_list = &sbinfo->si_plink.head;
4a4d8108
AM
21261+ rcu_read_lock();
21262+ list_for_each_entry_rcu(plink, plink_list, list)
1facf9fc 21263+ if (plink->inode == inode) {
21264+ found = 1;
21265+ break;
21266+ }
4a4d8108 21267+ rcu_read_unlock();
1facf9fc 21268+ return found;
21269+}
21270+
21271+/* ---------------------------------------------------------------------- */
21272+
21273+/*
21274+ * generate a name for plink.
21275+ * the file will be stored under AUFS_WH_PLINKDIR.
21276+ */
21277+/* 20 is max digits length of ulong 64 */
21278+#define PLINK_NAME_LEN ((20 + 1) * 2)
21279+
21280+static int plink_name(char *name, int len, struct inode *inode,
21281+ aufs_bindex_t bindex)
21282+{
21283+ int rlen;
21284+ struct inode *h_inode;
21285+
21286+ h_inode = au_h_iptr(inode, bindex);
21287+ rlen = snprintf(name, len, "%lu.%lu", inode->i_ino, h_inode->i_ino);
21288+ return rlen;
21289+}
21290+
7f207e10
AM
21291+struct au_do_plink_lkup_args {
21292+ struct dentry **errp;
21293+ struct qstr *tgtname;
21294+ struct dentry *h_parent;
21295+ struct au_branch *br;
21296+};
21297+
21298+static struct dentry *au_do_plink_lkup(struct qstr *tgtname,
21299+ struct dentry *h_parent,
21300+ struct au_branch *br)
21301+{
21302+ struct dentry *h_dentry;
21303+ struct mutex *h_mtx;
21304+
21305+ h_mtx = &h_parent->d_inode->i_mutex;
21306+ mutex_lock_nested(h_mtx, AuLsc_I_CHILD2);
21307+ h_dentry = au_lkup_one(tgtname, h_parent, br, /*nd*/NULL);
21308+ mutex_unlock(h_mtx);
21309+ return h_dentry;
21310+}
21311+
21312+static void au_call_do_plink_lkup(void *args)
21313+{
21314+ struct au_do_plink_lkup_args *a = args;
21315+ *a->errp = au_do_plink_lkup(a->tgtname, a->h_parent, a->br);
21316+}
21317+
1facf9fc 21318+/* lookup the plink-ed @inode under the branch at @bindex */
21319+struct dentry *au_plink_lkup(struct inode *inode, aufs_bindex_t bindex)
21320+{
21321+ struct dentry *h_dentry, *h_parent;
21322+ struct au_branch *br;
21323+ struct inode *h_dir;
7f207e10 21324+ int wkq_err;
1facf9fc 21325+ char a[PLINK_NAME_LEN];
0c3ec466 21326+ struct qstr tgtname = QSTR_INIT(a, 0);
1facf9fc 21327+
e49829fe
JR
21328+ AuDebugOn(au_plink_maint(inode->i_sb, AuLock_NOPLM));
21329+
1facf9fc 21330+ br = au_sbr(inode->i_sb, bindex);
21331+ h_parent = br->br_wbr->wbr_plink;
21332+ h_dir = h_parent->d_inode;
21333+ tgtname.len = plink_name(a, sizeof(a), inode, bindex);
21334+
0c3ec466 21335+ if (current_fsuid() != GLOBAL_ROOT_GID) {
7f207e10
AM
21336+ struct au_do_plink_lkup_args args = {
21337+ .errp = &h_dentry,
21338+ .tgtname = &tgtname,
21339+ .h_parent = h_parent,
21340+ .br = br
21341+ };
21342+
21343+ wkq_err = au_wkq_wait(au_call_do_plink_lkup, &args);
21344+ if (unlikely(wkq_err))
21345+ h_dentry = ERR_PTR(wkq_err);
21346+ } else
21347+ h_dentry = au_do_plink_lkup(&tgtname, h_parent, br);
21348+
1facf9fc 21349+ return h_dentry;
21350+}
21351+
21352+/* create a pseudo-link */
21353+static int do_whplink(struct qstr *tgt, struct dentry *h_parent,
21354+ struct dentry *h_dentry, struct au_branch *br)
21355+{
21356+ int err;
21357+ struct path h_path = {
21358+ .mnt = br->br_mnt
21359+ };
21360+ struct inode *h_dir;
21361+
21362+ h_dir = h_parent->d_inode;
7f207e10 21363+ mutex_lock_nested(&h_dir->i_mutex, AuLsc_I_CHILD2);
4f0767ce 21364+again:
1facf9fc 21365+ h_path.dentry = au_lkup_one(tgt, h_parent, br, /*nd*/NULL);
21366+ err = PTR_ERR(h_path.dentry);
21367+ if (IS_ERR(h_path.dentry))
21368+ goto out;
21369+
21370+ err = 0;
21371+ /* wh.plink dir is not monitored */
7f207e10 21372+ /* todo: is it really safe? */
1facf9fc 21373+ if (h_path.dentry->d_inode
21374+ && h_path.dentry->d_inode != h_dentry->d_inode) {
21375+ err = vfsub_unlink(h_dir, &h_path, /*force*/0);
21376+ dput(h_path.dentry);
21377+ h_path.dentry = NULL;
21378+ if (!err)
21379+ goto again;
21380+ }
21381+ if (!err && !h_path.dentry->d_inode)
21382+ err = vfsub_link(h_dentry, h_dir, &h_path);
21383+ dput(h_path.dentry);
21384+
4f0767ce 21385+out:
7f207e10 21386+ mutex_unlock(&h_dir->i_mutex);
1facf9fc 21387+ return err;
21388+}
21389+
21390+struct do_whplink_args {
21391+ int *errp;
21392+ struct qstr *tgt;
21393+ struct dentry *h_parent;
21394+ struct dentry *h_dentry;
21395+ struct au_branch *br;
21396+};
21397+
21398+static void call_do_whplink(void *args)
21399+{
21400+ struct do_whplink_args *a = args;
21401+ *a->errp = do_whplink(a->tgt, a->h_parent, a->h_dentry, a->br);
21402+}
21403+
21404+static int whplink(struct dentry *h_dentry, struct inode *inode,
21405+ aufs_bindex_t bindex, struct au_branch *br)
21406+{
21407+ int err, wkq_err;
21408+ struct au_wbr *wbr;
21409+ struct dentry *h_parent;
21410+ struct inode *h_dir;
21411+ char a[PLINK_NAME_LEN];
0c3ec466 21412+ struct qstr tgtname = QSTR_INIT(a, 0);
1facf9fc 21413+
21414+ wbr = au_sbr(inode->i_sb, bindex)->br_wbr;
21415+ h_parent = wbr->wbr_plink;
21416+ h_dir = h_parent->d_inode;
21417+ tgtname.len = plink_name(a, sizeof(a), inode, bindex);
21418+
21419+ /* always superio. */
0c3ec466 21420+ if (current_fsuid() != GLOBAL_ROOT_GID) {
1facf9fc 21421+ struct do_whplink_args args = {
21422+ .errp = &err,
21423+ .tgt = &tgtname,
21424+ .h_parent = h_parent,
21425+ .h_dentry = h_dentry,
21426+ .br = br
21427+ };
21428+ wkq_err = au_wkq_wait(call_do_whplink, &args);
21429+ if (unlikely(wkq_err))
21430+ err = wkq_err;
21431+ } else
21432+ err = do_whplink(&tgtname, h_parent, h_dentry, br);
1facf9fc 21433+
21434+ return err;
21435+}
21436+
21437+/* free a single plink */
21438+static void do_put_plink(struct pseudo_link *plink, int do_del)
21439+{
1facf9fc 21440+ if (do_del)
21441+ list_del(&plink->list);
4a4d8108
AM
21442+ iput(plink->inode);
21443+ kfree(plink);
21444+}
21445+
21446+static void do_put_plink_rcu(struct rcu_head *rcu)
21447+{
21448+ struct pseudo_link *plink;
21449+
21450+ plink = container_of(rcu, struct pseudo_link, rcu);
21451+ iput(plink->inode);
1facf9fc 21452+ kfree(plink);
21453+}
21454+
21455+/*
21456+ * create a new pseudo-link for @h_dentry on @bindex.
21457+ * the linked inode is held in aufs @inode.
21458+ */
21459+void au_plink_append(struct inode *inode, aufs_bindex_t bindex,
21460+ struct dentry *h_dentry)
21461+{
21462+ struct super_block *sb;
21463+ struct au_sbinfo *sbinfo;
21464+ struct list_head *plink_list;
4a4d8108 21465+ struct pseudo_link *plink, *tmp;
1facf9fc 21466+ int found, err, cnt;
21467+
21468+ sb = inode->i_sb;
21469+ sbinfo = au_sbi(sb);
21470+ AuDebugOn(!au_opt_test(au_mntflags(sb), PLINK));
e49829fe 21471+ AuDebugOn(au_plink_maint(sb, AuLock_NOPLM));
1facf9fc 21472+
1facf9fc 21473+ cnt = 0;
21474+ found = 0;
21475+ plink_list = &sbinfo->si_plink.head;
4a4d8108
AM
21476+ rcu_read_lock();
21477+ list_for_each_entry_rcu(plink, plink_list, list) {
1facf9fc 21478+ cnt++;
21479+ if (plink->inode == inode) {
21480+ found = 1;
21481+ break;
21482+ }
21483+ }
4a4d8108
AM
21484+ rcu_read_unlock();
21485+ if (found)
1facf9fc 21486+ return;
4a4d8108
AM
21487+
21488+ tmp = kmalloc(sizeof(*plink), GFP_NOFS);
21489+ if (tmp)
21490+ tmp->inode = au_igrab(inode);
21491+ else {
21492+ err = -ENOMEM;
21493+ goto out;
1facf9fc 21494+ }
21495+
4a4d8108
AM
21496+ spin_lock(&sbinfo->si_plink.spin);
21497+ list_for_each_entry(plink, plink_list, list) {
21498+ if (plink->inode == inode) {
21499+ found = 1;
21500+ break;
21501+ }
1facf9fc 21502+ }
4a4d8108
AM
21503+ if (!found)
21504+ list_add_rcu(&tmp->list, plink_list);
1facf9fc 21505+ spin_unlock(&sbinfo->si_plink.spin);
4a4d8108
AM
21506+ if (!found) {
21507+ cnt++;
21508+ WARN_ONCE(cnt > AUFS_PLINK_WARN,
21509+ "unexpectedly many pseudo links, %d\n", cnt);
1facf9fc 21510+ err = whplink(h_dentry, inode, bindex, au_sbr(sb, bindex));
4a4d8108
AM
21511+ } else {
21512+ do_put_plink(tmp, 0);
21513+ return;
1facf9fc 21514+ }
21515+
4a4d8108 21516+out:
1facf9fc 21517+ if (unlikely(err)) {
0c3ec466 21518+ pr_warn("err %d, damaged pseudo link.\n", err);
4a4d8108
AM
21519+ if (tmp) {
21520+ au_spl_del_rcu(&tmp->list, &sbinfo->si_plink);
21521+ call_rcu(&tmp->rcu, do_put_plink_rcu);
21522+ }
1facf9fc 21523+ }
21524+}
21525+
21526+/* free all plinks */
e49829fe 21527+void au_plink_put(struct super_block *sb, int verbose)
1facf9fc 21528+{
21529+ struct au_sbinfo *sbinfo;
21530+ struct list_head *plink_list;
21531+ struct pseudo_link *plink, *tmp;
21532+
dece6358
AM
21533+ SiMustWriteLock(sb);
21534+
1facf9fc 21535+ sbinfo = au_sbi(sb);
21536+ AuDebugOn(!au_opt_test(au_mntflags(sb), PLINK));
e49829fe 21537+ AuDebugOn(au_plink_maint(sb, AuLock_NOPLM));
1facf9fc 21538+
21539+ plink_list = &sbinfo->si_plink.head;
21540+ /* no spin_lock since sbinfo is write-locked */
e49829fe 21541+ WARN(verbose && !list_empty(plink_list), "pseudo-link is not flushed");
1facf9fc 21542+ list_for_each_entry_safe(plink, tmp, plink_list, list)
21543+ do_put_plink(plink, 0);
21544+ INIT_LIST_HEAD(plink_list);
21545+}
21546+
e49829fe
JR
21547+void au_plink_clean(struct super_block *sb, int verbose)
21548+{
21549+ struct dentry *root;
21550+
21551+ root = sb->s_root;
21552+ aufs_write_lock(root);
21553+ if (au_opt_test(au_mntflags(sb), PLINK))
21554+ au_plink_put(sb, verbose);
21555+ aufs_write_unlock(root);
21556+}
21557+
1facf9fc 21558+/* free the plinks on a branch specified by @br_id */
21559+void au_plink_half_refresh(struct super_block *sb, aufs_bindex_t br_id)
21560+{
21561+ struct au_sbinfo *sbinfo;
21562+ struct list_head *plink_list;
21563+ struct pseudo_link *plink, *tmp;
21564+ struct inode *inode;
21565+ aufs_bindex_t bstart, bend, bindex;
21566+ unsigned char do_put;
21567+
dece6358
AM
21568+ SiMustWriteLock(sb);
21569+
1facf9fc 21570+ sbinfo = au_sbi(sb);
21571+ AuDebugOn(!au_opt_test(au_mntflags(sb), PLINK));
e49829fe 21572+ AuDebugOn(au_plink_maint(sb, AuLock_NOPLM));
1facf9fc 21573+
21574+ plink_list = &sbinfo->si_plink.head;
21575+ /* no spin_lock since sbinfo is write-locked */
21576+ list_for_each_entry_safe(plink, tmp, plink_list, list) {
21577+ do_put = 0;
21578+ inode = au_igrab(plink->inode);
21579+ ii_write_lock_child(inode);
21580+ bstart = au_ibstart(inode);
21581+ bend = au_ibend(inode);
21582+ if (bstart >= 0) {
21583+ for (bindex = bstart; bindex <= bend; bindex++) {
21584+ if (!au_h_iptr(inode, bindex)
21585+ || au_ii_br_id(inode, bindex) != br_id)
21586+ continue;
21587+ au_set_h_iptr(inode, bindex, NULL, 0);
21588+ do_put = 1;
21589+ break;
21590+ }
21591+ } else
21592+ do_put_plink(plink, 1);
21593+
dece6358
AM
21594+ if (do_put) {
21595+ for (bindex = bstart; bindex <= bend; bindex++)
21596+ if (au_h_iptr(inode, bindex)) {
21597+ do_put = 0;
21598+ break;
21599+ }
21600+ if (do_put)
21601+ do_put_plink(plink, 1);
21602+ }
21603+ ii_write_unlock(inode);
21604+ iput(inode);
21605+ }
21606+}
7f207e10
AM
21607diff -urN /usr/share/empty/fs/aufs/poll.c linux/fs/aufs/poll.c
21608--- /usr/share/empty/fs/aufs/poll.c 1970-01-01 01:00:00.000000000 +0100
0c3ec466 21609+++ linux/fs/aufs/poll.c 2012-07-22 19:57:03.164337936 +0200
dece6358
AM
21610@@ -0,0 +1,56 @@
21611+/*
f6c5ef8b 21612+ * Copyright (C) 2005-2012 Junjiro R. Okajima
dece6358
AM
21613+ *
21614+ * This program, aufs is free software; you can redistribute it and/or modify
21615+ * it under the terms of the GNU General Public License as published by
21616+ * the Free Software Foundation; either version 2 of the License, or
21617+ * (at your option) any later version.
21618+ *
21619+ * This program is distributed in the hope that it will be useful,
21620+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
21621+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21622+ * GNU General Public License for more details.
21623+ *
21624+ * You should have received a copy of the GNU General Public License
21625+ * along with this program; if not, write to the Free Software
21626+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
21627+ */
21628+
1308ab2a 21629+/*
21630+ * poll operation
21631+ * There is only one filesystem which implements ->poll operation, currently.
21632+ */
21633+
21634+#include "aufs.h"
21635+
21636+unsigned int aufs_poll(struct file *file, poll_table *wait)
21637+{
21638+ unsigned int mask;
21639+ int err;
21640+ struct file *h_file;
21641+ struct dentry *dentry;
21642+ struct super_block *sb;
21643+
21644+ /* We should pretend an error happened. */
21645+ mask = POLLERR /* | POLLIN | POLLOUT */;
21646+ dentry = file->f_dentry;
21647+ sb = dentry->d_sb;
e49829fe 21648+ si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLMW);
1308ab2a 21649+ err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/0);
21650+ if (unlikely(err))
21651+ goto out;
21652+
21653+ /* it is not an error if h_file has no operation */
21654+ mask = DEFAULT_POLLMASK;
4a4d8108 21655+ h_file = au_hf_top(file);
1308ab2a 21656+ if (h_file->f_op && h_file->f_op->poll)
21657+ mask = h_file->f_op->poll(h_file, wait);
21658+
21659+ di_read_unlock(dentry, AuLock_IR);
21660+ fi_read_unlock(file);
21661+
4f0767ce 21662+out:
1308ab2a 21663+ si_read_unlock(sb);
21664+ AuTraceErr((int)mask);
21665+ return mask;
21666+}
7f207e10
AM
21667diff -urN /usr/share/empty/fs/aufs/procfs.c linux/fs/aufs/procfs.c
21668--- /usr/share/empty/fs/aufs/procfs.c 1970-01-01 01:00:00.000000000 +0100
0c3ec466 21669+++ linux/fs/aufs/procfs.c 2012-07-22 19:57:03.164337936 +0200
53392da6 21670@@ -0,0 +1,170 @@
e49829fe 21671+/*
f6c5ef8b 21672+ * Copyright (C) 2010-2012 Junjiro R. Okajima
e49829fe
JR
21673+ *
21674+ * This program, aufs is free software; you can redistribute it and/or modify
21675+ * it under the terms of the GNU General Public License as published by
21676+ * the Free Software Foundation; either version 2 of the License, or
21677+ * (at your option) any later version.
21678+ *
21679+ * This program is distributed in the hope that it will be useful,
21680+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
21681+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21682+ * GNU General Public License for more details.
21683+ *
21684+ * You should have received a copy of the GNU General Public License
21685+ * along with this program; if not, write to the Free Software
21686+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
21687+ */
21688+
21689+/*
21690+ * procfs interfaces
21691+ */
21692+
21693+#include <linux/proc_fs.h>
21694+#include "aufs.h"
21695+
21696+static int au_procfs_plm_release(struct inode *inode, struct file *file)
21697+{
21698+ struct au_sbinfo *sbinfo;
21699+
21700+ sbinfo = file->private_data;
21701+ if (sbinfo) {
21702+ au_plink_maint_leave(sbinfo);
21703+ kobject_put(&sbinfo->si_kobj);
21704+ }
21705+
21706+ return 0;
21707+}
21708+
21709+static void au_procfs_plm_write_clean(struct file *file)
21710+{
21711+ struct au_sbinfo *sbinfo;
21712+
21713+ sbinfo = file->private_data;
21714+ if (sbinfo)
21715+ au_plink_clean(sbinfo->si_sb, /*verbose*/0);
21716+}
21717+
21718+static int au_procfs_plm_write_si(struct file *file, unsigned long id)
21719+{
21720+ int err;
21721+ struct super_block *sb;
21722+ struct au_sbinfo *sbinfo;
21723+
21724+ err = -EBUSY;
21725+ if (unlikely(file->private_data))
21726+ goto out;
21727+
21728+ sb = NULL;
53392da6 21729+ /* don't use au_sbilist_lock() here */
e49829fe
JR
21730+ spin_lock(&au_sbilist.spin);
21731+ list_for_each_entry(sbinfo, &au_sbilist.head, si_list)
21732+ if (id == sysaufs_si_id(sbinfo)) {
21733+ kobject_get(&sbinfo->si_kobj);
21734+ sb = sbinfo->si_sb;
21735+ break;
21736+ }
21737+ spin_unlock(&au_sbilist.spin);
21738+
21739+ err = -EINVAL;
21740+ if (unlikely(!sb))
21741+ goto out;
21742+
21743+ err = au_plink_maint_enter(sb);
21744+ if (!err)
21745+ /* keep kobject_get() */
21746+ file->private_data = sbinfo;
21747+ else
21748+ kobject_put(&sbinfo->si_kobj);
21749+out:
21750+ return err;
21751+}
21752+
21753+/*
21754+ * Accept a valid "si=xxxx" only.
21755+ * Once it is accepted successfully, accept "clean" too.
21756+ */
21757+static ssize_t au_procfs_plm_write(struct file *file, const char __user *ubuf,
21758+ size_t count, loff_t *ppos)
21759+{
21760+ ssize_t err;
21761+ unsigned long id;
21762+ /* last newline is allowed */
21763+ char buf[3 + sizeof(unsigned long) * 2 + 1];
21764+
21765+ err = -EACCES;
21766+ if (unlikely(!capable(CAP_SYS_ADMIN)))
21767+ goto out;
21768+
21769+ err = -EINVAL;
21770+ if (unlikely(count > sizeof(buf)))
21771+ goto out;
21772+
21773+ err = copy_from_user(buf, ubuf, count);
21774+ if (unlikely(err)) {
21775+ err = -EFAULT;
21776+ goto out;
21777+ }
21778+ buf[count] = 0;
21779+
21780+ err = -EINVAL;
21781+ if (!strcmp("clean", buf)) {
21782+ au_procfs_plm_write_clean(file);
21783+ goto out_success;
21784+ } else if (unlikely(strncmp("si=", buf, 3)))
21785+ goto out;
21786+
9dbd164d 21787+ err = kstrtoul(buf + 3, 16, &id);
e49829fe
JR
21788+ if (unlikely(err))
21789+ goto out;
21790+
21791+ err = au_procfs_plm_write_si(file, id);
21792+ if (unlikely(err))
21793+ goto out;
21794+
21795+out_success:
21796+ err = count; /* success */
21797+out:
21798+ return err;
21799+}
21800+
21801+static const struct file_operations au_procfs_plm_fop = {
21802+ .write = au_procfs_plm_write,
21803+ .release = au_procfs_plm_release,
21804+ .owner = THIS_MODULE
21805+};
21806+
21807+/* ---------------------------------------------------------------------- */
21808+
21809+static struct proc_dir_entry *au_procfs_dir;
21810+
21811+void au_procfs_fin(void)
21812+{
21813+ remove_proc_entry(AUFS_PLINK_MAINT_NAME, au_procfs_dir);
21814+ remove_proc_entry(AUFS_PLINK_MAINT_DIR, NULL);
21815+}
21816+
21817+int __init au_procfs_init(void)
21818+{
21819+ int err;
21820+ struct proc_dir_entry *entry;
21821+
21822+ err = -ENOMEM;
21823+ au_procfs_dir = proc_mkdir(AUFS_PLINK_MAINT_DIR, NULL);
21824+ if (unlikely(!au_procfs_dir))
21825+ goto out;
21826+
21827+ entry = proc_create(AUFS_PLINK_MAINT_NAME, S_IFREG | S_IWUSR,
21828+ au_procfs_dir, &au_procfs_plm_fop);
21829+ if (unlikely(!entry))
21830+ goto out_dir;
21831+
21832+ err = 0;
21833+ goto out; /* success */
21834+
21835+
21836+out_dir:
21837+ remove_proc_entry(AUFS_PLINK_MAINT_DIR, NULL);
21838+out:
21839+ return err;
21840+}
7f207e10
AM
21841diff -urN /usr/share/empty/fs/aufs/rdu.c linux/fs/aufs/rdu.c
21842--- /usr/share/empty/fs/aufs/rdu.c 1970-01-01 01:00:00.000000000 +0100
0c3ec466 21843+++ linux/fs/aufs/rdu.c 2012-07-22 19:57:03.164337936 +0200
92d182d2 21844@@ -0,0 +1,384 @@
1308ab2a 21845+/*
f6c5ef8b 21846+ * Copyright (C) 2005-2012 Junjiro R. Okajima
1308ab2a 21847+ *
21848+ * This program, aufs is free software; you can redistribute it and/or modify
21849+ * it under the terms of the GNU General Public License as published by
21850+ * the Free Software Foundation; either version 2 of the License, or
21851+ * (at your option) any later version.
21852+ *
21853+ * This program is distributed in the hope that it will be useful,
21854+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
21855+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21856+ * GNU General Public License for more details.
21857+ *
21858+ * You should have received a copy of the GNU General Public License
21859+ * along with this program; if not, write to the Free Software
21860+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
21861+ */
21862+
21863+/*
21864+ * readdir in userspace.
21865+ */
21866+
b752ccd1 21867+#include <linux/compat.h>
4a4d8108 21868+#include <linux/fs_stack.h>
1308ab2a 21869+#include <linux/security.h>
1308ab2a 21870+#include "aufs.h"
21871+
21872+/* bits for struct aufs_rdu.flags */
21873+#define AuRdu_CALLED 1
21874+#define AuRdu_CONT (1 << 1)
21875+#define AuRdu_FULL (1 << 2)
21876+#define au_ftest_rdu(flags, name) ((flags) & AuRdu_##name)
7f207e10
AM
21877+#define au_fset_rdu(flags, name) \
21878+ do { (flags) |= AuRdu_##name; } while (0)
21879+#define au_fclr_rdu(flags, name) \
21880+ do { (flags) &= ~AuRdu_##name; } while (0)
1308ab2a 21881+
21882+struct au_rdu_arg {
21883+ struct aufs_rdu *rdu;
21884+ union au_rdu_ent_ul ent;
21885+ unsigned long end;
21886+
21887+ struct super_block *sb;
21888+ int err;
21889+};
21890+
21891+static int au_rdu_fill(void *__arg, const char *name, int nlen,
21892+ loff_t offset, u64 h_ino, unsigned int d_type)
21893+{
21894+ int err, len;
21895+ struct au_rdu_arg *arg = __arg;
21896+ struct aufs_rdu *rdu = arg->rdu;
21897+ struct au_rdu_ent ent;
21898+
21899+ err = 0;
21900+ arg->err = 0;
21901+ au_fset_rdu(rdu->cookie.flags, CALLED);
21902+ len = au_rdu_len(nlen);
21903+ if (arg->ent.ul + len < arg->end) {
21904+ ent.ino = h_ino;
21905+ ent.bindex = rdu->cookie.bindex;
21906+ ent.type = d_type;
21907+ ent.nlen = nlen;
4a4d8108
AM
21908+ if (unlikely(nlen > AUFS_MAX_NAMELEN))
21909+ ent.type = DT_UNKNOWN;
1308ab2a 21910+
9dbd164d 21911+ /* unnecessary to support mmap_sem since this is a dir */
1308ab2a 21912+ err = -EFAULT;
21913+ if (copy_to_user(arg->ent.e, &ent, sizeof(ent)))
21914+ goto out;
21915+ if (copy_to_user(arg->ent.e->name, name, nlen))
21916+ goto out;
21917+ /* the terminating NULL */
21918+ if (__put_user(0, arg->ent.e->name + nlen))
21919+ goto out;
21920+ err = 0;
21921+ /* AuDbg("%p, %.*s\n", arg->ent.p, nlen, name); */
21922+ arg->ent.ul += len;
21923+ rdu->rent++;
21924+ } else {
21925+ err = -EFAULT;
21926+ au_fset_rdu(rdu->cookie.flags, FULL);
21927+ rdu->full = 1;
21928+ rdu->tail = arg->ent;
21929+ }
21930+
4f0767ce 21931+out:
1308ab2a 21932+ /* AuTraceErr(err); */
21933+ return err;
21934+}
21935+
21936+static int au_rdu_do(struct file *h_file, struct au_rdu_arg *arg)
21937+{
21938+ int err;
21939+ loff_t offset;
21940+ struct au_rdu_cookie *cookie = &arg->rdu->cookie;
21941+
92d182d2 21942+ /* we don't have to care (FMODE_32BITHASH | FMODE_64BITHASH) for ext4 */
1308ab2a 21943+ offset = vfsub_llseek(h_file, cookie->h_pos, SEEK_SET);
21944+ err = offset;
21945+ if (unlikely(offset != cookie->h_pos))
21946+ goto out;
21947+
21948+ err = 0;
21949+ do {
21950+ arg->err = 0;
21951+ au_fclr_rdu(cookie->flags, CALLED);
21952+ /* smp_mb(); */
21953+ err = vfsub_readdir(h_file, au_rdu_fill, arg);
21954+ if (err >= 0)
21955+ err = arg->err;
21956+ } while (!err
21957+ && au_ftest_rdu(cookie->flags, CALLED)
21958+ && !au_ftest_rdu(cookie->flags, FULL));
21959+ cookie->h_pos = h_file->f_pos;
21960+
4f0767ce 21961+out:
1308ab2a 21962+ AuTraceErr(err);
21963+ return err;
21964+}
21965+
21966+static int au_rdu(struct file *file, struct aufs_rdu *rdu)
21967+{
21968+ int err;
21969+ aufs_bindex_t bend;
21970+ struct au_rdu_arg arg;
21971+ struct dentry *dentry;
21972+ struct inode *inode;
21973+ struct file *h_file;
21974+ struct au_rdu_cookie *cookie = &rdu->cookie;
21975+
21976+ err = !access_ok(VERIFY_WRITE, rdu->ent.e, rdu->sz);
21977+ if (unlikely(err)) {
21978+ err = -EFAULT;
21979+ AuTraceErr(err);
21980+ goto out;
21981+ }
21982+ rdu->rent = 0;
21983+ rdu->tail = rdu->ent;
21984+ rdu->full = 0;
21985+ arg.rdu = rdu;
21986+ arg.ent = rdu->ent;
21987+ arg.end = arg.ent.ul;
21988+ arg.end += rdu->sz;
21989+
21990+ err = -ENOTDIR;
21991+ if (unlikely(!file->f_op || !file->f_op->readdir))
21992+ goto out;
21993+
21994+ err = security_file_permission(file, MAY_READ);
21995+ AuTraceErr(err);
21996+ if (unlikely(err))
21997+ goto out;
21998+
21999+ dentry = file->f_dentry;
22000+ inode = dentry->d_inode;
22001+#if 1
22002+ mutex_lock(&inode->i_mutex);
22003+#else
22004+ err = mutex_lock_killable(&inode->i_mutex);
22005+ AuTraceErr(err);
22006+ if (unlikely(err))
22007+ goto out;
22008+#endif
1308ab2a 22009+
22010+ arg.sb = inode->i_sb;
e49829fe
JR
22011+ err = si_read_lock(arg.sb, AuLock_FLUSH | AuLock_NOPLM);
22012+ if (unlikely(err))
22013+ goto out_mtx;
027c5e7a
AM
22014+ err = au_alive_dir(dentry);
22015+ if (unlikely(err))
22016+ goto out_si;
e49829fe 22017+ /* todo: reval? */
1308ab2a 22018+ fi_read_lock(file);
22019+
22020+ err = -EAGAIN;
22021+ if (unlikely(au_ftest_rdu(cookie->flags, CONT)
22022+ && cookie->generation != au_figen(file)))
22023+ goto out_unlock;
22024+
22025+ err = 0;
22026+ if (!rdu->blk) {
22027+ rdu->blk = au_sbi(arg.sb)->si_rdblk;
22028+ if (!rdu->blk)
22029+ rdu->blk = au_dir_size(file, /*dentry*/NULL);
22030+ }
22031+ bend = au_fbstart(file);
22032+ if (cookie->bindex < bend)
22033+ cookie->bindex = bend;
4a4d8108 22034+ bend = au_fbend_dir(file);
1308ab2a 22035+ /* AuDbg("b%d, b%d\n", cookie->bindex, bend); */
22036+ for (; !err && cookie->bindex <= bend;
22037+ cookie->bindex++, cookie->h_pos = 0) {
4a4d8108 22038+ h_file = au_hf_dir(file, cookie->bindex);
1308ab2a 22039+ if (!h_file)
22040+ continue;
22041+
22042+ au_fclr_rdu(cookie->flags, FULL);
22043+ err = au_rdu_do(h_file, &arg);
22044+ AuTraceErr(err);
22045+ if (unlikely(au_ftest_rdu(cookie->flags, FULL) || err))
22046+ break;
22047+ }
22048+ AuDbg("rent %llu\n", rdu->rent);
22049+
22050+ if (!err && !au_ftest_rdu(cookie->flags, CONT)) {
22051+ rdu->shwh = !!au_opt_test(au_sbi(arg.sb)->si_mntflags, SHWH);
22052+ au_fset_rdu(cookie->flags, CONT);
22053+ cookie->generation = au_figen(file);
22054+ }
22055+
22056+ ii_read_lock_child(inode);
22057+ fsstack_copy_attr_atime(inode, au_h_iptr(inode, au_ibstart(inode)));
22058+ ii_read_unlock(inode);
22059+
4f0767ce 22060+out_unlock:
1308ab2a 22061+ fi_read_unlock(file);
027c5e7a 22062+out_si:
1308ab2a 22063+ si_read_unlock(arg.sb);
4f0767ce 22064+out_mtx:
1308ab2a 22065+ mutex_unlock(&inode->i_mutex);
4f0767ce 22066+out:
1308ab2a 22067+ AuTraceErr(err);
22068+ return err;
22069+}
22070+
22071+static int au_rdu_ino(struct file *file, struct aufs_rdu *rdu)
22072+{
22073+ int err;
22074+ ino_t ino;
22075+ unsigned long long nent;
22076+ union au_rdu_ent_ul *u;
22077+ struct au_rdu_ent ent;
22078+ struct super_block *sb;
22079+
22080+ err = 0;
22081+ nent = rdu->nent;
22082+ u = &rdu->ent;
22083+ sb = file->f_dentry->d_sb;
22084+ si_read_lock(sb, AuLock_FLUSH);
22085+ while (nent-- > 0) {
9dbd164d 22086+ /* unnecessary to support mmap_sem since this is a dir */
1308ab2a 22087+ err = copy_from_user(&ent, u->e, sizeof(ent));
4a4d8108
AM
22088+ if (!err)
22089+ err = !access_ok(VERIFY_WRITE, &u->e->ino, sizeof(ino));
1308ab2a 22090+ if (unlikely(err)) {
22091+ err = -EFAULT;
22092+ AuTraceErr(err);
22093+ break;
22094+ }
22095+
22096+ /* AuDbg("b%d, i%llu\n", ent.bindex, ent.ino); */
22097+ if (!ent.wh)
22098+ err = au_ino(sb, ent.bindex, ent.ino, ent.type, &ino);
22099+ else
22100+ err = au_wh_ino(sb, ent.bindex, ent.ino, ent.type,
22101+ &ino);
22102+ if (unlikely(err)) {
22103+ AuTraceErr(err);
22104+ break;
22105+ }
22106+
22107+ err = __put_user(ino, &u->e->ino);
22108+ if (unlikely(err)) {
22109+ err = -EFAULT;
22110+ AuTraceErr(err);
22111+ break;
22112+ }
22113+ u->ul += au_rdu_len(ent.nlen);
22114+ }
22115+ si_read_unlock(sb);
22116+
22117+ return err;
22118+}
22119+
22120+/* ---------------------------------------------------------------------- */
22121+
22122+static int au_rdu_verify(struct aufs_rdu *rdu)
22123+{
b752ccd1 22124+ AuDbg("rdu{%llu, %p, %u | %u | %llu, %u, %u | "
1308ab2a 22125+ "%llu, b%d, 0x%x, g%u}\n",
b752ccd1 22126+ rdu->sz, rdu->ent.e, rdu->verify[AufsCtlRduV_SZ],
1308ab2a 22127+ rdu->blk,
22128+ rdu->rent, rdu->shwh, rdu->full,
22129+ rdu->cookie.h_pos, rdu->cookie.bindex, rdu->cookie.flags,
22130+ rdu->cookie.generation);
dece6358 22131+
b752ccd1 22132+ if (rdu->verify[AufsCtlRduV_SZ] == sizeof(*rdu))
1308ab2a 22133+ return 0;
dece6358 22134+
b752ccd1
AM
22135+ AuDbg("%u:%u\n",
22136+ rdu->verify[AufsCtlRduV_SZ], (unsigned int)sizeof(*rdu));
1308ab2a 22137+ return -EINVAL;
22138+}
22139+
22140+long au_rdu_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
dece6358 22141+{
1308ab2a 22142+ long err, e;
22143+ struct aufs_rdu rdu;
22144+ void __user *p = (void __user *)arg;
dece6358 22145+
1308ab2a 22146+ err = copy_from_user(&rdu, p, sizeof(rdu));
22147+ if (unlikely(err)) {
22148+ err = -EFAULT;
22149+ AuTraceErr(err);
22150+ goto out;
22151+ }
22152+ err = au_rdu_verify(&rdu);
dece6358
AM
22153+ if (unlikely(err))
22154+ goto out;
22155+
1308ab2a 22156+ switch (cmd) {
22157+ case AUFS_CTL_RDU:
22158+ err = au_rdu(file, &rdu);
22159+ if (unlikely(err))
22160+ break;
dece6358 22161+
1308ab2a 22162+ e = copy_to_user(p, &rdu, sizeof(rdu));
22163+ if (unlikely(e)) {
22164+ err = -EFAULT;
22165+ AuTraceErr(err);
22166+ }
22167+ break;
22168+ case AUFS_CTL_RDU_INO:
22169+ err = au_rdu_ino(file, &rdu);
22170+ break;
22171+
22172+ default:
4a4d8108 22173+ /* err = -ENOTTY; */
1308ab2a 22174+ err = -EINVAL;
22175+ }
dece6358 22176+
4f0767ce 22177+out:
1308ab2a 22178+ AuTraceErr(err);
22179+ return err;
1facf9fc 22180+}
b752ccd1
AM
22181+
22182+#ifdef CONFIG_COMPAT
22183+long au_rdu_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
22184+{
22185+ long err, e;
22186+ struct aufs_rdu rdu;
22187+ void __user *p = compat_ptr(arg);
22188+
22189+ /* todo: get_user()? */
22190+ err = copy_from_user(&rdu, p, sizeof(rdu));
22191+ if (unlikely(err)) {
22192+ err = -EFAULT;
22193+ AuTraceErr(err);
22194+ goto out;
22195+ }
22196+ rdu.ent.e = compat_ptr(rdu.ent.ul);
22197+ err = au_rdu_verify(&rdu);
22198+ if (unlikely(err))
22199+ goto out;
22200+
22201+ switch (cmd) {
22202+ case AUFS_CTL_RDU:
22203+ err = au_rdu(file, &rdu);
22204+ if (unlikely(err))
22205+ break;
22206+
22207+ rdu.ent.ul = ptr_to_compat(rdu.ent.e);
22208+ rdu.tail.ul = ptr_to_compat(rdu.tail.e);
22209+ e = copy_to_user(p, &rdu, sizeof(rdu));
22210+ if (unlikely(e)) {
22211+ err = -EFAULT;
22212+ AuTraceErr(err);
22213+ }
22214+ break;
22215+ case AUFS_CTL_RDU_INO:
22216+ err = au_rdu_ino(file, &rdu);
22217+ break;
22218+
22219+ default:
22220+ /* err = -ENOTTY; */
22221+ err = -EINVAL;
22222+ }
22223+
4f0767ce 22224+out:
b752ccd1
AM
22225+ AuTraceErr(err);
22226+ return err;
22227+}
22228+#endif
7f207e10
AM
22229diff -urN /usr/share/empty/fs/aufs/rwsem.h linux/fs/aufs/rwsem.h
22230--- /usr/share/empty/fs/aufs/rwsem.h 1970-01-01 01:00:00.000000000 +0100
0c3ec466 22231+++ linux/fs/aufs/rwsem.h 2012-07-22 19:57:03.164337936 +0200
f6c5ef8b 22232@@ -0,0 +1,188 @@
1facf9fc 22233+/*
f6c5ef8b 22234+ * Copyright (C) 2005-2012 Junjiro R. Okajima
1facf9fc 22235+ *
22236+ * This program, aufs is free software; you can redistribute it and/or modify
22237+ * it under the terms of the GNU General Public License as published by
22238+ * the Free Software Foundation; either version 2 of the License, or
22239+ * (at your option) any later version.
dece6358
AM
22240+ *
22241+ * This program is distributed in the hope that it will be useful,
22242+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
22243+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22244+ * GNU General Public License for more details.
22245+ *
22246+ * You should have received a copy of the GNU General Public License
22247+ * along with this program; if not, write to the Free Software
22248+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 22249+ */
22250+
22251+/*
22252+ * simple read-write semaphore wrappers
22253+ */
22254+
22255+#ifndef __AUFS_RWSEM_H__
22256+#define __AUFS_RWSEM_H__
22257+
22258+#ifdef __KERNEL__
22259+
4a4d8108 22260+#include "debug.h"
dece6358
AM
22261+
22262+struct au_rwsem {
22263+ struct rw_semaphore rwsem;
22264+#ifdef CONFIG_AUFS_DEBUG
22265+ /* just for debugging, not almighty counter */
22266+ atomic_t rcnt, wcnt;
22267+#endif
22268+};
22269+
22270+#ifdef CONFIG_AUFS_DEBUG
22271+#define AuDbgCntInit(rw) do { \
22272+ atomic_set(&(rw)->rcnt, 0); \
22273+ atomic_set(&(rw)->wcnt, 0); \
22274+ smp_mb(); /* atomic set */ \
22275+} while (0)
22276+
e49829fe 22277+#define AuDbgRcntInc(rw) atomic_inc(&(rw)->rcnt)
dece6358 22278+#define AuDbgRcntDec(rw) WARN_ON(atomic_dec_return(&(rw)->rcnt) < 0)
e49829fe 22279+#define AuDbgWcntInc(rw) atomic_inc(&(rw)->wcnt)
dece6358
AM
22280+#define AuDbgWcntDec(rw) WARN_ON(atomic_dec_return(&(rw)->wcnt) < 0)
22281+#else
22282+#define AuDbgCntInit(rw) do {} while (0)
22283+#define AuDbgRcntInc(rw) do {} while (0)
22284+#define AuDbgRcntDec(rw) do {} while (0)
22285+#define AuDbgWcntInc(rw) do {} while (0)
22286+#define AuDbgWcntDec(rw) do {} while (0)
22287+#endif /* CONFIG_AUFS_DEBUG */
22288+
22289+/* to debug easier, do not make them inlined functions */
22290+#define AuRwMustNoWaiters(rw) AuDebugOn(!list_empty(&(rw)->rwsem.wait_list))
22291+/* rwsem_is_locked() is unusable */
22292+#define AuRwMustReadLock(rw) AuDebugOn(atomic_read(&(rw)->rcnt) <= 0)
22293+#define AuRwMustWriteLock(rw) AuDebugOn(atomic_read(&(rw)->wcnt) <= 0)
22294+#define AuRwMustAnyLock(rw) AuDebugOn(atomic_read(&(rw)->rcnt) <= 0 \
22295+ && atomic_read(&(rw)->wcnt) <= 0)
22296+#define AuRwDestroy(rw) AuDebugOn(atomic_read(&(rw)->rcnt) \
22297+ || atomic_read(&(rw)->wcnt))
22298+
e49829fe
JR
22299+#define au_rw_class(rw, key) lockdep_set_class(&(rw)->rwsem, key)
22300+
dece6358
AM
22301+static inline void au_rw_init(struct au_rwsem *rw)
22302+{
22303+ AuDbgCntInit(rw);
22304+ init_rwsem(&rw->rwsem);
22305+}
22306+
22307+static inline void au_rw_init_wlock(struct au_rwsem *rw)
22308+{
22309+ au_rw_init(rw);
22310+ down_write(&rw->rwsem);
22311+ AuDbgWcntInc(rw);
22312+}
22313+
22314+static inline void au_rw_init_wlock_nested(struct au_rwsem *rw,
22315+ unsigned int lsc)
22316+{
22317+ au_rw_init(rw);
22318+ down_write_nested(&rw->rwsem, lsc);
22319+ AuDbgWcntInc(rw);
22320+}
22321+
22322+static inline void au_rw_read_lock(struct au_rwsem *rw)
22323+{
22324+ down_read(&rw->rwsem);
22325+ AuDbgRcntInc(rw);
22326+}
22327+
22328+static inline void au_rw_read_lock_nested(struct au_rwsem *rw, unsigned int lsc)
22329+{
22330+ down_read_nested(&rw->rwsem, lsc);
22331+ AuDbgRcntInc(rw);
22332+}
22333+
22334+static inline void au_rw_read_unlock(struct au_rwsem *rw)
22335+{
22336+ AuRwMustReadLock(rw);
22337+ AuDbgRcntDec(rw);
22338+ up_read(&rw->rwsem);
22339+}
22340+
22341+static inline void au_rw_dgrade_lock(struct au_rwsem *rw)
22342+{
22343+ AuRwMustWriteLock(rw);
22344+ AuDbgRcntInc(rw);
22345+ AuDbgWcntDec(rw);
22346+ downgrade_write(&rw->rwsem);
22347+}
22348+
22349+static inline void au_rw_write_lock(struct au_rwsem *rw)
22350+{
22351+ down_write(&rw->rwsem);
22352+ AuDbgWcntInc(rw);
22353+}
22354+
22355+static inline void au_rw_write_lock_nested(struct au_rwsem *rw,
22356+ unsigned int lsc)
22357+{
22358+ down_write_nested(&rw->rwsem, lsc);
22359+ AuDbgWcntInc(rw);
22360+}
1facf9fc 22361+
dece6358
AM
22362+static inline void au_rw_write_unlock(struct au_rwsem *rw)
22363+{
22364+ AuRwMustWriteLock(rw);
22365+ AuDbgWcntDec(rw);
22366+ up_write(&rw->rwsem);
22367+}
22368+
22369+/* why is not _nested version defined */
22370+static inline int au_rw_read_trylock(struct au_rwsem *rw)
22371+{
22372+ int ret = down_read_trylock(&rw->rwsem);
22373+ if (ret)
22374+ AuDbgRcntInc(rw);
22375+ return ret;
22376+}
22377+
22378+static inline int au_rw_write_trylock(struct au_rwsem *rw)
22379+{
22380+ int ret = down_write_trylock(&rw->rwsem);
22381+ if (ret)
22382+ AuDbgWcntInc(rw);
22383+ return ret;
22384+}
22385+
22386+#undef AuDbgCntInit
22387+#undef AuDbgRcntInc
22388+#undef AuDbgRcntDec
22389+#undef AuDbgWcntInc
22390+#undef AuDbgWcntDec
1facf9fc 22391+
22392+#define AuSimpleLockRwsemFuncs(prefix, param, rwsem) \
22393+static inline void prefix##_read_lock(param) \
dece6358 22394+{ au_rw_read_lock(rwsem); } \
1facf9fc 22395+static inline void prefix##_write_lock(param) \
dece6358 22396+{ au_rw_write_lock(rwsem); } \
1facf9fc 22397+static inline int prefix##_read_trylock(param) \
dece6358 22398+{ return au_rw_read_trylock(rwsem); } \
1facf9fc 22399+static inline int prefix##_write_trylock(param) \
dece6358 22400+{ return au_rw_write_trylock(rwsem); }
1facf9fc 22401+/* why is not _nested version defined */
22402+/* static inline void prefix##_read_trylock_nested(param, lsc)
dece6358 22403+{ au_rw_read_trylock_nested(rwsem, lsc)); }
1facf9fc 22404+static inline void prefix##_write_trylock_nestd(param, lsc)
dece6358 22405+{ au_rw_write_trylock_nested(rwsem, lsc); } */
1facf9fc 22406+
22407+#define AuSimpleUnlockRwsemFuncs(prefix, param, rwsem) \
22408+static inline void prefix##_read_unlock(param) \
dece6358 22409+{ au_rw_read_unlock(rwsem); } \
1facf9fc 22410+static inline void prefix##_write_unlock(param) \
dece6358 22411+{ au_rw_write_unlock(rwsem); } \
1facf9fc 22412+static inline void prefix##_downgrade_lock(param) \
dece6358 22413+{ au_rw_dgrade_lock(rwsem); }
1facf9fc 22414+
22415+#define AuSimpleRwsemFuncs(prefix, param, rwsem) \
22416+ AuSimpleLockRwsemFuncs(prefix, param, rwsem) \
22417+ AuSimpleUnlockRwsemFuncs(prefix, param, rwsem)
22418+
22419+#endif /* __KERNEL__ */
22420+#endif /* __AUFS_RWSEM_H__ */
7f207e10
AM
22421diff -urN /usr/share/empty/fs/aufs/sbinfo.c linux/fs/aufs/sbinfo.c
22422--- /usr/share/empty/fs/aufs/sbinfo.c 1970-01-01 01:00:00.000000000 +0100
0c3ec466 22423+++ linux/fs/aufs/sbinfo.c 2012-07-22 19:57:03.164337936 +0200
f6c5ef8b 22424@@ -0,0 +1,343 @@
1facf9fc 22425+/*
f6c5ef8b 22426+ * Copyright (C) 2005-2012 Junjiro R. Okajima
1facf9fc 22427+ *
22428+ * This program, aufs is free software; you can redistribute it and/or modify
22429+ * it under the terms of the GNU General Public License as published by
22430+ * the Free Software Foundation; either version 2 of the License, or
22431+ * (at your option) any later version.
dece6358
AM
22432+ *
22433+ * This program is distributed in the hope that it will be useful,
22434+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
22435+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22436+ * GNU General Public License for more details.
22437+ *
22438+ * You should have received a copy of the GNU General Public License
22439+ * along with this program; if not, write to the Free Software
22440+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 22441+ */
22442+
22443+/*
22444+ * superblock private data
22445+ */
22446+
22447+#include "aufs.h"
22448+
22449+/*
22450+ * they are necessary regardless sysfs is disabled.
22451+ */
22452+void au_si_free(struct kobject *kobj)
22453+{
22454+ struct au_sbinfo *sbinfo;
b752ccd1 22455+ char *locked __maybe_unused; /* debug only */
1facf9fc 22456+
22457+ sbinfo = container_of(kobj, struct au_sbinfo, si_kobj);
22458+ AuDebugOn(!list_empty(&sbinfo->si_plink.head));
e49829fe 22459+ AuDebugOn(atomic_read(&sbinfo->si_nowait.nw_len));
1facf9fc 22460+
e49829fe 22461+ au_rw_write_lock(&sbinfo->si_rwsem);
1facf9fc 22462+ au_br_free(sbinfo);
e49829fe 22463+ au_rw_write_unlock(&sbinfo->si_rwsem);
b752ccd1
AM
22464+
22465+ AuDebugOn(radix_tree_gang_lookup
22466+ (&sbinfo->au_si_pid.tree, (void **)&locked,
22467+ /*first_index*/PID_MAX_DEFAULT - 1,
22468+ /*max_items*/sizeof(locked)/sizeof(*locked)));
22469+
1facf9fc 22470+ kfree(sbinfo->si_branch);
b752ccd1 22471+ kfree(sbinfo->au_si_pid.bitmap);
1facf9fc 22472+ mutex_destroy(&sbinfo->si_xib_mtx);
dece6358 22473+ AuRwDestroy(&sbinfo->si_rwsem);
1facf9fc 22474+
22475+ kfree(sbinfo);
22476+}
22477+
22478+int au_si_alloc(struct super_block *sb)
22479+{
22480+ int err;
22481+ struct au_sbinfo *sbinfo;
e49829fe 22482+ static struct lock_class_key aufs_si;
1facf9fc 22483+
22484+ err = -ENOMEM;
4a4d8108 22485+ sbinfo = kzalloc(sizeof(*sbinfo), GFP_NOFS);
1facf9fc 22486+ if (unlikely(!sbinfo))
22487+ goto out;
22488+
b752ccd1
AM
22489+ BUILD_BUG_ON(sizeof(unsigned long) !=
22490+ sizeof(*sbinfo->au_si_pid.bitmap));
22491+ sbinfo->au_si_pid.bitmap = kcalloc(BITS_TO_LONGS(PID_MAX_DEFAULT),
22492+ sizeof(*sbinfo->au_si_pid.bitmap),
22493+ GFP_NOFS);
22494+ if (unlikely(!sbinfo->au_si_pid.bitmap))
22495+ goto out_sbinfo;
22496+
1facf9fc 22497+ /* will be reallocated separately */
22498+ sbinfo->si_branch = kzalloc(sizeof(*sbinfo->si_branch), GFP_NOFS);
22499+ if (unlikely(!sbinfo->si_branch))
b752ccd1 22500+ goto out_pidmap;
1facf9fc 22501+
1facf9fc 22502+ err = sysaufs_si_init(sbinfo);
22503+ if (unlikely(err))
22504+ goto out_br;
22505+
22506+ au_nwt_init(&sbinfo->si_nowait);
dece6358 22507+ au_rw_init_wlock(&sbinfo->si_rwsem);
e49829fe 22508+ au_rw_class(&sbinfo->si_rwsem, &aufs_si);
b752ccd1
AM
22509+ spin_lock_init(&sbinfo->au_si_pid.tree_lock);
22510+ INIT_RADIX_TREE(&sbinfo->au_si_pid.tree, GFP_ATOMIC | __GFP_NOFAIL);
22511+
7f207e10 22512+ atomic_long_set(&sbinfo->si_ninodes, 0);
7f207e10
AM
22513+ atomic_long_set(&sbinfo->si_nfiles, 0);
22514+
1facf9fc 22515+ sbinfo->si_bend = -1;
1facf9fc 22516+
22517+ sbinfo->si_wbr_copyup = AuWbrCopyup_Def;
22518+ sbinfo->si_wbr_create = AuWbrCreate_Def;
4a4d8108
AM
22519+ sbinfo->si_wbr_copyup_ops = au_wbr_copyup_ops + sbinfo->si_wbr_copyup;
22520+ sbinfo->si_wbr_create_ops = au_wbr_create_ops + sbinfo->si_wbr_create;
1facf9fc 22521+
e49829fe 22522+ sbinfo->si_mntflags = au_opts_plink(AuOpt_Def);
1facf9fc 22523+
1facf9fc 22524+ mutex_init(&sbinfo->si_xib_mtx);
1facf9fc 22525+ sbinfo->si_xino_brid = -1;
22526+ /* leave si_xib_last_pindex and si_xib_next_bit */
22527+
e49829fe 22528+ sbinfo->si_rdcache = msecs_to_jiffies(AUFS_RDCACHE_DEF * MSEC_PER_SEC);
1facf9fc 22529+ sbinfo->si_rdblk = AUFS_RDBLK_DEF;
22530+ sbinfo->si_rdhash = AUFS_RDHASH_DEF;
22531+ sbinfo->si_dirwh = AUFS_DIRWH_DEF;
22532+
22533+ au_spl_init(&sbinfo->si_plink);
22534+ init_waitqueue_head(&sbinfo->si_plink_wq);
4a4d8108 22535+ spin_lock_init(&sbinfo->si_plink_maint_lock);
1facf9fc 22536+
22537+ /* leave other members for sysaufs and si_mnt. */
22538+ sbinfo->si_sb = sb;
22539+ sb->s_fs_info = sbinfo;
b752ccd1 22540+ si_pid_set(sb);
1facf9fc 22541+ au_debug_sbinfo_init(sbinfo);
22542+ return 0; /* success */
22543+
4f0767ce 22544+out_br:
1facf9fc 22545+ kfree(sbinfo->si_branch);
4f0767ce 22546+out_pidmap:
b752ccd1 22547+ kfree(sbinfo->au_si_pid.bitmap);
4f0767ce 22548+out_sbinfo:
1facf9fc 22549+ kfree(sbinfo);
4f0767ce 22550+out:
1facf9fc 22551+ return err;
22552+}
22553+
22554+int au_sbr_realloc(struct au_sbinfo *sbinfo, int nbr)
22555+{
22556+ int err, sz;
22557+ struct au_branch **brp;
22558+
dece6358
AM
22559+ AuRwMustWriteLock(&sbinfo->si_rwsem);
22560+
1facf9fc 22561+ err = -ENOMEM;
22562+ sz = sizeof(*brp) * (sbinfo->si_bend + 1);
22563+ if (unlikely(!sz))
22564+ sz = sizeof(*brp);
22565+ brp = au_kzrealloc(sbinfo->si_branch, sz, sizeof(*brp) * nbr, GFP_NOFS);
22566+ if (brp) {
22567+ sbinfo->si_branch = brp;
22568+ err = 0;
22569+ }
22570+
22571+ return err;
22572+}
22573+
22574+/* ---------------------------------------------------------------------- */
22575+
22576+unsigned int au_sigen_inc(struct super_block *sb)
22577+{
22578+ unsigned int gen;
22579+
dece6358
AM
22580+ SiMustWriteLock(sb);
22581+
1facf9fc 22582+ gen = ++au_sbi(sb)->si_generation;
22583+ au_update_digen(sb->s_root);
22584+ au_update_iigen(sb->s_root->d_inode);
22585+ sb->s_root->d_inode->i_version++;
22586+ return gen;
22587+}
22588+
22589+aufs_bindex_t au_new_br_id(struct super_block *sb)
22590+{
22591+ aufs_bindex_t br_id;
22592+ int i;
22593+ struct au_sbinfo *sbinfo;
22594+
dece6358
AM
22595+ SiMustWriteLock(sb);
22596+
1facf9fc 22597+ sbinfo = au_sbi(sb);
22598+ for (i = 0; i <= AUFS_BRANCH_MAX; i++) {
22599+ br_id = ++sbinfo->si_last_br_id;
7f207e10 22600+ AuDebugOn(br_id < 0);
1facf9fc 22601+ if (br_id && au_br_index(sb, br_id) < 0)
22602+ return br_id;
22603+ }
22604+
22605+ return -1;
22606+}
22607+
22608+/* ---------------------------------------------------------------------- */
22609+
e49829fe
JR
22610+/* it is ok that new 'nwt' tasks are appended while we are sleeping */
22611+int si_read_lock(struct super_block *sb, int flags)
22612+{
22613+ int err;
22614+
22615+ err = 0;
22616+ if (au_ftest_lock(flags, FLUSH))
22617+ au_nwt_flush(&au_sbi(sb)->si_nowait);
22618+
22619+ si_noflush_read_lock(sb);
22620+ err = au_plink_maint(sb, flags);
22621+ if (unlikely(err))
22622+ si_read_unlock(sb);
22623+
22624+ return err;
22625+}
22626+
22627+int si_write_lock(struct super_block *sb, int flags)
22628+{
22629+ int err;
22630+
22631+ if (au_ftest_lock(flags, FLUSH))
22632+ au_nwt_flush(&au_sbi(sb)->si_nowait);
22633+
22634+ si_noflush_write_lock(sb);
22635+ err = au_plink_maint(sb, flags);
22636+ if (unlikely(err))
22637+ si_write_unlock(sb);
22638+
22639+ return err;
22640+}
22641+
1facf9fc 22642+/* dentry and super_block lock. call at entry point */
e49829fe 22643+int aufs_read_lock(struct dentry *dentry, int flags)
1facf9fc 22644+{
e49829fe 22645+ int err;
027c5e7a 22646+ struct super_block *sb;
e49829fe 22647+
027c5e7a
AM
22648+ sb = dentry->d_sb;
22649+ err = si_read_lock(sb, flags);
22650+ if (unlikely(err))
22651+ goto out;
22652+
22653+ if (au_ftest_lock(flags, DW))
22654+ di_write_lock_child(dentry);
22655+ else
22656+ di_read_lock_child(dentry, flags);
22657+
22658+ if (au_ftest_lock(flags, GEN)) {
22659+ err = au_digen_test(dentry, au_sigen(sb));
22660+ AuDebugOn(!err && au_dbrange_test(dentry));
22661+ if (unlikely(err))
22662+ aufs_read_unlock(dentry, flags);
e49829fe
JR
22663+ }
22664+
027c5e7a 22665+out:
e49829fe 22666+ return err;
1facf9fc 22667+}
22668+
22669+void aufs_read_unlock(struct dentry *dentry, int flags)
22670+{
22671+ if (au_ftest_lock(flags, DW))
22672+ di_write_unlock(dentry);
22673+ else
22674+ di_read_unlock(dentry, flags);
22675+ si_read_unlock(dentry->d_sb);
22676+}
22677+
22678+void aufs_write_lock(struct dentry *dentry)
22679+{
e49829fe 22680+ si_write_lock(dentry->d_sb, AuLock_FLUSH | AuLock_NOPLMW);
1facf9fc 22681+ di_write_lock_child(dentry);
22682+}
22683+
22684+void aufs_write_unlock(struct dentry *dentry)
22685+{
22686+ di_write_unlock(dentry);
22687+ si_write_unlock(dentry->d_sb);
22688+}
22689+
e49829fe 22690+int aufs_read_and_write_lock2(struct dentry *d1, struct dentry *d2, int flags)
1facf9fc 22691+{
e49829fe 22692+ int err;
027c5e7a
AM
22693+ unsigned int sigen;
22694+ struct super_block *sb;
e49829fe 22695+
027c5e7a
AM
22696+ sb = d1->d_sb;
22697+ err = si_read_lock(sb, flags);
22698+ if (unlikely(err))
22699+ goto out;
22700+
22701+ di_write_lock2_child(d1, d2, au_ftest_lock(flags, DIR));
22702+
22703+ if (au_ftest_lock(flags, GEN)) {
22704+ sigen = au_sigen(sb);
22705+ err = au_digen_test(d1, sigen);
22706+ AuDebugOn(!err && au_dbrange_test(d1));
22707+ if (!err) {
22708+ err = au_digen_test(d2, sigen);
22709+ AuDebugOn(!err && au_dbrange_test(d2));
22710+ }
22711+ if (unlikely(err))
22712+ aufs_read_and_write_unlock2(d1, d2);
22713+ }
22714+
22715+out:
e49829fe 22716+ return err;
1facf9fc 22717+}
22718+
22719+void aufs_read_and_write_unlock2(struct dentry *d1, struct dentry *d2)
22720+{
22721+ di_write_unlock2(d1, d2);
22722+ si_read_unlock(d1->d_sb);
22723+}
b752ccd1
AM
22724+
22725+/* ---------------------------------------------------------------------- */
22726+
22727+int si_pid_test_slow(struct super_block *sb)
22728+{
22729+ void *p;
22730+
22731+ rcu_read_lock();
22732+ p = radix_tree_lookup(&au_sbi(sb)->au_si_pid.tree, current->pid);
22733+ rcu_read_unlock();
22734+
027c5e7a 22735+ return (long)!!p;
b752ccd1
AM
22736+}
22737+
22738+void si_pid_set_slow(struct super_block *sb)
22739+{
22740+ int err;
22741+ struct au_sbinfo *sbinfo;
22742+
22743+ AuDebugOn(si_pid_test_slow(sb));
22744+
22745+ sbinfo = au_sbi(sb);
22746+ err = radix_tree_preload(GFP_NOFS | __GFP_NOFAIL);
22747+ AuDebugOn(err);
22748+ spin_lock(&sbinfo->au_si_pid.tree_lock);
22749+ err = radix_tree_insert(&sbinfo->au_si_pid.tree, current->pid,
027c5e7a 22750+ /*any valid ptr*/sb);
b752ccd1
AM
22751+ spin_unlock(&sbinfo->au_si_pid.tree_lock);
22752+ AuDebugOn(err);
22753+ radix_tree_preload_end();
22754+}
22755+
22756+void si_pid_clr_slow(struct super_block *sb)
22757+{
22758+ void *p;
22759+ struct au_sbinfo *sbinfo;
22760+
22761+ AuDebugOn(!si_pid_test_slow(sb));
22762+
22763+ sbinfo = au_sbi(sb);
22764+ spin_lock(&sbinfo->au_si_pid.tree_lock);
22765+ p = radix_tree_delete(&sbinfo->au_si_pid.tree, current->pid);
22766+ spin_unlock(&sbinfo->au_si_pid.tree_lock);
b752ccd1 22767+}
0c3ec466
AM
22768diff -urN /usr/share/empty/fs/aufs/security.c linux/fs/aufs/security.c
22769--- /usr/share/empty/fs/aufs/security.c 1970-01-01 01:00:00.000000000 +0100
22770+++ linux/fs/aufs/security.c 2012-07-22 19:57:03.164337936 +0200
22771@@ -0,0 +1,92 @@
22772+/*
22773+ * Copyright (C) 2012 Junjiro R. Okajima
22774+ *
22775+ * This program, aufs is free software; you can redistribute it and/or modify
22776+ * it under the terms of the GNU General Public License as published by
22777+ * the Free Software Foundation; either version 2 of the License, or
22778+ * (at your option) any later version.
22779+ *
22780+ * This program is distributed in the hope that it will be useful,
22781+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
22782+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22783+ * GNU General Public License for more details.
22784+ *
22785+ * You should have received a copy of the GNU General Public License
22786+ * along with this program; if not, write to the Free Software
22787+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
22788+ */
22789+
22790+/*
22791+ * securityf_file_mmap
22792+ */
22793+
22794+#include <linux/mman.h>
22795+#include <linux/security.h>
22796+#include "aufs.h"
22797+
22798+/* cf. linux/include/linux/mman.h: calc_vm_prot_bits() */
22799+#define AuConv_VM_PROT(f, b) _calc_vm_trans(f, VM_##b, PROT_##b)
22800+
22801+static unsigned long au_arch_prot_conv(unsigned long flags)
22802+{
22803+ /* currently ppc64 only */
22804+#ifdef CONFIG_PPC64
22805+ /* cf. linux/arch/powerpc/include/asm/mman.h */
22806+ AuDebugOn(arch_calc_vm_prot_bits(-1) != VM_SAO);
22807+ return AuConv_VM_PROT(flags, SAO);
22808+#else
22809+ AuDebugOn(arch_calc_vm_prot_bits(-1));
22810+ return 0;
22811+#endif
22812+}
22813+
22814+static unsigned long au_prot_conv(unsigned long flags)
22815+{
22816+ return AuConv_VM_PROT(flags, READ)
22817+ | AuConv_VM_PROT(flags, WRITE)
22818+ | AuConv_VM_PROT(flags, EXEC)
22819+ | au_arch_prot_conv(flags);
22820+}
22821+
22822+/* cf. linux/include/linux/mman.h: calc_vm_flag_bits() */
22823+#define AuConv_VM_MAP(f, b) _calc_vm_trans(f, VM_##b, MAP_##b)
22824+
22825+static unsigned long au_flag_conv(unsigned long flags)
22826+{
22827+ return AuConv_VM_MAP(flags, GROWSDOWN)
22828+ | AuConv_VM_MAP(flags, DENYWRITE)
22829+ | AuConv_VM_MAP(flags, EXECUTABLE)
22830+ | AuConv_VM_MAP(flags, LOCKED);
22831+}
22832+
22833+struct au_security_mmap_file_args {
22834+ int *errp;
22835+ struct file *h_file;
22836+ struct vm_area_struct *vma;
22837+};
22838+
22839+/*
22840+ * unnecessary to call security_mmap_file() since it doesn't have file as its
22841+ * argument.
22842+ */
22843+static void au_call_security_mmap_file(void *args)
22844+{
22845+ struct au_security_mmap_file_args *a = args;
22846+ *a->errp = security_mmap_file(a->h_file, au_prot_conv(a->vma->vm_flags),
22847+ au_flag_conv(a->vma->vm_flags));
22848+}
22849+
22850+int au_security_mmap_file(struct file *h_file, struct vm_area_struct *vma)
22851+{
22852+ int err, wkq_err;
22853+ struct au_security_mmap_file_args args = {
22854+ .errp = &err,
22855+ .h_file = h_file,
22856+ .vma = vma
22857+ };
22858+
22859+ wkq_err = au_wkq_wait(au_call_security_mmap_file, &args);
22860+ if (unlikely(wkq_err))
22861+ err = wkq_err;
22862+ return err;
22863+}
7f207e10
AM
22864diff -urN /usr/share/empty/fs/aufs/spl.h linux/fs/aufs/spl.h
22865--- /usr/share/empty/fs/aufs/spl.h 1970-01-01 01:00:00.000000000 +0100
0c3ec466 22866+++ linux/fs/aufs/spl.h 2012-07-22 19:57:03.164337936 +0200
f6c5ef8b 22867@@ -0,0 +1,62 @@
1facf9fc 22868+/*
f6c5ef8b 22869+ * Copyright (C) 2005-2012 Junjiro R. Okajima
1facf9fc 22870+ *
22871+ * This program, aufs is free software; you can redistribute it and/or modify
22872+ * it under the terms of the GNU General Public License as published by
22873+ * the Free Software Foundation; either version 2 of the License, or
22874+ * (at your option) any later version.
dece6358
AM
22875+ *
22876+ * This program is distributed in the hope that it will be useful,
22877+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
22878+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22879+ * GNU General Public License for more details.
22880+ *
22881+ * You should have received a copy of the GNU General Public License
22882+ * along with this program; if not, write to the Free Software
22883+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 22884+ */
22885+
22886+/*
22887+ * simple list protected by a spinlock
22888+ */
22889+
22890+#ifndef __AUFS_SPL_H__
22891+#define __AUFS_SPL_H__
22892+
22893+#ifdef __KERNEL__
22894+
1facf9fc 22895+struct au_splhead {
22896+ spinlock_t spin;
22897+ struct list_head head;
22898+};
22899+
22900+static inline void au_spl_init(struct au_splhead *spl)
22901+{
22902+ spin_lock_init(&spl->spin);
22903+ INIT_LIST_HEAD(&spl->head);
22904+}
22905+
22906+static inline void au_spl_add(struct list_head *list, struct au_splhead *spl)
22907+{
22908+ spin_lock(&spl->spin);
22909+ list_add(list, &spl->head);
22910+ spin_unlock(&spl->spin);
22911+}
22912+
22913+static inline void au_spl_del(struct list_head *list, struct au_splhead *spl)
22914+{
22915+ spin_lock(&spl->spin);
22916+ list_del(list);
22917+ spin_unlock(&spl->spin);
22918+}
22919+
4a4d8108
AM
22920+static inline void au_spl_del_rcu(struct list_head *list,
22921+ struct au_splhead *spl)
22922+{
22923+ spin_lock(&spl->spin);
22924+ list_del_rcu(list);
22925+ spin_unlock(&spl->spin);
22926+}
22927+
1facf9fc 22928+#endif /* __KERNEL__ */
22929+#endif /* __AUFS_SPL_H__ */
7f207e10
AM
22930diff -urN /usr/share/empty/fs/aufs/super.c linux/fs/aufs/super.c
22931--- /usr/share/empty/fs/aufs/super.c 1970-01-01 01:00:00.000000000 +0100
0c3ec466 22932+++ linux/fs/aufs/super.c 2012-07-22 19:57:03.164337936 +0200
92d182d2 22933@@ -0,0 +1,962 @@
1facf9fc 22934+/*
f6c5ef8b 22935+ * Copyright (C) 2005-2012 Junjiro R. Okajima
1facf9fc 22936+ *
22937+ * This program, aufs is free software; you can redistribute it and/or modify
22938+ * it under the terms of the GNU General Public License as published by
22939+ * the Free Software Foundation; either version 2 of the License, or
22940+ * (at your option) any later version.
dece6358
AM
22941+ *
22942+ * This program is distributed in the hope that it will be useful,
22943+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
22944+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22945+ * GNU General Public License for more details.
22946+ *
22947+ * You should have received a copy of the GNU General Public License
22948+ * along with this program; if not, write to the Free Software
22949+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 22950+ */
22951+
22952+/*
22953+ * mount and super_block operations
22954+ */
22955+
f6c5ef8b 22956+#include <linux/mm.h>
dece6358 22957+#include <linux/module.h>
1facf9fc 22958+#include <linux/seq_file.h>
22959+#include <linux/statfs.h>
7f207e10
AM
22960+#include <linux/vmalloc.h>
22961+#include <linux/writeback.h>
1facf9fc 22962+#include "aufs.h"
22963+
22964+/*
22965+ * super_operations
22966+ */
22967+static struct inode *aufs_alloc_inode(struct super_block *sb __maybe_unused)
22968+{
22969+ struct au_icntnr *c;
22970+
22971+ c = au_cache_alloc_icntnr();
22972+ if (c) {
027c5e7a 22973+ au_icntnr_init(c);
1facf9fc 22974+ c->vfs_inode.i_version = 1; /* sigen(sb); */
22975+ c->iinfo.ii_hinode = NULL;
22976+ return &c->vfs_inode;
22977+ }
22978+ return NULL;
22979+}
22980+
027c5e7a
AM
22981+static void aufs_destroy_inode_cb(struct rcu_head *head)
22982+{
22983+ struct inode *inode = container_of(head, struct inode, i_rcu);
22984+
22985+ INIT_LIST_HEAD(&inode->i_dentry);
22986+ au_cache_free_icntnr(container_of(inode, struct au_icntnr, vfs_inode));
22987+}
22988+
1facf9fc 22989+static void aufs_destroy_inode(struct inode *inode)
22990+{
22991+ au_iinfo_fin(inode);
027c5e7a 22992+ call_rcu(&inode->i_rcu, aufs_destroy_inode_cb);
1facf9fc 22993+}
22994+
22995+struct inode *au_iget_locked(struct super_block *sb, ino_t ino)
22996+{
22997+ struct inode *inode;
22998+ int err;
22999+
23000+ inode = iget_locked(sb, ino);
23001+ if (unlikely(!inode)) {
23002+ inode = ERR_PTR(-ENOMEM);
23003+ goto out;
23004+ }
23005+ if (!(inode->i_state & I_NEW))
23006+ goto out;
23007+
23008+ err = au_xigen_new(inode);
23009+ if (!err)
23010+ err = au_iinfo_init(inode);
23011+ if (!err)
23012+ inode->i_version++;
23013+ else {
23014+ iget_failed(inode);
23015+ inode = ERR_PTR(err);
23016+ }
23017+
4f0767ce 23018+out:
1facf9fc 23019+ /* never return NULL */
23020+ AuDebugOn(!inode);
23021+ AuTraceErrPtr(inode);
23022+ return inode;
23023+}
23024+
23025+/* lock free root dinfo */
23026+static int au_show_brs(struct seq_file *seq, struct super_block *sb)
23027+{
23028+ int err;
23029+ aufs_bindex_t bindex, bend;
23030+ struct path path;
4a4d8108 23031+ struct au_hdentry *hdp;
1facf9fc 23032+ struct au_branch *br;
1e00d052 23033+ char *perm;
1facf9fc 23034+
23035+ err = 0;
23036+ bend = au_sbend(sb);
4a4d8108 23037+ hdp = au_di(sb->s_root)->di_hdentry;
1facf9fc 23038+ for (bindex = 0; !err && bindex <= bend; bindex++) {
23039+ br = au_sbr(sb, bindex);
23040+ path.mnt = br->br_mnt;
4a4d8108 23041+ path.dentry = hdp[bindex].hd_dentry;
1facf9fc 23042+ err = au_seq_path(seq, &path);
1e00d052
AM
23043+ if (err > 0) {
23044+ perm = au_optstr_br_perm(br->br_perm);
23045+ if (perm) {
23046+ err = seq_printf(seq, "=%s", perm);
23047+ kfree(perm);
23048+ if (err == -1)
23049+ err = -E2BIG;
23050+ } else
23051+ err = -ENOMEM;
23052+ }
1facf9fc 23053+ if (!err && bindex != bend)
23054+ err = seq_putc(seq, ':');
23055+ }
23056+
23057+ return err;
23058+}
23059+
23060+static void au_show_wbr_create(struct seq_file *m, int v,
23061+ struct au_sbinfo *sbinfo)
23062+{
23063+ const char *pat;
23064+
dece6358
AM
23065+ AuRwMustAnyLock(&sbinfo->si_rwsem);
23066+
1facf9fc 23067+ seq_printf(m, ",create=");
23068+ pat = au_optstr_wbr_create(v);
23069+ switch (v) {
23070+ case AuWbrCreate_TDP:
23071+ case AuWbrCreate_RR:
23072+ case AuWbrCreate_MFS:
23073+ case AuWbrCreate_PMFS:
23074+ seq_printf(m, pat);
23075+ break;
23076+ case AuWbrCreate_MFSV:
23077+ seq_printf(m, /*pat*/"mfs:%lu",
e49829fe
JR
23078+ jiffies_to_msecs(sbinfo->si_wbr_mfs.mfs_expire)
23079+ / MSEC_PER_SEC);
1facf9fc 23080+ break;
23081+ case AuWbrCreate_PMFSV:
23082+ seq_printf(m, /*pat*/"pmfs:%lu",
e49829fe
JR
23083+ jiffies_to_msecs(sbinfo->si_wbr_mfs.mfs_expire)
23084+ / MSEC_PER_SEC);
1facf9fc 23085+ break;
23086+ case AuWbrCreate_MFSRR:
23087+ seq_printf(m, /*pat*/"mfsrr:%llu",
23088+ sbinfo->si_wbr_mfs.mfsrr_watermark);
23089+ break;
23090+ case AuWbrCreate_MFSRRV:
23091+ seq_printf(m, /*pat*/"mfsrr:%llu:%lu",
23092+ sbinfo->si_wbr_mfs.mfsrr_watermark,
e49829fe
JR
23093+ jiffies_to_msecs(sbinfo->si_wbr_mfs.mfs_expire)
23094+ / MSEC_PER_SEC);
1facf9fc 23095+ break;
23096+ }
23097+}
23098+
7eafdf33 23099+static int au_show_xino(struct seq_file *seq, struct super_block *sb)
1facf9fc 23100+{
23101+#ifdef CONFIG_SYSFS
23102+ return 0;
23103+#else
23104+ int err;
23105+ const int len = sizeof(AUFS_XINO_FNAME) - 1;
23106+ aufs_bindex_t bindex, brid;
1facf9fc 23107+ struct qstr *name;
23108+ struct file *f;
23109+ struct dentry *d, *h_root;
4a4d8108 23110+ struct au_hdentry *hdp;
1facf9fc 23111+
dece6358
AM
23112+ AuRwMustAnyLock(&sbinfo->si_rwsem);
23113+
1facf9fc 23114+ err = 0;
1facf9fc 23115+ f = au_sbi(sb)->si_xib;
23116+ if (!f)
23117+ goto out;
23118+
23119+ /* stop printing the default xino path on the first writable branch */
23120+ h_root = NULL;
23121+ brid = au_xino_brid(sb);
23122+ if (brid >= 0) {
23123+ bindex = au_br_index(sb, brid);
4a4d8108
AM
23124+ hdp = au_di(sb->s_root)->di_hdentry;
23125+ h_root = hdp[0 + bindex].hd_dentry;
1facf9fc 23126+ }
23127+ d = f->f_dentry;
23128+ name = &d->d_name;
23129+ /* safe ->d_parent because the file is unlinked */
23130+ if (d->d_parent == h_root
23131+ && name->len == len
23132+ && !memcmp(name->name, AUFS_XINO_FNAME, len))
23133+ goto out;
23134+
23135+ seq_puts(seq, ",xino=");
23136+ err = au_xino_path(seq, f);
23137+
4f0767ce 23138+out:
1facf9fc 23139+ return err;
23140+#endif
23141+}
23142+
23143+/* seq_file will re-call me in case of too long string */
7eafdf33 23144+static int aufs_show_options(struct seq_file *m, struct dentry *dentry)
1facf9fc 23145+{
027c5e7a 23146+ int err;
1facf9fc 23147+ unsigned int mnt_flags, v;
23148+ struct super_block *sb;
23149+ struct au_sbinfo *sbinfo;
23150+
23151+#define AuBool(name, str) do { \
23152+ v = au_opt_test(mnt_flags, name); \
23153+ if (v != au_opt_test(AuOpt_Def, name)) \
23154+ seq_printf(m, ",%s" #str, v ? "" : "no"); \
23155+} while (0)
23156+
23157+#define AuStr(name, str) do { \
23158+ v = mnt_flags & AuOptMask_##name; \
23159+ if (v != (AuOpt_Def & AuOptMask_##name)) \
23160+ seq_printf(m, "," #str "=%s", au_optstr_##str(v)); \
23161+} while (0)
23162+
23163+#define AuUInt(name, str, val) do { \
23164+ if (val != AUFS_##name##_DEF) \
23165+ seq_printf(m, "," #str "=%u", val); \
23166+} while (0)
23167+
23168+ /* lock free root dinfo */
7eafdf33 23169+ sb = dentry->d_sb;
1facf9fc 23170+ si_noflush_read_lock(sb);
23171+ sbinfo = au_sbi(sb);
23172+ seq_printf(m, ",si=%lx", sysaufs_si_id(sbinfo));
23173+
23174+ mnt_flags = au_mntflags(sb);
23175+ if (au_opt_test(mnt_flags, XINO)) {
7eafdf33 23176+ err = au_show_xino(m, sb);
1facf9fc 23177+ if (unlikely(err))
23178+ goto out;
23179+ } else
23180+ seq_puts(m, ",noxino");
23181+
23182+ AuBool(TRUNC_XINO, trunc_xino);
23183+ AuStr(UDBA, udba);
dece6358 23184+ AuBool(SHWH, shwh);
1facf9fc 23185+ AuBool(PLINK, plink);
4a4d8108 23186+ AuBool(DIO, dio);
1facf9fc 23187+ /* AuBool(DIRPERM1, dirperm1); */
23188+ /* AuBool(REFROF, refrof); */
23189+
23190+ v = sbinfo->si_wbr_create;
23191+ if (v != AuWbrCreate_Def)
23192+ au_show_wbr_create(m, v, sbinfo);
23193+
23194+ v = sbinfo->si_wbr_copyup;
23195+ if (v != AuWbrCopyup_Def)
23196+ seq_printf(m, ",cpup=%s", au_optstr_wbr_copyup(v));
23197+
23198+ v = au_opt_test(mnt_flags, ALWAYS_DIROPQ);
23199+ if (v != au_opt_test(AuOpt_Def, ALWAYS_DIROPQ))
23200+ seq_printf(m, ",diropq=%c", v ? 'a' : 'w');
23201+
23202+ AuUInt(DIRWH, dirwh, sbinfo->si_dirwh);
23203+
027c5e7a
AM
23204+ v = jiffies_to_msecs(sbinfo->si_rdcache) / MSEC_PER_SEC;
23205+ AuUInt(RDCACHE, rdcache, v);
1facf9fc 23206+
23207+ AuUInt(RDBLK, rdblk, sbinfo->si_rdblk);
23208+ AuUInt(RDHASH, rdhash, sbinfo->si_rdhash);
23209+
23210+ AuBool(SUM, sum);
23211+ /* AuBool(SUM_W, wsum); */
23212+ AuBool(WARN_PERM, warn_perm);
23213+ AuBool(VERBOSE, verbose);
23214+
4f0767ce 23215+out:
1facf9fc 23216+ /* be sure to print "br:" last */
23217+ if (!sysaufs_brs) {
23218+ seq_puts(m, ",br:");
23219+ au_show_brs(m, sb);
23220+ }
23221+ si_read_unlock(sb);
23222+ return 0;
23223+
1facf9fc 23224+#undef AuBool
23225+#undef AuStr
4a4d8108 23226+#undef AuUInt
1facf9fc 23227+}
23228+
23229+/* ---------------------------------------------------------------------- */
23230+
23231+/* sum mode which returns the summation for statfs(2) */
23232+
23233+static u64 au_add_till_max(u64 a, u64 b)
23234+{
23235+ u64 old;
23236+
23237+ old = a;
23238+ a += b;
92d182d2
AM
23239+ if (old <= a)
23240+ return a;
23241+ return ULLONG_MAX;
23242+}
23243+
23244+static u64 au_mul_till_max(u64 a, long mul)
23245+{
23246+ u64 old;
23247+
23248+ old = a;
23249+ a *= mul;
23250+ if (old <= a)
1facf9fc 23251+ return a;
23252+ return ULLONG_MAX;
23253+}
23254+
23255+static int au_statfs_sum(struct super_block *sb, struct kstatfs *buf)
23256+{
23257+ int err;
92d182d2 23258+ long bsize, factor;
1facf9fc 23259+ u64 blocks, bfree, bavail, files, ffree;
23260+ aufs_bindex_t bend, bindex, i;
23261+ unsigned char shared;
7f207e10 23262+ struct path h_path;
1facf9fc 23263+ struct super_block *h_sb;
23264+
92d182d2
AM
23265+ err = 0;
23266+ bsize = LONG_MAX;
23267+ files = 0;
23268+ ffree = 0;
1facf9fc 23269+ blocks = 0;
23270+ bfree = 0;
23271+ bavail = 0;
1facf9fc 23272+ bend = au_sbend(sb);
92d182d2 23273+ for (bindex = 0; bindex <= bend; bindex++) {
7f207e10
AM
23274+ h_path.mnt = au_sbr_mnt(sb, bindex);
23275+ h_sb = h_path.mnt->mnt_sb;
1facf9fc 23276+ shared = 0;
92d182d2 23277+ for (i = 0; !shared && i < bindex; i++)
1facf9fc 23278+ shared = (au_sbr_sb(sb, i) == h_sb);
23279+ if (shared)
23280+ continue;
23281+
23282+ /* sb->s_root for NFS is unreliable */
7f207e10
AM
23283+ h_path.dentry = h_path.mnt->mnt_root;
23284+ err = vfs_statfs(&h_path, buf);
1facf9fc 23285+ if (unlikely(err))
23286+ goto out;
23287+
92d182d2
AM
23288+ if (bsize > buf->f_bsize) {
23289+ /*
23290+ * we will reduce bsize, so we have to expand blocks
23291+ * etc. to match them again
23292+ */
23293+ factor = (bsize / buf->f_bsize);
23294+ blocks = au_mul_till_max(blocks, factor);
23295+ bfree = au_mul_till_max(bfree, factor);
23296+ bavail = au_mul_till_max(bavail, factor);
23297+ bsize = buf->f_bsize;
23298+ }
23299+
23300+ factor = (buf->f_bsize / bsize);
23301+ blocks = au_add_till_max(blocks,
23302+ au_mul_till_max(buf->f_blocks, factor));
23303+ bfree = au_add_till_max(bfree,
23304+ au_mul_till_max(buf->f_bfree, factor));
23305+ bavail = au_add_till_max(bavail,
23306+ au_mul_till_max(buf->f_bavail, factor));
1facf9fc 23307+ files = au_add_till_max(files, buf->f_files);
23308+ ffree = au_add_till_max(ffree, buf->f_ffree);
23309+ }
23310+
92d182d2 23311+ buf->f_bsize = bsize;
1facf9fc 23312+ buf->f_blocks = blocks;
23313+ buf->f_bfree = bfree;
23314+ buf->f_bavail = bavail;
23315+ buf->f_files = files;
23316+ buf->f_ffree = ffree;
92d182d2 23317+ buf->f_frsize = 0;
1facf9fc 23318+
4f0767ce 23319+out:
1facf9fc 23320+ return err;
23321+}
23322+
23323+static int aufs_statfs(struct dentry *dentry, struct kstatfs *buf)
23324+{
23325+ int err;
7f207e10 23326+ struct path h_path;
1facf9fc 23327+ struct super_block *sb;
23328+
23329+ /* lock free root dinfo */
23330+ sb = dentry->d_sb;
23331+ si_noflush_read_lock(sb);
7f207e10 23332+ if (!au_opt_test(au_mntflags(sb), SUM)) {
1facf9fc 23333+ /* sb->s_root for NFS is unreliable */
7f207e10
AM
23334+ h_path.mnt = au_sbr_mnt(sb, 0);
23335+ h_path.dentry = h_path.mnt->mnt_root;
23336+ err = vfs_statfs(&h_path, buf);
23337+ } else
1facf9fc 23338+ err = au_statfs_sum(sb, buf);
23339+ si_read_unlock(sb);
23340+
23341+ if (!err) {
23342+ buf->f_type = AUFS_SUPER_MAGIC;
4a4d8108 23343+ buf->f_namelen = AUFS_MAX_NAMELEN;
1facf9fc 23344+ memset(&buf->f_fsid, 0, sizeof(buf->f_fsid));
23345+ }
23346+ /* buf->f_bsize = buf->f_blocks = buf->f_bfree = buf->f_bavail = -1; */
23347+
23348+ return err;
23349+}
23350+
23351+/* ---------------------------------------------------------------------- */
23352+
1facf9fc 23353+/* final actions when unmounting a file system */
23354+static void aufs_put_super(struct super_block *sb)
23355+{
23356+ struct au_sbinfo *sbinfo;
23357+
23358+ sbinfo = au_sbi(sb);
23359+ if (!sbinfo)
23360+ return;
23361+
1facf9fc 23362+ dbgaufs_si_fin(sbinfo);
23363+ kobject_put(&sbinfo->si_kobj);
23364+}
23365+
23366+/* ---------------------------------------------------------------------- */
23367+
7f207e10
AM
23368+void au_array_free(void *array)
23369+{
23370+ if (array) {
23371+ if (!is_vmalloc_addr(array))
23372+ kfree(array);
23373+ else
23374+ vfree(array);
23375+ }
23376+}
23377+
23378+void *au_array_alloc(unsigned long long *hint, au_arraycb_t cb, void *arg)
23379+{
23380+ void *array;
23381+ unsigned long long n;
23382+
23383+ array = NULL;
23384+ n = 0;
23385+ if (!*hint)
23386+ goto out;
23387+
23388+ if (*hint > ULLONG_MAX / sizeof(array)) {
23389+ array = ERR_PTR(-EMFILE);
23390+ pr_err("hint %llu\n", *hint);
23391+ goto out;
23392+ }
23393+
23394+ array = kmalloc(sizeof(array) * *hint, GFP_NOFS);
23395+ if (unlikely(!array))
23396+ array = vmalloc(sizeof(array) * *hint);
23397+ if (unlikely(!array)) {
23398+ array = ERR_PTR(-ENOMEM);
23399+ goto out;
23400+ }
23401+
23402+ n = cb(array, *hint, arg);
23403+ AuDebugOn(n > *hint);
23404+
23405+out:
23406+ *hint = n;
23407+ return array;
23408+}
23409+
23410+static unsigned long long au_iarray_cb(void *a,
23411+ unsigned long long max __maybe_unused,
23412+ void *arg)
23413+{
23414+ unsigned long long n;
23415+ struct inode **p, *inode;
23416+ struct list_head *head;
23417+
23418+ n = 0;
23419+ p = a;
23420+ head = arg;
2cbb1c4b 23421+ spin_lock(&inode_sb_list_lock);
7f207e10
AM
23422+ list_for_each_entry(inode, head, i_sb_list) {
23423+ if (!is_bad_inode(inode)
23424+ && au_ii(inode)->ii_bstart >= 0) {
2cbb1c4b
JR
23425+ spin_lock(&inode->i_lock);
23426+ if (atomic_read(&inode->i_count)) {
23427+ au_igrab(inode);
23428+ *p++ = inode;
23429+ n++;
23430+ AuDebugOn(n > max);
23431+ }
23432+ spin_unlock(&inode->i_lock);
7f207e10
AM
23433+ }
23434+ }
2cbb1c4b 23435+ spin_unlock(&inode_sb_list_lock);
7f207e10
AM
23436+
23437+ return n;
23438+}
23439+
23440+struct inode **au_iarray_alloc(struct super_block *sb, unsigned long long *max)
23441+{
23442+ *max = atomic_long_read(&au_sbi(sb)->si_ninodes);
23443+ return au_array_alloc(max, au_iarray_cb, &sb->s_inodes);
23444+}
23445+
23446+void au_iarray_free(struct inode **a, unsigned long long max)
23447+{
23448+ unsigned long long ull;
23449+
23450+ for (ull = 0; ull < max; ull++)
23451+ iput(a[ull]);
23452+ au_array_free(a);
23453+}
23454+
23455+/* ---------------------------------------------------------------------- */
23456+
1facf9fc 23457+/*
23458+ * refresh dentry and inode at remount time.
23459+ */
027c5e7a
AM
23460+/* todo: consolidate with simple_reval_dpath() and au_reval_for_attr() */
23461+static int au_do_refresh(struct dentry *dentry, unsigned int dir_flags,
23462+ struct dentry *parent)
1facf9fc 23463+{
23464+ int err;
1facf9fc 23465+
23466+ di_write_lock_child(dentry);
1facf9fc 23467+ di_read_lock_parent(parent, AuLock_IR);
027c5e7a
AM
23468+ err = au_refresh_dentry(dentry, parent);
23469+ if (!err && dir_flags)
23470+ au_hn_reset(dentry->d_inode, dir_flags);
1facf9fc 23471+ di_read_unlock(parent, AuLock_IR);
1facf9fc 23472+ di_write_unlock(dentry);
23473+
23474+ return err;
23475+}
23476+
027c5e7a
AM
23477+static int au_do_refresh_d(struct dentry *dentry, unsigned int sigen,
23478+ struct au_sbinfo *sbinfo,
23479+ const unsigned int dir_flags)
1facf9fc 23480+{
027c5e7a
AM
23481+ int err;
23482+ struct dentry *parent;
23483+ struct inode *inode;
23484+
23485+ err = 0;
23486+ parent = dget_parent(dentry);
23487+ if (!au_digen_test(parent, sigen) && au_digen_test(dentry, sigen)) {
23488+ inode = dentry->d_inode;
23489+ if (inode) {
23490+ if (!S_ISDIR(inode->i_mode))
23491+ err = au_do_refresh(dentry, /*dir_flags*/0,
23492+ parent);
23493+ else {
23494+ err = au_do_refresh(dentry, dir_flags, parent);
23495+ if (unlikely(err))
23496+ au_fset_si(sbinfo, FAILED_REFRESH_DIR);
23497+ }
23498+ } else
23499+ err = au_do_refresh(dentry, /*dir_flags*/0, parent);
23500+ AuDbgDentry(dentry);
23501+ }
23502+ dput(parent);
23503+
23504+ AuTraceErr(err);
23505+ return err;
1facf9fc 23506+}
23507+
027c5e7a 23508+static int au_refresh_d(struct super_block *sb)
1facf9fc 23509+{
23510+ int err, i, j, ndentry, e;
027c5e7a 23511+ unsigned int sigen;
1facf9fc 23512+ struct au_dcsub_pages dpages;
23513+ struct au_dpage *dpage;
027c5e7a
AM
23514+ struct dentry **dentries, *d;
23515+ struct au_sbinfo *sbinfo;
23516+ struct dentry *root = sb->s_root;
23517+ const unsigned int dir_flags = au_hi_flags(root->d_inode, /*isdir*/1);
1facf9fc 23518+
027c5e7a
AM
23519+ err = au_dpages_init(&dpages, GFP_NOFS);
23520+ if (unlikely(err))
1facf9fc 23521+ goto out;
027c5e7a
AM
23522+ err = au_dcsub_pages(&dpages, root, NULL, NULL);
23523+ if (unlikely(err))
1facf9fc 23524+ goto out_dpages;
1facf9fc 23525+
027c5e7a
AM
23526+ sigen = au_sigen(sb);
23527+ sbinfo = au_sbi(sb);
23528+ for (i = 0; i < dpages.ndpage; i++) {
1facf9fc 23529+ dpage = dpages.dpages + i;
23530+ dentries = dpage->dentries;
23531+ ndentry = dpage->ndentry;
027c5e7a 23532+ for (j = 0; j < ndentry; j++) {
1facf9fc 23533+ d = dentries[j];
027c5e7a
AM
23534+ e = au_do_refresh_d(d, sigen, sbinfo, dir_flags);
23535+ if (unlikely(e && !err))
23536+ err = e;
23537+ /* go on even err */
1facf9fc 23538+ }
23539+ }
23540+
4f0767ce 23541+out_dpages:
1facf9fc 23542+ au_dpages_free(&dpages);
4f0767ce 23543+out:
1facf9fc 23544+ return err;
23545+}
23546+
027c5e7a 23547+static int au_refresh_i(struct super_block *sb)
1facf9fc 23548+{
027c5e7a
AM
23549+ int err, e;
23550+ unsigned int sigen;
23551+ unsigned long long max, ull;
23552+ struct inode *inode, **array;
1facf9fc 23553+
027c5e7a
AM
23554+ array = au_iarray_alloc(sb, &max);
23555+ err = PTR_ERR(array);
23556+ if (IS_ERR(array))
23557+ goto out;
1facf9fc 23558+
23559+ err = 0;
027c5e7a
AM
23560+ sigen = au_sigen(sb);
23561+ for (ull = 0; ull < max; ull++) {
23562+ inode = array[ull];
23563+ if (au_iigen(inode) != sigen) {
1facf9fc 23564+ ii_write_lock_child(inode);
027c5e7a 23565+ e = au_refresh_hinode_self(inode);
1facf9fc 23566+ ii_write_unlock(inode);
23567+ if (unlikely(e)) {
027c5e7a 23568+ pr_err("error %d, i%lu\n", e, inode->i_ino);
1facf9fc 23569+ if (!err)
23570+ err = e;
23571+ /* go on even if err */
23572+ }
23573+ }
1facf9fc 23574+ }
23575+
027c5e7a 23576+ au_iarray_free(array, max);
1facf9fc 23577+
4f0767ce 23578+out:
1facf9fc 23579+ return err;
23580+}
23581+
027c5e7a 23582+static void au_remount_refresh(struct super_block *sb)
1facf9fc 23583+{
027c5e7a
AM
23584+ int err, e;
23585+ unsigned int udba;
23586+ aufs_bindex_t bindex, bend;
1facf9fc 23587+ struct dentry *root;
23588+ struct inode *inode;
027c5e7a 23589+ struct au_branch *br;
1facf9fc 23590+
23591+ au_sigen_inc(sb);
027c5e7a 23592+ au_fclr_si(au_sbi(sb), FAILED_REFRESH_DIR);
1facf9fc 23593+
23594+ root = sb->s_root;
23595+ DiMustNoWaiters(root);
23596+ inode = root->d_inode;
23597+ IiMustNoWaiters(inode);
1facf9fc 23598+
027c5e7a
AM
23599+ udba = au_opt_udba(sb);
23600+ bend = au_sbend(sb);
23601+ for (bindex = 0; bindex <= bend; bindex++) {
23602+ br = au_sbr(sb, bindex);
23603+ err = au_hnotify_reset_br(udba, br, br->br_perm);
1facf9fc 23604+ if (unlikely(err))
027c5e7a
AM
23605+ AuIOErr("hnotify failed on br %d, %d, ignored\n",
23606+ bindex, err);
23607+ /* go on even if err */
1facf9fc 23608+ }
027c5e7a 23609+ au_hn_reset(inode, au_hi_flags(inode, /*isdir*/1));
1facf9fc 23610+
027c5e7a
AM
23611+ di_write_unlock(root);
23612+ err = au_refresh_d(sb);
23613+ e = au_refresh_i(sb);
23614+ if (unlikely(e && !err))
23615+ err = e;
1facf9fc 23616+ /* aufs_write_lock() calls ..._child() */
23617+ di_write_lock_child(root);
027c5e7a
AM
23618+
23619+ au_cpup_attr_all(inode, /*force*/1);
23620+
23621+ if (unlikely(err))
23622+ AuIOErr("refresh failed, ignored, %d\n", err);
1facf9fc 23623+}
23624+
23625+/* stop extra interpretation of errno in mount(8), and strange error messages */
23626+static int cvt_err(int err)
23627+{
23628+ AuTraceErr(err);
23629+
23630+ switch (err) {
23631+ case -ENOENT:
23632+ case -ENOTDIR:
23633+ case -EEXIST:
23634+ case -EIO:
23635+ err = -EINVAL;
23636+ }
23637+ return err;
23638+}
23639+
23640+static int aufs_remount_fs(struct super_block *sb, int *flags, char *data)
23641+{
4a4d8108
AM
23642+ int err, do_dx;
23643+ unsigned int mntflags;
1facf9fc 23644+ struct au_opts opts;
23645+ struct dentry *root;
23646+ struct inode *inode;
23647+ struct au_sbinfo *sbinfo;
23648+
23649+ err = 0;
23650+ root = sb->s_root;
23651+ if (!data || !*data) {
e49829fe
JR
23652+ err = si_write_lock(sb, AuLock_FLUSH | AuLock_NOPLM);
23653+ if (!err) {
23654+ di_write_lock_child(root);
23655+ err = au_opts_verify(sb, *flags, /*pending*/0);
23656+ aufs_write_unlock(root);
23657+ }
1facf9fc 23658+ goto out;
23659+ }
23660+
23661+ err = -ENOMEM;
23662+ memset(&opts, 0, sizeof(opts));
23663+ opts.opt = (void *)__get_free_page(GFP_NOFS);
23664+ if (unlikely(!opts.opt))
23665+ goto out;
23666+ opts.max_opt = PAGE_SIZE / sizeof(*opts.opt);
23667+ opts.flags = AuOpts_REMOUNT;
23668+ opts.sb_flags = *flags;
23669+
23670+ /* parse it before aufs lock */
23671+ err = au_opts_parse(sb, data, &opts);
23672+ if (unlikely(err))
23673+ goto out_opts;
23674+
23675+ sbinfo = au_sbi(sb);
23676+ inode = root->d_inode;
23677+ mutex_lock(&inode->i_mutex);
e49829fe
JR
23678+ err = si_write_lock(sb, AuLock_FLUSH | AuLock_NOPLM);
23679+ if (unlikely(err))
23680+ goto out_mtx;
23681+ di_write_lock_child(root);
1facf9fc 23682+
23683+ /* au_opts_remount() may return an error */
23684+ err = au_opts_remount(sb, &opts);
23685+ au_opts_free(&opts);
23686+
027c5e7a
AM
23687+ if (au_ftest_opts(opts.flags, REFRESH))
23688+ au_remount_refresh(sb);
1facf9fc 23689+
4a4d8108
AM
23690+ if (au_ftest_opts(opts.flags, REFRESH_DYAOP)) {
23691+ mntflags = au_mntflags(sb);
23692+ do_dx = !!au_opt_test(mntflags, DIO);
23693+ au_dy_arefresh(do_dx);
23694+ }
23695+
1facf9fc 23696+ aufs_write_unlock(root);
953406b4 23697+
e49829fe
JR
23698+out_mtx:
23699+ mutex_unlock(&inode->i_mutex);
4f0767ce 23700+out_opts:
1facf9fc 23701+ free_page((unsigned long)opts.opt);
4f0767ce 23702+out:
1facf9fc 23703+ err = cvt_err(err);
23704+ AuTraceErr(err);
23705+ return err;
23706+}
23707+
4a4d8108 23708+static const struct super_operations aufs_sop = {
1facf9fc 23709+ .alloc_inode = aufs_alloc_inode,
23710+ .destroy_inode = aufs_destroy_inode,
b752ccd1 23711+ /* always deleting, no clearing */
1facf9fc 23712+ .drop_inode = generic_delete_inode,
23713+ .show_options = aufs_show_options,
23714+ .statfs = aufs_statfs,
23715+ .put_super = aufs_put_super,
23716+ .remount_fs = aufs_remount_fs
23717+};
23718+
23719+/* ---------------------------------------------------------------------- */
23720+
23721+static int alloc_root(struct super_block *sb)
23722+{
23723+ int err;
23724+ struct inode *inode;
23725+ struct dentry *root;
23726+
23727+ err = -ENOMEM;
23728+ inode = au_iget_locked(sb, AUFS_ROOT_INO);
23729+ err = PTR_ERR(inode);
23730+ if (IS_ERR(inode))
23731+ goto out;
23732+
23733+ inode->i_op = &aufs_dir_iop;
23734+ inode->i_fop = &aufs_dir_fop;
23735+ inode->i_mode = S_IFDIR;
9dbd164d 23736+ set_nlink(inode, 2);
1facf9fc 23737+ unlock_new_inode(inode);
23738+
92d182d2 23739+ root = d_make_root(inode);
1facf9fc 23740+ if (unlikely(!root))
92d182d2 23741+ goto out;
1facf9fc 23742+ err = PTR_ERR(root);
23743+ if (IS_ERR(root))
92d182d2 23744+ goto out;
1facf9fc 23745+
4a4d8108 23746+ err = au_di_init(root);
1facf9fc 23747+ if (!err) {
23748+ sb->s_root = root;
23749+ return 0; /* success */
23750+ }
23751+ dput(root);
1facf9fc 23752+
4f0767ce 23753+out:
1facf9fc 23754+ return err;
1facf9fc 23755+}
23756+
23757+static int aufs_fill_super(struct super_block *sb, void *raw_data,
23758+ int silent __maybe_unused)
23759+{
23760+ int err;
23761+ struct au_opts opts;
23762+ struct dentry *root;
23763+ struct inode *inode;
23764+ char *arg = raw_data;
23765+
23766+ if (unlikely(!arg || !*arg)) {
23767+ err = -EINVAL;
4a4d8108 23768+ pr_err("no arg\n");
1facf9fc 23769+ goto out;
23770+ }
23771+
23772+ err = -ENOMEM;
23773+ memset(&opts, 0, sizeof(opts));
23774+ opts.opt = (void *)__get_free_page(GFP_NOFS);
23775+ if (unlikely(!opts.opt))
23776+ goto out;
23777+ opts.max_opt = PAGE_SIZE / sizeof(*opts.opt);
23778+ opts.sb_flags = sb->s_flags;
23779+
23780+ err = au_si_alloc(sb);
23781+ if (unlikely(err))
23782+ goto out_opts;
23783+
23784+ /* all timestamps always follow the ones on the branch */
23785+ sb->s_flags |= MS_NOATIME | MS_NODIRATIME;
23786+ sb->s_op = &aufs_sop;
027c5e7a 23787+ sb->s_d_op = &aufs_dop;
1facf9fc 23788+ sb->s_magic = AUFS_SUPER_MAGIC;
23789+ sb->s_maxbytes = 0;
23790+ au_export_init(sb);
23791+
23792+ err = alloc_root(sb);
23793+ if (unlikely(err)) {
23794+ si_write_unlock(sb);
23795+ goto out_info;
23796+ }
23797+ root = sb->s_root;
23798+ inode = root->d_inode;
23799+
23800+ /*
23801+ * actually we can parse options regardless aufs lock here.
23802+ * but at remount time, parsing must be done before aufs lock.
23803+ * so we follow the same rule.
23804+ */
23805+ ii_write_lock_parent(inode);
23806+ aufs_write_unlock(root);
23807+ err = au_opts_parse(sb, arg, &opts);
23808+ if (unlikely(err))
23809+ goto out_root;
23810+
23811+ /* lock vfs_inode first, then aufs. */
23812+ mutex_lock(&inode->i_mutex);
1facf9fc 23813+ aufs_write_lock(root);
23814+ err = au_opts_mount(sb, &opts);
23815+ au_opts_free(&opts);
1facf9fc 23816+ aufs_write_unlock(root);
23817+ mutex_unlock(&inode->i_mutex);
4a4d8108
AM
23818+ if (!err)
23819+ goto out_opts; /* success */
1facf9fc 23820+
4f0767ce 23821+out_root:
1facf9fc 23822+ dput(root);
23823+ sb->s_root = NULL;
4f0767ce 23824+out_info:
2cbb1c4b 23825+ dbgaufs_si_fin(au_sbi(sb));
1facf9fc 23826+ kobject_put(&au_sbi(sb)->si_kobj);
23827+ sb->s_fs_info = NULL;
4f0767ce 23828+out_opts:
1facf9fc 23829+ free_page((unsigned long)opts.opt);
4f0767ce 23830+out:
1facf9fc 23831+ AuTraceErr(err);
23832+ err = cvt_err(err);
23833+ AuTraceErr(err);
23834+ return err;
23835+}
23836+
23837+/* ---------------------------------------------------------------------- */
23838+
027c5e7a
AM
23839+static struct dentry *aufs_mount(struct file_system_type *fs_type, int flags,
23840+ const char *dev_name __maybe_unused,
23841+ void *raw_data)
1facf9fc 23842+{
027c5e7a 23843+ struct dentry *root;
1facf9fc 23844+ struct super_block *sb;
23845+
23846+ /* all timestamps always follow the ones on the branch */
23847+ /* mnt->mnt_flags |= MNT_NOATIME | MNT_NODIRATIME; */
027c5e7a
AM
23848+ root = mount_nodev(fs_type, flags, raw_data, aufs_fill_super);
23849+ if (IS_ERR(root))
23850+ goto out;
23851+
23852+ sb = root->d_sb;
23853+ si_write_lock(sb, !AuLock_FLUSH);
23854+ sysaufs_brs_add(sb, 0);
23855+ si_write_unlock(sb);
23856+ au_sbilist_add(sb);
23857+
23858+out:
23859+ return root;
1facf9fc 23860+}
23861+
e49829fe
JR
23862+static void aufs_kill_sb(struct super_block *sb)
23863+{
23864+ struct au_sbinfo *sbinfo;
23865+
23866+ sbinfo = au_sbi(sb);
23867+ if (sbinfo) {
23868+ au_sbilist_del(sb);
23869+ aufs_write_lock(sb->s_root);
23870+ if (sbinfo->si_wbr_create_ops->fin)
23871+ sbinfo->si_wbr_create_ops->fin(sb);
23872+ if (au_opt_test(sbinfo->si_mntflags, UDBA_HNOTIFY)) {
23873+ au_opt_set_udba(sbinfo->si_mntflags, UDBA_NONE);
027c5e7a 23874+ au_remount_refresh(sb);
e49829fe
JR
23875+ }
23876+ if (au_opt_test(sbinfo->si_mntflags, PLINK))
23877+ au_plink_put(sb, /*verbose*/1);
23878+ au_xino_clr(sb);
1e00d052 23879+ sbinfo->si_sb = NULL;
e49829fe 23880+ aufs_write_unlock(sb->s_root);
e49829fe
JR
23881+ au_nwt_flush(&sbinfo->si_nowait);
23882+ }
23883+ generic_shutdown_super(sb);
23884+}
23885+
1facf9fc 23886+struct file_system_type aufs_fs_type = {
23887+ .name = AUFS_FSTYPE,
23888+ .fs_flags =
23889+ FS_RENAME_DOES_D_MOVE /* a race between rename and others */
23890+ | FS_REVAL_DOT, /* for NFS branch and udba */
027c5e7a 23891+ .mount = aufs_mount,
e49829fe 23892+ .kill_sb = aufs_kill_sb,
1facf9fc 23893+ /* no need to __module_get() and module_put(). */
23894+ .owner = THIS_MODULE,
23895+};
7f207e10
AM
23896diff -urN /usr/share/empty/fs/aufs/super.h linux/fs/aufs/super.h
23897--- /usr/share/empty/fs/aufs/super.h 1970-01-01 01:00:00.000000000 +0100
0c3ec466 23898+++ linux/fs/aufs/super.h 2012-07-22 19:57:03.164337936 +0200
f6c5ef8b 23899@@ -0,0 +1,546 @@
1facf9fc 23900+/*
f6c5ef8b 23901+ * Copyright (C) 2005-2012 Junjiro R. Okajima
1facf9fc 23902+ *
23903+ * This program, aufs is free software; you can redistribute it and/or modify
23904+ * it under the terms of the GNU General Public License as published by
23905+ * the Free Software Foundation; either version 2 of the License, or
23906+ * (at your option) any later version.
dece6358
AM
23907+ *
23908+ * This program is distributed in the hope that it will be useful,
23909+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
23910+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23911+ * GNU General Public License for more details.
23912+ *
23913+ * You should have received a copy of the GNU General Public License
23914+ * along with this program; if not, write to the Free Software
23915+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 23916+ */
23917+
23918+/*
23919+ * super_block operations
23920+ */
23921+
23922+#ifndef __AUFS_SUPER_H__
23923+#define __AUFS_SUPER_H__
23924+
23925+#ifdef __KERNEL__
23926+
23927+#include <linux/fs.h>
1facf9fc 23928+#include "rwsem.h"
23929+#include "spl.h"
23930+#include "wkq.h"
23931+
23932+typedef ssize_t (*au_readf_t)(struct file *, char __user *, size_t, loff_t *);
23933+typedef ssize_t (*au_writef_t)(struct file *, const char __user *, size_t,
23934+ loff_t *);
23935+
23936+/* policies to select one among multiple writable branches */
23937+struct au_wbr_copyup_operations {
23938+ int (*copyup)(struct dentry *dentry);
23939+};
23940+
23941+struct au_wbr_create_operations {
23942+ int (*create)(struct dentry *dentry, int isdir);
23943+ int (*init)(struct super_block *sb);
23944+ int (*fin)(struct super_block *sb);
23945+};
23946+
23947+struct au_wbr_mfs {
23948+ struct mutex mfs_lock; /* protect this structure */
23949+ unsigned long mfs_jiffy;
23950+ unsigned long mfs_expire;
23951+ aufs_bindex_t mfs_bindex;
23952+
23953+ unsigned long long mfsrr_bytes;
23954+ unsigned long long mfsrr_watermark;
23955+};
23956+
1facf9fc 23957+struct au_branch;
23958+struct au_sbinfo {
23959+ /* nowait tasks in the system-wide workqueue */
23960+ struct au_nowait_tasks si_nowait;
23961+
b752ccd1
AM
23962+ /*
23963+ * tried sb->s_umount, but failed due to the dependecy between i_mutex.
23964+ * rwsem for au_sbinfo is necessary.
23965+ */
dece6358 23966+ struct au_rwsem si_rwsem;
1facf9fc 23967+
b752ccd1
AM
23968+ /* prevent recursive locking in deleting inode */
23969+ struct {
23970+ unsigned long *bitmap;
23971+ spinlock_t tree_lock;
23972+ struct radix_tree_root tree;
23973+ } au_si_pid;
23974+
7f207e10
AM
23975+ /*
23976+ * dirty approach to protect sb->sb_inodes and ->s_files from remount.
23977+ */
23978+ atomic_long_t si_ninodes, si_nfiles;
23979+
1facf9fc 23980+ /* branch management */
23981+ unsigned int si_generation;
23982+
23983+ /* see above flags */
23984+ unsigned char au_si_status;
23985+
23986+ aufs_bindex_t si_bend;
7f207e10
AM
23987+
23988+ /* dirty trick to keep br_id plus */
23989+ unsigned int si_last_br_id :
23990+ sizeof(aufs_bindex_t) * BITS_PER_BYTE - 1;
1facf9fc 23991+ struct au_branch **si_branch;
23992+
23993+ /* policy to select a writable branch */
23994+ unsigned char si_wbr_copyup;
23995+ unsigned char si_wbr_create;
23996+ struct au_wbr_copyup_operations *si_wbr_copyup_ops;
23997+ struct au_wbr_create_operations *si_wbr_create_ops;
23998+
23999+ /* round robin */
24000+ atomic_t si_wbr_rr_next;
24001+
24002+ /* most free space */
24003+ struct au_wbr_mfs si_wbr_mfs;
24004+
24005+ /* mount flags */
24006+ /* include/asm-ia64/siginfo.h defines a macro named si_flags */
24007+ unsigned int si_mntflags;
24008+
24009+ /* external inode number (bitmap and translation table) */
24010+ au_readf_t si_xread;
24011+ au_writef_t si_xwrite;
24012+ struct file *si_xib;
24013+ struct mutex si_xib_mtx; /* protect xib members */
24014+ unsigned long *si_xib_buf;
24015+ unsigned long si_xib_last_pindex;
24016+ int si_xib_next_bit;
24017+ aufs_bindex_t si_xino_brid;
24018+ /* reserved for future use */
24019+ /* unsigned long long si_xib_limit; */ /* Max xib file size */
24020+
24021+#ifdef CONFIG_AUFS_EXPORT
24022+ /* i_generation */
24023+ struct file *si_xigen;
24024+ atomic_t si_xigen_next;
24025+#endif
24026+
24027+ /* vdir parameters */
e49829fe 24028+ unsigned long si_rdcache; /* max cache time in jiffies */
1facf9fc 24029+ unsigned int si_rdblk; /* deblk size */
24030+ unsigned int si_rdhash; /* hash size */
24031+
24032+ /*
24033+ * If the number of whiteouts are larger than si_dirwh, leave all of
24034+ * them after au_whtmp_ren to reduce the cost of rmdir(2).
24035+ * future fsck.aufs or kernel thread will remove them later.
24036+ * Otherwise, remove all whiteouts and the dir in rmdir(2).
24037+ */
24038+ unsigned int si_dirwh;
24039+
24040+ /*
24041+ * rename(2) a directory with all children.
24042+ */
24043+ /* reserved for future use */
24044+ /* int si_rendir; */
24045+
24046+ /* pseudo_link list */
24047+ struct au_splhead si_plink;
24048+ wait_queue_head_t si_plink_wq;
4a4d8108 24049+ spinlock_t si_plink_maint_lock;
e49829fe 24050+ pid_t si_plink_maint_pid;
1facf9fc 24051+
24052+ /*
24053+ * sysfs and lifetime management.
24054+ * this is not a small structure and it may be a waste of memory in case
24055+ * of sysfs is disabled, particulary when many aufs-es are mounted.
24056+ * but using sysfs is majority.
24057+ */
24058+ struct kobject si_kobj;
24059+#ifdef CONFIG_DEBUG_FS
24060+ struct dentry *si_dbgaufs, *si_dbgaufs_xib;
24061+#ifdef CONFIG_AUFS_EXPORT
24062+ struct dentry *si_dbgaufs_xigen;
24063+#endif
24064+#endif
24065+
e49829fe
JR
24066+#ifdef CONFIG_AUFS_SBILIST
24067+ struct list_head si_list;
24068+#endif
24069+
1facf9fc 24070+ /* dirty, necessary for unmounting, sysfs and sysrq */
24071+ struct super_block *si_sb;
24072+};
24073+
dece6358
AM
24074+/* sbinfo status flags */
24075+/*
24076+ * set true when refresh_dirs() failed at remount time.
24077+ * then try refreshing dirs at access time again.
24078+ * if it is false, refreshing dirs at access time is unnecesary
24079+ */
027c5e7a 24080+#define AuSi_FAILED_REFRESH_DIR 1
dece6358
AM
24081+static inline unsigned char au_do_ftest_si(struct au_sbinfo *sbi,
24082+ unsigned int flag)
24083+{
24084+ AuRwMustAnyLock(&sbi->si_rwsem);
24085+ return sbi->au_si_status & flag;
24086+}
24087+#define au_ftest_si(sbinfo, name) au_do_ftest_si(sbinfo, AuSi_##name)
24088+#define au_fset_si(sbinfo, name) do { \
24089+ AuRwMustWriteLock(&(sbinfo)->si_rwsem); \
24090+ (sbinfo)->au_si_status |= AuSi_##name; \
24091+} while (0)
24092+#define au_fclr_si(sbinfo, name) do { \
24093+ AuRwMustWriteLock(&(sbinfo)->si_rwsem); \
24094+ (sbinfo)->au_si_status &= ~AuSi_##name; \
24095+} while (0)
24096+
1facf9fc 24097+/* ---------------------------------------------------------------------- */
24098+
24099+/* policy to select one among writable branches */
4a4d8108
AM
24100+#define AuWbrCopyup(sbinfo, ...) \
24101+ ((sbinfo)->si_wbr_copyup_ops->copyup(__VA_ARGS__))
24102+#define AuWbrCreate(sbinfo, ...) \
24103+ ((sbinfo)->si_wbr_create_ops->create(__VA_ARGS__))
1facf9fc 24104+
24105+/* flags for si_read_lock()/aufs_read_lock()/di_read_lock() */
24106+#define AuLock_DW 1 /* write-lock dentry */
24107+#define AuLock_IR (1 << 1) /* read-lock inode */
24108+#define AuLock_IW (1 << 2) /* write-lock inode */
24109+#define AuLock_FLUSH (1 << 3) /* wait for 'nowait' tasks */
24110+#define AuLock_DIR (1 << 4) /* target is a dir */
e49829fe
JR
24111+#define AuLock_NOPLM (1 << 5) /* return err in plm mode */
24112+#define AuLock_NOPLMW (1 << 6) /* wait for plm mode ends */
027c5e7a 24113+#define AuLock_GEN (1 << 7) /* test digen/iigen */
1facf9fc 24114+#define au_ftest_lock(flags, name) ((flags) & AuLock_##name)
7f207e10
AM
24115+#define au_fset_lock(flags, name) \
24116+ do { (flags) |= AuLock_##name; } while (0)
24117+#define au_fclr_lock(flags, name) \
24118+ do { (flags) &= ~AuLock_##name; } while (0)
1facf9fc 24119+
24120+/* ---------------------------------------------------------------------- */
24121+
24122+/* super.c */
24123+extern struct file_system_type aufs_fs_type;
24124+struct inode *au_iget_locked(struct super_block *sb, ino_t ino);
7f207e10
AM
24125+typedef unsigned long long (*au_arraycb_t)(void *array, unsigned long long max,
24126+ void *arg);
24127+void au_array_free(void *array);
24128+void *au_array_alloc(unsigned long long *hint, au_arraycb_t cb, void *arg);
24129+struct inode **au_iarray_alloc(struct super_block *sb, unsigned long long *max);
24130+void au_iarray_free(struct inode **a, unsigned long long max);
1facf9fc 24131+
24132+/* sbinfo.c */
24133+void au_si_free(struct kobject *kobj);
24134+int au_si_alloc(struct super_block *sb);
24135+int au_sbr_realloc(struct au_sbinfo *sbinfo, int nbr);
24136+
24137+unsigned int au_sigen_inc(struct super_block *sb);
24138+aufs_bindex_t au_new_br_id(struct super_block *sb);
24139+
e49829fe
JR
24140+int si_read_lock(struct super_block *sb, int flags);
24141+int si_write_lock(struct super_block *sb, int flags);
24142+int aufs_read_lock(struct dentry *dentry, int flags);
1facf9fc 24143+void aufs_read_unlock(struct dentry *dentry, int flags);
24144+void aufs_write_lock(struct dentry *dentry);
24145+void aufs_write_unlock(struct dentry *dentry);
e49829fe 24146+int aufs_read_and_write_lock2(struct dentry *d1, struct dentry *d2, int flags);
1facf9fc 24147+void aufs_read_and_write_unlock2(struct dentry *d1, struct dentry *d2);
24148+
b752ccd1
AM
24149+int si_pid_test_slow(struct super_block *sb);
24150+void si_pid_set_slow(struct super_block *sb);
24151+void si_pid_clr_slow(struct super_block *sb);
24152+
1facf9fc 24153+/* wbr_policy.c */
24154+extern struct au_wbr_copyup_operations au_wbr_copyup_ops[];
24155+extern struct au_wbr_create_operations au_wbr_create_ops[];
24156+int au_cpdown_dirs(struct dentry *dentry, aufs_bindex_t bdst);
24157+
24158+/* ---------------------------------------------------------------------- */
24159+
24160+static inline struct au_sbinfo *au_sbi(struct super_block *sb)
24161+{
24162+ return sb->s_fs_info;
24163+}
24164+
24165+/* ---------------------------------------------------------------------- */
24166+
24167+#ifdef CONFIG_AUFS_EXPORT
24168+void au_export_init(struct super_block *sb);
24169+
b752ccd1 24170+static inline int au_test_nfsd(void)
1facf9fc 24171+{
b752ccd1
AM
24172+ struct task_struct *tsk = current;
24173+
24174+ return (tsk->flags & PF_KTHREAD)
24175+ && !strcmp(tsk->comm, "nfsd");
1facf9fc 24176+}
24177+
b752ccd1 24178+void au_xigen_inc(struct inode *inode);
1facf9fc 24179+int au_xigen_new(struct inode *inode);
24180+int au_xigen_set(struct super_block *sb, struct file *base);
24181+void au_xigen_clr(struct super_block *sb);
24182+
24183+static inline int au_busy_or_stale(void)
24184+{
b752ccd1 24185+ if (!au_test_nfsd())
1facf9fc 24186+ return -EBUSY;
24187+ return -ESTALE;
24188+}
24189+#else
4a4d8108 24190+AuStubVoid(au_export_init, struct super_block *sb)
b752ccd1
AM
24191+AuStubInt0(au_test_nfsd, void)
24192+AuStubVoid(au_xigen_inc, struct inode *inode)
4a4d8108
AM
24193+AuStubInt0(au_xigen_new, struct inode *inode)
24194+AuStubInt0(au_xigen_set, struct super_block *sb, struct file *base)
24195+AuStubVoid(au_xigen_clr, struct super_block *sb)
1facf9fc 24196+static inline int au_busy_or_stale(void)
24197+{
24198+ return -EBUSY;
24199+}
24200+#endif /* CONFIG_AUFS_EXPORT */
24201+
24202+/* ---------------------------------------------------------------------- */
24203+
e49829fe
JR
24204+#ifdef CONFIG_AUFS_SBILIST
24205+/* module.c */
24206+extern struct au_splhead au_sbilist;
24207+
24208+static inline void au_sbilist_init(void)
24209+{
24210+ au_spl_init(&au_sbilist);
24211+}
24212+
24213+static inline void au_sbilist_add(struct super_block *sb)
24214+{
24215+ au_spl_add(&au_sbi(sb)->si_list, &au_sbilist);
24216+}
24217+
24218+static inline void au_sbilist_del(struct super_block *sb)
24219+{
24220+ au_spl_del(&au_sbi(sb)->si_list, &au_sbilist);
24221+}
53392da6
AM
24222+
24223+#ifdef CONFIG_AUFS_MAGIC_SYSRQ
24224+static inline void au_sbilist_lock(void)
24225+{
24226+ spin_lock(&au_sbilist.spin);
24227+}
24228+
24229+static inline void au_sbilist_unlock(void)
24230+{
24231+ spin_unlock(&au_sbilist.spin);
24232+}
24233+#define AuGFP_SBILIST GFP_ATOMIC
24234+#else
24235+AuStubVoid(au_sbilist_lock, void)
24236+AuStubVoid(au_sbilist_unlock, void)
24237+#define AuGFP_SBILIST GFP_NOFS
24238+#endif /* CONFIG_AUFS_MAGIC_SYSRQ */
e49829fe
JR
24239+#else
24240+AuStubVoid(au_sbilist_init, void)
24241+AuStubVoid(au_sbilist_add, struct super_block*)
24242+AuStubVoid(au_sbilist_del, struct super_block*)
53392da6
AM
24243+AuStubVoid(au_sbilist_lock, void)
24244+AuStubVoid(au_sbilist_unlock, void)
24245+#define AuGFP_SBILIST GFP_NOFS
e49829fe
JR
24246+#endif
24247+
24248+/* ---------------------------------------------------------------------- */
24249+
1facf9fc 24250+static inline void dbgaufs_si_null(struct au_sbinfo *sbinfo)
24251+{
dece6358
AM
24252+ /*
24253+ * This function is a dynamic '__init' fucntion actually,
24254+ * so the tiny check for si_rwsem is unnecessary.
24255+ */
24256+ /* AuRwMustWriteLock(&sbinfo->si_rwsem); */
1facf9fc 24257+#ifdef CONFIG_DEBUG_FS
24258+ sbinfo->si_dbgaufs = NULL;
24259+ sbinfo->si_dbgaufs_xib = NULL;
24260+#ifdef CONFIG_AUFS_EXPORT
24261+ sbinfo->si_dbgaufs_xigen = NULL;
24262+#endif
24263+#endif
24264+}
24265+
24266+/* ---------------------------------------------------------------------- */
24267+
b752ccd1
AM
24268+static inline pid_t si_pid_bit(void)
24269+{
24270+ /* the origin of pid is 1, but the bitmap's is 0 */
24271+ return current->pid - 1;
24272+}
24273+
24274+static inline int si_pid_test(struct super_block *sb)
24275+{
24276+ pid_t bit = si_pid_bit();
24277+ if (bit < PID_MAX_DEFAULT)
24278+ return test_bit(bit, au_sbi(sb)->au_si_pid.bitmap);
24279+ else
24280+ return si_pid_test_slow(sb);
24281+}
24282+
24283+static inline void si_pid_set(struct super_block *sb)
24284+{
24285+ pid_t bit = si_pid_bit();
24286+ if (bit < PID_MAX_DEFAULT) {
24287+ AuDebugOn(test_bit(bit, au_sbi(sb)->au_si_pid.bitmap));
24288+ set_bit(bit, au_sbi(sb)->au_si_pid.bitmap);
24289+ /* smp_mb(); */
24290+ } else
24291+ si_pid_set_slow(sb);
24292+}
24293+
24294+static inline void si_pid_clr(struct super_block *sb)
24295+{
24296+ pid_t bit = si_pid_bit();
24297+ if (bit < PID_MAX_DEFAULT) {
24298+ AuDebugOn(!test_bit(bit, au_sbi(sb)->au_si_pid.bitmap));
24299+ clear_bit(bit, au_sbi(sb)->au_si_pid.bitmap);
24300+ /* smp_mb(); */
24301+ } else
24302+ si_pid_clr_slow(sb);
24303+}
24304+
24305+/* ---------------------------------------------------------------------- */
24306+
1facf9fc 24307+/* lock superblock. mainly for entry point functions */
24308+/*
b752ccd1
AM
24309+ * __si_read_lock, __si_write_lock,
24310+ * __si_read_unlock, __si_write_unlock, __si_downgrade_lock
1facf9fc 24311+ */
b752ccd1 24312+AuSimpleRwsemFuncs(__si, struct super_block *sb, &au_sbi(sb)->si_rwsem);
1facf9fc 24313+
dece6358
AM
24314+#define SiMustNoWaiters(sb) AuRwMustNoWaiters(&au_sbi(sb)->si_rwsem)
24315+#define SiMustAnyLock(sb) AuRwMustAnyLock(&au_sbi(sb)->si_rwsem)
24316+#define SiMustWriteLock(sb) AuRwMustWriteLock(&au_sbi(sb)->si_rwsem)
24317+
b752ccd1
AM
24318+static inline void si_noflush_read_lock(struct super_block *sb)
24319+{
24320+ __si_read_lock(sb);
24321+ si_pid_set(sb);
24322+}
24323+
24324+static inline int si_noflush_read_trylock(struct super_block *sb)
24325+{
24326+ int locked = __si_read_trylock(sb);
24327+ if (locked)
24328+ si_pid_set(sb);
24329+ return locked;
24330+}
24331+
24332+static inline void si_noflush_write_lock(struct super_block *sb)
24333+{
24334+ __si_write_lock(sb);
24335+ si_pid_set(sb);
24336+}
24337+
24338+static inline int si_noflush_write_trylock(struct super_block *sb)
24339+{
24340+ int locked = __si_write_trylock(sb);
24341+ if (locked)
24342+ si_pid_set(sb);
24343+ return locked;
24344+}
24345+
e49829fe 24346+#if 0 /* unused */
1facf9fc 24347+static inline int si_read_trylock(struct super_block *sb, int flags)
24348+{
24349+ if (au_ftest_lock(flags, FLUSH))
24350+ au_nwt_flush(&au_sbi(sb)->si_nowait);
24351+ return si_noflush_read_trylock(sb);
24352+}
e49829fe 24353+#endif
1facf9fc 24354+
b752ccd1
AM
24355+static inline void si_read_unlock(struct super_block *sb)
24356+{
24357+ si_pid_clr(sb);
24358+ __si_read_unlock(sb);
24359+}
24360+
b752ccd1 24361+#if 0 /* unused */
1facf9fc 24362+static inline int si_write_trylock(struct super_block *sb, int flags)
24363+{
24364+ if (au_ftest_lock(flags, FLUSH))
24365+ au_nwt_flush(&au_sbi(sb)->si_nowait);
24366+ return si_noflush_write_trylock(sb);
24367+}
b752ccd1
AM
24368+#endif
24369+
24370+static inline void si_write_unlock(struct super_block *sb)
24371+{
24372+ si_pid_clr(sb);
24373+ __si_write_unlock(sb);
24374+}
24375+
24376+#if 0 /* unused */
24377+static inline void si_downgrade_lock(struct super_block *sb)
24378+{
24379+ __si_downgrade_lock(sb);
24380+}
24381+#endif
1facf9fc 24382+
24383+/* ---------------------------------------------------------------------- */
24384+
24385+static inline aufs_bindex_t au_sbend(struct super_block *sb)
24386+{
dece6358 24387+ SiMustAnyLock(sb);
1facf9fc 24388+ return au_sbi(sb)->si_bend;
24389+}
24390+
24391+static inline unsigned int au_mntflags(struct super_block *sb)
24392+{
dece6358 24393+ SiMustAnyLock(sb);
1facf9fc 24394+ return au_sbi(sb)->si_mntflags;
24395+}
24396+
24397+static inline unsigned int au_sigen(struct super_block *sb)
24398+{
dece6358 24399+ SiMustAnyLock(sb);
1facf9fc 24400+ return au_sbi(sb)->si_generation;
24401+}
24402+
7f207e10
AM
24403+static inline void au_ninodes_inc(struct super_block *sb)
24404+{
24405+ atomic_long_inc(&au_sbi(sb)->si_ninodes);
24406+}
24407+
24408+static inline void au_ninodes_dec(struct super_block *sb)
24409+{
24410+ AuDebugOn(!atomic_long_read(&au_sbi(sb)->si_ninodes));
24411+ atomic_long_dec(&au_sbi(sb)->si_ninodes);
24412+}
24413+
24414+static inline void au_nfiles_inc(struct super_block *sb)
24415+{
24416+ atomic_long_inc(&au_sbi(sb)->si_nfiles);
24417+}
24418+
24419+static inline void au_nfiles_dec(struct super_block *sb)
24420+{
24421+ AuDebugOn(!atomic_long_read(&au_sbi(sb)->si_nfiles));
24422+ atomic_long_dec(&au_sbi(sb)->si_nfiles);
24423+}
24424+
1facf9fc 24425+static inline struct au_branch *au_sbr(struct super_block *sb,
24426+ aufs_bindex_t bindex)
24427+{
dece6358 24428+ SiMustAnyLock(sb);
1facf9fc 24429+ return au_sbi(sb)->si_branch[0 + bindex];
24430+}
24431+
24432+static inline void au_xino_brid_set(struct super_block *sb, aufs_bindex_t brid)
24433+{
dece6358 24434+ SiMustWriteLock(sb);
1facf9fc 24435+ au_sbi(sb)->si_xino_brid = brid;
24436+}
24437+
24438+static inline aufs_bindex_t au_xino_brid(struct super_block *sb)
24439+{
dece6358 24440+ SiMustAnyLock(sb);
1facf9fc 24441+ return au_sbi(sb)->si_xino_brid;
24442+}
24443+
24444+#endif /* __KERNEL__ */
24445+#endif /* __AUFS_SUPER_H__ */
7f207e10
AM
24446diff -urN /usr/share/empty/fs/aufs/sysaufs.c linux/fs/aufs/sysaufs.c
24447--- /usr/share/empty/fs/aufs/sysaufs.c 1970-01-01 01:00:00.000000000 +0100
0c3ec466 24448+++ linux/fs/aufs/sysaufs.c 2012-07-22 19:57:03.167671344 +0200
f6c5ef8b 24449@@ -0,0 +1,105 @@
1facf9fc 24450+/*
f6c5ef8b 24451+ * Copyright (C) 2005-2012 Junjiro R. Okajima
1facf9fc 24452+ *
24453+ * This program, aufs is free software; you can redistribute it and/or modify
24454+ * it under the terms of the GNU General Public License as published by
24455+ * the Free Software Foundation; either version 2 of the License, or
24456+ * (at your option) any later version.
dece6358
AM
24457+ *
24458+ * This program is distributed in the hope that it will be useful,
24459+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
24460+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24461+ * GNU General Public License for more details.
24462+ *
24463+ * You should have received a copy of the GNU General Public License
24464+ * along with this program; if not, write to the Free Software
24465+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 24466+ */
24467+
24468+/*
24469+ * sysfs interface and lifetime management
24470+ * they are necessary regardless sysfs is disabled.
24471+ */
24472+
1facf9fc 24473+#include <linux/random.h>
1facf9fc 24474+#include "aufs.h"
24475+
24476+unsigned long sysaufs_si_mask;
e49829fe 24477+struct kset *sysaufs_kset;
1facf9fc 24478+
24479+#define AuSiAttr(_name) { \
24480+ .attr = { .name = __stringify(_name), .mode = 0444 }, \
24481+ .show = sysaufs_si_##_name, \
24482+}
24483+
24484+static struct sysaufs_si_attr sysaufs_si_attr_xi_path = AuSiAttr(xi_path);
24485+struct attribute *sysaufs_si_attrs[] = {
24486+ &sysaufs_si_attr_xi_path.attr,
24487+ NULL,
24488+};
24489+
4a4d8108 24490+static const struct sysfs_ops au_sbi_ops = {
1facf9fc 24491+ .show = sysaufs_si_show
24492+};
24493+
24494+static struct kobj_type au_sbi_ktype = {
24495+ .release = au_si_free,
24496+ .sysfs_ops = &au_sbi_ops,
24497+ .default_attrs = sysaufs_si_attrs
24498+};
24499+
24500+/* ---------------------------------------------------------------------- */
24501+
24502+int sysaufs_si_init(struct au_sbinfo *sbinfo)
24503+{
24504+ int err;
24505+
e49829fe 24506+ sbinfo->si_kobj.kset = sysaufs_kset;
1facf9fc 24507+ /* cf. sysaufs_name() */
24508+ err = kobject_init_and_add
e49829fe 24509+ (&sbinfo->si_kobj, &au_sbi_ktype, /*&sysaufs_kset->kobj*/NULL,
1facf9fc 24510+ SysaufsSiNamePrefix "%lx", sysaufs_si_id(sbinfo));
24511+
24512+ dbgaufs_si_null(sbinfo);
24513+ if (!err) {
24514+ err = dbgaufs_si_init(sbinfo);
24515+ if (unlikely(err))
24516+ kobject_put(&sbinfo->si_kobj);
24517+ }
24518+ return err;
24519+}
24520+
24521+void sysaufs_fin(void)
24522+{
24523+ dbgaufs_fin();
e49829fe
JR
24524+ sysfs_remove_group(&sysaufs_kset->kobj, sysaufs_attr_group);
24525+ kset_unregister(sysaufs_kset);
1facf9fc 24526+}
24527+
24528+int __init sysaufs_init(void)
24529+{
24530+ int err;
24531+
24532+ do {
24533+ get_random_bytes(&sysaufs_si_mask, sizeof(sysaufs_si_mask));
24534+ } while (!sysaufs_si_mask);
24535+
4a4d8108 24536+ err = -EINVAL;
e49829fe
JR
24537+ sysaufs_kset = kset_create_and_add(AUFS_NAME, NULL, fs_kobj);
24538+ if (unlikely(!sysaufs_kset))
4a4d8108 24539+ goto out;
e49829fe
JR
24540+ err = PTR_ERR(sysaufs_kset);
24541+ if (IS_ERR(sysaufs_kset))
1facf9fc 24542+ goto out;
e49829fe 24543+ err = sysfs_create_group(&sysaufs_kset->kobj, sysaufs_attr_group);
1facf9fc 24544+ if (unlikely(err)) {
e49829fe 24545+ kset_unregister(sysaufs_kset);
1facf9fc 24546+ goto out;
24547+ }
24548+
24549+ err = dbgaufs_init();
24550+ if (unlikely(err))
24551+ sysaufs_fin();
4f0767ce 24552+out:
1facf9fc 24553+ return err;
24554+}
7f207e10
AM
24555diff -urN /usr/share/empty/fs/aufs/sysaufs.h linux/fs/aufs/sysaufs.h
24556--- /usr/share/empty/fs/aufs/sysaufs.h 1970-01-01 01:00:00.000000000 +0100
0c3ec466 24557+++ linux/fs/aufs/sysaufs.h 2012-07-22 19:57:03.167671344 +0200
f6c5ef8b 24558@@ -0,0 +1,104 @@
1facf9fc 24559+/*
f6c5ef8b 24560+ * Copyright (C) 2005-2012 Junjiro R. Okajima
1facf9fc 24561+ *
24562+ * This program, aufs is free software; you can redistribute it and/or modify
24563+ * it under the terms of the GNU General Public License as published by
24564+ * the Free Software Foundation; either version 2 of the License, or
24565+ * (at your option) any later version.
dece6358
AM
24566+ *
24567+ * This program is distributed in the hope that it will be useful,
24568+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
24569+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24570+ * GNU General Public License for more details.
24571+ *
24572+ * You should have received a copy of the GNU General Public License
24573+ * along with this program; if not, write to the Free Software
24574+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 24575+ */
24576+
24577+/*
24578+ * sysfs interface and mount lifetime management
24579+ */
24580+
24581+#ifndef __SYSAUFS_H__
24582+#define __SYSAUFS_H__
24583+
24584+#ifdef __KERNEL__
24585+
1facf9fc 24586+#include <linux/sysfs.h>
1facf9fc 24587+#include "module.h"
24588+
dece6358
AM
24589+struct super_block;
24590+struct au_sbinfo;
24591+
1facf9fc 24592+struct sysaufs_si_attr {
24593+ struct attribute attr;
24594+ int (*show)(struct seq_file *seq, struct super_block *sb);
24595+};
24596+
24597+/* ---------------------------------------------------------------------- */
24598+
24599+/* sysaufs.c */
24600+extern unsigned long sysaufs_si_mask;
e49829fe 24601+extern struct kset *sysaufs_kset;
1facf9fc 24602+extern struct attribute *sysaufs_si_attrs[];
24603+int sysaufs_si_init(struct au_sbinfo *sbinfo);
24604+int __init sysaufs_init(void);
24605+void sysaufs_fin(void);
24606+
24607+/* ---------------------------------------------------------------------- */
24608+
24609+/* some people doesn't like to show a pointer in kernel */
24610+static inline unsigned long sysaufs_si_id(struct au_sbinfo *sbinfo)
24611+{
24612+ return sysaufs_si_mask ^ (unsigned long)sbinfo;
24613+}
24614+
24615+#define SysaufsSiNamePrefix "si_"
24616+#define SysaufsSiNameLen (sizeof(SysaufsSiNamePrefix) + 16)
24617+static inline void sysaufs_name(struct au_sbinfo *sbinfo, char *name)
24618+{
24619+ snprintf(name, SysaufsSiNameLen, SysaufsSiNamePrefix "%lx",
24620+ sysaufs_si_id(sbinfo));
24621+}
24622+
24623+struct au_branch;
24624+#ifdef CONFIG_SYSFS
24625+/* sysfs.c */
24626+extern struct attribute_group *sysaufs_attr_group;
24627+
24628+int sysaufs_si_xi_path(struct seq_file *seq, struct super_block *sb);
24629+ssize_t sysaufs_si_show(struct kobject *kobj, struct attribute *attr,
24630+ char *buf);
24631+
24632+void sysaufs_br_init(struct au_branch *br);
24633+void sysaufs_brs_add(struct super_block *sb, aufs_bindex_t bindex);
24634+void sysaufs_brs_del(struct super_block *sb, aufs_bindex_t bindex);
24635+
24636+#define sysaufs_brs_init() do {} while (0)
24637+
24638+#else
24639+#define sysaufs_attr_group NULL
24640+
4a4d8108 24641+AuStubInt0(sysaufs_si_xi_path, struct seq_file *seq, struct super_block *sb)
1facf9fc 24642+
24643+static inline
24644+ssize_t sysaufs_si_show(struct kobject *kobj, struct attribute *attr,
24645+ char *buf)
24646+{
24647+ return 0;
24648+}
24649+
4a4d8108
AM
24650+AuStubVoid(sysaufs_br_init, struct au_branch *br)
24651+AuStubVoid(sysaufs_brs_add, struct super_block *sb, aufs_bindex_t bindex)
24652+AuStubVoid(sysaufs_brs_del, struct super_block *sb, aufs_bindex_t bindex)
1facf9fc 24653+
24654+static inline void sysaufs_brs_init(void)
24655+{
24656+ sysaufs_brs = 0;
24657+}
24658+
24659+#endif /* CONFIG_SYSFS */
24660+
24661+#endif /* __KERNEL__ */
24662+#endif /* __SYSAUFS_H__ */
7f207e10
AM
24663diff -urN /usr/share/empty/fs/aufs/sysfs.c linux/fs/aufs/sysfs.c
24664--- /usr/share/empty/fs/aufs/sysfs.c 1970-01-01 01:00:00.000000000 +0100
0c3ec466 24665+++ linux/fs/aufs/sysfs.c 2012-07-22 19:57:03.167671344 +0200
f6c5ef8b 24666@@ -0,0 +1,257 @@
1facf9fc 24667+/*
f6c5ef8b 24668+ * Copyright (C) 2005-2012 Junjiro R. Okajima
1facf9fc 24669+ *
24670+ * This program, aufs is free software; you can redistribute it and/or modify
24671+ * it under the terms of the GNU General Public License as published by
24672+ * the Free Software Foundation; either version 2 of the License, or
24673+ * (at your option) any later version.
dece6358
AM
24674+ *
24675+ * This program is distributed in the hope that it will be useful,
24676+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
24677+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24678+ * GNU General Public License for more details.
24679+ *
24680+ * You should have received a copy of the GNU General Public License
24681+ * along with this program; if not, write to the Free Software
24682+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 24683+ */
24684+
24685+/*
24686+ * sysfs interface
24687+ */
24688+
1facf9fc 24689+#include <linux/seq_file.h>
1facf9fc 24690+#include "aufs.h"
24691+
4a4d8108
AM
24692+#ifdef CONFIG_AUFS_FS_MODULE
24693+/* this entry violates the "one line per file" policy of sysfs */
24694+static ssize_t config_show(struct kobject *kobj, struct kobj_attribute *attr,
24695+ char *buf)
24696+{
24697+ ssize_t err;
24698+ static char *conf =
24699+/* this file is generated at compiling */
24700+#include "conf.str"
24701+ ;
24702+
24703+ err = snprintf(buf, PAGE_SIZE, conf);
24704+ if (unlikely(err >= PAGE_SIZE))
24705+ err = -EFBIG;
24706+ return err;
24707+}
24708+
24709+static struct kobj_attribute au_config_attr = __ATTR_RO(config);
24710+#endif
24711+
1facf9fc 24712+static struct attribute *au_attr[] = {
4a4d8108
AM
24713+#ifdef CONFIG_AUFS_FS_MODULE
24714+ &au_config_attr.attr,
24715+#endif
1facf9fc 24716+ NULL, /* need to NULL terminate the list of attributes */
24717+};
24718+
24719+static struct attribute_group sysaufs_attr_group_body = {
24720+ .attrs = au_attr
24721+};
24722+
24723+struct attribute_group *sysaufs_attr_group = &sysaufs_attr_group_body;
24724+
24725+/* ---------------------------------------------------------------------- */
24726+
24727+int sysaufs_si_xi_path(struct seq_file *seq, struct super_block *sb)
24728+{
24729+ int err;
24730+
dece6358
AM
24731+ SiMustAnyLock(sb);
24732+
1facf9fc 24733+ err = 0;
24734+ if (au_opt_test(au_mntflags(sb), XINO)) {
24735+ err = au_xino_path(seq, au_sbi(sb)->si_xib);
24736+ seq_putc(seq, '\n');
24737+ }
24738+ return err;
24739+}
24740+
24741+/*
24742+ * the lifetime of branch is independent from the entry under sysfs.
24743+ * sysfs handles the lifetime of the entry, and never call ->show() after it is
24744+ * unlinked.
24745+ */
24746+static int sysaufs_si_br(struct seq_file *seq, struct super_block *sb,
24747+ aufs_bindex_t bindex)
24748+{
1e00d052 24749+ int err;
1facf9fc 24750+ struct path path;
24751+ struct dentry *root;
24752+ struct au_branch *br;
1e00d052 24753+ char *perm;
1facf9fc 24754+
24755+ AuDbg("b%d\n", bindex);
24756+
1e00d052 24757+ err = 0;
1facf9fc 24758+ root = sb->s_root;
24759+ di_read_lock_parent(root, !AuLock_IR);
24760+ br = au_sbr(sb, bindex);
24761+ path.mnt = br->br_mnt;
24762+ path.dentry = au_h_dptr(root, bindex);
24763+ au_seq_path(seq, &path);
24764+ di_read_unlock(root, !AuLock_IR);
1e00d052
AM
24765+ perm = au_optstr_br_perm(br->br_perm);
24766+ if (perm) {
24767+ err = seq_printf(seq, "=%s\n", perm);
24768+ kfree(perm);
24769+ if (err == -1)
24770+ err = -E2BIG;
24771+ } else
24772+ err = -ENOMEM;
24773+ return err;
1facf9fc 24774+}
24775+
24776+/* ---------------------------------------------------------------------- */
24777+
24778+static struct seq_file *au_seq(char *p, ssize_t len)
24779+{
24780+ struct seq_file *seq;
24781+
24782+ seq = kzalloc(sizeof(*seq), GFP_NOFS);
24783+ if (seq) {
24784+ /* mutex_init(&seq.lock); */
24785+ seq->buf = p;
24786+ seq->size = len;
24787+ return seq; /* success */
24788+ }
24789+
24790+ seq = ERR_PTR(-ENOMEM);
24791+ return seq;
24792+}
24793+
24794+#define SysaufsBr_PREFIX "br"
24795+
24796+/* todo: file size may exceed PAGE_SIZE */
24797+ssize_t sysaufs_si_show(struct kobject *kobj, struct attribute *attr,
1308ab2a 24798+ char *buf)
1facf9fc 24799+{
24800+ ssize_t err;
24801+ long l;
24802+ aufs_bindex_t bend;
24803+ struct au_sbinfo *sbinfo;
24804+ struct super_block *sb;
24805+ struct seq_file *seq;
24806+ char *name;
24807+ struct attribute **cattr;
24808+
24809+ sbinfo = container_of(kobj, struct au_sbinfo, si_kobj);
24810+ sb = sbinfo->si_sb;
1308ab2a 24811+
24812+ /*
24813+ * prevent a race condition between sysfs and aufs.
24814+ * for instance, sysfs_file_read() calls sysfs_get_active_two() which
24815+ * prohibits maintaining the sysfs entries.
24816+ * hew we acquire read lock after sysfs_get_active_two().
24817+ * on the other hand, the remount process may maintain the sysfs/aufs
24818+ * entries after acquiring write lock.
24819+ * it can cause a deadlock.
24820+ * simply we gave up processing read here.
24821+ */
24822+ err = -EBUSY;
24823+ if (unlikely(!si_noflush_read_trylock(sb)))
24824+ goto out;
1facf9fc 24825+
24826+ seq = au_seq(buf, PAGE_SIZE);
24827+ err = PTR_ERR(seq);
24828+ if (IS_ERR(seq))
1308ab2a 24829+ goto out_unlock;
1facf9fc 24830+
24831+ name = (void *)attr->name;
24832+ cattr = sysaufs_si_attrs;
24833+ while (*cattr) {
24834+ if (!strcmp(name, (*cattr)->name)) {
24835+ err = container_of(*cattr, struct sysaufs_si_attr, attr)
24836+ ->show(seq, sb);
24837+ goto out_seq;
24838+ }
24839+ cattr++;
24840+ }
24841+
24842+ bend = au_sbend(sb);
24843+ if (!strncmp(name, SysaufsBr_PREFIX, sizeof(SysaufsBr_PREFIX) - 1)) {
24844+ name += sizeof(SysaufsBr_PREFIX) - 1;
9dbd164d 24845+ err = kstrtol(name, 10, &l);
1facf9fc 24846+ if (!err) {
24847+ if (l <= bend)
24848+ err = sysaufs_si_br(seq, sb, (aufs_bindex_t)l);
24849+ else
24850+ err = -ENOENT;
24851+ }
24852+ goto out_seq;
24853+ }
24854+ BUG();
24855+
4f0767ce 24856+out_seq:
1facf9fc 24857+ if (!err) {
24858+ err = seq->count;
24859+ /* sysfs limit */
24860+ if (unlikely(err == PAGE_SIZE))
24861+ err = -EFBIG;
24862+ }
24863+ kfree(seq);
4f0767ce 24864+out_unlock:
1facf9fc 24865+ si_read_unlock(sb);
4f0767ce 24866+out:
1facf9fc 24867+ return err;
24868+}
24869+
24870+/* ---------------------------------------------------------------------- */
24871+
24872+void sysaufs_br_init(struct au_branch *br)
24873+{
4a4d8108
AM
24874+ struct attribute *attr = &br->br_attr;
24875+
24876+ sysfs_attr_init(attr);
24877+ attr->name = br->br_name;
24878+ attr->mode = S_IRUGO;
1facf9fc 24879+}
24880+
24881+void sysaufs_brs_del(struct super_block *sb, aufs_bindex_t bindex)
24882+{
24883+ struct au_branch *br;
24884+ struct kobject *kobj;
24885+ aufs_bindex_t bend;
24886+
24887+ dbgaufs_brs_del(sb, bindex);
24888+
24889+ if (!sysaufs_brs)
24890+ return;
24891+
24892+ kobj = &au_sbi(sb)->si_kobj;
24893+ bend = au_sbend(sb);
24894+ for (; bindex <= bend; bindex++) {
24895+ br = au_sbr(sb, bindex);
24896+ sysfs_remove_file(kobj, &br->br_attr);
24897+ }
24898+}
24899+
24900+void sysaufs_brs_add(struct super_block *sb, aufs_bindex_t bindex)
24901+{
24902+ int err;
24903+ aufs_bindex_t bend;
24904+ struct kobject *kobj;
24905+ struct au_branch *br;
24906+
24907+ dbgaufs_brs_add(sb, bindex);
24908+
24909+ if (!sysaufs_brs)
24910+ return;
24911+
24912+ kobj = &au_sbi(sb)->si_kobj;
24913+ bend = au_sbend(sb);
24914+ for (; bindex <= bend; bindex++) {
24915+ br = au_sbr(sb, bindex);
24916+ snprintf(br->br_name, sizeof(br->br_name), SysaufsBr_PREFIX
24917+ "%d", bindex);
24918+ err = sysfs_create_file(kobj, &br->br_attr);
24919+ if (unlikely(err))
0c3ec466
AM
24920+ pr_warn("failed %s under sysfs(%d)\n",
24921+ br->br_name, err);
1facf9fc 24922+ }
24923+}
7f207e10
AM
24924diff -urN /usr/share/empty/fs/aufs/sysrq.c linux/fs/aufs/sysrq.c
24925--- /usr/share/empty/fs/aufs/sysrq.c 1970-01-01 01:00:00.000000000 +0100
0c3ec466 24926+++ linux/fs/aufs/sysrq.c 2012-07-22 19:57:03.167671344 +0200
f6c5ef8b 24927@@ -0,0 +1,148 @@
1facf9fc 24928+/*
f6c5ef8b 24929+ * Copyright (C) 2005-2012 Junjiro R. Okajima
1facf9fc 24930+ *
24931+ * This program, aufs is free software; you can redistribute it and/or modify
24932+ * it under the terms of the GNU General Public License as published by
24933+ * the Free Software Foundation; either version 2 of the License, or
24934+ * (at your option) any later version.
dece6358
AM
24935+ *
24936+ * This program is distributed in the hope that it will be useful,
24937+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
24938+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24939+ * GNU General Public License for more details.
24940+ *
24941+ * You should have received a copy of the GNU General Public License
24942+ * along with this program; if not, write to the Free Software
24943+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 24944+ */
24945+
24946+/*
24947+ * magic sysrq hanlder
24948+ */
24949+
1facf9fc 24950+/* #include <linux/sysrq.h> */
027c5e7a 24951+#include <linux/writeback.h>
1facf9fc 24952+#include "aufs.h"
24953+
24954+/* ---------------------------------------------------------------------- */
24955+
24956+static void sysrq_sb(struct super_block *sb)
24957+{
24958+ char *plevel;
24959+ struct au_sbinfo *sbinfo;
24960+ struct file *file;
24961+
24962+ plevel = au_plevel;
24963+ au_plevel = KERN_WARNING;
1facf9fc 24964+
24965+ sbinfo = au_sbi(sb);
4a4d8108
AM
24966+ /* since we define pr_fmt, call printk directly */
24967+ printk(KERN_WARNING "si=%lx\n", sysaufs_si_id(sbinfo));
24968+ printk(KERN_WARNING AUFS_NAME ": superblock\n");
1facf9fc 24969+ au_dpri_sb(sb);
027c5e7a
AM
24970+
24971+#if 0
4a4d8108 24972+ printk(KERN_WARNING AUFS_NAME ": root dentry\n");
1facf9fc 24973+ au_dpri_dentry(sb->s_root);
4a4d8108 24974+ printk(KERN_WARNING AUFS_NAME ": root inode\n");
1facf9fc 24975+ au_dpri_inode(sb->s_root->d_inode);
027c5e7a
AM
24976+#endif
24977+
1facf9fc 24978+#if 0
027c5e7a
AM
24979+ do {
24980+ int err, i, j, ndentry;
24981+ struct au_dcsub_pages dpages;
24982+ struct au_dpage *dpage;
24983+
24984+ err = au_dpages_init(&dpages, GFP_ATOMIC);
24985+ if (unlikely(err))
24986+ break;
24987+ err = au_dcsub_pages(&dpages, sb->s_root, NULL, NULL);
24988+ if (!err)
24989+ for (i = 0; i < dpages.ndpage; i++) {
24990+ dpage = dpages.dpages + i;
24991+ ndentry = dpage->ndentry;
24992+ for (j = 0; j < ndentry; j++)
24993+ au_dpri_dentry(dpage->dentries[j]);
24994+ }
24995+ au_dpages_free(&dpages);
24996+ } while (0);
24997+#endif
24998+
24999+#if 1
25000+ {
25001+ struct inode *i;
25002+ printk(KERN_WARNING AUFS_NAME ": isolated inode\n");
2cbb1c4b
JR
25003+ spin_lock(&inode_sb_list_lock);
25004+ list_for_each_entry(i, &sb->s_inodes, i_sb_list) {
25005+ spin_lock(&i->i_lock);
027c5e7a
AM
25006+ if (1 || list_empty(&i->i_dentry))
25007+ au_dpri_inode(i);
2cbb1c4b
JR
25008+ spin_unlock(&i->i_lock);
25009+ }
25010+ spin_unlock(&inode_sb_list_lock);
027c5e7a 25011+ }
1facf9fc 25012+#endif
4a4d8108 25013+ printk(KERN_WARNING AUFS_NAME ": files\n");
0c3ec466 25014+ lg_global_lock(&files_lglock);
0c5527e5 25015+ do_file_list_for_each_entry(sb, file) {
4a4d8108
AM
25016+ umode_t mode;
25017+ mode = file->f_dentry->d_inode->i_mode;
25018+ if (!special_file(mode) || au_special_file(mode))
1facf9fc 25019+ au_dpri_file(file);
0c5527e5 25020+ } while_file_list_for_each_entry;
0c3ec466 25021+ lg_global_unlock(&files_lglock);
e49829fe 25022+ printk(KERN_WARNING AUFS_NAME ": done\n");
1facf9fc 25023+
25024+ au_plevel = plevel;
1facf9fc 25025+}
25026+
25027+/* ---------------------------------------------------------------------- */
25028+
25029+/* module parameter */
25030+static char *aufs_sysrq_key = "a";
25031+module_param_named(sysrq, aufs_sysrq_key, charp, S_IRUGO);
25032+MODULE_PARM_DESC(sysrq, "MagicSysRq key for " AUFS_NAME);
25033+
0c5527e5 25034+static void au_sysrq(int key __maybe_unused)
1facf9fc 25035+{
1facf9fc 25036+ struct au_sbinfo *sbinfo;
25037+
027c5e7a 25038+ lockdep_off();
53392da6 25039+ au_sbilist_lock();
e49829fe 25040+ list_for_each_entry(sbinfo, &au_sbilist.head, si_list)
1facf9fc 25041+ sysrq_sb(sbinfo->si_sb);
53392da6 25042+ au_sbilist_unlock();
027c5e7a 25043+ lockdep_on();
1facf9fc 25044+}
25045+
25046+static struct sysrq_key_op au_sysrq_op = {
25047+ .handler = au_sysrq,
25048+ .help_msg = "Aufs",
25049+ .action_msg = "Aufs",
25050+ .enable_mask = SYSRQ_ENABLE_DUMP
25051+};
25052+
25053+/* ---------------------------------------------------------------------- */
25054+
25055+int __init au_sysrq_init(void)
25056+{
25057+ int err;
25058+ char key;
25059+
25060+ err = -1;
25061+ key = *aufs_sysrq_key;
25062+ if ('a' <= key && key <= 'z')
25063+ err = register_sysrq_key(key, &au_sysrq_op);
25064+ if (unlikely(err))
4a4d8108 25065+ pr_err("err %d, sysrq=%c\n", err, key);
1facf9fc 25066+ return err;
25067+}
25068+
25069+void au_sysrq_fin(void)
25070+{
25071+ int err;
25072+ err = unregister_sysrq_key(*aufs_sysrq_key, &au_sysrq_op);
25073+ if (unlikely(err))
4a4d8108 25074+ pr_err("err %d (ignored)\n", err);
1facf9fc 25075+}
7f207e10
AM
25076diff -urN /usr/share/empty/fs/aufs/vdir.c linux/fs/aufs/vdir.c
25077--- /usr/share/empty/fs/aufs/vdir.c 1970-01-01 01:00:00.000000000 +0100
0c3ec466 25078+++ linux/fs/aufs/vdir.c 2012-07-22 19:57:03.167671344 +0200
f6c5ef8b 25079@@ -0,0 +1,885 @@
1facf9fc 25080+/*
f6c5ef8b 25081+ * Copyright (C) 2005-2012 Junjiro R. Okajima
1facf9fc 25082+ *
25083+ * This program, aufs is free software; you can redistribute it and/or modify
25084+ * it under the terms of the GNU General Public License as published by
25085+ * the Free Software Foundation; either version 2 of the License, or
25086+ * (at your option) any later version.
dece6358
AM
25087+ *
25088+ * This program is distributed in the hope that it will be useful,
25089+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
25090+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
25091+ * GNU General Public License for more details.
25092+ *
25093+ * You should have received a copy of the GNU General Public License
25094+ * along with this program; if not, write to the Free Software
25095+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 25096+ */
25097+
25098+/*
25099+ * virtual or vertical directory
25100+ */
25101+
25102+#include "aufs.h"
25103+
dece6358 25104+static unsigned int calc_size(int nlen)
1facf9fc 25105+{
dece6358 25106+ return ALIGN(sizeof(struct au_vdir_de) + nlen, sizeof(ino_t));
1facf9fc 25107+}
25108+
25109+static int set_deblk_end(union au_vdir_deblk_p *p,
25110+ union au_vdir_deblk_p *deblk_end)
25111+{
25112+ if (calc_size(0) <= deblk_end->deblk - p->deblk) {
25113+ p->de->de_str.len = 0;
25114+ /* smp_mb(); */
25115+ return 0;
25116+ }
25117+ return -1; /* error */
25118+}
25119+
25120+/* returns true or false */
25121+static int is_deblk_end(union au_vdir_deblk_p *p,
25122+ union au_vdir_deblk_p *deblk_end)
25123+{
25124+ if (calc_size(0) <= deblk_end->deblk - p->deblk)
25125+ return !p->de->de_str.len;
25126+ return 1;
25127+}
25128+
25129+static unsigned char *last_deblk(struct au_vdir *vdir)
25130+{
25131+ return vdir->vd_deblk[vdir->vd_nblk - 1];
25132+}
25133+
25134+/* ---------------------------------------------------------------------- */
25135+
1308ab2a 25136+/* estimate the apropriate size for name hash table */
25137+unsigned int au_rdhash_est(loff_t sz)
25138+{
25139+ unsigned int n;
25140+
25141+ n = UINT_MAX;
25142+ sz >>= 10;
25143+ if (sz < n)
25144+ n = sz;
25145+ if (sz < AUFS_RDHASH_DEF)
25146+ n = AUFS_RDHASH_DEF;
4a4d8108 25147+ /* pr_info("n %u\n", n); */
1308ab2a 25148+ return n;
25149+}
25150+
1facf9fc 25151+/*
25152+ * the allocated memory has to be freed by
dece6358 25153+ * au_nhash_wh_free() or au_nhash_de_free().
1facf9fc 25154+ */
dece6358 25155+int au_nhash_alloc(struct au_nhash *nhash, unsigned int num_hash, gfp_t gfp)
1facf9fc 25156+{
1facf9fc 25157+ struct hlist_head *head;
dece6358 25158+ unsigned int u;
1facf9fc 25159+
dece6358
AM
25160+ head = kmalloc(sizeof(*nhash->nh_head) * num_hash, gfp);
25161+ if (head) {
25162+ nhash->nh_num = num_hash;
25163+ nhash->nh_head = head;
25164+ for (u = 0; u < num_hash; u++)
1facf9fc 25165+ INIT_HLIST_HEAD(head++);
dece6358 25166+ return 0; /* success */
1facf9fc 25167+ }
1facf9fc 25168+
dece6358 25169+ return -ENOMEM;
1facf9fc 25170+}
25171+
dece6358
AM
25172+static void nhash_count(struct hlist_head *head)
25173+{
25174+#if 0
25175+ unsigned long n;
25176+ struct hlist_node *pos;
25177+
25178+ n = 0;
25179+ hlist_for_each(pos, head)
25180+ n++;
4a4d8108 25181+ pr_info("%lu\n", n);
dece6358
AM
25182+#endif
25183+}
25184+
25185+static void au_nhash_wh_do_free(struct hlist_head *head)
1facf9fc 25186+{
1facf9fc 25187+ struct au_vdir_wh *tpos;
25188+ struct hlist_node *pos, *node;
25189+
dece6358
AM
25190+ hlist_for_each_entry_safe(tpos, pos, node, head, wh_hash) {
25191+ /* hlist_del(pos); */
25192+ kfree(tpos);
1facf9fc 25193+ }
25194+}
25195+
dece6358 25196+static void au_nhash_de_do_free(struct hlist_head *head)
1facf9fc 25197+{
dece6358
AM
25198+ struct au_vdir_dehstr *tpos;
25199+ struct hlist_node *pos, *node;
1facf9fc 25200+
dece6358
AM
25201+ hlist_for_each_entry_safe(tpos, pos, node, head, hash) {
25202+ /* hlist_del(pos); */
4a4d8108 25203+ au_cache_free_vdir_dehstr(tpos);
1facf9fc 25204+ }
1facf9fc 25205+}
25206+
dece6358
AM
25207+static void au_nhash_do_free(struct au_nhash *nhash,
25208+ void (*free)(struct hlist_head *head))
1facf9fc 25209+{
1308ab2a 25210+ unsigned int n;
1facf9fc 25211+ struct hlist_head *head;
1facf9fc 25212+
dece6358 25213+ n = nhash->nh_num;
1308ab2a 25214+ if (!n)
25215+ return;
25216+
dece6358 25217+ head = nhash->nh_head;
1308ab2a 25218+ while (n-- > 0) {
dece6358
AM
25219+ nhash_count(head);
25220+ free(head++);
1facf9fc 25221+ }
dece6358 25222+ kfree(nhash->nh_head);
1facf9fc 25223+}
25224+
dece6358 25225+void au_nhash_wh_free(struct au_nhash *whlist)
1facf9fc 25226+{
dece6358
AM
25227+ au_nhash_do_free(whlist, au_nhash_wh_do_free);
25228+}
1facf9fc 25229+
dece6358
AM
25230+static void au_nhash_de_free(struct au_nhash *delist)
25231+{
25232+ au_nhash_do_free(delist, au_nhash_de_do_free);
1facf9fc 25233+}
25234+
25235+/* ---------------------------------------------------------------------- */
25236+
25237+int au_nhash_test_longer_wh(struct au_nhash *whlist, aufs_bindex_t btgt,
25238+ int limit)
25239+{
25240+ int num;
25241+ unsigned int u, n;
25242+ struct hlist_head *head;
25243+ struct au_vdir_wh *tpos;
25244+ struct hlist_node *pos;
25245+
25246+ num = 0;
25247+ n = whlist->nh_num;
25248+ head = whlist->nh_head;
1308ab2a 25249+ for (u = 0; u < n; u++, head++)
1facf9fc 25250+ hlist_for_each_entry(tpos, pos, head, wh_hash)
25251+ if (tpos->wh_bindex == btgt && ++num > limit)
25252+ return 1;
1facf9fc 25253+ return 0;
25254+}
25255+
25256+static struct hlist_head *au_name_hash(struct au_nhash *nhash,
dece6358 25257+ unsigned char *name,
1facf9fc 25258+ unsigned int len)
25259+{
dece6358
AM
25260+ unsigned int v;
25261+ /* const unsigned int magic_bit = 12; */
25262+
1308ab2a 25263+ AuDebugOn(!nhash->nh_num || !nhash->nh_head);
25264+
dece6358
AM
25265+ v = 0;
25266+ while (len--)
25267+ v += *name++;
25268+ /* v = hash_long(v, magic_bit); */
25269+ v %= nhash->nh_num;
25270+ return nhash->nh_head + v;
25271+}
25272+
25273+static int au_nhash_test_name(struct au_vdir_destr *str, const char *name,
25274+ int nlen)
25275+{
25276+ return str->len == nlen && !memcmp(str->name, name, nlen);
1facf9fc 25277+}
25278+
25279+/* returns found or not */
dece6358 25280+int au_nhash_test_known_wh(struct au_nhash *whlist, char *name, int nlen)
1facf9fc 25281+{
25282+ struct hlist_head *head;
25283+ struct au_vdir_wh *tpos;
25284+ struct hlist_node *pos;
25285+ struct au_vdir_destr *str;
25286+
dece6358 25287+ head = au_name_hash(whlist, name, nlen);
1facf9fc 25288+ hlist_for_each_entry(tpos, pos, head, wh_hash) {
25289+ str = &tpos->wh_str;
25290+ AuDbg("%.*s\n", str->len, str->name);
dece6358
AM
25291+ if (au_nhash_test_name(str, name, nlen))
25292+ return 1;
25293+ }
25294+ return 0;
25295+}
25296+
25297+/* returns found(true) or not */
25298+static int test_known(struct au_nhash *delist, char *name, int nlen)
25299+{
25300+ struct hlist_head *head;
25301+ struct au_vdir_dehstr *tpos;
25302+ struct hlist_node *pos;
25303+ struct au_vdir_destr *str;
25304+
25305+ head = au_name_hash(delist, name, nlen);
25306+ hlist_for_each_entry(tpos, pos, head, hash) {
25307+ str = tpos->str;
25308+ AuDbg("%.*s\n", str->len, str->name);
25309+ if (au_nhash_test_name(str, name, nlen))
1facf9fc 25310+ return 1;
25311+ }
25312+ return 0;
25313+}
25314+
dece6358
AM
25315+static void au_shwh_init_wh(struct au_vdir_wh *wh, ino_t ino,
25316+ unsigned char d_type)
25317+{
25318+#ifdef CONFIG_AUFS_SHWH
25319+ wh->wh_ino = ino;
25320+ wh->wh_type = d_type;
25321+#endif
25322+}
25323+
25324+/* ---------------------------------------------------------------------- */
25325+
25326+int au_nhash_append_wh(struct au_nhash *whlist, char *name, int nlen, ino_t ino,
25327+ unsigned int d_type, aufs_bindex_t bindex,
25328+ unsigned char shwh)
1facf9fc 25329+{
25330+ int err;
25331+ struct au_vdir_destr *str;
25332+ struct au_vdir_wh *wh;
25333+
dece6358 25334+ AuDbg("%.*s\n", nlen, name);
1308ab2a 25335+ AuDebugOn(!whlist->nh_num || !whlist->nh_head);
25336+
1facf9fc 25337+ err = -ENOMEM;
dece6358 25338+ wh = kmalloc(sizeof(*wh) + nlen, GFP_NOFS);
1facf9fc 25339+ if (unlikely(!wh))
25340+ goto out;
25341+
25342+ err = 0;
25343+ wh->wh_bindex = bindex;
dece6358
AM
25344+ if (shwh)
25345+ au_shwh_init_wh(wh, ino, d_type);
1facf9fc 25346+ str = &wh->wh_str;
dece6358
AM
25347+ str->len = nlen;
25348+ memcpy(str->name, name, nlen);
25349+ hlist_add_head(&wh->wh_hash, au_name_hash(whlist, name, nlen));
1facf9fc 25350+ /* smp_mb(); */
25351+
4f0767ce 25352+out:
1facf9fc 25353+ return err;
25354+}
25355+
1facf9fc 25356+static int append_deblk(struct au_vdir *vdir)
25357+{
25358+ int err;
dece6358 25359+ unsigned long ul;
1facf9fc 25360+ const unsigned int deblk_sz = vdir->vd_deblk_sz;
25361+ union au_vdir_deblk_p p, deblk_end;
25362+ unsigned char **o;
25363+
25364+ err = -ENOMEM;
dece6358
AM
25365+ o = krealloc(vdir->vd_deblk, sizeof(*o) * (vdir->vd_nblk + 1),
25366+ GFP_NOFS);
1facf9fc 25367+ if (unlikely(!o))
25368+ goto out;
25369+
25370+ vdir->vd_deblk = o;
25371+ p.deblk = kmalloc(deblk_sz, GFP_NOFS);
25372+ if (p.deblk) {
25373+ ul = vdir->vd_nblk++;
25374+ vdir->vd_deblk[ul] = p.deblk;
25375+ vdir->vd_last.ul = ul;
25376+ vdir->vd_last.p.deblk = p.deblk;
25377+ deblk_end.deblk = p.deblk + deblk_sz;
25378+ err = set_deblk_end(&p, &deblk_end);
25379+ }
25380+
4f0767ce 25381+out:
1facf9fc 25382+ return err;
25383+}
25384+
dece6358
AM
25385+static int append_de(struct au_vdir *vdir, char *name, int nlen, ino_t ino,
25386+ unsigned int d_type, struct au_nhash *delist)
25387+{
25388+ int err;
25389+ unsigned int sz;
25390+ const unsigned int deblk_sz = vdir->vd_deblk_sz;
25391+ union au_vdir_deblk_p p, *room, deblk_end;
25392+ struct au_vdir_dehstr *dehstr;
25393+
25394+ p.deblk = last_deblk(vdir);
25395+ deblk_end.deblk = p.deblk + deblk_sz;
25396+ room = &vdir->vd_last.p;
25397+ AuDebugOn(room->deblk < p.deblk || deblk_end.deblk <= room->deblk
25398+ || !is_deblk_end(room, &deblk_end));
25399+
25400+ sz = calc_size(nlen);
25401+ if (unlikely(sz > deblk_end.deblk - room->deblk)) {
25402+ err = append_deblk(vdir);
25403+ if (unlikely(err))
25404+ goto out;
25405+
25406+ p.deblk = last_deblk(vdir);
25407+ deblk_end.deblk = p.deblk + deblk_sz;
25408+ /* smp_mb(); */
25409+ AuDebugOn(room->deblk != p.deblk);
25410+ }
25411+
25412+ err = -ENOMEM;
4a4d8108 25413+ dehstr = au_cache_alloc_vdir_dehstr();
dece6358
AM
25414+ if (unlikely(!dehstr))
25415+ goto out;
25416+
25417+ dehstr->str = &room->de->de_str;
25418+ hlist_add_head(&dehstr->hash, au_name_hash(delist, name, nlen));
25419+ room->de->de_ino = ino;
25420+ room->de->de_type = d_type;
25421+ room->de->de_str.len = nlen;
25422+ memcpy(room->de->de_str.name, name, nlen);
25423+
25424+ err = 0;
25425+ room->deblk += sz;
25426+ if (unlikely(set_deblk_end(room, &deblk_end)))
25427+ err = append_deblk(vdir);
25428+ /* smp_mb(); */
25429+
4f0767ce 25430+out:
dece6358
AM
25431+ return err;
25432+}
25433+
25434+/* ---------------------------------------------------------------------- */
25435+
25436+void au_vdir_free(struct au_vdir *vdir)
25437+{
25438+ unsigned char **deblk;
25439+
25440+ deblk = vdir->vd_deblk;
25441+ while (vdir->vd_nblk--)
25442+ kfree(*deblk++);
25443+ kfree(vdir->vd_deblk);
25444+ au_cache_free_vdir(vdir);
25445+}
25446+
1308ab2a 25447+static struct au_vdir *alloc_vdir(struct file *file)
1facf9fc 25448+{
25449+ struct au_vdir *vdir;
1308ab2a 25450+ struct super_block *sb;
1facf9fc 25451+ int err;
25452+
1308ab2a 25453+ sb = file->f_dentry->d_sb;
dece6358
AM
25454+ SiMustAnyLock(sb);
25455+
1facf9fc 25456+ err = -ENOMEM;
25457+ vdir = au_cache_alloc_vdir();
25458+ if (unlikely(!vdir))
25459+ goto out;
25460+
25461+ vdir->vd_deblk = kzalloc(sizeof(*vdir->vd_deblk), GFP_NOFS);
25462+ if (unlikely(!vdir->vd_deblk))
25463+ goto out_free;
25464+
25465+ vdir->vd_deblk_sz = au_sbi(sb)->si_rdblk;
1308ab2a 25466+ if (!vdir->vd_deblk_sz) {
25467+ /* estimate the apropriate size for deblk */
25468+ vdir->vd_deblk_sz = au_dir_size(file, /*dentry*/NULL);
4a4d8108 25469+ /* pr_info("vd_deblk_sz %u\n", vdir->vd_deblk_sz); */
1308ab2a 25470+ }
1facf9fc 25471+ vdir->vd_nblk = 0;
25472+ vdir->vd_version = 0;
25473+ vdir->vd_jiffy = 0;
25474+ err = append_deblk(vdir);
25475+ if (!err)
25476+ return vdir; /* success */
25477+
25478+ kfree(vdir->vd_deblk);
25479+
4f0767ce 25480+out_free:
1facf9fc 25481+ au_cache_free_vdir(vdir);
4f0767ce 25482+out:
1facf9fc 25483+ vdir = ERR_PTR(err);
25484+ return vdir;
25485+}
25486+
25487+static int reinit_vdir(struct au_vdir *vdir)
25488+{
25489+ int err;
25490+ union au_vdir_deblk_p p, deblk_end;
25491+
25492+ while (vdir->vd_nblk > 1) {
25493+ kfree(vdir->vd_deblk[vdir->vd_nblk - 1]);
25494+ /* vdir->vd_deblk[vdir->vd_nblk - 1] = NULL; */
25495+ vdir->vd_nblk--;
25496+ }
25497+ p.deblk = vdir->vd_deblk[0];
25498+ deblk_end.deblk = p.deblk + vdir->vd_deblk_sz;
25499+ err = set_deblk_end(&p, &deblk_end);
25500+ /* keep vd_dblk_sz */
25501+ vdir->vd_last.ul = 0;
25502+ vdir->vd_last.p.deblk = vdir->vd_deblk[0];
25503+ vdir->vd_version = 0;
25504+ vdir->vd_jiffy = 0;
25505+ /* smp_mb(); */
25506+ return err;
25507+}
25508+
25509+/* ---------------------------------------------------------------------- */
25510+
1facf9fc 25511+#define AuFillVdir_CALLED 1
25512+#define AuFillVdir_WHABLE (1 << 1)
dece6358 25513+#define AuFillVdir_SHWH (1 << 2)
1facf9fc 25514+#define au_ftest_fillvdir(flags, name) ((flags) & AuFillVdir_##name)
7f207e10
AM
25515+#define au_fset_fillvdir(flags, name) \
25516+ do { (flags) |= AuFillVdir_##name; } while (0)
25517+#define au_fclr_fillvdir(flags, name) \
25518+ do { (flags) &= ~AuFillVdir_##name; } while (0)
1facf9fc 25519+
dece6358
AM
25520+#ifndef CONFIG_AUFS_SHWH
25521+#undef AuFillVdir_SHWH
25522+#define AuFillVdir_SHWH 0
25523+#endif
25524+
1facf9fc 25525+struct fillvdir_arg {
25526+ struct file *file;
25527+ struct au_vdir *vdir;
dece6358
AM
25528+ struct au_nhash delist;
25529+ struct au_nhash whlist;
1facf9fc 25530+ aufs_bindex_t bindex;
25531+ unsigned int flags;
25532+ int err;
25533+};
25534+
dece6358 25535+static int fillvdir(void *__arg, const char *__name, int nlen,
1facf9fc 25536+ loff_t offset __maybe_unused, u64 h_ino,
25537+ unsigned int d_type)
25538+{
25539+ struct fillvdir_arg *arg = __arg;
25540+ char *name = (void *)__name;
25541+ struct super_block *sb;
1facf9fc 25542+ ino_t ino;
dece6358 25543+ const unsigned char shwh = !!au_ftest_fillvdir(arg->flags, SHWH);
1facf9fc 25544+
1facf9fc 25545+ arg->err = 0;
dece6358 25546+ sb = arg->file->f_dentry->d_sb;
1facf9fc 25547+ au_fset_fillvdir(arg->flags, CALLED);
25548+ /* smp_mb(); */
dece6358 25549+ if (nlen <= AUFS_WH_PFX_LEN
1facf9fc 25550+ || memcmp(name, AUFS_WH_PFX, AUFS_WH_PFX_LEN)) {
dece6358
AM
25551+ if (test_known(&arg->delist, name, nlen)
25552+ || au_nhash_test_known_wh(&arg->whlist, name, nlen))
25553+ goto out; /* already exists or whiteouted */
1facf9fc 25554+
25555+ sb = arg->file->f_dentry->d_sb;
dece6358 25556+ arg->err = au_ino(sb, arg->bindex, h_ino, d_type, &ino);
4a4d8108
AM
25557+ if (!arg->err) {
25558+ if (unlikely(nlen > AUFS_MAX_NAMELEN))
25559+ d_type = DT_UNKNOWN;
dece6358
AM
25560+ arg->err = append_de(arg->vdir, name, nlen, ino,
25561+ d_type, &arg->delist);
4a4d8108 25562+ }
1facf9fc 25563+ } else if (au_ftest_fillvdir(arg->flags, WHABLE)) {
25564+ name += AUFS_WH_PFX_LEN;
dece6358
AM
25565+ nlen -= AUFS_WH_PFX_LEN;
25566+ if (au_nhash_test_known_wh(&arg->whlist, name, nlen))
25567+ goto out; /* already whiteouted */
1facf9fc 25568+
dece6358
AM
25569+ if (shwh)
25570+ arg->err = au_wh_ino(sb, arg->bindex, h_ino, d_type,
25571+ &ino);
4a4d8108
AM
25572+ if (!arg->err) {
25573+ if (nlen <= AUFS_MAX_NAMELEN + AUFS_WH_PFX_LEN)
25574+ d_type = DT_UNKNOWN;
1facf9fc 25575+ arg->err = au_nhash_append_wh
dece6358
AM
25576+ (&arg->whlist, name, nlen, ino, d_type,
25577+ arg->bindex, shwh);
4a4d8108 25578+ }
1facf9fc 25579+ }
25580+
4f0767ce 25581+out:
1facf9fc 25582+ if (!arg->err)
25583+ arg->vdir->vd_jiffy = jiffies;
25584+ /* smp_mb(); */
25585+ AuTraceErr(arg->err);
25586+ return arg->err;
25587+}
25588+
dece6358
AM
25589+static int au_handle_shwh(struct super_block *sb, struct au_vdir *vdir,
25590+ struct au_nhash *whlist, struct au_nhash *delist)
25591+{
25592+#ifdef CONFIG_AUFS_SHWH
25593+ int err;
25594+ unsigned int nh, u;
25595+ struct hlist_head *head;
25596+ struct au_vdir_wh *tpos;
25597+ struct hlist_node *pos, *n;
25598+ char *p, *o;
25599+ struct au_vdir_destr *destr;
25600+
25601+ AuDebugOn(!au_opt_test(au_mntflags(sb), SHWH));
25602+
25603+ err = -ENOMEM;
4a4d8108 25604+ o = p = __getname_gfp(GFP_NOFS);
dece6358
AM
25605+ if (unlikely(!p))
25606+ goto out;
25607+
25608+ err = 0;
25609+ nh = whlist->nh_num;
25610+ memcpy(p, AUFS_WH_PFX, AUFS_WH_PFX_LEN);
25611+ p += AUFS_WH_PFX_LEN;
25612+ for (u = 0; u < nh; u++) {
25613+ head = whlist->nh_head + u;
25614+ hlist_for_each_entry_safe(tpos, pos, n, head, wh_hash) {
25615+ destr = &tpos->wh_str;
25616+ memcpy(p, destr->name, destr->len);
25617+ err = append_de(vdir, o, destr->len + AUFS_WH_PFX_LEN,
25618+ tpos->wh_ino, tpos->wh_type, delist);
25619+ if (unlikely(err))
25620+ break;
25621+ }
25622+ }
25623+
25624+ __putname(o);
25625+
4f0767ce 25626+out:
dece6358
AM
25627+ AuTraceErr(err);
25628+ return err;
25629+#else
25630+ return 0;
25631+#endif
25632+}
25633+
1facf9fc 25634+static int au_do_read_vdir(struct fillvdir_arg *arg)
25635+{
25636+ int err;
dece6358 25637+ unsigned int rdhash;
1facf9fc 25638+ loff_t offset;
dece6358
AM
25639+ aufs_bindex_t bend, bindex, bstart;
25640+ unsigned char shwh;
1facf9fc 25641+ struct file *hf, *file;
25642+ struct super_block *sb;
25643+
1facf9fc 25644+ file = arg->file;
25645+ sb = file->f_dentry->d_sb;
dece6358
AM
25646+ SiMustAnyLock(sb);
25647+
25648+ rdhash = au_sbi(sb)->si_rdhash;
1308ab2a 25649+ if (!rdhash)
25650+ rdhash = au_rdhash_est(au_dir_size(file, /*dentry*/NULL));
dece6358
AM
25651+ err = au_nhash_alloc(&arg->delist, rdhash, GFP_NOFS);
25652+ if (unlikely(err))
1facf9fc 25653+ goto out;
dece6358
AM
25654+ err = au_nhash_alloc(&arg->whlist, rdhash, GFP_NOFS);
25655+ if (unlikely(err))
1facf9fc 25656+ goto out_delist;
25657+
25658+ err = 0;
25659+ arg->flags = 0;
dece6358
AM
25660+ shwh = 0;
25661+ if (au_opt_test(au_mntflags(sb), SHWH)) {
25662+ shwh = 1;
25663+ au_fset_fillvdir(arg->flags, SHWH);
25664+ }
25665+ bstart = au_fbstart(file);
4a4d8108 25666+ bend = au_fbend_dir(file);
dece6358 25667+ for (bindex = bstart; !err && bindex <= bend; bindex++) {
4a4d8108 25668+ hf = au_hf_dir(file, bindex);
1facf9fc 25669+ if (!hf)
25670+ continue;
25671+
25672+ offset = vfsub_llseek(hf, 0, SEEK_SET);
25673+ err = offset;
25674+ if (unlikely(offset))
25675+ break;
25676+
25677+ arg->bindex = bindex;
25678+ au_fclr_fillvdir(arg->flags, WHABLE);
dece6358
AM
25679+ if (shwh
25680+ || (bindex != bend
25681+ && au_br_whable(au_sbr_perm(sb, bindex))))
1facf9fc 25682+ au_fset_fillvdir(arg->flags, WHABLE);
25683+ do {
25684+ arg->err = 0;
25685+ au_fclr_fillvdir(arg->flags, CALLED);
25686+ /* smp_mb(); */
25687+ err = vfsub_readdir(hf, fillvdir, arg);
25688+ if (err >= 0)
25689+ err = arg->err;
25690+ } while (!err && au_ftest_fillvdir(arg->flags, CALLED));
25691+ }
dece6358
AM
25692+
25693+ if (!err && shwh)
25694+ err = au_handle_shwh(sb, arg->vdir, &arg->whlist, &arg->delist);
25695+
25696+ au_nhash_wh_free(&arg->whlist);
1facf9fc 25697+
4f0767ce 25698+out_delist:
dece6358 25699+ au_nhash_de_free(&arg->delist);
4f0767ce 25700+out:
1facf9fc 25701+ return err;
25702+}
25703+
25704+static int read_vdir(struct file *file, int may_read)
25705+{
25706+ int err;
25707+ unsigned long expire;
25708+ unsigned char do_read;
25709+ struct fillvdir_arg arg;
25710+ struct inode *inode;
25711+ struct au_vdir *vdir, *allocated;
25712+
25713+ err = 0;
25714+ inode = file->f_dentry->d_inode;
25715+ IMustLock(inode);
dece6358
AM
25716+ SiMustAnyLock(inode->i_sb);
25717+
1facf9fc 25718+ allocated = NULL;
25719+ do_read = 0;
25720+ expire = au_sbi(inode->i_sb)->si_rdcache;
25721+ vdir = au_ivdir(inode);
25722+ if (!vdir) {
25723+ do_read = 1;
1308ab2a 25724+ vdir = alloc_vdir(file);
1facf9fc 25725+ err = PTR_ERR(vdir);
25726+ if (IS_ERR(vdir))
25727+ goto out;
25728+ err = 0;
25729+ allocated = vdir;
25730+ } else if (may_read
25731+ && (inode->i_version != vdir->vd_version
25732+ || time_after(jiffies, vdir->vd_jiffy + expire))) {
25733+ do_read = 1;
25734+ err = reinit_vdir(vdir);
25735+ if (unlikely(err))
25736+ goto out;
25737+ }
25738+
25739+ if (!do_read)
25740+ return 0; /* success */
25741+
25742+ arg.file = file;
25743+ arg.vdir = vdir;
25744+ err = au_do_read_vdir(&arg);
25745+ if (!err) {
25746+ /* file->f_pos = 0; */
25747+ vdir->vd_version = inode->i_version;
25748+ vdir->vd_last.ul = 0;
25749+ vdir->vd_last.p.deblk = vdir->vd_deblk[0];
25750+ if (allocated)
25751+ au_set_ivdir(inode, allocated);
25752+ } else if (allocated)
25753+ au_vdir_free(allocated);
25754+
4f0767ce 25755+out:
1facf9fc 25756+ return err;
25757+}
25758+
25759+static int copy_vdir(struct au_vdir *tgt, struct au_vdir *src)
25760+{
25761+ int err, rerr;
25762+ unsigned long ul, n;
25763+ const unsigned int deblk_sz = src->vd_deblk_sz;
25764+
25765+ AuDebugOn(tgt->vd_nblk != 1);
25766+
25767+ err = -ENOMEM;
25768+ if (tgt->vd_nblk < src->vd_nblk) {
25769+ unsigned char **p;
25770+
dece6358
AM
25771+ p = krealloc(tgt->vd_deblk, sizeof(*p) * src->vd_nblk,
25772+ GFP_NOFS);
1facf9fc 25773+ if (unlikely(!p))
25774+ goto out;
25775+ tgt->vd_deblk = p;
25776+ }
25777+
1308ab2a 25778+ if (tgt->vd_deblk_sz != deblk_sz) {
25779+ unsigned char *p;
25780+
25781+ tgt->vd_deblk_sz = deblk_sz;
25782+ p = krealloc(tgt->vd_deblk[0], deblk_sz, GFP_NOFS);
25783+ if (unlikely(!p))
25784+ goto out;
25785+ tgt->vd_deblk[0] = p;
25786+ }
1facf9fc 25787+ memcpy(tgt->vd_deblk[0], src->vd_deblk[0], deblk_sz);
1facf9fc 25788+ tgt->vd_version = src->vd_version;
25789+ tgt->vd_jiffy = src->vd_jiffy;
25790+
25791+ n = src->vd_nblk;
25792+ for (ul = 1; ul < n; ul++) {
dece6358
AM
25793+ tgt->vd_deblk[ul] = kmemdup(src->vd_deblk[ul], deblk_sz,
25794+ GFP_NOFS);
25795+ if (unlikely(!tgt->vd_deblk[ul]))
1facf9fc 25796+ goto out;
1308ab2a 25797+ tgt->vd_nblk++;
1facf9fc 25798+ }
1308ab2a 25799+ tgt->vd_nblk = n;
25800+ tgt->vd_last.ul = tgt->vd_last.ul;
25801+ tgt->vd_last.p.deblk = tgt->vd_deblk[tgt->vd_last.ul];
25802+ tgt->vd_last.p.deblk += src->vd_last.p.deblk
25803+ - src->vd_deblk[src->vd_last.ul];
1facf9fc 25804+ /* smp_mb(); */
25805+ return 0; /* success */
25806+
4f0767ce 25807+out:
1facf9fc 25808+ rerr = reinit_vdir(tgt);
25809+ BUG_ON(rerr);
25810+ return err;
25811+}
25812+
25813+int au_vdir_init(struct file *file)
25814+{
25815+ int err;
25816+ struct inode *inode;
25817+ struct au_vdir *vdir_cache, *allocated;
25818+
25819+ err = read_vdir(file, !file->f_pos);
25820+ if (unlikely(err))
25821+ goto out;
25822+
25823+ allocated = NULL;
25824+ vdir_cache = au_fvdir_cache(file);
25825+ if (!vdir_cache) {
1308ab2a 25826+ vdir_cache = alloc_vdir(file);
1facf9fc 25827+ err = PTR_ERR(vdir_cache);
25828+ if (IS_ERR(vdir_cache))
25829+ goto out;
25830+ allocated = vdir_cache;
25831+ } else if (!file->f_pos && vdir_cache->vd_version != file->f_version) {
25832+ err = reinit_vdir(vdir_cache);
25833+ if (unlikely(err))
25834+ goto out;
25835+ } else
25836+ return 0; /* success */
25837+
25838+ inode = file->f_dentry->d_inode;
25839+ err = copy_vdir(vdir_cache, au_ivdir(inode));
25840+ if (!err) {
25841+ file->f_version = inode->i_version;
25842+ if (allocated)
25843+ au_set_fvdir_cache(file, allocated);
25844+ } else if (allocated)
25845+ au_vdir_free(allocated);
25846+
4f0767ce 25847+out:
1facf9fc 25848+ return err;
25849+}
25850+
25851+static loff_t calc_offset(struct au_vdir *vdir)
25852+{
25853+ loff_t offset;
25854+ union au_vdir_deblk_p p;
25855+
25856+ p.deblk = vdir->vd_deblk[vdir->vd_last.ul];
25857+ offset = vdir->vd_last.p.deblk - p.deblk;
25858+ offset += vdir->vd_deblk_sz * vdir->vd_last.ul;
25859+ return offset;
25860+}
25861+
25862+/* returns true or false */
25863+static int seek_vdir(struct file *file)
25864+{
25865+ int valid;
25866+ unsigned int deblk_sz;
25867+ unsigned long ul, n;
25868+ loff_t offset;
25869+ union au_vdir_deblk_p p, deblk_end;
25870+ struct au_vdir *vdir_cache;
25871+
25872+ valid = 1;
25873+ vdir_cache = au_fvdir_cache(file);
25874+ offset = calc_offset(vdir_cache);
25875+ AuDbg("offset %lld\n", offset);
25876+ if (file->f_pos == offset)
25877+ goto out;
25878+
25879+ vdir_cache->vd_last.ul = 0;
25880+ vdir_cache->vd_last.p.deblk = vdir_cache->vd_deblk[0];
25881+ if (!file->f_pos)
25882+ goto out;
25883+
25884+ valid = 0;
25885+ deblk_sz = vdir_cache->vd_deblk_sz;
25886+ ul = div64_u64(file->f_pos, deblk_sz);
25887+ AuDbg("ul %lu\n", ul);
25888+ if (ul >= vdir_cache->vd_nblk)
25889+ goto out;
25890+
25891+ n = vdir_cache->vd_nblk;
25892+ for (; ul < n; ul++) {
25893+ p.deblk = vdir_cache->vd_deblk[ul];
25894+ deblk_end.deblk = p.deblk + deblk_sz;
25895+ offset = ul;
25896+ offset *= deblk_sz;
25897+ while (!is_deblk_end(&p, &deblk_end) && offset < file->f_pos) {
25898+ unsigned int l;
25899+
25900+ l = calc_size(p.de->de_str.len);
25901+ offset += l;
25902+ p.deblk += l;
25903+ }
25904+ if (!is_deblk_end(&p, &deblk_end)) {
25905+ valid = 1;
25906+ vdir_cache->vd_last.ul = ul;
25907+ vdir_cache->vd_last.p = p;
25908+ break;
25909+ }
25910+ }
25911+
4f0767ce 25912+out:
1facf9fc 25913+ /* smp_mb(); */
25914+ AuTraceErr(!valid);
25915+ return valid;
25916+}
25917+
25918+int au_vdir_fill_de(struct file *file, void *dirent, filldir_t filldir)
25919+{
25920+ int err;
25921+ unsigned int l, deblk_sz;
25922+ union au_vdir_deblk_p deblk_end;
25923+ struct au_vdir *vdir_cache;
25924+ struct au_vdir_de *de;
25925+
25926+ vdir_cache = au_fvdir_cache(file);
25927+ if (!seek_vdir(file))
25928+ return 0;
25929+
25930+ deblk_sz = vdir_cache->vd_deblk_sz;
25931+ while (1) {
25932+ deblk_end.deblk = vdir_cache->vd_deblk[vdir_cache->vd_last.ul];
25933+ deblk_end.deblk += deblk_sz;
25934+ while (!is_deblk_end(&vdir_cache->vd_last.p, &deblk_end)) {
25935+ de = vdir_cache->vd_last.p.de;
25936+ AuDbg("%.*s, off%lld, i%lu, dt%d\n",
25937+ de->de_str.len, de->de_str.name, file->f_pos,
25938+ (unsigned long)de->de_ino, de->de_type);
25939+ err = filldir(dirent, de->de_str.name, de->de_str.len,
25940+ file->f_pos, de->de_ino, de->de_type);
25941+ if (unlikely(err)) {
25942+ AuTraceErr(err);
25943+ /* todo: ignore the error caused by udba? */
25944+ /* return err; */
25945+ return 0;
25946+ }
25947+
25948+ l = calc_size(de->de_str.len);
25949+ vdir_cache->vd_last.p.deblk += l;
25950+ file->f_pos += l;
25951+ }
25952+ if (vdir_cache->vd_last.ul < vdir_cache->vd_nblk - 1) {
25953+ vdir_cache->vd_last.ul++;
25954+ vdir_cache->vd_last.p.deblk
25955+ = vdir_cache->vd_deblk[vdir_cache->vd_last.ul];
25956+ file->f_pos = deblk_sz * vdir_cache->vd_last.ul;
25957+ continue;
25958+ }
25959+ break;
25960+ }
25961+
25962+ /* smp_mb(); */
25963+ return 0;
25964+}
7f207e10
AM
25965diff -urN /usr/share/empty/fs/aufs/vfsub.c linux/fs/aufs/vfsub.c
25966--- /usr/share/empty/fs/aufs/vfsub.c 1970-01-01 01:00:00.000000000 +0100
0c3ec466 25967+++ linux/fs/aufs/vfsub.c 2012-07-22 19:57:03.167671344 +0200
7eafdf33 25968@@ -0,0 +1,832 @@
1facf9fc 25969+/*
f6c5ef8b 25970+ * Copyright (C) 2005-2012 Junjiro R. Okajima
1facf9fc 25971+ *
25972+ * This program, aufs is free software; you can redistribute it and/or modify
25973+ * it under the terms of the GNU General Public License as published by
25974+ * the Free Software Foundation; either version 2 of the License, or
25975+ * (at your option) any later version.
dece6358
AM
25976+ *
25977+ * This program is distributed in the hope that it will be useful,
25978+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
25979+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
25980+ * GNU General Public License for more details.
25981+ *
25982+ * You should have received a copy of the GNU General Public License
25983+ * along with this program; if not, write to the Free Software
25984+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 25985+ */
25986+
25987+/*
25988+ * sub-routines for VFS
25989+ */
25990+
1308ab2a 25991+#include <linux/ima.h>
dece6358
AM
25992+#include <linux/namei.h>
25993+#include <linux/security.h>
25994+#include <linux/splice.h>
1facf9fc 25995+#include "aufs.h"
25996+
25997+int vfsub_update_h_iattr(struct path *h_path, int *did)
25998+{
25999+ int err;
26000+ struct kstat st;
26001+ struct super_block *h_sb;
26002+
26003+ /* for remote fs, leave work for its getattr or d_revalidate */
26004+ /* for bad i_attr fs, handle them in aufs_getattr() */
26005+ /* still some fs may acquire i_mutex. we need to skip them */
26006+ err = 0;
26007+ if (!did)
26008+ did = &err;
26009+ h_sb = h_path->dentry->d_sb;
26010+ *did = (!au_test_fs_remote(h_sb) && au_test_fs_refresh_iattr(h_sb));
26011+ if (*did)
26012+ err = vfs_getattr(h_path->mnt, h_path->dentry, &st);
26013+
26014+ return err;
26015+}
26016+
26017+/* ---------------------------------------------------------------------- */
26018+
4a4d8108 26019+struct file *vfsub_dentry_open(struct path *path, int flags)
1308ab2a 26020+{
26021+ struct file *file;
26022+
4a4d8108 26023+ path_get(path);
0c5527e5 26024+ file = dentry_open(path->dentry, path->mnt,
2cbb1c4b 26025+ flags /* | __FMODE_NONOTIFY */,
7f207e10 26026+ current_cred());
2cbb1c4b
JR
26027+ if (!IS_ERR_OR_NULL(file)
26028+ && (file->f_mode & (FMODE_READ | FMODE_WRITE)) == FMODE_READ)
26029+ i_readcount_inc(path->dentry->d_inode);
4a4d8108 26030+
1308ab2a 26031+ return file;
26032+}
26033+
1facf9fc 26034+struct file *vfsub_filp_open(const char *path, int oflags, int mode)
26035+{
26036+ struct file *file;
26037+
2cbb1c4b 26038+ lockdep_off();
7f207e10 26039+ file = filp_open(path,
2cbb1c4b 26040+ oflags /* | __FMODE_NONOTIFY */,
7f207e10 26041+ mode);
2cbb1c4b 26042+ lockdep_on();
1facf9fc 26043+ if (IS_ERR(file))
26044+ goto out;
26045+ vfsub_update_h_iattr(&file->f_path, /*did*/NULL); /*ignore*/
26046+
4f0767ce 26047+out:
1facf9fc 26048+ return file;
26049+}
26050+
26051+int vfsub_kern_path(const char *name, unsigned int flags, struct path *path)
26052+{
26053+ int err;
26054+
1facf9fc 26055+ err = kern_path(name, flags, path);
1facf9fc 26056+ if (!err && path->dentry->d_inode)
26057+ vfsub_update_h_iattr(path, /*did*/NULL); /*ignore*/
26058+ return err;
26059+}
26060+
26061+struct dentry *vfsub_lookup_one_len(const char *name, struct dentry *parent,
26062+ int len)
26063+{
26064+ struct path path = {
26065+ .mnt = NULL
26066+ };
26067+
1308ab2a 26068+ /* VFS checks it too, but by WARN_ON_ONCE() */
1facf9fc 26069+ IMustLock(parent->d_inode);
26070+
26071+ path.dentry = lookup_one_len(name, parent, len);
26072+ if (IS_ERR(path.dentry))
26073+ goto out;
26074+ if (path.dentry->d_inode)
26075+ vfsub_update_h_iattr(&path, /*did*/NULL); /*ignore*/
26076+
4f0767ce 26077+out:
4a4d8108 26078+ AuTraceErrPtr(path.dentry);
1facf9fc 26079+ return path.dentry;
26080+}
26081+
26082+struct dentry *vfsub_lookup_hash(struct nameidata *nd)
26083+{
26084+ struct path path = {
26085+ .mnt = nd->path.mnt
26086+ };
26087+
26088+ IMustLock(nd->path.dentry->d_inode);
26089+
26090+ path.dentry = lookup_hash(nd);
4a4d8108
AM
26091+ if (IS_ERR(path.dentry))
26092+ goto out;
26093+ if (path.dentry->d_inode)
1facf9fc 26094+ vfsub_update_h_iattr(&path, /*did*/NULL); /*ignore*/
26095+
4f0767ce 26096+out:
4a4d8108 26097+ AuTraceErrPtr(path.dentry);
1facf9fc 26098+ return path.dentry;
26099+}
26100+
2cbb1c4b
JR
26101+/*
26102+ * this is "VFS:__lookup_one_len()" which was removed and merged into
26103+ * VFS:lookup_one_len() by the commit.
26104+ * 6a96ba5 2011-03-14 kill __lookup_one_len()
26105+ * this function should always be equivalent to the corresponding part in
26106+ * VFS:lookup_one_len().
26107+ */
26108+int vfsub_name_hash(const char *name, struct qstr *this, int len)
26109+{
2cbb1c4b
JR
26110+ unsigned int c;
26111+
26112+ this->name = name;
26113+ this->len = len;
7eafdf33 26114+ this->hash = full_name_hash(name, len);
2cbb1c4b
JR
26115+ if (!len)
26116+ return -EACCES;
26117+
2cbb1c4b
JR
26118+ while (len--) {
26119+ c = *(const unsigned char *)name++;
26120+ if (c == '/' || c == '\0')
26121+ return -EACCES;
2cbb1c4b 26122+ }
2cbb1c4b
JR
26123+ return 0;
26124+}
26125+
1facf9fc 26126+/* ---------------------------------------------------------------------- */
26127+
26128+struct dentry *vfsub_lock_rename(struct dentry *d1, struct au_hinode *hdir1,
26129+ struct dentry *d2, struct au_hinode *hdir2)
26130+{
26131+ struct dentry *d;
26132+
2cbb1c4b 26133+ lockdep_off();
1facf9fc 26134+ d = lock_rename(d1, d2);
2cbb1c4b 26135+ lockdep_on();
4a4d8108 26136+ au_hn_suspend(hdir1);
1facf9fc 26137+ if (hdir1 != hdir2)
4a4d8108 26138+ au_hn_suspend(hdir2);
1facf9fc 26139+
26140+ return d;
26141+}
26142+
26143+void vfsub_unlock_rename(struct dentry *d1, struct au_hinode *hdir1,
26144+ struct dentry *d2, struct au_hinode *hdir2)
26145+{
4a4d8108 26146+ au_hn_resume(hdir1);
1facf9fc 26147+ if (hdir1 != hdir2)
4a4d8108 26148+ au_hn_resume(hdir2);
2cbb1c4b 26149+ lockdep_off();
1facf9fc 26150+ unlock_rename(d1, d2);
2cbb1c4b 26151+ lockdep_on();
1facf9fc 26152+}
26153+
26154+/* ---------------------------------------------------------------------- */
26155+
26156+int vfsub_create(struct inode *dir, struct path *path, int mode)
26157+{
26158+ int err;
26159+ struct dentry *d;
26160+
26161+ IMustLock(dir);
26162+
26163+ d = path->dentry;
26164+ path->dentry = d->d_parent;
b752ccd1 26165+ err = security_path_mknod(path, d, mode, 0);
1facf9fc 26166+ path->dentry = d;
26167+ if (unlikely(err))
26168+ goto out;
26169+
26170+ if (au_test_fs_null_nd(dir->i_sb))
26171+ err = vfs_create(dir, path->dentry, mode, NULL);
26172+ else {
26173+ struct nameidata h_nd;
26174+
26175+ memset(&h_nd, 0, sizeof(h_nd));
26176+ h_nd.flags = LOOKUP_CREATE;
26177+ h_nd.intent.open.flags = O_CREAT
26178+ | vfsub_fmode_to_uint(FMODE_READ);
26179+ h_nd.intent.open.create_mode = mode;
26180+ h_nd.path.dentry = path->dentry->d_parent;
26181+ h_nd.path.mnt = path->mnt;
26182+ path_get(&h_nd.path);
26183+ err = vfs_create(dir, path->dentry, mode, &h_nd);
26184+ path_put(&h_nd.path);
26185+ }
26186+
26187+ if (!err) {
26188+ struct path tmp = *path;
26189+ int did;
26190+
26191+ vfsub_update_h_iattr(&tmp, &did);
26192+ if (did) {
26193+ tmp.dentry = path->dentry->d_parent;
26194+ vfsub_update_h_iattr(&tmp, /*did*/NULL);
26195+ }
26196+ /*ignore*/
26197+ }
26198+
4f0767ce 26199+out:
1facf9fc 26200+ return err;
26201+}
26202+
26203+int vfsub_symlink(struct inode *dir, struct path *path, const char *symname)
26204+{
26205+ int err;
26206+ struct dentry *d;
26207+
26208+ IMustLock(dir);
26209+
26210+ d = path->dentry;
26211+ path->dentry = d->d_parent;
b752ccd1 26212+ err = security_path_symlink(path, d, symname);
1facf9fc 26213+ path->dentry = d;
26214+ if (unlikely(err))
26215+ goto out;
26216+
26217+ err = vfs_symlink(dir, path->dentry, symname);
26218+ if (!err) {
26219+ struct path tmp = *path;
26220+ int did;
26221+
26222+ vfsub_update_h_iattr(&tmp, &did);
26223+ if (did) {
26224+ tmp.dentry = path->dentry->d_parent;
26225+ vfsub_update_h_iattr(&tmp, /*did*/NULL);
26226+ }
26227+ /*ignore*/
26228+ }
26229+
4f0767ce 26230+out:
1facf9fc 26231+ return err;
26232+}
26233+
26234+int vfsub_mknod(struct inode *dir, struct path *path, int mode, dev_t dev)
26235+{
26236+ int err;
26237+ struct dentry *d;
26238+
26239+ IMustLock(dir);
26240+
26241+ d = path->dentry;
26242+ path->dentry = d->d_parent;
027c5e7a 26243+ err = security_path_mknod(path, d, mode, new_encode_dev(dev));
1facf9fc 26244+ path->dentry = d;
26245+ if (unlikely(err))
26246+ goto out;
26247+
26248+ err = vfs_mknod(dir, path->dentry, mode, dev);
26249+ if (!err) {
26250+ struct path tmp = *path;
26251+ int did;
26252+
26253+ vfsub_update_h_iattr(&tmp, &did);
26254+ if (did) {
26255+ tmp.dentry = path->dentry->d_parent;
26256+ vfsub_update_h_iattr(&tmp, /*did*/NULL);
26257+ }
26258+ /*ignore*/
26259+ }
26260+
4f0767ce 26261+out:
1facf9fc 26262+ return err;
26263+}
26264+
26265+static int au_test_nlink(struct inode *inode)
26266+{
26267+ const unsigned int link_max = UINT_MAX >> 1; /* rough margin */
26268+
26269+ if (!au_test_fs_no_limit_nlink(inode->i_sb)
26270+ || inode->i_nlink < link_max)
26271+ return 0;
26272+ return -EMLINK;
26273+}
26274+
26275+int vfsub_link(struct dentry *src_dentry, struct inode *dir, struct path *path)
26276+{
26277+ int err;
26278+ struct dentry *d;
26279+
26280+ IMustLock(dir);
26281+
26282+ err = au_test_nlink(src_dentry->d_inode);
26283+ if (unlikely(err))
26284+ return err;
26285+
26286+ d = path->dentry;
26287+ path->dentry = d->d_parent;
b752ccd1 26288+ err = security_path_link(src_dentry, path, d);
1facf9fc 26289+ path->dentry = d;
26290+ if (unlikely(err))
26291+ goto out;
26292+
2cbb1c4b 26293+ lockdep_off();
1facf9fc 26294+ err = vfs_link(src_dentry, dir, path->dentry);
2cbb1c4b 26295+ lockdep_on();
1facf9fc 26296+ if (!err) {
26297+ struct path tmp = *path;
26298+ int did;
26299+
26300+ /* fuse has different memory inode for the same inumber */
26301+ vfsub_update_h_iattr(&tmp, &did);
26302+ if (did) {
26303+ tmp.dentry = path->dentry->d_parent;
26304+ vfsub_update_h_iattr(&tmp, /*did*/NULL);
26305+ tmp.dentry = src_dentry;
26306+ vfsub_update_h_iattr(&tmp, /*did*/NULL);
26307+ }
26308+ /*ignore*/
26309+ }
26310+
4f0767ce 26311+out:
1facf9fc 26312+ return err;
26313+}
26314+
26315+int vfsub_rename(struct inode *src_dir, struct dentry *src_dentry,
26316+ struct inode *dir, struct path *path)
26317+{
26318+ int err;
26319+ struct path tmp = {
26320+ .mnt = path->mnt
26321+ };
26322+ struct dentry *d;
26323+
26324+ IMustLock(dir);
26325+ IMustLock(src_dir);
26326+
26327+ d = path->dentry;
26328+ path->dentry = d->d_parent;
26329+ tmp.dentry = src_dentry->d_parent;
b752ccd1 26330+ err = security_path_rename(&tmp, src_dentry, path, d);
1facf9fc 26331+ path->dentry = d;
26332+ if (unlikely(err))
26333+ goto out;
26334+
2cbb1c4b 26335+ lockdep_off();
1facf9fc 26336+ err = vfs_rename(src_dir, src_dentry, dir, path->dentry);
2cbb1c4b 26337+ lockdep_on();
1facf9fc 26338+ if (!err) {
26339+ int did;
26340+
26341+ tmp.dentry = d->d_parent;
26342+ vfsub_update_h_iattr(&tmp, &did);
26343+ if (did) {
26344+ tmp.dentry = src_dentry;
26345+ vfsub_update_h_iattr(&tmp, /*did*/NULL);
26346+ tmp.dentry = src_dentry->d_parent;
26347+ vfsub_update_h_iattr(&tmp, /*did*/NULL);
26348+ }
26349+ /*ignore*/
26350+ }
26351+
4f0767ce 26352+out:
1facf9fc 26353+ return err;
26354+}
26355+
26356+int vfsub_mkdir(struct inode *dir, struct path *path, int mode)
26357+{
26358+ int err;
26359+ struct dentry *d;
26360+
26361+ IMustLock(dir);
26362+
26363+ d = path->dentry;
26364+ path->dentry = d->d_parent;
b752ccd1 26365+ err = security_path_mkdir(path, d, mode);
1facf9fc 26366+ path->dentry = d;
26367+ if (unlikely(err))
26368+ goto out;
26369+
26370+ err = vfs_mkdir(dir, path->dentry, mode);
26371+ if (!err) {
26372+ struct path tmp = *path;
26373+ int did;
26374+
26375+ vfsub_update_h_iattr(&tmp, &did);
26376+ if (did) {
26377+ tmp.dentry = path->dentry->d_parent;
26378+ vfsub_update_h_iattr(&tmp, /*did*/NULL);
26379+ }
26380+ /*ignore*/
26381+ }
26382+
4f0767ce 26383+out:
1facf9fc 26384+ return err;
26385+}
26386+
26387+int vfsub_rmdir(struct inode *dir, struct path *path)
26388+{
26389+ int err;
26390+ struct dentry *d;
26391+
26392+ IMustLock(dir);
26393+
26394+ d = path->dentry;
26395+ path->dentry = d->d_parent;
b752ccd1 26396+ err = security_path_rmdir(path, d);
1facf9fc 26397+ path->dentry = d;
26398+ if (unlikely(err))
26399+ goto out;
26400+
2cbb1c4b 26401+ lockdep_off();
1facf9fc 26402+ err = vfs_rmdir(dir, path->dentry);
2cbb1c4b 26403+ lockdep_on();
1facf9fc 26404+ if (!err) {
26405+ struct path tmp = {
26406+ .dentry = path->dentry->d_parent,
26407+ .mnt = path->mnt
26408+ };
26409+
26410+ vfsub_update_h_iattr(&tmp, /*did*/NULL); /*ignore*/
26411+ }
26412+
4f0767ce 26413+out:
1facf9fc 26414+ return err;
26415+}
26416+
26417+/* ---------------------------------------------------------------------- */
26418+
9dbd164d 26419+/* todo: support mmap_sem? */
1facf9fc 26420+ssize_t vfsub_read_u(struct file *file, char __user *ubuf, size_t count,
26421+ loff_t *ppos)
26422+{
26423+ ssize_t err;
26424+
2cbb1c4b 26425+ lockdep_off();
1facf9fc 26426+ err = vfs_read(file, ubuf, count, ppos);
2cbb1c4b 26427+ lockdep_on();
1facf9fc 26428+ if (err >= 0)
26429+ vfsub_update_h_iattr(&file->f_path, /*did*/NULL); /*ignore*/
26430+ return err;
26431+}
26432+
26433+/* todo: kernel_read()? */
26434+ssize_t vfsub_read_k(struct file *file, void *kbuf, size_t count,
26435+ loff_t *ppos)
26436+{
26437+ ssize_t err;
26438+ mm_segment_t oldfs;
b752ccd1
AM
26439+ union {
26440+ void *k;
26441+ char __user *u;
26442+ } buf;
1facf9fc 26443+
b752ccd1 26444+ buf.k = kbuf;
1facf9fc 26445+ oldfs = get_fs();
26446+ set_fs(KERNEL_DS);
b752ccd1 26447+ err = vfsub_read_u(file, buf.u, count, ppos);
1facf9fc 26448+ set_fs(oldfs);
26449+ return err;
26450+}
26451+
26452+ssize_t vfsub_write_u(struct file *file, const char __user *ubuf, size_t count,
26453+ loff_t *ppos)
26454+{
26455+ ssize_t err;
26456+
2cbb1c4b 26457+ lockdep_off();
1facf9fc 26458+ err = vfs_write(file, ubuf, count, ppos);
2cbb1c4b 26459+ lockdep_on();
1facf9fc 26460+ if (err >= 0)
26461+ vfsub_update_h_iattr(&file->f_path, /*did*/NULL); /*ignore*/
26462+ return err;
26463+}
26464+
26465+ssize_t vfsub_write_k(struct file *file, void *kbuf, size_t count, loff_t *ppos)
26466+{
26467+ ssize_t err;
26468+ mm_segment_t oldfs;
b752ccd1
AM
26469+ union {
26470+ void *k;
26471+ const char __user *u;
26472+ } buf;
1facf9fc 26473+
b752ccd1 26474+ buf.k = kbuf;
1facf9fc 26475+ oldfs = get_fs();
26476+ set_fs(KERNEL_DS);
b752ccd1 26477+ err = vfsub_write_u(file, buf.u, count, ppos);
1facf9fc 26478+ set_fs(oldfs);
26479+ return err;
26480+}
26481+
4a4d8108
AM
26482+int vfsub_flush(struct file *file, fl_owner_t id)
26483+{
26484+ int err;
26485+
26486+ err = 0;
26487+ if (file->f_op && file->f_op->flush) {
2cbb1c4b
JR
26488+ if (!au_test_nfs(file->f_dentry->d_sb))
26489+ err = file->f_op->flush(file, id);
26490+ else {
26491+ lockdep_off();
26492+ err = file->f_op->flush(file, id);
26493+ lockdep_on();
26494+ }
4a4d8108
AM
26495+ if (!err)
26496+ vfsub_update_h_iattr(&file->f_path, /*did*/NULL);
26497+ /*ignore*/
26498+ }
26499+ return err;
26500+}
26501+
1facf9fc 26502+int vfsub_readdir(struct file *file, filldir_t filldir, void *arg)
26503+{
26504+ int err;
26505+
2cbb1c4b 26506+ lockdep_off();
1facf9fc 26507+ err = vfs_readdir(file, filldir, arg);
2cbb1c4b 26508+ lockdep_on();
1facf9fc 26509+ if (err >= 0)
26510+ vfsub_update_h_iattr(&file->f_path, /*did*/NULL); /*ignore*/
26511+ return err;
26512+}
26513+
26514+long vfsub_splice_to(struct file *in, loff_t *ppos,
26515+ struct pipe_inode_info *pipe, size_t len,
26516+ unsigned int flags)
26517+{
26518+ long err;
26519+
2cbb1c4b 26520+ lockdep_off();
0fc653ad 26521+ err = do_splice_to(in, ppos, pipe, len, flags);
2cbb1c4b 26522+ lockdep_on();
4a4d8108 26523+ file_accessed(in);
1facf9fc 26524+ if (err >= 0)
26525+ vfsub_update_h_iattr(&in->f_path, /*did*/NULL); /*ignore*/
26526+ return err;
26527+}
26528+
26529+long vfsub_splice_from(struct pipe_inode_info *pipe, struct file *out,
26530+ loff_t *ppos, size_t len, unsigned int flags)
26531+{
26532+ long err;
26533+
2cbb1c4b 26534+ lockdep_off();
0fc653ad 26535+ err = do_splice_from(pipe, out, ppos, len, flags);
2cbb1c4b 26536+ lockdep_on();
1facf9fc 26537+ if (err >= 0)
26538+ vfsub_update_h_iattr(&out->f_path, /*did*/NULL); /*ignore*/
26539+ return err;
26540+}
26541+
53392da6
AM
26542+int vfsub_fsync(struct file *file, struct path *path, int datasync)
26543+{
26544+ int err;
26545+
26546+ /* file can be NULL */
26547+ lockdep_off();
26548+ err = vfs_fsync(file, datasync);
26549+ lockdep_on();
26550+ if (!err) {
26551+ if (!path) {
26552+ AuDebugOn(!file);
26553+ path = &file->f_path;
26554+ }
26555+ vfsub_update_h_iattr(path, /*did*/NULL); /*ignore*/
26556+ }
26557+ return err;
26558+}
26559+
1facf9fc 26560+/* cf. open.c:do_sys_truncate() and do_sys_ftruncate() */
26561+int vfsub_trunc(struct path *h_path, loff_t length, unsigned int attr,
26562+ struct file *h_file)
26563+{
26564+ int err;
26565+ struct inode *h_inode;
26566+
26567+ h_inode = h_path->dentry->d_inode;
26568+ if (!h_file) {
26569+ err = mnt_want_write(h_path->mnt);
26570+ if (err)
26571+ goto out;
26572+ err = inode_permission(h_inode, MAY_WRITE);
26573+ if (err)
26574+ goto out_mnt;
26575+ err = get_write_access(h_inode);
26576+ if (err)
26577+ goto out_mnt;
4a4d8108 26578+ err = break_lease(h_inode, O_WRONLY);
1facf9fc 26579+ if (err)
26580+ goto out_inode;
26581+ }
26582+
26583+ err = locks_verify_truncate(h_inode, h_file, length);
26584+ if (!err)
953406b4 26585+ err = security_path_truncate(h_path);
2cbb1c4b
JR
26586+ if (!err) {
26587+ lockdep_off();
1facf9fc 26588+ err = do_truncate(h_path->dentry, length, attr, h_file);
2cbb1c4b
JR
26589+ lockdep_on();
26590+ }
1facf9fc 26591+
4f0767ce 26592+out_inode:
1facf9fc 26593+ if (!h_file)
26594+ put_write_access(h_inode);
4f0767ce 26595+out_mnt:
1facf9fc 26596+ if (!h_file)
26597+ mnt_drop_write(h_path->mnt);
4f0767ce 26598+out:
1facf9fc 26599+ return err;
26600+}
26601+
26602+/* ---------------------------------------------------------------------- */
26603+
26604+struct au_vfsub_mkdir_args {
26605+ int *errp;
26606+ struct inode *dir;
26607+ struct path *path;
26608+ int mode;
26609+};
26610+
26611+static void au_call_vfsub_mkdir(void *args)
26612+{
26613+ struct au_vfsub_mkdir_args *a = args;
26614+ *a->errp = vfsub_mkdir(a->dir, a->path, a->mode);
26615+}
26616+
26617+int vfsub_sio_mkdir(struct inode *dir, struct path *path, int mode)
26618+{
26619+ int err, do_sio, wkq_err;
26620+
26621+ do_sio = au_test_h_perm_sio(dir, MAY_EXEC | MAY_WRITE);
26622+ if (!do_sio)
26623+ err = vfsub_mkdir(dir, path, mode);
26624+ else {
26625+ struct au_vfsub_mkdir_args args = {
26626+ .errp = &err,
26627+ .dir = dir,
26628+ .path = path,
26629+ .mode = mode
26630+ };
26631+ wkq_err = au_wkq_wait(au_call_vfsub_mkdir, &args);
26632+ if (unlikely(wkq_err))
26633+ err = wkq_err;
26634+ }
26635+
26636+ return err;
26637+}
26638+
26639+struct au_vfsub_rmdir_args {
26640+ int *errp;
26641+ struct inode *dir;
26642+ struct path *path;
26643+};
26644+
26645+static void au_call_vfsub_rmdir(void *args)
26646+{
26647+ struct au_vfsub_rmdir_args *a = args;
26648+ *a->errp = vfsub_rmdir(a->dir, a->path);
26649+}
26650+
26651+int vfsub_sio_rmdir(struct inode *dir, struct path *path)
26652+{
26653+ int err, do_sio, wkq_err;
26654+
26655+ do_sio = au_test_h_perm_sio(dir, MAY_EXEC | MAY_WRITE);
26656+ if (!do_sio)
26657+ err = vfsub_rmdir(dir, path);
26658+ else {
26659+ struct au_vfsub_rmdir_args args = {
26660+ .errp = &err,
26661+ .dir = dir,
26662+ .path = path
26663+ };
26664+ wkq_err = au_wkq_wait(au_call_vfsub_rmdir, &args);
26665+ if (unlikely(wkq_err))
26666+ err = wkq_err;
26667+ }
26668+
26669+ return err;
26670+}
26671+
26672+/* ---------------------------------------------------------------------- */
26673+
26674+struct notify_change_args {
26675+ int *errp;
26676+ struct path *path;
26677+ struct iattr *ia;
26678+};
26679+
26680+static void call_notify_change(void *args)
26681+{
26682+ struct notify_change_args *a = args;
26683+ struct inode *h_inode;
26684+
26685+ h_inode = a->path->dentry->d_inode;
26686+ IMustLock(h_inode);
26687+
26688+ *a->errp = -EPERM;
26689+ if (!IS_IMMUTABLE(h_inode) && !IS_APPEND(h_inode)) {
1facf9fc 26690+ *a->errp = notify_change(a->path->dentry, a->ia);
1facf9fc 26691+ if (!*a->errp)
26692+ vfsub_update_h_iattr(a->path, /*did*/NULL); /*ignore*/
26693+ }
26694+ AuTraceErr(*a->errp);
26695+}
26696+
26697+int vfsub_notify_change(struct path *path, struct iattr *ia)
26698+{
26699+ int err;
26700+ struct notify_change_args args = {
26701+ .errp = &err,
26702+ .path = path,
26703+ .ia = ia
26704+ };
26705+
26706+ call_notify_change(&args);
26707+
26708+ return err;
26709+}
26710+
26711+int vfsub_sio_notify_change(struct path *path, struct iattr *ia)
26712+{
26713+ int err, wkq_err;
26714+ struct notify_change_args args = {
26715+ .errp = &err,
26716+ .path = path,
26717+ .ia = ia
26718+ };
26719+
26720+ wkq_err = au_wkq_wait(call_notify_change, &args);
26721+ if (unlikely(wkq_err))
26722+ err = wkq_err;
26723+
26724+ return err;
26725+}
26726+
26727+/* ---------------------------------------------------------------------- */
26728+
26729+struct unlink_args {
26730+ int *errp;
26731+ struct inode *dir;
26732+ struct path *path;
26733+};
26734+
26735+static void call_unlink(void *args)
26736+{
26737+ struct unlink_args *a = args;
26738+ struct dentry *d = a->path->dentry;
26739+ struct inode *h_inode;
26740+ const int stop_sillyrename = (au_test_nfs(d->d_sb)
027c5e7a 26741+ && d->d_count == 1);
1facf9fc 26742+
26743+ IMustLock(a->dir);
26744+
26745+ a->path->dentry = d->d_parent;
26746+ *a->errp = security_path_unlink(a->path, d);
26747+ a->path->dentry = d;
26748+ if (unlikely(*a->errp))
26749+ return;
26750+
26751+ if (!stop_sillyrename)
26752+ dget(d);
26753+ h_inode = d->d_inode;
26754+ if (h_inode)
027c5e7a 26755+ ihold(h_inode);
1facf9fc 26756+
2cbb1c4b 26757+ lockdep_off();
1facf9fc 26758+ *a->errp = vfs_unlink(a->dir, d);
2cbb1c4b 26759+ lockdep_on();
1facf9fc 26760+ if (!*a->errp) {
26761+ struct path tmp = {
26762+ .dentry = d->d_parent,
26763+ .mnt = a->path->mnt
26764+ };
26765+ vfsub_update_h_iattr(&tmp, /*did*/NULL); /*ignore*/
26766+ }
26767+
26768+ if (!stop_sillyrename)
26769+ dput(d);
26770+ if (h_inode)
26771+ iput(h_inode);
26772+
26773+ AuTraceErr(*a->errp);
26774+}
26775+
26776+/*
26777+ * @dir: must be locked.
26778+ * @dentry: target dentry.
26779+ */
26780+int vfsub_unlink(struct inode *dir, struct path *path, int force)
26781+{
26782+ int err;
26783+ struct unlink_args args = {
26784+ .errp = &err,
26785+ .dir = dir,
26786+ .path = path
26787+ };
26788+
26789+ if (!force)
26790+ call_unlink(&args);
26791+ else {
26792+ int wkq_err;
26793+
26794+ wkq_err = au_wkq_wait(call_unlink, &args);
26795+ if (unlikely(wkq_err))
26796+ err = wkq_err;
26797+ }
26798+
26799+ return err;
26800+}
7f207e10
AM
26801diff -urN /usr/share/empty/fs/aufs/vfsub.h linux/fs/aufs/vfsub.h
26802--- /usr/share/empty/fs/aufs/vfsub.h 1970-01-01 01:00:00.000000000 +0100
0c3ec466
AM
26803+++ linux/fs/aufs/vfsub.h 2012-07-22 19:57:03.167671344 +0200
26804@@ -0,0 +1,252 @@
1facf9fc 26805+/*
f6c5ef8b 26806+ * Copyright (C) 2005-2012 Junjiro R. Okajima
1facf9fc 26807+ *
26808+ * This program, aufs is free software; you can redistribute it and/or modify
26809+ * it under the terms of the GNU General Public License as published by
26810+ * the Free Software Foundation; either version 2 of the License, or
26811+ * (at your option) any later version.
dece6358
AM
26812+ *
26813+ * This program is distributed in the hope that it will be useful,
26814+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
26815+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
26816+ * GNU General Public License for more details.
26817+ *
26818+ * You should have received a copy of the GNU General Public License
26819+ * along with this program; if not, write to the Free Software
26820+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 26821+ */
26822+
26823+/*
26824+ * sub-routines for VFS
26825+ */
26826+
26827+#ifndef __AUFS_VFSUB_H__
26828+#define __AUFS_VFSUB_H__
26829+
26830+#ifdef __KERNEL__
26831+
26832+#include <linux/fs.h>
0c5527e5 26833+#include <linux/lglock.h>
7f207e10 26834+#include "debug.h"
1facf9fc 26835+
7f207e10 26836+/* copied from linux/fs/internal.h */
2cbb1c4b 26837+/* todo: BAD approach!! */
0c3ec466 26838+extern struct lglock vfsmount_lock;
0c5527e5 26839+extern void file_sb_list_del(struct file *f);
2cbb1c4b 26840+extern spinlock_t inode_sb_list_lock;
0c5527e5 26841+
7f207e10 26842+/* copied from linux/fs/file_table.c */
0c3ec466 26843+extern struct lglock files_lglock;
0c5527e5
AM
26844+#ifdef CONFIG_SMP
26845+/*
26846+ * These macros iterate all files on all CPUs for a given superblock.
26847+ * files_lglock must be held globally.
26848+ */
26849+#define do_file_list_for_each_entry(__sb, __file) \
26850+{ \
26851+ int i; \
26852+ for_each_possible_cpu(i) { \
26853+ struct list_head *list; \
26854+ list = per_cpu_ptr((__sb)->s_files, i); \
26855+ list_for_each_entry((__file), list, f_u.fu_list)
26856+
26857+#define while_file_list_for_each_entry \
26858+ } \
26859+}
26860+
26861+#else
26862+
26863+#define do_file_list_for_each_entry(__sb, __file) \
26864+{ \
26865+ struct list_head *list; \
26866+ list = &(sb)->s_files; \
26867+ list_for_each_entry((__file), list, f_u.fu_list)
26868+
26869+#define while_file_list_for_each_entry \
26870+}
7f207e10
AM
26871+#endif
26872+
26873+/* ---------------------------------------------------------------------- */
1facf9fc 26874+
26875+/* lock subclass for lower inode */
26876+/* default MAX_LOCKDEP_SUBCLASSES(8) is not enough */
26877+/* reduce? gave up. */
26878+enum {
26879+ AuLsc_I_Begin = I_MUTEX_QUOTA, /* 4 */
26880+ AuLsc_I_PARENT, /* lower inode, parent first */
26881+ AuLsc_I_PARENT2, /* copyup dirs */
dece6358 26882+ AuLsc_I_PARENT3, /* copyup wh */
1facf9fc 26883+ AuLsc_I_CHILD,
26884+ AuLsc_I_CHILD2,
26885+ AuLsc_I_End
26886+};
26887+
26888+/* to debug easier, do not make them inlined functions */
26889+#define MtxMustLock(mtx) AuDebugOn(!mutex_is_locked(mtx))
26890+#define IMustLock(i) MtxMustLock(&(i)->i_mutex)
26891+
26892+/* ---------------------------------------------------------------------- */
26893+
7f207e10
AM
26894+static inline void vfsub_drop_nlink(struct inode *inode)
26895+{
26896+ AuDebugOn(!inode->i_nlink);
26897+ drop_nlink(inode);
26898+}
26899+
027c5e7a
AM
26900+static inline void vfsub_dead_dir(struct inode *inode)
26901+{
26902+ AuDebugOn(!S_ISDIR(inode->i_mode));
26903+ inode->i_flags |= S_DEAD;
26904+ clear_nlink(inode);
26905+}
26906+
7f207e10
AM
26907+/* ---------------------------------------------------------------------- */
26908+
0c3ec466
AM
26909+/* cf. i_[ug]id_read() in linux/include/fs.h */
26910+static inline uid_t vfsub_ia_uid(struct iattr *ia)
26911+{
26912+ return from_kuid(&init_user_ns, ia->ia_uid);
26913+}
26914+
26915+static inline gid_t vfsub_ia_gid(struct iattr *ia)
26916+{
26917+ return from_kgid(&init_user_ns, ia->ia_gid);
26918+}
26919+
26920+/* ---------------------------------------------------------------------- */
26921+
7f207e10
AM
26922+int vfsub_update_h_iattr(struct path *h_path, int *did);
26923+struct file *vfsub_dentry_open(struct path *path, int flags);
26924+struct file *vfsub_filp_open(const char *path, int oflags, int mode);
1facf9fc 26925+int vfsub_kern_path(const char *name, unsigned int flags, struct path *path);
26926+struct dentry *vfsub_lookup_one_len(const char *name, struct dentry *parent,
26927+ int len);
26928+struct dentry *vfsub_lookup_hash(struct nameidata *nd);
2cbb1c4b 26929+int vfsub_name_hash(const char *name, struct qstr *this, int len);
1facf9fc 26930+
26931+/* ---------------------------------------------------------------------- */
26932+
26933+struct au_hinode;
26934+struct dentry *vfsub_lock_rename(struct dentry *d1, struct au_hinode *hdir1,
26935+ struct dentry *d2, struct au_hinode *hdir2);
26936+void vfsub_unlock_rename(struct dentry *d1, struct au_hinode *hdir1,
26937+ struct dentry *d2, struct au_hinode *hdir2);
26938+
26939+int vfsub_create(struct inode *dir, struct path *path, int mode);
26940+int vfsub_symlink(struct inode *dir, struct path *path,
26941+ const char *symname);
26942+int vfsub_mknod(struct inode *dir, struct path *path, int mode, dev_t dev);
26943+int vfsub_link(struct dentry *src_dentry, struct inode *dir,
26944+ struct path *path);
26945+int vfsub_rename(struct inode *src_hdir, struct dentry *src_dentry,
26946+ struct inode *hdir, struct path *path);
26947+int vfsub_mkdir(struct inode *dir, struct path *path, int mode);
26948+int vfsub_rmdir(struct inode *dir, struct path *path);
26949+
26950+/* ---------------------------------------------------------------------- */
26951+
26952+ssize_t vfsub_read_u(struct file *file, char __user *ubuf, size_t count,
26953+ loff_t *ppos);
26954+ssize_t vfsub_read_k(struct file *file, void *kbuf, size_t count,
26955+ loff_t *ppos);
26956+ssize_t vfsub_write_u(struct file *file, const char __user *ubuf, size_t count,
26957+ loff_t *ppos);
26958+ssize_t vfsub_write_k(struct file *file, void *kbuf, size_t count,
26959+ loff_t *ppos);
4a4d8108 26960+int vfsub_flush(struct file *file, fl_owner_t id);
1facf9fc 26961+int vfsub_readdir(struct file *file, filldir_t filldir, void *arg);
26962+
4a4d8108
AM
26963+static inline unsigned int vfsub_file_flags(struct file *file)
26964+{
26965+ unsigned int flags;
26966+
26967+ spin_lock(&file->f_lock);
26968+ flags = file->f_flags;
26969+ spin_unlock(&file->f_lock);
26970+
26971+ return flags;
26972+}
1308ab2a 26973+
1facf9fc 26974+static inline void vfsub_file_accessed(struct file *h_file)
26975+{
26976+ file_accessed(h_file);
26977+ vfsub_update_h_iattr(&h_file->f_path, /*did*/NULL); /*ignore*/
26978+}
26979+
26980+static inline void vfsub_touch_atime(struct vfsmount *h_mnt,
26981+ struct dentry *h_dentry)
26982+{
26983+ struct path h_path = {
26984+ .dentry = h_dentry,
26985+ .mnt = h_mnt
26986+ };
92d182d2 26987+ touch_atime(&h_path);
1facf9fc 26988+ vfsub_update_h_iattr(&h_path, /*did*/NULL); /*ignore*/
26989+}
26990+
0c3ec466
AM
26991+static inline int vfsub_update_time(struct inode *h_inode, struct timespec *ts,
26992+ int flags)
26993+{
26994+ return update_time(h_inode, ts, flags);
26995+ /* no vfsub_update_h_iattr() since we don't have struct path */
26996+}
26997+
4a4d8108
AM
26998+long vfsub_splice_to(struct file *in, loff_t *ppos,
26999+ struct pipe_inode_info *pipe, size_t len,
27000+ unsigned int flags);
27001+long vfsub_splice_from(struct pipe_inode_info *pipe, struct file *out,
27002+ loff_t *ppos, size_t len, unsigned int flags);
27003+int vfsub_trunc(struct path *h_path, loff_t length, unsigned int attr,
27004+ struct file *h_file);
53392da6 27005+int vfsub_fsync(struct file *file, struct path *path, int datasync);
4a4d8108 27006+
1facf9fc 27007+/* ---------------------------------------------------------------------- */
27008+
27009+static inline loff_t vfsub_llseek(struct file *file, loff_t offset, int origin)
27010+{
27011+ loff_t err;
27012+
2cbb1c4b 27013+ lockdep_off();
1facf9fc 27014+ err = vfs_llseek(file, offset, origin);
2cbb1c4b 27015+ lockdep_on();
1facf9fc 27016+ return err;
27017+}
27018+
27019+/* ---------------------------------------------------------------------- */
27020+
27021+/* dirty workaround for strict type of fmode_t */
27022+union vfsub_fmu {
27023+ fmode_t fm;
27024+ unsigned int ui;
27025+};
27026+
27027+static inline unsigned int vfsub_fmode_to_uint(fmode_t fm)
27028+{
27029+ union vfsub_fmu u = {
27030+ .fm = fm
27031+ };
27032+
27033+ BUILD_BUG_ON(sizeof(u.fm) != sizeof(u.ui));
27034+
27035+ return u.ui;
27036+}
27037+
27038+static inline fmode_t vfsub_uint_to_fmode(unsigned int ui)
27039+{
27040+ union vfsub_fmu u = {
27041+ .ui = ui
27042+ };
27043+
27044+ return u.fm;
27045+}
27046+
4a4d8108
AM
27047+/* ---------------------------------------------------------------------- */
27048+
27049+int vfsub_sio_mkdir(struct inode *dir, struct path *path, int mode);
27050+int vfsub_sio_rmdir(struct inode *dir, struct path *path);
27051+int vfsub_sio_notify_change(struct path *path, struct iattr *ia);
27052+int vfsub_notify_change(struct path *path, struct iattr *ia);
27053+int vfsub_unlink(struct inode *dir, struct path *path, int force);
27054+
1facf9fc 27055+#endif /* __KERNEL__ */
27056+#endif /* __AUFS_VFSUB_H__ */
7f207e10
AM
27057diff -urN /usr/share/empty/fs/aufs/wbr_policy.c linux/fs/aufs/wbr_policy.c
27058--- /usr/share/empty/fs/aufs/wbr_policy.c 1970-01-01 01:00:00.000000000 +0100
0c3ec466 27059+++ linux/fs/aufs/wbr_policy.c 2012-07-22 19:57:03.167671344 +0200
027c5e7a 27060@@ -0,0 +1,700 @@
1facf9fc 27061+/*
f6c5ef8b 27062+ * Copyright (C) 2005-2012 Junjiro R. Okajima
1facf9fc 27063+ *
27064+ * This program, aufs is free software; you can redistribute it and/or modify
27065+ * it under the terms of the GNU General Public License as published by
27066+ * the Free Software Foundation; either version 2 of the License, or
27067+ * (at your option) any later version.
dece6358
AM
27068+ *
27069+ * This program is distributed in the hope that it will be useful,
27070+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
27071+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
27072+ * GNU General Public License for more details.
27073+ *
27074+ * You should have received a copy of the GNU General Public License
27075+ * along with this program; if not, write to the Free Software
27076+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 27077+ */
27078+
27079+/*
27080+ * policies for selecting one among multiple writable branches
27081+ */
27082+
27083+#include <linux/statfs.h>
27084+#include "aufs.h"
27085+
27086+/* subset of cpup_attr() */
27087+static noinline_for_stack
27088+int au_cpdown_attr(struct path *h_path, struct dentry *h_src)
27089+{
27090+ int err, sbits;
27091+ struct iattr ia;
27092+ struct inode *h_isrc;
27093+
27094+ h_isrc = h_src->d_inode;
27095+ ia.ia_valid = ATTR_FORCE | ATTR_MODE | ATTR_UID | ATTR_GID;
27096+ ia.ia_mode = h_isrc->i_mode;
27097+ ia.ia_uid = h_isrc->i_uid;
27098+ ia.ia_gid = h_isrc->i_gid;
27099+ sbits = !!(ia.ia_mode & (S_ISUID | S_ISGID));
27100+ au_cpup_attr_flags(h_path->dentry->d_inode, h_isrc);
27101+ err = vfsub_sio_notify_change(h_path, &ia);
27102+
27103+ /* is this nfs only? */
27104+ if (!err && sbits && au_test_nfs(h_path->dentry->d_sb)) {
27105+ ia.ia_valid = ATTR_FORCE | ATTR_MODE;
27106+ ia.ia_mode = h_isrc->i_mode;
27107+ err = vfsub_sio_notify_change(h_path, &ia);
27108+ }
27109+
27110+ return err;
27111+}
27112+
27113+#define AuCpdown_PARENT_OPQ 1
27114+#define AuCpdown_WHED (1 << 1)
27115+#define AuCpdown_MADE_DIR (1 << 2)
27116+#define AuCpdown_DIROPQ (1 << 3)
27117+#define au_ftest_cpdown(flags, name) ((flags) & AuCpdown_##name)
7f207e10
AM
27118+#define au_fset_cpdown(flags, name) \
27119+ do { (flags) |= AuCpdown_##name; } while (0)
27120+#define au_fclr_cpdown(flags, name) \
27121+ do { (flags) &= ~AuCpdown_##name; } while (0)
1facf9fc 27122+
27123+struct au_cpdown_dir_args {
27124+ struct dentry *parent;
27125+ unsigned int flags;
27126+};
27127+
27128+static int au_cpdown_dir_opq(struct dentry *dentry, aufs_bindex_t bdst,
27129+ struct au_cpdown_dir_args *a)
27130+{
27131+ int err;
27132+ struct dentry *opq_dentry;
27133+
27134+ opq_dentry = au_diropq_create(dentry, bdst);
27135+ err = PTR_ERR(opq_dentry);
27136+ if (IS_ERR(opq_dentry))
27137+ goto out;
27138+ dput(opq_dentry);
27139+ au_fset_cpdown(a->flags, DIROPQ);
27140+
4f0767ce 27141+out:
1facf9fc 27142+ return err;
27143+}
27144+
27145+static int au_cpdown_dir_wh(struct dentry *dentry, struct dentry *h_parent,
27146+ struct inode *dir, aufs_bindex_t bdst)
27147+{
27148+ int err;
27149+ struct path h_path;
27150+ struct au_branch *br;
27151+
27152+ br = au_sbr(dentry->d_sb, bdst);
27153+ h_path.dentry = au_wh_lkup(h_parent, &dentry->d_name, br);
27154+ err = PTR_ERR(h_path.dentry);
27155+ if (IS_ERR(h_path.dentry))
27156+ goto out;
27157+
27158+ err = 0;
27159+ if (h_path.dentry->d_inode) {
27160+ h_path.mnt = br->br_mnt;
27161+ err = au_wh_unlink_dentry(au_h_iptr(dir, bdst), &h_path,
27162+ dentry);
27163+ }
27164+ dput(h_path.dentry);
27165+
4f0767ce 27166+out:
1facf9fc 27167+ return err;
27168+}
27169+
27170+static int au_cpdown_dir(struct dentry *dentry, aufs_bindex_t bdst,
27171+ struct dentry *h_parent, void *arg)
27172+{
27173+ int err, rerr;
4a4d8108 27174+ aufs_bindex_t bopq, bstart;
1facf9fc 27175+ struct path h_path;
27176+ struct dentry *parent;
27177+ struct inode *h_dir, *h_inode, *inode, *dir;
27178+ struct au_cpdown_dir_args *args = arg;
27179+
27180+ bstart = au_dbstart(dentry);
27181+ /* dentry is di-locked */
27182+ parent = dget_parent(dentry);
27183+ dir = parent->d_inode;
27184+ h_dir = h_parent->d_inode;
27185+ AuDebugOn(h_dir != au_h_iptr(dir, bdst));
27186+ IMustLock(h_dir);
27187+
27188+ err = au_lkup_neg(dentry, bdst);
27189+ if (unlikely(err < 0))
27190+ goto out;
27191+ h_path.dentry = au_h_dptr(dentry, bdst);
27192+ h_path.mnt = au_sbr_mnt(dentry->d_sb, bdst);
27193+ err = vfsub_sio_mkdir(au_h_iptr(dir, bdst), &h_path,
27194+ S_IRWXU | S_IRUGO | S_IXUGO);
27195+ if (unlikely(err))
27196+ goto out_put;
27197+ au_fset_cpdown(args->flags, MADE_DIR);
27198+
1facf9fc 27199+ bopq = au_dbdiropq(dentry);
27200+ au_fclr_cpdown(args->flags, WHED);
27201+ au_fclr_cpdown(args->flags, DIROPQ);
27202+ if (au_dbwh(dentry) == bdst)
27203+ au_fset_cpdown(args->flags, WHED);
27204+ if (!au_ftest_cpdown(args->flags, PARENT_OPQ) && bopq <= bdst)
27205+ au_fset_cpdown(args->flags, PARENT_OPQ);
1facf9fc 27206+ h_inode = h_path.dentry->d_inode;
27207+ mutex_lock_nested(&h_inode->i_mutex, AuLsc_I_CHILD);
27208+ if (au_ftest_cpdown(args->flags, WHED)) {
27209+ err = au_cpdown_dir_opq(dentry, bdst, args);
27210+ if (unlikely(err)) {
27211+ mutex_unlock(&h_inode->i_mutex);
27212+ goto out_dir;
27213+ }
27214+ }
27215+
27216+ err = au_cpdown_attr(&h_path, au_h_dptr(dentry, bstart));
27217+ mutex_unlock(&h_inode->i_mutex);
27218+ if (unlikely(err))
27219+ goto out_opq;
27220+
27221+ if (au_ftest_cpdown(args->flags, WHED)) {
27222+ err = au_cpdown_dir_wh(dentry, h_parent, dir, bdst);
27223+ if (unlikely(err))
27224+ goto out_opq;
27225+ }
27226+
27227+ inode = dentry->d_inode;
27228+ if (au_ibend(inode) < bdst)
27229+ au_set_ibend(inode, bdst);
27230+ au_set_h_iptr(inode, bdst, au_igrab(h_inode),
27231+ au_hi_flags(inode, /*isdir*/1));
27232+ goto out; /* success */
27233+
27234+ /* revert */
4f0767ce 27235+out_opq:
1facf9fc 27236+ if (au_ftest_cpdown(args->flags, DIROPQ)) {
27237+ mutex_lock_nested(&h_inode->i_mutex, AuLsc_I_CHILD);
27238+ rerr = au_diropq_remove(dentry, bdst);
27239+ mutex_unlock(&h_inode->i_mutex);
27240+ if (unlikely(rerr)) {
27241+ AuIOErr("failed removing diropq for %.*s b%d (%d)\n",
27242+ AuDLNPair(dentry), bdst, rerr);
27243+ err = -EIO;
27244+ goto out;
27245+ }
27246+ }
4f0767ce 27247+out_dir:
1facf9fc 27248+ if (au_ftest_cpdown(args->flags, MADE_DIR)) {
27249+ rerr = vfsub_sio_rmdir(au_h_iptr(dir, bdst), &h_path);
27250+ if (unlikely(rerr)) {
27251+ AuIOErr("failed removing %.*s b%d (%d)\n",
27252+ AuDLNPair(dentry), bdst, rerr);
27253+ err = -EIO;
27254+ }
27255+ }
4f0767ce 27256+out_put:
1facf9fc 27257+ au_set_h_dptr(dentry, bdst, NULL);
27258+ if (au_dbend(dentry) == bdst)
27259+ au_update_dbend(dentry);
4f0767ce 27260+out:
1facf9fc 27261+ dput(parent);
27262+ return err;
27263+}
27264+
27265+int au_cpdown_dirs(struct dentry *dentry, aufs_bindex_t bdst)
27266+{
27267+ int err;
27268+ struct au_cpdown_dir_args args = {
27269+ .parent = dget_parent(dentry),
27270+ .flags = 0
27271+ };
27272+
27273+ err = au_cp_dirs(dentry, bdst, au_cpdown_dir, &args);
27274+ dput(args.parent);
27275+
27276+ return err;
27277+}
27278+
27279+/* ---------------------------------------------------------------------- */
27280+
27281+/* policies for create */
27282+
4a4d8108
AM
27283+static int au_wbr_nonopq(struct dentry *dentry, aufs_bindex_t bindex)
27284+{
27285+ int err, i, j, ndentry;
27286+ aufs_bindex_t bopq;
27287+ struct au_dcsub_pages dpages;
27288+ struct au_dpage *dpage;
27289+ struct dentry **dentries, *parent, *d;
27290+
27291+ err = au_dpages_init(&dpages, GFP_NOFS);
27292+ if (unlikely(err))
27293+ goto out;
27294+ parent = dget_parent(dentry);
027c5e7a 27295+ err = au_dcsub_pages_rev_aufs(&dpages, parent, /*do_include*/0);
4a4d8108
AM
27296+ if (unlikely(err))
27297+ goto out_free;
27298+
27299+ err = bindex;
27300+ for (i = 0; i < dpages.ndpage; i++) {
27301+ dpage = dpages.dpages + i;
27302+ dentries = dpage->dentries;
27303+ ndentry = dpage->ndentry;
27304+ for (j = 0; j < ndentry; j++) {
27305+ d = dentries[j];
27306+ di_read_lock_parent2(d, !AuLock_IR);
27307+ bopq = au_dbdiropq(d);
27308+ di_read_unlock(d, !AuLock_IR);
27309+ if (bopq >= 0 && bopq < err)
27310+ err = bopq;
27311+ }
27312+ }
27313+
27314+out_free:
27315+ dput(parent);
27316+ au_dpages_free(&dpages);
27317+out:
27318+ return err;
27319+}
27320+
1facf9fc 27321+static int au_wbr_bu(struct super_block *sb, aufs_bindex_t bindex)
27322+{
27323+ for (; bindex >= 0; bindex--)
27324+ if (!au_br_rdonly(au_sbr(sb, bindex)))
27325+ return bindex;
27326+ return -EROFS;
27327+}
27328+
27329+/* top down parent */
27330+static int au_wbr_create_tdp(struct dentry *dentry, int isdir __maybe_unused)
27331+{
27332+ int err;
27333+ aufs_bindex_t bstart, bindex;
27334+ struct super_block *sb;
27335+ struct dentry *parent, *h_parent;
27336+
27337+ sb = dentry->d_sb;
27338+ bstart = au_dbstart(dentry);
27339+ err = bstart;
27340+ if (!au_br_rdonly(au_sbr(sb, bstart)))
27341+ goto out;
27342+
27343+ err = -EROFS;
27344+ parent = dget_parent(dentry);
27345+ for (bindex = au_dbstart(parent); bindex < bstart; bindex++) {
27346+ h_parent = au_h_dptr(parent, bindex);
27347+ if (!h_parent || !h_parent->d_inode)
27348+ continue;
27349+
27350+ if (!au_br_rdonly(au_sbr(sb, bindex))) {
27351+ err = bindex;
27352+ break;
27353+ }
27354+ }
27355+ dput(parent);
27356+
27357+ /* bottom up here */
4a4d8108 27358+ if (unlikely(err < 0)) {
1facf9fc 27359+ err = au_wbr_bu(sb, bstart - 1);
4a4d8108
AM
27360+ if (err >= 0)
27361+ err = au_wbr_nonopq(dentry, err);
27362+ }
1facf9fc 27363+
4f0767ce 27364+out:
1facf9fc 27365+ AuDbg("b%d\n", err);
27366+ return err;
27367+}
27368+
27369+/* ---------------------------------------------------------------------- */
27370+
27371+/* an exception for the policy other than tdp */
27372+static int au_wbr_create_exp(struct dentry *dentry)
27373+{
27374+ int err;
27375+ aufs_bindex_t bwh, bdiropq;
27376+ struct dentry *parent;
27377+
27378+ err = -1;
27379+ bwh = au_dbwh(dentry);
27380+ parent = dget_parent(dentry);
27381+ bdiropq = au_dbdiropq(parent);
27382+ if (bwh >= 0) {
27383+ if (bdiropq >= 0)
27384+ err = min(bdiropq, bwh);
27385+ else
27386+ err = bwh;
27387+ AuDbg("%d\n", err);
27388+ } else if (bdiropq >= 0) {
27389+ err = bdiropq;
27390+ AuDbg("%d\n", err);
27391+ }
27392+ dput(parent);
27393+
4a4d8108
AM
27394+ if (err >= 0)
27395+ err = au_wbr_nonopq(dentry, err);
27396+
1facf9fc 27397+ if (err >= 0 && au_br_rdonly(au_sbr(dentry->d_sb, err)))
27398+ err = -1;
27399+
27400+ AuDbg("%d\n", err);
27401+ return err;
27402+}
27403+
27404+/* ---------------------------------------------------------------------- */
27405+
27406+/* round robin */
27407+static int au_wbr_create_init_rr(struct super_block *sb)
27408+{
27409+ int err;
27410+
27411+ err = au_wbr_bu(sb, au_sbend(sb));
27412+ atomic_set(&au_sbi(sb)->si_wbr_rr_next, -err); /* less important */
dece6358 27413+ /* smp_mb(); */
1facf9fc 27414+
27415+ AuDbg("b%d\n", err);
27416+ return err;
27417+}
27418+
27419+static int au_wbr_create_rr(struct dentry *dentry, int isdir)
27420+{
27421+ int err, nbr;
27422+ unsigned int u;
27423+ aufs_bindex_t bindex, bend;
27424+ struct super_block *sb;
27425+ atomic_t *next;
27426+
27427+ err = au_wbr_create_exp(dentry);
27428+ if (err >= 0)
27429+ goto out;
27430+
27431+ sb = dentry->d_sb;
27432+ next = &au_sbi(sb)->si_wbr_rr_next;
27433+ bend = au_sbend(sb);
27434+ nbr = bend + 1;
27435+ for (bindex = 0; bindex <= bend; bindex++) {
27436+ if (!isdir) {
27437+ err = atomic_dec_return(next) + 1;
27438+ /* modulo for 0 is meaningless */
27439+ if (unlikely(!err))
27440+ err = atomic_dec_return(next) + 1;
27441+ } else
27442+ err = atomic_read(next);
27443+ AuDbg("%d\n", err);
27444+ u = err;
27445+ err = u % nbr;
27446+ AuDbg("%d\n", err);
27447+ if (!au_br_rdonly(au_sbr(sb, err)))
27448+ break;
27449+ err = -EROFS;
27450+ }
27451+
4a4d8108
AM
27452+ if (err >= 0)
27453+ err = au_wbr_nonopq(dentry, err);
27454+
4f0767ce 27455+out:
1facf9fc 27456+ AuDbg("%d\n", err);
27457+ return err;
27458+}
27459+
27460+/* ---------------------------------------------------------------------- */
27461+
27462+/* most free space */
27463+static void au_mfs(struct dentry *dentry)
27464+{
27465+ struct super_block *sb;
27466+ struct au_branch *br;
27467+ struct au_wbr_mfs *mfs;
27468+ aufs_bindex_t bindex, bend;
27469+ int err;
27470+ unsigned long long b, bavail;
7f207e10 27471+ struct path h_path;
1facf9fc 27472+ /* reduce the stack usage */
27473+ struct kstatfs *st;
27474+
27475+ st = kmalloc(sizeof(*st), GFP_NOFS);
27476+ if (unlikely(!st)) {
27477+ AuWarn1("failed updating mfs(%d), ignored\n", -ENOMEM);
27478+ return;
27479+ }
27480+
27481+ bavail = 0;
27482+ sb = dentry->d_sb;
27483+ mfs = &au_sbi(sb)->si_wbr_mfs;
dece6358 27484+ MtxMustLock(&mfs->mfs_lock);
1facf9fc 27485+ mfs->mfs_bindex = -EROFS;
27486+ mfs->mfsrr_bytes = 0;
27487+ bend = au_sbend(sb);
27488+ for (bindex = 0; bindex <= bend; bindex++) {
27489+ br = au_sbr(sb, bindex);
27490+ if (au_br_rdonly(br))
27491+ continue;
27492+
27493+ /* sb->s_root for NFS is unreliable */
7f207e10
AM
27494+ h_path.mnt = br->br_mnt;
27495+ h_path.dentry = h_path.mnt->mnt_root;
27496+ err = vfs_statfs(&h_path, st);
1facf9fc 27497+ if (unlikely(err)) {
27498+ AuWarn1("failed statfs, b%d, %d\n", bindex, err);
27499+ continue;
27500+ }
27501+
27502+ /* when the available size is equal, select the lower one */
27503+ BUILD_BUG_ON(sizeof(b) < sizeof(st->f_bavail)
27504+ || sizeof(b) < sizeof(st->f_bsize));
27505+ b = st->f_bavail * st->f_bsize;
27506+ br->br_wbr->wbr_bytes = b;
27507+ if (b >= bavail) {
27508+ bavail = b;
27509+ mfs->mfs_bindex = bindex;
27510+ mfs->mfs_jiffy = jiffies;
27511+ }
27512+ }
27513+
27514+ mfs->mfsrr_bytes = bavail;
27515+ AuDbg("b%d\n", mfs->mfs_bindex);
27516+ kfree(st);
27517+}
27518+
27519+static int au_wbr_create_mfs(struct dentry *dentry, int isdir __maybe_unused)
27520+{
27521+ int err;
27522+ struct super_block *sb;
27523+ struct au_wbr_mfs *mfs;
27524+
27525+ err = au_wbr_create_exp(dentry);
27526+ if (err >= 0)
27527+ goto out;
27528+
27529+ sb = dentry->d_sb;
27530+ mfs = &au_sbi(sb)->si_wbr_mfs;
27531+ mutex_lock(&mfs->mfs_lock);
27532+ if (time_after(jiffies, mfs->mfs_jiffy + mfs->mfs_expire)
27533+ || mfs->mfs_bindex < 0
27534+ || au_br_rdonly(au_sbr(sb, mfs->mfs_bindex)))
27535+ au_mfs(dentry);
27536+ mutex_unlock(&mfs->mfs_lock);
27537+ err = mfs->mfs_bindex;
27538+
4a4d8108
AM
27539+ if (err >= 0)
27540+ err = au_wbr_nonopq(dentry, err);
27541+
4f0767ce 27542+out:
1facf9fc 27543+ AuDbg("b%d\n", err);
27544+ return err;
27545+}
27546+
27547+static int au_wbr_create_init_mfs(struct super_block *sb)
27548+{
27549+ struct au_wbr_mfs *mfs;
27550+
27551+ mfs = &au_sbi(sb)->si_wbr_mfs;
27552+ mutex_init(&mfs->mfs_lock);
27553+ mfs->mfs_jiffy = 0;
27554+ mfs->mfs_bindex = -EROFS;
27555+
27556+ return 0;
27557+}
27558+
27559+static int au_wbr_create_fin_mfs(struct super_block *sb __maybe_unused)
27560+{
27561+ mutex_destroy(&au_sbi(sb)->si_wbr_mfs.mfs_lock);
27562+ return 0;
27563+}
27564+
27565+/* ---------------------------------------------------------------------- */
27566+
27567+/* most free space and then round robin */
27568+static int au_wbr_create_mfsrr(struct dentry *dentry, int isdir)
27569+{
27570+ int err;
27571+ struct au_wbr_mfs *mfs;
27572+
27573+ err = au_wbr_create_mfs(dentry, isdir);
27574+ if (err >= 0) {
27575+ mfs = &au_sbi(dentry->d_sb)->si_wbr_mfs;
dece6358 27576+ mutex_lock(&mfs->mfs_lock);
1facf9fc 27577+ if (mfs->mfsrr_bytes < mfs->mfsrr_watermark)
27578+ err = au_wbr_create_rr(dentry, isdir);
dece6358 27579+ mutex_unlock(&mfs->mfs_lock);
1facf9fc 27580+ }
27581+
27582+ AuDbg("b%d\n", err);
27583+ return err;
27584+}
27585+
27586+static int au_wbr_create_init_mfsrr(struct super_block *sb)
27587+{
27588+ int err;
27589+
27590+ au_wbr_create_init_mfs(sb); /* ignore */
27591+ err = au_wbr_create_init_rr(sb);
27592+
27593+ return err;
27594+}
27595+
27596+/* ---------------------------------------------------------------------- */
27597+
27598+/* top down parent and most free space */
27599+static int au_wbr_create_pmfs(struct dentry *dentry, int isdir)
27600+{
27601+ int err, e2;
27602+ unsigned long long b;
27603+ aufs_bindex_t bindex, bstart, bend;
27604+ struct super_block *sb;
27605+ struct dentry *parent, *h_parent;
27606+ struct au_branch *br;
27607+
27608+ err = au_wbr_create_tdp(dentry, isdir);
27609+ if (unlikely(err < 0))
27610+ goto out;
27611+ parent = dget_parent(dentry);
27612+ bstart = au_dbstart(parent);
27613+ bend = au_dbtaildir(parent);
27614+ if (bstart == bend)
27615+ goto out_parent; /* success */
27616+
27617+ e2 = au_wbr_create_mfs(dentry, isdir);
27618+ if (e2 < 0)
27619+ goto out_parent; /* success */
27620+
27621+ /* when the available size is equal, select upper one */
27622+ sb = dentry->d_sb;
27623+ br = au_sbr(sb, err);
27624+ b = br->br_wbr->wbr_bytes;
27625+ AuDbg("b%d, %llu\n", err, b);
27626+
27627+ for (bindex = bstart; bindex <= bend; bindex++) {
27628+ h_parent = au_h_dptr(parent, bindex);
27629+ if (!h_parent || !h_parent->d_inode)
27630+ continue;
27631+
27632+ br = au_sbr(sb, bindex);
27633+ if (!au_br_rdonly(br) && br->br_wbr->wbr_bytes > b) {
27634+ b = br->br_wbr->wbr_bytes;
27635+ err = bindex;
27636+ AuDbg("b%d, %llu\n", err, b);
27637+ }
27638+ }
27639+
4a4d8108
AM
27640+ if (err >= 0)
27641+ err = au_wbr_nonopq(dentry, err);
27642+
4f0767ce 27643+out_parent:
1facf9fc 27644+ dput(parent);
4f0767ce 27645+out:
1facf9fc 27646+ AuDbg("b%d\n", err);
27647+ return err;
27648+}
27649+
27650+/* ---------------------------------------------------------------------- */
27651+
27652+/* policies for copyup */
27653+
27654+/* top down parent */
27655+static int au_wbr_copyup_tdp(struct dentry *dentry)
27656+{
27657+ return au_wbr_create_tdp(dentry, /*isdir, anything is ok*/0);
27658+}
27659+
27660+/* bottom up parent */
27661+static int au_wbr_copyup_bup(struct dentry *dentry)
27662+{
27663+ int err;
27664+ aufs_bindex_t bindex, bstart;
27665+ struct dentry *parent, *h_parent;
27666+ struct super_block *sb;
27667+
27668+ err = -EROFS;
27669+ sb = dentry->d_sb;
27670+ parent = dget_parent(dentry);
27671+ bstart = au_dbstart(parent);
27672+ for (bindex = au_dbstart(dentry); bindex >= bstart; bindex--) {
27673+ h_parent = au_h_dptr(parent, bindex);
27674+ if (!h_parent || !h_parent->d_inode)
27675+ continue;
27676+
27677+ if (!au_br_rdonly(au_sbr(sb, bindex))) {
27678+ err = bindex;
27679+ break;
27680+ }
27681+ }
27682+ dput(parent);
27683+
27684+ /* bottom up here */
27685+ if (unlikely(err < 0))
27686+ err = au_wbr_bu(sb, bstart - 1);
27687+
27688+ AuDbg("b%d\n", err);
27689+ return err;
27690+}
27691+
27692+/* bottom up */
27693+static int au_wbr_copyup_bu(struct dentry *dentry)
27694+{
27695+ int err;
4a4d8108 27696+ aufs_bindex_t bstart;
1facf9fc 27697+
4a4d8108
AM
27698+ bstart = au_dbstart(dentry);
27699+ err = au_wbr_bu(dentry->d_sb, bstart);
27700+ AuDbg("b%d\n", err);
27701+ if (err > bstart)
27702+ err = au_wbr_nonopq(dentry, err);
1facf9fc 27703+
27704+ AuDbg("b%d\n", err);
27705+ return err;
27706+}
27707+
27708+/* ---------------------------------------------------------------------- */
27709+
27710+struct au_wbr_copyup_operations au_wbr_copyup_ops[] = {
27711+ [AuWbrCopyup_TDP] = {
27712+ .copyup = au_wbr_copyup_tdp
27713+ },
27714+ [AuWbrCopyup_BUP] = {
27715+ .copyup = au_wbr_copyup_bup
27716+ },
27717+ [AuWbrCopyup_BU] = {
27718+ .copyup = au_wbr_copyup_bu
27719+ }
27720+};
27721+
27722+struct au_wbr_create_operations au_wbr_create_ops[] = {
27723+ [AuWbrCreate_TDP] = {
27724+ .create = au_wbr_create_tdp
27725+ },
27726+ [AuWbrCreate_RR] = {
27727+ .create = au_wbr_create_rr,
27728+ .init = au_wbr_create_init_rr
27729+ },
27730+ [AuWbrCreate_MFS] = {
27731+ .create = au_wbr_create_mfs,
27732+ .init = au_wbr_create_init_mfs,
27733+ .fin = au_wbr_create_fin_mfs
27734+ },
27735+ [AuWbrCreate_MFSV] = {
27736+ .create = au_wbr_create_mfs,
27737+ .init = au_wbr_create_init_mfs,
27738+ .fin = au_wbr_create_fin_mfs
27739+ },
27740+ [AuWbrCreate_MFSRR] = {
27741+ .create = au_wbr_create_mfsrr,
27742+ .init = au_wbr_create_init_mfsrr,
27743+ .fin = au_wbr_create_fin_mfs
27744+ },
27745+ [AuWbrCreate_MFSRRV] = {
27746+ .create = au_wbr_create_mfsrr,
27747+ .init = au_wbr_create_init_mfsrr,
27748+ .fin = au_wbr_create_fin_mfs
27749+ },
27750+ [AuWbrCreate_PMFS] = {
27751+ .create = au_wbr_create_pmfs,
27752+ .init = au_wbr_create_init_mfs,
27753+ .fin = au_wbr_create_fin_mfs
27754+ },
27755+ [AuWbrCreate_PMFSV] = {
27756+ .create = au_wbr_create_pmfs,
27757+ .init = au_wbr_create_init_mfs,
27758+ .fin = au_wbr_create_fin_mfs
27759+ }
27760+};
7f207e10
AM
27761diff -urN /usr/share/empty/fs/aufs/whout.c linux/fs/aufs/whout.c
27762--- /usr/share/empty/fs/aufs/whout.c 1970-01-01 01:00:00.000000000 +0100
0c3ec466
AM
27763+++ linux/fs/aufs/whout.c 2012-07-22 19:57:03.167671344 +0200
27764@@ -0,0 +1,1041 @@
1facf9fc 27765+/*
f6c5ef8b 27766+ * Copyright (C) 2005-2012 Junjiro R. Okajima
1facf9fc 27767+ *
27768+ * This program, aufs is free software; you can redistribute it and/or modify
27769+ * it under the terms of the GNU General Public License as published by
27770+ * the Free Software Foundation; either version 2 of the License, or
27771+ * (at your option) any later version.
dece6358
AM
27772+ *
27773+ * This program is distributed in the hope that it will be useful,
27774+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
27775+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
27776+ * GNU General Public License for more details.
27777+ *
27778+ * You should have received a copy of the GNU General Public License
27779+ * along with this program; if not, write to the Free Software
27780+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 27781+ */
27782+
27783+/*
27784+ * whiteout for logical deletion and opaque directory
27785+ */
27786+
1facf9fc 27787+#include "aufs.h"
27788+
27789+#define WH_MASK S_IRUGO
27790+
27791+/*
27792+ * If a directory contains this file, then it is opaque. We start with the
27793+ * .wh. flag so that it is blocked by lookup.
27794+ */
0c3ec466
AM
27795+static struct qstr diropq_name = QSTR_INIT(AUFS_WH_DIROPQ,
27796+ sizeof(AUFS_WH_DIROPQ) - 1);
1facf9fc 27797+
27798+/*
27799+ * generate whiteout name, which is NOT terminated by NULL.
27800+ * @name: original d_name.name
27801+ * @len: original d_name.len
27802+ * @wh: whiteout qstr
27803+ * returns zero when succeeds, otherwise error.
27804+ * succeeded value as wh->name should be freed by kfree().
27805+ */
27806+int au_wh_name_alloc(struct qstr *wh, const struct qstr *name)
27807+{
27808+ char *p;
27809+
27810+ if (unlikely(name->len > PATH_MAX - AUFS_WH_PFX_LEN))
27811+ return -ENAMETOOLONG;
27812+
27813+ wh->len = name->len + AUFS_WH_PFX_LEN;
27814+ p = kmalloc(wh->len, GFP_NOFS);
27815+ wh->name = p;
27816+ if (p) {
27817+ memcpy(p, AUFS_WH_PFX, AUFS_WH_PFX_LEN);
27818+ memcpy(p + AUFS_WH_PFX_LEN, name->name, name->len);
27819+ /* smp_mb(); */
27820+ return 0;
27821+ }
27822+ return -ENOMEM;
27823+}
27824+
27825+/* ---------------------------------------------------------------------- */
27826+
27827+/*
27828+ * test if the @wh_name exists under @h_parent.
27829+ * @try_sio specifies the necessary of super-io.
27830+ */
27831+int au_wh_test(struct dentry *h_parent, struct qstr *wh_name,
27832+ struct au_branch *br, int try_sio)
27833+{
27834+ int err;
27835+ struct dentry *wh_dentry;
1facf9fc 27836+
1facf9fc 27837+ if (!try_sio)
27838+ wh_dentry = au_lkup_one(wh_name, h_parent, br, /*nd*/NULL);
27839+ else
27840+ wh_dentry = au_sio_lkup_one(wh_name, h_parent, br);
27841+ err = PTR_ERR(wh_dentry);
27842+ if (IS_ERR(wh_dentry))
27843+ goto out;
27844+
27845+ err = 0;
27846+ if (!wh_dentry->d_inode)
27847+ goto out_wh; /* success */
27848+
27849+ err = 1;
27850+ if (S_ISREG(wh_dentry->d_inode->i_mode))
27851+ goto out_wh; /* success */
27852+
27853+ err = -EIO;
27854+ AuIOErr("%.*s Invalid whiteout entry type 0%o.\n",
27855+ AuDLNPair(wh_dentry), wh_dentry->d_inode->i_mode);
27856+
4f0767ce 27857+out_wh:
1facf9fc 27858+ dput(wh_dentry);
4f0767ce 27859+out:
1facf9fc 27860+ return err;
27861+}
27862+
27863+/*
27864+ * test if the @h_dentry sets opaque or not.
27865+ */
27866+int au_diropq_test(struct dentry *h_dentry, struct au_branch *br)
27867+{
27868+ int err;
27869+ struct inode *h_dir;
27870+
27871+ h_dir = h_dentry->d_inode;
27872+ err = au_wh_test(h_dentry, &diropq_name, br,
27873+ au_test_h_perm_sio(h_dir, MAY_EXEC));
27874+ return err;
27875+}
27876+
27877+/*
27878+ * returns a negative dentry whose name is unique and temporary.
27879+ */
27880+struct dentry *au_whtmp_lkup(struct dentry *h_parent, struct au_branch *br,
27881+ struct qstr *prefix)
27882+{
1facf9fc 27883+ struct dentry *dentry;
27884+ int i;
027c5e7a 27885+ char defname[NAME_MAX - AUFS_MAX_NAMELEN + DNAME_INLINE_LEN + 1],
4a4d8108 27886+ *name, *p;
027c5e7a 27887+ /* strict atomic_t is unnecessary here */
1facf9fc 27888+ static unsigned short cnt;
27889+ struct qstr qs;
27890+
4a4d8108
AM
27891+ BUILD_BUG_ON(sizeof(cnt) * 2 > AUFS_WH_TMP_LEN);
27892+
1facf9fc 27893+ name = defname;
027c5e7a
AM
27894+ qs.len = sizeof(defname) - DNAME_INLINE_LEN + prefix->len - 1;
27895+ if (unlikely(prefix->len > DNAME_INLINE_LEN)) {
1facf9fc 27896+ dentry = ERR_PTR(-ENAMETOOLONG);
4a4d8108 27897+ if (unlikely(qs.len > NAME_MAX))
1facf9fc 27898+ goto out;
27899+ dentry = ERR_PTR(-ENOMEM);
27900+ name = kmalloc(qs.len + 1, GFP_NOFS);
27901+ if (unlikely(!name))
27902+ goto out;
27903+ }
27904+
27905+ /* doubly whiteout-ed */
27906+ memcpy(name, AUFS_WH_PFX AUFS_WH_PFX, AUFS_WH_PFX_LEN * 2);
27907+ p = name + AUFS_WH_PFX_LEN * 2;
27908+ memcpy(p, prefix->name, prefix->len);
27909+ p += prefix->len;
27910+ *p++ = '.';
4a4d8108 27911+ AuDebugOn(name + qs.len + 1 - p <= AUFS_WH_TMP_LEN);
1facf9fc 27912+
27913+ qs.name = name;
27914+ for (i = 0; i < 3; i++) {
b752ccd1 27915+ sprintf(p, "%.*x", AUFS_WH_TMP_LEN, cnt++);
1facf9fc 27916+ dentry = au_sio_lkup_one(&qs, h_parent, br);
27917+ if (IS_ERR(dentry) || !dentry->d_inode)
27918+ goto out_name;
27919+ dput(dentry);
27920+ }
0c3ec466 27921+ /* pr_warn("could not get random name\n"); */
1facf9fc 27922+ dentry = ERR_PTR(-EEXIST);
27923+ AuDbg("%.*s\n", AuLNPair(&qs));
27924+ BUG();
27925+
4f0767ce 27926+out_name:
1facf9fc 27927+ if (name != defname)
27928+ kfree(name);
4f0767ce 27929+out:
4a4d8108 27930+ AuTraceErrPtr(dentry);
1facf9fc 27931+ return dentry;
1facf9fc 27932+}
27933+
27934+/*
27935+ * rename the @h_dentry on @br to the whiteouted temporary name.
27936+ */
27937+int au_whtmp_ren(struct dentry *h_dentry, struct au_branch *br)
27938+{
27939+ int err;
27940+ struct path h_path = {
27941+ .mnt = br->br_mnt
27942+ };
27943+ struct inode *h_dir;
27944+ struct dentry *h_parent;
27945+
27946+ h_parent = h_dentry->d_parent; /* dir inode is locked */
27947+ h_dir = h_parent->d_inode;
27948+ IMustLock(h_dir);
27949+
27950+ h_path.dentry = au_whtmp_lkup(h_parent, br, &h_dentry->d_name);
27951+ err = PTR_ERR(h_path.dentry);
27952+ if (IS_ERR(h_path.dentry))
27953+ goto out;
27954+
27955+ /* under the same dir, no need to lock_rename() */
27956+ err = vfsub_rename(h_dir, h_dentry, h_dir, &h_path);
27957+ AuTraceErr(err);
27958+ dput(h_path.dentry);
27959+
4f0767ce 27960+out:
4a4d8108 27961+ AuTraceErr(err);
1facf9fc 27962+ return err;
27963+}
27964+
27965+/* ---------------------------------------------------------------------- */
27966+/*
27967+ * functions for removing a whiteout
27968+ */
27969+
27970+static int do_unlink_wh(struct inode *h_dir, struct path *h_path)
27971+{
27972+ int force;
27973+
27974+ /*
27975+ * forces superio when the dir has a sticky bit.
27976+ * this may be a violation of unix fs semantics.
27977+ */
27978+ force = (h_dir->i_mode & S_ISVTX)
0c3ec466 27979+ && !uid_eq(current_fsuid(), h_path->dentry->d_inode->i_uid);
1facf9fc 27980+ return vfsub_unlink(h_dir, h_path, force);
27981+}
27982+
27983+int au_wh_unlink_dentry(struct inode *h_dir, struct path *h_path,
27984+ struct dentry *dentry)
27985+{
27986+ int err;
27987+
27988+ err = do_unlink_wh(h_dir, h_path);
27989+ if (!err && dentry)
27990+ au_set_dbwh(dentry, -1);
27991+
27992+ return err;
27993+}
27994+
27995+static int unlink_wh_name(struct dentry *h_parent, struct qstr *wh,
27996+ struct au_branch *br)
27997+{
27998+ int err;
27999+ struct path h_path = {
28000+ .mnt = br->br_mnt
28001+ };
28002+
28003+ err = 0;
28004+ h_path.dentry = au_lkup_one(wh, h_parent, br, /*nd*/NULL);
28005+ if (IS_ERR(h_path.dentry))
28006+ err = PTR_ERR(h_path.dentry);
28007+ else {
28008+ if (h_path.dentry->d_inode
28009+ && S_ISREG(h_path.dentry->d_inode->i_mode))
28010+ err = do_unlink_wh(h_parent->d_inode, &h_path);
28011+ dput(h_path.dentry);
28012+ }
28013+
28014+ return err;
28015+}
28016+
28017+/* ---------------------------------------------------------------------- */
28018+/*
28019+ * initialize/clean whiteout for a branch
28020+ */
28021+
28022+static void au_wh_clean(struct inode *h_dir, struct path *whpath,
28023+ const int isdir)
28024+{
28025+ int err;
28026+
28027+ if (!whpath->dentry->d_inode)
28028+ return;
28029+
28030+ err = mnt_want_write(whpath->mnt);
28031+ if (!err) {
28032+ if (isdir)
28033+ err = vfsub_rmdir(h_dir, whpath);
28034+ else
28035+ err = vfsub_unlink(h_dir, whpath, /*force*/0);
28036+ mnt_drop_write(whpath->mnt);
28037+ }
28038+ if (unlikely(err))
0c3ec466
AM
28039+ pr_warn("failed removing %.*s (%d), ignored.\n",
28040+ AuDLNPair(whpath->dentry), err);
1facf9fc 28041+}
28042+
28043+static int test_linkable(struct dentry *h_root)
28044+{
28045+ struct inode *h_dir = h_root->d_inode;
28046+
28047+ if (h_dir->i_op->link)
28048+ return 0;
28049+
4a4d8108
AM
28050+ pr_err("%.*s (%s) doesn't support link(2), use noplink and rw+nolwh\n",
28051+ AuDLNPair(h_root), au_sbtype(h_root->d_sb));
1facf9fc 28052+ return -ENOSYS;
28053+}
28054+
28055+/* todo: should this mkdir be done in /sbin/mount.aufs helper? */
28056+static int au_whdir(struct inode *h_dir, struct path *path)
28057+{
28058+ int err;
28059+
28060+ err = -EEXIST;
28061+ if (!path->dentry->d_inode) {
28062+ int mode = S_IRWXU;
28063+
28064+ if (au_test_nfs(path->dentry->d_sb))
28065+ mode |= S_IXUGO;
28066+ err = mnt_want_write(path->mnt);
28067+ if (!err) {
28068+ err = vfsub_mkdir(h_dir, path, mode);
28069+ mnt_drop_write(path->mnt);
28070+ }
28071+ } else if (S_ISDIR(path->dentry->d_inode->i_mode))
28072+ err = 0;
28073+ else
4a4d8108 28074+ pr_err("unknown %.*s exists\n", AuDLNPair(path->dentry));
1facf9fc 28075+
28076+ return err;
28077+}
28078+
28079+struct au_wh_base {
28080+ const struct qstr *name;
28081+ struct dentry *dentry;
28082+};
28083+
28084+static void au_wh_init_ro(struct inode *h_dir, struct au_wh_base base[],
28085+ struct path *h_path)
28086+{
28087+ h_path->dentry = base[AuBrWh_BASE].dentry;
28088+ au_wh_clean(h_dir, h_path, /*isdir*/0);
28089+ h_path->dentry = base[AuBrWh_PLINK].dentry;
28090+ au_wh_clean(h_dir, h_path, /*isdir*/1);
28091+ h_path->dentry = base[AuBrWh_ORPH].dentry;
28092+ au_wh_clean(h_dir, h_path, /*isdir*/1);
28093+}
28094+
28095+/*
28096+ * returns tri-state,
28097+ * minus: error, caller should print the mesage
28098+ * zero: succuess
28099+ * plus: error, caller should NOT print the mesage
28100+ */
28101+static int au_wh_init_rw_nolink(struct dentry *h_root, struct au_wbr *wbr,
28102+ int do_plink, struct au_wh_base base[],
28103+ struct path *h_path)
28104+{
28105+ int err;
28106+ struct inode *h_dir;
28107+
28108+ h_dir = h_root->d_inode;
28109+ h_path->dentry = base[AuBrWh_BASE].dentry;
28110+ au_wh_clean(h_dir, h_path, /*isdir*/0);
28111+ h_path->dentry = base[AuBrWh_PLINK].dentry;
28112+ if (do_plink) {
28113+ err = test_linkable(h_root);
28114+ if (unlikely(err)) {
28115+ err = 1;
28116+ goto out;
28117+ }
28118+
28119+ err = au_whdir(h_dir, h_path);
28120+ if (unlikely(err))
28121+ goto out;
28122+ wbr->wbr_plink = dget(base[AuBrWh_PLINK].dentry);
28123+ } else
28124+ au_wh_clean(h_dir, h_path, /*isdir*/1);
28125+ h_path->dentry = base[AuBrWh_ORPH].dentry;
28126+ err = au_whdir(h_dir, h_path);
28127+ if (unlikely(err))
28128+ goto out;
28129+ wbr->wbr_orph = dget(base[AuBrWh_ORPH].dentry);
28130+
4f0767ce 28131+out:
1facf9fc 28132+ return err;
28133+}
28134+
28135+/*
28136+ * for the moment, aufs supports the branch filesystem which does not support
28137+ * link(2). testing on FAT which does not support i_op->setattr() fully either,
28138+ * copyup failed. finally, such filesystem will not be used as the writable
28139+ * branch.
28140+ *
28141+ * returns tri-state, see above.
28142+ */
28143+static int au_wh_init_rw(struct dentry *h_root, struct au_wbr *wbr,
28144+ int do_plink, struct au_wh_base base[],
28145+ struct path *h_path)
28146+{
28147+ int err;
28148+ struct inode *h_dir;
28149+
1308ab2a 28150+ WbrWhMustWriteLock(wbr);
28151+
1facf9fc 28152+ err = test_linkable(h_root);
28153+ if (unlikely(err)) {
28154+ err = 1;
28155+ goto out;
28156+ }
28157+
28158+ /*
28159+ * todo: should this create be done in /sbin/mount.aufs helper?
28160+ */
28161+ err = -EEXIST;
28162+ h_dir = h_root->d_inode;
28163+ if (!base[AuBrWh_BASE].dentry->d_inode) {
28164+ err = mnt_want_write(h_path->mnt);
28165+ if (!err) {
28166+ h_path->dentry = base[AuBrWh_BASE].dentry;
28167+ err = vfsub_create(h_dir, h_path, WH_MASK);
28168+ mnt_drop_write(h_path->mnt);
28169+ }
28170+ } else if (S_ISREG(base[AuBrWh_BASE].dentry->d_inode->i_mode))
28171+ err = 0;
28172+ else
4a4d8108
AM
28173+ pr_err("unknown %.*s/%.*s exists\n",
28174+ AuDLNPair(h_root), AuDLNPair(base[AuBrWh_BASE].dentry));
1facf9fc 28175+ if (unlikely(err))
28176+ goto out;
28177+
28178+ h_path->dentry = base[AuBrWh_PLINK].dentry;
28179+ if (do_plink) {
28180+ err = au_whdir(h_dir, h_path);
28181+ if (unlikely(err))
28182+ goto out;
28183+ wbr->wbr_plink = dget(base[AuBrWh_PLINK].dentry);
28184+ } else
28185+ au_wh_clean(h_dir, h_path, /*isdir*/1);
28186+ wbr->wbr_whbase = dget(base[AuBrWh_BASE].dentry);
28187+
28188+ h_path->dentry = base[AuBrWh_ORPH].dentry;
28189+ err = au_whdir(h_dir, h_path);
28190+ if (unlikely(err))
28191+ goto out;
28192+ wbr->wbr_orph = dget(base[AuBrWh_ORPH].dentry);
28193+
4f0767ce 28194+out:
1facf9fc 28195+ return err;
28196+}
28197+
28198+/*
28199+ * initialize the whiteout base file/dir for @br.
28200+ */
28201+int au_wh_init(struct dentry *h_root, struct au_branch *br,
28202+ struct super_block *sb)
28203+{
28204+ int err, i;
28205+ const unsigned char do_plink
28206+ = !!au_opt_test(au_mntflags(sb), PLINK);
28207+ struct path path = {
28208+ .mnt = br->br_mnt
28209+ };
28210+ struct inode *h_dir;
28211+ struct au_wbr *wbr = br->br_wbr;
28212+ static const struct qstr base_name[] = {
0c3ec466
AM
28213+ [AuBrWh_BASE] = QSTR_INIT(AUFS_BASE_NAME,
28214+ sizeof(AUFS_BASE_NAME) - 1),
28215+ [AuBrWh_PLINK] = QSTR_INIT(AUFS_PLINKDIR_NAME,
28216+ sizeof(AUFS_PLINKDIR_NAME) - 1),
28217+ [AuBrWh_ORPH] = QSTR_INIT(AUFS_ORPHDIR_NAME,
28218+ sizeof(AUFS_ORPHDIR_NAME) - 1)
1facf9fc 28219+ };
28220+ struct au_wh_base base[] = {
28221+ [AuBrWh_BASE] = {
28222+ .name = base_name + AuBrWh_BASE,
28223+ .dentry = NULL
28224+ },
28225+ [AuBrWh_PLINK] = {
28226+ .name = base_name + AuBrWh_PLINK,
28227+ .dentry = NULL
28228+ },
28229+ [AuBrWh_ORPH] = {
28230+ .name = base_name + AuBrWh_ORPH,
28231+ .dentry = NULL
28232+ }
28233+ };
28234+
1308ab2a 28235+ if (wbr)
28236+ WbrWhMustWriteLock(wbr);
1facf9fc 28237+
1facf9fc 28238+ for (i = 0; i < AuBrWh_Last; i++) {
28239+ /* doubly whiteouted */
28240+ struct dentry *d;
28241+
28242+ d = au_wh_lkup(h_root, (void *)base[i].name, br);
28243+ err = PTR_ERR(d);
28244+ if (IS_ERR(d))
28245+ goto out;
28246+
28247+ base[i].dentry = d;
28248+ AuDebugOn(wbr
28249+ && wbr->wbr_wh[i]
28250+ && wbr->wbr_wh[i] != base[i].dentry);
28251+ }
28252+
28253+ if (wbr)
28254+ for (i = 0; i < AuBrWh_Last; i++) {
28255+ dput(wbr->wbr_wh[i]);
28256+ wbr->wbr_wh[i] = NULL;
28257+ }
28258+
28259+ err = 0;
1e00d052 28260+ if (!au_br_writable(br->br_perm)) {
4a4d8108 28261+ h_dir = h_root->d_inode;
1facf9fc 28262+ au_wh_init_ro(h_dir, base, &path);
1e00d052 28263+ } else if (!au_br_wh_linkable(br->br_perm)) {
1facf9fc 28264+ err = au_wh_init_rw_nolink(h_root, wbr, do_plink, base, &path);
28265+ if (err > 0)
28266+ goto out;
28267+ else if (err)
28268+ goto out_err;
1e00d052 28269+ } else {
1facf9fc 28270+ err = au_wh_init_rw(h_root, wbr, do_plink, base, &path);
28271+ if (err > 0)
28272+ goto out;
28273+ else if (err)
28274+ goto out_err;
1facf9fc 28275+ }
28276+ goto out; /* success */
28277+
4f0767ce 28278+out_err:
4a4d8108
AM
28279+ pr_err("an error(%d) on the writable branch %.*s(%s)\n",
28280+ err, AuDLNPair(h_root), au_sbtype(h_root->d_sb));
4f0767ce 28281+out:
1facf9fc 28282+ for (i = 0; i < AuBrWh_Last; i++)
28283+ dput(base[i].dentry);
28284+ return err;
28285+}
28286+
28287+/* ---------------------------------------------------------------------- */
28288+/*
28289+ * whiteouts are all hard-linked usually.
28290+ * when its link count reaches a ceiling, we create a new whiteout base
28291+ * asynchronously.
28292+ */
28293+
28294+struct reinit_br_wh {
28295+ struct super_block *sb;
28296+ struct au_branch *br;
28297+};
28298+
28299+static void reinit_br_wh(void *arg)
28300+{
28301+ int err;
28302+ aufs_bindex_t bindex;
28303+ struct path h_path;
28304+ struct reinit_br_wh *a = arg;
28305+ struct au_wbr *wbr;
28306+ struct inode *dir;
28307+ struct dentry *h_root;
28308+ struct au_hinode *hdir;
28309+
28310+ err = 0;
28311+ wbr = a->br->br_wbr;
28312+ /* big aufs lock */
28313+ si_noflush_write_lock(a->sb);
28314+ if (!au_br_writable(a->br->br_perm))
28315+ goto out;
28316+ bindex = au_br_index(a->sb, a->br->br_id);
28317+ if (unlikely(bindex < 0))
28318+ goto out;
28319+
1308ab2a 28320+ di_read_lock_parent(a->sb->s_root, AuLock_IR);
1facf9fc 28321+ dir = a->sb->s_root->d_inode;
1facf9fc 28322+ hdir = au_hi(dir, bindex);
28323+ h_root = au_h_dptr(a->sb->s_root, bindex);
28324+
4a4d8108 28325+ au_hn_imtx_lock_nested(hdir, AuLsc_I_PARENT);
1facf9fc 28326+ wbr_wh_write_lock(wbr);
28327+ err = au_h_verify(wbr->wbr_whbase, au_opt_udba(a->sb), hdir->hi_inode,
28328+ h_root, a->br);
28329+ if (!err) {
28330+ err = mnt_want_write(a->br->br_mnt);
28331+ if (!err) {
28332+ h_path.dentry = wbr->wbr_whbase;
28333+ h_path.mnt = a->br->br_mnt;
28334+ err = vfsub_unlink(hdir->hi_inode, &h_path, /*force*/0);
28335+ mnt_drop_write(a->br->br_mnt);
28336+ }
28337+ } else {
0c3ec466
AM
28338+ pr_warn("%.*s is moved, ignored\n",
28339+ AuDLNPair(wbr->wbr_whbase));
1facf9fc 28340+ err = 0;
28341+ }
28342+ dput(wbr->wbr_whbase);
28343+ wbr->wbr_whbase = NULL;
28344+ if (!err)
28345+ err = au_wh_init(h_root, a->br, a->sb);
28346+ wbr_wh_write_unlock(wbr);
4a4d8108 28347+ au_hn_imtx_unlock(hdir);
1308ab2a 28348+ di_read_unlock(a->sb->s_root, AuLock_IR);
1facf9fc 28349+
4f0767ce 28350+out:
1facf9fc 28351+ if (wbr)
28352+ atomic_dec(&wbr->wbr_wh_running);
28353+ atomic_dec(&a->br->br_count);
1facf9fc 28354+ si_write_unlock(a->sb);
027c5e7a 28355+ au_nwt_done(&au_sbi(a->sb)->si_nowait);
1facf9fc 28356+ kfree(arg);
28357+ if (unlikely(err))
28358+ AuIOErr("err %d\n", err);
28359+}
28360+
28361+static void kick_reinit_br_wh(struct super_block *sb, struct au_branch *br)
28362+{
28363+ int do_dec, wkq_err;
28364+ struct reinit_br_wh *arg;
28365+
28366+ do_dec = 1;
28367+ if (atomic_inc_return(&br->br_wbr->wbr_wh_running) != 1)
28368+ goto out;
28369+
28370+ /* ignore ENOMEM */
28371+ arg = kmalloc(sizeof(*arg), GFP_NOFS);
28372+ if (arg) {
28373+ /*
28374+ * dec(wh_running), kfree(arg) and dec(br_count)
28375+ * in reinit function
28376+ */
28377+ arg->sb = sb;
28378+ arg->br = br;
28379+ atomic_inc(&br->br_count);
53392da6 28380+ wkq_err = au_wkq_nowait(reinit_br_wh, arg, sb, /*flags*/0);
1facf9fc 28381+ if (unlikely(wkq_err)) {
28382+ atomic_dec(&br->br_wbr->wbr_wh_running);
28383+ atomic_dec(&br->br_count);
28384+ kfree(arg);
28385+ }
28386+ do_dec = 0;
28387+ }
28388+
4f0767ce 28389+out:
1facf9fc 28390+ if (do_dec)
28391+ atomic_dec(&br->br_wbr->wbr_wh_running);
28392+}
28393+
28394+/* ---------------------------------------------------------------------- */
28395+
28396+/*
28397+ * create the whiteout @wh.
28398+ */
28399+static int link_or_create_wh(struct super_block *sb, aufs_bindex_t bindex,
28400+ struct dentry *wh)
28401+{
28402+ int err;
28403+ struct path h_path = {
28404+ .dentry = wh
28405+ };
28406+ struct au_branch *br;
28407+ struct au_wbr *wbr;
28408+ struct dentry *h_parent;
28409+ struct inode *h_dir;
28410+
28411+ h_parent = wh->d_parent; /* dir inode is locked */
28412+ h_dir = h_parent->d_inode;
28413+ IMustLock(h_dir);
28414+
28415+ br = au_sbr(sb, bindex);
28416+ h_path.mnt = br->br_mnt;
28417+ wbr = br->br_wbr;
28418+ wbr_wh_read_lock(wbr);
28419+ if (wbr->wbr_whbase) {
28420+ err = vfsub_link(wbr->wbr_whbase, h_dir, &h_path);
28421+ if (!err || err != -EMLINK)
28422+ goto out;
28423+
28424+ /* link count full. re-initialize br_whbase. */
28425+ kick_reinit_br_wh(sb, br);
28426+ }
28427+
28428+ /* return this error in this context */
28429+ err = vfsub_create(h_dir, &h_path, WH_MASK);
28430+
4f0767ce 28431+out:
1facf9fc 28432+ wbr_wh_read_unlock(wbr);
28433+ return err;
28434+}
28435+
28436+/* ---------------------------------------------------------------------- */
28437+
28438+/*
28439+ * create or remove the diropq.
28440+ */
28441+static struct dentry *do_diropq(struct dentry *dentry, aufs_bindex_t bindex,
28442+ unsigned int flags)
28443+{
28444+ struct dentry *opq_dentry, *h_dentry;
28445+ struct super_block *sb;
28446+ struct au_branch *br;
28447+ int err;
28448+
28449+ sb = dentry->d_sb;
28450+ br = au_sbr(sb, bindex);
28451+ h_dentry = au_h_dptr(dentry, bindex);
28452+ opq_dentry = au_lkup_one(&diropq_name, h_dentry, br, /*nd*/NULL);
28453+ if (IS_ERR(opq_dentry))
28454+ goto out;
28455+
28456+ if (au_ftest_diropq(flags, CREATE)) {
28457+ err = link_or_create_wh(sb, bindex, opq_dentry);
28458+ if (!err) {
28459+ au_set_dbdiropq(dentry, bindex);
28460+ goto out; /* success */
28461+ }
28462+ } else {
28463+ struct path tmp = {
28464+ .dentry = opq_dentry,
28465+ .mnt = br->br_mnt
28466+ };
28467+ err = do_unlink_wh(au_h_iptr(dentry->d_inode, bindex), &tmp);
28468+ if (!err)
28469+ au_set_dbdiropq(dentry, -1);
28470+ }
28471+ dput(opq_dentry);
28472+ opq_dentry = ERR_PTR(err);
28473+
4f0767ce 28474+out:
1facf9fc 28475+ return opq_dentry;
28476+}
28477+
28478+struct do_diropq_args {
28479+ struct dentry **errp;
28480+ struct dentry *dentry;
28481+ aufs_bindex_t bindex;
28482+ unsigned int flags;
28483+};
28484+
28485+static void call_do_diropq(void *args)
28486+{
28487+ struct do_diropq_args *a = args;
28488+ *a->errp = do_diropq(a->dentry, a->bindex, a->flags);
28489+}
28490+
28491+struct dentry *au_diropq_sio(struct dentry *dentry, aufs_bindex_t bindex,
28492+ unsigned int flags)
28493+{
28494+ struct dentry *diropq, *h_dentry;
28495+
28496+ h_dentry = au_h_dptr(dentry, bindex);
28497+ if (!au_test_h_perm_sio(h_dentry->d_inode, MAY_EXEC | MAY_WRITE))
28498+ diropq = do_diropq(dentry, bindex, flags);
28499+ else {
28500+ int wkq_err;
28501+ struct do_diropq_args args = {
28502+ .errp = &diropq,
28503+ .dentry = dentry,
28504+ .bindex = bindex,
28505+ .flags = flags
28506+ };
28507+
28508+ wkq_err = au_wkq_wait(call_do_diropq, &args);
28509+ if (unlikely(wkq_err))
28510+ diropq = ERR_PTR(wkq_err);
28511+ }
28512+
28513+ return diropq;
28514+}
28515+
28516+/* ---------------------------------------------------------------------- */
28517+
28518+/*
28519+ * lookup whiteout dentry.
28520+ * @h_parent: lower parent dentry which must exist and be locked
28521+ * @base_name: name of dentry which will be whiteouted
28522+ * returns dentry for whiteout.
28523+ */
28524+struct dentry *au_wh_lkup(struct dentry *h_parent, struct qstr *base_name,
28525+ struct au_branch *br)
28526+{
28527+ int err;
28528+ struct qstr wh_name;
28529+ struct dentry *wh_dentry;
28530+
28531+ err = au_wh_name_alloc(&wh_name, base_name);
28532+ wh_dentry = ERR_PTR(err);
28533+ if (!err) {
28534+ wh_dentry = au_lkup_one(&wh_name, h_parent, br, /*nd*/NULL);
28535+ kfree(wh_name.name);
28536+ }
28537+ return wh_dentry;
28538+}
28539+
28540+/*
28541+ * link/create a whiteout for @dentry on @bindex.
28542+ */
28543+struct dentry *au_wh_create(struct dentry *dentry, aufs_bindex_t bindex,
28544+ struct dentry *h_parent)
28545+{
28546+ struct dentry *wh_dentry;
28547+ struct super_block *sb;
28548+ int err;
28549+
28550+ sb = dentry->d_sb;
28551+ wh_dentry = au_wh_lkup(h_parent, &dentry->d_name, au_sbr(sb, bindex));
28552+ if (!IS_ERR(wh_dentry) && !wh_dentry->d_inode) {
28553+ err = link_or_create_wh(sb, bindex, wh_dentry);
28554+ if (!err)
28555+ au_set_dbwh(dentry, bindex);
28556+ else {
28557+ dput(wh_dentry);
28558+ wh_dentry = ERR_PTR(err);
28559+ }
28560+ }
28561+
28562+ return wh_dentry;
28563+}
28564+
28565+/* ---------------------------------------------------------------------- */
28566+
28567+/* Delete all whiteouts in this directory on branch bindex. */
28568+static int del_wh_children(struct dentry *h_dentry, struct au_nhash *whlist,
28569+ aufs_bindex_t bindex, struct au_branch *br)
28570+{
28571+ int err;
28572+ unsigned long ul, n;
28573+ struct qstr wh_name;
28574+ char *p;
28575+ struct hlist_head *head;
28576+ struct au_vdir_wh *tpos;
28577+ struct hlist_node *pos;
28578+ struct au_vdir_destr *str;
28579+
28580+ err = -ENOMEM;
4a4d8108 28581+ p = __getname_gfp(GFP_NOFS);
1facf9fc 28582+ wh_name.name = p;
28583+ if (unlikely(!wh_name.name))
28584+ goto out;
28585+
28586+ err = 0;
28587+ memcpy(p, AUFS_WH_PFX, AUFS_WH_PFX_LEN);
28588+ p += AUFS_WH_PFX_LEN;
28589+ n = whlist->nh_num;
28590+ head = whlist->nh_head;
28591+ for (ul = 0; !err && ul < n; ul++, head++) {
28592+ hlist_for_each_entry(tpos, pos, head, wh_hash) {
28593+ if (tpos->wh_bindex != bindex)
28594+ continue;
28595+
28596+ str = &tpos->wh_str;
28597+ if (str->len + AUFS_WH_PFX_LEN <= PATH_MAX) {
28598+ memcpy(p, str->name, str->len);
28599+ wh_name.len = AUFS_WH_PFX_LEN + str->len;
28600+ err = unlink_wh_name(h_dentry, &wh_name, br);
28601+ if (!err)
28602+ continue;
28603+ break;
28604+ }
28605+ AuIOErr("whiteout name too long %.*s\n",
28606+ str->len, str->name);
28607+ err = -EIO;
28608+ break;
28609+ }
28610+ }
28611+ __putname(wh_name.name);
28612+
4f0767ce 28613+out:
1facf9fc 28614+ return err;
28615+}
28616+
28617+struct del_wh_children_args {
28618+ int *errp;
28619+ struct dentry *h_dentry;
1308ab2a 28620+ struct au_nhash *whlist;
1facf9fc 28621+ aufs_bindex_t bindex;
28622+ struct au_branch *br;
28623+};
28624+
28625+static void call_del_wh_children(void *args)
28626+{
28627+ struct del_wh_children_args *a = args;
1308ab2a 28628+ *a->errp = del_wh_children(a->h_dentry, a->whlist, a->bindex, a->br);
1facf9fc 28629+}
28630+
28631+/* ---------------------------------------------------------------------- */
28632+
28633+struct au_whtmp_rmdir *au_whtmp_rmdir_alloc(struct super_block *sb, gfp_t gfp)
28634+{
28635+ struct au_whtmp_rmdir *whtmp;
dece6358 28636+ int err;
1308ab2a 28637+ unsigned int rdhash;
dece6358
AM
28638+
28639+ SiMustAnyLock(sb);
1facf9fc 28640+
28641+ whtmp = kmalloc(sizeof(*whtmp), gfp);
dece6358
AM
28642+ if (unlikely(!whtmp)) {
28643+ whtmp = ERR_PTR(-ENOMEM);
1facf9fc 28644+ goto out;
dece6358 28645+ }
1facf9fc 28646+
28647+ whtmp->dir = NULL;
027c5e7a 28648+ whtmp->br = NULL;
1facf9fc 28649+ whtmp->wh_dentry = NULL;
1308ab2a 28650+ /* no estimation for dir size */
28651+ rdhash = au_sbi(sb)->si_rdhash;
28652+ if (!rdhash)
28653+ rdhash = AUFS_RDHASH_DEF;
28654+ err = au_nhash_alloc(&whtmp->whlist, rdhash, gfp);
28655+ if (unlikely(err)) {
28656+ kfree(whtmp);
28657+ whtmp = ERR_PTR(err);
28658+ }
dece6358 28659+
4f0767ce 28660+out:
dece6358 28661+ return whtmp;
1facf9fc 28662+}
28663+
28664+void au_whtmp_rmdir_free(struct au_whtmp_rmdir *whtmp)
28665+{
027c5e7a
AM
28666+ if (whtmp->br)
28667+ atomic_dec(&whtmp->br->br_count);
1facf9fc 28668+ dput(whtmp->wh_dentry);
28669+ iput(whtmp->dir);
dece6358 28670+ au_nhash_wh_free(&whtmp->whlist);
1facf9fc 28671+ kfree(whtmp);
28672+}
28673+
28674+/*
28675+ * rmdir the whiteouted temporary named dir @h_dentry.
28676+ * @whlist: whiteouted children.
28677+ */
28678+int au_whtmp_rmdir(struct inode *dir, aufs_bindex_t bindex,
28679+ struct dentry *wh_dentry, struct au_nhash *whlist)
28680+{
28681+ int err;
28682+ struct path h_tmp;
28683+ struct inode *wh_inode, *h_dir;
28684+ struct au_branch *br;
28685+
28686+ h_dir = wh_dentry->d_parent->d_inode; /* dir inode is locked */
28687+ IMustLock(h_dir);
28688+
28689+ br = au_sbr(dir->i_sb, bindex);
28690+ wh_inode = wh_dentry->d_inode;
28691+ mutex_lock_nested(&wh_inode->i_mutex, AuLsc_I_CHILD);
28692+
28693+ /*
28694+ * someone else might change some whiteouts while we were sleeping.
28695+ * it means this whlist may have an obsoleted entry.
28696+ */
28697+ if (!au_test_h_perm_sio(wh_inode, MAY_EXEC | MAY_WRITE))
28698+ err = del_wh_children(wh_dentry, whlist, bindex, br);
28699+ else {
28700+ int wkq_err;
28701+ struct del_wh_children_args args = {
28702+ .errp = &err,
28703+ .h_dentry = wh_dentry,
1308ab2a 28704+ .whlist = whlist,
1facf9fc 28705+ .bindex = bindex,
28706+ .br = br
28707+ };
28708+
28709+ wkq_err = au_wkq_wait(call_del_wh_children, &args);
28710+ if (unlikely(wkq_err))
28711+ err = wkq_err;
28712+ }
28713+ mutex_unlock(&wh_inode->i_mutex);
28714+
28715+ if (!err) {
28716+ h_tmp.dentry = wh_dentry;
28717+ h_tmp.mnt = br->br_mnt;
28718+ err = vfsub_rmdir(h_dir, &h_tmp);
1facf9fc 28719+ }
28720+
28721+ if (!err) {
28722+ if (au_ibstart(dir) == bindex) {
7f207e10 28723+ /* todo: dir->i_mutex is necessary */
1facf9fc 28724+ au_cpup_attr_timesizes(dir);
7f207e10 28725+ vfsub_drop_nlink(dir);
1facf9fc 28726+ }
28727+ return 0; /* success */
28728+ }
28729+
0c3ec466
AM
28730+ pr_warn("failed removing %.*s(%d), ignored\n",
28731+ AuDLNPair(wh_dentry), err);
1facf9fc 28732+ return err;
28733+}
28734+
28735+static void call_rmdir_whtmp(void *args)
28736+{
28737+ int err;
e49829fe 28738+ aufs_bindex_t bindex;
1facf9fc 28739+ struct au_whtmp_rmdir *a = args;
28740+ struct super_block *sb;
28741+ struct dentry *h_parent;
28742+ struct inode *h_dir;
1facf9fc 28743+ struct au_hinode *hdir;
28744+
28745+ /* rmdir by nfsd may cause deadlock with this i_mutex */
28746+ /* mutex_lock(&a->dir->i_mutex); */
e49829fe 28747+ err = -EROFS;
1facf9fc 28748+ sb = a->dir->i_sb;
e49829fe
JR
28749+ si_read_lock(sb, !AuLock_FLUSH);
28750+ if (!au_br_writable(a->br->br_perm))
28751+ goto out;
28752+ bindex = au_br_index(sb, a->br->br_id);
28753+ if (unlikely(bindex < 0))
1facf9fc 28754+ goto out;
28755+
28756+ err = -EIO;
1facf9fc 28757+ ii_write_lock_parent(a->dir);
28758+ h_parent = dget_parent(a->wh_dentry);
28759+ h_dir = h_parent->d_inode;
e49829fe 28760+ hdir = au_hi(a->dir, bindex);
4a4d8108 28761+ au_hn_imtx_lock_nested(hdir, AuLsc_I_PARENT);
e49829fe
JR
28762+ err = au_h_verify(a->wh_dentry, au_opt_udba(sb), h_dir, h_parent,
28763+ a->br);
1facf9fc 28764+ if (!err) {
e49829fe 28765+ err = mnt_want_write(a->br->br_mnt);
1facf9fc 28766+ if (!err) {
e49829fe 28767+ err = au_whtmp_rmdir(a->dir, bindex, a->wh_dentry,
dece6358 28768+ &a->whlist);
e49829fe 28769+ mnt_drop_write(a->br->br_mnt);
1facf9fc 28770+ }
28771+ }
4a4d8108 28772+ au_hn_imtx_unlock(hdir);
1facf9fc 28773+ dput(h_parent);
28774+ ii_write_unlock(a->dir);
28775+
4f0767ce 28776+out:
1facf9fc 28777+ /* mutex_unlock(&a->dir->i_mutex); */
1facf9fc 28778+ au_whtmp_rmdir_free(a);
027c5e7a
AM
28779+ si_read_unlock(sb);
28780+ au_nwt_done(&au_sbi(sb)->si_nowait);
1facf9fc 28781+ if (unlikely(err))
28782+ AuIOErr("err %d\n", err);
28783+}
28784+
28785+void au_whtmp_kick_rmdir(struct inode *dir, aufs_bindex_t bindex,
28786+ struct dentry *wh_dentry, struct au_whtmp_rmdir *args)
28787+{
28788+ int wkq_err;
e49829fe 28789+ struct super_block *sb;
1facf9fc 28790+
28791+ IMustLock(dir);
28792+
28793+ /* all post-process will be done in do_rmdir_whtmp(). */
e49829fe 28794+ sb = dir->i_sb;
1facf9fc 28795+ args->dir = au_igrab(dir);
e49829fe
JR
28796+ args->br = au_sbr(sb, bindex);
28797+ atomic_inc(&args->br->br_count);
1facf9fc 28798+ args->wh_dentry = dget(wh_dentry);
53392da6 28799+ wkq_err = au_wkq_nowait(call_rmdir_whtmp, args, sb, /*flags*/0);
1facf9fc 28800+ if (unlikely(wkq_err)) {
0c3ec466
AM
28801+ pr_warn("rmdir error %.*s (%d), ignored\n",
28802+ AuDLNPair(wh_dentry), wkq_err);
1facf9fc 28803+ au_whtmp_rmdir_free(args);
28804+ }
28805+}
7f207e10
AM
28806diff -urN /usr/share/empty/fs/aufs/whout.h linux/fs/aufs/whout.h
28807--- /usr/share/empty/fs/aufs/whout.h 1970-01-01 01:00:00.000000000 +0100
0c3ec466 28808+++ linux/fs/aufs/whout.h 2012-07-22 19:57:03.167671344 +0200
f6c5ef8b 28809@@ -0,0 +1,88 @@
1facf9fc 28810+/*
f6c5ef8b 28811+ * Copyright (C) 2005-2012 Junjiro R. Okajima
1facf9fc 28812+ *
28813+ * This program, aufs is free software; you can redistribute it and/or modify
28814+ * it under the terms of the GNU General Public License as published by
28815+ * the Free Software Foundation; either version 2 of the License, or
28816+ * (at your option) any later version.
dece6358
AM
28817+ *
28818+ * This program is distributed in the hope that it will be useful,
28819+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
28820+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
28821+ * GNU General Public License for more details.
28822+ *
28823+ * You should have received a copy of the GNU General Public License
28824+ * along with this program; if not, write to the Free Software
28825+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 28826+ */
28827+
28828+/*
28829+ * whiteout for logical deletion and opaque directory
28830+ */
28831+
28832+#ifndef __AUFS_WHOUT_H__
28833+#define __AUFS_WHOUT_H__
28834+
28835+#ifdef __KERNEL__
28836+
1facf9fc 28837+#include "dir.h"
28838+
28839+/* whout.c */
28840+int au_wh_name_alloc(struct qstr *wh, const struct qstr *name);
28841+struct au_branch;
28842+int au_wh_test(struct dentry *h_parent, struct qstr *wh_name,
28843+ struct au_branch *br, int try_sio);
28844+int au_diropq_test(struct dentry *h_dentry, struct au_branch *br);
28845+struct dentry *au_whtmp_lkup(struct dentry *h_parent, struct au_branch *br,
28846+ struct qstr *prefix);
28847+int au_whtmp_ren(struct dentry *h_dentry, struct au_branch *br);
28848+int au_wh_unlink_dentry(struct inode *h_dir, struct path *h_path,
28849+ struct dentry *dentry);
28850+int au_wh_init(struct dentry *h_parent, struct au_branch *br,
28851+ struct super_block *sb);
28852+
28853+/* diropq flags */
28854+#define AuDiropq_CREATE 1
28855+#define au_ftest_diropq(flags, name) ((flags) & AuDiropq_##name)
7f207e10
AM
28856+#define au_fset_diropq(flags, name) \
28857+ do { (flags) |= AuDiropq_##name; } while (0)
28858+#define au_fclr_diropq(flags, name) \
28859+ do { (flags) &= ~AuDiropq_##name; } while (0)
1facf9fc 28860+
28861+struct dentry *au_diropq_sio(struct dentry *dentry, aufs_bindex_t bindex,
28862+ unsigned int flags);
28863+struct dentry *au_wh_lkup(struct dentry *h_parent, struct qstr *base_name,
28864+ struct au_branch *br);
28865+struct dentry *au_wh_create(struct dentry *dentry, aufs_bindex_t bindex,
28866+ struct dentry *h_parent);
28867+
28868+/* real rmdir for the whiteout-ed dir */
28869+struct au_whtmp_rmdir {
28870+ struct inode *dir;
e49829fe 28871+ struct au_branch *br;
1facf9fc 28872+ struct dentry *wh_dentry;
dece6358 28873+ struct au_nhash whlist;
1facf9fc 28874+};
28875+
28876+struct au_whtmp_rmdir *au_whtmp_rmdir_alloc(struct super_block *sb, gfp_t gfp);
28877+void au_whtmp_rmdir_free(struct au_whtmp_rmdir *whtmp);
28878+int au_whtmp_rmdir(struct inode *dir, aufs_bindex_t bindex,
28879+ struct dentry *wh_dentry, struct au_nhash *whlist);
28880+void au_whtmp_kick_rmdir(struct inode *dir, aufs_bindex_t bindex,
28881+ struct dentry *wh_dentry, struct au_whtmp_rmdir *args);
28882+
28883+/* ---------------------------------------------------------------------- */
28884+
28885+static inline struct dentry *au_diropq_create(struct dentry *dentry,
28886+ aufs_bindex_t bindex)
28887+{
28888+ return au_diropq_sio(dentry, bindex, AuDiropq_CREATE);
28889+}
28890+
28891+static inline int au_diropq_remove(struct dentry *dentry, aufs_bindex_t bindex)
28892+{
28893+ return PTR_ERR(au_diropq_sio(dentry, bindex, !AuDiropq_CREATE));
28894+}
28895+
28896+#endif /* __KERNEL__ */
28897+#endif /* __AUFS_WHOUT_H__ */
7f207e10
AM
28898diff -urN /usr/share/empty/fs/aufs/wkq.c linux/fs/aufs/wkq.c
28899--- /usr/share/empty/fs/aufs/wkq.c 1970-01-01 01:00:00.000000000 +0100
0c3ec466 28900+++ linux/fs/aufs/wkq.c 2012-07-22 19:57:03.167671344 +0200
9dbd164d 28901@@ -0,0 +1,214 @@
1facf9fc 28902+/*
f6c5ef8b 28903+ * Copyright (C) 2005-2012 Junjiro R. Okajima
1facf9fc 28904+ *
28905+ * This program, aufs is free software; you can redistribute it and/or modify
28906+ * it under the terms of the GNU General Public License as published by
28907+ * the Free Software Foundation; either version 2 of the License, or
28908+ * (at your option) any later version.
dece6358
AM
28909+ *
28910+ * This program is distributed in the hope that it will be useful,
28911+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
28912+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
28913+ * GNU General Public License for more details.
28914+ *
28915+ * You should have received a copy of the GNU General Public License
28916+ * along with this program; if not, write to the Free Software
28917+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 28918+ */
28919+
28920+/*
28921+ * workqueue for asynchronous/super-io operations
28922+ * todo: try new dredential scheme
28923+ */
28924+
dece6358 28925+#include <linux/module.h>
1facf9fc 28926+#include "aufs.h"
28927+
9dbd164d 28928+/* internal workqueue named AUFS_WKQ_NAME */
b752ccd1 28929+
9dbd164d 28930+static struct workqueue_struct *au_wkq;
1facf9fc 28931+
28932+struct au_wkinfo {
28933+ struct work_struct wk;
7f207e10 28934+ struct kobject *kobj;
1facf9fc 28935+
28936+ unsigned int flags; /* see wkq.h */
28937+
28938+ au_wkq_func_t func;
28939+ void *args;
28940+
1facf9fc 28941+ struct completion *comp;
28942+};
28943+
28944+/* ---------------------------------------------------------------------- */
28945+
1facf9fc 28946+static void wkq_func(struct work_struct *wk)
28947+{
28948+ struct au_wkinfo *wkinfo = container_of(wk, struct au_wkinfo, wk);
28949+
0c3ec466 28950+ AuDebugOn(current_fsuid() != GLOBAL_ROOT_GID);
7f207e10
AM
28951+ AuDebugOn(rlimit(RLIMIT_FSIZE) != RLIM_INFINITY);
28952+
1facf9fc 28953+ wkinfo->func(wkinfo->args);
1facf9fc 28954+ if (au_ftest_wkq(wkinfo->flags, WAIT))
28955+ complete(wkinfo->comp);
28956+ else {
7f207e10 28957+ kobject_put(wkinfo->kobj);
9dbd164d 28958+ module_put(THIS_MODULE); /* todo: ?? */
1facf9fc 28959+ kfree(wkinfo);
28960+ }
28961+}
28962+
28963+/*
28964+ * Since struct completion is large, try allocating it dynamically.
28965+ */
28966+#if defined(CONFIG_4KSTACKS) || defined(AuTest4KSTACKS)
28967+#define AuWkqCompDeclare(name) struct completion *comp = NULL
28968+
28969+static int au_wkq_comp_alloc(struct au_wkinfo *wkinfo, struct completion **comp)
28970+{
28971+ *comp = kmalloc(sizeof(**comp), GFP_NOFS);
28972+ if (*comp) {
28973+ init_completion(*comp);
28974+ wkinfo->comp = *comp;
28975+ return 0;
28976+ }
28977+ return -ENOMEM;
28978+}
28979+
28980+static void au_wkq_comp_free(struct completion *comp)
28981+{
28982+ kfree(comp);
28983+}
28984+
28985+#else
28986+
28987+/* no braces */
28988+#define AuWkqCompDeclare(name) \
28989+ DECLARE_COMPLETION_ONSTACK(_ ## name); \
28990+ struct completion *comp = &_ ## name
28991+
28992+static int au_wkq_comp_alloc(struct au_wkinfo *wkinfo, struct completion **comp)
28993+{
28994+ wkinfo->comp = *comp;
28995+ return 0;
28996+}
28997+
28998+static void au_wkq_comp_free(struct completion *comp __maybe_unused)
28999+{
29000+ /* empty */
29001+}
29002+#endif /* 4KSTACKS */
29003+
53392da6 29004+static void au_wkq_run(struct au_wkinfo *wkinfo)
1facf9fc 29005+{
53392da6
AM
29006+ if (au_ftest_wkq(wkinfo->flags, NEST)) {
29007+ if (au_wkq_test()) {
29008+ AuWarn1("wkq from wkq, due to a dead dir by UDBA?\n");
29009+ AuDebugOn(au_ftest_wkq(wkinfo->flags, WAIT));
29010+ }
29011+ } else
29012+ au_dbg_verify_kthread();
29013+
29014+ if (au_ftest_wkq(wkinfo->flags, WAIT)) {
a1f66529 29015+ INIT_WORK_ONSTACK(&wkinfo->wk, wkq_func);
9dbd164d 29016+ queue_work(au_wkq, &wkinfo->wk);
4a4d8108
AM
29017+ } else {
29018+ INIT_WORK(&wkinfo->wk, wkq_func);
29019+ schedule_work(&wkinfo->wk);
29020+ }
1facf9fc 29021+}
29022+
7f207e10
AM
29023+/*
29024+ * Be careful. It is easy to make deadlock happen.
29025+ * processA: lock, wkq and wait
29026+ * processB: wkq and wait, lock in wkq
29027+ * --> deadlock
29028+ */
b752ccd1 29029+int au_wkq_do_wait(unsigned int flags, au_wkq_func_t func, void *args)
1facf9fc 29030+{
29031+ int err;
29032+ AuWkqCompDeclare(comp);
29033+ struct au_wkinfo wkinfo = {
b752ccd1 29034+ .flags = flags,
1facf9fc 29035+ .func = func,
29036+ .args = args
29037+ };
29038+
29039+ err = au_wkq_comp_alloc(&wkinfo, &comp);
29040+ if (!err) {
53392da6 29041+ au_wkq_run(&wkinfo);
1facf9fc 29042+ /* no timeout, no interrupt */
29043+ wait_for_completion(wkinfo.comp);
29044+ au_wkq_comp_free(comp);
4a4d8108 29045+ destroy_work_on_stack(&wkinfo.wk);
1facf9fc 29046+ }
29047+
29048+ return err;
29049+
29050+}
29051+
027c5e7a
AM
29052+/*
29053+ * Note: dget/dput() in func for aufs dentries are not supported. It will be a
29054+ * problem in a concurrent umounting.
29055+ */
53392da6
AM
29056+int au_wkq_nowait(au_wkq_func_t func, void *args, struct super_block *sb,
29057+ unsigned int flags)
1facf9fc 29058+{
29059+ int err;
29060+ struct au_wkinfo *wkinfo;
29061+
29062+ atomic_inc(&au_sbi(sb)->si_nowait.nw_len);
29063+
29064+ /*
29065+ * wkq_func() must free this wkinfo.
29066+ * it highly depends upon the implementation of workqueue.
29067+ */
29068+ err = 0;
29069+ wkinfo = kmalloc(sizeof(*wkinfo), GFP_NOFS);
29070+ if (wkinfo) {
7f207e10 29071+ wkinfo->kobj = &au_sbi(sb)->si_kobj;
53392da6 29072+ wkinfo->flags = flags & ~AuWkq_WAIT;
1facf9fc 29073+ wkinfo->func = func;
29074+ wkinfo->args = args;
29075+ wkinfo->comp = NULL;
7f207e10 29076+ kobject_get(wkinfo->kobj);
9dbd164d 29077+ __module_get(THIS_MODULE); /* todo: ?? */
1facf9fc 29078+
53392da6 29079+ au_wkq_run(wkinfo);
1facf9fc 29080+ } else {
29081+ err = -ENOMEM;
e49829fe 29082+ au_nwt_done(&au_sbi(sb)->si_nowait);
1facf9fc 29083+ }
29084+
29085+ return err;
29086+}
29087+
29088+/* ---------------------------------------------------------------------- */
29089+
29090+void au_nwt_init(struct au_nowait_tasks *nwt)
29091+{
29092+ atomic_set(&nwt->nw_len, 0);
4a4d8108 29093+ /* smp_mb(); */ /* atomic_set */
1facf9fc 29094+ init_waitqueue_head(&nwt->nw_wq);
29095+}
29096+
29097+void au_wkq_fin(void)
29098+{
9dbd164d 29099+ destroy_workqueue(au_wkq);
1facf9fc 29100+}
29101+
29102+int __init au_wkq_init(void)
29103+{
9dbd164d 29104+ int err;
b752ccd1
AM
29105+
29106+ err = 0;
9dbd164d
AM
29107+ BUILD_BUG_ON(!WQ_RESCUER);
29108+ au_wkq = alloc_workqueue(AUFS_WKQ_NAME, !WQ_RESCUER, WQ_DFL_ACTIVE);
29109+ if (IS_ERR(au_wkq))
29110+ err = PTR_ERR(au_wkq);
29111+ else if (!au_wkq)
29112+ err = -ENOMEM;
b752ccd1
AM
29113+
29114+ return err;
1facf9fc 29115+}
7f207e10
AM
29116diff -urN /usr/share/empty/fs/aufs/wkq.h linux/fs/aufs/wkq.h
29117--- /usr/share/empty/fs/aufs/wkq.h 1970-01-01 01:00:00.000000000 +0100
0c3ec466 29118+++ linux/fs/aufs/wkq.h 2012-07-22 19:57:03.167671344 +0200
f6c5ef8b 29119@@ -0,0 +1,92 @@
1facf9fc 29120+/*
f6c5ef8b 29121+ * Copyright (C) 2005-2012 Junjiro R. Okajima
1facf9fc 29122+ *
29123+ * This program, aufs is free software; you can redistribute it and/or modify
29124+ * it under the terms of the GNU General Public License as published by
29125+ * the Free Software Foundation; either version 2 of the License, or
29126+ * (at your option) any later version.
dece6358
AM
29127+ *
29128+ * This program is distributed in the hope that it will be useful,
29129+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
29130+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
29131+ * GNU General Public License for more details.
29132+ *
29133+ * You should have received a copy of the GNU General Public License
29134+ * along with this program; if not, write to the Free Software
29135+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 29136+ */
29137+
29138+/*
29139+ * workqueue for asynchronous/super-io operations
29140+ * todo: try new credentials management scheme
29141+ */
29142+
29143+#ifndef __AUFS_WKQ_H__
29144+#define __AUFS_WKQ_H__
29145+
29146+#ifdef __KERNEL__
29147+
dece6358
AM
29148+struct super_block;
29149+
1facf9fc 29150+/* ---------------------------------------------------------------------- */
29151+
29152+/*
29153+ * in the next operation, wait for the 'nowait' tasks in system-wide workqueue
29154+ */
29155+struct au_nowait_tasks {
29156+ atomic_t nw_len;
29157+ wait_queue_head_t nw_wq;
29158+};
29159+
29160+/* ---------------------------------------------------------------------- */
29161+
29162+typedef void (*au_wkq_func_t)(void *args);
29163+
29164+/* wkq flags */
29165+#define AuWkq_WAIT 1
9dbd164d 29166+#define AuWkq_NEST (1 << 1)
1facf9fc 29167+#define au_ftest_wkq(flags, name) ((flags) & AuWkq_##name)
7f207e10
AM
29168+#define au_fset_wkq(flags, name) \
29169+ do { (flags) |= AuWkq_##name; } while (0)
29170+#define au_fclr_wkq(flags, name) \
29171+ do { (flags) &= ~AuWkq_##name; } while (0)
1facf9fc 29172+
9dbd164d
AM
29173+#ifndef CONFIG_AUFS_HNOTIFY
29174+#undef AuWkq_NEST
29175+#define AuWkq_NEST 0
29176+#endif
29177+
1facf9fc 29178+/* wkq.c */
b752ccd1 29179+int au_wkq_do_wait(unsigned int flags, au_wkq_func_t func, void *args);
53392da6
AM
29180+int au_wkq_nowait(au_wkq_func_t func, void *args, struct super_block *sb,
29181+ unsigned int flags);
1facf9fc 29182+void au_nwt_init(struct au_nowait_tasks *nwt);
29183+int __init au_wkq_init(void);
29184+void au_wkq_fin(void);
29185+
29186+/* ---------------------------------------------------------------------- */
29187+
53392da6
AM
29188+static inline int au_wkq_test(void)
29189+{
29190+ return current->flags & PF_WQ_WORKER;
29191+}
29192+
b752ccd1 29193+static inline int au_wkq_wait(au_wkq_func_t func, void *args)
1facf9fc 29194+{
b752ccd1 29195+ return au_wkq_do_wait(AuWkq_WAIT, func, args);
1facf9fc 29196+}
29197+
29198+static inline void au_nwt_done(struct au_nowait_tasks *nwt)
29199+{
e49829fe 29200+ if (atomic_dec_and_test(&nwt->nw_len))
1facf9fc 29201+ wake_up_all(&nwt->nw_wq);
29202+}
29203+
29204+static inline int au_nwt_flush(struct au_nowait_tasks *nwt)
29205+{
29206+ wait_event(nwt->nw_wq, !atomic_read(&nwt->nw_len));
29207+ return 0;
29208+}
29209+
29210+#endif /* __KERNEL__ */
29211+#endif /* __AUFS_WKQ_H__ */
7f207e10
AM
29212diff -urN /usr/share/empty/fs/aufs/xino.c linux/fs/aufs/xino.c
29213--- /usr/share/empty/fs/aufs/xino.c 1970-01-01 01:00:00.000000000 +0100
0c3ec466 29214+++ linux/fs/aufs/xino.c 2012-07-22 19:57:03.167671344 +0200
f6c5ef8b 29215@@ -0,0 +1,1264 @@
1facf9fc 29216+/*
f6c5ef8b 29217+ * Copyright (C) 2005-2012 Junjiro R. Okajima
1facf9fc 29218+ *
29219+ * This program, aufs is free software; you can redistribute it and/or modify
29220+ * it under the terms of the GNU General Public License as published by
29221+ * the Free Software Foundation; either version 2 of the License, or
29222+ * (at your option) any later version.
dece6358
AM
29223+ *
29224+ * This program is distributed in the hope that it will be useful,
29225+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
29226+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
29227+ * GNU General Public License for more details.
29228+ *
29229+ * You should have received a copy of the GNU General Public License
29230+ * along with this program; if not, write to the Free Software
29231+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1facf9fc 29232+ */
29233+
29234+/*
29235+ * external inode number translation table and bitmap
29236+ */
29237+
29238+#include <linux/seq_file.h>
1facf9fc 29239+#include "aufs.h"
29240+
9dbd164d 29241+/* todo: unnecessary to support mmap_sem since kernel-space? */
b752ccd1 29242+ssize_t xino_fread(au_readf_t func, struct file *file, void *kbuf, size_t size,
1facf9fc 29243+ loff_t *pos)
29244+{
29245+ ssize_t err;
29246+ mm_segment_t oldfs;
b752ccd1
AM
29247+ union {
29248+ void *k;
29249+ char __user *u;
29250+ } buf;
1facf9fc 29251+
b752ccd1 29252+ buf.k = kbuf;
1facf9fc 29253+ oldfs = get_fs();
29254+ set_fs(KERNEL_DS);
29255+ do {
29256+ /* todo: signal_pending? */
b752ccd1 29257+ err = func(file, buf.u, size, pos);
1facf9fc 29258+ } while (err == -EAGAIN || err == -EINTR);
29259+ set_fs(oldfs);
29260+
29261+#if 0 /* reserved for future use */
29262+ if (err > 0)
29263+ fsnotify_access(file->f_dentry);
29264+#endif
29265+
29266+ return err;
29267+}
29268+
29269+/* ---------------------------------------------------------------------- */
29270+
b752ccd1 29271+static ssize_t do_xino_fwrite(au_writef_t func, struct file *file, void *kbuf,
1facf9fc 29272+ size_t size, loff_t *pos)
29273+{
29274+ ssize_t err;
29275+ mm_segment_t oldfs;
b752ccd1
AM
29276+ union {
29277+ void *k;
29278+ const char __user *u;
29279+ } buf;
1facf9fc 29280+
b752ccd1 29281+ buf.k = kbuf;
1facf9fc 29282+ oldfs = get_fs();
29283+ set_fs(KERNEL_DS);
1facf9fc 29284+ do {
29285+ /* todo: signal_pending? */
b752ccd1 29286+ err = func(file, buf.u, size, pos);
1facf9fc 29287+ } while (err == -EAGAIN || err == -EINTR);
1facf9fc 29288+ set_fs(oldfs);
29289+
29290+#if 0 /* reserved for future use */
29291+ if (err > 0)
29292+ fsnotify_modify(file->f_dentry);
29293+#endif
29294+
29295+ return err;
29296+}
29297+
29298+struct do_xino_fwrite_args {
29299+ ssize_t *errp;
29300+ au_writef_t func;
29301+ struct file *file;
29302+ void *buf;
29303+ size_t size;
29304+ loff_t *pos;
29305+};
29306+
29307+static void call_do_xino_fwrite(void *args)
29308+{
29309+ struct do_xino_fwrite_args *a = args;
29310+ *a->errp = do_xino_fwrite(a->func, a->file, a->buf, a->size, a->pos);
29311+}
29312+
29313+ssize_t xino_fwrite(au_writef_t func, struct file *file, void *buf, size_t size,
29314+ loff_t *pos)
29315+{
29316+ ssize_t err;
29317+
29318+ /* todo: signal block and no wkq? */
b752ccd1
AM
29319+ if (rlimit(RLIMIT_FSIZE) == RLIM_INFINITY) {
29320+ lockdep_off();
29321+ err = do_xino_fwrite(func, file, buf, size, pos);
29322+ lockdep_on();
29323+ } else {
29324+ /*
29325+ * it breaks RLIMIT_FSIZE and normal user's limit,
29326+ * users should care about quota and real 'filesystem full.'
29327+ */
1facf9fc 29328+ int wkq_err;
29329+ struct do_xino_fwrite_args args = {
29330+ .errp = &err,
29331+ .func = func,
29332+ .file = file,
29333+ .buf = buf,
29334+ .size = size,
29335+ .pos = pos
29336+ };
29337+
29338+ wkq_err = au_wkq_wait(call_do_xino_fwrite, &args);
29339+ if (unlikely(wkq_err))
29340+ err = wkq_err;
b752ccd1 29341+ }
1facf9fc 29342+
29343+ return err;
29344+}
29345+
29346+/* ---------------------------------------------------------------------- */
29347+
29348+/*
29349+ * create a new xinofile at the same place/path as @base_file.
29350+ */
29351+struct file *au_xino_create2(struct file *base_file, struct file *copy_src)
29352+{
29353+ struct file *file;
4a4d8108 29354+ struct dentry *base, *parent;
1facf9fc 29355+ struct inode *dir;
29356+ struct qstr *name;
1308ab2a 29357+ struct path path;
4a4d8108 29358+ int err;
1facf9fc 29359+
29360+ base = base_file->f_dentry;
29361+ parent = base->d_parent; /* dir inode is locked */
29362+ dir = parent->d_inode;
29363+ IMustLock(dir);
29364+
29365+ file = ERR_PTR(-EINVAL);
29366+ name = &base->d_name;
4a4d8108
AM
29367+ path.dentry = vfsub_lookup_one_len(name->name, parent, name->len);
29368+ if (IS_ERR(path.dentry)) {
29369+ file = (void *)path.dentry;
29370+ pr_err("%.*s lookup err %ld\n",
29371+ AuLNPair(name), PTR_ERR(path.dentry));
1facf9fc 29372+ goto out;
29373+ }
29374+
29375+ /* no need to mnt_want_write() since we call dentry_open() later */
4a4d8108 29376+ err = vfs_create(dir, path.dentry, S_IRUGO | S_IWUGO, NULL);
1facf9fc 29377+ if (unlikely(err)) {
29378+ file = ERR_PTR(err);
4a4d8108 29379+ pr_err("%.*s create err %d\n", AuLNPair(name), err);
1facf9fc 29380+ goto out_dput;
29381+ }
29382+
1308ab2a 29383+ path.mnt = base_file->f_vfsmnt;
4a4d8108 29384+ file = vfsub_dentry_open(&path,
7f207e10 29385+ O_RDWR | O_CREAT | O_EXCL | O_LARGEFILE
2cbb1c4b 29386+ /* | __FMODE_NONOTIFY */);
1facf9fc 29387+ if (IS_ERR(file)) {
4a4d8108 29388+ pr_err("%.*s open err %ld\n", AuLNPair(name), PTR_ERR(file));
1facf9fc 29389+ goto out_dput;
29390+ }
29391+
29392+ err = vfsub_unlink(dir, &file->f_path, /*force*/0);
29393+ if (unlikely(err)) {
4a4d8108 29394+ pr_err("%.*s unlink err %d\n", AuLNPair(name), err);
1facf9fc 29395+ goto out_fput;
29396+ }
29397+
29398+ if (copy_src) {
29399+ /* no one can touch copy_src xino */
29400+ err = au_copy_file(file, copy_src,
29401+ i_size_read(copy_src->f_dentry->d_inode));
29402+ if (unlikely(err)) {
4a4d8108 29403+ pr_err("%.*s copy err %d\n", AuLNPair(name), err);
1facf9fc 29404+ goto out_fput;
29405+ }
29406+ }
29407+ goto out_dput; /* success */
29408+
4f0767ce 29409+out_fput:
1facf9fc 29410+ fput(file);
29411+ file = ERR_PTR(err);
4f0767ce 29412+out_dput:
4a4d8108 29413+ dput(path.dentry);
4f0767ce 29414+out:
1facf9fc 29415+ return file;
29416+}
29417+
29418+struct au_xino_lock_dir {
29419+ struct au_hinode *hdir;
29420+ struct dentry *parent;
29421+ struct mutex *mtx;
29422+};
29423+
29424+static void au_xino_lock_dir(struct super_block *sb, struct file *xino,
29425+ struct au_xino_lock_dir *ldir)
29426+{
29427+ aufs_bindex_t brid, bindex;
29428+
29429+ ldir->hdir = NULL;
29430+ bindex = -1;
29431+ brid = au_xino_brid(sb);
29432+ if (brid >= 0)
29433+ bindex = au_br_index(sb, brid);
29434+ if (bindex >= 0) {
29435+ ldir->hdir = au_hi(sb->s_root->d_inode, bindex);
4a4d8108 29436+ au_hn_imtx_lock_nested(ldir->hdir, AuLsc_I_PARENT);
1facf9fc 29437+ } else {
29438+ ldir->parent = dget_parent(xino->f_dentry);
29439+ ldir->mtx = &ldir->parent->d_inode->i_mutex;
29440+ mutex_lock_nested(ldir->mtx, AuLsc_I_PARENT);
29441+ }
29442+}
29443+
29444+static void au_xino_unlock_dir(struct au_xino_lock_dir *ldir)
29445+{
29446+ if (ldir->hdir)
4a4d8108 29447+ au_hn_imtx_unlock(ldir->hdir);
1facf9fc 29448+ else {
29449+ mutex_unlock(ldir->mtx);
29450+ dput(ldir->parent);
29451+ }
29452+}
29453+
29454+/* ---------------------------------------------------------------------- */
29455+
29456+/* trucate xino files asynchronously */
29457+
29458+int au_xino_trunc(struct super_block *sb, aufs_bindex_t bindex)
29459+{
29460+ int err;
29461+ aufs_bindex_t bi, bend;
29462+ struct au_branch *br;
29463+ struct file *new_xino, *file;
29464+ struct super_block *h_sb;
29465+ struct au_xino_lock_dir ldir;
29466+
29467+ err = -EINVAL;
29468+ bend = au_sbend(sb);
29469+ if (unlikely(bindex < 0 || bend < bindex))
29470+ goto out;
29471+ br = au_sbr(sb, bindex);
29472+ file = br->br_xino.xi_file;
29473+ if (!file)
29474+ goto out;
29475+
29476+ au_xino_lock_dir(sb, file, &ldir);
29477+ /* mnt_want_write() is unnecessary here */
29478+ new_xino = au_xino_create2(file, file);
29479+ au_xino_unlock_dir(&ldir);
29480+ err = PTR_ERR(new_xino);
29481+ if (IS_ERR(new_xino))
29482+ goto out;
29483+ err = 0;
29484+ fput(file);
29485+ br->br_xino.xi_file = new_xino;
29486+
29487+ h_sb = br->br_mnt->mnt_sb;
29488+ for (bi = 0; bi <= bend; bi++) {
29489+ if (unlikely(bi == bindex))
29490+ continue;
29491+ br = au_sbr(sb, bi);
29492+ if (br->br_mnt->mnt_sb != h_sb)
29493+ continue;
29494+
29495+ fput(br->br_xino.xi_file);
29496+ br->br_xino.xi_file = new_xino;
29497+ get_file(new_xino);
29498+ }
29499+
4f0767ce 29500+out:
1facf9fc 29501+ return err;
29502+}
29503+
29504+struct xino_do_trunc_args {
29505+ struct super_block *sb;
29506+ struct au_branch *br;
29507+};
29508+
29509+static void xino_do_trunc(void *_args)
29510+{
29511+ struct xino_do_trunc_args *args = _args;
29512+ struct super_block *sb;
29513+ struct au_branch *br;
29514+ struct inode *dir;
29515+ int err;
29516+ aufs_bindex_t bindex;
29517+
29518+ err = 0;
29519+ sb = args->sb;
29520+ dir = sb->s_root->d_inode;
29521+ br = args->br;
29522+
29523+ si_noflush_write_lock(sb);
29524+ ii_read_lock_parent(dir);
29525+ bindex = au_br_index(sb, br->br_id);
29526+ err = au_xino_trunc(sb, bindex);
dece6358
AM
29527+ if (!err
29528+ && br->br_xino.xi_file->f_dentry->d_inode->i_blocks
1facf9fc 29529+ >= br->br_xino_upper)
29530+ br->br_xino_upper += AUFS_XINO_TRUNC_STEP;
29531+
1facf9fc 29532+ ii_read_unlock(dir);
29533+ if (unlikely(err))
0c3ec466 29534+ pr_warn("err b%d, (%d)\n", bindex, err);
1facf9fc 29535+ atomic_dec(&br->br_xino_running);
29536+ atomic_dec(&br->br_count);
1facf9fc 29537+ si_write_unlock(sb);
027c5e7a 29538+ au_nwt_done(&au_sbi(sb)->si_nowait);
1facf9fc 29539+ kfree(args);
29540+}
29541+
29542+static void xino_try_trunc(struct super_block *sb, struct au_branch *br)
29543+{
29544+ struct xino_do_trunc_args *args;
29545+ int wkq_err;
29546+
29547+ if (br->br_xino.xi_file->f_dentry->d_inode->i_blocks
29548+ < br->br_xino_upper)
29549+ return;
29550+
29551+ if (atomic_inc_return(&br->br_xino_running) > 1)
29552+ goto out;
29553+
29554+ /* lock and kfree() will be called in trunc_xino() */
29555+ args = kmalloc(sizeof(*args), GFP_NOFS);
29556+ if (unlikely(!args)) {
29557+ AuErr1("no memory\n");
29558+ goto out_args;
29559+ }
29560+
e49829fe 29561+ atomic_inc(&br->br_count);
1facf9fc 29562+ args->sb = sb;
29563+ args->br = br;
53392da6 29564+ wkq_err = au_wkq_nowait(xino_do_trunc, args, sb, /*flags*/0);
1facf9fc 29565+ if (!wkq_err)
29566+ return; /* success */
29567+
4a4d8108 29568+ pr_err("wkq %d\n", wkq_err);
e49829fe 29569+ atomic_dec(&br->br_count);
1facf9fc 29570+
4f0767ce 29571+out_args:
1facf9fc 29572+ kfree(args);
4f0767ce 29573+out:
e49829fe 29574+ atomic_dec(&br->br_xino_running);
1facf9fc 29575+}
29576+
29577+/* ---------------------------------------------------------------------- */
29578+
29579+static int au_xino_do_write(au_writef_t write, struct file *file,
29580+ ino_t h_ino, ino_t ino)
29581+{
29582+ loff_t pos;
29583+ ssize_t sz;
29584+
29585+ pos = h_ino;
29586+ if (unlikely(au_loff_max / sizeof(ino) - 1 < pos)) {
29587+ AuIOErr1("too large hi%lu\n", (unsigned long)h_ino);
29588+ return -EFBIG;
29589+ }
29590+ pos *= sizeof(ino);
29591+ sz = xino_fwrite(write, file, &ino, sizeof(ino), &pos);
29592+ if (sz == sizeof(ino))
29593+ return 0; /* success */
29594+
29595+ AuIOErr("write failed (%zd)\n", sz);
29596+ return -EIO;
29597+}
29598+
29599+/*
29600+ * write @ino to the xinofile for the specified branch{@sb, @bindex}
29601+ * at the position of @h_ino.
29602+ * even if @ino is zero, it is written to the xinofile and means no entry.
29603+ * if the size of the xino file on a specific filesystem exceeds the watermark,
29604+ * try truncating it.
29605+ */
29606+int au_xino_write(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino,
29607+ ino_t ino)
29608+{
29609+ int err;
29610+ unsigned int mnt_flags;
29611+ struct au_branch *br;
29612+
29613+ BUILD_BUG_ON(sizeof(long long) != sizeof(au_loff_max)
29614+ || ((loff_t)-1) > 0);
dece6358 29615+ SiMustAnyLock(sb);
1facf9fc 29616+
29617+ mnt_flags = au_mntflags(sb);
29618+ if (!au_opt_test(mnt_flags, XINO))
29619+ return 0;
29620+
29621+ br = au_sbr(sb, bindex);
29622+ err = au_xino_do_write(au_sbi(sb)->si_xwrite, br->br_xino.xi_file,
29623+ h_ino, ino);
29624+ if (!err) {
29625+ if (au_opt_test(mnt_flags, TRUNC_XINO)
29626+ && au_test_fs_trunc_xino(br->br_mnt->mnt_sb))
29627+ xino_try_trunc(sb, br);
29628+ return 0; /* success */
29629+ }
29630+
29631+ AuIOErr("write failed (%d)\n", err);
29632+ return -EIO;
29633+}
29634+
29635+/* ---------------------------------------------------------------------- */
29636+
29637+/* aufs inode number bitmap */
29638+
29639+static const int page_bits = (int)PAGE_SIZE * BITS_PER_BYTE;
29640+static ino_t xib_calc_ino(unsigned long pindex, int bit)
29641+{
29642+ ino_t ino;
29643+
29644+ AuDebugOn(bit < 0 || page_bits <= bit);
29645+ ino = AUFS_FIRST_INO + pindex * page_bits + bit;
29646+ return ino;
29647+}
29648+
29649+static void xib_calc_bit(ino_t ino, unsigned long *pindex, int *bit)
29650+{
29651+ AuDebugOn(ino < AUFS_FIRST_INO);
29652+ ino -= AUFS_FIRST_INO;
29653+ *pindex = ino / page_bits;
29654+ *bit = ino % page_bits;
29655+}
29656+
29657+static int xib_pindex(struct super_block *sb, unsigned long pindex)
29658+{
29659+ int err;
29660+ loff_t pos;
29661+ ssize_t sz;
29662+ struct au_sbinfo *sbinfo;
29663+ struct file *xib;
29664+ unsigned long *p;
29665+
29666+ sbinfo = au_sbi(sb);
29667+ MtxMustLock(&sbinfo->si_xib_mtx);
29668+ AuDebugOn(pindex > ULONG_MAX / PAGE_SIZE
29669+ || !au_opt_test(sbinfo->si_mntflags, XINO));
29670+
29671+ if (pindex == sbinfo->si_xib_last_pindex)
29672+ return 0;
29673+
29674+ xib = sbinfo->si_xib;
29675+ p = sbinfo->si_xib_buf;
29676+ pos = sbinfo->si_xib_last_pindex;
29677+ pos *= PAGE_SIZE;
29678+ sz = xino_fwrite(sbinfo->si_xwrite, xib, p, PAGE_SIZE, &pos);
29679+ if (unlikely(sz != PAGE_SIZE))
29680+ goto out;
29681+
29682+ pos = pindex;
29683+ pos *= PAGE_SIZE;
29684+ if (i_size_read(xib->f_dentry->d_inode) >= pos + PAGE_SIZE)
29685+ sz = xino_fread(sbinfo->si_xread, xib, p, PAGE_SIZE, &pos);
29686+ else {
29687+ memset(p, 0, PAGE_SIZE);
29688+ sz = xino_fwrite(sbinfo->si_xwrite, xib, p, PAGE_SIZE, &pos);
29689+ }
29690+ if (sz == PAGE_SIZE) {
29691+ sbinfo->si_xib_last_pindex = pindex;
29692+ return 0; /* success */
29693+ }
29694+
4f0767ce 29695+out:
b752ccd1
AM
29696+ AuIOErr1("write failed (%zd)\n", sz);
29697+ err = sz;
29698+ if (sz >= 0)
29699+ err = -EIO;
29700+ return err;
29701+}
29702+
29703+/* ---------------------------------------------------------------------- */
29704+
29705+static void au_xib_clear_bit(struct inode *inode)
29706+{
29707+ int err, bit;
29708+ unsigned long pindex;
29709+ struct super_block *sb;
29710+ struct au_sbinfo *sbinfo;
29711+
29712+ AuDebugOn(inode->i_nlink);
29713+
29714+ sb = inode->i_sb;
29715+ xib_calc_bit(inode->i_ino, &pindex, &bit);
29716+ AuDebugOn(page_bits <= bit);
29717+ sbinfo = au_sbi(sb);
29718+ mutex_lock(&sbinfo->si_xib_mtx);
29719+ err = xib_pindex(sb, pindex);
29720+ if (!err) {
29721+ clear_bit(bit, sbinfo->si_xib_buf);
29722+ sbinfo->si_xib_next_bit = bit;
29723+ }
29724+ mutex_unlock(&sbinfo->si_xib_mtx);
29725+}
29726+
29727+/* for s_op->delete_inode() */
29728+void au_xino_delete_inode(struct inode *inode, const int unlinked)
29729+{
29730+ int err;
29731+ unsigned int mnt_flags;
29732+ aufs_bindex_t bindex, bend, bi;
29733+ unsigned char try_trunc;
29734+ struct au_iinfo *iinfo;
29735+ struct super_block *sb;
29736+ struct au_hinode *hi;
29737+ struct inode *h_inode;
29738+ struct au_branch *br;
29739+ au_writef_t xwrite;
29740+
29741+ sb = inode->i_sb;
29742+ mnt_flags = au_mntflags(sb);
29743+ if (!au_opt_test(mnt_flags, XINO)
29744+ || inode->i_ino == AUFS_ROOT_INO)
29745+ return;
29746+
29747+ if (unlinked) {
29748+ au_xigen_inc(inode);
29749+ au_xib_clear_bit(inode);
29750+ }
29751+
29752+ iinfo = au_ii(inode);
29753+ if (!iinfo)
29754+ return;
1facf9fc 29755+
b752ccd1
AM
29756+ bindex = iinfo->ii_bstart;
29757+ if (bindex < 0)
29758+ return;
1facf9fc 29759+
b752ccd1
AM
29760+ xwrite = au_sbi(sb)->si_xwrite;
29761+ try_trunc = !!au_opt_test(mnt_flags, TRUNC_XINO);
29762+ hi = iinfo->ii_hinode + bindex;
29763+ bend = iinfo->ii_bend;
29764+ for (; bindex <= bend; bindex++, hi++) {
29765+ h_inode = hi->hi_inode;
29766+ if (!h_inode
29767+ || (!unlinked && h_inode->i_nlink))
29768+ continue;
1facf9fc 29769+
b752ccd1
AM
29770+ /* inode may not be revalidated */
29771+ bi = au_br_index(sb, hi->hi_id);
29772+ if (bi < 0)
29773+ continue;
1facf9fc 29774+
b752ccd1
AM
29775+ br = au_sbr(sb, bi);
29776+ err = au_xino_do_write(xwrite, br->br_xino.xi_file,
29777+ h_inode->i_ino, /*ino*/0);
29778+ if (!err && try_trunc
29779+ && au_test_fs_trunc_xino(br->br_mnt->mnt_sb))
29780+ xino_try_trunc(sb, br);
1facf9fc 29781+ }
1facf9fc 29782+}
29783+
29784+/* get an unused inode number from bitmap */
29785+ino_t au_xino_new_ino(struct super_block *sb)
29786+{
29787+ ino_t ino;
29788+ unsigned long *p, pindex, ul, pend;
29789+ struct au_sbinfo *sbinfo;
29790+ struct file *file;
29791+ int free_bit, err;
29792+
29793+ if (!au_opt_test(au_mntflags(sb), XINO))
29794+ return iunique(sb, AUFS_FIRST_INO);
29795+
29796+ sbinfo = au_sbi(sb);
29797+ mutex_lock(&sbinfo->si_xib_mtx);
29798+ p = sbinfo->si_xib_buf;
29799+ free_bit = sbinfo->si_xib_next_bit;
29800+ if (free_bit < page_bits && !test_bit(free_bit, p))
29801+ goto out; /* success */
29802+ free_bit = find_first_zero_bit(p, page_bits);
29803+ if (free_bit < page_bits)
29804+ goto out; /* success */
29805+
29806+ pindex = sbinfo->si_xib_last_pindex;
29807+ for (ul = pindex - 1; ul < ULONG_MAX; ul--) {
29808+ err = xib_pindex(sb, ul);
29809+ if (unlikely(err))
29810+ goto out_err;
29811+ free_bit = find_first_zero_bit(p, page_bits);
29812+ if (free_bit < page_bits)
29813+ goto out; /* success */
29814+ }
29815+
29816+ file = sbinfo->si_xib;
29817+ pend = i_size_read(file->f_dentry->d_inode) / PAGE_SIZE;
29818+ for (ul = pindex + 1; ul <= pend; ul++) {
29819+ err = xib_pindex(sb, ul);
29820+ if (unlikely(err))
29821+ goto out_err;
29822+ free_bit = find_first_zero_bit(p, page_bits);
29823+ if (free_bit < page_bits)
29824+ goto out; /* success */
29825+ }
29826+ BUG();
29827+
4f0767ce 29828+out:
1facf9fc 29829+ set_bit(free_bit, p);
7f207e10 29830+ sbinfo->si_xib_next_bit = free_bit + 1;
1facf9fc 29831+ pindex = sbinfo->si_xib_last_pindex;
29832+ mutex_unlock(&sbinfo->si_xib_mtx);
29833+ ino = xib_calc_ino(pindex, free_bit);
29834+ AuDbg("i%lu\n", (unsigned long)ino);
29835+ return ino;
4f0767ce 29836+out_err:
1facf9fc 29837+ mutex_unlock(&sbinfo->si_xib_mtx);
29838+ AuDbg("i0\n");
29839+ return 0;
29840+}
29841+
29842+/*
29843+ * read @ino from xinofile for the specified branch{@sb, @bindex}
29844+ * at the position of @h_ino.
29845+ * if @ino does not exist and @do_new is true, get new one.
29846+ */
29847+int au_xino_read(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino,
29848+ ino_t *ino)
29849+{
29850+ int err;
29851+ ssize_t sz;
29852+ loff_t pos;
29853+ struct file *file;
29854+ struct au_sbinfo *sbinfo;
29855+
29856+ *ino = 0;
29857+ if (!au_opt_test(au_mntflags(sb), XINO))
29858+ return 0; /* no xino */
29859+
29860+ err = 0;
29861+ sbinfo = au_sbi(sb);
29862+ pos = h_ino;
29863+ if (unlikely(au_loff_max / sizeof(*ino) - 1 < pos)) {
29864+ AuIOErr1("too large hi%lu\n", (unsigned long)h_ino);
29865+ return -EFBIG;
29866+ }
29867+ pos *= sizeof(*ino);
29868+
29869+ file = au_sbr(sb, bindex)->br_xino.xi_file;
29870+ if (i_size_read(file->f_dentry->d_inode) < pos + sizeof(*ino))
29871+ return 0; /* no ino */
29872+
29873+ sz = xino_fread(sbinfo->si_xread, file, ino, sizeof(*ino), &pos);
29874+ if (sz == sizeof(*ino))
29875+ return 0; /* success */
29876+
29877+ err = sz;
29878+ if (unlikely(sz >= 0)) {
29879+ err = -EIO;
29880+ AuIOErr("xino read error (%zd)\n", sz);
29881+ }
29882+
29883+ return err;
29884+}
29885+
29886+/* ---------------------------------------------------------------------- */
29887+
29888+/* create and set a new xino file */
29889+
29890+struct file *au_xino_create(struct super_block *sb, char *fname, int silent)
29891+{
29892+ struct file *file;
29893+ struct dentry *h_parent, *d;
29894+ struct inode *h_dir;
29895+ int err;
29896+
29897+ /*
29898+ * at mount-time, and the xino file is the default path,
4a4d8108 29899+ * hnotify is disabled so we have no notify events to ignore.
1facf9fc 29900+ * when a user specified the xino, we cannot get au_hdir to be ignored.
29901+ */
7f207e10 29902+ file = vfsub_filp_open(fname, O_RDWR | O_CREAT | O_EXCL | O_LARGEFILE
2cbb1c4b 29903+ /* | __FMODE_NONOTIFY */,
1facf9fc 29904+ S_IRUGO | S_IWUGO);
29905+ if (IS_ERR(file)) {
29906+ if (!silent)
4a4d8108 29907+ pr_err("open %s(%ld)\n", fname, PTR_ERR(file));
1facf9fc 29908+ return file;
29909+ }
29910+
29911+ /* keep file count */
29912+ h_parent = dget_parent(file->f_dentry);
29913+ h_dir = h_parent->d_inode;
29914+ mutex_lock_nested(&h_dir->i_mutex, AuLsc_I_PARENT);
29915+ /* mnt_want_write() is unnecessary here */
29916+ err = vfsub_unlink(h_dir, &file->f_path, /*force*/0);
29917+ mutex_unlock(&h_dir->i_mutex);
29918+ dput(h_parent);
29919+ if (unlikely(err)) {
29920+ if (!silent)
4a4d8108 29921+ pr_err("unlink %s(%d)\n", fname, err);
1facf9fc 29922+ goto out;
29923+ }
29924+
29925+ err = -EINVAL;
29926+ d = file->f_dentry;
29927+ if (unlikely(sb == d->d_sb)) {
29928+ if (!silent)
4a4d8108 29929+ pr_err("%s must be outside\n", fname);
1facf9fc 29930+ goto out;
29931+ }
29932+ if (unlikely(au_test_fs_bad_xino(d->d_sb))) {
29933+ if (!silent)
4a4d8108
AM
29934+ pr_err("xino doesn't support %s(%s)\n",
29935+ fname, au_sbtype(d->d_sb));
1facf9fc 29936+ goto out;
29937+ }
29938+ return file; /* success */
29939+
4f0767ce 29940+out:
1facf9fc 29941+ fput(file);
29942+ file = ERR_PTR(err);
29943+ return file;
29944+}
29945+
29946+/*
29947+ * find another branch who is on the same filesystem of the specified
29948+ * branch{@btgt}. search until @bend.
29949+ */
29950+static int is_sb_shared(struct super_block *sb, aufs_bindex_t btgt,
29951+ aufs_bindex_t bend)
29952+{
29953+ aufs_bindex_t bindex;
29954+ struct super_block *tgt_sb = au_sbr_sb(sb, btgt);
29955+
29956+ for (bindex = 0; bindex < btgt; bindex++)
29957+ if (unlikely(tgt_sb == au_sbr_sb(sb, bindex)))
29958+ return bindex;
29959+ for (bindex++; bindex <= bend; bindex++)
29960+ if (unlikely(tgt_sb == au_sbr_sb(sb, bindex)))
29961+ return bindex;
29962+ return -1;
29963+}
29964+
29965+/* ---------------------------------------------------------------------- */
29966+
29967+/*
29968+ * initialize the xinofile for the specified branch @br
29969+ * at the place/path where @base_file indicates.
29970+ * test whether another branch is on the same filesystem or not,
29971+ * if @do_test is true.
29972+ */
29973+int au_xino_br(struct super_block *sb, struct au_branch *br, ino_t h_ino,
29974+ struct file *base_file, int do_test)
29975+{
29976+ int err;
29977+ ino_t ino;
29978+ aufs_bindex_t bend, bindex;
29979+ struct au_branch *shared_br, *b;
29980+ struct file *file;
29981+ struct super_block *tgt_sb;
29982+
29983+ shared_br = NULL;
29984+ bend = au_sbend(sb);
29985+ if (do_test) {
29986+ tgt_sb = br->br_mnt->mnt_sb;
29987+ for (bindex = 0; bindex <= bend; bindex++) {
29988+ b = au_sbr(sb, bindex);
29989+ if (tgt_sb == b->br_mnt->mnt_sb) {
29990+ shared_br = b;
29991+ break;
29992+ }
29993+ }
29994+ }
29995+
29996+ if (!shared_br || !shared_br->br_xino.xi_file) {
29997+ struct au_xino_lock_dir ldir;
29998+
29999+ au_xino_lock_dir(sb, base_file, &ldir);
30000+ /* mnt_want_write() is unnecessary here */
30001+ file = au_xino_create2(base_file, NULL);
30002+ au_xino_unlock_dir(&ldir);
30003+ err = PTR_ERR(file);
30004+ if (IS_ERR(file))
30005+ goto out;
30006+ br->br_xino.xi_file = file;
30007+ } else {
30008+ br->br_xino.xi_file = shared_br->br_xino.xi_file;
30009+ get_file(br->br_xino.xi_file);
30010+ }
30011+
30012+ ino = AUFS_ROOT_INO;
30013+ err = au_xino_do_write(au_sbi(sb)->si_xwrite, br->br_xino.xi_file,
30014+ h_ino, ino);
b752ccd1
AM
30015+ if (unlikely(err)) {
30016+ fput(br->br_xino.xi_file);
30017+ br->br_xino.xi_file = NULL;
30018+ }
1facf9fc 30019+
4f0767ce 30020+out:
1facf9fc 30021+ return err;
30022+}
30023+
30024+/* ---------------------------------------------------------------------- */
30025+
30026+/* trucate a xino bitmap file */
30027+
30028+/* todo: slow */
30029+static int do_xib_restore(struct super_block *sb, struct file *file, void *page)
30030+{
30031+ int err, bit;
30032+ ssize_t sz;
30033+ unsigned long pindex;
30034+ loff_t pos, pend;
30035+ struct au_sbinfo *sbinfo;
30036+ au_readf_t func;
30037+ ino_t *ino;
30038+ unsigned long *p;
30039+
30040+ err = 0;
30041+ sbinfo = au_sbi(sb);
dece6358 30042+ MtxMustLock(&sbinfo->si_xib_mtx);
1facf9fc 30043+ p = sbinfo->si_xib_buf;
30044+ func = sbinfo->si_xread;
30045+ pend = i_size_read(file->f_dentry->d_inode);
30046+ pos = 0;
30047+ while (pos < pend) {
30048+ sz = xino_fread(func, file, page, PAGE_SIZE, &pos);
30049+ err = sz;
30050+ if (unlikely(sz <= 0))
30051+ goto out;
30052+
30053+ err = 0;
30054+ for (ino = page; sz > 0; ino++, sz -= sizeof(ino)) {
30055+ if (unlikely(*ino < AUFS_FIRST_INO))
30056+ continue;
30057+
30058+ xib_calc_bit(*ino, &pindex, &bit);
30059+ AuDebugOn(page_bits <= bit);
30060+ err = xib_pindex(sb, pindex);
30061+ if (!err)
30062+ set_bit(bit, p);
30063+ else
30064+ goto out;
30065+ }
30066+ }
30067+
4f0767ce 30068+out:
1facf9fc 30069+ return err;
30070+}
30071+
30072+static int xib_restore(struct super_block *sb)
30073+{
30074+ int err;
30075+ aufs_bindex_t bindex, bend;
30076+ void *page;
30077+
30078+ err = -ENOMEM;
30079+ page = (void *)__get_free_page(GFP_NOFS);
30080+ if (unlikely(!page))
30081+ goto out;
30082+
30083+ err = 0;
30084+ bend = au_sbend(sb);
30085+ for (bindex = 0; !err && bindex <= bend; bindex++)
30086+ if (!bindex || is_sb_shared(sb, bindex, bindex - 1) < 0)
30087+ err = do_xib_restore
30088+ (sb, au_sbr(sb, bindex)->br_xino.xi_file, page);
30089+ else
30090+ AuDbg("b%d\n", bindex);
30091+ free_page((unsigned long)page);
30092+
4f0767ce 30093+out:
1facf9fc 30094+ return err;
30095+}
30096+
30097+int au_xib_trunc(struct super_block *sb)
30098+{
30099+ int err;
30100+ ssize_t sz;
30101+ loff_t pos;
30102+ struct au_xino_lock_dir ldir;
30103+ struct au_sbinfo *sbinfo;
30104+ unsigned long *p;
30105+ struct file *file;
30106+
dece6358
AM
30107+ SiMustWriteLock(sb);
30108+
1facf9fc 30109+ err = 0;
30110+ sbinfo = au_sbi(sb);
30111+ if (!au_opt_test(sbinfo->si_mntflags, XINO))
30112+ goto out;
30113+
30114+ file = sbinfo->si_xib;
30115+ if (i_size_read(file->f_dentry->d_inode) <= PAGE_SIZE)
30116+ goto out;
30117+
30118+ au_xino_lock_dir(sb, file, &ldir);
30119+ /* mnt_want_write() is unnecessary here */
30120+ file = au_xino_create2(sbinfo->si_xib, NULL);
30121+ au_xino_unlock_dir(&ldir);
30122+ err = PTR_ERR(file);
30123+ if (IS_ERR(file))
30124+ goto out;
30125+ fput(sbinfo->si_xib);
30126+ sbinfo->si_xib = file;
30127+
30128+ p = sbinfo->si_xib_buf;
30129+ memset(p, 0, PAGE_SIZE);
30130+ pos = 0;
30131+ sz = xino_fwrite(sbinfo->si_xwrite, sbinfo->si_xib, p, PAGE_SIZE, &pos);
30132+ if (unlikely(sz != PAGE_SIZE)) {
30133+ err = sz;
30134+ AuIOErr("err %d\n", err);
30135+ if (sz >= 0)
30136+ err = -EIO;
30137+ goto out;
30138+ }
30139+
30140+ mutex_lock(&sbinfo->si_xib_mtx);
30141+ /* mnt_want_write() is unnecessary here */
30142+ err = xib_restore(sb);
30143+ mutex_unlock(&sbinfo->si_xib_mtx);
30144+
30145+out:
30146+ return err;
30147+}
30148+
30149+/* ---------------------------------------------------------------------- */
30150+
30151+/*
30152+ * xino mount option handlers
30153+ */
30154+static au_readf_t find_readf(struct file *h_file)
30155+{
30156+ const struct file_operations *fop = h_file->f_op;
30157+
30158+ if (fop) {
30159+ if (fop->read)
30160+ return fop->read;
30161+ if (fop->aio_read)
30162+ return do_sync_read;
30163+ }
30164+ return ERR_PTR(-ENOSYS);
30165+}
30166+
30167+static au_writef_t find_writef(struct file *h_file)
30168+{
30169+ const struct file_operations *fop = h_file->f_op;
30170+
30171+ if (fop) {
30172+ if (fop->write)
30173+ return fop->write;
30174+ if (fop->aio_write)
30175+ return do_sync_write;
30176+ }
30177+ return ERR_PTR(-ENOSYS);
30178+}
30179+
30180+/* xino bitmap */
30181+static void xino_clear_xib(struct super_block *sb)
30182+{
30183+ struct au_sbinfo *sbinfo;
30184+
dece6358
AM
30185+ SiMustWriteLock(sb);
30186+
1facf9fc 30187+ sbinfo = au_sbi(sb);
30188+ sbinfo->si_xread = NULL;
30189+ sbinfo->si_xwrite = NULL;
30190+ if (sbinfo->si_xib)
30191+ fput(sbinfo->si_xib);
30192+ sbinfo->si_xib = NULL;
30193+ free_page((unsigned long)sbinfo->si_xib_buf);
30194+ sbinfo->si_xib_buf = NULL;
30195+}
30196+
30197+static int au_xino_set_xib(struct super_block *sb, struct file *base)
30198+{
30199+ int err;
30200+ loff_t pos;
30201+ struct au_sbinfo *sbinfo;
30202+ struct file *file;
30203+
dece6358
AM
30204+ SiMustWriteLock(sb);
30205+
1facf9fc 30206+ sbinfo = au_sbi(sb);
30207+ file = au_xino_create2(base, sbinfo->si_xib);
30208+ err = PTR_ERR(file);
30209+ if (IS_ERR(file))
30210+ goto out;
30211+ if (sbinfo->si_xib)
30212+ fput(sbinfo->si_xib);
30213+ sbinfo->si_xib = file;
30214+ sbinfo->si_xread = find_readf(file);
30215+ sbinfo->si_xwrite = find_writef(file);
30216+
30217+ err = -ENOMEM;
30218+ if (!sbinfo->si_xib_buf)
30219+ sbinfo->si_xib_buf = (void *)get_zeroed_page(GFP_NOFS);
30220+ if (unlikely(!sbinfo->si_xib_buf))
30221+ goto out_unset;
30222+
30223+ sbinfo->si_xib_last_pindex = 0;
30224+ sbinfo->si_xib_next_bit = 0;
30225+ if (i_size_read(file->f_dentry->d_inode) < PAGE_SIZE) {
30226+ pos = 0;
30227+ err = xino_fwrite(sbinfo->si_xwrite, file, sbinfo->si_xib_buf,
30228+ PAGE_SIZE, &pos);
30229+ if (unlikely(err != PAGE_SIZE))
30230+ goto out_free;
30231+ }
30232+ err = 0;
30233+ goto out; /* success */
30234+
4f0767ce 30235+out_free:
1facf9fc 30236+ free_page((unsigned long)sbinfo->si_xib_buf);
b752ccd1
AM
30237+ sbinfo->si_xib_buf = NULL;
30238+ if (err >= 0)
30239+ err = -EIO;
4f0767ce 30240+out_unset:
b752ccd1
AM
30241+ fput(sbinfo->si_xib);
30242+ sbinfo->si_xib = NULL;
30243+ sbinfo->si_xread = NULL;
30244+ sbinfo->si_xwrite = NULL;
4f0767ce 30245+out:
b752ccd1 30246+ return err;
1facf9fc 30247+}
30248+
b752ccd1
AM
30249+/* xino for each branch */
30250+static void xino_clear_br(struct super_block *sb)
30251+{
30252+ aufs_bindex_t bindex, bend;
30253+ struct au_branch *br;
1facf9fc 30254+
b752ccd1
AM
30255+ bend = au_sbend(sb);
30256+ for (bindex = 0; bindex <= bend; bindex++) {
30257+ br = au_sbr(sb, bindex);
30258+ if (!br || !br->br_xino.xi_file)
30259+ continue;
30260+
30261+ fput(br->br_xino.xi_file);
30262+ br->br_xino.xi_file = NULL;
30263+ }
30264+}
30265+
30266+static int au_xino_set_br(struct super_block *sb, struct file *base)
1facf9fc 30267+{
30268+ int err;
b752ccd1
AM
30269+ ino_t ino;
30270+ aufs_bindex_t bindex, bend, bshared;
30271+ struct {
30272+ struct file *old, *new;
30273+ } *fpair, *p;
30274+ struct au_branch *br;
30275+ struct inode *inode;
30276+ au_writef_t writef;
1facf9fc 30277+
b752ccd1
AM
30278+ SiMustWriteLock(sb);
30279+
30280+ err = -ENOMEM;
30281+ bend = au_sbend(sb);
30282+ fpair = kcalloc(bend + 1, sizeof(*fpair), GFP_NOFS);
30283+ if (unlikely(!fpair))
1facf9fc 30284+ goto out;
30285+
b752ccd1
AM
30286+ inode = sb->s_root->d_inode;
30287+ ino = AUFS_ROOT_INO;
30288+ writef = au_sbi(sb)->si_xwrite;
30289+ for (bindex = 0, p = fpair; bindex <= bend; bindex++, p++) {
30290+ br = au_sbr(sb, bindex);
30291+ bshared = is_sb_shared(sb, bindex, bindex - 1);
30292+ if (bshared >= 0) {
30293+ /* shared xino */
30294+ *p = fpair[bshared];
30295+ get_file(p->new);
30296+ }
30297+
30298+ if (!p->new) {
30299+ /* new xino */
30300+ p->old = br->br_xino.xi_file;
30301+ p->new = au_xino_create2(base, br->br_xino.xi_file);
30302+ err = PTR_ERR(p->new);
30303+ if (IS_ERR(p->new)) {
30304+ p->new = NULL;
30305+ goto out_pair;
30306+ }
30307+ }
30308+
30309+ err = au_xino_do_write(writef, p->new,
30310+ au_h_iptr(inode, bindex)->i_ino, ino);
30311+ if (unlikely(err))
30312+ goto out_pair;
30313+ }
30314+
30315+ for (bindex = 0, p = fpair; bindex <= bend; bindex++, p++) {
30316+ br = au_sbr(sb, bindex);
30317+ if (br->br_xino.xi_file)
30318+ fput(br->br_xino.xi_file);
30319+ get_file(p->new);
30320+ br->br_xino.xi_file = p->new;
30321+ }
1facf9fc 30322+
4f0767ce 30323+out_pair:
b752ccd1
AM
30324+ for (bindex = 0, p = fpair; bindex <= bend; bindex++, p++)
30325+ if (p->new)
30326+ fput(p->new);
30327+ else
30328+ break;
30329+ kfree(fpair);
4f0767ce 30330+out:
1facf9fc 30331+ return err;
30332+}
b752ccd1
AM
30333+
30334+void au_xino_clr(struct super_block *sb)
30335+{
30336+ struct au_sbinfo *sbinfo;
30337+
30338+ au_xigen_clr(sb);
30339+ xino_clear_xib(sb);
30340+ xino_clear_br(sb);
30341+ sbinfo = au_sbi(sb);
30342+ /* lvalue, do not call au_mntflags() */
30343+ au_opt_clr(sbinfo->si_mntflags, XINO);
30344+}
30345+
30346+int au_xino_set(struct super_block *sb, struct au_opt_xino *xino, int remount)
30347+{
30348+ int err, skip;
30349+ struct dentry *parent, *cur_parent;
30350+ struct qstr *dname, *cur_name;
30351+ struct file *cur_xino;
30352+ struct inode *dir;
30353+ struct au_sbinfo *sbinfo;
30354+
30355+ SiMustWriteLock(sb);
30356+
30357+ err = 0;
30358+ sbinfo = au_sbi(sb);
30359+ parent = dget_parent(xino->file->f_dentry);
30360+ if (remount) {
30361+ skip = 0;
30362+ dname = &xino->file->f_dentry->d_name;
30363+ cur_xino = sbinfo->si_xib;
30364+ if (cur_xino) {
30365+ cur_parent = dget_parent(cur_xino->f_dentry);
30366+ cur_name = &cur_xino->f_dentry->d_name;
30367+ skip = (cur_parent == parent
30368+ && dname->len == cur_name->len
30369+ && !memcmp(dname->name, cur_name->name,
30370+ dname->len));
30371+ dput(cur_parent);
30372+ }
30373+ if (skip)
30374+ goto out;
30375+ }
30376+
30377+ au_opt_set(sbinfo->si_mntflags, XINO);
30378+ dir = parent->d_inode;
30379+ mutex_lock_nested(&dir->i_mutex, AuLsc_I_PARENT);
30380+ /* mnt_want_write() is unnecessary here */
30381+ err = au_xino_set_xib(sb, xino->file);
30382+ if (!err)
30383+ err = au_xigen_set(sb, xino->file);
30384+ if (!err)
30385+ err = au_xino_set_br(sb, xino->file);
30386+ mutex_unlock(&dir->i_mutex);
30387+ if (!err)
30388+ goto out; /* success */
30389+
30390+ /* reset all */
30391+ AuIOErr("failed creating xino(%d).\n", err);
30392+
4f0767ce 30393+out:
b752ccd1
AM
30394+ dput(parent);
30395+ return err;
30396+}
30397+
30398+/* ---------------------------------------------------------------------- */
30399+
30400+/*
30401+ * create a xinofile at the default place/path.
30402+ */
30403+struct file *au_xino_def(struct super_block *sb)
30404+{
30405+ struct file *file;
30406+ char *page, *p;
30407+ struct au_branch *br;
30408+ struct super_block *h_sb;
30409+ struct path path;
30410+ aufs_bindex_t bend, bindex, bwr;
30411+
30412+ br = NULL;
30413+ bend = au_sbend(sb);
30414+ bwr = -1;
30415+ for (bindex = 0; bindex <= bend; bindex++) {
30416+ br = au_sbr(sb, bindex);
30417+ if (au_br_writable(br->br_perm)
30418+ && !au_test_fs_bad_xino(br->br_mnt->mnt_sb)) {
30419+ bwr = bindex;
30420+ break;
30421+ }
30422+ }
30423+
7f207e10
AM
30424+ if (bwr >= 0) {
30425+ file = ERR_PTR(-ENOMEM);
30426+ page = __getname_gfp(GFP_NOFS);
30427+ if (unlikely(!page))
30428+ goto out;
30429+ path.mnt = br->br_mnt;
30430+ path.dentry = au_h_dptr(sb->s_root, bwr);
30431+ p = d_path(&path, page, PATH_MAX - sizeof(AUFS_XINO_FNAME));
30432+ file = (void *)p;
30433+ if (!IS_ERR(p)) {
30434+ strcat(p, "/" AUFS_XINO_FNAME);
30435+ AuDbg("%s\n", p);
30436+ file = au_xino_create(sb, p, /*silent*/0);
30437+ if (!IS_ERR(file))
30438+ au_xino_brid_set(sb, br->br_id);
30439+ }
30440+ __putname(page);
30441+ } else {
30442+ file = au_xino_create(sb, AUFS_XINO_DEFPATH, /*silent*/0);
30443+ if (IS_ERR(file))
30444+ goto out;
30445+ h_sb = file->f_dentry->d_sb;
30446+ if (unlikely(au_test_fs_bad_xino(h_sb))) {
30447+ pr_err("xino doesn't support %s(%s)\n",
30448+ AUFS_XINO_DEFPATH, au_sbtype(h_sb));
30449+ fput(file);
30450+ file = ERR_PTR(-EINVAL);
30451+ }
30452+ if (!IS_ERR(file))
30453+ au_xino_brid_set(sb, -1);
30454+ }
0c5527e5 30455+
7f207e10
AM
30456+out:
30457+ return file;
30458+}
30459+
30460+/* ---------------------------------------------------------------------- */
30461+
30462+int au_xino_path(struct seq_file *seq, struct file *file)
30463+{
30464+ int err;
30465+
30466+ err = au_seq_path(seq, &file->f_path);
30467+ if (unlikely(err < 0))
30468+ goto out;
30469+
30470+ err = 0;
30471+#define Deleted "\\040(deleted)"
30472+ seq->count -= sizeof(Deleted) - 1;
30473+ AuDebugOn(memcmp(seq->buf + seq->count, Deleted,
30474+ sizeof(Deleted) - 1));
30475+#undef Deleted
30476+
30477+out:
30478+ return err;
30479+}
30480diff -urN /usr/share/empty/include/linux/aufs_type.h linux/include/linux/aufs_type.h
30481--- /usr/share/empty/include/linux/aufs_type.h 1970-01-01 01:00:00.000000000 +0100
0c3ec466 30482+++ linux/include/linux/aufs_type.h 2012-07-22 19:57:03.167671344 +0200
f6c5ef8b 30483@@ -0,0 +1,233 @@
7f207e10 30484+/*
f6c5ef8b 30485+ * Copyright (C) 2005-2012 Junjiro R. Okajima
7f207e10
AM
30486+ *
30487+ * This program, aufs is free software; you can redistribute it and/or modify
30488+ * it under the terms of the GNU General Public License as published by
30489+ * the Free Software Foundation; either version 2 of the License, or
30490+ * (at your option) any later version.
30491+ *
30492+ * This program is distributed in the hope that it will be useful,
30493+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
30494+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
30495+ * GNU General Public License for more details.
30496+ *
30497+ * You should have received a copy of the GNU General Public License
30498+ * along with this program; if not, write to the Free Software
30499+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
30500+ */
30501+
30502+#ifndef __AUFS_TYPE_H__
30503+#define __AUFS_TYPE_H__
30504+
f6c5ef8b
AM
30505+#define AUFS_NAME "aufs"
30506+
9dbd164d 30507+#ifdef __KERNEL__
f6c5ef8b
AM
30508+/*
30509+ * define it before including all other headers.
30510+ * sched.h may use pr_* macros before defining "current", so define the
30511+ * no-current version first, and re-define later.
30512+ */
30513+#define pr_fmt(fmt) AUFS_NAME " %s:%d: " fmt, __func__, __LINE__
30514+#include <linux/sched.h>
30515+#undef pr_fmt
30516+#define pr_fmt(fmt) AUFS_NAME " %s:%d:%s[%d]: " fmt, \
30517+ __func__, __LINE__, current->comm, current->pid
9dbd164d
AM
30518+#else
30519+#include <stdint.h>
30520+#include <sys/types.h>
f6c5ef8b 30521+#endif /* __KERNEL__ */
7f207e10 30522+
f6c5ef8b
AM
30523+#include <linux/limits.h>
30524+
0c3ec466 30525+#define AUFS_VERSION "3.x-rcN-20120618"
7f207e10
AM
30526+
30527+/* todo? move this to linux-2.6.19/include/magic.h */
30528+#define AUFS_SUPER_MAGIC ('a' << 24 | 'u' << 16 | 'f' << 8 | 's')
30529+
30530+/* ---------------------------------------------------------------------- */
30531+
30532+#ifdef CONFIG_AUFS_BRANCH_MAX_127
9dbd164d 30533+typedef int8_t aufs_bindex_t;
7f207e10
AM
30534+#define AUFS_BRANCH_MAX 127
30535+#else
9dbd164d 30536+typedef int16_t aufs_bindex_t;
7f207e10
AM
30537+#ifdef CONFIG_AUFS_BRANCH_MAX_511
30538+#define AUFS_BRANCH_MAX 511
30539+#elif defined(CONFIG_AUFS_BRANCH_MAX_1023)
30540+#define AUFS_BRANCH_MAX 1023
30541+#elif defined(CONFIG_AUFS_BRANCH_MAX_32767)
30542+#define AUFS_BRANCH_MAX 32767
30543+#endif
30544+#endif
30545+
30546+#ifdef __KERNEL__
30547+#ifndef AUFS_BRANCH_MAX
30548+#error unknown CONFIG_AUFS_BRANCH_MAX value
30549+#endif
30550+#endif /* __KERNEL__ */
30551+
30552+/* ---------------------------------------------------------------------- */
30553+
7f207e10
AM
30554+#define AUFS_FSTYPE AUFS_NAME
30555+
30556+#define AUFS_ROOT_INO 2
30557+#define AUFS_FIRST_INO 11
30558+
30559+#define AUFS_WH_PFX ".wh."
30560+#define AUFS_WH_PFX_LEN ((int)sizeof(AUFS_WH_PFX) - 1)
30561+#define AUFS_WH_TMP_LEN 4
30562+/* a limit for rmdir/rename a dir */
30563+#define AUFS_MAX_NAMELEN (NAME_MAX \
30564+ - AUFS_WH_PFX_LEN * 2 /* doubly whiteouted */\
30565+ - 1 /* dot */\
30566+ - AUFS_WH_TMP_LEN) /* hex */
30567+#define AUFS_XINO_FNAME "." AUFS_NAME ".xino"
30568+#define AUFS_XINO_DEFPATH "/tmp/" AUFS_XINO_FNAME
30569+#define AUFS_XINO_TRUNC_INIT 64 /* blocks */
30570+#define AUFS_XINO_TRUNC_STEP 4 /* blocks */
30571+#define AUFS_DIRWH_DEF 3
30572+#define AUFS_RDCACHE_DEF 10 /* seconds */
027c5e7a 30573+#define AUFS_RDCACHE_MAX 3600 /* seconds */
7f207e10
AM
30574+#define AUFS_RDBLK_DEF 512 /* bytes */
30575+#define AUFS_RDHASH_DEF 32
30576+#define AUFS_WKQ_NAME AUFS_NAME "d"
027c5e7a
AM
30577+#define AUFS_MFS_DEF_SEC 30 /* seconds */
30578+#define AUFS_MFS_MAX_SEC 3600 /* seconds */
7f207e10
AM
30579+#define AUFS_PLINK_WARN 100 /* number of plinks */
30580+
30581+/* pseudo-link maintenace under /proc */
30582+#define AUFS_PLINK_MAINT_NAME "plink_maint"
30583+#define AUFS_PLINK_MAINT_DIR "fs/" AUFS_NAME
30584+#define AUFS_PLINK_MAINT_PATH AUFS_PLINK_MAINT_DIR "/" AUFS_PLINK_MAINT_NAME
30585+
30586+#define AUFS_DIROPQ_NAME AUFS_WH_PFX ".opq" /* whiteouted doubly */
30587+#define AUFS_WH_DIROPQ AUFS_WH_PFX AUFS_DIROPQ_NAME
30588+
30589+#define AUFS_BASE_NAME AUFS_WH_PFX AUFS_NAME
30590+#define AUFS_PLINKDIR_NAME AUFS_WH_PFX "plnk"
30591+#define AUFS_ORPHDIR_NAME AUFS_WH_PFX "orph"
30592+
30593+/* doubly whiteouted */
30594+#define AUFS_WH_BASE AUFS_WH_PFX AUFS_BASE_NAME
30595+#define AUFS_WH_PLINKDIR AUFS_WH_PFX AUFS_PLINKDIR_NAME
30596+#define AUFS_WH_ORPHDIR AUFS_WH_PFX AUFS_ORPHDIR_NAME
30597+
1e00d052 30598+/* branch permissions and attributes */
7f207e10
AM
30599+#define AUFS_BRPERM_RW "rw"
30600+#define AUFS_BRPERM_RO "ro"
30601+#define AUFS_BRPERM_RR "rr"
1e00d052
AM
30602+#define AUFS_BRRATTR_WH "wh"
30603+#define AUFS_BRWATTR_NLWH "nolwh"
7f207e10
AM
30604+
30605+/* ---------------------------------------------------------------------- */
30606+
30607+/* ioctl */
30608+enum {
30609+ /* readdir in userspace */
30610+ AuCtl_RDU,
30611+ AuCtl_RDU_INO,
30612+
30613+ /* pathconf wrapper */
027c5e7a
AM
30614+ AuCtl_WBR_FD,
30615+
30616+ /* busy inode */
30617+ AuCtl_IBUSY
7f207e10
AM
30618+};
30619+
30620+/* borrowed from linux/include/linux/kernel.h */
30621+#ifndef ALIGN
30622+#define ALIGN(x, a) __ALIGN_MASK(x, (typeof(x))(a)-1)
30623+#define __ALIGN_MASK(x, mask) (((x)+(mask))&~(mask))
30624+#endif
30625+
30626+/* borrowed from linux/include/linux/compiler-gcc3.h */
30627+#ifndef __aligned
30628+#define __aligned(x) __attribute__((aligned(x)))
53392da6
AM
30629+#endif
30630+
30631+#ifdef __KERNEL__
30632+#ifndef __packed
7f207e10
AM
30633+#define __packed __attribute__((packed))
30634+#endif
53392da6 30635+#endif
7f207e10
AM
30636+
30637+struct au_rdu_cookie {
9dbd164d
AM
30638+ uint64_t h_pos;
30639+ int16_t bindex;
30640+ uint8_t flags;
30641+ uint8_t pad;
30642+ uint32_t generation;
7f207e10
AM
30643+} __aligned(8);
30644+
30645+struct au_rdu_ent {
9dbd164d
AM
30646+ uint64_t ino;
30647+ int16_t bindex;
30648+ uint8_t type;
30649+ uint8_t nlen;
30650+ uint8_t wh;
7f207e10
AM
30651+ char name[0];
30652+} __aligned(8);
30653+
30654+static inline int au_rdu_len(int nlen)
30655+{
30656+ /* include the terminating NULL */
30657+ return ALIGN(sizeof(struct au_rdu_ent) + nlen + 1,
9dbd164d 30658+ sizeof(uint64_t));
7f207e10
AM
30659+}
30660+
30661+union au_rdu_ent_ul {
30662+ struct au_rdu_ent __user *e;
9dbd164d 30663+ uint64_t ul;
7f207e10
AM
30664+};
30665+
30666+enum {
30667+ AufsCtlRduV_SZ,
30668+ AufsCtlRduV_End
30669+};
30670+
30671+struct aufs_rdu {
30672+ /* input */
30673+ union {
9dbd164d
AM
30674+ uint64_t sz; /* AuCtl_RDU */
30675+ uint64_t nent; /* AuCtl_RDU_INO */
7f207e10
AM
30676+ };
30677+ union au_rdu_ent_ul ent;
9dbd164d 30678+ uint16_t verify[AufsCtlRduV_End];
7f207e10
AM
30679+
30680+ /* input/output */
9dbd164d 30681+ uint32_t blk;
7f207e10
AM
30682+
30683+ /* output */
30684+ union au_rdu_ent_ul tail;
30685+ /* number of entries which were added in a single call */
9dbd164d
AM
30686+ uint64_t rent;
30687+ uint8_t full;
30688+ uint8_t shwh;
7f207e10
AM
30689+
30690+ struct au_rdu_cookie cookie;
30691+} __aligned(8);
30692+
1e00d052
AM
30693+/* ---------------------------------------------------------------------- */
30694+
30695+struct aufs_wbr_fd {
9dbd164d
AM
30696+ uint32_t oflags;
30697+ int16_t brid;
1e00d052
AM
30698+} __aligned(8);
30699+
30700+/* ---------------------------------------------------------------------- */
30701+
027c5e7a 30702+struct aufs_ibusy {
9dbd164d
AM
30703+ uint64_t ino, h_ino;
30704+ int16_t bindex;
027c5e7a
AM
30705+} __aligned(8);
30706+
1e00d052
AM
30707+/* ---------------------------------------------------------------------- */
30708+
7f207e10
AM
30709+#define AuCtlType 'A'
30710+#define AUFS_CTL_RDU _IOWR(AuCtlType, AuCtl_RDU, struct aufs_rdu)
30711+#define AUFS_CTL_RDU_INO _IOWR(AuCtlType, AuCtl_RDU_INO, struct aufs_rdu)
1e00d052
AM
30712+#define AUFS_CTL_WBR_FD _IOW(AuCtlType, AuCtl_WBR_FD, \
30713+ struct aufs_wbr_fd)
027c5e7a 30714+#define AUFS_CTL_IBUSY _IOWR(AuCtlType, AuCtl_IBUSY, struct aufs_ibusy)
7f207e10
AM
30715+
30716+#endif /* __AUFS_TYPE_H__ */
This page took 4.466466 seconds and 4 git commands to generate.